mwifiex: move under marvell vendor directory
authorKalle Valo <kvalo@codeaurora.org>
Tue, 17 Nov 2015 19:14:51 +0000 (21:14 +0200)
committerKalle Valo <kvalo@codeaurora.org>
Wed, 18 Nov 2015 12:28:30 +0000 (14:28 +0200)
Part of reorganising wireless drivers directory and Kconfig.

Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
101 files changed:
MAINTAINERS
drivers/net/wireless/Kconfig
drivers/net/wireless/Makefile
drivers/net/wireless/marvell/Kconfig
drivers/net/wireless/marvell/Makefile
drivers/net/wireless/marvell/mwifiex/11ac.c [new file with mode: 0644]
drivers/net/wireless/marvell/mwifiex/11ac.h [new file with mode: 0644]
drivers/net/wireless/marvell/mwifiex/11h.c [new file with mode: 0644]
drivers/net/wireless/marvell/mwifiex/11n.c [new file with mode: 0644]
drivers/net/wireless/marvell/mwifiex/11n.h [new file with mode: 0644]
drivers/net/wireless/marvell/mwifiex/11n_aggr.c [new file with mode: 0644]
drivers/net/wireless/marvell/mwifiex/11n_aggr.h [new file with mode: 0644]
drivers/net/wireless/marvell/mwifiex/11n_rxreorder.c [new file with mode: 0644]
drivers/net/wireless/marvell/mwifiex/11n_rxreorder.h [new file with mode: 0644]
drivers/net/wireless/marvell/mwifiex/Kconfig [new file with mode: 0644]
drivers/net/wireless/marvell/mwifiex/Makefile [new file with mode: 0644]
drivers/net/wireless/marvell/mwifiex/README [new file with mode: 0644]
drivers/net/wireless/marvell/mwifiex/cfg80211.c [new file with mode: 0644]
drivers/net/wireless/marvell/mwifiex/cfg80211.h [new file with mode: 0644]
drivers/net/wireless/marvell/mwifiex/cfp.c [new file with mode: 0644]
drivers/net/wireless/marvell/mwifiex/cmdevt.c [new file with mode: 0644]
drivers/net/wireless/marvell/mwifiex/debugfs.c [new file with mode: 0644]
drivers/net/wireless/marvell/mwifiex/decl.h [new file with mode: 0644]
drivers/net/wireless/marvell/mwifiex/ethtool.c [new file with mode: 0644]
drivers/net/wireless/marvell/mwifiex/fw.h [new file with mode: 0644]
drivers/net/wireless/marvell/mwifiex/ie.c [new file with mode: 0644]
drivers/net/wireless/marvell/mwifiex/init.c [new file with mode: 0644]
drivers/net/wireless/marvell/mwifiex/ioctl.h [new file with mode: 0644]
drivers/net/wireless/marvell/mwifiex/join.c [new file with mode: 0644]
drivers/net/wireless/marvell/mwifiex/main.c [new file with mode: 0644]
drivers/net/wireless/marvell/mwifiex/main.h [new file with mode: 0644]
drivers/net/wireless/marvell/mwifiex/pcie.c [new file with mode: 0644]
drivers/net/wireless/marvell/mwifiex/pcie.h [new file with mode: 0644]
drivers/net/wireless/marvell/mwifiex/scan.c [new file with mode: 0644]
drivers/net/wireless/marvell/mwifiex/sdio.c [new file with mode: 0644]
drivers/net/wireless/marvell/mwifiex/sdio.h [new file with mode: 0644]
drivers/net/wireless/marvell/mwifiex/sta_cmd.c [new file with mode: 0644]
drivers/net/wireless/marvell/mwifiex/sta_cmdresp.c [new file with mode: 0644]
drivers/net/wireless/marvell/mwifiex/sta_event.c [new file with mode: 0644]
drivers/net/wireless/marvell/mwifiex/sta_ioctl.c [new file with mode: 0644]
drivers/net/wireless/marvell/mwifiex/sta_rx.c [new file with mode: 0644]
drivers/net/wireless/marvell/mwifiex/sta_tx.c [new file with mode: 0644]
drivers/net/wireless/marvell/mwifiex/tdls.c [new file with mode: 0644]
drivers/net/wireless/marvell/mwifiex/txrx.c [new file with mode: 0644]
drivers/net/wireless/marvell/mwifiex/uap_cmd.c [new file with mode: 0644]
drivers/net/wireless/marvell/mwifiex/uap_event.c [new file with mode: 0644]
drivers/net/wireless/marvell/mwifiex/uap_txrx.c [new file with mode: 0644]
drivers/net/wireless/marvell/mwifiex/usb.c [new file with mode: 0644]
drivers/net/wireless/marvell/mwifiex/usb.h [new file with mode: 0644]
drivers/net/wireless/marvell/mwifiex/util.c [new file with mode: 0644]
drivers/net/wireless/marvell/mwifiex/util.h [new file with mode: 0644]
drivers/net/wireless/marvell/mwifiex/wmm.c [new file with mode: 0644]
drivers/net/wireless/marvell/mwifiex/wmm.h [new file with mode: 0644]
drivers/net/wireless/mwifiex/11ac.c [deleted file]
drivers/net/wireless/mwifiex/11ac.h [deleted file]
drivers/net/wireless/mwifiex/11h.c [deleted file]
drivers/net/wireless/mwifiex/11n.c [deleted file]
drivers/net/wireless/mwifiex/11n.h [deleted file]
drivers/net/wireless/mwifiex/11n_aggr.c [deleted file]
drivers/net/wireless/mwifiex/11n_aggr.h [deleted file]
drivers/net/wireless/mwifiex/11n_rxreorder.c [deleted file]
drivers/net/wireless/mwifiex/11n_rxreorder.h [deleted file]
drivers/net/wireless/mwifiex/Kconfig [deleted file]
drivers/net/wireless/mwifiex/Makefile [deleted file]
drivers/net/wireless/mwifiex/README [deleted file]
drivers/net/wireless/mwifiex/cfg80211.c [deleted file]
drivers/net/wireless/mwifiex/cfg80211.h [deleted file]
drivers/net/wireless/mwifiex/cfp.c [deleted file]
drivers/net/wireless/mwifiex/cmdevt.c [deleted file]
drivers/net/wireless/mwifiex/debugfs.c [deleted file]
drivers/net/wireless/mwifiex/decl.h [deleted file]
drivers/net/wireless/mwifiex/ethtool.c [deleted file]
drivers/net/wireless/mwifiex/fw.h [deleted file]
drivers/net/wireless/mwifiex/ie.c [deleted file]
drivers/net/wireless/mwifiex/init.c [deleted file]
drivers/net/wireless/mwifiex/ioctl.h [deleted file]
drivers/net/wireless/mwifiex/join.c [deleted file]
drivers/net/wireless/mwifiex/main.c [deleted file]
drivers/net/wireless/mwifiex/main.h [deleted file]
drivers/net/wireless/mwifiex/pcie.c [deleted file]
drivers/net/wireless/mwifiex/pcie.h [deleted file]
drivers/net/wireless/mwifiex/scan.c [deleted file]
drivers/net/wireless/mwifiex/sdio.c [deleted file]
drivers/net/wireless/mwifiex/sdio.h [deleted file]
drivers/net/wireless/mwifiex/sta_cmd.c [deleted file]
drivers/net/wireless/mwifiex/sta_cmdresp.c [deleted file]
drivers/net/wireless/mwifiex/sta_event.c [deleted file]
drivers/net/wireless/mwifiex/sta_ioctl.c [deleted file]
drivers/net/wireless/mwifiex/sta_rx.c [deleted file]
drivers/net/wireless/mwifiex/sta_tx.c [deleted file]
drivers/net/wireless/mwifiex/tdls.c [deleted file]
drivers/net/wireless/mwifiex/txrx.c [deleted file]
drivers/net/wireless/mwifiex/uap_cmd.c [deleted file]
drivers/net/wireless/mwifiex/uap_event.c [deleted file]
drivers/net/wireless/mwifiex/uap_txrx.c [deleted file]
drivers/net/wireless/mwifiex/usb.c [deleted file]
drivers/net/wireless/mwifiex/usb.h [deleted file]
drivers/net/wireless/mwifiex/util.c [deleted file]
drivers/net/wireless/mwifiex/util.h [deleted file]
drivers/net/wireless/mwifiex/wmm.c [deleted file]
drivers/net/wireless/mwifiex/wmm.h [deleted file]

index 75ff743..5b889f6 100644 (file)
@@ -6728,7 +6728,7 @@ M:        Amitkumar Karwar <akarwar@marvell.com>
 M:     Nishant Sarmukadam <nishants@marvell.com>
 L:     linux-wireless@vger.kernel.org
 S:     Maintained
-F:     drivers/net/wireless/mwifiex/
+F:     drivers/net/wireless/marvell/mwifiex/
 
 MARVELL MWL8K WIRELESS DRIVER
 M:     Lennert Buytenhek <buytenh@wantstofly.org>
index 25f52b3..4656652 100644 (file)
@@ -152,7 +152,6 @@ source "drivers/net/wireless/realtek/rtlwifi/Kconfig"
 source "drivers/net/wireless/realtek/rtl8xxxu/Kconfig"
 source "drivers/net/wireless/ti/Kconfig"
 source "drivers/net/wireless/zd1211rw/Kconfig"
-source "drivers/net/wireless/mwifiex/Kconfig"
 source "drivers/net/wireless/rsi/Kconfig"
 
 endif # WLAN
index 72b1677..7a95b58 100644 (file)
@@ -40,6 +40,4 @@ obj-$(CONFIG_MAC80211_HWSIM)  += mac80211_hwsim.o
 
 obj-$(CONFIG_WL_TI)    += ti/
 
-obj-$(CONFIG_MWIFIEX)  += mwifiex/
-
 obj-$(CONFIG_RSI_91X)  += rsi/
index 97ec8f3..bbdbac9 100644 (file)
@@ -13,5 +13,6 @@ if WLAN_VENDOR_MARVELL
 
 source "drivers/net/wireless/marvell/libertas/Kconfig"
 source "drivers/net/wireless/marvell/libertas_tf/Kconfig"
+source "drivers/net/wireless/marvell/mwifiex/Kconfig"
 
 endif # WLAN_VENDOR_MARVELL
index 8f5eb42..f4ab48a 100644 (file)
@@ -1,3 +1,4 @@
 obj-$(CONFIG_LIBERTAS)         += libertas/
 
 obj-$(CONFIG_LIBERTAS_THINFIRM)        += libertas_tf/
+obj-$(CONFIG_MWIFIEX)  += mwifiex/
diff --git a/drivers/net/wireless/marvell/mwifiex/11ac.c b/drivers/net/wireless/marvell/mwifiex/11ac.c
new file mode 100644 (file)
index 0000000..59d23fb
--- /dev/null
@@ -0,0 +1,382 @@
+/*
+ * Marvell Wireless LAN device driver: 802.11ac
+ *
+ * Copyright (C) 2013-2014, Marvell International Ltd.
+ *
+ * This software file (the "File") is distributed by Marvell International
+ * Ltd. under the terms of the GNU General Public License Version 2, June 1991
+ * (the "License").  You may use, redistribute and/or modify this File in
+ * accordance with the terms and conditions of the License, a copy of which
+ * is available by writing to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the
+ * worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
+ *
+ * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
+ * ARE EXPRESSLY DISCLAIMED.  The License provides additional details about
+ * this warranty disclaimer.
+ */
+
+#include "decl.h"
+#include "ioctl.h"
+#include "fw.h"
+#include "main.h"
+#include "11ac.h"
+
+/* Tables of the MCS map to the highest data rate (in Mbps) supported
+ * for long GI.
+ */
+static const u16 max_rate_lgi_80MHZ[8][3] = {
+       {0x124, 0x15F, 0x186},  /* NSS = 1 */
+       {0x249, 0x2BE, 0x30C},  /* NSS = 2 */
+       {0x36D, 0x41D, 0x492},  /* NSS = 3 */
+       {0x492, 0x57C, 0x618},  /* NSS = 4 */
+       {0x5B6, 0x6DB, 0x79E},  /* NSS = 5 */
+       {0x6DB, 0x83A, 0x0},    /* NSS = 6 */
+       {0x7FF, 0x999, 0xAAA},  /* NSS = 7 */
+       {0x924, 0xAF8, 0xC30}   /* NSS = 8 */
+};
+
+static const u16 max_rate_lgi_160MHZ[8][3] = {
+       {0x249, 0x2BE, 0x30C},   /* NSS = 1 */
+       {0x492, 0x57C, 0x618},   /* NSS = 2 */
+       {0x6DB, 0x83A, 0x0},     /* NSS = 3 */
+       {0x924, 0xAF8, 0xC30},   /* NSS = 4 */
+       {0xB6D, 0xDB6, 0xF3C},   /* NSS = 5 */
+       {0xDB6, 0x1074, 0x1248}, /* NSS = 6 */
+       {0xFFF, 0x1332, 0x1554}, /* NSS = 7 */
+       {0x1248, 0x15F0, 0x1860} /* NSS = 8 */
+};
+
+/* This function converts the 2-bit MCS map to the highest long GI
+ * VHT data rate.
+ */
+static u16
+mwifiex_convert_mcsmap_to_maxrate(struct mwifiex_private *priv,
+                                 u8 bands, u16 mcs_map)
+{
+       u8 i, nss, mcs;
+       u16 max_rate = 0;
+       u32 usr_vht_cap_info = 0;
+       struct mwifiex_adapter *adapter = priv->adapter;
+
+       if (bands & BAND_AAC)
+               usr_vht_cap_info = adapter->usr_dot_11ac_dev_cap_a;
+       else
+               usr_vht_cap_info = adapter->usr_dot_11ac_dev_cap_bg;
+
+       /* find the max NSS supported */
+       nss = 1;
+       for (i = 1; i <= 8; i++) {
+               mcs = GET_VHTNSSMCS(mcs_map, i);
+               if (mcs < IEEE80211_VHT_MCS_NOT_SUPPORTED)
+                       nss = i;
+       }
+       mcs = GET_VHTNSSMCS(mcs_map, nss);
+
+       /* if mcs is 3, nss must be 1 (NSS = 1). Default mcs to MCS 0~9 */
+       if (mcs == IEEE80211_VHT_MCS_NOT_SUPPORTED)
+               mcs = IEEE80211_VHT_MCS_SUPPORT_0_9;
+
+       if (GET_VHTCAP_CHWDSET(usr_vht_cap_info)) {
+               /* support 160 MHz */
+               max_rate = max_rate_lgi_160MHZ[nss - 1][mcs];
+               if (!max_rate)
+                       /* MCS9 is not supported in NSS6 */
+                       max_rate = max_rate_lgi_160MHZ[nss - 1][mcs - 1];
+       } else {
+               max_rate = max_rate_lgi_80MHZ[nss - 1][mcs];
+               if (!max_rate)
+                       /* MCS9 is not supported in NSS3 */
+                       max_rate = max_rate_lgi_80MHZ[nss - 1][mcs - 1];
+       }
+
+       return max_rate;
+}
+
+static void
+mwifiex_fill_vht_cap_info(struct mwifiex_private *priv,
+                         struct ieee80211_vht_cap *vht_cap, u8 bands)
+{
+       struct mwifiex_adapter *adapter = priv->adapter;
+
+       if (bands & BAND_A)
+               vht_cap->vht_cap_info =
+                               cpu_to_le32(adapter->usr_dot_11ac_dev_cap_a);
+       else
+               vht_cap->vht_cap_info =
+                               cpu_to_le32(adapter->usr_dot_11ac_dev_cap_bg);
+}
+
+void mwifiex_fill_vht_cap_tlv(struct mwifiex_private *priv,
+                             struct ieee80211_vht_cap *vht_cap, u8 bands)
+{
+       struct mwifiex_adapter *adapter = priv->adapter;
+       u16 mcs_map_user, mcs_map_resp, mcs_map_result;
+       u16 mcs_user, mcs_resp, nss, tmp;
+
+       /* Fill VHT cap info */
+       mwifiex_fill_vht_cap_info(priv, vht_cap, bands);
+
+       /* rx MCS Set: find the minimum of the user rx mcs and ap rx mcs */
+       mcs_map_user = GET_DEVRXMCSMAP(adapter->usr_dot_11ac_mcs_support);
+       mcs_map_resp = le16_to_cpu(vht_cap->supp_mcs.rx_mcs_map);
+       mcs_map_result = 0;
+
+       for (nss = 1; nss <= 8; nss++) {
+               mcs_user = GET_VHTNSSMCS(mcs_map_user, nss);
+               mcs_resp = GET_VHTNSSMCS(mcs_map_resp, nss);
+
+               if ((mcs_user == IEEE80211_VHT_MCS_NOT_SUPPORTED) ||
+                   (mcs_resp == IEEE80211_VHT_MCS_NOT_SUPPORTED))
+                       SET_VHTNSSMCS(mcs_map_result, nss,
+                                     IEEE80211_VHT_MCS_NOT_SUPPORTED);
+               else
+                       SET_VHTNSSMCS(mcs_map_result, nss,
+                                     min(mcs_user, mcs_resp));
+       }
+
+       vht_cap->supp_mcs.rx_mcs_map = cpu_to_le16(mcs_map_result);
+
+       tmp = mwifiex_convert_mcsmap_to_maxrate(priv, bands, mcs_map_result);
+       vht_cap->supp_mcs.rx_highest = cpu_to_le16(tmp);
+
+       /* tx MCS Set: find the minimum of the user tx mcs and ap tx mcs */
+       mcs_map_user = GET_DEVTXMCSMAP(adapter->usr_dot_11ac_mcs_support);
+       mcs_map_resp = le16_to_cpu(vht_cap->supp_mcs.tx_mcs_map);
+       mcs_map_result = 0;
+
+       for (nss = 1; nss <= 8; nss++) {
+               mcs_user = GET_VHTNSSMCS(mcs_map_user, nss);
+               mcs_resp = GET_VHTNSSMCS(mcs_map_resp, nss);
+               if ((mcs_user == IEEE80211_VHT_MCS_NOT_SUPPORTED) ||
+                   (mcs_resp == IEEE80211_VHT_MCS_NOT_SUPPORTED))
+                       SET_VHTNSSMCS(mcs_map_result, nss,
+                                     IEEE80211_VHT_MCS_NOT_SUPPORTED);
+               else
+                       SET_VHTNSSMCS(mcs_map_result, nss,
+                                     min(mcs_user, mcs_resp));
+       }
+
+       vht_cap->supp_mcs.tx_mcs_map = cpu_to_le16(mcs_map_result);
+
+       tmp = mwifiex_convert_mcsmap_to_maxrate(priv, bands, mcs_map_result);
+       vht_cap->supp_mcs.tx_highest = cpu_to_le16(tmp);
+
+       return;
+}
+
+int mwifiex_cmd_append_11ac_tlv(struct mwifiex_private *priv,
+                            struct mwifiex_bssdescriptor *bss_desc,
+                            u8 **buffer)
+{
+       struct mwifiex_ie_types_vhtcap *vht_cap;
+       struct mwifiex_ie_types_oper_mode_ntf *oper_ntf;
+       struct ieee_types_oper_mode_ntf *ieee_oper_ntf;
+       struct mwifiex_ie_types_vht_oper *vht_op;
+       struct mwifiex_adapter *adapter = priv->adapter;
+       u8 supp_chwd_set;
+       u32 usr_vht_cap_info;
+       int ret_len = 0;
+
+       if (bss_desc->bss_band & BAND_A)
+               usr_vht_cap_info = adapter->usr_dot_11ac_dev_cap_a;
+       else
+               usr_vht_cap_info = adapter->usr_dot_11ac_dev_cap_bg;
+
+       /* VHT Capabilities IE */
+       if (bss_desc->bcn_vht_cap) {
+               vht_cap = (struct mwifiex_ie_types_vhtcap *)*buffer;
+               memset(vht_cap, 0, sizeof(*vht_cap));
+               vht_cap->header.type = cpu_to_le16(WLAN_EID_VHT_CAPABILITY);
+               vht_cap->header.len  =
+                               cpu_to_le16(sizeof(struct ieee80211_vht_cap));
+               memcpy((u8 *)vht_cap + sizeof(struct mwifiex_ie_types_header),
+                      (u8 *)bss_desc->bcn_vht_cap,
+                      le16_to_cpu(vht_cap->header.len));
+
+               mwifiex_fill_vht_cap_tlv(priv, &vht_cap->vht_cap,
+                                        bss_desc->bss_band);
+               *buffer += sizeof(*vht_cap);
+               ret_len += sizeof(*vht_cap);
+       }
+
+       /* VHT Operation IE */
+       if (bss_desc->bcn_vht_oper) {
+               if (priv->bss_mode == NL80211_IFTYPE_STATION) {
+                       vht_op = (struct mwifiex_ie_types_vht_oper *)*buffer;
+                       memset(vht_op, 0, sizeof(*vht_op));
+                       vht_op->header.type =
+                                       cpu_to_le16(WLAN_EID_VHT_OPERATION);
+                       vht_op->header.len  = cpu_to_le16(sizeof(*vht_op) -
+                                     sizeof(struct mwifiex_ie_types_header));
+                       memcpy((u8 *)vht_op +
+                               sizeof(struct mwifiex_ie_types_header),
+                              (u8 *)bss_desc->bcn_vht_oper,
+                              le16_to_cpu(vht_op->header.len));
+
+                       /* negotiate the channel width and central freq
+                        * and keep the central freq as the peer suggests
+                        */
+                       supp_chwd_set = GET_VHTCAP_CHWDSET(usr_vht_cap_info);
+
+                       switch (supp_chwd_set) {
+                       case 0:
+                               vht_op->chan_width =
+                                    min_t(u8, IEEE80211_VHT_CHANWIDTH_80MHZ,
+                                          bss_desc->bcn_vht_oper->chan_width);
+                               break;
+                       case 1:
+                               vht_op->chan_width =
+                                    min_t(u8, IEEE80211_VHT_CHANWIDTH_160MHZ,
+                                          bss_desc->bcn_vht_oper->chan_width);
+                               break;
+                       case 2:
+                               vht_op->chan_width =
+                                    min_t(u8, IEEE80211_VHT_CHANWIDTH_80P80MHZ,
+                                          bss_desc->bcn_vht_oper->chan_width);
+                               break;
+                       default:
+                               vht_op->chan_width =
+                                    IEEE80211_VHT_CHANWIDTH_USE_HT;
+                               break;
+                       }
+
+                       *buffer += sizeof(*vht_op);
+                       ret_len += sizeof(*vht_op);
+               }
+       }
+
+       /* Operating Mode Notification IE */
+       if (bss_desc->oper_mode) {
+               ieee_oper_ntf = bss_desc->oper_mode;
+               oper_ntf = (void *)*buffer;
+               memset(oper_ntf, 0, sizeof(*oper_ntf));
+               oper_ntf->header.type = cpu_to_le16(WLAN_EID_OPMODE_NOTIF);
+               oper_ntf->header.len = cpu_to_le16(sizeof(u8));
+               oper_ntf->oper_mode = ieee_oper_ntf->oper_mode;
+               *buffer += sizeof(*oper_ntf);
+               ret_len += sizeof(*oper_ntf);
+       }
+
+       return ret_len;
+}
+
+int mwifiex_cmd_11ac_cfg(struct mwifiex_private *priv,
+                        struct host_cmd_ds_command *cmd, u16 cmd_action,
+                        struct mwifiex_11ac_vht_cfg *cfg)
+{
+       struct host_cmd_11ac_vht_cfg *vhtcfg = &cmd->params.vht_cfg;
+
+       cmd->command = cpu_to_le16(HostCmd_CMD_11AC_CFG);
+       cmd->size = cpu_to_le16(sizeof(struct host_cmd_11ac_vht_cfg) +
+                               S_DS_GEN);
+       vhtcfg->action = cpu_to_le16(cmd_action);
+       vhtcfg->band_config = cfg->band_config;
+       vhtcfg->misc_config = cfg->misc_config;
+       vhtcfg->cap_info = cpu_to_le32(cfg->cap_info);
+       vhtcfg->mcs_tx_set = cpu_to_le32(cfg->mcs_tx_set);
+       vhtcfg->mcs_rx_set = cpu_to_le32(cfg->mcs_rx_set);
+
+       return 0;
+}
+
+/* This function initializes the BlockACK setup information for given
+ * mwifiex_private structure for 11ac enabled networks.
+ */
+void mwifiex_set_11ac_ba_params(struct mwifiex_private *priv)
+{
+       priv->add_ba_param.timeout = MWIFIEX_DEFAULT_BLOCK_ACK_TIMEOUT;
+
+       if (GET_BSS_ROLE(priv) == MWIFIEX_BSS_ROLE_UAP) {
+               priv->add_ba_param.tx_win_size =
+                                          MWIFIEX_11AC_UAP_AMPDU_DEF_TXWINSIZE;
+               priv->add_ba_param.rx_win_size =
+                                          MWIFIEX_11AC_UAP_AMPDU_DEF_RXWINSIZE;
+       } else {
+               priv->add_ba_param.tx_win_size =
+                                          MWIFIEX_11AC_STA_AMPDU_DEF_TXWINSIZE;
+               priv->add_ba_param.rx_win_size =
+                                          MWIFIEX_11AC_STA_AMPDU_DEF_RXWINSIZE;
+       }
+
+       return;
+}
+
+bool mwifiex_is_bss_in_11ac_mode(struct mwifiex_private *priv)
+{
+       struct mwifiex_bssdescriptor *bss_desc;
+       struct ieee80211_vht_operation *vht_oper;
+
+       bss_desc = &priv->curr_bss_params.bss_descriptor;
+       vht_oper = bss_desc->bcn_vht_oper;
+
+       if (!bss_desc->bcn_vht_cap || !vht_oper)
+               return false;
+
+       if (vht_oper->chan_width == IEEE80211_VHT_CHANWIDTH_USE_HT)
+               return false;
+
+       return true;
+}
+
+u8 mwifiex_get_center_freq_index(struct mwifiex_private *priv, u8 band,
+                                u32 pri_chan, u8 chan_bw)
+{
+       u8 center_freq_idx = 0;
+
+       if (band & BAND_AAC) {
+               switch (pri_chan) {
+               case 36:
+               case 40:
+               case 44:
+               case 48:
+                       if (chan_bw == IEEE80211_VHT_CHANWIDTH_80MHZ)
+                               center_freq_idx = 42;
+                       break;
+               case 52:
+               case 56:
+               case 60:
+               case 64:
+                       if (chan_bw == IEEE80211_VHT_CHANWIDTH_80MHZ)
+                               center_freq_idx = 58;
+                       else if (chan_bw == IEEE80211_VHT_CHANWIDTH_160MHZ)
+                               center_freq_idx = 50;
+                       break;
+               case 100:
+               case 104:
+               case 108:
+               case 112:
+                       if (chan_bw == IEEE80211_VHT_CHANWIDTH_80MHZ)
+                               center_freq_idx = 106;
+                       break;
+               case 116:
+               case 120:
+               case 124:
+               case 128:
+                       if (chan_bw == IEEE80211_VHT_CHANWIDTH_80MHZ)
+                               center_freq_idx = 122;
+                       else if (chan_bw == IEEE80211_VHT_CHANWIDTH_160MHZ)
+                               center_freq_idx = 114;
+                       break;
+               case 132:
+               case 136:
+               case 140:
+               case 144:
+                       if (chan_bw == IEEE80211_VHT_CHANWIDTH_80MHZ)
+                               center_freq_idx = 138;
+                       break;
+               case 149:
+               case 153:
+               case 157:
+               case 161:
+                       if (chan_bw == IEEE80211_VHT_CHANWIDTH_80MHZ)
+                               center_freq_idx = 155;
+                       break;
+               default:
+                       center_freq_idx = 42;
+               }
+       }
+
+       return center_freq_idx;
+}
diff --git a/drivers/net/wireless/marvell/mwifiex/11ac.h b/drivers/net/wireless/marvell/mwifiex/11ac.h
new file mode 100644 (file)
index 0000000..1ca92c7
--- /dev/null
@@ -0,0 +1,45 @@
+/*
+ * Marvell Wireless LAN device driver: 802.11ac
+ *
+ * Copyright (C) 2013-2014, Marvell International Ltd.
+ *
+ * This software file (the "File") is distributed by Marvell International
+ * Ltd. under the terms of the GNU General Public License Version 2, June 1991
+ * (the "License").  You may use, redistribute and/or modify this File in
+ * accordance with the terms and conditions of the License, a copy of which
+ * is available by writing to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the
+ * worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
+ *
+ * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
+ * ARE EXPRESSLY DISCLAIMED.  The License provides additional details about
+ * this warranty disclaimer.
+ */
+
+#ifndef _MWIFIEX_11AC_H_
+#define _MWIFIEX_11AC_H_
+
+#define VHT_CFG_2GHZ BIT(0)
+#define VHT_CFG_5GHZ BIT(1)
+
+enum vht_cfg_misc_config {
+       VHT_CAP_TX_OPERATION = 1,
+       VHT_CAP_ASSOCIATION,
+       VHT_CAP_UAP_ONLY
+};
+
+#define DEFAULT_VHT_MCS_SET 0xfffa
+#define DISABLE_VHT_MCS_SET 0xffff
+
+#define VHT_BW_80_160_80P80 BIT(2)
+
+int mwifiex_cmd_append_11ac_tlv(struct mwifiex_private *priv,
+                               struct mwifiex_bssdescriptor *bss_desc,
+                               u8 **buffer);
+int mwifiex_cmd_11ac_cfg(struct mwifiex_private *priv,
+                        struct host_cmd_ds_command *cmd, u16 cmd_action,
+                        struct mwifiex_11ac_vht_cfg *cfg);
+void mwifiex_fill_vht_cap_tlv(struct mwifiex_private *priv,
+                             struct ieee80211_vht_cap *vht_cap, u8 bands);
+#endif /* _MWIFIEX_11AC_H_ */
diff --git a/drivers/net/wireless/marvell/mwifiex/11h.c b/drivers/net/wireless/marvell/mwifiex/11h.c
new file mode 100644 (file)
index 0000000..71a1b58
--- /dev/null
@@ -0,0 +1,319 @@
+/*
+ * Marvell Wireless LAN device driver: 802.11h
+ *
+ * Copyright (C) 2013-2014, Marvell International Ltd.
+ *
+ * This software file (the "File") is distributed by Marvell International
+ * Ltd. under the terms of the GNU General Public License Version 2, June 1991
+ * (the "License").  You may use, redistribute and/or modify this File in
+ * accordance with the terms and conditions of the License, a copy of which
+ * is available by writing to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the
+ * worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
+ *
+ * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
+ * ARE EXPRESSLY DISCLAIMED.  The License provides additional details about
+ * this warranty disclaimer.
+ */
+
+#include "main.h"
+#include "fw.h"
+
+
+void mwifiex_init_11h_params(struct mwifiex_private *priv)
+{
+       priv->state_11h.is_11h_enabled = true;
+       priv->state_11h.is_11h_active = false;
+}
+
+inline int mwifiex_is_11h_active(struct mwifiex_private *priv)
+{
+       return priv->state_11h.is_11h_active;
+}
+/* This function appends 11h info to a buffer while joining an
+ * infrastructure BSS
+ */
+static void
+mwifiex_11h_process_infra_join(struct mwifiex_private *priv, u8 **buffer,
+                              struct mwifiex_bssdescriptor *bss_desc)
+{
+       struct mwifiex_ie_types_header *ie_header;
+       struct mwifiex_ie_types_pwr_capability *cap;
+       struct mwifiex_ie_types_local_pwr_constraint *constraint;
+       struct ieee80211_supported_band *sband;
+       u8 radio_type;
+       int i;
+
+       if (!buffer || !(*buffer))
+               return;
+
+       radio_type = mwifiex_band_to_radio_type((u8) bss_desc->bss_band);
+       sband = priv->wdev.wiphy->bands[radio_type];
+
+       cap = (struct mwifiex_ie_types_pwr_capability *)*buffer;
+       cap->header.type = cpu_to_le16(WLAN_EID_PWR_CAPABILITY);
+       cap->header.len = cpu_to_le16(2);
+       cap->min_pwr = 0;
+       cap->max_pwr = 0;
+       *buffer += sizeof(*cap);
+
+       constraint = (struct mwifiex_ie_types_local_pwr_constraint *)*buffer;
+       constraint->header.type = cpu_to_le16(WLAN_EID_PWR_CONSTRAINT);
+       constraint->header.len = cpu_to_le16(2);
+       constraint->chan = bss_desc->channel;
+       constraint->constraint = bss_desc->local_constraint;
+       *buffer += sizeof(*constraint);
+
+       ie_header = (struct mwifiex_ie_types_header *)*buffer;
+       ie_header->type = cpu_to_le16(TLV_TYPE_PASSTHROUGH);
+       ie_header->len  = cpu_to_le16(2 * sband->n_channels + 2);
+       *buffer += sizeof(*ie_header);
+       *(*buffer)++ = WLAN_EID_SUPPORTED_CHANNELS;
+       *(*buffer)++ = 2 * sband->n_channels;
+       for (i = 0; i < sband->n_channels; i++) {
+               *(*buffer)++ = ieee80211_frequency_to_channel(
+                                       sband->channels[i].center_freq);
+               *(*buffer)++ = 1; /* one channel in the subband */
+       }
+}
+
+/* Enable or disable the 11h extensions in the firmware */
+int mwifiex_11h_activate(struct mwifiex_private *priv, bool flag)
+{
+       u32 enable = flag;
+
+       /* enable master mode radar detection on AP interface */
+       if ((GET_BSS_ROLE(priv) == MWIFIEX_BSS_ROLE_UAP) && enable)
+               enable |= MWIFIEX_MASTER_RADAR_DET_MASK;
+
+       return mwifiex_send_cmd(priv, HostCmd_CMD_802_11_SNMP_MIB,
+                               HostCmd_ACT_GEN_SET, DOT11H_I, &enable, true);
+}
+
+/* This functions processes TLV buffer for a pending BSS Join command.
+ *
+ * Activate 11h functionality in the firmware if the spectrum management
+ * capability bit is found in the network we are joining. Also, necessary
+ * TLVs are set based on requested network's 11h capability.
+ */
+void mwifiex_11h_process_join(struct mwifiex_private *priv, u8 **buffer,
+                             struct mwifiex_bssdescriptor *bss_desc)
+{
+       if (bss_desc->sensed_11h) {
+               /* Activate 11h functions in firmware, turns on capability
+                * bit
+                */
+               mwifiex_11h_activate(priv, true);
+               priv->state_11h.is_11h_active = true;
+               bss_desc->cap_info_bitmap |= WLAN_CAPABILITY_SPECTRUM_MGMT;
+               mwifiex_11h_process_infra_join(priv, buffer, bss_desc);
+       } else {
+               /* Deactivate 11h functions in the firmware */
+               mwifiex_11h_activate(priv, false);
+               priv->state_11h.is_11h_active = false;
+               bss_desc->cap_info_bitmap &= ~WLAN_CAPABILITY_SPECTRUM_MGMT;
+       }
+}
+
+/* This is DFS CAC work queue function.
+ * This delayed work emits CAC finished event for cfg80211 if
+ * CAC was started earlier.
+ */
+void mwifiex_dfs_cac_work_queue(struct work_struct *work)
+{
+       struct cfg80211_chan_def chandef;
+       struct delayed_work *delayed_work =
+                       container_of(work, struct delayed_work, work);
+       struct mwifiex_private *priv =
+                       container_of(delayed_work, struct mwifiex_private,
+                                    dfs_cac_work);
+
+       if (WARN_ON(!priv))
+               return;
+
+       chandef = priv->dfs_chandef;
+       if (priv->wdev.cac_started) {
+               mwifiex_dbg(priv->adapter, MSG,
+                           "CAC timer finished; No radar detected\n");
+               cfg80211_cac_event(priv->netdev, &chandef,
+                                  NL80211_RADAR_CAC_FINISHED,
+                                  GFP_KERNEL);
+       }
+}
+
+/* This function prepares channel report request command to FW for
+ * starting radar detection.
+ */
+int mwifiex_cmd_issue_chan_report_request(struct mwifiex_private *priv,
+                                         struct host_cmd_ds_command *cmd,
+                                         void *data_buf)
+{
+       struct host_cmd_ds_chan_rpt_req *cr_req = &cmd->params.chan_rpt_req;
+       struct mwifiex_radar_params *radar_params = (void *)data_buf;
+
+       cmd->command = cpu_to_le16(HostCmd_CMD_CHAN_REPORT_REQUEST);
+       cmd->size = cpu_to_le16(S_DS_GEN);
+       le16_add_cpu(&cmd->size, sizeof(struct host_cmd_ds_chan_rpt_req));
+
+       cr_req->chan_desc.start_freq = cpu_to_le16(MWIFIEX_A_BAND_START_FREQ);
+       cr_req->chan_desc.chan_num = radar_params->chandef->chan->hw_value;
+       cr_req->chan_desc.chan_width = radar_params->chandef->width;
+       cr_req->msec_dwell_time = cpu_to_le32(radar_params->cac_time_ms);
+
+       if (radar_params->cac_time_ms)
+               mwifiex_dbg(priv->adapter, MSG,
+                           "11h: issuing DFS Radar check for channel=%d\n",
+                           radar_params->chandef->chan->hw_value);
+       else
+               mwifiex_dbg(priv->adapter, MSG, "cancelling CAC\n");
+
+       return 0;
+}
+
+int mwifiex_stop_radar_detection(struct mwifiex_private *priv,
+                                struct cfg80211_chan_def *chandef)
+{
+       struct mwifiex_radar_params radar_params;
+
+       memset(&radar_params, 0, sizeof(struct mwifiex_radar_params));
+       radar_params.chandef = chandef;
+       radar_params.cac_time_ms = 0;
+
+       return mwifiex_send_cmd(priv, HostCmd_CMD_CHAN_REPORT_REQUEST,
+                               HostCmd_ACT_GEN_SET, 0, &radar_params, true);
+}
+
+/* This function is to abort ongoing CAC upon stopping AP operations
+ * or during unload.
+ */
+void mwifiex_abort_cac(struct mwifiex_private *priv)
+{
+       if (priv->wdev.cac_started) {
+               if (mwifiex_stop_radar_detection(priv, &priv->dfs_chandef))
+                       mwifiex_dbg(priv->adapter, ERROR,
+                                   "failed to stop CAC in FW\n");
+               mwifiex_dbg(priv->adapter, MSG,
+                           "Aborting delayed work for CAC.\n");
+               cancel_delayed_work_sync(&priv->dfs_cac_work);
+               cfg80211_cac_event(priv->netdev, &priv->dfs_chandef,
+                                  NL80211_RADAR_CAC_ABORTED, GFP_KERNEL);
+       }
+}
+
+/* This function handles channel report event from FW during CAC period.
+ * If radar is detected during CAC, driver indicates the same to cfg80211
+ * and also cancels ongoing delayed work.
+ */
+int mwifiex_11h_handle_chanrpt_ready(struct mwifiex_private *priv,
+                                    struct sk_buff *skb)
+{
+       struct host_cmd_ds_chan_rpt_event *rpt_event;
+       struct mwifiex_ie_types_chan_rpt_data *rpt;
+       u8 *evt_buf;
+       u16 event_len, tlv_len;
+
+       rpt_event = (void *)(skb->data + sizeof(u32));
+       event_len = skb->len - (sizeof(struct host_cmd_ds_chan_rpt_event)+
+                               sizeof(u32));
+
+       if (le32_to_cpu(rpt_event->result) != HostCmd_RESULT_OK) {
+               mwifiex_dbg(priv->adapter, ERROR,
+                           "Error in channel report event\n");
+               return -1;
+       }
+
+       evt_buf = (void *)&rpt_event->tlvbuf;
+
+       while (event_len >= sizeof(struct mwifiex_ie_types_header)) {
+               rpt = (void *)&rpt_event->tlvbuf;
+               tlv_len = le16_to_cpu(rpt->header.len);
+
+               switch (le16_to_cpu(rpt->header.type)) {
+               case TLV_TYPE_CHANRPT_11H_BASIC:
+                       if (rpt->map.radar) {
+                               mwifiex_dbg(priv->adapter, MSG,
+                                           "RADAR Detected on channel %d!\n",
+                                           priv->dfs_chandef.chan->hw_value);
+                               cancel_delayed_work_sync(&priv->dfs_cac_work);
+                               cfg80211_cac_event(priv->netdev,
+                                                  &priv->dfs_chandef,
+                                                  NL80211_RADAR_DETECTED,
+                                                  GFP_KERNEL);
+                       }
+                       break;
+               default:
+                       break;
+               }
+
+               evt_buf += (tlv_len + sizeof(rpt->header));
+               event_len -= (tlv_len + sizeof(rpt->header));
+       }
+
+       return 0;
+}
+
+/* Handler for radar detected event from FW.*/
+int mwifiex_11h_handle_radar_detected(struct mwifiex_private *priv,
+                                     struct sk_buff *skb)
+{
+       struct mwifiex_radar_det_event *rdr_event;
+
+       rdr_event = (void *)(skb->data + sizeof(u32));
+
+       if (le32_to_cpu(rdr_event->passed)) {
+               mwifiex_dbg(priv->adapter, MSG,
+                           "radar detected; indicating kernel\n");
+               if (mwifiex_stop_radar_detection(priv, &priv->dfs_chandef))
+                       mwifiex_dbg(priv->adapter, ERROR,
+                                   "Failed to stop CAC in FW\n");
+               cfg80211_radar_event(priv->adapter->wiphy, &priv->dfs_chandef,
+                                    GFP_KERNEL);
+               mwifiex_dbg(priv->adapter, MSG, "regdomain: %d\n",
+                           rdr_event->reg_domain);
+               mwifiex_dbg(priv->adapter, MSG, "radar detection type: %d\n",
+                           rdr_event->det_type);
+       } else {
+               mwifiex_dbg(priv->adapter, MSG,
+                           "false radar detection event!\n");
+       }
+
+       return 0;
+}
+
+/* This is work queue function for channel switch handling.
+ * This function takes care of updating new channel definitin to
+ * bss config structure, restart AP and indicate channel switch success
+ * to cfg80211.
+ */
+void mwifiex_dfs_chan_sw_work_queue(struct work_struct *work)
+{
+       struct mwifiex_uap_bss_param *bss_cfg;
+       struct delayed_work *delayed_work =
+                       container_of(work, struct delayed_work, work);
+       struct mwifiex_private *priv =
+                       container_of(delayed_work, struct mwifiex_private,
+                                    dfs_chan_sw_work);
+
+       if (WARN_ON(!priv))
+               return;
+
+       bss_cfg = &priv->bss_cfg;
+       if (!bss_cfg->beacon_period) {
+               mwifiex_dbg(priv->adapter, ERROR,
+                           "channel switch: AP already stopped\n");
+               return;
+       }
+
+       mwifiex_uap_set_channel(priv, bss_cfg, priv->dfs_chandef);
+
+       if (mwifiex_config_start_uap(priv, bss_cfg)) {
+               mwifiex_dbg(priv->adapter, ERROR,
+                           "Failed to start AP after channel switch\n");
+               return;
+       }
+
+       mwifiex_dbg(priv->adapter, MSG,
+                   "indicating channel switch completion to kernel\n");
+       cfg80211_ch_switch_notify(priv->netdev, &priv->dfs_chandef);
+}
diff --git a/drivers/net/wireless/marvell/mwifiex/11n.c b/drivers/net/wireless/marvell/mwifiex/11n.c
new file mode 100644 (file)
index 0000000..c174e79
--- /dev/null
@@ -0,0 +1,914 @@
+/*
+ * Marvell Wireless LAN device driver: 802.11n
+ *
+ * Copyright (C) 2011-2014, Marvell International Ltd.
+ *
+ * This software file (the "File") is distributed by Marvell International
+ * Ltd. under the terms of the GNU General Public License Version 2, June 1991
+ * (the "License").  You may use, redistribute and/or modify this File in
+ * accordance with the terms and conditions of the License, a copy of which
+ * is available by writing to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the
+ * worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
+ *
+ * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
+ * ARE EXPRESSLY DISCLAIMED.  The License provides additional details about
+ * this warranty disclaimer.
+ */
+
+#include "decl.h"
+#include "ioctl.h"
+#include "util.h"
+#include "fw.h"
+#include "main.h"
+#include "wmm.h"
+#include "11n.h"
+
+/*
+ * Fills HT capability information field, AMPDU Parameters field, HT extended
+ * capability field, and supported MCS set fields.
+ *
+ * HT capability information field, AMPDU Parameters field, supported MCS set
+ * fields are retrieved from cfg80211 stack
+ *
+ * RD responder bit to set to clear in the extended capability header.
+ */
+int mwifiex_fill_cap_info(struct mwifiex_private *priv, u8 radio_type,
+                         struct ieee80211_ht_cap *ht_cap)
+{
+       uint16_t ht_ext_cap = le16_to_cpu(ht_cap->extended_ht_cap_info);
+       struct ieee80211_supported_band *sband =
+                                       priv->wdev.wiphy->bands[radio_type];
+
+       if (WARN_ON_ONCE(!sband)) {
+               mwifiex_dbg(priv->adapter, ERROR, "Invalid radio type!\n");
+               return -EINVAL;
+       }
+
+       ht_cap->ampdu_params_info =
+               (sband->ht_cap.ampdu_factor &
+                IEEE80211_HT_AMPDU_PARM_FACTOR) |
+               ((sband->ht_cap.ampdu_density <<
+                IEEE80211_HT_AMPDU_PARM_DENSITY_SHIFT) &
+                IEEE80211_HT_AMPDU_PARM_DENSITY);
+
+       memcpy((u8 *)&ht_cap->mcs, &sband->ht_cap.mcs,
+              sizeof(sband->ht_cap.mcs));
+
+       if (priv->bss_mode == NL80211_IFTYPE_STATION ||
+           (sband->ht_cap.cap & IEEE80211_HT_CAP_SUP_WIDTH_20_40 &&
+            (priv->adapter->sec_chan_offset !=
+                                       IEEE80211_HT_PARAM_CHA_SEC_NONE)))
+               /* Set MCS32 for infra mode or ad-hoc mode with 40MHz support */
+               SETHT_MCS32(ht_cap->mcs.rx_mask);
+
+       /* Clear RD responder bit */
+       ht_ext_cap &= ~IEEE80211_HT_EXT_CAP_RD_RESPONDER;
+
+       ht_cap->cap_info = cpu_to_le16(sband->ht_cap.cap);
+       ht_cap->extended_ht_cap_info = cpu_to_le16(ht_ext_cap);
+
+       if (ISSUPP_BEAMFORMING(priv->adapter->hw_dot_11n_dev_cap))
+               ht_cap->tx_BF_cap_info = cpu_to_le32(MWIFIEX_DEF_11N_TX_BF_CAP);
+
+       return 0;
+}
+
+/*
+ * This function returns the pointer to an entry in BA Stream
+ * table which matches the requested BA status.
+ */
+static struct mwifiex_tx_ba_stream_tbl *
+mwifiex_get_ba_status(struct mwifiex_private *priv,
+                     enum mwifiex_ba_status ba_status)
+{
+       struct mwifiex_tx_ba_stream_tbl *tx_ba_tsr_tbl;
+       unsigned long flags;
+
+       spin_lock_irqsave(&priv->tx_ba_stream_tbl_lock, flags);
+       list_for_each_entry(tx_ba_tsr_tbl, &priv->tx_ba_stream_tbl_ptr, list) {
+               if (tx_ba_tsr_tbl->ba_status == ba_status) {
+                       spin_unlock_irqrestore(&priv->tx_ba_stream_tbl_lock,
+                                              flags);
+                       return tx_ba_tsr_tbl;
+               }
+       }
+       spin_unlock_irqrestore(&priv->tx_ba_stream_tbl_lock, flags);
+       return NULL;
+}
+
+/*
+ * This function handles the command response of delete a block
+ * ack request.
+ *
+ * The function checks the response success status and takes action
+ * accordingly (send an add BA request in case of success, or recreate
+ * the deleted stream in case of failure, if the add BA was also
+ * initiated by us).
+ */
+int mwifiex_ret_11n_delba(struct mwifiex_private *priv,
+                         struct host_cmd_ds_command *resp)
+{
+       int tid;
+       struct mwifiex_tx_ba_stream_tbl *tx_ba_tbl;
+       struct host_cmd_ds_11n_delba *del_ba = &resp->params.del_ba;
+       uint16_t del_ba_param_set = le16_to_cpu(del_ba->del_ba_param_set);
+
+       tid = del_ba_param_set >> DELBA_TID_POS;
+       if (del_ba->del_result == BA_RESULT_SUCCESS) {
+               mwifiex_del_ba_tbl(priv, tid, del_ba->peer_mac_addr,
+                                  TYPE_DELBA_SENT,
+                                  INITIATOR_BIT(del_ba_param_set));
+
+               tx_ba_tbl = mwifiex_get_ba_status(priv, BA_SETUP_INPROGRESS);
+               if (tx_ba_tbl)
+                       mwifiex_send_addba(priv, tx_ba_tbl->tid,
+                                          tx_ba_tbl->ra);
+       } else { /*
+                 * In case of failure, recreate the deleted stream in case
+                 * we initiated the ADDBA
+                 */
+               if (!INITIATOR_BIT(del_ba_param_set))
+                       return 0;
+
+               mwifiex_create_ba_tbl(priv, del_ba->peer_mac_addr, tid,
+                                     BA_SETUP_INPROGRESS);
+
+               tx_ba_tbl = mwifiex_get_ba_status(priv, BA_SETUP_INPROGRESS);
+
+               if (tx_ba_tbl)
+                       mwifiex_del_ba_tbl(priv, tx_ba_tbl->tid, tx_ba_tbl->ra,
+                                          TYPE_DELBA_SENT, true);
+       }
+
+       return 0;
+}
+
+/*
+ * This function handles the command response of add a block
+ * ack request.
+ *
+ * Handling includes changing the header fields to CPU formats, checking
+ * the response success status and taking actions accordingly (delete the
+ * BA stream table in case of failure).
+ */
+int mwifiex_ret_11n_addba_req(struct mwifiex_private *priv,
+                             struct host_cmd_ds_command *resp)
+{
+       int tid, tid_down;
+       struct host_cmd_ds_11n_addba_rsp *add_ba_rsp = &resp->params.add_ba_rsp;
+       struct mwifiex_tx_ba_stream_tbl *tx_ba_tbl;
+       struct mwifiex_ra_list_tbl *ra_list;
+       u16 block_ack_param_set = le16_to_cpu(add_ba_rsp->block_ack_param_set);
+
+       add_ba_rsp->ssn = cpu_to_le16((le16_to_cpu(add_ba_rsp->ssn))
+                       & SSN_MASK);
+
+       tid = (block_ack_param_set & IEEE80211_ADDBA_PARAM_TID_MASK)
+              >> BLOCKACKPARAM_TID_POS;
+
+       tid_down = mwifiex_wmm_downgrade_tid(priv, tid);
+       ra_list = mwifiex_wmm_get_ralist_node(priv, tid_down, add_ba_rsp->
+               peer_mac_addr);
+       if (le16_to_cpu(add_ba_rsp->status_code) != BA_RESULT_SUCCESS) {
+               if (ra_list) {
+                       ra_list->ba_status = BA_SETUP_NONE;
+                       ra_list->amsdu_in_ampdu = false;
+               }
+               mwifiex_del_ba_tbl(priv, tid, add_ba_rsp->peer_mac_addr,
+                                  TYPE_DELBA_SENT, true);
+               if (add_ba_rsp->add_rsp_result != BA_RESULT_TIMEOUT)
+                       priv->aggr_prio_tbl[tid].ampdu_ap =
+                               BA_STREAM_NOT_ALLOWED;
+               return 0;
+       }
+
+       tx_ba_tbl = mwifiex_get_ba_tbl(priv, tid, add_ba_rsp->peer_mac_addr);
+       if (tx_ba_tbl) {
+               mwifiex_dbg(priv->adapter, EVENT, "info: BA stream complete\n");
+               tx_ba_tbl->ba_status = BA_SETUP_COMPLETE;
+               if ((block_ack_param_set & BLOCKACKPARAM_AMSDU_SUPP_MASK) &&
+                   priv->add_ba_param.tx_amsdu &&
+                   (priv->aggr_prio_tbl[tid].amsdu != BA_STREAM_NOT_ALLOWED))
+                       tx_ba_tbl->amsdu = true;
+               else
+                       tx_ba_tbl->amsdu = false;
+               if (ra_list) {
+                       ra_list->amsdu_in_ampdu = tx_ba_tbl->amsdu;
+                       ra_list->ba_status = BA_SETUP_COMPLETE;
+               }
+       } else {
+               mwifiex_dbg(priv->adapter, ERROR, "BA stream not created\n");
+       }
+
+       return 0;
+}
+
+/*
+ * This function prepares command of reconfigure Tx buffer.
+ *
+ * Preparation includes -
+ *      - Setting command ID, action and proper size
+ *      - Setting Tx buffer size (for SET only)
+ *      - Ensuring correct endian-ness
+ */
+int mwifiex_cmd_recfg_tx_buf(struct mwifiex_private *priv,
+                            struct host_cmd_ds_command *cmd, int cmd_action,
+                            u16 *buf_size)
+{
+       struct host_cmd_ds_txbuf_cfg *tx_buf = &cmd->params.tx_buf;
+       u16 action = (u16) cmd_action;
+
+       cmd->command = cpu_to_le16(HostCmd_CMD_RECONFIGURE_TX_BUFF);
+       cmd->size =
+               cpu_to_le16(sizeof(struct host_cmd_ds_txbuf_cfg) + S_DS_GEN);
+       tx_buf->action = cpu_to_le16(action);
+       switch (action) {
+       case HostCmd_ACT_GEN_SET:
+               mwifiex_dbg(priv->adapter, CMD,
+                           "cmd: set tx_buf=%d\n", *buf_size);
+               tx_buf->buff_size = cpu_to_le16(*buf_size);
+               break;
+       case HostCmd_ACT_GEN_GET:
+       default:
+               tx_buf->buff_size = 0;
+               break;
+       }
+       return 0;
+}
+
+/*
+ * This function prepares command of AMSDU aggregation control.
+ *
+ * Preparation includes -
+ *      - Setting command ID, action and proper size
+ *      - Setting AMSDU control parameters (for SET only)
+ *      - Ensuring correct endian-ness
+ */
+int mwifiex_cmd_amsdu_aggr_ctrl(struct host_cmd_ds_command *cmd,
+                               int cmd_action,
+                               struct mwifiex_ds_11n_amsdu_aggr_ctrl *aa_ctrl)
+{
+       struct host_cmd_ds_amsdu_aggr_ctrl *amsdu_ctrl =
+               &cmd->params.amsdu_aggr_ctrl;
+       u16 action = (u16) cmd_action;
+
+       cmd->command = cpu_to_le16(HostCmd_CMD_AMSDU_AGGR_CTRL);
+       cmd->size = cpu_to_le16(sizeof(struct host_cmd_ds_amsdu_aggr_ctrl)
+                               + S_DS_GEN);
+       amsdu_ctrl->action = cpu_to_le16(action);
+       switch (action) {
+       case HostCmd_ACT_GEN_SET:
+               amsdu_ctrl->enable = cpu_to_le16(aa_ctrl->enable);
+               amsdu_ctrl->curr_buf_size = 0;
+               break;
+       case HostCmd_ACT_GEN_GET:
+       default:
+               amsdu_ctrl->curr_buf_size = 0;
+               break;
+       }
+       return 0;
+}
+
+/*
+ * This function prepares 11n configuration command.
+ *
+ * Preparation includes -
+ *      - Setting command ID, action and proper size
+ *      - Setting HT Tx capability and HT Tx information fields
+ *      - Ensuring correct endian-ness
+ */
+int mwifiex_cmd_11n_cfg(struct mwifiex_private *priv,
+                       struct host_cmd_ds_command *cmd, u16 cmd_action,
+                       struct mwifiex_ds_11n_tx_cfg *txcfg)
+{
+       struct host_cmd_ds_11n_cfg *htcfg = &cmd->params.htcfg;
+
+       cmd->command = cpu_to_le16(HostCmd_CMD_11N_CFG);
+       cmd->size = cpu_to_le16(sizeof(struct host_cmd_ds_11n_cfg) + S_DS_GEN);
+       htcfg->action = cpu_to_le16(cmd_action);
+       htcfg->ht_tx_cap = cpu_to_le16(txcfg->tx_htcap);
+       htcfg->ht_tx_info = cpu_to_le16(txcfg->tx_htinfo);
+
+       if (priv->adapter->is_hw_11ac_capable)
+               htcfg->misc_config = cpu_to_le16(txcfg->misc_config);
+
+       return 0;
+}
+
+/*
+ * This function appends an 11n TLV to a buffer.
+ *
+ * Buffer allocation is responsibility of the calling
+ * function. No size validation is made here.
+ *
+ * The function fills up the following sections, if applicable -
+ *      - HT capability IE
+ *      - HT information IE (with channel list)
+ *      - 20/40 BSS Coexistence IE
+ *      - HT Extended Capabilities IE
+ */
+int
+mwifiex_cmd_append_11n_tlv(struct mwifiex_private *priv,
+                          struct mwifiex_bssdescriptor *bss_desc,
+                          u8 **buffer)
+{
+       struct mwifiex_ie_types_htcap *ht_cap;
+       struct mwifiex_ie_types_htinfo *ht_info;
+       struct mwifiex_ie_types_chan_list_param_set *chan_list;
+       struct mwifiex_ie_types_2040bssco *bss_co_2040;
+       struct mwifiex_ie_types_extcap *ext_cap;
+       int ret_len = 0;
+       struct ieee80211_supported_band *sband;
+       struct ieee_types_header *hdr;
+       u8 radio_type;
+
+       if (!buffer || !*buffer)
+               return ret_len;
+
+       radio_type = mwifiex_band_to_radio_type((u8) bss_desc->bss_band);
+       sband = priv->wdev.wiphy->bands[radio_type];
+
+       if (bss_desc->bcn_ht_cap) {
+               ht_cap = (struct mwifiex_ie_types_htcap *) *buffer;
+               memset(ht_cap, 0, sizeof(struct mwifiex_ie_types_htcap));
+               ht_cap->header.type = cpu_to_le16(WLAN_EID_HT_CAPABILITY);
+               ht_cap->header.len =
+                               cpu_to_le16(sizeof(struct ieee80211_ht_cap));
+               memcpy((u8 *) ht_cap + sizeof(struct mwifiex_ie_types_header),
+                      (u8 *)bss_desc->bcn_ht_cap,
+                      le16_to_cpu(ht_cap->header.len));
+
+               mwifiex_fill_cap_info(priv, radio_type, &ht_cap->ht_cap);
+
+               *buffer += sizeof(struct mwifiex_ie_types_htcap);
+               ret_len += sizeof(struct mwifiex_ie_types_htcap);
+       }
+
+       if (bss_desc->bcn_ht_oper) {
+               if (priv->bss_mode == NL80211_IFTYPE_ADHOC) {
+                       ht_info = (struct mwifiex_ie_types_htinfo *) *buffer;
+                       memset(ht_info, 0,
+                              sizeof(struct mwifiex_ie_types_htinfo));
+                       ht_info->header.type =
+                                       cpu_to_le16(WLAN_EID_HT_OPERATION);
+                       ht_info->header.len =
+                               cpu_to_le16(
+                                       sizeof(struct ieee80211_ht_operation));
+
+                       memcpy((u8 *) ht_info +
+                              sizeof(struct mwifiex_ie_types_header),
+                              (u8 *)bss_desc->bcn_ht_oper,
+                              le16_to_cpu(ht_info->header.len));
+
+                       if (!(sband->ht_cap.cap &
+                                       IEEE80211_HT_CAP_SUP_WIDTH_20_40))
+                               ht_info->ht_oper.ht_param &=
+                                       ~(IEEE80211_HT_PARAM_CHAN_WIDTH_ANY |
+                                       IEEE80211_HT_PARAM_CHA_SEC_OFFSET);
+
+                       *buffer += sizeof(struct mwifiex_ie_types_htinfo);
+                       ret_len += sizeof(struct mwifiex_ie_types_htinfo);
+               }
+
+               chan_list =
+                       (struct mwifiex_ie_types_chan_list_param_set *) *buffer;
+               memset(chan_list, 0,
+                      sizeof(struct mwifiex_ie_types_chan_list_param_set));
+               chan_list->header.type = cpu_to_le16(TLV_TYPE_CHANLIST);
+               chan_list->header.len = cpu_to_le16(
+                       sizeof(struct mwifiex_ie_types_chan_list_param_set) -
+                       sizeof(struct mwifiex_ie_types_header));
+               chan_list->chan_scan_param[0].chan_number =
+                       bss_desc->bcn_ht_oper->primary_chan;
+               chan_list->chan_scan_param[0].radio_type =
+                       mwifiex_band_to_radio_type((u8) bss_desc->bss_band);
+
+               if (sband->ht_cap.cap & IEEE80211_HT_CAP_SUP_WIDTH_20_40 &&
+                   bss_desc->bcn_ht_oper->ht_param &
+                   IEEE80211_HT_PARAM_CHAN_WIDTH_ANY)
+                       SET_SECONDARYCHAN(chan_list->chan_scan_param[0].
+                                         radio_type,
+                                         (bss_desc->bcn_ht_oper->ht_param &
+                                         IEEE80211_HT_PARAM_CHA_SEC_OFFSET));
+
+               *buffer += sizeof(struct mwifiex_ie_types_chan_list_param_set);
+               ret_len += sizeof(struct mwifiex_ie_types_chan_list_param_set);
+       }
+
+       if (bss_desc->bcn_bss_co_2040) {
+               bss_co_2040 = (struct mwifiex_ie_types_2040bssco *) *buffer;
+               memset(bss_co_2040, 0,
+                      sizeof(struct mwifiex_ie_types_2040bssco));
+               bss_co_2040->header.type = cpu_to_le16(WLAN_EID_BSS_COEX_2040);
+               bss_co_2040->header.len =
+                      cpu_to_le16(sizeof(bss_co_2040->bss_co_2040));
+
+               memcpy((u8 *) bss_co_2040 +
+                      sizeof(struct mwifiex_ie_types_header),
+                      bss_desc->bcn_bss_co_2040 +
+                      sizeof(struct ieee_types_header),
+                      le16_to_cpu(bss_co_2040->header.len));
+
+               *buffer += sizeof(struct mwifiex_ie_types_2040bssco);
+               ret_len += sizeof(struct mwifiex_ie_types_2040bssco);
+       }
+
+       if (bss_desc->bcn_ext_cap) {
+               hdr = (void *)bss_desc->bcn_ext_cap;
+               ext_cap = (struct mwifiex_ie_types_extcap *) *buffer;
+               memset(ext_cap, 0, sizeof(struct mwifiex_ie_types_extcap));
+               ext_cap->header.type = cpu_to_le16(WLAN_EID_EXT_CAPABILITY);
+               ext_cap->header.len = cpu_to_le16(hdr->len);
+
+               memcpy((u8 *)ext_cap->ext_capab,
+                      bss_desc->bcn_ext_cap + sizeof(struct ieee_types_header),
+                      le16_to_cpu(ext_cap->header.len));
+
+               if (hdr->len > 3 &&
+                   ext_cap->ext_capab[3] & WLAN_EXT_CAPA4_INTERWORKING_ENABLED)
+                       priv->hs2_enabled = true;
+               else
+                       priv->hs2_enabled = false;
+
+               *buffer += sizeof(struct mwifiex_ie_types_extcap) + hdr->len;
+               ret_len += sizeof(struct mwifiex_ie_types_extcap) + hdr->len;
+       }
+
+       return ret_len;
+}
+
+/*
+ * This function checks if the given pointer is valid entry of
+ * Tx BA Stream table.
+ */
+static int mwifiex_is_tx_ba_stream_ptr_valid(struct mwifiex_private *priv,
+                               struct mwifiex_tx_ba_stream_tbl *tx_tbl_ptr)
+{
+       struct mwifiex_tx_ba_stream_tbl *tx_ba_tsr_tbl;
+
+       list_for_each_entry(tx_ba_tsr_tbl, &priv->tx_ba_stream_tbl_ptr, list) {
+               if (tx_ba_tsr_tbl == tx_tbl_ptr)
+                       return true;
+       }
+
+       return false;
+}
+
+/*
+ * This function deletes the given entry in Tx BA Stream table.
+ *
+ * The function also performs a validity check on the supplied
+ * pointer before trying to delete.
+ */
+void mwifiex_11n_delete_tx_ba_stream_tbl_entry(struct mwifiex_private *priv,
+                               struct mwifiex_tx_ba_stream_tbl *tx_ba_tsr_tbl)
+{
+       if (!tx_ba_tsr_tbl &&
+           mwifiex_is_tx_ba_stream_ptr_valid(priv, tx_ba_tsr_tbl))
+               return;
+
+       mwifiex_dbg(priv->adapter, INFO,
+                   "info: tx_ba_tsr_tbl %p\n", tx_ba_tsr_tbl);
+
+       list_del(&tx_ba_tsr_tbl->list);
+
+       kfree(tx_ba_tsr_tbl);
+}
+
+/*
+ * This function deletes all the entries in Tx BA Stream table.
+ */
+void mwifiex_11n_delete_all_tx_ba_stream_tbl(struct mwifiex_private *priv)
+{
+       int i;
+       struct mwifiex_tx_ba_stream_tbl *del_tbl_ptr, *tmp_node;
+       unsigned long flags;
+
+       spin_lock_irqsave(&priv->tx_ba_stream_tbl_lock, flags);
+       list_for_each_entry_safe(del_tbl_ptr, tmp_node,
+                                &priv->tx_ba_stream_tbl_ptr, list)
+               mwifiex_11n_delete_tx_ba_stream_tbl_entry(priv, del_tbl_ptr);
+       spin_unlock_irqrestore(&priv->tx_ba_stream_tbl_lock, flags);
+
+       INIT_LIST_HEAD(&priv->tx_ba_stream_tbl_ptr);
+
+       for (i = 0; i < MAX_NUM_TID; ++i)
+               priv->aggr_prio_tbl[i].ampdu_ap =
+                       priv->aggr_prio_tbl[i].ampdu_user;
+}
+
+/*
+ * This function returns the pointer to an entry in BA Stream
+ * table which matches the given RA/TID pair.
+ */
+struct mwifiex_tx_ba_stream_tbl *
+mwifiex_get_ba_tbl(struct mwifiex_private *priv, int tid, u8 *ra)
+{
+       struct mwifiex_tx_ba_stream_tbl *tx_ba_tsr_tbl;
+       unsigned long flags;
+
+       spin_lock_irqsave(&priv->tx_ba_stream_tbl_lock, flags);
+       list_for_each_entry(tx_ba_tsr_tbl, &priv->tx_ba_stream_tbl_ptr, list) {
+               if (ether_addr_equal_unaligned(tx_ba_tsr_tbl->ra, ra) &&
+                   tx_ba_tsr_tbl->tid == tid) {
+                       spin_unlock_irqrestore(&priv->tx_ba_stream_tbl_lock,
+                                              flags);
+                       return tx_ba_tsr_tbl;
+               }
+       }
+       spin_unlock_irqrestore(&priv->tx_ba_stream_tbl_lock, flags);
+       return NULL;
+}
+
+/*
+ * This function creates an entry in Tx BA stream table for the
+ * given RA/TID pair.
+ */
+void mwifiex_create_ba_tbl(struct mwifiex_private *priv, u8 *ra, int tid,
+                          enum mwifiex_ba_status ba_status)
+{
+       struct mwifiex_tx_ba_stream_tbl *new_node;
+       struct mwifiex_ra_list_tbl *ra_list;
+       unsigned long flags;
+       int tid_down;
+
+       if (!mwifiex_get_ba_tbl(priv, tid, ra)) {
+               new_node = kzalloc(sizeof(struct mwifiex_tx_ba_stream_tbl),
+                                  GFP_ATOMIC);
+               if (!new_node)
+                       return;
+
+               tid_down = mwifiex_wmm_downgrade_tid(priv, tid);
+               ra_list = mwifiex_wmm_get_ralist_node(priv, tid_down, ra);
+               if (ra_list) {
+                       ra_list->ba_status = ba_status;
+                       ra_list->amsdu_in_ampdu = false;
+               }
+               INIT_LIST_HEAD(&new_node->list);
+
+               new_node->tid = tid;
+               new_node->ba_status = ba_status;
+               memcpy(new_node->ra, ra, ETH_ALEN);
+
+               spin_lock_irqsave(&priv->tx_ba_stream_tbl_lock, flags);
+               list_add_tail(&new_node->list, &priv->tx_ba_stream_tbl_ptr);
+               spin_unlock_irqrestore(&priv->tx_ba_stream_tbl_lock, flags);
+       }
+}
+
+/*
+ * This function sends an add BA request to the given TID/RA pair.
+ */
+int mwifiex_send_addba(struct mwifiex_private *priv, int tid, u8 *peer_mac)
+{
+       struct host_cmd_ds_11n_addba_req add_ba_req;
+       u32 tx_win_size = priv->add_ba_param.tx_win_size;
+       static u8 dialog_tok;
+       int ret;
+       unsigned long flags;
+       u16 block_ack_param_set;
+
+       mwifiex_dbg(priv->adapter, CMD, "cmd: %s: tid %d\n", __func__, tid);
+
+       if ((GET_BSS_ROLE(priv) == MWIFIEX_BSS_ROLE_STA) &&
+           ISSUPP_TDLS_ENABLED(priv->adapter->fw_cap_info) &&
+           priv->adapter->is_hw_11ac_capable &&
+           memcmp(priv->cfg_bssid, peer_mac, ETH_ALEN)) {
+               struct mwifiex_sta_node *sta_ptr;
+
+               spin_lock_irqsave(&priv->sta_list_spinlock, flags);
+               sta_ptr = mwifiex_get_sta_entry(priv, peer_mac);
+               if (!sta_ptr) {
+                       spin_unlock_irqrestore(&priv->sta_list_spinlock, flags);
+                       mwifiex_dbg(priv->adapter, ERROR,
+                                   "BA setup with unknown TDLS peer %pM!\n",
+                                   peer_mac);
+                       return -1;
+               }
+               if (sta_ptr->is_11ac_enabled)
+                       tx_win_size = MWIFIEX_11AC_STA_AMPDU_DEF_TXWINSIZE;
+               spin_unlock_irqrestore(&priv->sta_list_spinlock, flags);
+       }
+
+       block_ack_param_set = (u16)((tid << BLOCKACKPARAM_TID_POS) |
+                                   tx_win_size << BLOCKACKPARAM_WINSIZE_POS |
+                                   IMMEDIATE_BLOCK_ACK);
+
+       /* enable AMSDU inside AMPDU */
+       if (priv->add_ba_param.tx_amsdu &&
+           (priv->aggr_prio_tbl[tid].amsdu != BA_STREAM_NOT_ALLOWED))
+               block_ack_param_set |= BLOCKACKPARAM_AMSDU_SUPP_MASK;
+
+       add_ba_req.block_ack_param_set = cpu_to_le16(block_ack_param_set);
+       add_ba_req.block_ack_tmo = cpu_to_le16((u16)priv->add_ba_param.timeout);
+
+       ++dialog_tok;
+
+       if (dialog_tok == 0)
+               dialog_tok = 1;
+
+       add_ba_req.dialog_token = dialog_tok;
+       memcpy(&add_ba_req.peer_mac_addr, peer_mac, ETH_ALEN);
+
+       /* We don't wait for the response of this command */
+       ret = mwifiex_send_cmd(priv, HostCmd_CMD_11N_ADDBA_REQ,
+                              0, 0, &add_ba_req, false);
+
+       return ret;
+}
+
+/*
+ * This function sends a delete BA request to the given TID/RA pair.
+ */
+int mwifiex_send_delba(struct mwifiex_private *priv, int tid, u8 *peer_mac,
+                      int initiator)
+{
+       struct host_cmd_ds_11n_delba delba;
+       int ret;
+       uint16_t del_ba_param_set;
+
+       memset(&delba, 0, sizeof(delba));
+       delba.del_ba_param_set = cpu_to_le16(tid << DELBA_TID_POS);
+
+       del_ba_param_set = le16_to_cpu(delba.del_ba_param_set);
+       if (initiator)
+               del_ba_param_set |= IEEE80211_DELBA_PARAM_INITIATOR_MASK;
+       else
+               del_ba_param_set &= ~IEEE80211_DELBA_PARAM_INITIATOR_MASK;
+
+       memcpy(&delba.peer_mac_addr, peer_mac, ETH_ALEN);
+
+       /* We don't wait for the response of this command */
+       ret = mwifiex_send_cmd(priv, HostCmd_CMD_11N_DELBA,
+                              HostCmd_ACT_GEN_SET, 0, &delba, false);
+
+       return ret;
+}
+
+/*
+ * This function sends delba to specific tid
+ */
+void mwifiex_11n_delba(struct mwifiex_private *priv, int tid)
+{
+       struct mwifiex_rx_reorder_tbl *rx_reor_tbl_ptr;
+
+       if (list_empty(&priv->rx_reorder_tbl_ptr)) {
+               dev_dbg(priv->adapter->dev,
+                       "mwifiex_11n_delba: rx_reorder_tbl_ptr empty\n");
+               return;
+       }
+
+       list_for_each_entry(rx_reor_tbl_ptr, &priv->rx_reorder_tbl_ptr, list) {
+               if (rx_reor_tbl_ptr->tid == tid) {
+                       dev_dbg(priv->adapter->dev,
+                               "Send delba to tid=%d, %pM\n",
+                               tid, rx_reor_tbl_ptr->ta);
+                       mwifiex_send_delba(priv, tid, rx_reor_tbl_ptr->ta, 0);
+                       return;
+               }
+       }
+}
+
+/*
+ * This function handles the command response of a delete BA request.
+ */
+void mwifiex_11n_delete_ba_stream(struct mwifiex_private *priv, u8 *del_ba)
+{
+       struct host_cmd_ds_11n_delba *cmd_del_ba =
+               (struct host_cmd_ds_11n_delba *) del_ba;
+       uint16_t del_ba_param_set = le16_to_cpu(cmd_del_ba->del_ba_param_set);
+       int tid;
+
+       tid = del_ba_param_set >> DELBA_TID_POS;
+
+       mwifiex_del_ba_tbl(priv, tid, cmd_del_ba->peer_mac_addr,
+                          TYPE_DELBA_RECEIVE, INITIATOR_BIT(del_ba_param_set));
+}
+
+/*
+ * This function retrieves the Rx reordering table.
+ */
+int mwifiex_get_rx_reorder_tbl(struct mwifiex_private *priv,
+                              struct mwifiex_ds_rx_reorder_tbl *buf)
+{
+       int i;
+       struct mwifiex_ds_rx_reorder_tbl *rx_reo_tbl = buf;
+       struct mwifiex_rx_reorder_tbl *rx_reorder_tbl_ptr;
+       int count = 0;
+       unsigned long flags;
+
+       spin_lock_irqsave(&priv->rx_reorder_tbl_lock, flags);
+       list_for_each_entry(rx_reorder_tbl_ptr, &priv->rx_reorder_tbl_ptr,
+                           list) {
+               rx_reo_tbl->tid = (u16) rx_reorder_tbl_ptr->tid;
+               memcpy(rx_reo_tbl->ta, rx_reorder_tbl_ptr->ta, ETH_ALEN);
+               rx_reo_tbl->start_win = rx_reorder_tbl_ptr->start_win;
+               rx_reo_tbl->win_size = rx_reorder_tbl_ptr->win_size;
+               for (i = 0; i < rx_reorder_tbl_ptr->win_size; ++i) {
+                       if (rx_reorder_tbl_ptr->rx_reorder_ptr[i])
+                               rx_reo_tbl->buffer[i] = true;
+                       else
+                               rx_reo_tbl->buffer[i] = false;
+               }
+               rx_reo_tbl++;
+               count++;
+
+               if (count >= MWIFIEX_MAX_RX_BASTREAM_SUPPORTED)
+                       break;
+       }
+       spin_unlock_irqrestore(&priv->rx_reorder_tbl_lock, flags);
+
+       return count;
+}
+
+/*
+ * This function retrieves the Tx BA stream table.
+ */
+int mwifiex_get_tx_ba_stream_tbl(struct mwifiex_private *priv,
+                                struct mwifiex_ds_tx_ba_stream_tbl *buf)
+{
+       struct mwifiex_tx_ba_stream_tbl *tx_ba_tsr_tbl;
+       struct mwifiex_ds_tx_ba_stream_tbl *rx_reo_tbl = buf;
+       int count = 0;
+       unsigned long flags;
+
+       spin_lock_irqsave(&priv->tx_ba_stream_tbl_lock, flags);
+       list_for_each_entry(tx_ba_tsr_tbl, &priv->tx_ba_stream_tbl_ptr, list) {
+               rx_reo_tbl->tid = (u16) tx_ba_tsr_tbl->tid;
+               mwifiex_dbg(priv->adapter, DATA, "data: %s tid=%d\n",
+                           __func__, rx_reo_tbl->tid);
+               memcpy(rx_reo_tbl->ra, tx_ba_tsr_tbl->ra, ETH_ALEN);
+               rx_reo_tbl->amsdu = tx_ba_tsr_tbl->amsdu;
+               rx_reo_tbl++;
+               count++;
+               if (count >= MWIFIEX_MAX_TX_BASTREAM_SUPPORTED)
+                       break;
+       }
+       spin_unlock_irqrestore(&priv->tx_ba_stream_tbl_lock, flags);
+
+       return count;
+}
+
+/*
+ * This function retrieves the entry for specific tx BA stream table by RA and
+ * deletes it.
+ */
+void mwifiex_del_tx_ba_stream_tbl_by_ra(struct mwifiex_private *priv, u8 *ra)
+{
+       struct mwifiex_tx_ba_stream_tbl *tbl, *tmp;
+       unsigned long flags;
+
+       if (!ra)
+               return;
+
+       spin_lock_irqsave(&priv->tx_ba_stream_tbl_lock, flags);
+       list_for_each_entry_safe(tbl, tmp, &priv->tx_ba_stream_tbl_ptr, list) {
+               if (!memcmp(tbl->ra, ra, ETH_ALEN)) {
+                       spin_unlock_irqrestore(&priv->tx_ba_stream_tbl_lock,
+                                              flags);
+                       mwifiex_11n_delete_tx_ba_stream_tbl_entry(priv, tbl);
+                       spin_lock_irqsave(&priv->tx_ba_stream_tbl_lock, flags);
+               }
+       }
+       spin_unlock_irqrestore(&priv->tx_ba_stream_tbl_lock, flags);
+
+       return;
+}
+
+/* This function initializes the BlockACK setup information for given
+ * mwifiex_private structure.
+ */
+void mwifiex_set_ba_params(struct mwifiex_private *priv)
+{
+       priv->add_ba_param.timeout = MWIFIEX_DEFAULT_BLOCK_ACK_TIMEOUT;
+
+       if (GET_BSS_ROLE(priv) == MWIFIEX_BSS_ROLE_UAP) {
+               priv->add_ba_param.tx_win_size =
+                                               MWIFIEX_UAP_AMPDU_DEF_TXWINSIZE;
+               priv->add_ba_param.rx_win_size =
+                                               MWIFIEX_UAP_AMPDU_DEF_RXWINSIZE;
+       } else {
+               priv->add_ba_param.tx_win_size =
+                                               MWIFIEX_STA_AMPDU_DEF_TXWINSIZE;
+               priv->add_ba_param.rx_win_size =
+                                               MWIFIEX_STA_AMPDU_DEF_RXWINSIZE;
+       }
+
+       priv->add_ba_param.tx_amsdu = true;
+       priv->add_ba_param.rx_amsdu = true;
+
+       return;
+}
+
+u8 mwifiex_get_sec_chan_offset(int chan)
+{
+       u8 sec_offset;
+
+       switch (chan) {
+       case 36:
+       case 44:
+       case 52:
+       case 60:
+       case 100:
+       case 108:
+       case 116:
+       case 124:
+       case 132:
+       case 140:
+       case 149:
+       case 157:
+               sec_offset = IEEE80211_HT_PARAM_CHA_SEC_ABOVE;
+               break;
+       case 40:
+       case 48:
+       case 56:
+       case 64:
+       case 104:
+       case 112:
+       case 120:
+       case 128:
+       case 136:
+       case 144:
+       case 153:
+       case 161:
+               sec_offset = IEEE80211_HT_PARAM_CHA_SEC_BELOW;
+               break;
+       case 165:
+       default:
+               sec_offset = IEEE80211_HT_PARAM_CHA_SEC_NONE;
+               break;
+       }
+
+       return sec_offset;
+}
+
+/* This function will send DELBA to entries in the priv's
+ * Tx BA stream table
+ */
+static void
+mwifiex_send_delba_txbastream_tbl(struct mwifiex_private *priv, u8 tid)
+{
+       struct mwifiex_adapter *adapter = priv->adapter;
+       struct mwifiex_tx_ba_stream_tbl *tx_ba_stream_tbl_ptr;
+
+       if (list_empty(&priv->tx_ba_stream_tbl_ptr))
+               return;
+
+       list_for_each_entry(tx_ba_stream_tbl_ptr,
+                           &priv->tx_ba_stream_tbl_ptr, list) {
+               if (tx_ba_stream_tbl_ptr->ba_status == BA_SETUP_COMPLETE) {
+                       if (tid == tx_ba_stream_tbl_ptr->tid) {
+                               dev_dbg(adapter->dev,
+                                       "Tx:Send delba to tid=%d, %pM\n", tid,
+                                       tx_ba_stream_tbl_ptr->ra);
+                               mwifiex_send_delba(priv,
+                                                  tx_ba_stream_tbl_ptr->tid,
+                                                  tx_ba_stream_tbl_ptr->ra, 1);
+                               return;
+                       }
+               }
+       }
+}
+
+/* This function updates all the tx_win_size
+ */
+void mwifiex_update_ampdu_txwinsize(struct mwifiex_adapter *adapter)
+{
+       u8 i;
+       u32 tx_win_size;
+       struct mwifiex_private *priv;
+
+       for (i = 0; i < adapter->priv_num; i++) {
+               if (!adapter->priv[i])
+                       continue;
+               priv = adapter->priv[i];
+               tx_win_size = priv->add_ba_param.tx_win_size;
+
+               if (priv->bss_type == MWIFIEX_BSS_TYPE_STA)
+                       priv->add_ba_param.tx_win_size =
+                               MWIFIEX_STA_AMPDU_DEF_TXWINSIZE;
+
+               if (priv->bss_type == MWIFIEX_BSS_TYPE_P2P)
+                       priv->add_ba_param.tx_win_size =
+                               MWIFIEX_STA_AMPDU_DEF_TXWINSIZE;
+
+               if (priv->bss_type == MWIFIEX_BSS_TYPE_UAP)
+                       priv->add_ba_param.tx_win_size =
+                               MWIFIEX_UAP_AMPDU_DEF_TXWINSIZE;
+
+               if (adapter->coex_win_size) {
+                       if (adapter->coex_tx_win_size)
+                               priv->add_ba_param.tx_win_size =
+                                       adapter->coex_tx_win_size;
+               }
+
+               if (tx_win_size != priv->add_ba_param.tx_win_size) {
+                       if (!priv->media_connected)
+                               continue;
+                       for (i = 0; i < MAX_NUM_TID; i++)
+                               mwifiex_send_delba_txbastream_tbl(priv, i);
+               }
+       }
+}
diff --git a/drivers/net/wireless/marvell/mwifiex/11n.h b/drivers/net/wireless/marvell/mwifiex/11n.h
new file mode 100644 (file)
index 0000000..afdd58a
--- /dev/null
@@ -0,0 +1,191 @@
+/*
+ * Marvell Wireless LAN device driver: 802.11n
+ *
+ * Copyright (C) 2011-2014, Marvell International Ltd.
+ *
+ * This software file (the "File") is distributed by Marvell International
+ * Ltd. under the terms of the GNU General Public License Version 2, June 1991
+ * (the "License").  You may use, redistribute and/or modify this File in
+ * accordance with the terms and conditions of the License, a copy of which
+ * is available by writing to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the
+ * worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
+ *
+ * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
+ * ARE EXPRESSLY DISCLAIMED.  The License provides additional details about
+ * this warranty disclaimer.
+ */
+
+#ifndef _MWIFIEX_11N_H_
+#define _MWIFIEX_11N_H_
+
+#include "11n_aggr.h"
+#include "11n_rxreorder.h"
+#include "wmm.h"
+
+int mwifiex_ret_11n_delba(struct mwifiex_private *priv,
+                         struct host_cmd_ds_command *resp);
+int mwifiex_ret_11n_addba_req(struct mwifiex_private *priv,
+                             struct host_cmd_ds_command *resp);
+int mwifiex_cmd_11n_cfg(struct mwifiex_private *priv,
+                       struct host_cmd_ds_command *cmd, u16 cmd_action,
+                       struct mwifiex_ds_11n_tx_cfg *txcfg);
+int mwifiex_cmd_append_11n_tlv(struct mwifiex_private *priv,
+                              struct mwifiex_bssdescriptor *bss_desc,
+                              u8 **buffer);
+int mwifiex_fill_cap_info(struct mwifiex_private *, u8 radio_type,
+                         struct ieee80211_ht_cap *);
+int mwifiex_set_get_11n_htcap_cfg(struct mwifiex_private *priv,
+                                 u16 action, int *htcap_cfg);
+void mwifiex_11n_delete_tx_ba_stream_tbl_entry(struct mwifiex_private *priv,
+                                            struct mwifiex_tx_ba_stream_tbl
+                                            *tx_tbl);
+void mwifiex_11n_delete_all_tx_ba_stream_tbl(struct mwifiex_private *priv);
+struct mwifiex_tx_ba_stream_tbl *mwifiex_get_ba_tbl(struct
+                                                            mwifiex_private
+                                                            *priv, int tid,
+                                                            u8 *ra);
+void mwifiex_create_ba_tbl(struct mwifiex_private *priv, u8 *ra, int tid,
+                          enum mwifiex_ba_status ba_status);
+int mwifiex_send_addba(struct mwifiex_private *priv, int tid, u8 *peer_mac);
+int mwifiex_send_delba(struct mwifiex_private *priv, int tid, u8 *peer_mac,
+                      int initiator);
+void mwifiex_11n_delete_ba_stream(struct mwifiex_private *priv, u8 *del_ba);
+int mwifiex_get_rx_reorder_tbl(struct mwifiex_private *priv,
+                             struct mwifiex_ds_rx_reorder_tbl *buf);
+int mwifiex_get_tx_ba_stream_tbl(struct mwifiex_private *priv,
+                              struct mwifiex_ds_tx_ba_stream_tbl *buf);
+int mwifiex_cmd_recfg_tx_buf(struct mwifiex_private *priv,
+                            struct host_cmd_ds_command *cmd,
+                            int cmd_action, u16 *buf_size);
+int mwifiex_cmd_amsdu_aggr_ctrl(struct host_cmd_ds_command *cmd,
+                               int cmd_action,
+                               struct mwifiex_ds_11n_amsdu_aggr_ctrl *aa_ctrl);
+void mwifiex_del_tx_ba_stream_tbl_by_ra(struct mwifiex_private *priv, u8 *ra);
+u8 mwifiex_get_sec_chan_offset(int chan);
+
+static inline u8
+mwifiex_is_station_ampdu_allowed(struct mwifiex_private *priv,
+                                struct mwifiex_ra_list_tbl *ptr, int tid)
+{
+       struct mwifiex_sta_node *node = mwifiex_get_sta_entry(priv, ptr->ra);
+
+       if (unlikely(!node))
+               return false;
+
+       return (node->ampdu_sta[tid] != BA_STREAM_NOT_ALLOWED) ? true : false;
+}
+
+/* This function checks whether AMPDU is allowed or not for a particular TID. */
+static inline u8
+mwifiex_is_ampdu_allowed(struct mwifiex_private *priv,
+                        struct mwifiex_ra_list_tbl *ptr, int tid)
+{
+       if (is_broadcast_ether_addr(ptr->ra))
+               return false;
+       if (GET_BSS_ROLE(priv) == MWIFIEX_BSS_ROLE_UAP) {
+               return mwifiex_is_station_ampdu_allowed(priv, ptr, tid);
+       } else {
+               if (ptr->tdls_link)
+                       return mwifiex_is_station_ampdu_allowed(priv, ptr, tid);
+
+               return (priv->aggr_prio_tbl[tid].ampdu_ap !=
+                       BA_STREAM_NOT_ALLOWED) ? true : false;
+       }
+}
+
+/*
+ * This function checks whether AMSDU is allowed or not for a particular TID.
+ */
+static inline u8
+mwifiex_is_amsdu_allowed(struct mwifiex_private *priv, int tid)
+{
+       return (((priv->aggr_prio_tbl[tid].amsdu != BA_STREAM_NOT_ALLOWED) &&
+                (priv->is_data_rate_auto || !(priv->bitmap_rates[2] & 0x03)))
+               ? true : false);
+}
+
+/*
+ * This function checks whether a space is available for new BA stream or not.
+ */
+static inline u8 mwifiex_space_avail_for_new_ba_stream(
+                                       struct mwifiex_adapter *adapter)
+{
+       struct mwifiex_private *priv;
+       u8 i;
+       u32 ba_stream_num = 0, ba_stream_max;
+
+       ba_stream_max = MWIFIEX_MAX_TX_BASTREAM_SUPPORTED;
+
+       for (i = 0; i < adapter->priv_num; i++) {
+               priv = adapter->priv[i];
+               if (priv)
+                       ba_stream_num += mwifiex_wmm_list_len(
+                               &priv->tx_ba_stream_tbl_ptr);
+       }
+
+       if (adapter->fw_api_ver == MWIFIEX_FW_V15) {
+               ba_stream_max =
+                              GETSUPP_TXBASTREAMS(adapter->hw_dot_11n_dev_cap);
+               if (!ba_stream_max)
+                       ba_stream_max = MWIFIEX_MAX_TX_BASTREAM_SUPPORTED;
+       }
+
+       return ((ba_stream_num < ba_stream_max) ? true : false);
+}
+
+/*
+ * This function finds the correct Tx BA stream to delete.
+ *
+ * Upon successfully locating, both the TID and the RA are returned.
+ */
+static inline u8
+mwifiex_find_stream_to_delete(struct mwifiex_private *priv, int ptr_tid,
+                             int *ptid, u8 *ra)
+{
+       int tid;
+       u8 ret = false;
+       struct mwifiex_tx_ba_stream_tbl *tx_tbl;
+       unsigned long flags;
+
+       tid = priv->aggr_prio_tbl[ptr_tid].ampdu_user;
+
+       spin_lock_irqsave(&priv->tx_ba_stream_tbl_lock, flags);
+       list_for_each_entry(tx_tbl, &priv->tx_ba_stream_tbl_ptr, list) {
+               if (tid > priv->aggr_prio_tbl[tx_tbl->tid].ampdu_user) {
+                       tid = priv->aggr_prio_tbl[tx_tbl->tid].ampdu_user;
+                       *ptid = tx_tbl->tid;
+                       memcpy(ra, tx_tbl->ra, ETH_ALEN);
+                       ret = true;
+               }
+       }
+       spin_unlock_irqrestore(&priv->tx_ba_stream_tbl_lock, flags);
+
+       return ret;
+}
+
+/*
+ * This function checks whether associated station is 11n enabled
+ */
+static inline int mwifiex_is_sta_11n_enabled(struct mwifiex_private *priv,
+                                            struct mwifiex_sta_node *node)
+{
+
+       if (!node || (priv->bss_role != MWIFIEX_BSS_ROLE_UAP) ||
+           !priv->ap_11n_enabled)
+               return 0;
+
+       return node->is_11n_enabled;
+}
+
+static inline u8
+mwifiex_tdls_peer_11n_enabled(struct mwifiex_private *priv, const u8 *ra)
+{
+       struct mwifiex_sta_node *node = mwifiex_get_sta_entry(priv, ra);
+       if (node)
+               return node->is_11n_enabled;
+
+       return false;
+}
+#endif /* !_MWIFIEX_11N_H_ */
diff --git a/drivers/net/wireless/marvell/mwifiex/11n_aggr.c b/drivers/net/wireless/marvell/mwifiex/11n_aggr.c
new file mode 100644 (file)
index 0000000..aa498e0
--- /dev/null
@@ -0,0 +1,318 @@
+/*
+ * Marvell Wireless LAN device driver: 802.11n Aggregation
+ *
+ * Copyright (C) 2011-2014, Marvell International Ltd.
+ *
+ * This software file (the "File") is distributed by Marvell International
+ * Ltd. under the terms of the GNU General Public License Version 2, June 1991
+ * (the "License").  You may use, redistribute and/or modify this File in
+ * accordance with the terms and conditions of the License, a copy of which
+ * is available by writing to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the
+ * worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
+ *
+ * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
+ * ARE EXPRESSLY DISCLAIMED.  The License provides additional details about
+ * this warranty disclaimer.
+ */
+
+#include "decl.h"
+#include "ioctl.h"
+#include "util.h"
+#include "fw.h"
+#include "main.h"
+#include "wmm.h"
+#include "11n.h"
+#include "11n_aggr.h"
+
+/*
+ * Creates an AMSDU subframe for aggregation into one AMSDU packet.
+ *
+ * The resultant AMSDU subframe format is -
+ *
+ * +---- ~ -----+---- ~ ------+---- ~ -----+----- ~ -----+---- ~ -----+
+ * |     DA     |     SA      |   Length   | SNAP header |   MSDU     |
+ * | data[0..5] | data[6..11] |            |             | data[14..] |
+ * +---- ~ -----+---- ~ ------+---- ~ -----+----- ~ -----+---- ~ -----+
+ * <--6-bytes--> <--6-bytes--> <--2-bytes--><--8-bytes--> <--n-bytes-->
+ *
+ * This function also computes the amount of padding required to make the
+ * buffer length multiple of 4 bytes.
+ *
+ * Data => |DA|SA|SNAP-TYPE|........    .|
+ * MSDU => |DA|SA|Length|SNAP|......   ..|
+ */
+static int
+mwifiex_11n_form_amsdu_pkt(struct sk_buff *skb_aggr,
+                          struct sk_buff *skb_src, int *pad)
+
+{
+       int dt_offset;
+       struct rfc_1042_hdr snap = {
+               0xaa,           /* LLC DSAP */
+               0xaa,           /* LLC SSAP */
+               0x03,           /* LLC CTRL */
+               {0x00, 0x00, 0x00},     /* SNAP OUI */
+               0x0000          /* SNAP type */
+                       /*
+                        * This field will be overwritten
+                        * later with ethertype
+                        */
+       };
+       struct tx_packet_hdr *tx_header;
+
+       tx_header = (void *)skb_put(skb_aggr, sizeof(*tx_header));
+
+       /* Copy DA and SA */
+       dt_offset = 2 * ETH_ALEN;
+       memcpy(&tx_header->eth803_hdr, skb_src->data, dt_offset);
+
+       /* Copy SNAP header */
+       snap.snap_type = ((struct ethhdr *)skb_src->data)->h_proto;
+
+       dt_offset += sizeof(__be16);
+
+       memcpy(&tx_header->rfc1042_hdr, &snap, sizeof(struct rfc_1042_hdr));
+
+       skb_pull(skb_src, dt_offset);
+
+       /* Update Length field */
+       tx_header->eth803_hdr.h_proto = htons(skb_src->len + LLC_SNAP_LEN);
+
+       /* Add payload */
+       memcpy(skb_put(skb_aggr, skb_src->len), skb_src->data, skb_src->len);
+
+       /* Add padding for new MSDU to start from 4 byte boundary */
+       *pad = (4 - ((unsigned long)skb_aggr->tail & 0x3)) % 4;
+
+       return skb_aggr->len + *pad;
+}
+
+/*
+ * Adds TxPD to AMSDU header.
+ *
+ * Each AMSDU packet will contain one TxPD at the beginning,
+ * followed by multiple AMSDU subframes.
+ */
+static void
+mwifiex_11n_form_amsdu_txpd(struct mwifiex_private *priv,
+                           struct sk_buff *skb)
+{
+       struct txpd *local_tx_pd;
+       struct mwifiex_txinfo *tx_info = MWIFIEX_SKB_TXCB(skb);
+       unsigned int pad;
+       int headroom = (priv->adapter->iface_type ==
+                       MWIFIEX_USB) ? 0 : INTF_HEADER_LEN;
+
+       pad = ((void *)skb->data - sizeof(*local_tx_pd) -
+               headroom - NULL) & (MWIFIEX_DMA_ALIGN_SZ - 1);
+       skb_push(skb, pad);
+
+       skb_push(skb, sizeof(*local_tx_pd));
+
+       local_tx_pd = (struct txpd *) skb->data;
+       memset(local_tx_pd, 0, sizeof(struct txpd));
+
+       /* Original priority has been overwritten */
+       local_tx_pd->priority = (u8) skb->priority;
+       local_tx_pd->pkt_delay_2ms =
+               mwifiex_wmm_compute_drv_pkt_delay(priv, skb);
+       local_tx_pd->bss_num = priv->bss_num;
+       local_tx_pd->bss_type = priv->bss_type;
+       /* Always zero as the data is followed by struct txpd */
+       local_tx_pd->tx_pkt_offset = cpu_to_le16(sizeof(struct txpd) +
+                                                pad);
+       local_tx_pd->tx_pkt_type = cpu_to_le16(PKT_TYPE_AMSDU);
+       local_tx_pd->tx_pkt_length = cpu_to_le16(skb->len -
+                                                sizeof(*local_tx_pd) -
+                                                pad);
+
+       if (tx_info->flags & MWIFIEX_BUF_FLAG_TDLS_PKT)
+               local_tx_pd->flags |= MWIFIEX_TXPD_FLAGS_TDLS_PACKET;
+
+       if (local_tx_pd->tx_control == 0)
+               /* TxCtrl set by user or default */
+               local_tx_pd->tx_control = cpu_to_le32(priv->pkt_tx_ctrl);
+
+       if (GET_BSS_ROLE(priv) == MWIFIEX_BSS_ROLE_STA &&
+           priv->adapter->pps_uapsd_mode) {
+               if (true == mwifiex_check_last_packet_indication(priv)) {
+                       priv->adapter->tx_lock_flag = true;
+                       local_tx_pd->flags =
+                               MWIFIEX_TxPD_POWER_MGMT_LAST_PACKET;
+               }
+       }
+}
+
+/*
+ * Create aggregated packet.
+ *
+ * This function creates an aggregated MSDU packet, by combining buffers
+ * from the RA list. Each individual buffer is encapsulated as an AMSDU
+ * subframe and all such subframes are concatenated together to form the
+ * AMSDU packet.
+ *
+ * A TxPD is also added to the front of the resultant AMSDU packets for
+ * transmission. The resultant packets format is -
+ *
+ * +---- ~ ----+------ ~ ------+------ ~ ------+-..-+------ ~ ------+
+ * |    TxPD   |AMSDU sub-frame|AMSDU sub-frame| .. |AMSDU sub-frame|
+ * |           |       1       |       2       | .. |       n       |
+ * +---- ~ ----+------ ~ ------+------ ~ ------+ .. +------ ~ ------+
+ */
+int
+mwifiex_11n_aggregate_pkt(struct mwifiex_private *priv,
+                         struct mwifiex_ra_list_tbl *pra_list,
+                         int ptrindex, unsigned long ra_list_flags)
+                         __releases(&priv->wmm.ra_list_spinlock)
+{
+       struct mwifiex_adapter *adapter = priv->adapter;
+       struct sk_buff *skb_aggr, *skb_src;
+       struct mwifiex_txinfo *tx_info_aggr, *tx_info_src;
+       int pad = 0, aggr_num = 0, ret;
+       struct mwifiex_tx_param tx_param;
+       struct txpd *ptx_pd = NULL;
+       int headroom = adapter->iface_type == MWIFIEX_USB ? 0 : INTF_HEADER_LEN;
+
+       skb_src = skb_peek(&pra_list->skb_head);
+       if (!skb_src) {
+               spin_unlock_irqrestore(&priv->wmm.ra_list_spinlock,
+                                      ra_list_flags);
+               return 0;
+       }
+
+       tx_info_src = MWIFIEX_SKB_TXCB(skb_src);
+       skb_aggr = mwifiex_alloc_dma_align_buf(adapter->tx_buf_size,
+                                              GFP_ATOMIC | GFP_DMA);
+       if (!skb_aggr) {
+               spin_unlock_irqrestore(&priv->wmm.ra_list_spinlock,
+                                      ra_list_flags);
+               return -1;
+       }
+       skb_reserve(skb_aggr, MWIFIEX_MIN_DATA_HEADER_LEN);
+       tx_info_aggr =  MWIFIEX_SKB_TXCB(skb_aggr);
+
+       memset(tx_info_aggr, 0, sizeof(*tx_info_aggr));
+       tx_info_aggr->bss_type = tx_info_src->bss_type;
+       tx_info_aggr->bss_num = tx_info_src->bss_num;
+
+       if (tx_info_src->flags & MWIFIEX_BUF_FLAG_TDLS_PKT)
+               tx_info_aggr->flags |= MWIFIEX_BUF_FLAG_TDLS_PKT;
+       tx_info_aggr->flags |= MWIFIEX_BUF_FLAG_AGGR_PKT;
+       skb_aggr->priority = skb_src->priority;
+       skb_aggr->tstamp = skb_src->tstamp;
+
+       skb_aggr->tstamp = ktime_get_real();
+
+       do {
+               /* Check if AMSDU can accommodate this MSDU */
+               if (skb_tailroom(skb_aggr) < (skb_src->len + LLC_SNAP_LEN))
+                       break;
+
+               skb_src = skb_dequeue(&pra_list->skb_head);
+               pra_list->total_pkt_count--;
+               atomic_dec(&priv->wmm.tx_pkts_queued);
+               aggr_num++;
+               spin_unlock_irqrestore(&priv->wmm.ra_list_spinlock,
+                                      ra_list_flags);
+               mwifiex_11n_form_amsdu_pkt(skb_aggr, skb_src, &pad);
+
+               mwifiex_write_data_complete(adapter, skb_src, 0, 0);
+
+               spin_lock_irqsave(&priv->wmm.ra_list_spinlock, ra_list_flags);
+
+               if (!mwifiex_is_ralist_valid(priv, pra_list, ptrindex)) {
+                       spin_unlock_irqrestore(&priv->wmm.ra_list_spinlock,
+                                              ra_list_flags);
+                       return -1;
+               }
+
+               if (skb_tailroom(skb_aggr) < pad) {
+                       pad = 0;
+                       break;
+               }
+               skb_put(skb_aggr, pad);
+
+               skb_src = skb_peek(&pra_list->skb_head);
+
+       } while (skb_src);
+
+       spin_unlock_irqrestore(&priv->wmm.ra_list_spinlock, ra_list_flags);
+
+       /* Last AMSDU packet does not need padding */
+       skb_trim(skb_aggr, skb_aggr->len - pad);
+
+       /* Form AMSDU */
+       mwifiex_11n_form_amsdu_txpd(priv, skb_aggr);
+       if (GET_BSS_ROLE(priv) == MWIFIEX_BSS_ROLE_STA)
+               ptx_pd = (struct txpd *)skb_aggr->data;
+
+       skb_push(skb_aggr, headroom);
+       tx_info_aggr->aggr_num = aggr_num * 2;
+       if (adapter->data_sent || adapter->tx_lock_flag) {
+               atomic_add(aggr_num * 2, &adapter->tx_queued);
+               skb_queue_tail(&adapter->tx_data_q, skb_aggr);
+               return 0;
+       }
+
+       if (adapter->iface_type == MWIFIEX_USB) {
+               ret = adapter->if_ops.host_to_card(adapter, priv->usb_port,
+                                                  skb_aggr, NULL);
+       } else {
+               if (skb_src)
+                       tx_param.next_pkt_len =
+                                       skb_src->len + sizeof(struct txpd);
+               else
+                       tx_param.next_pkt_len = 0;
+
+               ret = adapter->if_ops.host_to_card(adapter, MWIFIEX_TYPE_DATA,
+                                                  skb_aggr, &tx_param);
+       }
+       switch (ret) {
+       case -EBUSY:
+               spin_lock_irqsave(&priv->wmm.ra_list_spinlock, ra_list_flags);
+               if (!mwifiex_is_ralist_valid(priv, pra_list, ptrindex)) {
+                       spin_unlock_irqrestore(&priv->wmm.ra_list_spinlock,
+                                              ra_list_flags);
+                       mwifiex_write_data_complete(adapter, skb_aggr, 1, -1);
+                       return -1;
+               }
+               if (GET_BSS_ROLE(priv) == MWIFIEX_BSS_ROLE_STA &&
+                   adapter->pps_uapsd_mode && adapter->tx_lock_flag) {
+                               priv->adapter->tx_lock_flag = false;
+                               if (ptx_pd)
+                                       ptx_pd->flags = 0;
+               }
+
+               skb_queue_tail(&pra_list->skb_head, skb_aggr);
+
+               pra_list->total_pkt_count++;
+
+               atomic_inc(&priv->wmm.tx_pkts_queued);
+
+               tx_info_aggr->flags |= MWIFIEX_BUF_FLAG_REQUEUED_PKT;
+               spin_unlock_irqrestore(&priv->wmm.ra_list_spinlock,
+                                      ra_list_flags);
+               mwifiex_dbg(adapter, ERROR, "data: -EBUSY is returned\n");
+               break;
+       case -1:
+               mwifiex_dbg(adapter, ERROR, "%s: host_to_card failed: %#x\n",
+                           __func__, ret);
+               adapter->dbg.num_tx_host_to_card_failure++;
+               mwifiex_write_data_complete(adapter, skb_aggr, 1, ret);
+               return 0;
+       case -EINPROGRESS:
+               break;
+       case 0:
+               mwifiex_write_data_complete(adapter, skb_aggr, 1, ret);
+               break;
+       default:
+               break;
+       }
+       if (ret != -EBUSY) {
+               mwifiex_rotate_priolists(priv, pra_list, ptrindex);
+       }
+
+       return 0;
+}
diff --git a/drivers/net/wireless/marvell/mwifiex/11n_aggr.h b/drivers/net/wireless/marvell/mwifiex/11n_aggr.h
new file mode 100644 (file)
index 0000000..0cd2a3e
--- /dev/null
@@ -0,0 +1,33 @@
+/*
+ * Marvell Wireless LAN device driver: 802.11n Aggregation
+ *
+ * Copyright (C) 2011-2014, Marvell International Ltd.
+ *
+ * This software file (the "File") is distributed by Marvell International
+ * Ltd. under the terms of the GNU General Public License Version 2, June 1991
+ * (the "License").  You may use, redistribute and/or modify this File in
+ * accordance with the terms and conditions of the License, a copy of which
+ * is available by writing to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the
+ * worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
+ *
+ * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
+ * ARE EXPRESSLY DISCLAIMED.  The License provides additional details about
+ * this warranty disclaimer.
+ */
+
+#ifndef _MWIFIEX_11N_AGGR_H_
+#define _MWIFIEX_11N_AGGR_H_
+
+#define PKT_TYPE_AMSDU 0xE6
+#define MIN_NUM_AMSDU 2
+
+int mwifiex_11n_deaggregate_pkt(struct mwifiex_private *priv,
+                               struct sk_buff *skb);
+int mwifiex_11n_aggregate_pkt(struct mwifiex_private *priv,
+                             struct mwifiex_ra_list_tbl *ptr,
+                             int ptr_index, unsigned long flags)
+                             __releases(&priv->wmm.ra_list_spinlock);
+
+#endif /* !_MWIFIEX_11N_AGGR_H_ */
diff --git a/drivers/net/wireless/marvell/mwifiex/11n_rxreorder.c b/drivers/net/wireless/marvell/mwifiex/11n_rxreorder.c
new file mode 100644 (file)
index 0000000..b3970a8
--- /dev/null
@@ -0,0 +1,910 @@
+/*
+ * Marvell Wireless LAN device driver: 802.11n RX Re-ordering
+ *
+ * Copyright (C) 2011-2014, Marvell International Ltd.
+ *
+ * This software file (the "File") is distributed by Marvell International
+ * Ltd. under the terms of the GNU General Public License Version 2, June 1991
+ * (the "License").  You may use, redistribute and/or modify this File in
+ * accordance with the terms and conditions of the License, a copy of which
+ * is available by writing to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the
+ * worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
+ *
+ * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
+ * ARE EXPRESSLY DISCLAIMED.  The License provides additional details about
+ * this warranty disclaimer.
+ */
+
+#include "decl.h"
+#include "ioctl.h"
+#include "util.h"
+#include "fw.h"
+#include "main.h"
+#include "wmm.h"
+#include "11n.h"
+#include "11n_rxreorder.h"
+
+/* This function will dispatch amsdu packet and forward it to kernel/upper
+ * layer.
+ */
+static int mwifiex_11n_dispatch_amsdu_pkt(struct mwifiex_private *priv,
+                                         struct sk_buff *skb)
+{
+       struct rxpd *local_rx_pd = (struct rxpd *)(skb->data);
+       int ret;
+
+       if (le16_to_cpu(local_rx_pd->rx_pkt_type) == PKT_TYPE_AMSDU) {
+               struct sk_buff_head list;
+               struct sk_buff *rx_skb;
+
+               __skb_queue_head_init(&list);
+
+               skb_pull(skb, le16_to_cpu(local_rx_pd->rx_pkt_offset));
+               skb_trim(skb, le16_to_cpu(local_rx_pd->rx_pkt_length));
+
+               ieee80211_amsdu_to_8023s(skb, &list, priv->curr_addr,
+                                        priv->wdev.iftype, 0, false);
+
+               while (!skb_queue_empty(&list)) {
+                       rx_skb = __skb_dequeue(&list);
+                       ret = mwifiex_recv_packet(priv, rx_skb);
+                       if (ret == -1)
+                               mwifiex_dbg(priv->adapter, ERROR,
+                                           "Rx of A-MSDU failed");
+               }
+               return 0;
+       }
+
+       return -1;
+}
+
+/* This function will process the rx packet and forward it to kernel/upper
+ * layer.
+ */
+static int mwifiex_11n_dispatch_pkt(struct mwifiex_private *priv, void *payload)
+{
+       int ret = mwifiex_11n_dispatch_amsdu_pkt(priv, payload);
+
+       if (!ret)
+               return 0;
+
+       if (priv->bss_role == MWIFIEX_BSS_ROLE_UAP)
+               return mwifiex_handle_uap_rx_forward(priv, payload);
+
+       return mwifiex_process_rx_packet(priv, payload);
+}
+
+/*
+ * This function dispatches all packets in the Rx reorder table until the
+ * start window.
+ *
+ * There could be holes in the buffer, which are skipped by the function.
+ * Since the buffer is linear, the function uses rotation to simulate
+ * circular buffer.
+ */
+static void
+mwifiex_11n_dispatch_pkt_until_start_win(struct mwifiex_private *priv,
+                                        struct mwifiex_rx_reorder_tbl *tbl,
+                                        int start_win)
+{
+       int pkt_to_send, i;
+       void *rx_tmp_ptr;
+       unsigned long flags;
+
+       pkt_to_send = (start_win > tbl->start_win) ?
+                     min((start_win - tbl->start_win), tbl->win_size) :
+                     tbl->win_size;
+
+       for (i = 0; i < pkt_to_send; ++i) {
+               spin_lock_irqsave(&priv->rx_pkt_lock, flags);
+               rx_tmp_ptr = NULL;
+               if (tbl->rx_reorder_ptr[i]) {
+                       rx_tmp_ptr = tbl->rx_reorder_ptr[i];
+                       tbl->rx_reorder_ptr[i] = NULL;
+               }
+               spin_unlock_irqrestore(&priv->rx_pkt_lock, flags);
+               if (rx_tmp_ptr)
+                       mwifiex_11n_dispatch_pkt(priv, rx_tmp_ptr);
+       }
+
+       spin_lock_irqsave(&priv->rx_pkt_lock, flags);
+       /*
+        * We don't have a circular buffer, hence use rotation to simulate
+        * circular buffer
+        */
+       for (i = 0; i < tbl->win_size - pkt_to_send; ++i) {
+               tbl->rx_reorder_ptr[i] = tbl->rx_reorder_ptr[pkt_to_send + i];
+               tbl->rx_reorder_ptr[pkt_to_send + i] = NULL;
+       }
+
+       tbl->start_win = start_win;
+       spin_unlock_irqrestore(&priv->rx_pkt_lock, flags);
+}
+
+/*
+ * This function dispatches all packets in the Rx reorder table until
+ * a hole is found.
+ *
+ * The start window is adjusted automatically when a hole is located.
+ * Since the buffer is linear, the function uses rotation to simulate
+ * circular buffer.
+ */
+static void
+mwifiex_11n_scan_and_dispatch(struct mwifiex_private *priv,
+                             struct mwifiex_rx_reorder_tbl *tbl)
+{
+       int i, j, xchg;
+       void *rx_tmp_ptr;
+       unsigned long flags;
+
+       for (i = 0; i < tbl->win_size; ++i) {
+               spin_lock_irqsave(&priv->rx_pkt_lock, flags);
+               if (!tbl->rx_reorder_ptr[i]) {
+                       spin_unlock_irqrestore(&priv->rx_pkt_lock, flags);
+                       break;
+               }
+               rx_tmp_ptr = tbl->rx_reorder_ptr[i];
+               tbl->rx_reorder_ptr[i] = NULL;
+               spin_unlock_irqrestore(&priv->rx_pkt_lock, flags);
+               mwifiex_11n_dispatch_pkt(priv, rx_tmp_ptr);
+       }
+
+       spin_lock_irqsave(&priv->rx_pkt_lock, flags);
+       /*
+        * We don't have a circular buffer, hence use rotation to simulate
+        * circular buffer
+        */
+       if (i > 0) {
+               xchg = tbl->win_size - i;
+               for (j = 0; j < xchg; ++j) {
+                       tbl->rx_reorder_ptr[j] = tbl->rx_reorder_ptr[i + j];
+                       tbl->rx_reorder_ptr[i + j] = NULL;
+               }
+       }
+       tbl->start_win = (tbl->start_win + i) & (MAX_TID_VALUE - 1);
+       spin_unlock_irqrestore(&priv->rx_pkt_lock, flags);
+}
+
+/*
+ * This function deletes the Rx reorder table and frees the memory.
+ *
+ * The function stops the associated timer and dispatches all the
+ * pending packets in the Rx reorder table before deletion.
+ */
+static void
+mwifiex_del_rx_reorder_entry(struct mwifiex_private *priv,
+                            struct mwifiex_rx_reorder_tbl *tbl)
+{
+       unsigned long flags;
+       int start_win;
+
+       if (!tbl)
+               return;
+
+       spin_lock_irqsave(&priv->adapter->rx_proc_lock, flags);
+       priv->adapter->rx_locked = true;
+       if (priv->adapter->rx_processing) {
+               spin_unlock_irqrestore(&priv->adapter->rx_proc_lock, flags);
+               flush_workqueue(priv->adapter->rx_workqueue);
+       } else {
+               spin_unlock_irqrestore(&priv->adapter->rx_proc_lock, flags);
+       }
+
+       start_win = (tbl->start_win + tbl->win_size) & (MAX_TID_VALUE - 1);
+       mwifiex_11n_dispatch_pkt_until_start_win(priv, tbl, start_win);
+
+       del_timer_sync(&tbl->timer_context.timer);
+       tbl->timer_context.timer_is_set = false;
+
+       spin_lock_irqsave(&priv->rx_reorder_tbl_lock, flags);
+       list_del(&tbl->list);
+       spin_unlock_irqrestore(&priv->rx_reorder_tbl_lock, flags);
+
+       kfree(tbl->rx_reorder_ptr);
+       kfree(tbl);
+
+       spin_lock_irqsave(&priv->adapter->rx_proc_lock, flags);
+       priv->adapter->rx_locked = false;
+       spin_unlock_irqrestore(&priv->adapter->rx_proc_lock, flags);
+
+}
+
+/*
+ * This function returns the pointer to an entry in Rx reordering
+ * table which matches the given TA/TID pair.
+ */
+struct mwifiex_rx_reorder_tbl *
+mwifiex_11n_get_rx_reorder_tbl(struct mwifiex_private *priv, int tid, u8 *ta)
+{
+       struct mwifiex_rx_reorder_tbl *tbl;
+       unsigned long flags;
+
+       spin_lock_irqsave(&priv->rx_reorder_tbl_lock, flags);
+       list_for_each_entry(tbl, &priv->rx_reorder_tbl_ptr, list) {
+               if (!memcmp(tbl->ta, ta, ETH_ALEN) && tbl->tid == tid) {
+                       spin_unlock_irqrestore(&priv->rx_reorder_tbl_lock,
+                                              flags);
+                       return tbl;
+               }
+       }
+       spin_unlock_irqrestore(&priv->rx_reorder_tbl_lock, flags);
+
+       return NULL;
+}
+
+/* This function retrieves the pointer to an entry in Rx reordering
+ * table which matches the given TA and deletes it.
+ */
+void mwifiex_11n_del_rx_reorder_tbl_by_ta(struct mwifiex_private *priv, u8 *ta)
+{
+       struct mwifiex_rx_reorder_tbl *tbl, *tmp;
+       unsigned long flags;
+
+       if (!ta)
+               return;
+
+       spin_lock_irqsave(&priv->rx_reorder_tbl_lock, flags);
+       list_for_each_entry_safe(tbl, tmp, &priv->rx_reorder_tbl_ptr, list) {
+               if (!memcmp(tbl->ta, ta, ETH_ALEN)) {
+                       spin_unlock_irqrestore(&priv->rx_reorder_tbl_lock,
+                                              flags);
+                       mwifiex_del_rx_reorder_entry(priv, tbl);
+                       spin_lock_irqsave(&priv->rx_reorder_tbl_lock, flags);
+               }
+       }
+       spin_unlock_irqrestore(&priv->rx_reorder_tbl_lock, flags);
+
+       return;
+}
+
+/*
+ * This function finds the last sequence number used in the packets
+ * buffered in Rx reordering table.
+ */
+static int
+mwifiex_11n_find_last_seq_num(struct reorder_tmr_cnxt *ctx)
+{
+       struct mwifiex_rx_reorder_tbl *rx_reorder_tbl_ptr = ctx->ptr;
+       struct mwifiex_private *priv = ctx->priv;
+       unsigned long flags;
+       int i;
+
+       spin_lock_irqsave(&priv->rx_reorder_tbl_lock, flags);
+       for (i = rx_reorder_tbl_ptr->win_size - 1; i >= 0; --i) {
+               if (rx_reorder_tbl_ptr->rx_reorder_ptr[i]) {
+                       spin_unlock_irqrestore(&priv->rx_reorder_tbl_lock,
+                                              flags);
+                       return i;
+               }
+       }
+       spin_unlock_irqrestore(&priv->rx_reorder_tbl_lock, flags);
+
+       return -1;
+}
+
+/*
+ * This function flushes all the packets in Rx reordering table.
+ *
+ * The function checks if any packets are currently buffered in the
+ * table or not. In case there are packets available, it dispatches
+ * them and then dumps the Rx reordering table.
+ */
+static void
+mwifiex_flush_data(unsigned long context)
+{
+       struct reorder_tmr_cnxt *ctx =
+               (struct reorder_tmr_cnxt *) context;
+       int start_win, seq_num;
+
+       ctx->timer_is_set = false;
+       seq_num = mwifiex_11n_find_last_seq_num(ctx);
+
+       if (seq_num < 0)
+               return;
+
+       mwifiex_dbg(ctx->priv->adapter, INFO, "info: flush data %d\n", seq_num);
+       start_win = (ctx->ptr->start_win + seq_num + 1) & (MAX_TID_VALUE - 1);
+       mwifiex_11n_dispatch_pkt_until_start_win(ctx->priv, ctx->ptr,
+                                                start_win);
+}
+
+/*
+ * This function creates an entry in Rx reordering table for the
+ * given TA/TID.
+ *
+ * The function also initializes the entry with sequence number, window
+ * size as well as initializes the timer.
+ *
+ * If the received TA/TID pair is already present, all the packets are
+ * dispatched and the window size is moved until the SSN.
+ */
+static void
+mwifiex_11n_create_rx_reorder_tbl(struct mwifiex_private *priv, u8 *ta,
+                                 int tid, int win_size, int seq_num)
+{
+       int i;
+       struct mwifiex_rx_reorder_tbl *tbl, *new_node;
+       u16 last_seq = 0;
+       unsigned long flags;
+       struct mwifiex_sta_node *node;
+
+       /*
+        * If we get a TID, ta pair which is already present dispatch all the
+        * the packets and move the window size until the ssn
+        */
+       tbl = mwifiex_11n_get_rx_reorder_tbl(priv, tid, ta);
+       if (tbl) {
+               mwifiex_11n_dispatch_pkt_until_start_win(priv, tbl, seq_num);
+               return;
+       }
+       /* if !tbl then create one */
+       new_node = kzalloc(sizeof(struct mwifiex_rx_reorder_tbl), GFP_KERNEL);
+       if (!new_node)
+               return;
+
+       INIT_LIST_HEAD(&new_node->list);
+       new_node->tid = tid;
+       memcpy(new_node->ta, ta, ETH_ALEN);
+       new_node->start_win = seq_num;
+       new_node->init_win = seq_num;
+       new_node->flags = 0;
+
+       spin_lock_irqsave(&priv->sta_list_spinlock, flags);
+       if (mwifiex_queuing_ra_based(priv)) {
+               if (priv->bss_role == MWIFIEX_BSS_ROLE_UAP) {
+                       node = mwifiex_get_sta_entry(priv, ta);
+                       if (node)
+                               last_seq = node->rx_seq[tid];
+               }
+       } else {
+               node = mwifiex_get_sta_entry(priv, ta);
+               if (node)
+                       last_seq = node->rx_seq[tid];
+               else
+                       last_seq = priv->rx_seq[tid];
+       }
+       spin_unlock_irqrestore(&priv->sta_list_spinlock, flags);
+
+       mwifiex_dbg(priv->adapter, INFO,
+                   "info: last_seq=%d start_win=%d\n",
+                   last_seq, new_node->start_win);
+
+       if (last_seq != MWIFIEX_DEF_11N_RX_SEQ_NUM &&
+           last_seq >= new_node->start_win) {
+               new_node->start_win = last_seq + 1;
+               new_node->flags |= RXREOR_INIT_WINDOW_SHIFT;
+       }
+
+       new_node->win_size = win_size;
+
+       new_node->rx_reorder_ptr = kzalloc(sizeof(void *) * win_size,
+                                       GFP_KERNEL);
+       if (!new_node->rx_reorder_ptr) {
+               kfree((u8 *) new_node);
+               mwifiex_dbg(priv->adapter, ERROR,
+                           "%s: failed to alloc reorder_ptr\n", __func__);
+               return;
+       }
+
+       new_node->timer_context.ptr = new_node;
+       new_node->timer_context.priv = priv;
+       new_node->timer_context.timer_is_set = false;
+
+       setup_timer(&new_node->timer_context.timer, mwifiex_flush_data,
+                   (unsigned long)&new_node->timer_context);
+
+       for (i = 0; i < win_size; ++i)
+               new_node->rx_reorder_ptr[i] = NULL;
+
+       spin_lock_irqsave(&priv->rx_reorder_tbl_lock, flags);
+       list_add_tail(&new_node->list, &priv->rx_reorder_tbl_ptr);
+       spin_unlock_irqrestore(&priv->rx_reorder_tbl_lock, flags);
+}
+
+static void
+mwifiex_11n_rxreorder_timer_restart(struct mwifiex_rx_reorder_tbl *tbl)
+{
+       u32 min_flush_time;
+
+       if (tbl->win_size >= MWIFIEX_BA_WIN_SIZE_32)
+               min_flush_time = MIN_FLUSH_TIMER_15_MS;
+       else
+               min_flush_time = MIN_FLUSH_TIMER_MS;
+
+       mod_timer(&tbl->timer_context.timer,
+                 jiffies + msecs_to_jiffies(min_flush_time * tbl->win_size));
+
+       tbl->timer_context.timer_is_set = true;
+}
+
+/*
+ * This function prepares command for adding a BA request.
+ *
+ * Preparation includes -
+ *      - Setting command ID and proper size
+ *      - Setting add BA request buffer
+ *      - Ensuring correct endian-ness
+ */
+int mwifiex_cmd_11n_addba_req(struct host_cmd_ds_command *cmd, void *data_buf)
+{
+       struct host_cmd_ds_11n_addba_req *add_ba_req = &cmd->params.add_ba_req;
+
+       cmd->command = cpu_to_le16(HostCmd_CMD_11N_ADDBA_REQ);
+       cmd->size = cpu_to_le16(sizeof(*add_ba_req) + S_DS_GEN);
+       memcpy(add_ba_req, data_buf, sizeof(*add_ba_req));
+
+       return 0;
+}
+
+/*
+ * This function prepares command for adding a BA response.
+ *
+ * Preparation includes -
+ *      - Setting command ID and proper size
+ *      - Setting add BA response buffer
+ *      - Ensuring correct endian-ness
+ */
+int mwifiex_cmd_11n_addba_rsp_gen(struct mwifiex_private *priv,
+                                 struct host_cmd_ds_command *cmd,
+                                 struct host_cmd_ds_11n_addba_req
+                                 *cmd_addba_req)
+{
+       struct host_cmd_ds_11n_addba_rsp *add_ba_rsp = &cmd->params.add_ba_rsp;
+       struct mwifiex_sta_node *sta_ptr;
+       u32 rx_win_size = priv->add_ba_param.rx_win_size;
+       u8 tid;
+       int win_size;
+       unsigned long flags;
+       uint16_t block_ack_param_set;
+
+       if ((GET_BSS_ROLE(priv) == MWIFIEX_BSS_ROLE_STA) &&
+           ISSUPP_TDLS_ENABLED(priv->adapter->fw_cap_info) &&
+           priv->adapter->is_hw_11ac_capable &&
+           memcmp(priv->cfg_bssid, cmd_addba_req->peer_mac_addr, ETH_ALEN)) {
+               spin_lock_irqsave(&priv->sta_list_spinlock, flags);
+               sta_ptr = mwifiex_get_sta_entry(priv,
+                                               cmd_addba_req->peer_mac_addr);
+               if (!sta_ptr) {
+                       spin_unlock_irqrestore(&priv->sta_list_spinlock, flags);
+                       mwifiex_dbg(priv->adapter, ERROR,
+                                   "BA setup with unknown TDLS peer %pM!\n",
+                                   cmd_addba_req->peer_mac_addr);
+                       return -1;
+               }
+               if (sta_ptr->is_11ac_enabled)
+                       rx_win_size = MWIFIEX_11AC_STA_AMPDU_DEF_RXWINSIZE;
+               spin_unlock_irqrestore(&priv->sta_list_spinlock, flags);
+       }
+
+       cmd->command = cpu_to_le16(HostCmd_CMD_11N_ADDBA_RSP);
+       cmd->size = cpu_to_le16(sizeof(*add_ba_rsp) + S_DS_GEN);
+
+       memcpy(add_ba_rsp->peer_mac_addr, cmd_addba_req->peer_mac_addr,
+              ETH_ALEN);
+       add_ba_rsp->dialog_token = cmd_addba_req->dialog_token;
+       add_ba_rsp->block_ack_tmo = cmd_addba_req->block_ack_tmo;
+       add_ba_rsp->ssn = cmd_addba_req->ssn;
+
+       block_ack_param_set = le16_to_cpu(cmd_addba_req->block_ack_param_set);
+       tid = (block_ack_param_set & IEEE80211_ADDBA_PARAM_TID_MASK)
+               >> BLOCKACKPARAM_TID_POS;
+       add_ba_rsp->status_code = cpu_to_le16(ADDBA_RSP_STATUS_ACCEPT);
+       block_ack_param_set &= ~IEEE80211_ADDBA_PARAM_BUF_SIZE_MASK;
+
+       /* If we don't support AMSDU inside AMPDU, reset the bit */
+       if (!priv->add_ba_param.rx_amsdu ||
+           (priv->aggr_prio_tbl[tid].amsdu == BA_STREAM_NOT_ALLOWED))
+               block_ack_param_set &= ~BLOCKACKPARAM_AMSDU_SUPP_MASK;
+       block_ack_param_set |= rx_win_size << BLOCKACKPARAM_WINSIZE_POS;
+       add_ba_rsp->block_ack_param_set = cpu_to_le16(block_ack_param_set);
+       win_size = (le16_to_cpu(add_ba_rsp->block_ack_param_set)
+                                       & IEEE80211_ADDBA_PARAM_BUF_SIZE_MASK)
+                                       >> BLOCKACKPARAM_WINSIZE_POS;
+       cmd_addba_req->block_ack_param_set = cpu_to_le16(block_ack_param_set);
+
+       mwifiex_11n_create_rx_reorder_tbl(priv, cmd_addba_req->peer_mac_addr,
+                                         tid, win_size,
+                                         le16_to_cpu(cmd_addba_req->ssn));
+       return 0;
+}
+
+/*
+ * This function prepares command for deleting a BA request.
+ *
+ * Preparation includes -
+ *      - Setting command ID and proper size
+ *      - Setting del BA request buffer
+ *      - Ensuring correct endian-ness
+ */
+int mwifiex_cmd_11n_delba(struct host_cmd_ds_command *cmd, void *data_buf)
+{
+       struct host_cmd_ds_11n_delba *del_ba = &cmd->params.del_ba;
+
+       cmd->command = cpu_to_le16(HostCmd_CMD_11N_DELBA);
+       cmd->size = cpu_to_le16(sizeof(*del_ba) + S_DS_GEN);
+       memcpy(del_ba, data_buf, sizeof(*del_ba));
+
+       return 0;
+}
+
+/*
+ * This function identifies if Rx reordering is needed for a received packet.
+ *
+ * In case reordering is required, the function will do the reordering
+ * before sending it to kernel.
+ *
+ * The Rx reorder table is checked first with the received TID/TA pair. If
+ * not found, the received packet is dispatched immediately. But if found,
+ * the packet is reordered and all the packets in the updated Rx reordering
+ * table is dispatched until a hole is found.
+ *
+ * For sequence number less than the starting window, the packet is dropped.
+ */
+int mwifiex_11n_rx_reorder_pkt(struct mwifiex_private *priv,
+                               u16 seq_num, u16 tid,
+                               u8 *ta, u8 pkt_type, void *payload)
+{
+       struct mwifiex_rx_reorder_tbl *tbl;
+       int prev_start_win, start_win, end_win, win_size;
+       u16 pkt_index;
+       bool init_window_shift = false;
+       int ret = 0;
+
+       tbl = mwifiex_11n_get_rx_reorder_tbl(priv, tid, ta);
+       if (!tbl) {
+               if (pkt_type != PKT_TYPE_BAR)
+                       mwifiex_11n_dispatch_pkt(priv, payload);
+               return ret;
+       }
+
+       if ((pkt_type == PKT_TYPE_AMSDU) && !tbl->amsdu) {
+               mwifiex_11n_dispatch_pkt(priv, payload);
+               return ret;
+       }
+
+       start_win = tbl->start_win;
+       prev_start_win = start_win;
+       win_size = tbl->win_size;
+       end_win = ((start_win + win_size) - 1) & (MAX_TID_VALUE - 1);
+       if (tbl->flags & RXREOR_INIT_WINDOW_SHIFT) {
+               init_window_shift = true;
+               tbl->flags &= ~RXREOR_INIT_WINDOW_SHIFT;
+       }
+
+       if (tbl->flags & RXREOR_FORCE_NO_DROP) {
+               mwifiex_dbg(priv->adapter, INFO,
+                           "RXREOR_FORCE_NO_DROP when HS is activated\n");
+               tbl->flags &= ~RXREOR_FORCE_NO_DROP;
+       } else if (init_window_shift && seq_num < start_win &&
+                  seq_num >= tbl->init_win) {
+               mwifiex_dbg(priv->adapter, INFO,
+                           "Sender TID sequence number reset %d->%d for SSN %d\n",
+                           start_win, seq_num, tbl->init_win);
+               tbl->start_win = start_win = seq_num;
+               end_win = ((start_win + win_size) - 1) & (MAX_TID_VALUE - 1);
+       } else {
+               /*
+                * If seq_num is less then starting win then ignore and drop
+                * the packet
+                */
+               if ((start_win + TWOPOW11) > (MAX_TID_VALUE - 1)) {
+                       if (seq_num >= ((start_win + TWOPOW11) &
+                                       (MAX_TID_VALUE - 1)) &&
+                           seq_num < start_win) {
+                               ret = -1;
+                               goto done;
+                       }
+               } else if ((seq_num < start_win) ||
+                          (seq_num >= (start_win + TWOPOW11))) {
+                       ret = -1;
+                       goto done;
+               }
+       }
+
+       /*
+        * If this packet is a BAR we adjust seq_num as
+        * WinStart = seq_num
+        */
+       if (pkt_type == PKT_TYPE_BAR)
+               seq_num = ((seq_num + win_size) - 1) & (MAX_TID_VALUE - 1);
+
+       if (((end_win < start_win) &&
+            (seq_num < start_win) && (seq_num > end_win)) ||
+           ((end_win > start_win) && ((seq_num > end_win) ||
+                                      (seq_num < start_win)))) {
+               end_win = seq_num;
+               if (((end_win - win_size) + 1) >= 0)
+                       start_win = (end_win - win_size) + 1;
+               else
+                       start_win = (MAX_TID_VALUE - (win_size - end_win)) + 1;
+               mwifiex_11n_dispatch_pkt_until_start_win(priv, tbl, start_win);
+       }
+
+       if (pkt_type != PKT_TYPE_BAR) {
+               if (seq_num >= start_win)
+                       pkt_index = seq_num - start_win;
+               else
+                       pkt_index = (seq_num+MAX_TID_VALUE) - start_win;
+
+               if (tbl->rx_reorder_ptr[pkt_index]) {
+                       ret = -1;
+                       goto done;
+               }
+
+               tbl->rx_reorder_ptr[pkt_index] = payload;
+       }
+
+       /*
+        * Dispatch all packets sequentially from start_win until a
+        * hole is found and adjust the start_win appropriately
+        */
+       mwifiex_11n_scan_and_dispatch(priv, tbl);
+
+done:
+       if (!tbl->timer_context.timer_is_set ||
+           prev_start_win != tbl->start_win)
+               mwifiex_11n_rxreorder_timer_restart(tbl);
+       return ret;
+}
+
+/*
+ * This function deletes an entry for a given TID/TA pair.
+ *
+ * The TID/TA are taken from del BA event body.
+ */
+void
+mwifiex_del_ba_tbl(struct mwifiex_private *priv, int tid, u8 *peer_mac,
+                  u8 type, int initiator)
+{
+       struct mwifiex_rx_reorder_tbl *tbl;
+       struct mwifiex_tx_ba_stream_tbl *ptx_tbl;
+       struct mwifiex_ra_list_tbl *ra_list;
+       u8 cleanup_rx_reorder_tbl;
+       unsigned long flags;
+       int tid_down;
+
+       if (type == TYPE_DELBA_RECEIVE)
+               cleanup_rx_reorder_tbl = (initiator) ? true : false;
+       else
+               cleanup_rx_reorder_tbl = (initiator) ? false : true;
+
+       mwifiex_dbg(priv->adapter, EVENT, "event: DELBA: %pM tid=%d initiator=%d\n",
+                   peer_mac, tid, initiator);
+
+       if (cleanup_rx_reorder_tbl) {
+               tbl = mwifiex_11n_get_rx_reorder_tbl(priv, tid,
+                                                                peer_mac);
+               if (!tbl) {
+                       mwifiex_dbg(priv->adapter, EVENT,
+                                   "event: TID, TA not found in table\n");
+                       return;
+               }
+               mwifiex_del_rx_reorder_entry(priv, tbl);
+       } else {
+               ptx_tbl = mwifiex_get_ba_tbl(priv, tid, peer_mac);
+               if (!ptx_tbl) {
+                       mwifiex_dbg(priv->adapter, EVENT,
+                                   "event: TID, RA not found in table\n");
+                       return;
+               }
+
+               tid_down = mwifiex_wmm_downgrade_tid(priv, tid);
+               ra_list = mwifiex_wmm_get_ralist_node(priv, tid_down, peer_mac);
+               if (ra_list) {
+                       ra_list->amsdu_in_ampdu = false;
+                       ra_list->ba_status = BA_SETUP_NONE;
+               }
+               spin_lock_irqsave(&priv->tx_ba_stream_tbl_lock, flags);
+               mwifiex_11n_delete_tx_ba_stream_tbl_entry(priv, ptx_tbl);
+               spin_unlock_irqrestore(&priv->tx_ba_stream_tbl_lock, flags);
+       }
+}
+
+/*
+ * This function handles the command response of an add BA response.
+ *
+ * Handling includes changing the header fields into CPU format and
+ * creating the stream, provided the add BA is accepted.
+ */
+int mwifiex_ret_11n_addba_resp(struct mwifiex_private *priv,
+                              struct host_cmd_ds_command *resp)
+{
+       struct host_cmd_ds_11n_addba_rsp *add_ba_rsp = &resp->params.add_ba_rsp;
+       int tid, win_size;
+       struct mwifiex_rx_reorder_tbl *tbl;
+       uint16_t block_ack_param_set;
+
+       block_ack_param_set = le16_to_cpu(add_ba_rsp->block_ack_param_set);
+
+       tid = (block_ack_param_set & IEEE80211_ADDBA_PARAM_TID_MASK)
+               >> BLOCKACKPARAM_TID_POS;
+       /*
+        * Check if we had rejected the ADDBA, if yes then do not create
+        * the stream
+        */
+       if (le16_to_cpu(add_ba_rsp->status_code) != BA_RESULT_SUCCESS) {
+               mwifiex_dbg(priv->adapter, ERROR, "ADDBA RSP: failed %pM tid=%d)\n",
+                           add_ba_rsp->peer_mac_addr, tid);
+
+               tbl = mwifiex_11n_get_rx_reorder_tbl(priv, tid,
+                                                    add_ba_rsp->peer_mac_addr);
+               if (tbl)
+                       mwifiex_del_rx_reorder_entry(priv, tbl);
+
+               return 0;
+       }
+
+       win_size = (block_ack_param_set & IEEE80211_ADDBA_PARAM_BUF_SIZE_MASK)
+                   >> BLOCKACKPARAM_WINSIZE_POS;
+
+       tbl = mwifiex_11n_get_rx_reorder_tbl(priv, tid,
+                                            add_ba_rsp->peer_mac_addr);
+       if (tbl) {
+               if ((block_ack_param_set & BLOCKACKPARAM_AMSDU_SUPP_MASK) &&
+                   priv->add_ba_param.rx_amsdu &&
+                   (priv->aggr_prio_tbl[tid].amsdu != BA_STREAM_NOT_ALLOWED))
+                       tbl->amsdu = true;
+               else
+                       tbl->amsdu = false;
+       }
+
+       mwifiex_dbg(priv->adapter, CMD,
+                   "cmd: ADDBA RSP: %pM tid=%d ssn=%d win_size=%d\n",
+               add_ba_rsp->peer_mac_addr, tid, add_ba_rsp->ssn, win_size);
+
+       return 0;
+}
+
+/*
+ * This function handles BA stream timeout event by preparing and sending
+ * a command to the firmware.
+ */
+void mwifiex_11n_ba_stream_timeout(struct mwifiex_private *priv,
+                                  struct host_cmd_ds_11n_batimeout *event)
+{
+       struct host_cmd_ds_11n_delba delba;
+
+       memset(&delba, 0, sizeof(struct host_cmd_ds_11n_delba));
+       memcpy(delba.peer_mac_addr, event->peer_mac_addr, ETH_ALEN);
+
+       delba.del_ba_param_set |=
+               cpu_to_le16((u16) event->tid << DELBA_TID_POS);
+       delba.del_ba_param_set |= cpu_to_le16(
+               (u16) event->origninator << DELBA_INITIATOR_POS);
+       delba.reason_code = cpu_to_le16(WLAN_REASON_QSTA_TIMEOUT);
+       mwifiex_send_cmd(priv, HostCmd_CMD_11N_DELBA, 0, 0, &delba, false);
+}
+
+/*
+ * This function cleans up the Rx reorder table by deleting all the entries
+ * and re-initializing.
+ */
+void mwifiex_11n_cleanup_reorder_tbl(struct mwifiex_private *priv)
+{
+       struct mwifiex_rx_reorder_tbl *del_tbl_ptr, *tmp_node;
+       unsigned long flags;
+
+       spin_lock_irqsave(&priv->rx_reorder_tbl_lock, flags);
+       list_for_each_entry_safe(del_tbl_ptr, tmp_node,
+                                &priv->rx_reorder_tbl_ptr, list) {
+               spin_unlock_irqrestore(&priv->rx_reorder_tbl_lock, flags);
+               mwifiex_del_rx_reorder_entry(priv, del_tbl_ptr);
+               spin_lock_irqsave(&priv->rx_reorder_tbl_lock, flags);
+       }
+       INIT_LIST_HEAD(&priv->rx_reorder_tbl_ptr);
+       spin_unlock_irqrestore(&priv->rx_reorder_tbl_lock, flags);
+
+       mwifiex_reset_11n_rx_seq_num(priv);
+}
+
+/*
+ * This function updates all rx_reorder_tbl's flags.
+ */
+void mwifiex_update_rxreor_flags(struct mwifiex_adapter *adapter, u8 flags)
+{
+       struct mwifiex_private *priv;
+       struct mwifiex_rx_reorder_tbl *tbl;
+       unsigned long lock_flags;
+       int i;
+
+       for (i = 0; i < adapter->priv_num; i++) {
+               priv = adapter->priv[i];
+               if (!priv)
+                       continue;
+
+               spin_lock_irqsave(&priv->rx_reorder_tbl_lock, lock_flags);
+               if (list_empty(&priv->rx_reorder_tbl_ptr)) {
+                       spin_unlock_irqrestore(&priv->rx_reorder_tbl_lock,
+                                              lock_flags);
+                       continue;
+               }
+
+               list_for_each_entry(tbl, &priv->rx_reorder_tbl_ptr, list)
+                       tbl->flags = flags;
+               spin_unlock_irqrestore(&priv->rx_reorder_tbl_lock, lock_flags);
+       }
+
+       return;
+}
+
+/* This function update all the rx_win_size based on coex flag
+ */
+static void mwifiex_update_ampdu_rxwinsize(struct mwifiex_adapter *adapter,
+                                          bool coex_flag)
+{
+       u8 i;
+       u32 rx_win_size;
+       struct mwifiex_private *priv;
+
+       dev_dbg(adapter->dev, "Update rxwinsize %d\n", coex_flag);
+
+       for (i = 0; i < adapter->priv_num; i++) {
+               if (!adapter->priv[i])
+                       continue;
+               priv = adapter->priv[i];
+               rx_win_size = priv->add_ba_param.rx_win_size;
+               if (coex_flag) {
+                       if (priv->bss_type == MWIFIEX_BSS_TYPE_STA)
+                               priv->add_ba_param.rx_win_size =
+                                       MWIFIEX_STA_COEX_AMPDU_DEF_RXWINSIZE;
+                       if (priv->bss_type == MWIFIEX_BSS_TYPE_P2P)
+                               priv->add_ba_param.rx_win_size =
+                                       MWIFIEX_STA_COEX_AMPDU_DEF_RXWINSIZE;
+                       if (priv->bss_type == MWIFIEX_BSS_TYPE_UAP)
+                               priv->add_ba_param.rx_win_size =
+                                       MWIFIEX_UAP_COEX_AMPDU_DEF_RXWINSIZE;
+               } else {
+                       if (priv->bss_type == MWIFIEX_BSS_TYPE_STA)
+                               priv->add_ba_param.rx_win_size =
+                                       MWIFIEX_STA_AMPDU_DEF_RXWINSIZE;
+                       if (priv->bss_type == MWIFIEX_BSS_TYPE_P2P)
+                               priv->add_ba_param.rx_win_size =
+                                       MWIFIEX_STA_AMPDU_DEF_RXWINSIZE;
+                       if (priv->bss_type == MWIFIEX_BSS_TYPE_UAP)
+                               priv->add_ba_param.rx_win_size =
+                                       MWIFIEX_UAP_AMPDU_DEF_RXWINSIZE;
+               }
+
+               if (adapter->coex_win_size && adapter->coex_rx_win_size)
+                       priv->add_ba_param.rx_win_size =
+                                       adapter->coex_rx_win_size;
+
+               if (rx_win_size != priv->add_ba_param.rx_win_size) {
+                       if (!priv->media_connected)
+                               continue;
+                       for (i = 0; i < MAX_NUM_TID; i++)
+                               mwifiex_11n_delba(priv, i);
+               }
+       }
+}
+
+/* This function check coex for RX BA
+ */
+void mwifiex_coex_ampdu_rxwinsize(struct mwifiex_adapter *adapter)
+{
+       u8 i;
+       struct mwifiex_private *priv;
+       u8 count = 0;
+
+       for (i = 0; i < adapter->priv_num; i++) {
+               if (adapter->priv[i]) {
+                       priv = adapter->priv[i];
+                       if (GET_BSS_ROLE(priv) == MWIFIEX_BSS_ROLE_STA) {
+                               if (priv->media_connected)
+                                       count++;
+                       }
+                       if (GET_BSS_ROLE(priv) == MWIFIEX_BSS_ROLE_UAP) {
+                               if (priv->bss_started)
+                                       count++;
+                       }
+               }
+               if (count >= MWIFIEX_BSS_COEX_COUNT)
+                       break;
+       }
+       if (count >= MWIFIEX_BSS_COEX_COUNT)
+               mwifiex_update_ampdu_rxwinsize(adapter, true);
+       else
+               mwifiex_update_ampdu_rxwinsize(adapter, false);
+}
diff --git a/drivers/net/wireless/marvell/mwifiex/11n_rxreorder.h b/drivers/net/wireless/marvell/mwifiex/11n_rxreorder.h
new file mode 100644 (file)
index 0000000..63ecea8
--- /dev/null
@@ -0,0 +1,85 @@
+/*
+ * Marvell Wireless LAN device driver: 802.11n RX Re-ordering
+ *
+ * Copyright (C) 2011-2014, Marvell International Ltd.
+ *
+ * This software file (the "File") is distributed by Marvell International
+ * Ltd. under the terms of the GNU General Public License Version 2, June 1991
+ * (the "License").  You may use, redistribute and/or modify this File in
+ * accordance with the terms and conditions of the License, a copy of which
+ * is available by writing to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the
+ * worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
+ *
+ * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
+ * ARE EXPRESSLY DISCLAIMED.  The License provides additional details about
+ * this warranty disclaimer.
+ */
+
+#ifndef _MWIFIEX_11N_RXREORDER_H_
+#define _MWIFIEX_11N_RXREORDER_H_
+
+#define MIN_FLUSH_TIMER_MS             50
+#define MIN_FLUSH_TIMER_15_MS          15
+#define MWIFIEX_BA_WIN_SIZE_32         32
+
+#define PKT_TYPE_BAR 0xE7
+#define MAX_TID_VALUE                  (2 << 11)
+#define TWOPOW11                       (2 << 10)
+
+#define BLOCKACKPARAM_TID_POS          2
+#define BLOCKACKPARAM_AMSDU_SUPP_MASK  0x1
+#define BLOCKACKPARAM_WINSIZE_POS      6
+#define DELBA_TID_POS                  12
+#define DELBA_INITIATOR_POS            11
+#define TYPE_DELBA_SENT                        1
+#define TYPE_DELBA_RECEIVE             2
+#define IMMEDIATE_BLOCK_ACK            0x2
+
+#define ADDBA_RSP_STATUS_ACCEPT 0
+
+#define MWIFIEX_DEF_11N_RX_SEQ_NUM     0xffff
+#define BA_SETUP_MAX_PACKET_THRESHOLD  16
+#define BA_SETUP_PACKET_OFFSET         16
+
+enum mwifiex_rxreor_flags {
+       RXREOR_FORCE_NO_DROP            = 1<<0,
+       RXREOR_INIT_WINDOW_SHIFT        = 1<<1,
+};
+
+static inline void mwifiex_reset_11n_rx_seq_num(struct mwifiex_private *priv)
+{
+       memset(priv->rx_seq, 0xff, sizeof(priv->rx_seq));
+}
+
+int mwifiex_11n_rx_reorder_pkt(struct mwifiex_private *,
+                              u16 seqNum,
+                              u16 tid, u8 *ta,
+                              u8 pkttype, void *payload);
+void mwifiex_del_ba_tbl(struct mwifiex_private *priv, int Tid,
+                       u8 *PeerMACAddr, u8 type, int initiator);
+void mwifiex_11n_ba_stream_timeout(struct mwifiex_private *priv,
+                                  struct host_cmd_ds_11n_batimeout *event);
+int mwifiex_ret_11n_addba_resp(struct mwifiex_private *priv,
+                              struct host_cmd_ds_command
+                              *resp);
+int mwifiex_cmd_11n_delba(struct host_cmd_ds_command *cmd,
+                         void *data_buf);
+int mwifiex_cmd_11n_addba_rsp_gen(struct mwifiex_private *priv,
+                                 struct host_cmd_ds_command *cmd,
+                                 struct host_cmd_ds_11n_addba_req
+                                 *cmd_addba_req);
+int mwifiex_cmd_11n_addba_req(struct host_cmd_ds_command *cmd,
+                             void *data_buf);
+void mwifiex_11n_cleanup_reorder_tbl(struct mwifiex_private *priv);
+struct mwifiex_rx_reorder_tbl *mwifiex_11n_get_rxreorder_tbl(struct
+                                                          mwifiex_private
+                                                          *priv, int tid,
+                                                          u8 *ta);
+struct mwifiex_rx_reorder_tbl *
+mwifiex_11n_get_rx_reorder_tbl(struct mwifiex_private *priv, int tid, u8 *ta);
+void mwifiex_11n_del_rx_reorder_tbl_by_ta(struct mwifiex_private *priv, u8 *ta);
+void mwifiex_update_rxreor_flags(struct mwifiex_adapter *adapter, u8 flags);
+
+#endif /* _MWIFIEX_11N_RXREORDER_H_ */
diff --git a/drivers/net/wireless/marvell/mwifiex/Kconfig b/drivers/net/wireless/marvell/mwifiex/Kconfig
new file mode 100644 (file)
index 0000000..279167d
--- /dev/null
@@ -0,0 +1,44 @@
+config MWIFIEX
+       tristate "Marvell WiFi-Ex Driver"
+       depends on CFG80211
+       ---help---
+         This adds support for wireless adapters based on Marvell
+         802.11n/ac chipsets.
+
+         If you choose to build it as a module, it will be called
+         mwifiex.
+
+config MWIFIEX_SDIO
+       tristate "Marvell WiFi-Ex Driver for SD8786/SD8787/SD8797/SD8887/SD8897/SD8997"
+       depends on MWIFIEX && MMC
+       select FW_LOADER
+       select WANT_DEV_COREDUMP
+       ---help---
+         This adds support for wireless adapters based on Marvell
+         8786/8787/8797/8887/8897/8997 chipsets with SDIO interface.
+
+         If you choose to build it as a module, it will be called
+         mwifiex_sdio.
+
+config MWIFIEX_PCIE
+       tristate "Marvell WiFi-Ex Driver for PCIE 8766/8897/8997"
+       depends on MWIFIEX && PCI
+       select FW_LOADER
+       select WANT_DEV_COREDUMP
+       ---help---
+         This adds support for wireless adapters based on Marvell
+         8766/8897/8997 chipsets with PCIe interface.
+
+         If you choose to build it as a module, it will be called
+         mwifiex_pcie.
+
+config MWIFIEX_USB
+       tristate "Marvell WiFi-Ex Driver for USB8766/8797/8997"
+       depends on MWIFIEX && USB
+       select FW_LOADER
+       ---help---
+         This adds support for wireless adapters based on Marvell
+         8797/8997 chipset with USB interface.
+
+         If you choose to build it as a module, it will be called
+         mwifiex_usb.
diff --git a/drivers/net/wireless/marvell/mwifiex/Makefile b/drivers/net/wireless/marvell/mwifiex/Makefile
new file mode 100644 (file)
index 0000000..fdfd9bf
--- /dev/null
@@ -0,0 +1,57 @@
+#
+# Copyright (C) 2011-2014, Marvell International Ltd.
+#
+# This software file (the "File") is distributed by Marvell International
+# Ltd. under the terms of the GNU General Public License Version 2, June 1991
+# (the "License").  You may use, redistribute and/or modify this File in
+# accordance with the terms and conditions of the License, a copy of which
+# is available by writing to the Free Software Foundation, Inc.,
+# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the
+# worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
+#
+# THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
+# IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
+# ARE EXPRESSLY DISCLAIMED.  The License provides additional details about
+# this warranty disclaimer.
+
+
+mwifiex-y += main.o
+mwifiex-y += init.o
+mwifiex-y += cfp.o
+mwifiex-y += cmdevt.o
+mwifiex-y += util.o
+mwifiex-y += txrx.o
+mwifiex-y += wmm.o
+mwifiex-y += 11n.o
+mwifiex-y += 11ac.o
+mwifiex-y += 11n_aggr.o
+mwifiex-y += 11n_rxreorder.o
+mwifiex-y += scan.o
+mwifiex-y += join.o
+mwifiex-y += sta_ioctl.o
+mwifiex-y += sta_cmd.o
+mwifiex-y += uap_cmd.o
+mwifiex-y += ie.o
+mwifiex-y += sta_cmdresp.o
+mwifiex-y += sta_event.o
+mwifiex-y += uap_event.o
+mwifiex-y += sta_tx.o
+mwifiex-y += sta_rx.o
+mwifiex-y += uap_txrx.o
+mwifiex-y += cfg80211.o
+mwifiex-y += ethtool.o
+mwifiex-y += 11h.o
+mwifiex-y += tdls.o
+mwifiex-$(CONFIG_DEBUG_FS) += debugfs.o
+obj-$(CONFIG_MWIFIEX) += mwifiex.o
+
+mwifiex_sdio-y += sdio.o
+obj-$(CONFIG_MWIFIEX_SDIO) += mwifiex_sdio.o
+
+mwifiex_pcie-y += pcie.o
+obj-$(CONFIG_MWIFIEX_PCIE) += mwifiex_pcie.o
+
+mwifiex_usb-y += usb.o
+obj-$(CONFIG_MWIFIEX_USB) += mwifiex_usb.o
+
+ccflags-y += -D__CHECK_ENDIAN
diff --git a/drivers/net/wireless/marvell/mwifiex/README b/drivers/net/wireless/marvell/mwifiex/README
new file mode 100644 (file)
index 0000000..2f0f9b5
--- /dev/null
@@ -0,0 +1,240 @@
+# Copyright (C) 2011-2014, Marvell International Ltd.
+#
+# This software file (the "File") is distributed by Marvell International
+# Ltd. under the terms of the GNU General Public License Version 2, June 1991
+# (the "License").  You may use, redistribute and/or modify this File in
+# accordance with the terms and conditions of the License, a copy of which
+# is available by writing to the Free Software Foundation, Inc.,
+# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the
+# worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
+#
+# THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
+# IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
+# ARE EXPRESSLY DISCLAIMED.  The License provides additional details about
+# this warranty disclaimer.
+
+
+===============================================================================
+                       U S E R  M A N U A L
+
+1) FOR DRIVER INSTALL
+
+       a) Copy sd8787.bin to /lib/firmware/mrvl/ directory,
+          create the directory if it doesn't exist.
+       b) Install WLAN driver,
+               insmod mwifiex.ko
+       c) Uninstall WLAN driver,
+               ifconfig mlanX down
+               rmmod mwifiex
+
+
+2) FOR DRIVER CONFIGURATION AND INFO
+       The configurations can be done either using the 'iw' user space
+       utility or debugfs.
+
+       a) 'iw' utility commands
+
+       Following are some useful iw commands:-
+
+iw dev mlan0 scan
+
+       This command will trigger a scan.
+       The command will then display the scan table entries
+
+iw dev mlan0 connect -w <SSID> [<freq in MHz>] [<bssid>] [key 0:abcde d:1123456789a]
+       The above command can be used to connect to an AP with a particular SSID.
+       Ap's operating frequency can be specified or even the bssid. If the AP is using
+       WEP encryption, wep keys can be specified in the command.
+       Note: Every time before connecting to an AP scan command (iw dev mlan0 scan) should be used by user.
+
+iw dev mlan0 disconnect
+       This command will be used to disconnect from an AP.
+
+
+iw dev mlan0 ibss join <SSID> <freq in MHz> [fixed-freq] [fixed-bssid] [key 0:abcde]
+       The command will be used to join or create an ibss. Optionally, operating frequency,
+       bssid and the security related parameters can be specified while joining/creating
+       and ibss.
+
+iw dev mlan0 ibss leave
+       The command will be used to leave an ibss network.
+
+iw dev mlan0 link
+       The command will be used to get the connection status. The command will return parameters
+       such as SSID, operating frequency, rx/tx packets, signal strength, tx bitrate.
+
+       Apart from the iw utility all standard configurations using the 'iwconfig' utility are also supported.
+
+       b) Debugfs interface
+
+       The debugfs interface can be used for configurations and for getting
+       some useful information from the driver.
+       The section below explains the configurations that can be
+       done.
+
+       Mount debugfs to /debugfs mount point:
+
+               mkdir /debugfs
+               mount -t debugfs debugfs /debugfs
+
+       The information is provided in /debugfs/mwifiex/mlanX/:
+
+iw reg set <country code>
+       The command will be used to change the regulatory domain.
+
+iw reg get
+       The command will be used to get current regulatory domain.
+
+info
+       This command is used to get driver info.
+
+       Usage:
+               cat info
+
+       driver_name = "mwifiex"
+       driver_version = <driver_name, driver_version, (firmware_version)>
+       interface_name = "mlanX"
+       bss_mode = "Ad-hoc" | "Managed" | "Auto" | "Unknown"
+       media_state = "Disconnected" | "Connected"
+       mac_address = <6-byte adapter MAC address>
+       multicase_count = <multicast address count>
+       essid = <current SSID>
+       bssid = <current BSSID>
+       channel = <current channel>
+       region_code = <current region code>
+       multicasr_address[n] = <multicast address>
+       num_tx_bytes = <number of bytes sent to device>
+       num_rx_bytes = <number of bytes received from device and sent to kernel>
+       num_tx_pkts = <number of packets sent to device>
+       num_rx_pkts = <number of packets received from device and sent to kernel>
+       num_tx_pkts_dropped = <number of Tx packets dropped by driver>
+       num_rx_pkts_dropped = <number of Rx packets dropped by driver>
+       num_tx_pkts_err = <number of Tx packets failed to send to device>
+       num_rx_pkts_err = <number of Rx packets failed to receive from device>
+       carrier "on" | "off"
+       tx queue "stopped" | "started"
+
+       The following debug info are provided in /debugfs/mwifiex/mlanX/debug:
+
+       int_counter = <interrupt count, cleared when interrupt handled>
+       wmm_ac_vo = <number of packets sent to device from WMM AcVo queue>
+       wmm_ac_vi = <number of packets sent to device from WMM AcVi queue>
+       wmm_ac_be = <number of packets sent to device from WMM AcBE queue>
+       wmm_ac_bk = <number of packets sent to device from WMM AcBK queue>
+       tx_buf_size = <current Tx buffer size>
+       curr_tx_buf_size = <current Tx buffer size>
+       ps_mode = <0/1, CAM mode/PS mode>
+       ps_state = <0/1/2/3, full power state/awake state/pre-sleep state/sleep state>
+       is_deep_sleep = <0/1, not deep sleep state/deep sleep state>
+       wakeup_dev_req = <0/1, wakeup device not required/required>
+       wakeup_tries = <wakeup device count, cleared when device awake>
+       hs_configured = <0/1, host sleep not configured/configured>
+       hs_activated = <0/1, extended host sleep not activated/activated>
+       num_tx_timeout = <number of Tx timeout>
+       is_cmd_timedout = <0/1 command timeout not occurred/occurred>
+       timeout_cmd_id = <command id of the last timeout command>
+       timeout_cmd_act = <command action of the last timeout command>
+       last_cmd_id = <command id of the last several commands sent to device>
+       last_cmd_act = <command action of the last several commands sent to device>
+       last_cmd_index = <0 based last command index>
+       last_cmd_resp_id = <command id of the last several command responses received from device>
+       last_cmd_resp_index = <0 based last command response index>
+       last_event = <event id of the last several events received from device>
+       last_event_index = <0 based last event index>
+       num_cmd_h2c_fail = <number of commands failed to send to device>
+       num_cmd_sleep_cfm_fail = <number of sleep confirm failed to send to device>
+       num_tx_h2c_fail = <number of data packets failed to send to device>
+       num_evt_deauth = <number of deauthenticated events received from device>
+       num_evt_disassoc = <number of disassociated events received from device>
+       num_evt_link_lost = <number of link lost events received from device>
+       num_cmd_deauth = <number of deauthenticate commands sent to device>
+       num_cmd_assoc_ok = <number of associate commands with success return>
+       num_cmd_assoc_fail = <number of associate commands with failure return>
+       cmd_sent = <0/1, send command resources available/sending command to device>
+       data_sent = <0/1, send data resources available/sending data to device>
+       mp_rd_bitmap = <SDIO multi-port read bitmap>
+       mp_wr_bitmap = <SDIO multi-port write bitmap>
+       cmd_resp_received = <0/1, no cmd response to process/response received and yet to process>
+       event_received = <0/1, no event to process/event received and yet to process>
+       cmd_pending = <number of cmd pending>
+       tx_pending = <number of Tx packet pending>
+       rx_pending = <number of Rx packet pending>
+
+
+3) FOR DRIVER CONFIGURATION
+
+regrdwr
+       This command is used to read/write the adapter register.
+
+       Usage:
+               echo " <type> <offset> [value]" > regrdwr
+               cat regrdwr
+
+       where the parameters are,
+               <type>:     1:MAC/SOC, 2:BBP, 3:RF, 4:PMIC, 5:CAU
+               <offset>:   offset of register
+               [value]:    value to be written
+
+       Examples:
+               echo "1 0xa060" > regrdwr           : Read the MAC register
+               echo "1 0xa060 0x12" > regrdwr      : Write the MAC register
+               echo "1 0xa794 0x80000000" > regrdwr
+                                                   : Write 0x80000000 to MAC register
+rdeeprom
+       This command is used to read the EEPROM contents of the card.
+
+       Usage:
+               echo "<offset> <length>" > rdeeprom
+               cat rdeeprom
+
+       where the parameters are,
+               <offset>:   multiples of 4
+               <length>:   4-20, multiples of 4
+
+       Example:
+               echo "0 20" > rdeeprom      : Read 20 bytes of EEPROM data from offset 0
+
+hscfg
+       This command is used to debug/simulate host sleep feature using
+       different configuration parameters.
+
+       Usage:
+               echo "<condition> [GPIO# [gap]]]" > hscfg
+               cat hscfg
+
+       where the parameters are,
+               <condition>: bit 0 = 1   -- broadcast data
+                            bit 1 = 1   -- unicast data
+                            bit 2 = 1   -- mac event
+                            bit 3 = 1   -- multicast data
+               [GPIO#]: pin number of GPIO used to wakeup the host.
+                        GPIO pin# (e.g. 0-7) or 0xff (interface, e.g. SDIO
+                        will be used instead).
+               [gap]:   the gap in milliseconds between wakeup signal and
+                        wakeup event or 0xff for special setting (host
+                        acknowledge required) when GPIO is used to wakeup host.
+
+       Examples:
+               echo "-1" > hscfg        : Cancel host sleep mode
+               echo "3" > hscfg         : Broadcast and unicast data;
+                                          Use GPIO and gap set previously
+               echo "2 3" > hscfg       : Unicast data and GPIO 3;
+                                          Use gap set previously
+               echo "2 1 160" > hscfg   : Unicast data, GPIO 1 and gap 160 ms
+               echo "2 1 0xff" > hscfg  : Unicast data, GPIO 1; Wait for host
+                                          to ack before sending wakeup event
+
+getlog
+        This command is used to get the statistics available in the station.
+       Usage:
+
+       cat getlog
+
+device_dump
+       This command is used to dump driver information and firmware memory
+       segments.
+       Usage:
+
+       cat fw_dump
+
+===============================================================================
diff --git a/drivers/net/wireless/marvell/mwifiex/cfg80211.c b/drivers/net/wireless/marvell/mwifiex/cfg80211.c
new file mode 100644 (file)
index 0000000..4073116
--- /dev/null
@@ -0,0 +1,3887 @@
+/*
+ * Marvell Wireless LAN device driver: CFG80211
+ *
+ * Copyright (C) 2011-2014, Marvell International Ltd.
+ *
+ * This software file (the "File") is distributed by Marvell International
+ * Ltd. under the terms of the GNU General Public License Version 2, June 1991
+ * (the "License").  You may use, redistribute and/or modify this File in
+ * accordance with the terms and conditions of the License, a copy of which
+ * is available by writing to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the
+ * worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
+ *
+ * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
+ * ARE EXPRESSLY DISCLAIMED.  The License provides additional details about
+ * this warranty disclaimer.
+ */
+
+#include "cfg80211.h"
+#include "main.h"
+#include "11n.h"
+
+static char *reg_alpha2;
+module_param(reg_alpha2, charp, 0);
+
+static const struct ieee80211_iface_limit mwifiex_ap_sta_limits[] = {
+       {
+               .max = 2, .types = BIT(NL80211_IFTYPE_STATION) |
+                                  BIT(NL80211_IFTYPE_P2P_GO) |
+                                  BIT(NL80211_IFTYPE_P2P_CLIENT),
+       },
+       {
+               .max = 1, .types = BIT(NL80211_IFTYPE_AP),
+       },
+};
+
+static const struct ieee80211_iface_combination
+mwifiex_iface_comb_ap_sta = {
+       .limits = mwifiex_ap_sta_limits,
+       .num_different_channels = 1,
+       .n_limits = ARRAY_SIZE(mwifiex_ap_sta_limits),
+       .max_interfaces = MWIFIEX_MAX_BSS_NUM,
+       .beacon_int_infra_match = true,
+       .radar_detect_widths =  BIT(NL80211_CHAN_WIDTH_20_NOHT) |
+                               BIT(NL80211_CHAN_WIDTH_20) |
+                               BIT(NL80211_CHAN_WIDTH_40),
+};
+
+static const struct ieee80211_iface_combination
+mwifiex_iface_comb_ap_sta_vht = {
+       .limits = mwifiex_ap_sta_limits,
+       .num_different_channels = 1,
+       .n_limits = ARRAY_SIZE(mwifiex_ap_sta_limits),
+       .max_interfaces = MWIFIEX_MAX_BSS_NUM,
+       .beacon_int_infra_match = true,
+       .radar_detect_widths =  BIT(NL80211_CHAN_WIDTH_20_NOHT) |
+                               BIT(NL80211_CHAN_WIDTH_20) |
+                               BIT(NL80211_CHAN_WIDTH_40) |
+                               BIT(NL80211_CHAN_WIDTH_80),
+};
+
+static const struct
+ieee80211_iface_combination mwifiex_iface_comb_ap_sta_drcs = {
+       .limits = mwifiex_ap_sta_limits,
+       .num_different_channels = 2,
+       .n_limits = ARRAY_SIZE(mwifiex_ap_sta_limits),
+       .max_interfaces = MWIFIEX_MAX_BSS_NUM,
+       .beacon_int_infra_match = true,
+};
+
+/*
+ * This function maps the nl802.11 channel type into driver channel type.
+ *
+ * The mapping is as follows -
+ *      NL80211_CHAN_NO_HT     -> IEEE80211_HT_PARAM_CHA_SEC_NONE
+ *      NL80211_CHAN_HT20      -> IEEE80211_HT_PARAM_CHA_SEC_NONE
+ *      NL80211_CHAN_HT40PLUS  -> IEEE80211_HT_PARAM_CHA_SEC_ABOVE
+ *      NL80211_CHAN_HT40MINUS -> IEEE80211_HT_PARAM_CHA_SEC_BELOW
+ *      Others                 -> IEEE80211_HT_PARAM_CHA_SEC_NONE
+ */
+u8 mwifiex_chan_type_to_sec_chan_offset(enum nl80211_channel_type chan_type)
+{
+       switch (chan_type) {
+       case NL80211_CHAN_NO_HT:
+       case NL80211_CHAN_HT20:
+               return IEEE80211_HT_PARAM_CHA_SEC_NONE;
+       case NL80211_CHAN_HT40PLUS:
+               return IEEE80211_HT_PARAM_CHA_SEC_ABOVE;
+       case NL80211_CHAN_HT40MINUS:
+               return IEEE80211_HT_PARAM_CHA_SEC_BELOW;
+       default:
+               return IEEE80211_HT_PARAM_CHA_SEC_NONE;
+       }
+}
+
+/* This function maps IEEE HT secondary channel type to NL80211 channel type
+ */
+u8 mwifiex_sec_chan_offset_to_chan_type(u8 second_chan_offset)
+{
+       switch (second_chan_offset) {
+       case IEEE80211_HT_PARAM_CHA_SEC_NONE:
+               return NL80211_CHAN_HT20;
+       case IEEE80211_HT_PARAM_CHA_SEC_ABOVE:
+               return NL80211_CHAN_HT40PLUS;
+       case IEEE80211_HT_PARAM_CHA_SEC_BELOW:
+               return NL80211_CHAN_HT40MINUS;
+       default:
+               return NL80211_CHAN_HT20;
+       }
+}
+
+/*
+ * This function checks whether WEP is set.
+ */
+static int
+mwifiex_is_alg_wep(u32 cipher)
+{
+       switch (cipher) {
+       case WLAN_CIPHER_SUITE_WEP40:
+       case WLAN_CIPHER_SUITE_WEP104:
+               return 1;
+       default:
+               break;
+       }
+
+       return 0;
+}
+
+/*
+ * This function retrieves the private structure from kernel wiphy structure.
+ */
+static void *mwifiex_cfg80211_get_adapter(struct wiphy *wiphy)
+{
+       return (void *) (*(unsigned long *) wiphy_priv(wiphy));
+}
+
+/*
+ * CFG802.11 operation handler to delete a network key.
+ */
+static int
+mwifiex_cfg80211_del_key(struct wiphy *wiphy, struct net_device *netdev,
+                        u8 key_index, bool pairwise, const u8 *mac_addr)
+{
+       struct mwifiex_private *priv = mwifiex_netdev_get_priv(netdev);
+       const u8 bc_mac[] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
+       const u8 *peer_mac = pairwise ? mac_addr : bc_mac;
+
+       if (mwifiex_set_encode(priv, NULL, NULL, 0, key_index, peer_mac, 1)) {
+               mwifiex_dbg(priv->adapter, ERROR, "deleting the crypto keys\n");
+               return -EFAULT;
+       }
+
+       mwifiex_dbg(priv->adapter, INFO, "info: crypto keys deleted\n");
+       return 0;
+}
+
+/*
+ * This function forms an skb for management frame.
+ */
+static int
+mwifiex_form_mgmt_frame(struct sk_buff *skb, const u8 *buf, size_t len)
+{
+       u8 addr[ETH_ALEN] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF};
+       u16 pkt_len;
+       u32 tx_control = 0, pkt_type = PKT_TYPE_MGMT;
+
+       pkt_len = len + ETH_ALEN;
+
+       skb_reserve(skb, MWIFIEX_MIN_DATA_HEADER_LEN +
+                   MWIFIEX_MGMT_FRAME_HEADER_SIZE + sizeof(pkt_len));
+       memcpy(skb_push(skb, sizeof(pkt_len)), &pkt_len, sizeof(pkt_len));
+
+       memcpy(skb_push(skb, sizeof(tx_control)),
+              &tx_control, sizeof(tx_control));
+
+       memcpy(skb_push(skb, sizeof(pkt_type)), &pkt_type, sizeof(pkt_type));
+
+       /* Add packet data and address4 */
+       memcpy(skb_put(skb, sizeof(struct ieee80211_hdr_3addr)), buf,
+              sizeof(struct ieee80211_hdr_3addr));
+       memcpy(skb_put(skb, ETH_ALEN), addr, ETH_ALEN);
+       memcpy(skb_put(skb, len - sizeof(struct ieee80211_hdr_3addr)),
+              buf + sizeof(struct ieee80211_hdr_3addr),
+              len - sizeof(struct ieee80211_hdr_3addr));
+
+       skb->priority = LOW_PRIO_TID;
+       __net_timestamp(skb);
+
+       return 0;
+}
+
+/*
+ * CFG802.11 operation handler to transmit a management frame.
+ */
+static int
+mwifiex_cfg80211_mgmt_tx(struct wiphy *wiphy, struct wireless_dev *wdev,
+                        struct cfg80211_mgmt_tx_params *params, u64 *cookie)
+{
+       const u8 *buf = params->buf;
+       size_t len = params->len;
+       struct sk_buff *skb;
+       u16 pkt_len;
+       const struct ieee80211_mgmt *mgmt;
+       struct mwifiex_txinfo *tx_info;
+       struct mwifiex_private *priv = mwifiex_netdev_get_priv(wdev->netdev);
+
+       if (!buf || !len) {
+               mwifiex_dbg(priv->adapter, ERROR, "invalid buffer and length\n");
+               return -EFAULT;
+       }
+
+       mgmt = (const struct ieee80211_mgmt *)buf;
+       if (GET_BSS_ROLE(priv) != MWIFIEX_BSS_ROLE_STA &&
+           ieee80211_is_probe_resp(mgmt->frame_control)) {
+               /* Since we support offload probe resp, we need to skip probe
+                * resp in AP or GO mode */
+               mwifiex_dbg(priv->adapter, INFO,
+                           "info: skip to send probe resp in AP or GO mode\n");
+               return 0;
+       }
+
+       pkt_len = len + ETH_ALEN;
+       skb = dev_alloc_skb(MWIFIEX_MIN_DATA_HEADER_LEN +
+                           MWIFIEX_MGMT_FRAME_HEADER_SIZE +
+                           pkt_len + sizeof(pkt_len));
+
+       if (!skb) {
+               mwifiex_dbg(priv->adapter, ERROR,
+                           "allocate skb failed for management frame\n");
+               return -ENOMEM;
+       }
+
+       tx_info = MWIFIEX_SKB_TXCB(skb);
+       memset(tx_info, 0, sizeof(*tx_info));
+       tx_info->bss_num = priv->bss_num;
+       tx_info->bss_type = priv->bss_type;
+       tx_info->pkt_len = pkt_len;
+
+       mwifiex_form_mgmt_frame(skb, buf, len);
+       *cookie = prandom_u32() | 1;
+
+       if (ieee80211_is_action(mgmt->frame_control))
+               skb = mwifiex_clone_skb_for_tx_status(priv,
+                                                     skb,
+                               MWIFIEX_BUF_FLAG_ACTION_TX_STATUS, cookie);
+       else
+               cfg80211_mgmt_tx_status(wdev, *cookie, buf, len, true,
+                                       GFP_ATOMIC);
+
+       mwifiex_queue_tx_pkt(priv, skb);
+
+       mwifiex_dbg(priv->adapter, INFO, "info: management frame transmitted\n");
+       return 0;
+}
+
+/*
+ * CFG802.11 operation handler to register a mgmt frame.
+ */
+static void
+mwifiex_cfg80211_mgmt_frame_register(struct wiphy *wiphy,
+                                    struct wireless_dev *wdev,
+                                    u16 frame_type, bool reg)
+{
+       struct mwifiex_private *priv = mwifiex_netdev_get_priv(wdev->netdev);
+       u32 mask;
+
+       if (reg)
+               mask = priv->mgmt_frame_mask | BIT(frame_type >> 4);
+       else
+               mask = priv->mgmt_frame_mask & ~BIT(frame_type >> 4);
+
+       if (mask != priv->mgmt_frame_mask) {
+               priv->mgmt_frame_mask = mask;
+               mwifiex_send_cmd(priv, HostCmd_CMD_MGMT_FRAME_REG,
+                                HostCmd_ACT_GEN_SET, 0,
+                                &priv->mgmt_frame_mask, false);
+               mwifiex_dbg(priv->adapter, INFO, "info: mgmt frame registered\n");
+       }
+}
+
+/*
+ * CFG802.11 operation handler to remain on channel.
+ */
+static int
+mwifiex_cfg80211_remain_on_channel(struct wiphy *wiphy,
+                                  struct wireless_dev *wdev,
+                                  struct ieee80211_channel *chan,
+                                  unsigned int duration, u64 *cookie)
+{
+       struct mwifiex_private *priv = mwifiex_netdev_get_priv(wdev->netdev);
+       int ret;
+
+       if (!chan || !cookie) {
+               mwifiex_dbg(priv->adapter, ERROR, "Invalid parameter for ROC\n");
+               return -EINVAL;
+       }
+
+       if (priv->roc_cfg.cookie) {
+               mwifiex_dbg(priv->adapter, INFO,
+                           "info: ongoing ROC, cookie = 0x%llx\n",
+                           priv->roc_cfg.cookie);
+               return -EBUSY;
+       }
+
+       ret = mwifiex_remain_on_chan_cfg(priv, HostCmd_ACT_GEN_SET, chan,
+                                        duration);
+
+       if (!ret) {
+               *cookie = prandom_u32() | 1;
+               priv->roc_cfg.cookie = *cookie;
+               priv->roc_cfg.chan = *chan;
+
+               cfg80211_ready_on_channel(wdev, *cookie, chan,
+                                         duration, GFP_ATOMIC);
+
+               mwifiex_dbg(priv->adapter, INFO,
+                           "info: ROC, cookie = 0x%llx\n", *cookie);
+       }
+
+       return ret;
+}
+
+/*
+ * CFG802.11 operation handler to cancel remain on channel.
+ */
+static int
+mwifiex_cfg80211_cancel_remain_on_channel(struct wiphy *wiphy,
+                                         struct wireless_dev *wdev, u64 cookie)
+{
+       struct mwifiex_private *priv = mwifiex_netdev_get_priv(wdev->netdev);
+       int ret;
+
+       if (cookie != priv->roc_cfg.cookie)
+               return -ENOENT;
+
+       ret = mwifiex_remain_on_chan_cfg(priv, HostCmd_ACT_GEN_REMOVE,
+                                        &priv->roc_cfg.chan, 0);
+
+       if (!ret) {
+               cfg80211_remain_on_channel_expired(wdev, cookie,
+                                                  &priv->roc_cfg.chan,
+                                                  GFP_ATOMIC);
+
+               memset(&priv->roc_cfg, 0, sizeof(struct mwifiex_roc_cfg));
+
+               mwifiex_dbg(priv->adapter, INFO,
+                           "info: cancel ROC, cookie = 0x%llx\n", cookie);
+       }
+
+       return ret;
+}
+
+/*
+ * CFG802.11 operation handler to set Tx power.
+ */
+static int
+mwifiex_cfg80211_set_tx_power(struct wiphy *wiphy,
+                             struct wireless_dev *wdev,
+                             enum nl80211_tx_power_setting type,
+                             int mbm)
+{
+       struct mwifiex_adapter *adapter = mwifiex_cfg80211_get_adapter(wiphy);
+       struct mwifiex_private *priv;
+       struct mwifiex_power_cfg power_cfg;
+       int dbm = MBM_TO_DBM(mbm);
+
+       if (type == NL80211_TX_POWER_FIXED) {
+               power_cfg.is_power_auto = 0;
+               power_cfg.power_level = dbm;
+       } else {
+               power_cfg.is_power_auto = 1;
+       }
+
+       priv = mwifiex_get_priv(adapter, MWIFIEX_BSS_ROLE_ANY);
+
+       return mwifiex_set_tx_power(priv, &power_cfg);
+}
+
+/*
+ * CFG802.11 operation handler to set Power Save option.
+ *
+ * The timeout value, if provided, is currently ignored.
+ */
+static int
+mwifiex_cfg80211_set_power_mgmt(struct wiphy *wiphy,
+                               struct net_device *dev,
+                               bool enabled, int timeout)
+{
+       struct mwifiex_private *priv = mwifiex_netdev_get_priv(dev);
+       u32 ps_mode;
+
+       if (timeout)
+               mwifiex_dbg(priv->adapter, INFO,
+                           "info: ignore timeout value for IEEE Power Save\n");
+
+       ps_mode = enabled;
+
+       return mwifiex_drv_set_power(priv, &ps_mode);
+}
+
+/*
+ * CFG802.11 operation handler to set the default network key.
+ */
+static int
+mwifiex_cfg80211_set_default_key(struct wiphy *wiphy, struct net_device *netdev,
+                                u8 key_index, bool unicast,
+                                bool multicast)
+{
+       struct mwifiex_private *priv = mwifiex_netdev_get_priv(netdev);
+
+       /* Return if WEP key not configured */
+       if (!priv->sec_info.wep_enabled)
+               return 0;
+
+       if (priv->bss_type == MWIFIEX_BSS_TYPE_UAP) {
+               priv->wep_key_curr_index = key_index;
+       } else if (mwifiex_set_encode(priv, NULL, NULL, 0, key_index,
+                                     NULL, 0)) {
+               mwifiex_dbg(priv->adapter, ERROR, "set default Tx key index\n");
+               return -EFAULT;
+       }
+
+       return 0;
+}
+
+/*
+ * CFG802.11 operation handler to add a network key.
+ */
+static int
+mwifiex_cfg80211_add_key(struct wiphy *wiphy, struct net_device *netdev,
+                        u8 key_index, bool pairwise, const u8 *mac_addr,
+                        struct key_params *params)
+{
+       struct mwifiex_private *priv = mwifiex_netdev_get_priv(netdev);
+       struct mwifiex_wep_key *wep_key;
+       const u8 bc_mac[] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
+       const u8 *peer_mac = pairwise ? mac_addr : bc_mac;
+
+       if (GET_BSS_ROLE(priv) == MWIFIEX_BSS_ROLE_UAP &&
+           (params->cipher == WLAN_CIPHER_SUITE_WEP40 ||
+            params->cipher == WLAN_CIPHER_SUITE_WEP104)) {
+               if (params->key && params->key_len) {
+                       wep_key = &priv->wep_key[key_index];
+                       memset(wep_key, 0, sizeof(struct mwifiex_wep_key));
+                       memcpy(wep_key->key_material, params->key,
+                              params->key_len);
+                       wep_key->key_index = key_index;
+                       wep_key->key_length = params->key_len;
+                       priv->sec_info.wep_enabled = 1;
+               }
+               return 0;
+       }
+
+       if (mwifiex_set_encode(priv, params, params->key, params->key_len,
+                              key_index, peer_mac, 0)) {
+               mwifiex_dbg(priv->adapter, ERROR, "crypto keys added\n");
+               return -EFAULT;
+       }
+
+       return 0;
+}
+
+/*
+ * This function sends domain information to the firmware.
+ *
+ * The following information are passed to the firmware -
+ *      - Country codes
+ *      - Sub bands (first channel, number of channels, maximum Tx power)
+ */
+int mwifiex_send_domain_info_cmd_fw(struct wiphy *wiphy)
+{
+       u8 no_of_triplet = 0;
+       struct ieee80211_country_ie_triplet *t;
+       u8 no_of_parsed_chan = 0;
+       u8 first_chan = 0, next_chan = 0, max_pwr = 0;
+       u8 i, flag = 0;
+       enum ieee80211_band band;
+       struct ieee80211_supported_band *sband;
+       struct ieee80211_channel *ch;
+       struct mwifiex_adapter *adapter = mwifiex_cfg80211_get_adapter(wiphy);
+       struct mwifiex_private *priv;
+       struct mwifiex_802_11d_domain_reg *domain_info = &adapter->domain_reg;
+
+       /* Set country code */
+       domain_info->country_code[0] = adapter->country_code[0];
+       domain_info->country_code[1] = adapter->country_code[1];
+       domain_info->country_code[2] = ' ';
+
+       band = mwifiex_band_to_radio_type(adapter->config_bands);
+       if (!wiphy->bands[band]) {
+               mwifiex_dbg(adapter, ERROR,
+                           "11D: setting domain info in FW\n");
+               return -1;
+       }
+
+       sband = wiphy->bands[band];
+
+       for (i = 0; i < sband->n_channels ; i++) {
+               ch = &sband->channels[i];
+               if (ch->flags & IEEE80211_CHAN_DISABLED)
+                       continue;
+
+               if (!flag) {
+                       flag = 1;
+                       first_chan = (u32) ch->hw_value;
+                       next_chan = first_chan;
+                       max_pwr = ch->max_power;
+                       no_of_parsed_chan = 1;
+                       continue;
+               }
+
+               if (ch->hw_value == next_chan + 1 &&
+                   ch->max_power == max_pwr) {
+                       next_chan++;
+                       no_of_parsed_chan++;
+               } else {
+                       t = &domain_info->triplet[no_of_triplet];
+                       t->chans.first_channel = first_chan;
+                       t->chans.num_channels = no_of_parsed_chan;
+                       t->chans.max_power = max_pwr;
+                       no_of_triplet++;
+                       first_chan = (u32) ch->hw_value;
+                       next_chan = first_chan;
+                       max_pwr = ch->max_power;
+                       no_of_parsed_chan = 1;
+               }
+       }
+
+       if (flag) {
+               t = &domain_info->triplet[no_of_triplet];
+               t->chans.first_channel = first_chan;
+               t->chans.num_channels = no_of_parsed_chan;
+               t->chans.max_power = max_pwr;
+               no_of_triplet++;
+       }
+
+       domain_info->no_of_triplet = no_of_triplet;
+
+       priv = mwifiex_get_priv(adapter, MWIFIEX_BSS_ROLE_ANY);
+
+       if (mwifiex_send_cmd(priv, HostCmd_CMD_802_11D_DOMAIN_INFO,
+                            HostCmd_ACT_GEN_SET, 0, NULL, false)) {
+               mwifiex_dbg(adapter, INFO,
+                           "11D: setting domain info in FW\n");
+               return -1;
+       }
+
+       return 0;
+}
+
+/*
+ * CFG802.11 regulatory domain callback function.
+ *
+ * This function is called when the regulatory domain is changed due to the
+ * following reasons -
+ *      - Set by driver
+ *      - Set by system core
+ *      - Set by user
+ *      - Set bt Country IE
+ */
+static void mwifiex_reg_notifier(struct wiphy *wiphy,
+                                struct regulatory_request *request)
+{
+       struct mwifiex_adapter *adapter = mwifiex_cfg80211_get_adapter(wiphy);
+       struct mwifiex_private *priv = mwifiex_get_priv(adapter,
+                                                       MWIFIEX_BSS_ROLE_ANY);
+       mwifiex_dbg(adapter, INFO,
+                   "info: cfg80211 regulatory domain callback for %c%c\n",
+                   request->alpha2[0], request->alpha2[1]);
+
+       switch (request->initiator) {
+       case NL80211_REGDOM_SET_BY_DRIVER:
+       case NL80211_REGDOM_SET_BY_CORE:
+       case NL80211_REGDOM_SET_BY_USER:
+       case NL80211_REGDOM_SET_BY_COUNTRY_IE:
+               break;
+       default:
+               mwifiex_dbg(adapter, ERROR,
+                           "unknown regdom initiator: %d\n",
+                           request->initiator);
+               return;
+       }
+
+       /* Don't send world or same regdom info to firmware */
+       if (strncmp(request->alpha2, "00", 2) &&
+           strncmp(request->alpha2, adapter->country_code,
+                   sizeof(request->alpha2))) {
+               memcpy(adapter->country_code, request->alpha2,
+                      sizeof(request->alpha2));
+               mwifiex_send_domain_info_cmd_fw(wiphy);
+               mwifiex_dnld_txpwr_table(priv);
+       }
+}
+
+/*
+ * This function sets the fragmentation threshold.
+ *
+ * The fragmentation threshold value must lie between MWIFIEX_FRAG_MIN_VALUE
+ * and MWIFIEX_FRAG_MAX_VALUE.
+ */
+static int
+mwifiex_set_frag(struct mwifiex_private *priv, u32 frag_thr)
+{
+       if (frag_thr < MWIFIEX_FRAG_MIN_VALUE ||
+           frag_thr > MWIFIEX_FRAG_MAX_VALUE)
+               frag_thr = MWIFIEX_FRAG_MAX_VALUE;
+
+       return mwifiex_send_cmd(priv, HostCmd_CMD_802_11_SNMP_MIB,
+                               HostCmd_ACT_GEN_SET, FRAG_THRESH_I,
+                               &frag_thr, true);
+}
+
+/*
+ * This function sets the RTS threshold.
+
+ * The rts value must lie between MWIFIEX_RTS_MIN_VALUE
+ * and MWIFIEX_RTS_MAX_VALUE.
+ */
+static int
+mwifiex_set_rts(struct mwifiex_private *priv, u32 rts_thr)
+{
+       if (rts_thr < MWIFIEX_RTS_MIN_VALUE || rts_thr > MWIFIEX_RTS_MAX_VALUE)
+               rts_thr = MWIFIEX_RTS_MAX_VALUE;
+
+       return mwifiex_send_cmd(priv, HostCmd_CMD_802_11_SNMP_MIB,
+                               HostCmd_ACT_GEN_SET, RTS_THRESH_I,
+                               &rts_thr, true);
+}
+
+/*
+ * CFG802.11 operation handler to set wiphy parameters.
+ *
+ * This function can be used to set the RTS threshold and the
+ * Fragmentation threshold of the driver.
+ */
+static int
+mwifiex_cfg80211_set_wiphy_params(struct wiphy *wiphy, u32 changed)
+{
+       struct mwifiex_adapter *adapter = mwifiex_cfg80211_get_adapter(wiphy);
+       struct mwifiex_private *priv;
+       struct mwifiex_uap_bss_param *bss_cfg;
+       int ret;
+
+       priv = mwifiex_get_priv(adapter, MWIFIEX_BSS_ROLE_ANY);
+
+       switch (priv->bss_role) {
+       case MWIFIEX_BSS_ROLE_UAP:
+               if (priv->bss_started) {
+                       mwifiex_dbg(adapter, ERROR,
+                                   "cannot change wiphy params when bss started");
+                       return -EINVAL;
+               }
+
+               bss_cfg = kzalloc(sizeof(*bss_cfg), GFP_KERNEL);
+               if (!bss_cfg)
+                       return -ENOMEM;
+
+               mwifiex_set_sys_config_invalid_data(bss_cfg);
+
+               if (changed & WIPHY_PARAM_RTS_THRESHOLD)
+                       bss_cfg->rts_threshold = wiphy->rts_threshold;
+               if (changed & WIPHY_PARAM_FRAG_THRESHOLD)
+                       bss_cfg->frag_threshold = wiphy->frag_threshold;
+               if (changed & WIPHY_PARAM_RETRY_LONG)
+                       bss_cfg->retry_limit = wiphy->retry_long;
+
+               ret = mwifiex_send_cmd(priv, HostCmd_CMD_UAP_SYS_CONFIG,
+                                      HostCmd_ACT_GEN_SET,
+                                      UAP_BSS_PARAMS_I, bss_cfg,
+                                      false);
+
+               kfree(bss_cfg);
+               if (ret) {
+                       mwifiex_dbg(adapter, ERROR,
+                                   "Failed to set wiphy phy params\n");
+                       return ret;
+               }
+               break;
+
+               case MWIFIEX_BSS_ROLE_STA:
+               if (priv->media_connected) {
+                       mwifiex_dbg(adapter, ERROR,
+                                   "cannot change wiphy params when connected");
+                       return -EINVAL;
+               }
+               if (changed & WIPHY_PARAM_RTS_THRESHOLD) {
+                       ret = mwifiex_set_rts(priv,
+                                             wiphy->rts_threshold);
+                       if (ret)
+                               return ret;
+               }
+               if (changed & WIPHY_PARAM_FRAG_THRESHOLD) {
+                       ret = mwifiex_set_frag(priv,
+                                              wiphy->frag_threshold);
+                       if (ret)
+                               return ret;
+               }
+               break;
+       }
+
+       return 0;
+}
+
+static int
+mwifiex_cfg80211_deinit_p2p(struct mwifiex_private *priv)
+{
+       u16 mode = P2P_MODE_DISABLE;
+
+       if (mwifiex_send_cmd(priv, HostCmd_CMD_P2P_MODE_CFG,
+                            HostCmd_ACT_GEN_SET, 0, &mode, true))
+               return -1;
+
+       return 0;
+}
+
+/*
+ * This function initializes the functionalities for P2P client.
+ * The P2P client initialization sequence is:
+ * disable -> device -> client
+ */
+static int
+mwifiex_cfg80211_init_p2p_client(struct mwifiex_private *priv)
+{
+       u16 mode;
+
+       if (mwifiex_cfg80211_deinit_p2p(priv))
+               return -1;
+
+       mode = P2P_MODE_DEVICE;
+       if (mwifiex_send_cmd(priv, HostCmd_CMD_P2P_MODE_CFG,
+                            HostCmd_ACT_GEN_SET, 0, &mode, true))
+               return -1;
+
+       mode = P2P_MODE_CLIENT;
+       if (mwifiex_send_cmd(priv, HostCmd_CMD_P2P_MODE_CFG,
+                            HostCmd_ACT_GEN_SET, 0, &mode, true))
+               return -1;
+
+       return 0;
+}
+
+/*
+ * This function initializes the functionalities for P2P GO.
+ * The P2P GO initialization sequence is:
+ * disable -> device -> GO
+ */
+static int
+mwifiex_cfg80211_init_p2p_go(struct mwifiex_private *priv)
+{
+       u16 mode;
+
+       if (mwifiex_cfg80211_deinit_p2p(priv))
+               return -1;
+
+       mode = P2P_MODE_DEVICE;
+       if (mwifiex_send_cmd(priv, HostCmd_CMD_P2P_MODE_CFG,
+                            HostCmd_ACT_GEN_SET, 0, &mode, true))
+               return -1;
+
+       mode = P2P_MODE_GO;
+       if (mwifiex_send_cmd(priv, HostCmd_CMD_P2P_MODE_CFG,
+                            HostCmd_ACT_GEN_SET, 0, &mode, true))
+               return -1;
+
+       return 0;
+}
+
+static int mwifiex_deinit_priv_params(struct mwifiex_private *priv)
+{
+       struct mwifiex_adapter *adapter = priv->adapter;
+       unsigned long flags;
+
+       priv->mgmt_frame_mask = 0;
+       if (mwifiex_send_cmd(priv, HostCmd_CMD_MGMT_FRAME_REG,
+                            HostCmd_ACT_GEN_SET, 0,
+                            &priv->mgmt_frame_mask, false)) {
+               mwifiex_dbg(adapter, ERROR,
+                           "could not unregister mgmt frame rx\n");
+               return -1;
+       }
+
+       mwifiex_deauthenticate(priv, NULL);
+
+       spin_lock_irqsave(&adapter->main_proc_lock, flags);
+       adapter->main_locked = true;
+       if (adapter->mwifiex_processing) {
+               spin_unlock_irqrestore(&adapter->main_proc_lock, flags);
+               flush_workqueue(adapter->workqueue);
+       } else {
+               spin_unlock_irqrestore(&adapter->main_proc_lock, flags);
+       }
+
+       spin_lock_irqsave(&adapter->rx_proc_lock, flags);
+       adapter->rx_locked = true;
+       if (adapter->rx_processing) {
+               spin_unlock_irqrestore(&adapter->rx_proc_lock, flags);
+               flush_workqueue(adapter->rx_workqueue);
+       } else {
+       spin_unlock_irqrestore(&adapter->rx_proc_lock, flags);
+       }
+
+       mwifiex_free_priv(priv);
+       priv->wdev.iftype = NL80211_IFTYPE_UNSPECIFIED;
+       priv->bss_mode = NL80211_IFTYPE_UNSPECIFIED;
+       priv->sec_info.authentication_mode = NL80211_AUTHTYPE_OPEN_SYSTEM;
+
+       return 0;
+}
+
+static int
+mwifiex_init_new_priv_params(struct mwifiex_private *priv,
+                            struct net_device *dev,
+                            enum nl80211_iftype type)
+{
+       struct mwifiex_adapter *adapter = priv->adapter;
+       unsigned long flags;
+
+       mwifiex_init_priv(priv);
+
+       priv->bss_mode = type;
+       priv->wdev.iftype = type;
+
+       mwifiex_init_priv_params(priv, priv->netdev);
+       priv->bss_started = 0;
+
+       switch (type) {
+       case NL80211_IFTYPE_STATION:
+       case NL80211_IFTYPE_ADHOC:
+               priv->bss_role =  MWIFIEX_BSS_ROLE_STA;
+               priv->bss_type = MWIFIEX_BSS_TYPE_STA;
+               break;
+       case NL80211_IFTYPE_P2P_CLIENT:
+               priv->bss_role =  MWIFIEX_BSS_ROLE_STA;
+               priv->bss_type = MWIFIEX_BSS_TYPE_P2P;
+               break;
+       case NL80211_IFTYPE_P2P_GO:
+               priv->bss_role =  MWIFIEX_BSS_ROLE_UAP;
+               priv->bss_type = MWIFIEX_BSS_TYPE_P2P;
+               break;
+       case NL80211_IFTYPE_AP:
+               priv->bss_type = MWIFIEX_BSS_TYPE_UAP;
+               priv->bss_role = MWIFIEX_BSS_ROLE_UAP;
+               break;
+       default:
+               mwifiex_dbg(adapter, ERROR,
+                           "%s: changing to %d not supported\n",
+                           dev->name, type);
+               return -EOPNOTSUPP;
+       }
+
+       spin_lock_irqsave(&adapter->main_proc_lock, flags);
+       adapter->main_locked = false;
+       spin_unlock_irqrestore(&adapter->main_proc_lock, flags);
+
+       spin_lock_irqsave(&adapter->rx_proc_lock, flags);
+       adapter->rx_locked = false;
+       spin_unlock_irqrestore(&adapter->rx_proc_lock, flags);
+
+       return 0;
+}
+
+static int
+mwifiex_change_vif_to_p2p(struct net_device *dev,
+                         enum nl80211_iftype curr_iftype,
+                         enum nl80211_iftype type, u32 *flags,
+                         struct vif_params *params)
+{
+       struct mwifiex_private *priv;
+       struct mwifiex_adapter *adapter;
+
+       priv = mwifiex_netdev_get_priv(dev);
+
+       if (!priv)
+               return -1;
+
+       adapter = priv->adapter;
+
+       if (adapter->curr_iface_comb.p2p_intf ==
+           adapter->iface_limit.p2p_intf) {
+               mwifiex_dbg(adapter, ERROR,
+                           "cannot create multiple P2P ifaces\n");
+               return -1;
+       }
+
+       mwifiex_dbg(adapter, INFO,
+                   "%s: changing role to p2p\n", dev->name);
+
+       if (mwifiex_deinit_priv_params(priv))
+               return -1;
+       if (mwifiex_init_new_priv_params(priv, dev, type))
+               return -1;
+
+       switch (type) {
+       case NL80211_IFTYPE_P2P_CLIENT:
+               if (mwifiex_cfg80211_init_p2p_client(priv))
+                       return -EFAULT;
+               break;
+       case NL80211_IFTYPE_P2P_GO:
+               if (mwifiex_cfg80211_init_p2p_go(priv))
+                       return -EFAULT;
+               break;
+       default:
+               mwifiex_dbg(adapter, ERROR,
+                           "%s: changing to %d not supported\n",
+                           dev->name, type);
+               return -EOPNOTSUPP;
+       }
+
+       if (mwifiex_send_cmd(priv, HostCmd_CMD_SET_BSS_MODE,
+                            HostCmd_ACT_GEN_SET, 0, NULL, true))
+               return -1;
+
+       if (mwifiex_sta_init_cmd(priv, false, false))
+               return -1;
+
+       switch (curr_iftype) {
+       case NL80211_IFTYPE_STATION:
+       case NL80211_IFTYPE_ADHOC:
+               adapter->curr_iface_comb.sta_intf--;
+               break;
+       case NL80211_IFTYPE_AP:
+               adapter->curr_iface_comb.uap_intf--;
+               break;
+       default:
+               break;
+       }
+
+       adapter->curr_iface_comb.p2p_intf++;
+       dev->ieee80211_ptr->iftype = type;
+
+       return 0;
+}
+
+static int
+mwifiex_change_vif_to_sta_adhoc(struct net_device *dev,
+                               enum nl80211_iftype curr_iftype,
+                               enum nl80211_iftype type, u32 *flags,
+                               struct vif_params *params)
+{
+       struct mwifiex_private *priv;
+       struct mwifiex_adapter *adapter;
+
+       priv = mwifiex_netdev_get_priv(dev);
+
+       if (!priv)
+               return -1;
+
+       adapter = priv->adapter;
+
+       if ((curr_iftype != NL80211_IFTYPE_P2P_CLIENT &&
+            curr_iftype != NL80211_IFTYPE_P2P_GO) &&
+           (adapter->curr_iface_comb.sta_intf ==
+            adapter->iface_limit.sta_intf)) {
+               mwifiex_dbg(adapter, ERROR,
+                           "cannot create multiple station/adhoc ifaces\n");
+               return -1;
+       }
+
+       if (type == NL80211_IFTYPE_STATION)
+               mwifiex_dbg(adapter, INFO,
+                           "%s: changing role to station\n", dev->name);
+       else
+               mwifiex_dbg(adapter, INFO,
+                           "%s: changing role to adhoc\n", dev->name);
+
+       if (mwifiex_deinit_priv_params(priv))
+               return -1;
+       if (mwifiex_init_new_priv_params(priv, dev, type))
+               return -1;
+       if (mwifiex_send_cmd(priv, HostCmd_CMD_SET_BSS_MODE,
+                            HostCmd_ACT_GEN_SET, 0, NULL, true))
+               return -1;
+       if (mwifiex_sta_init_cmd(priv, false, false))
+               return -1;
+
+       switch (curr_iftype) {
+       case NL80211_IFTYPE_P2P_CLIENT:
+       case NL80211_IFTYPE_P2P_GO:
+               adapter->curr_iface_comb.p2p_intf--;
+               break;
+       case NL80211_IFTYPE_AP:
+               adapter->curr_iface_comb.uap_intf--;
+               break;
+       default:
+               break;
+       }
+
+       adapter->curr_iface_comb.sta_intf++;
+       dev->ieee80211_ptr->iftype = type;
+       return 0;
+}
+
+static int
+mwifiex_change_vif_to_ap(struct net_device *dev,
+                        enum nl80211_iftype curr_iftype,
+                        enum nl80211_iftype type, u32 *flags,
+                        struct vif_params *params)
+{
+       struct mwifiex_private *priv;
+       struct mwifiex_adapter *adapter;
+
+       priv = mwifiex_netdev_get_priv(dev);
+
+       if (!priv)
+               return -1;
+
+       adapter = priv->adapter;
+
+       if (adapter->curr_iface_comb.uap_intf ==
+           adapter->iface_limit.uap_intf) {
+               mwifiex_dbg(adapter, ERROR,
+                           "cannot create multiple AP ifaces\n");
+               return -1;
+       }
+
+       mwifiex_dbg(adapter, INFO,
+                   "%s: changing role to AP\n", dev->name);
+
+       if (mwifiex_deinit_priv_params(priv))
+               return -1;
+       if (mwifiex_init_new_priv_params(priv, dev, type))
+               return -1;
+       if (mwifiex_send_cmd(priv, HostCmd_CMD_SET_BSS_MODE,
+                            HostCmd_ACT_GEN_SET, 0, NULL, true))
+               return -1;
+       if (mwifiex_sta_init_cmd(priv, false, false))
+               return -1;
+
+       switch (curr_iftype) {
+       case NL80211_IFTYPE_P2P_CLIENT:
+       case NL80211_IFTYPE_P2P_GO:
+               adapter->curr_iface_comb.p2p_intf--;
+               break;
+       case NL80211_IFTYPE_STATION:
+       case NL80211_IFTYPE_ADHOC:
+               adapter->curr_iface_comb.sta_intf--;
+               break;
+       default:
+               break;
+       }
+
+       adapter->curr_iface_comb.uap_intf++;
+       dev->ieee80211_ptr->iftype = type;
+       return 0;
+}
+/*
+ * CFG802.11 operation handler to change interface type.
+ */
+static int
+mwifiex_cfg80211_change_virtual_intf(struct wiphy *wiphy,
+                                    struct net_device *dev,
+                                    enum nl80211_iftype type, u32 *flags,
+                                    struct vif_params *params)
+{
+       struct mwifiex_private *priv = mwifiex_netdev_get_priv(dev);
+       enum nl80211_iftype curr_iftype = dev->ieee80211_ptr->iftype;
+
+       switch (curr_iftype) {
+       case NL80211_IFTYPE_ADHOC:
+               switch (type) {
+               case NL80211_IFTYPE_STATION:
+                       priv->bss_mode = type;
+                       priv->sec_info.authentication_mode =
+                                                  NL80211_AUTHTYPE_OPEN_SYSTEM;
+                       dev->ieee80211_ptr->iftype = type;
+                       mwifiex_deauthenticate(priv, NULL);
+                       return mwifiex_send_cmd(priv, HostCmd_CMD_SET_BSS_MODE,
+                                               HostCmd_ACT_GEN_SET, 0, NULL,
+                                               true);
+               case NL80211_IFTYPE_P2P_CLIENT:
+               case NL80211_IFTYPE_P2P_GO:
+                       return mwifiex_change_vif_to_p2p(dev, curr_iftype,
+                                                        type, flags, params);
+               case NL80211_IFTYPE_AP:
+                       return mwifiex_change_vif_to_ap(dev, curr_iftype, type,
+                                                       flags, params);
+               case NL80211_IFTYPE_UNSPECIFIED:
+                       mwifiex_dbg(priv->adapter, INFO,
+                                   "%s: kept type as IBSS\n", dev->name);
+               case NL80211_IFTYPE_ADHOC:      /* This shouldn't happen */
+                       return 0;
+               default:
+                       mwifiex_dbg(priv->adapter, ERROR,
+                                   "%s: changing to %d not supported\n",
+                                   dev->name, type);
+                       return -EOPNOTSUPP;
+               }
+               break;
+       case NL80211_IFTYPE_STATION:
+               switch (type) {
+               case NL80211_IFTYPE_ADHOC:
+                       priv->bss_mode = type;
+                       priv->sec_info.authentication_mode =
+                                                  NL80211_AUTHTYPE_OPEN_SYSTEM;
+                       dev->ieee80211_ptr->iftype = type;
+                       mwifiex_deauthenticate(priv, NULL);
+                       return mwifiex_send_cmd(priv, HostCmd_CMD_SET_BSS_MODE,
+                                               HostCmd_ACT_GEN_SET, 0, NULL,
+                                               true);
+               case NL80211_IFTYPE_P2P_CLIENT:
+               case NL80211_IFTYPE_P2P_GO:
+                       return mwifiex_change_vif_to_p2p(dev, curr_iftype,
+                                                        type, flags, params);
+               case NL80211_IFTYPE_AP:
+                       return mwifiex_change_vif_to_ap(dev, curr_iftype, type,
+                                                       flags, params);
+               case NL80211_IFTYPE_UNSPECIFIED:
+                       mwifiex_dbg(priv->adapter, INFO,
+                                   "%s: kept type as STA\n", dev->name);
+               case NL80211_IFTYPE_STATION:    /* This shouldn't happen */
+                       return 0;
+               default:
+                       mwifiex_dbg(priv->adapter, ERROR,
+                                   "%s: changing to %d not supported\n",
+                                   dev->name, type);
+                       return -EOPNOTSUPP;
+               }
+               break;
+       case NL80211_IFTYPE_AP:
+               switch (type) {
+               case NL80211_IFTYPE_ADHOC:
+               case NL80211_IFTYPE_STATION:
+                       return mwifiex_change_vif_to_sta_adhoc(dev, curr_iftype,
+                                                              type, flags,
+                                                              params);
+                       break;
+               case NL80211_IFTYPE_P2P_CLIENT:
+               case NL80211_IFTYPE_P2P_GO:
+                       return mwifiex_change_vif_to_p2p(dev, curr_iftype,
+                                                        type, flags, params);
+               case NL80211_IFTYPE_UNSPECIFIED:
+                       mwifiex_dbg(priv->adapter, INFO,
+                                   "%s: kept type as AP\n", dev->name);
+               case NL80211_IFTYPE_AP:         /* This shouldn't happen */
+                       return 0;
+               default:
+                       mwifiex_dbg(priv->adapter, ERROR,
+                                   "%s: changing to %d not supported\n",
+                                   dev->name, type);
+                       return -EOPNOTSUPP;
+               }
+               break;
+       case NL80211_IFTYPE_P2P_CLIENT:
+       case NL80211_IFTYPE_P2P_GO:
+               switch (type) {
+               case NL80211_IFTYPE_STATION:
+                       if (mwifiex_cfg80211_deinit_p2p(priv))
+                               return -EFAULT;
+                       priv->adapter->curr_iface_comb.p2p_intf--;
+                       priv->adapter->curr_iface_comb.sta_intf++;
+                       dev->ieee80211_ptr->iftype = type;
+                       break;
+               case NL80211_IFTYPE_ADHOC:
+                       if (mwifiex_cfg80211_deinit_p2p(priv))
+                               return -EFAULT;
+                       return mwifiex_change_vif_to_sta_adhoc(dev, curr_iftype,
+                                                              type, flags,
+                                                              params);
+                       break;
+               case NL80211_IFTYPE_AP:
+                       if (mwifiex_cfg80211_deinit_p2p(priv))
+                               return -EFAULT;
+                       return mwifiex_change_vif_to_ap(dev, curr_iftype, type,
+                                                       flags, params);
+               case NL80211_IFTYPE_UNSPECIFIED:
+                       mwifiex_dbg(priv->adapter, INFO,
+                                   "%s: kept type as P2P\n", dev->name);
+               case NL80211_IFTYPE_P2P_CLIENT:
+               case NL80211_IFTYPE_P2P_GO:
+                       return 0;
+               default:
+                       mwifiex_dbg(priv->adapter, ERROR,
+                                   "%s: changing to %d not supported\n",
+                                   dev->name, type);
+                       return -EOPNOTSUPP;
+               }
+               break;
+       default:
+               mwifiex_dbg(priv->adapter, ERROR,
+                           "%s: unknown iftype: %d\n",
+                           dev->name, dev->ieee80211_ptr->iftype);
+               return -EOPNOTSUPP;
+       }
+
+
+       return 0;
+}
+
+static void
+mwifiex_parse_htinfo(struct mwifiex_private *priv, u8 tx_htinfo,
+                    struct rate_info *rate)
+{
+       struct mwifiex_adapter *adapter = priv->adapter;
+
+       if (adapter->is_hw_11ac_capable) {
+               /* bit[1-0]: 00=LG 01=HT 10=VHT */
+               if (tx_htinfo & BIT(0)) {
+                       /* HT */
+                       rate->mcs = priv->tx_rate;
+                       rate->flags |= RATE_INFO_FLAGS_MCS;
+               }
+               if (tx_htinfo & BIT(1)) {
+                       /* VHT */
+                       rate->mcs = priv->tx_rate & 0x0F;
+                       rate->flags |= RATE_INFO_FLAGS_VHT_MCS;
+               }
+
+               if (tx_htinfo & (BIT(1) | BIT(0))) {
+                       /* HT or VHT */
+                       switch (tx_htinfo & (BIT(3) | BIT(2))) {
+                       case 0:
+                               rate->bw = RATE_INFO_BW_20;
+                               break;
+                       case (BIT(2)):
+                               rate->bw = RATE_INFO_BW_40;
+                               break;
+                       case (BIT(3)):
+                               rate->bw = RATE_INFO_BW_80;
+                               break;
+                       case (BIT(3) | BIT(2)):
+                               rate->bw = RATE_INFO_BW_160;
+                               break;
+                       }
+
+                       if (tx_htinfo & BIT(4))
+                               rate->flags |= RATE_INFO_FLAGS_SHORT_GI;
+
+                       if ((priv->tx_rate >> 4) == 1)
+                               rate->nss = 2;
+                       else
+                               rate->nss = 1;
+               }
+       } else {
+               /*
+                * Bit 0 in tx_htinfo indicates that current Tx rate
+                * is 11n rate. Valid MCS index values for us are 0 to 15.
+                */
+               if ((tx_htinfo & BIT(0)) && (priv->tx_rate < 16)) {
+                       rate->mcs = priv->tx_rate;
+                       rate->flags |= RATE_INFO_FLAGS_MCS;
+                       rate->bw = RATE_INFO_BW_20;
+                       if (tx_htinfo & BIT(1))
+                               rate->bw = RATE_INFO_BW_40;
+                       if (tx_htinfo & BIT(2))
+                               rate->flags |= RATE_INFO_FLAGS_SHORT_GI;
+               }
+       }
+}
+
+/*
+ * This function dumps the station information on a buffer.
+ *
+ * The following information are shown -
+ *      - Total bytes transmitted
+ *      - Total bytes received
+ *      - Total packets transmitted
+ *      - Total packets received
+ *      - Signal quality level
+ *      - Transmission rate
+ */
+static int
+mwifiex_dump_station_info(struct mwifiex_private *priv,
+                         struct mwifiex_sta_node *node,
+                         struct station_info *sinfo)
+{
+       u32 rate;
+
+       sinfo->filled = BIT(NL80211_STA_INFO_RX_BYTES) | BIT(NL80211_STA_INFO_TX_BYTES) |
+                       BIT(NL80211_STA_INFO_RX_PACKETS) | BIT(NL80211_STA_INFO_TX_PACKETS) |
+                       BIT(NL80211_STA_INFO_TX_BITRATE) |
+                       BIT(NL80211_STA_INFO_SIGNAL) | BIT(NL80211_STA_INFO_SIGNAL_AVG);
+
+       if (GET_BSS_ROLE(priv) == MWIFIEX_BSS_ROLE_UAP) {
+               if (!node)
+                       return -ENOENT;
+
+               sinfo->filled |= BIT(NL80211_STA_INFO_INACTIVE_TIME) |
+                               BIT(NL80211_STA_INFO_TX_FAILED);
+               sinfo->inactive_time =
+                       jiffies_to_msecs(jiffies - node->stats.last_rx);
+
+               sinfo->signal = node->stats.rssi;
+               sinfo->signal_avg = node->stats.rssi;
+               sinfo->rx_bytes = node->stats.rx_bytes;
+               sinfo->tx_bytes = node->stats.tx_bytes;
+               sinfo->rx_packets = node->stats.rx_packets;
+               sinfo->tx_packets = node->stats.tx_packets;
+               sinfo->tx_failed = node->stats.tx_failed;
+
+               mwifiex_parse_htinfo(priv, node->stats.last_tx_htinfo,
+                                    &sinfo->txrate);
+               sinfo->txrate.legacy = node->stats.last_tx_rate * 5;
+
+               return 0;
+       }
+
+       /* Get signal information from the firmware */
+       if (mwifiex_send_cmd(priv, HostCmd_CMD_RSSI_INFO,
+                            HostCmd_ACT_GEN_GET, 0, NULL, true)) {
+               mwifiex_dbg(priv->adapter, ERROR,
+                           "failed to get signal information\n");
+               return -EFAULT;
+       }
+
+       if (mwifiex_drv_get_data_rate(priv, &rate)) {
+               mwifiex_dbg(priv->adapter, ERROR,
+                           "getting data rate error\n");
+               return -EFAULT;
+       }
+
+       /* Get DTIM period information from firmware */
+       mwifiex_send_cmd(priv, HostCmd_CMD_802_11_SNMP_MIB,
+                        HostCmd_ACT_GEN_GET, DTIM_PERIOD_I,
+                        &priv->dtim_period, true);
+
+       mwifiex_parse_htinfo(priv, priv->tx_htinfo, &sinfo->txrate);
+
+       sinfo->signal_avg = priv->bcn_rssi_avg;
+       sinfo->rx_bytes = priv->stats.rx_bytes;
+       sinfo->tx_bytes = priv->stats.tx_bytes;
+       sinfo->rx_packets = priv->stats.rx_packets;
+       sinfo->tx_packets = priv->stats.tx_packets;
+       sinfo->signal = priv->bcn_rssi_avg;
+       /* bit rate is in 500 kb/s units. Convert it to 100kb/s units */
+       sinfo->txrate.legacy = rate * 5;
+
+       if (priv->bss_mode == NL80211_IFTYPE_STATION) {
+               sinfo->filled |= BIT(NL80211_STA_INFO_BSS_PARAM);
+               sinfo->bss_param.flags = 0;
+               if (priv->curr_bss_params.bss_descriptor.cap_info_bitmap &
+                                               WLAN_CAPABILITY_SHORT_PREAMBLE)
+                       sinfo->bss_param.flags |=
+                                       BSS_PARAM_FLAGS_SHORT_PREAMBLE;
+               if (priv->curr_bss_params.bss_descriptor.cap_info_bitmap &
+                                               WLAN_CAPABILITY_SHORT_SLOT_TIME)
+                       sinfo->bss_param.flags |=
+                                       BSS_PARAM_FLAGS_SHORT_SLOT_TIME;
+               sinfo->bss_param.dtim_period = priv->dtim_period;
+               sinfo->bss_param.beacon_interval =
+                       priv->curr_bss_params.bss_descriptor.beacon_period;
+       }
+
+       return 0;
+}
+
+/*
+ * CFG802.11 operation handler to get station information.
+ *
+ * This function only works in connected mode, and dumps the
+ * requested station information, if available.
+ */
+static int
+mwifiex_cfg80211_get_station(struct wiphy *wiphy, struct net_device *dev,
+                            const u8 *mac, struct station_info *sinfo)
+{
+       struct mwifiex_private *priv = mwifiex_netdev_get_priv(dev);
+
+       if (!priv->media_connected)
+               return -ENOENT;
+       if (memcmp(mac, priv->cfg_bssid, ETH_ALEN))
+               return -ENOENT;
+
+       return mwifiex_dump_station_info(priv, NULL, sinfo);
+}
+
+/*
+ * CFG802.11 operation handler to dump station information.
+ */
+static int
+mwifiex_cfg80211_dump_station(struct wiphy *wiphy, struct net_device *dev,
+                             int idx, u8 *mac, struct station_info *sinfo)
+{
+       struct mwifiex_private *priv = mwifiex_netdev_get_priv(dev);
+       static struct mwifiex_sta_node *node;
+
+       if ((GET_BSS_ROLE(priv) == MWIFIEX_BSS_ROLE_STA) &&
+           priv->media_connected && idx == 0) {
+               ether_addr_copy(mac, priv->cfg_bssid);
+               return mwifiex_dump_station_info(priv, NULL, sinfo);
+       } else if (GET_BSS_ROLE(priv) == MWIFIEX_BSS_ROLE_UAP) {
+               mwifiex_send_cmd(priv, HOST_CMD_APCMD_STA_LIST,
+                                HostCmd_ACT_GEN_GET, 0, NULL, true);
+
+               if (node && (&node->list == &priv->sta_list)) {
+                       node = NULL;
+                       return -ENOENT;
+               }
+
+               node = list_prepare_entry(node, &priv->sta_list, list);
+               list_for_each_entry_continue(node, &priv->sta_list, list) {
+                       ether_addr_copy(mac, node->mac_addr);
+                       return mwifiex_dump_station_info(priv, node, sinfo);
+               }
+       }
+
+       return -ENOENT;
+}
+
+static int
+mwifiex_cfg80211_dump_survey(struct wiphy *wiphy, struct net_device *dev,
+                            int idx, struct survey_info *survey)
+{
+       struct mwifiex_private *priv = mwifiex_netdev_get_priv(dev);
+       struct mwifiex_chan_stats *pchan_stats = priv->adapter->chan_stats;
+       enum ieee80211_band band;
+
+       mwifiex_dbg(priv->adapter, DUMP, "dump_survey idx=%d\n", idx);
+
+       memset(survey, 0, sizeof(struct survey_info));
+
+       if ((GET_BSS_ROLE(priv) == MWIFIEX_BSS_ROLE_STA) &&
+           priv->media_connected && idx == 0) {
+                       u8 curr_bss_band = priv->curr_bss_params.band;
+                       u32 chan = priv->curr_bss_params.bss_descriptor.channel;
+
+                       band = mwifiex_band_to_radio_type(curr_bss_band);
+                       survey->channel = ieee80211_get_channel(wiphy,
+                               ieee80211_channel_to_frequency(chan, band));
+
+                       if (priv->bcn_nf_last) {
+                               survey->filled = SURVEY_INFO_NOISE_DBM;
+                               survey->noise = priv->bcn_nf_last;
+                       }
+                       return 0;
+       }
+
+       if (idx >= priv->adapter->num_in_chan_stats)
+               return -ENOENT;
+
+       if (!pchan_stats[idx].cca_scan_dur)
+               return 0;
+
+       band = pchan_stats[idx].bandcfg;
+       survey->channel = ieee80211_get_channel(wiphy,
+           ieee80211_channel_to_frequency(pchan_stats[idx].chan_num, band));
+       survey->filled = SURVEY_INFO_NOISE_DBM |
+                        SURVEY_INFO_TIME |
+                        SURVEY_INFO_TIME_BUSY;
+       survey->noise = pchan_stats[idx].noise;
+       survey->time = pchan_stats[idx].cca_scan_dur;
+       survey->time_busy = pchan_stats[idx].cca_busy_dur;
+
+       return 0;
+}
+
+/* Supported rates to be advertised to the cfg80211 */
+static struct ieee80211_rate mwifiex_rates[] = {
+       {.bitrate = 10, .hw_value = 2, },
+       {.bitrate = 20, .hw_value = 4, },
+       {.bitrate = 55, .hw_value = 11, },
+       {.bitrate = 110, .hw_value = 22, },
+       {.bitrate = 60, .hw_value = 12, },
+       {.bitrate = 90, .hw_value = 18, },
+       {.bitrate = 120, .hw_value = 24, },
+       {.bitrate = 180, .hw_value = 36, },
+       {.bitrate = 240, .hw_value = 48, },
+       {.bitrate = 360, .hw_value = 72, },
+       {.bitrate = 480, .hw_value = 96, },
+       {.bitrate = 540, .hw_value = 108, },
+};
+
+/* Channel definitions to be advertised to cfg80211 */
+static struct ieee80211_channel mwifiex_channels_2ghz[] = {
+       {.center_freq = 2412, .hw_value = 1, },
+       {.center_freq = 2417, .hw_value = 2, },
+       {.center_freq = 2422, .hw_value = 3, },
+       {.center_freq = 2427, .hw_value = 4, },
+       {.center_freq = 2432, .hw_value = 5, },
+       {.center_freq = 2437, .hw_value = 6, },
+       {.center_freq = 2442, .hw_value = 7, },
+       {.center_freq = 2447, .hw_value = 8, },
+       {.center_freq = 2452, .hw_value = 9, },
+       {.center_freq = 2457, .hw_value = 10, },
+       {.center_freq = 2462, .hw_value = 11, },
+       {.center_freq = 2467, .hw_value = 12, },
+       {.center_freq = 2472, .hw_value = 13, },
+       {.center_freq = 2484, .hw_value = 14, },
+};
+
+static struct ieee80211_supported_band mwifiex_band_2ghz = {
+       .channels = mwifiex_channels_2ghz,
+       .n_channels = ARRAY_SIZE(mwifiex_channels_2ghz),
+       .bitrates = mwifiex_rates,
+       .n_bitrates = ARRAY_SIZE(mwifiex_rates),
+};
+
+static struct ieee80211_channel mwifiex_channels_5ghz[] = {
+       {.center_freq = 5040, .hw_value = 8, },
+       {.center_freq = 5060, .hw_value = 12, },
+       {.center_freq = 5080, .hw_value = 16, },
+       {.center_freq = 5170, .hw_value = 34, },
+       {.center_freq = 5190, .hw_value = 38, },
+       {.center_freq = 5210, .hw_value = 42, },
+       {.center_freq = 5230, .hw_value = 46, },
+       {.center_freq = 5180, .hw_value = 36, },
+       {.center_freq = 5200, .hw_value = 40, },
+       {.center_freq = 5220, .hw_value = 44, },
+       {.center_freq = 5240, .hw_value = 48, },
+       {.center_freq = 5260, .hw_value = 52, },
+       {.center_freq = 5280, .hw_value = 56, },
+       {.center_freq = 5300, .hw_value = 60, },
+       {.center_freq = 5320, .hw_value = 64, },
+       {.center_freq = 5500, .hw_value = 100, },
+       {.center_freq = 5520, .hw_value = 104, },
+       {.center_freq = 5540, .hw_value = 108, },
+       {.center_freq = 5560, .hw_value = 112, },
+       {.center_freq = 5580, .hw_value = 116, },
+       {.center_freq = 5600, .hw_value = 120, },
+       {.center_freq = 5620, .hw_value = 124, },
+       {.center_freq = 5640, .hw_value = 128, },
+       {.center_freq = 5660, .hw_value = 132, },
+       {.center_freq = 5680, .hw_value = 136, },
+       {.center_freq = 5700, .hw_value = 140, },
+       {.center_freq = 5745, .hw_value = 149, },
+       {.center_freq = 5765, .hw_value = 153, },
+       {.center_freq = 5785, .hw_value = 157, },
+       {.center_freq = 5805, .hw_value = 161, },
+       {.center_freq = 5825, .hw_value = 165, },
+};
+
+static struct ieee80211_supported_band mwifiex_band_5ghz = {
+       .channels = mwifiex_channels_5ghz,
+       .n_channels = ARRAY_SIZE(mwifiex_channels_5ghz),
+       .bitrates = mwifiex_rates + 4,
+       .n_bitrates = ARRAY_SIZE(mwifiex_rates) - 4,
+};
+
+
+/* Supported crypto cipher suits to be advertised to cfg80211 */
+static const u32 mwifiex_cipher_suites[] = {
+       WLAN_CIPHER_SUITE_WEP40,
+       WLAN_CIPHER_SUITE_WEP104,
+       WLAN_CIPHER_SUITE_TKIP,
+       WLAN_CIPHER_SUITE_CCMP,
+       WLAN_CIPHER_SUITE_AES_CMAC,
+};
+
+/* Supported mgmt frame types to be advertised to cfg80211 */
+static const struct ieee80211_txrx_stypes
+mwifiex_mgmt_stypes[NUM_NL80211_IFTYPES] = {
+       [NL80211_IFTYPE_STATION] = {
+               .tx = BIT(IEEE80211_STYPE_ACTION >> 4) |
+                     BIT(IEEE80211_STYPE_PROBE_RESP >> 4),
+               .rx = BIT(IEEE80211_STYPE_ACTION >> 4) |
+                     BIT(IEEE80211_STYPE_PROBE_REQ >> 4),
+       },
+       [NL80211_IFTYPE_AP] = {
+               .tx = BIT(IEEE80211_STYPE_ACTION >> 4) |
+                     BIT(IEEE80211_STYPE_PROBE_RESP >> 4),
+               .rx = BIT(IEEE80211_STYPE_ACTION >> 4) |
+                     BIT(IEEE80211_STYPE_PROBE_REQ >> 4),
+       },
+       [NL80211_IFTYPE_P2P_CLIENT] = {
+               .tx = BIT(IEEE80211_STYPE_ACTION >> 4) |
+                     BIT(IEEE80211_STYPE_PROBE_RESP >> 4),
+               .rx = BIT(IEEE80211_STYPE_ACTION >> 4) |
+                     BIT(IEEE80211_STYPE_PROBE_REQ >> 4),
+       },
+       [NL80211_IFTYPE_P2P_GO] = {
+               .tx = BIT(IEEE80211_STYPE_ACTION >> 4) |
+                     BIT(IEEE80211_STYPE_PROBE_RESP >> 4),
+               .rx = BIT(IEEE80211_STYPE_ACTION >> 4) |
+                     BIT(IEEE80211_STYPE_PROBE_REQ >> 4),
+       },
+};
+
+/*
+ * CFG802.11 operation handler for setting bit rates.
+ *
+ * Function configures data rates to firmware using bitrate mask
+ * provided by cfg80211.
+ */
+static int mwifiex_cfg80211_set_bitrate_mask(struct wiphy *wiphy,
+                               struct net_device *dev,
+                               const u8 *peer,
+                               const struct cfg80211_bitrate_mask *mask)
+{
+       struct mwifiex_private *priv = mwifiex_netdev_get_priv(dev);
+       u16 bitmap_rates[MAX_BITMAP_RATES_SIZE];
+       enum ieee80211_band band;
+       struct mwifiex_adapter *adapter = priv->adapter;
+
+       if (!priv->media_connected) {
+               mwifiex_dbg(adapter, ERROR,
+                           "Can not set Tx data rate in disconnected state\n");
+               return -EINVAL;
+       }
+
+       band = mwifiex_band_to_radio_type(priv->curr_bss_params.band);
+
+       memset(bitmap_rates, 0, sizeof(bitmap_rates));
+
+       /* Fill HR/DSSS rates. */
+       if (band == IEEE80211_BAND_2GHZ)
+               bitmap_rates[0] = mask->control[band].legacy & 0x000f;
+
+       /* Fill OFDM rates */
+       if (band == IEEE80211_BAND_2GHZ)
+               bitmap_rates[1] = (mask->control[band].legacy & 0x0ff0) >> 4;
+       else
+               bitmap_rates[1] = mask->control[band].legacy;
+
+       /* Fill HT MCS rates */
+       bitmap_rates[2] = mask->control[band].ht_mcs[0];
+       if (adapter->hw_dev_mcs_support == HT_STREAM_2X2)
+               bitmap_rates[2] |= mask->control[band].ht_mcs[1] << 8;
+
+       /* Fill VHT MCS rates */
+       if (adapter->fw_api_ver == MWIFIEX_FW_V15) {
+               bitmap_rates[10] = mask->control[band].vht_mcs[0];
+               if (adapter->hw_dev_mcs_support == HT_STREAM_2X2)
+                       bitmap_rates[11] = mask->control[band].vht_mcs[1];
+       }
+
+       return mwifiex_send_cmd(priv, HostCmd_CMD_TX_RATE_CFG,
+                               HostCmd_ACT_GEN_SET, 0, bitmap_rates, true);
+}
+
+/*
+ * CFG802.11 operation handler for connection quality monitoring.
+ *
+ * This function subscribes/unsubscribes HIGH_RSSI and LOW_RSSI
+ * events to FW.
+ */
+static int mwifiex_cfg80211_set_cqm_rssi_config(struct wiphy *wiphy,
+                                               struct net_device *dev,
+                                               s32 rssi_thold, u32 rssi_hyst)
+{
+       struct mwifiex_private *priv = mwifiex_netdev_get_priv(dev);
+       struct mwifiex_ds_misc_subsc_evt subsc_evt;
+
+       priv->cqm_rssi_thold = rssi_thold;
+       priv->cqm_rssi_hyst = rssi_hyst;
+
+       memset(&subsc_evt, 0x00, sizeof(struct mwifiex_ds_misc_subsc_evt));
+       subsc_evt.events = BITMASK_BCN_RSSI_LOW | BITMASK_BCN_RSSI_HIGH;
+
+       /* Subscribe/unsubscribe low and high rssi events */
+       if (rssi_thold && rssi_hyst) {
+               subsc_evt.action = HostCmd_ACT_BITWISE_SET;
+               subsc_evt.bcn_l_rssi_cfg.abs_value = abs(rssi_thold);
+               subsc_evt.bcn_h_rssi_cfg.abs_value = abs(rssi_thold);
+               subsc_evt.bcn_l_rssi_cfg.evt_freq = 1;
+               subsc_evt.bcn_h_rssi_cfg.evt_freq = 1;
+               return mwifiex_send_cmd(priv,
+                                       HostCmd_CMD_802_11_SUBSCRIBE_EVENT,
+                                       0, 0, &subsc_evt, true);
+       } else {
+               subsc_evt.action = HostCmd_ACT_BITWISE_CLR;
+               return mwifiex_send_cmd(priv,
+                                       HostCmd_CMD_802_11_SUBSCRIBE_EVENT,
+                                       0, 0, &subsc_evt, true);
+       }
+
+       return 0;
+}
+
+/* cfg80211 operation handler for change_beacon.
+ * Function retrieves and sets modified management IEs to FW.
+ */
+static int mwifiex_cfg80211_change_beacon(struct wiphy *wiphy,
+                                         struct net_device *dev,
+                                         struct cfg80211_beacon_data *data)
+{
+       struct mwifiex_private *priv = mwifiex_netdev_get_priv(dev);
+
+       if (GET_BSS_ROLE(priv) != MWIFIEX_BSS_ROLE_UAP) {
+               mwifiex_dbg(priv->adapter, ERROR,
+                           "%s: bss_type mismatched\n", __func__);
+               return -EINVAL;
+       }
+
+       if (!priv->bss_started) {
+               mwifiex_dbg(priv->adapter, ERROR,
+                           "%s: bss not started\n", __func__);
+               return -EINVAL;
+       }
+
+       if (mwifiex_set_mgmt_ies(priv, data)) {
+               mwifiex_dbg(priv->adapter, ERROR,
+                           "%s: setting mgmt ies failed\n", __func__);
+               return -EFAULT;
+       }
+
+       return 0;
+}
+
+/* cfg80211 operation handler for del_station.
+ * Function deauthenticates station which value is provided in mac parameter.
+ * If mac is NULL/broadcast, all stations in associated station list are
+ * deauthenticated. If bss is not started or there are no stations in
+ * associated stations list, no action is taken.
+ */
+static int
+mwifiex_cfg80211_del_station(struct wiphy *wiphy, struct net_device *dev,
+                            struct station_del_parameters *params)
+{
+       struct mwifiex_private *priv = mwifiex_netdev_get_priv(dev);
+       struct mwifiex_sta_node *sta_node;
+       u8 deauth_mac[ETH_ALEN];
+       unsigned long flags;
+
+       if (list_empty(&priv->sta_list) || !priv->bss_started)
+               return 0;
+
+       if (!params->mac || is_broadcast_ether_addr(params->mac))
+               return 0;
+
+       mwifiex_dbg(priv->adapter, INFO, "%s: mac address %pM\n",
+                   __func__, params->mac);
+
+       eth_zero_addr(deauth_mac);
+
+       spin_lock_irqsave(&priv->sta_list_spinlock, flags);
+       sta_node = mwifiex_get_sta_entry(priv, params->mac);
+       if (sta_node)
+               ether_addr_copy(deauth_mac, params->mac);
+       spin_unlock_irqrestore(&priv->sta_list_spinlock, flags);
+
+       if (is_valid_ether_addr(deauth_mac)) {
+               if (mwifiex_send_cmd(priv, HostCmd_CMD_UAP_STA_DEAUTH,
+                                    HostCmd_ACT_GEN_SET, 0,
+                                    deauth_mac, true))
+                       return -1;
+       }
+
+       return 0;
+}
+
+static int
+mwifiex_cfg80211_set_antenna(struct wiphy *wiphy, u32 tx_ant, u32 rx_ant)
+{
+       struct mwifiex_adapter *adapter = mwifiex_cfg80211_get_adapter(wiphy);
+       struct mwifiex_private *priv = mwifiex_get_priv(adapter,
+                                                       MWIFIEX_BSS_ROLE_ANY);
+       struct mwifiex_ds_ant_cfg ant_cfg;
+
+       if (!tx_ant || !rx_ant)
+               return -EOPNOTSUPP;
+
+       if (adapter->hw_dev_mcs_support != HT_STREAM_2X2) {
+               /* Not a MIMO chip. User should provide specific antenna number
+                * for Tx/Rx path or enable all antennas for diversity
+                */
+               if (tx_ant != rx_ant)
+                       return -EOPNOTSUPP;
+
+               if ((tx_ant & (tx_ant - 1)) &&
+                   (tx_ant != BIT(adapter->number_of_antenna) - 1))
+                       return -EOPNOTSUPP;
+
+               if ((tx_ant == BIT(adapter->number_of_antenna) - 1) &&
+                   (priv->adapter->number_of_antenna > 1)) {
+                       tx_ant = RF_ANTENNA_AUTO;
+                       rx_ant = RF_ANTENNA_AUTO;
+               }
+       } else {
+               struct ieee80211_sta_ht_cap *ht_info;
+               int rx_mcs_supp;
+               enum ieee80211_band band;
+
+               if ((tx_ant == 0x1 && rx_ant == 0x1)) {
+                       adapter->user_dev_mcs_support = HT_STREAM_1X1;
+                       if (adapter->is_hw_11ac_capable)
+                               adapter->usr_dot_11ac_mcs_support =
+                                               MWIFIEX_11AC_MCS_MAP_1X1;
+               } else {
+                       adapter->user_dev_mcs_support = HT_STREAM_2X2;
+                       if (adapter->is_hw_11ac_capable)
+                               adapter->usr_dot_11ac_mcs_support =
+                                               MWIFIEX_11AC_MCS_MAP_2X2;
+               }
+
+               for (band = 0; band < IEEE80211_NUM_BANDS; band++) {
+                       if (!adapter->wiphy->bands[band])
+                               continue;
+
+                       ht_info = &adapter->wiphy->bands[band]->ht_cap;
+                       rx_mcs_supp =
+                               GET_RXMCSSUPP(adapter->user_dev_mcs_support);
+                       memset(&ht_info->mcs, 0, adapter->number_of_antenna);
+                       memset(&ht_info->mcs, 0xff, rx_mcs_supp);
+               }
+       }
+
+       ant_cfg.tx_ant = tx_ant;
+       ant_cfg.rx_ant = rx_ant;
+
+       return mwifiex_send_cmd(priv, HostCmd_CMD_RF_ANTENNA,
+                               HostCmd_ACT_GEN_SET, 0, &ant_cfg, true);
+}
+
+/* cfg80211 operation handler for stop ap.
+ * Function stops BSS running at uAP interface.
+ */
+static int mwifiex_cfg80211_stop_ap(struct wiphy *wiphy, struct net_device *dev)
+{
+       struct mwifiex_private *priv = mwifiex_netdev_get_priv(dev);
+
+       mwifiex_abort_cac(priv);
+
+       if (mwifiex_del_mgmt_ies(priv))
+               mwifiex_dbg(priv->adapter, ERROR,
+                           "Failed to delete mgmt IEs!\n");
+
+       priv->ap_11n_enabled = 0;
+       memset(&priv->bss_cfg, 0, sizeof(priv->bss_cfg));
+
+       if (mwifiex_send_cmd(priv, HostCmd_CMD_UAP_BSS_STOP,
+                            HostCmd_ACT_GEN_SET, 0, NULL, true)) {
+               mwifiex_dbg(priv->adapter, ERROR,
+                           "Failed to stop the BSS\n");
+               return -1;
+       }
+
+       if (mwifiex_send_cmd(priv, HOST_CMD_APCMD_SYS_RESET,
+                            HostCmd_ACT_GEN_SET, 0, NULL, true)) {
+               mwifiex_dbg(priv->adapter, ERROR,
+                           "Failed to reset BSS\n");
+               return -1;
+       }
+
+       if (netif_carrier_ok(priv->netdev))
+               netif_carrier_off(priv->netdev);
+       mwifiex_stop_net_dev_queue(priv->netdev, priv->adapter);
+
+       return 0;
+}
+
+/* cfg80211 operation handler for start_ap.
+ * Function sets beacon period, DTIM period, SSID and security into
+ * AP config structure.
+ * AP is configured with these settings and BSS is started.
+ */
+static int mwifiex_cfg80211_start_ap(struct wiphy *wiphy,
+                                    struct net_device *dev,
+                                    struct cfg80211_ap_settings *params)
+{
+       struct mwifiex_uap_bss_param *bss_cfg;
+       struct mwifiex_private *priv = mwifiex_netdev_get_priv(dev);
+
+       if (GET_BSS_ROLE(priv) != MWIFIEX_BSS_ROLE_UAP)
+               return -1;
+
+       bss_cfg = kzalloc(sizeof(struct mwifiex_uap_bss_param), GFP_KERNEL);
+       if (!bss_cfg)
+               return -ENOMEM;
+
+       mwifiex_set_sys_config_invalid_data(bss_cfg);
+
+       if (params->beacon_interval)
+               bss_cfg->beacon_period = params->beacon_interval;
+       if (params->dtim_period)
+               bss_cfg->dtim_period = params->dtim_period;
+
+       if (params->ssid && params->ssid_len) {
+               memcpy(bss_cfg->ssid.ssid, params->ssid, params->ssid_len);
+               bss_cfg->ssid.ssid_len = params->ssid_len;
+       }
+       if (params->inactivity_timeout > 0) {
+               /* sta_ao_timer/ps_sta_ao_timer is in unit of 100ms */
+               bss_cfg->sta_ao_timer = 10 * params->inactivity_timeout;
+               bss_cfg->ps_sta_ao_timer = 10 * params->inactivity_timeout;
+       }
+
+       switch (params->hidden_ssid) {
+       case NL80211_HIDDEN_SSID_NOT_IN_USE:
+               bss_cfg->bcast_ssid_ctl = 1;
+               break;
+       case NL80211_HIDDEN_SSID_ZERO_LEN:
+               bss_cfg->bcast_ssid_ctl = 0;
+               break;
+       case NL80211_HIDDEN_SSID_ZERO_CONTENTS:
+               /* firmware doesn't support this type of hidden SSID */
+       default:
+               kfree(bss_cfg);
+               return -EINVAL;
+       }
+
+       mwifiex_uap_set_channel(priv, bss_cfg, params->chandef);
+       mwifiex_set_uap_rates(bss_cfg, params);
+
+       if (mwifiex_set_secure_params(priv, bss_cfg, params)) {
+               kfree(bss_cfg);
+               mwifiex_dbg(priv->adapter, ERROR,
+                           "Failed to parse secuirty parameters!\n");
+               return -1;
+       }
+
+       mwifiex_set_ht_params(priv, bss_cfg, params);
+
+       if (priv->adapter->is_hw_11ac_capable) {
+               mwifiex_set_vht_params(priv, bss_cfg, params);
+               mwifiex_set_vht_width(priv, params->chandef.width,
+                                     priv->ap_11ac_enabled);
+       }
+
+       if (priv->ap_11ac_enabled)
+               mwifiex_set_11ac_ba_params(priv);
+       else
+               mwifiex_set_ba_params(priv);
+
+       mwifiex_set_wmm_params(priv, bss_cfg, params);
+
+       if (mwifiex_is_11h_active(priv))
+               mwifiex_set_tpc_params(priv, bss_cfg, params);
+
+       if (mwifiex_is_11h_active(priv) &&
+           !cfg80211_chandef_dfs_required(wiphy, &params->chandef,
+                                          priv->bss_mode)) {
+               mwifiex_dbg(priv->adapter, INFO,
+                           "Disable 11h extensions in FW\n");
+               if (mwifiex_11h_activate(priv, false)) {
+                       mwifiex_dbg(priv->adapter, ERROR,
+                                   "Failed to disable 11h extensions!!");
+                       return -1;
+               }
+               priv->state_11h.is_11h_active = false;
+       }
+
+       if (mwifiex_config_start_uap(priv, bss_cfg)) {
+               mwifiex_dbg(priv->adapter, ERROR,
+                           "Failed to start AP\n");
+               kfree(bss_cfg);
+               return -1;
+       }
+
+       if (mwifiex_set_mgmt_ies(priv, &params->beacon))
+               return -1;
+
+       if (!netif_carrier_ok(priv->netdev))
+               netif_carrier_on(priv->netdev);
+       mwifiex_wake_up_net_dev_queue(priv->netdev, priv->adapter);
+
+       memcpy(&priv->bss_cfg, bss_cfg, sizeof(priv->bss_cfg));
+       kfree(bss_cfg);
+       return 0;
+}
+
+/*
+ * CFG802.11 operation handler for disconnection request.
+ *
+ * This function does not work when there is already a disconnection
+ * procedure going on.
+ */
+static int
+mwifiex_cfg80211_disconnect(struct wiphy *wiphy, struct net_device *dev,
+                           u16 reason_code)
+{
+       struct mwifiex_private *priv = mwifiex_netdev_get_priv(dev);
+
+       if (mwifiex_deauthenticate(priv, NULL))
+               return -EFAULT;
+
+       mwifiex_dbg(priv->adapter, MSG,
+                   "info: successfully disconnected from %pM:\t"
+                   "reason code %d\n", priv->cfg_bssid, reason_code);
+
+       eth_zero_addr(priv->cfg_bssid);
+       priv->hs2_enabled = false;
+
+       return 0;
+}
+
+/*
+ * This function informs the CFG802.11 subsystem of a new IBSS.
+ *
+ * The following information are sent to the CFG802.11 subsystem
+ * to register the new IBSS. If we do not register the new IBSS,
+ * a kernel panic will result.
+ *      - SSID
+ *      - SSID length
+ *      - BSSID
+ *      - Channel
+ */
+static int mwifiex_cfg80211_inform_ibss_bss(struct mwifiex_private *priv)
+{
+       struct ieee80211_channel *chan;
+       struct mwifiex_bss_info bss_info;
+       struct cfg80211_bss *bss;
+       int ie_len;
+       u8 ie_buf[IEEE80211_MAX_SSID_LEN + sizeof(struct ieee_types_header)];
+       enum ieee80211_band band;
+
+       if (mwifiex_get_bss_info(priv, &bss_info))
+               return -1;
+
+       ie_buf[0] = WLAN_EID_SSID;
+       ie_buf[1] = bss_info.ssid.ssid_len;
+
+       memcpy(&ie_buf[sizeof(struct ieee_types_header)],
+              &bss_info.ssid.ssid, bss_info.ssid.ssid_len);
+       ie_len = ie_buf[1] + sizeof(struct ieee_types_header);
+
+       band = mwifiex_band_to_radio_type(priv->curr_bss_params.band);
+       chan = __ieee80211_get_channel(priv->wdev.wiphy,
+                       ieee80211_channel_to_frequency(bss_info.bss_chan,
+                                                      band));
+
+       bss = cfg80211_inform_bss(priv->wdev.wiphy, chan,
+                                 CFG80211_BSS_FTYPE_UNKNOWN,
+                                 bss_info.bssid, 0, WLAN_CAPABILITY_IBSS,
+                                 0, ie_buf, ie_len, 0, GFP_KERNEL);
+       if (bss) {
+               cfg80211_put_bss(priv->wdev.wiphy, bss);
+               ether_addr_copy(priv->cfg_bssid, bss_info.bssid);
+       }
+
+       return 0;
+}
+
+/*
+ * This function connects with a BSS.
+ *
+ * This function handles both Infra and Ad-Hoc modes. It also performs
+ * validity checking on the provided parameters, disconnects from the
+ * current BSS (if any), sets up the association/scan parameters,
+ * including security settings, and performs specific SSID scan before
+ * trying to connect.
+ *
+ * For Infra mode, the function returns failure if the specified SSID
+ * is not found in scan table. However, for Ad-Hoc mode, it can create
+ * the IBSS if it does not exist. On successful completion in either case,
+ * the function notifies the CFG802.11 subsystem of the new BSS connection.
+ */
+static int
+mwifiex_cfg80211_assoc(struct mwifiex_private *priv, size_t ssid_len,
+                      const u8 *ssid, const u8 *bssid, int mode,
+                      struct ieee80211_channel *channel,
+                      struct cfg80211_connect_params *sme, bool privacy)
+{
+       struct cfg80211_ssid req_ssid;
+       int ret, auth_type = 0;
+       struct cfg80211_bss *bss = NULL;
+       u8 is_scanning_required = 0;
+
+       memset(&req_ssid, 0, sizeof(struct cfg80211_ssid));
+
+       req_ssid.ssid_len = ssid_len;
+       if (ssid_len > IEEE80211_MAX_SSID_LEN) {
+               mwifiex_dbg(priv->adapter, ERROR, "invalid SSID - aborting\n");
+               return -EINVAL;
+       }
+
+       memcpy(req_ssid.ssid, ssid, ssid_len);
+       if (!req_ssid.ssid_len || req_ssid.ssid[0] < 0x20) {
+               mwifiex_dbg(priv->adapter, ERROR, "invalid SSID - aborting\n");
+               return -EINVAL;
+       }
+
+       /* As this is new association, clear locally stored
+        * keys and security related flags */
+       priv->sec_info.wpa_enabled = false;
+       priv->sec_info.wpa2_enabled = false;
+       priv->wep_key_curr_index = 0;
+       priv->sec_info.encryption_mode = 0;
+       priv->sec_info.is_authtype_auto = 0;
+       ret = mwifiex_set_encode(priv, NULL, NULL, 0, 0, NULL, 1);
+
+       if (mode == NL80211_IFTYPE_ADHOC) {
+               /* "privacy" is set only for ad-hoc mode */
+               if (privacy) {
+                       /*
+                        * Keep WLAN_CIPHER_SUITE_WEP104 for now so that
+                        * the firmware can find a matching network from the
+                        * scan. The cfg80211 does not give us the encryption
+                        * mode at this stage so just setting it to WEP here.
+                        */
+                       priv->sec_info.encryption_mode =
+                                       WLAN_CIPHER_SUITE_WEP104;
+                       priv->sec_info.authentication_mode =
+                                       NL80211_AUTHTYPE_OPEN_SYSTEM;
+               }
+
+               goto done;
+       }
+
+       /* Now handle infra mode. "sme" is valid for infra mode only */
+       if (sme->auth_type == NL80211_AUTHTYPE_AUTOMATIC) {
+               auth_type = NL80211_AUTHTYPE_OPEN_SYSTEM;
+               priv->sec_info.is_authtype_auto = 1;
+       } else {
+               auth_type = sme->auth_type;
+       }
+
+       if (sme->crypto.n_ciphers_pairwise) {
+               priv->sec_info.encryption_mode =
+                                               sme->crypto.ciphers_pairwise[0];
+               priv->sec_info.authentication_mode = auth_type;
+       }
+
+       if (sme->crypto.cipher_group) {
+               priv->sec_info.encryption_mode = sme->crypto.cipher_group;
+               priv->sec_info.authentication_mode = auth_type;
+       }
+       if (sme->ie)
+               ret = mwifiex_set_gen_ie(priv, sme->ie, sme->ie_len);
+
+       if (sme->key) {
+               if (mwifiex_is_alg_wep(priv->sec_info.encryption_mode)) {
+                       mwifiex_dbg(priv->adapter, INFO,
+                                   "info: setting wep encryption\t"
+                                   "with key len %d\n", sme->key_len);
+                       priv->wep_key_curr_index = sme->key_idx;
+                       ret = mwifiex_set_encode(priv, NULL, sme->key,
+                                                sme->key_len, sme->key_idx,
+                                                NULL, 0);
+               }
+       }
+done:
+       /*
+        * Scan entries are valid for some time (15 sec). So we can save one
+        * active scan time if we just try cfg80211_get_bss first. If it fails
+        * then request scan and cfg80211_get_bss() again for final output.
+        */
+       while (1) {
+               if (is_scanning_required) {
+                       /* Do specific SSID scanning */
+                       if (mwifiex_request_scan(priv, &req_ssid)) {
+                               mwifiex_dbg(priv->adapter, ERROR, "scan error\n");
+                               return -EFAULT;
+                       }
+               }
+
+               /* Find the BSS we want using available scan results */
+               if (mode == NL80211_IFTYPE_ADHOC)
+                       bss = cfg80211_get_bss(priv->wdev.wiphy, channel,
+                                              bssid, ssid, ssid_len,
+                                              IEEE80211_BSS_TYPE_IBSS,
+                                              IEEE80211_PRIVACY_ANY);
+               else
+                       bss = cfg80211_get_bss(priv->wdev.wiphy, channel,
+                                              bssid, ssid, ssid_len,
+                                              IEEE80211_BSS_TYPE_ESS,
+                                              IEEE80211_PRIVACY_ANY);
+
+               if (!bss) {
+                       if (is_scanning_required) {
+                               mwifiex_dbg(priv->adapter, WARN,
+                                           "assoc: requested bss not found in scan results\n");
+                               break;
+                       }
+                       is_scanning_required = 1;
+               } else {
+                       mwifiex_dbg(priv->adapter, MSG,
+                                   "info: trying to associate to '%s' bssid %pM\n",
+                                   (char *)req_ssid.ssid, bss->bssid);
+                       memcpy(&priv->cfg_bssid, bss->bssid, ETH_ALEN);
+                       break;
+               }
+       }
+
+       ret = mwifiex_bss_start(priv, bss, &req_ssid);
+       if (ret)
+               return ret;
+
+       if (mode == NL80211_IFTYPE_ADHOC) {
+               /* Inform the BSS information to kernel, otherwise
+                * kernel will give a panic after successful assoc */
+               if (mwifiex_cfg80211_inform_ibss_bss(priv))
+                       return -EFAULT;
+       }
+
+       return ret;
+}
+
+/*
+ * CFG802.11 operation handler for association request.
+ *
+ * This function does not work when the current mode is set to Ad-Hoc, or
+ * when there is already an association procedure going on. The given BSS
+ * information is used to associate.
+ */
+static int
+mwifiex_cfg80211_connect(struct wiphy *wiphy, struct net_device *dev,
+                        struct cfg80211_connect_params *sme)
+{
+       struct mwifiex_private *priv = mwifiex_netdev_get_priv(dev);
+       struct mwifiex_adapter *adapter = priv->adapter;
+       int ret;
+
+       if (GET_BSS_ROLE(priv) != MWIFIEX_BSS_ROLE_STA) {
+               mwifiex_dbg(adapter, ERROR,
+                           "%s: reject infra assoc request in non-STA role\n",
+                           dev->name);
+               return -EINVAL;
+       }
+
+       if (priv->wdev.current_bss) {
+               mwifiex_dbg(adapter, ERROR,
+                           "%s: already connected\n", dev->name);
+               return -EALREADY;
+       }
+
+       if (adapter->surprise_removed || adapter->is_cmd_timedout) {
+               mwifiex_dbg(adapter, ERROR,
+                           "%s: Ignore connection.\t"
+                           "Card removed or FW in bad state\n",
+                           dev->name);
+               return -EFAULT;
+       }
+
+       mwifiex_dbg(adapter, INFO,
+                   "info: Trying to associate to %s and bssid %pM\n",
+                   (char *)sme->ssid, sme->bssid);
+
+       ret = mwifiex_cfg80211_assoc(priv, sme->ssid_len, sme->ssid, sme->bssid,
+                                    priv->bss_mode, sme->channel, sme, 0);
+       if (!ret) {
+               cfg80211_connect_result(priv->netdev, priv->cfg_bssid, NULL, 0,
+                                       NULL, 0, WLAN_STATUS_SUCCESS,
+                                       GFP_KERNEL);
+               mwifiex_dbg(priv->adapter, MSG,
+                           "info: associated to bssid %pM successfully\n",
+                           priv->cfg_bssid);
+               if (ISSUPP_TDLS_ENABLED(priv->adapter->fw_cap_info) &&
+                   priv->adapter->auto_tdls &&
+                   priv->bss_type == MWIFIEX_BSS_TYPE_STA)
+                       mwifiex_setup_auto_tdls_timer(priv);
+       } else {
+               mwifiex_dbg(priv->adapter, ERROR,
+                           "info: association to bssid %pM failed\n",
+                           priv->cfg_bssid);
+               eth_zero_addr(priv->cfg_bssid);
+
+               if (ret > 0)
+                       cfg80211_connect_result(priv->netdev, priv->cfg_bssid,
+                                               NULL, 0, NULL, 0, ret,
+                                               GFP_KERNEL);
+               else
+                       cfg80211_connect_result(priv->netdev, priv->cfg_bssid,
+                                               NULL, 0, NULL, 0,
+                                               WLAN_STATUS_UNSPECIFIED_FAILURE,
+                                               GFP_KERNEL);
+       }
+
+       return 0;
+}
+
+/*
+ * This function sets following parameters for ibss network.
+ *  -  channel
+ *  -  start band
+ *  -  11n flag
+ *  -  secondary channel offset
+ */
+static int mwifiex_set_ibss_params(struct mwifiex_private *priv,
+                                  struct cfg80211_ibss_params *params)
+{
+       struct mwifiex_adapter *adapter = priv->adapter;
+       int index = 0, i;
+       u8 config_bands = 0;
+
+       if (params->chandef.chan->band == IEEE80211_BAND_2GHZ) {
+               if (!params->basic_rates) {
+                       config_bands = BAND_B | BAND_G;
+               } else {
+                       for (i = 0; i < mwifiex_band_2ghz.n_bitrates; i++) {
+                               /*
+                                * Rates below 6 Mbps in the table are CCK
+                                * rates; 802.11b and from 6 they are OFDM;
+                                * 802.11G
+                                */
+                               if (mwifiex_rates[i].bitrate == 60) {
+                                       index = 1 << i;
+                                       break;
+                               }
+                       }
+
+                       if (params->basic_rates < index) {
+                               config_bands = BAND_B;
+                       } else {
+                               config_bands = BAND_G;
+                               if (params->basic_rates % index)
+                                       config_bands |= BAND_B;
+                       }
+               }
+
+               if (cfg80211_get_chandef_type(&params->chandef) !=
+                                               NL80211_CHAN_NO_HT)
+                       config_bands |= BAND_G | BAND_GN;
+       } else {
+               if (cfg80211_get_chandef_type(&params->chandef) ==
+                                               NL80211_CHAN_NO_HT)
+                       config_bands = BAND_A;
+               else
+                       config_bands = BAND_AN | BAND_A;
+       }
+
+       if (!((config_bands | adapter->fw_bands) & ~adapter->fw_bands)) {
+               adapter->config_bands = config_bands;
+               adapter->adhoc_start_band = config_bands;
+
+               if ((config_bands & BAND_GN) || (config_bands & BAND_AN))
+                       adapter->adhoc_11n_enabled = true;
+               else
+                       adapter->adhoc_11n_enabled = false;
+       }
+
+       adapter->sec_chan_offset =
+               mwifiex_chan_type_to_sec_chan_offset(
+                       cfg80211_get_chandef_type(&params->chandef));
+       priv->adhoc_channel = ieee80211_frequency_to_channel(
+                               params->chandef.chan->center_freq);
+
+       mwifiex_dbg(adapter, INFO,
+                   "info: set ibss band %d, chan %d, chan offset %d\n",
+                   config_bands, priv->adhoc_channel,
+                   adapter->sec_chan_offset);
+
+       return 0;
+}
+
+/*
+ * CFG802.11 operation handler to join an IBSS.
+ *
+ * This function does not work in any mode other than Ad-Hoc, or if
+ * a join operation is already in progress.
+ */
+static int
+mwifiex_cfg80211_join_ibss(struct wiphy *wiphy, struct net_device *dev,
+                          struct cfg80211_ibss_params *params)
+{
+       struct mwifiex_private *priv = mwifiex_netdev_get_priv(dev);
+       int ret = 0;
+
+       if (priv->bss_mode != NL80211_IFTYPE_ADHOC) {
+               mwifiex_dbg(priv->adapter, ERROR,
+                           "request to join ibss received\t"
+                           "when station is not in ibss mode\n");
+               goto done;
+       }
+
+       mwifiex_dbg(priv->adapter, MSG,
+                   "info: trying to join to %s and bssid %pM\n",
+                   (char *)params->ssid, params->bssid);
+
+       mwifiex_set_ibss_params(priv, params);
+
+       ret = mwifiex_cfg80211_assoc(priv, params->ssid_len, params->ssid,
+                                    params->bssid, priv->bss_mode,
+                                    params->chandef.chan, NULL,
+                                    params->privacy);
+done:
+       if (!ret) {
+               cfg80211_ibss_joined(priv->netdev, priv->cfg_bssid,
+                                    params->chandef.chan, GFP_KERNEL);
+               mwifiex_dbg(priv->adapter, MSG,
+                           "info: joined/created adhoc network with bssid\t"
+                           "%pM successfully\n", priv->cfg_bssid);
+       } else {
+               mwifiex_dbg(priv->adapter, ERROR,
+                           "info: failed creating/joining adhoc network\n");
+       }
+
+       return ret;
+}
+
+/*
+ * CFG802.11 operation handler to leave an IBSS.
+ *
+ * This function does not work if a leave operation is
+ * already in progress.
+ */
+static int
+mwifiex_cfg80211_leave_ibss(struct wiphy *wiphy, struct net_device *dev)
+{
+       struct mwifiex_private *priv = mwifiex_netdev_get_priv(dev);
+
+       mwifiex_dbg(priv->adapter, MSG, "info: disconnecting from essid %pM\n",
+                   priv->cfg_bssid);
+       if (mwifiex_deauthenticate(priv, NULL))
+               return -EFAULT;
+
+       eth_zero_addr(priv->cfg_bssid);
+
+       return 0;
+}
+
+/*
+ * CFG802.11 operation handler for scan request.
+ *
+ * This function issues a scan request to the firmware based upon
+ * the user specified scan configuration. On successful completion,
+ * it also informs the results.
+ */
+static int
+mwifiex_cfg80211_scan(struct wiphy *wiphy,
+                     struct cfg80211_scan_request *request)
+{
+       struct net_device *dev = request->wdev->netdev;
+       struct mwifiex_private *priv = mwifiex_netdev_get_priv(dev);
+       int i, offset, ret;
+       struct ieee80211_channel *chan;
+       struct ieee_types_header *ie;
+       struct mwifiex_user_scan_cfg *user_scan_cfg;
+
+       mwifiex_dbg(priv->adapter, CMD,
+                   "info: received scan request on %s\n", dev->name);
+
+       /* Block scan request if scan operation or scan cleanup when interface
+        * is disabled is in process
+        */
+       if (priv->scan_request || priv->scan_aborting) {
+               mwifiex_dbg(priv->adapter, WARN,
+                           "cmd: Scan already in process..\n");
+               return -EBUSY;
+       }
+
+       user_scan_cfg = kzalloc(sizeof(*user_scan_cfg), GFP_KERNEL);
+       if (!user_scan_cfg)
+               return -ENOMEM;
+
+       priv->scan_request = request;
+
+       user_scan_cfg->num_ssids = request->n_ssids;
+       user_scan_cfg->ssid_list = request->ssids;
+
+       if (request->ie && request->ie_len) {
+               offset = 0;
+               for (i = 0; i < MWIFIEX_MAX_VSIE_NUM; i++) {
+                       if (priv->vs_ie[i].mask != MWIFIEX_VSIE_MASK_CLEAR)
+                               continue;
+                       priv->vs_ie[i].mask = MWIFIEX_VSIE_MASK_SCAN;
+                       ie = (struct ieee_types_header *)(request->ie + offset);
+                       memcpy(&priv->vs_ie[i].ie, ie, sizeof(*ie) + ie->len);
+                       offset += sizeof(*ie) + ie->len;
+
+                       if (offset >= request->ie_len)
+                               break;
+               }
+       }
+
+       for (i = 0; i < min_t(u32, request->n_channels,
+                             MWIFIEX_USER_SCAN_CHAN_MAX); i++) {
+               chan = request->channels[i];
+               user_scan_cfg->chan_list[i].chan_number = chan->hw_value;
+               user_scan_cfg->chan_list[i].radio_type = chan->band;
+
+               if ((chan->flags & IEEE80211_CHAN_NO_IR) || !request->n_ssids)
+                       user_scan_cfg->chan_list[i].scan_type =
+                                               MWIFIEX_SCAN_TYPE_PASSIVE;
+               else
+                       user_scan_cfg->chan_list[i].scan_type =
+                                               MWIFIEX_SCAN_TYPE_ACTIVE;
+
+               user_scan_cfg->chan_list[i].scan_time = 0;
+       }
+
+       if (priv->adapter->scan_chan_gap_enabled &&
+           mwifiex_is_any_intf_active(priv))
+               user_scan_cfg->scan_chan_gap =
+                                             priv->adapter->scan_chan_gap_time;
+
+       ret = mwifiex_scan_networks(priv, user_scan_cfg);
+       kfree(user_scan_cfg);
+       if (ret) {
+               mwifiex_dbg(priv->adapter, ERROR,
+                           "scan failed: %d\n", ret);
+               priv->scan_aborting = false;
+               priv->scan_request = NULL;
+               return ret;
+       }
+
+       if (request->ie && request->ie_len) {
+               for (i = 0; i < MWIFIEX_MAX_VSIE_NUM; i++) {
+                       if (priv->vs_ie[i].mask == MWIFIEX_VSIE_MASK_SCAN) {
+                               priv->vs_ie[i].mask = MWIFIEX_VSIE_MASK_CLEAR;
+                               memset(&priv->vs_ie[i].ie, 0,
+                                      MWIFIEX_MAX_VSIE_LEN);
+                       }
+               }
+       }
+       return 0;
+}
+
+static void mwifiex_setup_vht_caps(struct ieee80211_sta_vht_cap *vht_info,
+                                  struct mwifiex_private *priv)
+{
+       struct mwifiex_adapter *adapter = priv->adapter;
+
+       vht_info->vht_supported = true;
+
+       vht_info->cap = adapter->hw_dot_11ac_dev_cap;
+       /* Update MCS support for VHT */
+       vht_info->vht_mcs.rx_mcs_map = cpu_to_le16(
+                               adapter->hw_dot_11ac_mcs_support & 0xFFFF);
+       vht_info->vht_mcs.rx_highest = 0;
+       vht_info->vht_mcs.tx_mcs_map = cpu_to_le16(
+                               adapter->hw_dot_11ac_mcs_support >> 16);
+       vht_info->vht_mcs.tx_highest = 0;
+}
+
+/*
+ * This function sets up the CFG802.11 specific HT capability fields
+ * with default values.
+ *
+ * The following default values are set -
+ *      - HT Supported = True
+ *      - Maximum AMPDU length factor = IEEE80211_HT_MAX_AMPDU_64K
+ *      - Minimum AMPDU spacing = IEEE80211_HT_MPDU_DENSITY_NONE
+ *      - HT Capabilities supported by firmware
+ *      - MCS information, Rx mask = 0xff
+ *      - MCD information, Tx parameters = IEEE80211_HT_MCS_TX_DEFINED (0x01)
+ */
+static void
+mwifiex_setup_ht_caps(struct ieee80211_sta_ht_cap *ht_info,
+                     struct mwifiex_private *priv)
+{
+       int rx_mcs_supp;
+       struct ieee80211_mcs_info mcs_set;
+       u8 *mcs = (u8 *)&mcs_set;
+       struct mwifiex_adapter *adapter = priv->adapter;
+
+       ht_info->ht_supported = true;
+       ht_info->ampdu_factor = IEEE80211_HT_MAX_AMPDU_64K;
+       ht_info->ampdu_density = IEEE80211_HT_MPDU_DENSITY_NONE;
+
+       memset(&ht_info->mcs, 0, sizeof(ht_info->mcs));
+
+       /* Fill HT capability information */
+       if (ISSUPP_CHANWIDTH40(adapter->hw_dot_11n_dev_cap))
+               ht_info->cap |= IEEE80211_HT_CAP_SUP_WIDTH_20_40;
+       else
+               ht_info->cap &= ~IEEE80211_HT_CAP_SUP_WIDTH_20_40;
+
+       if (ISSUPP_SHORTGI20(adapter->hw_dot_11n_dev_cap))
+               ht_info->cap |= IEEE80211_HT_CAP_SGI_20;
+       else
+               ht_info->cap &= ~IEEE80211_HT_CAP_SGI_20;
+
+       if (ISSUPP_SHORTGI40(adapter->hw_dot_11n_dev_cap))
+               ht_info->cap |= IEEE80211_HT_CAP_SGI_40;
+       else
+               ht_info->cap &= ~IEEE80211_HT_CAP_SGI_40;
+
+       if (adapter->user_dev_mcs_support == HT_STREAM_2X2)
+               ht_info->cap |= 3 << IEEE80211_HT_CAP_RX_STBC_SHIFT;
+       else
+               ht_info->cap |= 1 << IEEE80211_HT_CAP_RX_STBC_SHIFT;
+
+       if (ISSUPP_TXSTBC(adapter->hw_dot_11n_dev_cap))
+               ht_info->cap |= IEEE80211_HT_CAP_TX_STBC;
+       else
+               ht_info->cap &= ~IEEE80211_HT_CAP_TX_STBC;
+
+       if (ISSUPP_GREENFIELD(adapter->hw_dot_11n_dev_cap))
+               ht_info->cap |= IEEE80211_HT_CAP_GRN_FLD;
+       else
+               ht_info->cap &= ~IEEE80211_HT_CAP_GRN_FLD;
+
+       if (ISENABLED_40MHZ_INTOLERANT(adapter->hw_dot_11n_dev_cap))
+               ht_info->cap |= IEEE80211_HT_CAP_40MHZ_INTOLERANT;
+       else
+               ht_info->cap &= ~IEEE80211_HT_CAP_40MHZ_INTOLERANT;
+
+       if (ISSUPP_RXLDPC(adapter->hw_dot_11n_dev_cap))
+               ht_info->cap |= IEEE80211_HT_CAP_LDPC_CODING;
+       else
+               ht_info->cap &= ~IEEE80211_HT_CAP_LDPC_CODING;
+
+       ht_info->cap &= ~IEEE80211_HT_CAP_MAX_AMSDU;
+       ht_info->cap |= IEEE80211_HT_CAP_SM_PS;
+
+       rx_mcs_supp = GET_RXMCSSUPP(adapter->user_dev_mcs_support);
+       /* Set MCS for 1x1/2x2 */
+       memset(mcs, 0xff, rx_mcs_supp);
+       /* Clear all the other values */
+       memset(&mcs[rx_mcs_supp], 0,
+              sizeof(struct ieee80211_mcs_info) - rx_mcs_supp);
+       if (priv->bss_mode == NL80211_IFTYPE_STATION ||
+           ISSUPP_CHANWIDTH40(adapter->hw_dot_11n_dev_cap))
+               /* Set MCS32 for infra mode or ad-hoc mode with 40MHz support */
+               SETHT_MCS32(mcs_set.rx_mask);
+
+       memcpy((u8 *) &ht_info->mcs, mcs, sizeof(struct ieee80211_mcs_info));
+
+       ht_info->mcs.tx_params = IEEE80211_HT_MCS_TX_DEFINED;
+}
+
+/*
+ *  create a new virtual interface with the given name and name assign type
+ */
+struct wireless_dev *mwifiex_add_virtual_intf(struct wiphy *wiphy,
+                                             const char *name,
+                                             unsigned char name_assign_type,
+                                             enum nl80211_iftype type,
+                                             u32 *flags,
+                                             struct vif_params *params)
+{
+       struct mwifiex_adapter *adapter = mwifiex_cfg80211_get_adapter(wiphy);
+       struct mwifiex_private *priv;
+       struct net_device *dev;
+       void *mdev_priv;
+
+       if (!adapter)
+               return ERR_PTR(-EFAULT);
+
+       switch (type) {
+       case NL80211_IFTYPE_UNSPECIFIED:
+       case NL80211_IFTYPE_STATION:
+       case NL80211_IFTYPE_ADHOC:
+               if (adapter->curr_iface_comb.sta_intf ==
+                   adapter->iface_limit.sta_intf) {
+                       mwifiex_dbg(adapter, ERROR,
+                                   "cannot create multiple sta/adhoc ifaces\n");
+                       return ERR_PTR(-EINVAL);
+               }
+
+               priv = mwifiex_get_unused_priv(adapter);
+               if (!priv) {
+                       mwifiex_dbg(adapter, ERROR,
+                                   "could not get free private struct\n");
+                       return ERR_PTR(-EFAULT);
+               }
+
+               priv->wdev.wiphy = wiphy;
+               priv->wdev.iftype = NL80211_IFTYPE_STATION;
+
+               if (type == NL80211_IFTYPE_UNSPECIFIED)
+                       priv->bss_mode = NL80211_IFTYPE_STATION;
+               else
+                       priv->bss_mode = type;
+
+               priv->bss_type = MWIFIEX_BSS_TYPE_STA;
+               priv->frame_type = MWIFIEX_DATA_FRAME_TYPE_ETH_II;
+               priv->bss_priority = 0;
+               priv->bss_role = MWIFIEX_BSS_ROLE_STA;
+               priv->bss_num = adapter->curr_iface_comb.sta_intf;
+
+               break;
+       case NL80211_IFTYPE_AP:
+               if (adapter->curr_iface_comb.uap_intf ==
+                   adapter->iface_limit.uap_intf) {
+                       mwifiex_dbg(adapter, ERROR,
+                                   "cannot create multiple AP ifaces\n");
+                       return ERR_PTR(-EINVAL);
+               }
+
+               priv = mwifiex_get_unused_priv(adapter);
+               if (!priv) {
+                       mwifiex_dbg(adapter, ERROR,
+                                   "could not get free private struct\n");
+                       return ERR_PTR(-EFAULT);
+               }
+
+               priv->wdev.wiphy = wiphy;
+               priv->wdev.iftype = NL80211_IFTYPE_AP;
+
+               priv->bss_type = MWIFIEX_BSS_TYPE_UAP;
+               priv->frame_type = MWIFIEX_DATA_FRAME_TYPE_ETH_II;
+               priv->bss_priority = 0;
+               priv->bss_role = MWIFIEX_BSS_ROLE_UAP;
+               priv->bss_started = 0;
+               priv->bss_num = adapter->curr_iface_comb.uap_intf;
+               priv->bss_mode = type;
+
+               break;
+       case NL80211_IFTYPE_P2P_CLIENT:
+               if (adapter->curr_iface_comb.p2p_intf ==
+                   adapter->iface_limit.p2p_intf) {
+                       mwifiex_dbg(adapter, ERROR,
+                                   "cannot create multiple P2P ifaces\n");
+                       return ERR_PTR(-EINVAL);
+               }
+
+               priv = mwifiex_get_unused_priv(adapter);
+               if (!priv) {
+                       mwifiex_dbg(adapter, ERROR,
+                                   "could not get free private struct\n");
+                       return ERR_PTR(-EFAULT);
+               }
+
+               priv->wdev.wiphy = wiphy;
+               /* At start-up, wpa_supplicant tries to change the interface
+                * to NL80211_IFTYPE_STATION if it is not managed mode.
+                */
+               priv->wdev.iftype = NL80211_IFTYPE_P2P_CLIENT;
+               priv->bss_mode = NL80211_IFTYPE_P2P_CLIENT;
+
+               /* Setting bss_type to P2P tells firmware that this interface
+                * is receiving P2P peers found during find phase and doing
+                * action frame handshake.
+                */
+               priv->bss_type = MWIFIEX_BSS_TYPE_P2P;
+
+               priv->frame_type = MWIFIEX_DATA_FRAME_TYPE_ETH_II;
+               priv->bss_priority = MWIFIEX_BSS_ROLE_STA;
+               priv->bss_role = MWIFIEX_BSS_ROLE_STA;
+               priv->bss_started = 0;
+               priv->bss_num = adapter->curr_iface_comb.p2p_intf;
+
+               if (mwifiex_cfg80211_init_p2p_client(priv)) {
+                       memset(&priv->wdev, 0, sizeof(priv->wdev));
+                       priv->wdev.iftype = NL80211_IFTYPE_UNSPECIFIED;
+                       return ERR_PTR(-EFAULT);
+               }
+
+               break;
+       default:
+               mwifiex_dbg(adapter, ERROR, "type not supported\n");
+               return ERR_PTR(-EINVAL);
+       }
+
+       dev = alloc_netdev_mqs(sizeof(struct mwifiex_private *), name,
+                              name_assign_type, ether_setup,
+                              IEEE80211_NUM_ACS, 1);
+       if (!dev) {
+               mwifiex_dbg(adapter, ERROR,
+                           "no memory available for netdevice\n");
+               memset(&priv->wdev, 0, sizeof(priv->wdev));
+               priv->wdev.iftype = NL80211_IFTYPE_UNSPECIFIED;
+               priv->bss_mode = NL80211_IFTYPE_UNSPECIFIED;
+               return ERR_PTR(-ENOMEM);
+       }
+
+       mwifiex_init_priv_params(priv, dev);
+       priv->netdev = dev;
+
+       mwifiex_setup_ht_caps(&wiphy->bands[IEEE80211_BAND_2GHZ]->ht_cap, priv);
+       if (adapter->is_hw_11ac_capable)
+               mwifiex_setup_vht_caps(
+                       &wiphy->bands[IEEE80211_BAND_2GHZ]->vht_cap, priv);
+
+       if (adapter->config_bands & BAND_A)
+               mwifiex_setup_ht_caps(
+                       &wiphy->bands[IEEE80211_BAND_5GHZ]->ht_cap, priv);
+
+       if ((adapter->config_bands & BAND_A) && adapter->is_hw_11ac_capable)
+               mwifiex_setup_vht_caps(
+                       &wiphy->bands[IEEE80211_BAND_5GHZ]->vht_cap, priv);
+
+       dev_net_set(dev, wiphy_net(wiphy));
+       dev->ieee80211_ptr = &priv->wdev;
+       dev->ieee80211_ptr->iftype = priv->bss_mode;
+       memcpy(dev->dev_addr, wiphy->perm_addr, ETH_ALEN);
+       SET_NETDEV_DEV(dev, wiphy_dev(wiphy));
+
+       dev->flags |= IFF_BROADCAST | IFF_MULTICAST;
+       dev->watchdog_timeo = MWIFIEX_DEFAULT_WATCHDOG_TIMEOUT;
+       dev->hard_header_len += MWIFIEX_MIN_DATA_HEADER_LEN;
+       dev->ethtool_ops = &mwifiex_ethtool_ops;
+
+       mdev_priv = netdev_priv(dev);
+       *((unsigned long *) mdev_priv) = (unsigned long) priv;
+
+       SET_NETDEV_DEV(dev, adapter->dev);
+
+       /* Register network device */
+       if (register_netdevice(dev)) {
+               mwifiex_dbg(adapter, ERROR,
+                           "cannot register virtual network device\n");
+               free_netdev(dev);
+               priv->bss_mode = NL80211_IFTYPE_UNSPECIFIED;
+               priv->netdev = NULL;
+               memset(&priv->wdev, 0, sizeof(priv->wdev));
+               priv->wdev.iftype = NL80211_IFTYPE_UNSPECIFIED;
+               return ERR_PTR(-EFAULT);
+       }
+
+       priv->dfs_cac_workqueue = alloc_workqueue("MWIFIEX_DFS_CAC%s",
+                                                 WQ_HIGHPRI |
+                                                 WQ_MEM_RECLAIM |
+                                                 WQ_UNBOUND, 1, name);
+       if (!priv->dfs_cac_workqueue) {
+               mwifiex_dbg(adapter, ERROR,
+                           "cannot register virtual network device\n");
+               free_netdev(dev);
+               priv->bss_mode = NL80211_IFTYPE_UNSPECIFIED;
+               priv->netdev = NULL;
+               memset(&priv->wdev, 0, sizeof(priv->wdev));
+               priv->wdev.iftype = NL80211_IFTYPE_UNSPECIFIED;
+               return ERR_PTR(-ENOMEM);
+       }
+
+       INIT_DELAYED_WORK(&priv->dfs_cac_work, mwifiex_dfs_cac_work_queue);
+
+       priv->dfs_chan_sw_workqueue = alloc_workqueue("MWIFIEX_DFS_CHSW%s",
+                                                     WQ_HIGHPRI | WQ_UNBOUND |
+                                                     WQ_MEM_RECLAIM, 1, name);
+       if (!priv->dfs_chan_sw_workqueue) {
+               mwifiex_dbg(adapter, ERROR,
+                           "cannot register virtual network device\n");
+               free_netdev(dev);
+               priv->bss_mode = NL80211_IFTYPE_UNSPECIFIED;
+               priv->netdev = NULL;
+               memset(&priv->wdev, 0, sizeof(priv->wdev));
+               priv->wdev.iftype = NL80211_IFTYPE_UNSPECIFIED;
+               return ERR_PTR(-ENOMEM);
+       }
+
+       INIT_DELAYED_WORK(&priv->dfs_chan_sw_work,
+                         mwifiex_dfs_chan_sw_work_queue);
+
+       sema_init(&priv->async_sem, 1);
+
+       mwifiex_dbg(adapter, INFO,
+                   "info: %s: Marvell 802.11 Adapter\n", dev->name);
+
+#ifdef CONFIG_DEBUG_FS
+       mwifiex_dev_debugfs_init(priv);
+#endif
+
+       switch (type) {
+       case NL80211_IFTYPE_UNSPECIFIED:
+       case NL80211_IFTYPE_STATION:
+       case NL80211_IFTYPE_ADHOC:
+               adapter->curr_iface_comb.sta_intf++;
+               break;
+       case NL80211_IFTYPE_AP:
+               adapter->curr_iface_comb.uap_intf++;
+               break;
+       case NL80211_IFTYPE_P2P_CLIENT:
+               adapter->curr_iface_comb.p2p_intf++;
+               break;
+       default:
+               mwifiex_dbg(adapter, ERROR, "type not supported\n");
+               return ERR_PTR(-EINVAL);
+       }
+
+       return &priv->wdev;
+}
+EXPORT_SYMBOL_GPL(mwifiex_add_virtual_intf);
+
+/*
+ * del_virtual_intf: remove the virtual interface determined by dev
+ */
+int mwifiex_del_virtual_intf(struct wiphy *wiphy, struct wireless_dev *wdev)
+{
+       struct mwifiex_private *priv = mwifiex_netdev_get_priv(wdev->netdev);
+       struct mwifiex_adapter *adapter = priv->adapter;
+       struct sk_buff *skb, *tmp;
+
+#ifdef CONFIG_DEBUG_FS
+       mwifiex_dev_debugfs_remove(priv);
+#endif
+
+       mwifiex_stop_net_dev_queue(priv->netdev, adapter);
+
+       skb_queue_walk_safe(&priv->bypass_txq, skb, tmp)
+               mwifiex_write_data_complete(priv->adapter, skb, 0, -1);
+
+       if (netif_carrier_ok(priv->netdev))
+               netif_carrier_off(priv->netdev);
+
+       if (wdev->netdev->reg_state == NETREG_REGISTERED)
+               unregister_netdevice(wdev->netdev);
+
+       if (priv->dfs_cac_workqueue) {
+               flush_workqueue(priv->dfs_cac_workqueue);
+               destroy_workqueue(priv->dfs_cac_workqueue);
+               priv->dfs_cac_workqueue = NULL;
+       }
+
+       if (priv->dfs_chan_sw_workqueue) {
+               flush_workqueue(priv->dfs_chan_sw_workqueue);
+               destroy_workqueue(priv->dfs_chan_sw_workqueue);
+               priv->dfs_chan_sw_workqueue = NULL;
+       }
+       /* Clear the priv in adapter */
+       priv->netdev->ieee80211_ptr = NULL;
+       priv->netdev = NULL;
+       priv->wdev.iftype = NL80211_IFTYPE_UNSPECIFIED;
+
+       priv->media_connected = false;
+
+       switch (priv->bss_mode) {
+       case NL80211_IFTYPE_UNSPECIFIED:
+       case NL80211_IFTYPE_STATION:
+       case NL80211_IFTYPE_ADHOC:
+               adapter->curr_iface_comb.sta_intf--;
+               break;
+       case NL80211_IFTYPE_AP:
+               adapter->curr_iface_comb.uap_intf--;
+               break;
+       case NL80211_IFTYPE_P2P_CLIENT:
+       case NL80211_IFTYPE_P2P_GO:
+               adapter->curr_iface_comb.p2p_intf--;
+               break;
+       default:
+               mwifiex_dbg(adapter, ERROR,
+                           "del_virtual_intf: type not supported\n");
+               break;
+       }
+
+       priv->bss_mode = NL80211_IFTYPE_UNSPECIFIED;
+
+       if (GET_BSS_ROLE(priv) == MWIFIEX_BSS_ROLE_STA ||
+           GET_BSS_ROLE(priv) == MWIFIEX_BSS_ROLE_UAP)
+               kfree(priv->hist_data);
+
+       return 0;
+}
+EXPORT_SYMBOL_GPL(mwifiex_del_virtual_intf);
+
+static bool
+mwifiex_is_pattern_supported(struct cfg80211_pkt_pattern *pat, s8 *byte_seq,
+                            u8 max_byte_seq)
+{
+       int j, k, valid_byte_cnt = 0;
+       bool dont_care_byte = false;
+
+       for (j = 0; j < DIV_ROUND_UP(pat->pattern_len, 8); j++) {
+               for (k = 0; k < 8; k++) {
+                       if (pat->mask[j] & 1 << k) {
+                               memcpy(byte_seq + valid_byte_cnt,
+                                      &pat->pattern[j * 8 + k], 1);
+                               valid_byte_cnt++;
+                               if (dont_care_byte)
+                                       return false;
+                       } else {
+                               if (valid_byte_cnt)
+                                       dont_care_byte = true;
+                       }
+
+                       if (valid_byte_cnt > max_byte_seq)
+                               return false;
+               }
+       }
+
+       byte_seq[max_byte_seq] = valid_byte_cnt;
+
+       return true;
+}
+
+#ifdef CONFIG_PM
+static void mwifiex_set_auto_arp_mef_entry(struct mwifiex_private *priv,
+                                          struct mwifiex_mef_entry *mef_entry)
+{
+       int i, filt_num = 0, num_ipv4 = 0;
+       struct in_device *in_dev;
+       struct in_ifaddr *ifa;
+       __be32 ips[MWIFIEX_MAX_SUPPORTED_IPADDR];
+       struct mwifiex_adapter *adapter = priv->adapter;
+
+       mef_entry->mode = MEF_MODE_HOST_SLEEP;
+       mef_entry->action = MEF_ACTION_AUTO_ARP;
+
+       /* Enable ARP offload feature */
+       memset(ips, 0, sizeof(ips));
+       for (i = 0; i < MWIFIEX_MAX_BSS_NUM; i++) {
+               if (adapter->priv[i]->netdev) {
+                       in_dev = __in_dev_get_rtnl(adapter->priv[i]->netdev);
+                       if (!in_dev)
+                               continue;
+                       ifa = in_dev->ifa_list;
+                       if (!ifa || !ifa->ifa_local)
+                               continue;
+                       ips[i] = ifa->ifa_local;
+                       num_ipv4++;
+               }
+       }
+
+       for (i = 0; i < num_ipv4; i++) {
+               if (!ips[i])
+                       continue;
+               mef_entry->filter[filt_num].repeat = 1;
+               memcpy(mef_entry->filter[filt_num].byte_seq,
+                      (u8 *)&ips[i], sizeof(ips[i]));
+               mef_entry->filter[filt_num].
+                       byte_seq[MWIFIEX_MEF_MAX_BYTESEQ] =
+                       sizeof(ips[i]);
+               mef_entry->filter[filt_num].offset = 46;
+               mef_entry->filter[filt_num].filt_type = TYPE_EQ;
+               if (filt_num) {
+                       mef_entry->filter[filt_num].filt_action =
+                               TYPE_OR;
+               }
+               filt_num++;
+       }
+
+       mef_entry->filter[filt_num].repeat = 1;
+       mef_entry->filter[filt_num].byte_seq[0] = 0x08;
+       mef_entry->filter[filt_num].byte_seq[1] = 0x06;
+       mef_entry->filter[filt_num].byte_seq[MWIFIEX_MEF_MAX_BYTESEQ] = 2;
+       mef_entry->filter[filt_num].offset = 20;
+       mef_entry->filter[filt_num].filt_type = TYPE_EQ;
+       mef_entry->filter[filt_num].filt_action = TYPE_AND;
+}
+
+static int mwifiex_set_wowlan_mef_entry(struct mwifiex_private *priv,
+                                       struct mwifiex_ds_mef_cfg *mef_cfg,
+                                       struct mwifiex_mef_entry *mef_entry,
+                                       struct cfg80211_wowlan *wowlan)
+{
+       int i, filt_num = 0, ret = 0;
+       bool first_pat = true;
+       u8 byte_seq[MWIFIEX_MEF_MAX_BYTESEQ + 1];
+       const u8 ipv4_mc_mac[] = {0x33, 0x33};
+       const u8 ipv6_mc_mac[] = {0x01, 0x00, 0x5e};
+
+       mef_entry->mode = MEF_MODE_HOST_SLEEP;
+       mef_entry->action = MEF_ACTION_ALLOW_AND_WAKEUP_HOST;
+
+       for (i = 0; i < wowlan->n_patterns; i++) {
+               memset(byte_seq, 0, sizeof(byte_seq));
+               if (!mwifiex_is_pattern_supported(&wowlan->patterns[i],
+                                       byte_seq,
+                                       MWIFIEX_MEF_MAX_BYTESEQ)) {
+                       mwifiex_dbg(priv->adapter, ERROR,
+                                   "Pattern not supported\n");
+                       return -EOPNOTSUPP;
+               }
+
+               if (!wowlan->patterns[i].pkt_offset) {
+                       if (!(byte_seq[0] & 0x01) &&
+                           (byte_seq[MWIFIEX_MEF_MAX_BYTESEQ] == 1)) {
+                               mef_cfg->criteria |= MWIFIEX_CRITERIA_UNICAST;
+                               continue;
+                       } else if (is_broadcast_ether_addr(byte_seq)) {
+                               mef_cfg->criteria |= MWIFIEX_CRITERIA_BROADCAST;
+                               continue;
+                       } else if ((!memcmp(byte_seq, ipv4_mc_mac, 2) &&
+                                   (byte_seq[MWIFIEX_MEF_MAX_BYTESEQ] == 2)) ||
+                                  (!memcmp(byte_seq, ipv6_mc_mac, 3) &&
+                                   (byte_seq[MWIFIEX_MEF_MAX_BYTESEQ] == 3))) {
+                               mef_cfg->criteria |= MWIFIEX_CRITERIA_MULTICAST;
+                               continue;
+                       }
+               }
+               mef_entry->filter[filt_num].repeat = 1;
+               mef_entry->filter[filt_num].offset =
+                       wowlan->patterns[i].pkt_offset;
+               memcpy(mef_entry->filter[filt_num].byte_seq, byte_seq,
+                               sizeof(byte_seq));
+               mef_entry->filter[filt_num].filt_type = TYPE_EQ;
+
+               if (first_pat)
+                       first_pat = false;
+               else
+                       mef_entry->filter[filt_num].filt_action = TYPE_AND;
+
+               filt_num++;
+       }
+
+       if (wowlan->magic_pkt) {
+               mef_cfg->criteria |= MWIFIEX_CRITERIA_UNICAST;
+               mef_entry->filter[filt_num].repeat = 16;
+               memcpy(mef_entry->filter[filt_num].byte_seq, priv->curr_addr,
+                               ETH_ALEN);
+               mef_entry->filter[filt_num].byte_seq[MWIFIEX_MEF_MAX_BYTESEQ] =
+                       ETH_ALEN;
+               mef_entry->filter[filt_num].offset = 28;
+               mef_entry->filter[filt_num].filt_type = TYPE_EQ;
+               if (filt_num)
+                       mef_entry->filter[filt_num].filt_action = TYPE_OR;
+
+               filt_num++;
+               mef_entry->filter[filt_num].repeat = 16;
+               memcpy(mef_entry->filter[filt_num].byte_seq, priv->curr_addr,
+                               ETH_ALEN);
+               mef_entry->filter[filt_num].byte_seq[MWIFIEX_MEF_MAX_BYTESEQ] =
+                       ETH_ALEN;
+               mef_entry->filter[filt_num].offset = 56;
+               mef_entry->filter[filt_num].filt_type = TYPE_EQ;
+               mef_entry->filter[filt_num].filt_action = TYPE_OR;
+       }
+       return ret;
+}
+
+static int mwifiex_set_mef_filter(struct mwifiex_private *priv,
+                                 struct cfg80211_wowlan *wowlan)
+{
+       int ret = 0, num_entries = 1;
+       struct mwifiex_ds_mef_cfg mef_cfg;
+       struct mwifiex_mef_entry *mef_entry;
+
+       if (wowlan->n_patterns || wowlan->magic_pkt)
+               num_entries++;
+
+       mef_entry = kcalloc(num_entries, sizeof(*mef_entry), GFP_KERNEL);
+       if (!mef_entry)
+               return -ENOMEM;
+
+       memset(&mef_cfg, 0, sizeof(mef_cfg));
+       mef_cfg.criteria |= MWIFIEX_CRITERIA_BROADCAST |
+               MWIFIEX_CRITERIA_UNICAST;
+       mef_cfg.num_entries = num_entries;
+       mef_cfg.mef_entry = mef_entry;
+
+       mwifiex_set_auto_arp_mef_entry(priv, &mef_entry[0]);
+
+       if (wowlan->n_patterns || wowlan->magic_pkt) {
+               ret = mwifiex_set_wowlan_mef_entry(priv, &mef_cfg,
+                                                  &mef_entry[1], wowlan);
+               if (ret)
+                       goto err;
+       }
+
+       if (!mef_cfg.criteria)
+               mef_cfg.criteria = MWIFIEX_CRITERIA_BROADCAST |
+                       MWIFIEX_CRITERIA_UNICAST |
+                       MWIFIEX_CRITERIA_MULTICAST;
+
+       ret = mwifiex_send_cmd(priv, HostCmd_CMD_MEF_CFG,
+                       HostCmd_ACT_GEN_SET, 0,
+                       &mef_cfg, true);
+
+err:
+       kfree(mef_entry);
+       return ret;
+}
+
+static int mwifiex_cfg80211_suspend(struct wiphy *wiphy,
+                                   struct cfg80211_wowlan *wowlan)
+{
+       struct mwifiex_adapter *adapter = mwifiex_cfg80211_get_adapter(wiphy);
+       struct mwifiex_ds_hs_cfg hs_cfg;
+       int i, ret = 0;
+       struct mwifiex_private *priv;
+
+       for (i = 0; i < adapter->priv_num; i++) {
+               priv = adapter->priv[i];
+               mwifiex_abort_cac(priv);
+       }
+
+       mwifiex_cancel_all_pending_cmd(adapter);
+
+       if (!wowlan) {
+               mwifiex_dbg(adapter, ERROR,
+                           "None of the WOWLAN triggers enabled\n");
+               return 0;
+       }
+
+       priv = mwifiex_get_priv(adapter, MWIFIEX_BSS_ROLE_STA);
+
+       if (!priv->media_connected) {
+               mwifiex_dbg(adapter, ERROR,
+                           "Can not configure WOWLAN in disconnected state\n");
+               return 0;
+       }
+
+       ret = mwifiex_set_mef_filter(priv, wowlan);
+       if (ret) {
+               mwifiex_dbg(adapter, ERROR, "Failed to set MEF filter\n");
+               return ret;
+       }
+
+       if (wowlan->disconnect) {
+               memset(&hs_cfg, 0, sizeof(hs_cfg));
+               hs_cfg.is_invoke_hostcmd = false;
+               hs_cfg.conditions = HS_CFG_COND_MAC_EVENT;
+               hs_cfg.gpio = HS_CFG_GPIO_DEF;
+               hs_cfg.gap = HS_CFG_GAP_DEF;
+               ret = mwifiex_set_hs_params(priv, HostCmd_ACT_GEN_SET,
+                                           MWIFIEX_SYNC_CMD, &hs_cfg);
+               if (ret) {
+                       mwifiex_dbg(adapter, ERROR,
+                                   "Failed to set HS params\n");
+                       return ret;
+               }
+       }
+
+       return ret;
+}
+
+static int mwifiex_cfg80211_resume(struct wiphy *wiphy)
+{
+       return 0;
+}
+
+static void mwifiex_cfg80211_set_wakeup(struct wiphy *wiphy,
+                                      bool enabled)
+{
+       struct mwifiex_adapter *adapter = mwifiex_cfg80211_get_adapter(wiphy);
+
+       device_set_wakeup_enable(adapter->dev, enabled);
+}
+#endif
+
+static int mwifiex_get_coalesce_pkt_type(u8 *byte_seq)
+{
+       const u8 ipv4_mc_mac[] = {0x33, 0x33};
+       const u8 ipv6_mc_mac[] = {0x01, 0x00, 0x5e};
+       const u8 bc_mac[] = {0xff, 0xff, 0xff, 0xff};
+
+       if ((byte_seq[0] & 0x01) &&
+           (byte_seq[MWIFIEX_COALESCE_MAX_BYTESEQ] == 1))
+               return PACKET_TYPE_UNICAST;
+       else if (!memcmp(byte_seq, bc_mac, 4))
+               return PACKET_TYPE_BROADCAST;
+       else if ((!memcmp(byte_seq, ipv4_mc_mac, 2) &&
+                 byte_seq[MWIFIEX_COALESCE_MAX_BYTESEQ] == 2) ||
+                (!memcmp(byte_seq, ipv6_mc_mac, 3) &&
+                 byte_seq[MWIFIEX_COALESCE_MAX_BYTESEQ] == 3))
+               return PACKET_TYPE_MULTICAST;
+
+       return 0;
+}
+
+static int
+mwifiex_fill_coalesce_rule_info(struct mwifiex_private *priv,
+                               struct cfg80211_coalesce_rules *crule,
+                               struct mwifiex_coalesce_rule *mrule)
+{
+       u8 byte_seq[MWIFIEX_COALESCE_MAX_BYTESEQ + 1];
+       struct filt_field_param *param;
+       int i;
+
+       mrule->max_coalescing_delay = crule->delay;
+
+       param = mrule->params;
+
+       for (i = 0; i < crule->n_patterns; i++) {
+               memset(byte_seq, 0, sizeof(byte_seq));
+               if (!mwifiex_is_pattern_supported(&crule->patterns[i],
+                                                 byte_seq,
+                                               MWIFIEX_COALESCE_MAX_BYTESEQ)) {
+                       mwifiex_dbg(priv->adapter, ERROR,
+                                   "Pattern not supported\n");
+                       return -EOPNOTSUPP;
+               }
+
+               if (!crule->patterns[i].pkt_offset) {
+                       u8 pkt_type;
+
+                       pkt_type = mwifiex_get_coalesce_pkt_type(byte_seq);
+                       if (pkt_type && mrule->pkt_type) {
+                               mwifiex_dbg(priv->adapter, ERROR,
+                                           "Multiple packet types not allowed\n");
+                               return -EOPNOTSUPP;
+                       } else if (pkt_type) {
+                               mrule->pkt_type = pkt_type;
+                               continue;
+                       }
+               }
+
+               if (crule->condition == NL80211_COALESCE_CONDITION_MATCH)
+                       param->operation = RECV_FILTER_MATCH_TYPE_EQ;
+               else
+                       param->operation = RECV_FILTER_MATCH_TYPE_NE;
+
+               param->operand_len = byte_seq[MWIFIEX_COALESCE_MAX_BYTESEQ];
+               memcpy(param->operand_byte_stream, byte_seq,
+                      param->operand_len);
+               param->offset = crule->patterns[i].pkt_offset;
+               param++;
+
+               mrule->num_of_fields++;
+       }
+
+       if (!mrule->pkt_type) {
+               mwifiex_dbg(priv->adapter, ERROR,
+                           "Packet type can not be determined\n");
+               return -EOPNOTSUPP;
+       }
+
+       return 0;
+}
+
+static int mwifiex_cfg80211_set_coalesce(struct wiphy *wiphy,
+                                        struct cfg80211_coalesce *coalesce)
+{
+       struct mwifiex_adapter *adapter = mwifiex_cfg80211_get_adapter(wiphy);
+       int i, ret;
+       struct mwifiex_ds_coalesce_cfg coalesce_cfg;
+       struct mwifiex_private *priv =
+                       mwifiex_get_priv(adapter, MWIFIEX_BSS_ROLE_STA);
+
+       memset(&coalesce_cfg, 0, sizeof(coalesce_cfg));
+       if (!coalesce) {
+               mwifiex_dbg(adapter, WARN,
+                           "Disable coalesce and reset all previous rules\n");
+               return mwifiex_send_cmd(priv, HostCmd_CMD_COALESCE_CFG,
+                                       HostCmd_ACT_GEN_SET, 0,
+                                       &coalesce_cfg, true);
+       }
+
+       coalesce_cfg.num_of_rules = coalesce->n_rules;
+       for (i = 0; i < coalesce->n_rules; i++) {
+               ret = mwifiex_fill_coalesce_rule_info(priv, &coalesce->rules[i],
+                                                     &coalesce_cfg.rule[i]);
+               if (ret) {
+                       mwifiex_dbg(adapter, ERROR,
+                                   "Recheck the patterns provided for rule %d\n",
+                               i + 1);
+                       return ret;
+               }
+       }
+
+       return mwifiex_send_cmd(priv, HostCmd_CMD_COALESCE_CFG,
+                               HostCmd_ACT_GEN_SET, 0, &coalesce_cfg, true);
+}
+
+/* cfg80211 ops handler for tdls_mgmt.
+ * Function prepares TDLS action frame packets and forwards them to FW
+ */
+static int
+mwifiex_cfg80211_tdls_mgmt(struct wiphy *wiphy, struct net_device *dev,
+                          const u8 *peer, u8 action_code, u8 dialog_token,
+                          u16 status_code, u32 peer_capability,
+                          bool initiator, const u8 *extra_ies,
+                          size_t extra_ies_len)
+{
+       struct mwifiex_private *priv = mwifiex_netdev_get_priv(dev);
+       int ret;
+
+       if (!(wiphy->flags & WIPHY_FLAG_SUPPORTS_TDLS))
+               return -ENOTSUPP;
+
+       /* make sure we are in station mode and connected */
+       if (!(priv->bss_type == MWIFIEX_BSS_TYPE_STA && priv->media_connected))
+               return -ENOTSUPP;
+
+       switch (action_code) {
+       case WLAN_TDLS_SETUP_REQUEST:
+               mwifiex_dbg(priv->adapter, MSG,
+                           "Send TDLS Setup Request to %pM status_code=%d\n",
+                           peer, status_code);
+               mwifiex_add_auto_tdls_peer(priv, peer);
+               ret = mwifiex_send_tdls_data_frame(priv, peer, action_code,
+                                                  dialog_token, status_code,
+                                                  extra_ies, extra_ies_len);
+               break;
+       case WLAN_TDLS_SETUP_RESPONSE:
+               mwifiex_add_auto_tdls_peer(priv, peer);
+               mwifiex_dbg(priv->adapter, MSG,
+                           "Send TDLS Setup Response to %pM status_code=%d\n",
+                           peer, status_code);
+               ret = mwifiex_send_tdls_data_frame(priv, peer, action_code,
+                                                  dialog_token, status_code,
+                                                  extra_ies, extra_ies_len);
+               break;
+       case WLAN_TDLS_SETUP_CONFIRM:
+               mwifiex_dbg(priv->adapter, MSG,
+                           "Send TDLS Confirm to %pM status_code=%d\n", peer,
+                           status_code);
+               ret = mwifiex_send_tdls_data_frame(priv, peer, action_code,
+                                                  dialog_token, status_code,
+                                                  extra_ies, extra_ies_len);
+               break;
+       case WLAN_TDLS_TEARDOWN:
+               mwifiex_dbg(priv->adapter, MSG,
+                           "Send TDLS Tear down to %pM\n", peer);
+               ret = mwifiex_send_tdls_data_frame(priv, peer, action_code,
+                                                  dialog_token, status_code,
+                                                  extra_ies, extra_ies_len);
+               break;
+       case WLAN_TDLS_DISCOVERY_REQUEST:
+               mwifiex_dbg(priv->adapter, MSG,
+                           "Send TDLS Discovery Request to %pM\n", peer);
+               ret = mwifiex_send_tdls_data_frame(priv, peer, action_code,
+                                                  dialog_token, status_code,
+                                                  extra_ies, extra_ies_len);
+               break;
+       case WLAN_PUB_ACTION_TDLS_DISCOVER_RES:
+               mwifiex_dbg(priv->adapter, MSG,
+                           "Send TDLS Discovery Response to %pM\n", peer);
+               ret = mwifiex_send_tdls_action_frame(priv, peer, action_code,
+                                                  dialog_token, status_code,
+                                                  extra_ies, extra_ies_len);
+               break;
+       default:
+               mwifiex_dbg(priv->adapter, ERROR,
+                           "Unknown TDLS mgmt/action frame %pM\n", peer);
+               ret = -EINVAL;
+               break;
+       }
+
+       return ret;
+}
+
+static int
+mwifiex_cfg80211_tdls_oper(struct wiphy *wiphy, struct net_device *dev,
+                          const u8 *peer, enum nl80211_tdls_operation action)
+{
+       struct mwifiex_private *priv = mwifiex_netdev_get_priv(dev);
+
+       if (!(wiphy->flags & WIPHY_FLAG_SUPPORTS_TDLS) ||
+           !(wiphy->flags & WIPHY_FLAG_TDLS_EXTERNAL_SETUP))
+               return -ENOTSUPP;
+
+       /* make sure we are in station mode and connected */
+       if (!(priv->bss_type == MWIFIEX_BSS_TYPE_STA && priv->media_connected))
+               return -ENOTSUPP;
+
+       mwifiex_dbg(priv->adapter, MSG,
+                   "TDLS peer=%pM, oper=%d\n", peer, action);
+
+       switch (action) {
+       case NL80211_TDLS_ENABLE_LINK:
+               action = MWIFIEX_TDLS_ENABLE_LINK;
+               break;
+       case NL80211_TDLS_DISABLE_LINK:
+               action = MWIFIEX_TDLS_DISABLE_LINK;
+               break;
+       case NL80211_TDLS_TEARDOWN:
+               /* shouldn't happen!*/
+               mwifiex_dbg(priv->adapter, ERROR,
+                           "tdls_oper: teardown from driver not supported\n");
+               return -EINVAL;
+       case NL80211_TDLS_SETUP:
+               /* shouldn't happen!*/
+               mwifiex_dbg(priv->adapter, ERROR,
+                           "tdls_oper: setup from driver not supported\n");
+               return -EINVAL;
+       case NL80211_TDLS_DISCOVERY_REQ:
+               /* shouldn't happen!*/
+               mwifiex_dbg(priv->adapter, ERROR,
+                           "tdls_oper: discovery from driver not supported\n");
+               return -EINVAL;
+       default:
+               mwifiex_dbg(priv->adapter, ERROR,
+                           "tdls_oper: operation not supported\n");
+               return -ENOTSUPP;
+       }
+
+       return mwifiex_tdls_oper(priv, peer, action);
+}
+
+static int
+mwifiex_cfg80211_tdls_chan_switch(struct wiphy *wiphy, struct net_device *dev,
+                                 const u8 *addr, u8 oper_class,
+                                 struct cfg80211_chan_def *chandef)
+{
+       struct mwifiex_sta_node *sta_ptr;
+       unsigned long flags;
+       u16 chan;
+       u8 second_chan_offset, band;
+       struct mwifiex_private *priv = mwifiex_netdev_get_priv(dev);
+
+       spin_lock_irqsave(&priv->sta_list_spinlock, flags);
+       sta_ptr = mwifiex_get_sta_entry(priv, addr);
+       spin_unlock_irqrestore(&priv->sta_list_spinlock, flags);
+
+       if (!sta_ptr) {
+               wiphy_err(wiphy, "%s: Invalid TDLS peer %pM\n",
+                         __func__, addr);
+               return -ENOENT;
+       }
+
+       if (!(sta_ptr->tdls_cap.extcap.ext_capab[3] &
+             WLAN_EXT_CAPA4_TDLS_CHAN_SWITCH)) {
+               wiphy_err(wiphy, "%pM do not support tdls cs\n", addr);
+               return -ENOENT;
+       }
+
+       if (sta_ptr->tdls_status == TDLS_CHAN_SWITCHING ||
+           sta_ptr->tdls_status == TDLS_IN_OFF_CHAN) {
+               wiphy_err(wiphy, "channel switch is running, abort request\n");
+               return -EALREADY;
+       }
+
+       chan = chandef->chan->hw_value;
+       second_chan_offset = mwifiex_get_sec_chan_offset(chan);
+       band = chandef->chan->band;
+       mwifiex_start_tdls_cs(priv, addr, chan, second_chan_offset, band);
+
+       return 0;
+}
+
+static void
+mwifiex_cfg80211_tdls_cancel_chan_switch(struct wiphy *wiphy,
+                                        struct net_device *dev,
+                                        const u8 *addr)
+{
+       struct mwifiex_sta_node *sta_ptr;
+       unsigned long flags;
+       struct mwifiex_private *priv = mwifiex_netdev_get_priv(dev);
+
+       spin_lock_irqsave(&priv->sta_list_spinlock, flags);
+       sta_ptr = mwifiex_get_sta_entry(priv, addr);
+       spin_unlock_irqrestore(&priv->sta_list_spinlock, flags);
+
+       if (!sta_ptr) {
+               wiphy_err(wiphy, "%s: Invalid TDLS peer %pM\n",
+                         __func__, addr);
+       } else if (!(sta_ptr->tdls_status == TDLS_CHAN_SWITCHING ||
+                    sta_ptr->tdls_status == TDLS_IN_BASE_CHAN ||
+                    sta_ptr->tdls_status == TDLS_IN_OFF_CHAN)) {
+               wiphy_err(wiphy, "tdls chan switch not initialize by %pM\n",
+                         addr);
+       } else
+               mwifiex_stop_tdls_cs(priv, addr);
+}
+
+static int
+mwifiex_cfg80211_add_station(struct wiphy *wiphy, struct net_device *dev,
+                            const u8 *mac, struct station_parameters *params)
+{
+       struct mwifiex_private *priv = mwifiex_netdev_get_priv(dev);
+
+       if (!(params->sta_flags_set & BIT(NL80211_STA_FLAG_TDLS_PEER)))
+               return -ENOTSUPP;
+
+       /* make sure we are in station mode and connected */
+       if ((priv->bss_type != MWIFIEX_BSS_TYPE_STA) || !priv->media_connected)
+               return -ENOTSUPP;
+
+       return mwifiex_tdls_oper(priv, mac, MWIFIEX_TDLS_CREATE_LINK);
+}
+
+static int
+mwifiex_cfg80211_channel_switch(struct wiphy *wiphy, struct net_device *dev,
+                               struct cfg80211_csa_settings *params)
+{
+       struct ieee_types_header *chsw_ie;
+       struct ieee80211_channel_sw_ie *channel_sw;
+       int chsw_msec;
+       struct mwifiex_private *priv = mwifiex_netdev_get_priv(dev);
+
+       if (priv->adapter->scan_processing) {
+               mwifiex_dbg(priv->adapter, ERROR,
+                           "radar detection: scan in process...\n");
+               return -EBUSY;
+       }
+
+       if (priv->wdev.cac_started)
+               return -EBUSY;
+
+       if (cfg80211_chandef_identical(&params->chandef,
+                                      &priv->dfs_chandef))
+               return -EINVAL;
+
+       chsw_ie = (void *)cfg80211_find_ie(WLAN_EID_CHANNEL_SWITCH,
+                                          params->beacon_csa.tail,
+                                          params->beacon_csa.tail_len);
+       if (!chsw_ie) {
+               mwifiex_dbg(priv->adapter, ERROR,
+                           "Could not parse channel switch announcement IE\n");
+               return -EINVAL;
+       }
+
+       channel_sw = (void *)(chsw_ie + 1);
+       if (channel_sw->mode) {
+               if (netif_carrier_ok(priv->netdev))
+                       netif_carrier_off(priv->netdev);
+               mwifiex_stop_net_dev_queue(priv->netdev, priv->adapter);
+       }
+
+       if (mwifiex_del_mgmt_ies(priv))
+               mwifiex_dbg(priv->adapter, ERROR,
+                           "Failed to delete mgmt IEs!\n");
+
+       if (mwifiex_set_mgmt_ies(priv, &params->beacon_csa)) {
+               mwifiex_dbg(priv->adapter, ERROR,
+                           "%s: setting mgmt ies failed\n", __func__);
+               return -EFAULT;
+       }
+
+       memcpy(&priv->dfs_chandef, &params->chandef, sizeof(priv->dfs_chandef));
+       memcpy(&priv->beacon_after, &params->beacon_after,
+              sizeof(priv->beacon_after));
+
+       chsw_msec = max(channel_sw->count * priv->bss_cfg.beacon_period, 100);
+       queue_delayed_work(priv->dfs_chan_sw_workqueue, &priv->dfs_chan_sw_work,
+                          msecs_to_jiffies(chsw_msec));
+       return 0;
+}
+
+static int mwifiex_cfg80211_get_channel(struct wiphy *wiphy,
+                                       struct wireless_dev *wdev,
+                                       struct cfg80211_chan_def *chandef)
+{
+       struct mwifiex_private *priv = mwifiex_netdev_get_priv(wdev->netdev);
+       struct mwifiex_bssdescriptor *curr_bss;
+       struct ieee80211_channel *chan;
+       u8 second_chan_offset;
+       enum nl80211_channel_type chan_type;
+       enum ieee80211_band band;
+       int freq;
+       int ret = -ENODATA;
+
+       if (GET_BSS_ROLE(priv) == MWIFIEX_BSS_ROLE_UAP &&
+           cfg80211_chandef_valid(&priv->bss_chandef)) {
+               *chandef = priv->bss_chandef;
+               ret = 0;
+       } else if (priv->media_connected) {
+               curr_bss = &priv->curr_bss_params.bss_descriptor;
+               band = mwifiex_band_to_radio_type(priv->curr_bss_params.band);
+               freq = ieee80211_channel_to_frequency(curr_bss->channel, band);
+               chan = ieee80211_get_channel(wiphy, freq);
+
+               if (curr_bss->bcn_ht_oper) {
+                       second_chan_offset = curr_bss->bcn_ht_oper->ht_param &
+                                       IEEE80211_HT_PARAM_CHA_SEC_OFFSET;
+                       chan_type = mwifiex_sec_chan_offset_to_chan_type
+                                                       (second_chan_offset);
+                       cfg80211_chandef_create(chandef, chan, chan_type);
+               } else {
+                       cfg80211_chandef_create(chandef, chan,
+                                               NL80211_CHAN_NO_HT);
+               }
+               ret = 0;
+       }
+
+       return ret;
+}
+
+static int
+mwifiex_cfg80211_start_radar_detection(struct wiphy *wiphy,
+                                      struct net_device *dev,
+                                      struct cfg80211_chan_def *chandef,
+                                      u32 cac_time_ms)
+{
+       struct mwifiex_private *priv = mwifiex_netdev_get_priv(dev);
+       struct mwifiex_radar_params radar_params;
+
+       if (priv->adapter->scan_processing) {
+               mwifiex_dbg(priv->adapter, ERROR,
+                           "radar detection: scan already in process...\n");
+               return -EBUSY;
+       }
+
+       if (!mwifiex_is_11h_active(priv)) {
+               mwifiex_dbg(priv->adapter, INFO,
+                           "Enable 11h extensions in FW\n");
+               if (mwifiex_11h_activate(priv, true)) {
+                       mwifiex_dbg(priv->adapter, ERROR,
+                                   "Failed to activate 11h extensions!!");
+                       return -1;
+               }
+               priv->state_11h.is_11h_active = true;
+       }
+
+       memset(&radar_params, 0, sizeof(struct mwifiex_radar_params));
+       radar_params.chandef = chandef;
+       radar_params.cac_time_ms = cac_time_ms;
+
+       memcpy(&priv->dfs_chandef, chandef, sizeof(priv->dfs_chandef));
+
+       if (mwifiex_send_cmd(priv, HostCmd_CMD_CHAN_REPORT_REQUEST,
+                            HostCmd_ACT_GEN_SET, 0, &radar_params, true))
+               return -1;
+
+       queue_delayed_work(priv->dfs_cac_workqueue, &priv->dfs_cac_work,
+                          msecs_to_jiffies(cac_time_ms));
+       return 0;
+}
+
+static int
+mwifiex_cfg80211_change_station(struct wiphy *wiphy, struct net_device *dev,
+                               const u8 *mac,
+                               struct station_parameters *params)
+{
+       int ret;
+       struct mwifiex_private *priv = mwifiex_netdev_get_priv(dev);
+
+       /* we support change_station handler only for TDLS peers*/
+       if (!(params->sta_flags_set & BIT(NL80211_STA_FLAG_TDLS_PEER)))
+               return -ENOTSUPP;
+
+       /* make sure we are in station mode and connected */
+       if ((priv->bss_type != MWIFIEX_BSS_TYPE_STA) || !priv->media_connected)
+               return -ENOTSUPP;
+
+       priv->sta_params = params;
+
+       ret = mwifiex_tdls_oper(priv, mac, MWIFIEX_TDLS_CONFIG_LINK);
+       priv->sta_params = NULL;
+
+       return ret;
+}
+
+/* station cfg80211 operations */
+static struct cfg80211_ops mwifiex_cfg80211_ops = {
+       .add_virtual_intf = mwifiex_add_virtual_intf,
+       .del_virtual_intf = mwifiex_del_virtual_intf,
+       .change_virtual_intf = mwifiex_cfg80211_change_virtual_intf,
+       .scan = mwifiex_cfg80211_scan,
+       .connect = mwifiex_cfg80211_connect,
+       .disconnect = mwifiex_cfg80211_disconnect,
+       .get_station = mwifiex_cfg80211_get_station,
+       .dump_station = mwifiex_cfg80211_dump_station,
+       .dump_survey = mwifiex_cfg80211_dump_survey,
+       .set_wiphy_params = mwifiex_cfg80211_set_wiphy_params,
+       .join_ibss = mwifiex_cfg80211_join_ibss,
+       .leave_ibss = mwifiex_cfg80211_leave_ibss,
+       .add_key = mwifiex_cfg80211_add_key,
+       .del_key = mwifiex_cfg80211_del_key,
+       .mgmt_tx = mwifiex_cfg80211_mgmt_tx,
+       .mgmt_frame_register = mwifiex_cfg80211_mgmt_frame_register,
+       .remain_on_channel = mwifiex_cfg80211_remain_on_channel,
+       .cancel_remain_on_channel = mwifiex_cfg80211_cancel_remain_on_channel,
+       .set_default_key = mwifiex_cfg80211_set_default_key,
+       .set_power_mgmt = mwifiex_cfg80211_set_power_mgmt,
+       .set_tx_power = mwifiex_cfg80211_set_tx_power,
+       .set_bitrate_mask = mwifiex_cfg80211_set_bitrate_mask,
+       .start_ap = mwifiex_cfg80211_start_ap,
+       .stop_ap = mwifiex_cfg80211_stop_ap,
+       .change_beacon = mwifiex_cfg80211_change_beacon,
+       .set_cqm_rssi_config = mwifiex_cfg80211_set_cqm_rssi_config,
+       .set_antenna = mwifiex_cfg80211_set_antenna,
+       .del_station = mwifiex_cfg80211_del_station,
+#ifdef CONFIG_PM
+       .suspend = mwifiex_cfg80211_suspend,
+       .resume = mwifiex_cfg80211_resume,
+       .set_wakeup = mwifiex_cfg80211_set_wakeup,
+#endif
+       .set_coalesce = mwifiex_cfg80211_set_coalesce,
+       .tdls_mgmt = mwifiex_cfg80211_tdls_mgmt,
+       .tdls_oper = mwifiex_cfg80211_tdls_oper,
+       .tdls_channel_switch = mwifiex_cfg80211_tdls_chan_switch,
+       .tdls_cancel_channel_switch = mwifiex_cfg80211_tdls_cancel_chan_switch,
+       .add_station = mwifiex_cfg80211_add_station,
+       .change_station = mwifiex_cfg80211_change_station,
+       .get_channel = mwifiex_cfg80211_get_channel,
+       .start_radar_detection = mwifiex_cfg80211_start_radar_detection,
+       .channel_switch = mwifiex_cfg80211_channel_switch,
+};
+
+#ifdef CONFIG_PM
+static const struct wiphy_wowlan_support mwifiex_wowlan_support = {
+       .flags = WIPHY_WOWLAN_MAGIC_PKT | WIPHY_WOWLAN_DISCONNECT,
+       .n_patterns = MWIFIEX_MEF_MAX_FILTERS,
+       .pattern_min_len = 1,
+       .pattern_max_len = MWIFIEX_MAX_PATTERN_LEN,
+       .max_pkt_offset = MWIFIEX_MAX_OFFSET_LEN,
+};
+#endif
+
+static bool mwifiex_is_valid_alpha2(const char *alpha2)
+{
+       if (!alpha2 || strlen(alpha2) != 2)
+               return false;
+
+       if (isalpha(alpha2[0]) && isalpha(alpha2[1]))
+               return true;
+
+       return false;
+}
+
+static const struct wiphy_coalesce_support mwifiex_coalesce_support = {
+       .n_rules = MWIFIEX_COALESCE_MAX_RULES,
+       .max_delay = MWIFIEX_MAX_COALESCING_DELAY,
+       .n_patterns = MWIFIEX_COALESCE_MAX_FILTERS,
+       .pattern_min_len = 1,
+       .pattern_max_len = MWIFIEX_MAX_PATTERN_LEN,
+       .max_pkt_offset = MWIFIEX_MAX_OFFSET_LEN,
+};
+
+int mwifiex_init_channel_scan_gap(struct mwifiex_adapter *adapter)
+{
+       u32 n_channels_bg, n_channels_a = 0;
+
+       n_channels_bg = mwifiex_band_2ghz.n_channels;
+
+       if (adapter->config_bands & BAND_A)
+               n_channels_a = mwifiex_band_5ghz.n_channels;
+
+       adapter->num_in_chan_stats = max_t(u32, n_channels_bg, n_channels_a);
+       adapter->chan_stats = vmalloc(sizeof(*adapter->chan_stats) *
+                                     adapter->num_in_chan_stats);
+
+       if (!adapter->chan_stats)
+               return -ENOMEM;
+
+       return 0;
+}
+
+/*
+ * This function registers the device with CFG802.11 subsystem.
+ *
+ * The function creates the wireless device/wiphy, populates it with
+ * default parameters and handler function pointers, and finally
+ * registers the device.
+ */
+
+int mwifiex_register_cfg80211(struct mwifiex_adapter *adapter)
+{
+       int ret;
+       void *wdev_priv;
+       struct wiphy *wiphy;
+       struct mwifiex_private *priv = adapter->priv[MWIFIEX_BSS_TYPE_STA];
+       u8 *country_code;
+       u32 thr, retry;
+
+       /* create a new wiphy for use with cfg80211 */
+       wiphy = wiphy_new(&mwifiex_cfg80211_ops,
+                         sizeof(struct mwifiex_adapter *));
+       if (!wiphy) {
+               mwifiex_dbg(adapter, ERROR,
+                           "%s: creating new wiphy\n", __func__);
+               return -ENOMEM;
+       }
+       wiphy->max_scan_ssids = MWIFIEX_MAX_SSID_LIST_LENGTH;
+       wiphy->max_scan_ie_len = MWIFIEX_MAX_VSIE_LEN;
+       wiphy->mgmt_stypes = mwifiex_mgmt_stypes;
+       wiphy->max_remain_on_channel_duration = 5000;
+       wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION) |
+                                BIT(NL80211_IFTYPE_ADHOC) |
+                                BIT(NL80211_IFTYPE_P2P_CLIENT) |
+                                BIT(NL80211_IFTYPE_P2P_GO) |
+                                BIT(NL80211_IFTYPE_AP);
+
+       wiphy->bands[IEEE80211_BAND_2GHZ] = &mwifiex_band_2ghz;
+       if (adapter->config_bands & BAND_A)
+               wiphy->bands[IEEE80211_BAND_5GHZ] = &mwifiex_band_5ghz;
+       else
+               wiphy->bands[IEEE80211_BAND_5GHZ] = NULL;
+
+       if (adapter->drcs_enabled && ISSUPP_DRCS_ENABLED(adapter->fw_cap_info))
+               wiphy->iface_combinations = &mwifiex_iface_comb_ap_sta_drcs;
+       else if (adapter->is_hw_11ac_capable)
+               wiphy->iface_combinations = &mwifiex_iface_comb_ap_sta_vht;
+       else
+               wiphy->iface_combinations = &mwifiex_iface_comb_ap_sta;
+       wiphy->n_iface_combinations = 1;
+
+       /* Initialize cipher suits */
+       wiphy->cipher_suites = mwifiex_cipher_suites;
+       wiphy->n_cipher_suites = ARRAY_SIZE(mwifiex_cipher_suites);
+
+       ether_addr_copy(wiphy->perm_addr, adapter->perm_addr);
+       wiphy->signal_type = CFG80211_SIGNAL_TYPE_MBM;
+       wiphy->flags |= WIPHY_FLAG_HAVE_AP_SME |
+                       WIPHY_FLAG_AP_PROBE_RESP_OFFLOAD |
+                       WIPHY_FLAG_AP_UAPSD |
+                       WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL |
+                       WIPHY_FLAG_HAS_CHANNEL_SWITCH |
+                       WIPHY_FLAG_PS_ON_BY_DEFAULT;
+
+       if (ISSUPP_TDLS_ENABLED(adapter->fw_cap_info))
+               wiphy->flags |= WIPHY_FLAG_SUPPORTS_TDLS |
+                               WIPHY_FLAG_TDLS_EXTERNAL_SETUP;
+
+#ifdef CONFIG_PM
+       wiphy->wowlan = &mwifiex_wowlan_support;
+#endif
+
+       wiphy->coalesce = &mwifiex_coalesce_support;
+
+       wiphy->probe_resp_offload = NL80211_PROBE_RESP_OFFLOAD_SUPPORT_WPS |
+                                   NL80211_PROBE_RESP_OFFLOAD_SUPPORT_WPS2 |
+                                   NL80211_PROBE_RESP_OFFLOAD_SUPPORT_P2P;
+
+       wiphy->available_antennas_tx = BIT(adapter->number_of_antenna) - 1;
+       wiphy->available_antennas_rx = BIT(adapter->number_of_antenna) - 1;
+
+       wiphy->features |= NL80211_FEATURE_HT_IBSS |
+                          NL80211_FEATURE_INACTIVITY_TIMER |
+                          NL80211_FEATURE_NEED_OBSS_SCAN;
+
+       if (ISSUPP_TDLS_ENABLED(adapter->fw_cap_info))
+               wiphy->features |= NL80211_FEATURE_TDLS_CHANNEL_SWITCH;
+
+       if (adapter->fw_api_ver == MWIFIEX_FW_V15)
+               wiphy->features |= NL80211_FEATURE_SK_TX_STATUS;
+
+       /* Reserve space for mwifiex specific private data for BSS */
+       wiphy->bss_priv_size = sizeof(struct mwifiex_bss_priv);
+
+       wiphy->reg_notifier = mwifiex_reg_notifier;
+
+       /* Set struct mwifiex_adapter pointer in wiphy_priv */
+       wdev_priv = wiphy_priv(wiphy);
+       *(unsigned long *)wdev_priv = (unsigned long)adapter;
+
+       set_wiphy_dev(wiphy, priv->adapter->dev);
+
+       ret = wiphy_register(wiphy);
+       if (ret < 0) {
+               mwifiex_dbg(adapter, ERROR,
+                           "%s: wiphy_register failed: %d\n", __func__, ret);
+               wiphy_free(wiphy);
+               return ret;
+       }
+
+       if (reg_alpha2 && mwifiex_is_valid_alpha2(reg_alpha2)) {
+               mwifiex_dbg(adapter, INFO,
+                           "driver hint alpha2: %2.2s\n", reg_alpha2);
+               regulatory_hint(wiphy, reg_alpha2);
+       } else {
+               country_code = mwifiex_11d_code_2_region(adapter->region_code);
+               if (country_code)
+                       mwifiex_dbg(adapter, WARN,
+                                   "ignoring F/W country code %2.2s\n",
+                                   country_code);
+       }
+
+       mwifiex_send_cmd(priv, HostCmd_CMD_802_11_SNMP_MIB,
+                        HostCmd_ACT_GEN_GET, FRAG_THRESH_I, &thr, true);
+       wiphy->frag_threshold = thr;
+       mwifiex_send_cmd(priv, HostCmd_CMD_802_11_SNMP_MIB,
+                        HostCmd_ACT_GEN_GET, RTS_THRESH_I, &thr, true);
+       wiphy->rts_threshold = thr;
+       mwifiex_send_cmd(priv, HostCmd_CMD_802_11_SNMP_MIB,
+                        HostCmd_ACT_GEN_GET, SHORT_RETRY_LIM_I, &retry, true);
+       wiphy->retry_short = (u8) retry;
+       mwifiex_send_cmd(priv, HostCmd_CMD_802_11_SNMP_MIB,
+                        HostCmd_ACT_GEN_GET, LONG_RETRY_LIM_I, &retry, true);
+       wiphy->retry_long = (u8) retry;
+
+       adapter->wiphy = wiphy;
+       return ret;
+}
diff --git a/drivers/net/wireless/marvell/mwifiex/cfg80211.h b/drivers/net/wireless/marvell/mwifiex/cfg80211.h
new file mode 100644 (file)
index 0000000..9083678
--- /dev/null
@@ -0,0 +1,29 @@
+/*
+ * Marvell Wireless LAN device driver: CFG80211
+ *
+ * Copyright (C) 2011-2014, Marvell International Ltd.
+ *
+ * This software file (the "File") is distributed by Marvell International
+ * Ltd. under the terms of the GNU General Public License Version 2, June 1991
+ * (the "License").  You may use, redistribute and/or modify this File in
+ * accordance with the terms and conditions of the License, a copy of which
+ * is available by writing to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the
+ * worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
+ *
+ * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
+ * ARE EXPRESSLY DISCLAIMED.  The License provides additional details about
+ * this warranty disclaimer.
+ */
+
+#ifndef __MWIFIEX_CFG80211__
+#define __MWIFIEX_CFG80211__
+
+#include <net/cfg80211.h>
+
+#include "main.h"
+
+int mwifiex_register_cfg80211(struct mwifiex_adapter *);
+
+#endif
diff --git a/drivers/net/wireless/marvell/mwifiex/cfp.c b/drivers/net/wireless/marvell/mwifiex/cfp.c
new file mode 100644 (file)
index 0000000..3ddb8ec
--- /dev/null
@@ -0,0 +1,537 @@
+/*
+ * Marvell Wireless LAN device driver: Channel, Frequence and Power
+ *
+ * Copyright (C) 2011-2014, Marvell International Ltd.
+ *
+ * This software file (the "File") is distributed by Marvell International
+ * Ltd. under the terms of the GNU General Public License Version 2, June 1991
+ * (the "License").  You may use, redistribute and/or modify this File in
+ * accordance with the terms and conditions of the License, a copy of which
+ * is available by writing to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the
+ * worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
+ *
+ * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
+ * ARE EXPRESSLY DISCLAIMED.  The License provides additional details about
+ * this warranty disclaimer.
+ */
+
+#include "decl.h"
+#include "ioctl.h"
+#include "util.h"
+#include "fw.h"
+#include "main.h"
+#include "cfg80211.h"
+
+/* 100mW */
+#define MWIFIEX_TX_PWR_DEFAULT     20
+/* 100mW */
+#define MWIFIEX_TX_PWR_US_DEFAULT      20
+/* 50mW */
+#define MWIFIEX_TX_PWR_JP_DEFAULT      16
+/* 100mW */
+#define MWIFIEX_TX_PWR_FR_100MW        20
+/* 10mW */
+#define MWIFIEX_TX_PWR_FR_10MW         10
+/* 100mW */
+#define MWIFIEX_TX_PWR_EMEA_DEFAULT    20
+
+static u8 adhoc_rates_b[B_SUPPORTED_RATES] = { 0x82, 0x84, 0x8b, 0x96, 0 };
+
+static u8 adhoc_rates_g[G_SUPPORTED_RATES] = { 0x8c, 0x12, 0x98, 0x24,
+                                              0xb0, 0x48, 0x60, 0x6c, 0 };
+
+static u8 adhoc_rates_bg[BG_SUPPORTED_RATES] = { 0x82, 0x84, 0x8b, 0x96,
+                                                0x0c, 0x12, 0x18, 0x24,
+                                                0x30, 0x48, 0x60, 0x6c, 0 };
+
+static u8 adhoc_rates_a[A_SUPPORTED_RATES] = { 0x8c, 0x12, 0x98, 0x24,
+                                              0xb0, 0x48, 0x60, 0x6c, 0 };
+static u8 supported_rates_a[A_SUPPORTED_RATES] = { 0x0c, 0x12, 0x18, 0x24,
+                                       0xb0, 0x48, 0x60, 0x6c, 0 };
+static u16 mwifiex_data_rates[MWIFIEX_SUPPORTED_RATES_EXT] = { 0x02, 0x04,
+                                       0x0B, 0x16, 0x00, 0x0C, 0x12, 0x18,
+                                       0x24, 0x30, 0x48, 0x60, 0x6C, 0x90,
+                                       0x0D, 0x1A, 0x27, 0x34, 0x4E, 0x68,
+                                       0x75, 0x82, 0x0C, 0x1B, 0x36, 0x51,
+                                       0x6C, 0xA2, 0xD8, 0xF3, 0x10E, 0x00 };
+
+static u8 supported_rates_b[B_SUPPORTED_RATES] = { 0x02, 0x04, 0x0b, 0x16, 0 };
+
+static u8 supported_rates_g[G_SUPPORTED_RATES] = { 0x0c, 0x12, 0x18, 0x24,
+                                       0x30, 0x48, 0x60, 0x6c, 0 };
+
+static u8 supported_rates_bg[BG_SUPPORTED_RATES] = { 0x02, 0x04, 0x0b, 0x0c,
+                                       0x12, 0x16, 0x18, 0x24, 0x30, 0x48,
+                                       0x60, 0x6c, 0 };
+
+u16 region_code_index[MWIFIEX_MAX_REGION_CODE] = { 0x10, 0x20, 0x30,
+                                               0x32, 0x40, 0x41, 0xff };
+
+static u8 supported_rates_n[N_SUPPORTED_RATES] = { 0x02, 0x04, 0 };
+
+/* For every mcs_rate line, the first 8 bytes are for stream 1x1,
+ * and all 16 bytes are for stream 2x2.
+ */
+static const u16 mcs_rate[4][16] = {
+       /* LGI 40M */
+       { 0x1b, 0x36, 0x51, 0x6c, 0xa2, 0xd8, 0xf3, 0x10e,
+         0x36, 0x6c, 0xa2, 0xd8, 0x144, 0x1b0, 0x1e6, 0x21c },
+
+       /* SGI 40M */
+       { 0x1e, 0x3c, 0x5a, 0x78, 0xb4, 0xf0, 0x10e, 0x12c,
+         0x3c, 0x78, 0xb4, 0xf0, 0x168, 0x1e0, 0x21c, 0x258 },
+
+       /* LGI 20M */
+       { 0x0d, 0x1a, 0x27, 0x34, 0x4e, 0x68, 0x75, 0x82,
+         0x1a, 0x34, 0x4e, 0x68, 0x9c, 0xd0, 0xea, 0x104 },
+
+       /* SGI 20M */
+       { 0x0e, 0x1c, 0x2b, 0x39, 0x56, 0x73, 0x82, 0x90,
+         0x1c, 0x39, 0x56, 0x73, 0xad, 0xe7, 0x104, 0x120 }
+};
+
+/* AC rates */
+static const u16 ac_mcs_rate_nss1[8][10] = {
+       /* LG 160M */
+       { 0x75, 0xEA, 0x15F, 0x1D4, 0x2BE, 0x3A8, 0x41D,
+         0x492, 0x57C, 0x618 },
+
+       /* SG 160M */
+       { 0x82, 0x104, 0x186, 0x208, 0x30C, 0x410, 0x492,
+         0x514, 0x618, 0x6C6 },
+
+       /* LG 80M */
+       { 0x3B, 0x75, 0xB0, 0xEA, 0x15F, 0x1D4, 0x20F,
+         0x249, 0x2BE, 0x30C },
+
+       /* SG 80M */
+       { 0x41, 0x82, 0xC3, 0x104, 0x186, 0x208, 0x249,
+         0x28A, 0x30C, 0x363 },
+
+       /* LG 40M */
+       { 0x1B, 0x36, 0x51, 0x6C, 0xA2, 0xD8, 0xF3,
+         0x10E, 0x144, 0x168 },
+
+       /* SG 40M */
+       { 0x1E, 0x3C, 0x5A, 0x78, 0xB4, 0xF0, 0x10E,
+         0x12C, 0x168, 0x190 },
+
+       /* LG 20M */
+       { 0xD, 0x1A, 0x27, 0x34, 0x4E, 0x68, 0x75, 0x82, 0x9C, 0x00 },
+
+       /* SG 20M */
+       { 0xF, 0x1D, 0x2C, 0x3A, 0x57, 0x74, 0x82, 0x91, 0xAE, 0x00 },
+};
+
+/* NSS2 note: the value in the table is 2 multiplier of the actual rate */
+static const u16 ac_mcs_rate_nss2[8][10] = {
+       /* LG 160M */
+       { 0xEA, 0x1D4, 0x2BE, 0x3A8, 0x57C, 0x750, 0x83A,
+         0x924, 0xAF8, 0xC30 },
+
+       /* SG 160M */
+       { 0x104, 0x208, 0x30C, 0x410, 0x618, 0x820, 0x924,
+         0xA28, 0xC30, 0xD8B },
+
+       /* LG 80M */
+       { 0x75, 0xEA, 0x15F, 0x1D4, 0x2BE, 0x3A8, 0x41D,
+         0x492, 0x57C, 0x618 },
+
+       /* SG 80M */
+       { 0x82, 0x104, 0x186, 0x208, 0x30C, 0x410, 0x492,
+         0x514, 0x618, 0x6C6 },
+
+       /* LG 40M */
+       { 0x36, 0x6C, 0xA2, 0xD8, 0x144, 0x1B0, 0x1E6,
+         0x21C, 0x288, 0x2D0 },
+
+       /* SG 40M */
+       { 0x3C, 0x78, 0xB4, 0xF0, 0x168, 0x1E0, 0x21C,
+         0x258, 0x2D0, 0x320 },
+
+       /* LG 20M */
+       { 0x1A, 0x34, 0x4A, 0x68, 0x9C, 0xD0, 0xEA, 0x104,
+         0x138, 0x00 },
+
+       /* SG 20M */
+       { 0x1D, 0x3A, 0x57, 0x74, 0xAE, 0xE6, 0x104, 0x121,
+         0x15B, 0x00 },
+};
+
+struct region_code_mapping {
+       u8 code;
+       u8 region[IEEE80211_COUNTRY_STRING_LEN];
+};
+
+static struct region_code_mapping region_code_mapping_t[] = {
+       { 0x10, "US " }, /* US FCC */
+       { 0x20, "CA " }, /* IC Canada */
+       { 0x30, "EU " }, /* ETSI */
+       { 0x31, "ES " }, /* Spain */
+       { 0x32, "FR " }, /* France */
+       { 0x40, "JP " }, /* Japan */
+       { 0x41, "JP " }, /* Japan */
+       { 0x50, "CN " }, /* China */
+};
+
+/* This function converts integer code to region string */
+u8 *mwifiex_11d_code_2_region(u8 code)
+{
+       u8 i;
+       u8 size = sizeof(region_code_mapping_t)/
+                               sizeof(struct region_code_mapping);
+
+       /* Look for code in mapping table */
+       for (i = 0; i < size; i++)
+               if (region_code_mapping_t[i].code == code)
+                       return region_code_mapping_t[i].region;
+
+       return NULL;
+}
+
+/*
+ * This function maps an index in supported rates table into
+ * the corresponding data rate.
+ */
+u32 mwifiex_index_to_acs_data_rate(struct mwifiex_private *priv,
+                                  u8 index, u8 ht_info)
+{
+       u32 rate = 0;
+       u8 mcs_index = 0;
+       u8 bw = 0;
+       u8 gi = 0;
+
+       if ((ht_info & 0x3) == MWIFIEX_RATE_FORMAT_VHT) {
+               mcs_index = min(index & 0xF, 9);
+
+               /* 20M: bw=0, 40M: bw=1, 80M: bw=2, 160M: bw=3 */
+               bw = (ht_info & 0xC) >> 2;
+
+               /* LGI: gi =0, SGI: gi = 1 */
+               gi = (ht_info & 0x10) >> 4;
+
+               if ((index >> 4) == 1)  /* NSS = 2 */
+                       rate = ac_mcs_rate_nss2[2 * (3 - bw) + gi][mcs_index];
+               else                    /* NSS = 1 */
+                       rate = ac_mcs_rate_nss1[2 * (3 - bw) + gi][mcs_index];
+       } else if ((ht_info & 0x3) == MWIFIEX_RATE_FORMAT_HT) {
+               /* 20M: bw=0, 40M: bw=1 */
+               bw = (ht_info & 0xC) >> 2;
+
+               /* LGI: gi =0, SGI: gi = 1 */
+               gi = (ht_info & 0x10) >> 4;
+
+               if (index == MWIFIEX_RATE_BITMAP_MCS0) {
+                       if (gi == 1)
+                               rate = 0x0D;    /* MCS 32 SGI rate */
+                       else
+                               rate = 0x0C;    /* MCS 32 LGI rate */
+               } else if (index < 16) {
+                       if ((bw == 1) || (bw == 0))
+                               rate = mcs_rate[2 * (1 - bw) + gi][index];
+                       else
+                               rate = mwifiex_data_rates[0];
+               } else {
+                       rate = mwifiex_data_rates[0];
+               }
+       } else {
+               /* 11n non-HT rates */
+               if (index >= MWIFIEX_SUPPORTED_RATES_EXT)
+                       index = 0;
+               rate = mwifiex_data_rates[index];
+       }
+
+       return rate;
+}
+
+/* This function maps an index in supported rates table into
+ * the corresponding data rate.
+ */
+u32 mwifiex_index_to_data_rate(struct mwifiex_private *priv,
+                              u8 index, u8 ht_info)
+{
+       u32 mcs_num_supp =
+               (priv->adapter->user_dev_mcs_support == HT_STREAM_2X2) ? 16 : 8;
+       u32 rate;
+
+       if (priv->adapter->is_hw_11ac_capable)
+               return mwifiex_index_to_acs_data_rate(priv, index, ht_info);
+
+       if (ht_info & BIT(0)) {
+               if (index == MWIFIEX_RATE_BITMAP_MCS0) {
+                       if (ht_info & BIT(2))
+                               rate = 0x0D;    /* MCS 32 SGI rate */
+                       else
+                               rate = 0x0C;    /* MCS 32 LGI rate */
+               } else if (index < mcs_num_supp) {
+                       if (ht_info & BIT(1)) {
+                               if (ht_info & BIT(2))
+                                       /* SGI, 40M */
+                                       rate = mcs_rate[1][index];
+                               else
+                                       /* LGI, 40M */
+                                       rate = mcs_rate[0][index];
+                       } else {
+                               if (ht_info & BIT(2))
+                                       /* SGI, 20M */
+                                       rate = mcs_rate[3][index];
+                               else
+                                       /* LGI, 20M */
+                                       rate = mcs_rate[2][index];
+                       }
+               } else
+                       rate = mwifiex_data_rates[0];
+       } else {
+               if (index >= MWIFIEX_SUPPORTED_RATES_EXT)
+                       index = 0;
+               rate = mwifiex_data_rates[index];
+       }
+       return rate;
+}
+
+/*
+ * This function returns the current active data rates.
+ *
+ * The result may vary depending upon connection status.
+ */
+u32 mwifiex_get_active_data_rates(struct mwifiex_private *priv, u8 *rates)
+{
+       if (!priv->media_connected)
+               return mwifiex_get_supported_rates(priv, rates);
+       else
+               return mwifiex_copy_rates(rates, 0,
+                                         priv->curr_bss_params.data_rates,
+                                         priv->curr_bss_params.num_of_rates);
+}
+
+/*
+ * This function locates the Channel-Frequency-Power triplet based upon
+ * band and channel/frequency parameters.
+ */
+struct mwifiex_chan_freq_power *
+mwifiex_get_cfp(struct mwifiex_private *priv, u8 band, u16 channel, u32 freq)
+{
+       struct mwifiex_chan_freq_power *cfp = NULL;
+       struct ieee80211_supported_band *sband;
+       struct ieee80211_channel *ch = NULL;
+       int i;
+
+       if (!channel && !freq)
+               return cfp;
+
+       if (mwifiex_band_to_radio_type(band) == HostCmd_SCAN_RADIO_TYPE_BG)
+               sband = priv->wdev.wiphy->bands[IEEE80211_BAND_2GHZ];
+       else
+               sband = priv->wdev.wiphy->bands[IEEE80211_BAND_5GHZ];
+
+       if (!sband) {
+               mwifiex_dbg(priv->adapter, ERROR,
+                           "%s: cannot find cfp by band %d\n",
+                           __func__, band);
+               return cfp;
+       }
+
+       for (i = 0; i < sband->n_channels; i++) {
+               ch = &sband->channels[i];
+
+               if (ch->flags & IEEE80211_CHAN_DISABLED)
+                       continue;
+
+               if (freq) {
+                       if (ch->center_freq == freq)
+                               break;
+               } else {
+                       /* find by valid channel*/
+                       if (ch->hw_value == channel ||
+                           channel == FIRST_VALID_CHANNEL)
+                               break;
+               }
+       }
+       if (i == sband->n_channels) {
+               mwifiex_dbg(priv->adapter, ERROR,
+                           "%s: cannot find cfp by band %d\t"
+                           "& channel=%d freq=%d\n",
+                           __func__, band, channel, freq);
+       } else {
+               if (!ch)
+                       return cfp;
+
+               priv->cfp.channel = ch->hw_value;
+               priv->cfp.freq = ch->center_freq;
+               priv->cfp.max_tx_power = ch->max_power;
+               cfp = &priv->cfp;
+       }
+
+       return cfp;
+}
+
+/*
+ * This function checks if the data rate is set to auto.
+ */
+u8
+mwifiex_is_rate_auto(struct mwifiex_private *priv)
+{
+       u32 i;
+       int rate_num = 0;
+
+       for (i = 0; i < ARRAY_SIZE(priv->bitmap_rates); i++)
+               if (priv->bitmap_rates[i])
+                       rate_num++;
+
+       if (rate_num > 1)
+               return true;
+       else
+               return false;
+}
+
+/* This function gets the supported data rates from bitmask inside
+ * cfg80211_scan_request.
+ */
+u32 mwifiex_get_rates_from_cfg80211(struct mwifiex_private *priv,
+                                   u8 *rates, u8 radio_type)
+{
+       struct wiphy *wiphy = priv->adapter->wiphy;
+       struct cfg80211_scan_request *request = priv->scan_request;
+       u32 num_rates, rate_mask;
+       struct ieee80211_supported_band *sband;
+       int i;
+
+       if (radio_type) {
+               sband = wiphy->bands[IEEE80211_BAND_5GHZ];
+               if (WARN_ON_ONCE(!sband))
+                       return 0;
+               rate_mask = request->rates[IEEE80211_BAND_5GHZ];
+       } else {
+               sband = wiphy->bands[IEEE80211_BAND_2GHZ];
+               if (WARN_ON_ONCE(!sband))
+                       return 0;
+               rate_mask = request->rates[IEEE80211_BAND_2GHZ];
+       }
+
+       num_rates = 0;
+       for (i = 0; i < sband->n_bitrates; i++) {
+               if ((BIT(i) & rate_mask) == 0)
+                       continue; /* skip rate */
+               rates[num_rates++] = (u8)(sband->bitrates[i].bitrate / 5);
+       }
+
+       return num_rates;
+}
+
+/* This function gets the supported data rates. The function works in
+ * both Ad-Hoc and infra mode by printing the band and returning the
+ * data rates.
+ */
+u32 mwifiex_get_supported_rates(struct mwifiex_private *priv, u8 *rates)
+{
+       u32 k = 0;
+       struct mwifiex_adapter *adapter = priv->adapter;
+
+       if (priv->bss_mode == NL80211_IFTYPE_STATION ||
+           priv->bss_mode == NL80211_IFTYPE_P2P_CLIENT) {
+               switch (adapter->config_bands) {
+               case BAND_B:
+                       mwifiex_dbg(adapter, INFO, "info: infra band=%d\t"
+                                   "supported_rates_b\n",
+                                   adapter->config_bands);
+                       k = mwifiex_copy_rates(rates, k, supported_rates_b,
+                                              sizeof(supported_rates_b));
+                       break;
+               case BAND_G:
+               case BAND_G | BAND_GN:
+                       mwifiex_dbg(adapter, INFO, "info: infra band=%d\t"
+                                   "supported_rates_g\n",
+                                   adapter->config_bands);
+                       k = mwifiex_copy_rates(rates, k, supported_rates_g,
+                                              sizeof(supported_rates_g));
+                       break;
+               case BAND_B | BAND_G:
+               case BAND_A | BAND_B | BAND_G:
+               case BAND_A | BAND_B:
+               case BAND_A | BAND_B | BAND_G | BAND_GN | BAND_AN:
+               case BAND_A | BAND_B | BAND_G | BAND_GN | BAND_AN | BAND_AAC:
+               case BAND_B | BAND_G | BAND_GN:
+                       mwifiex_dbg(adapter, INFO, "info: infra band=%d\t"
+                                   "supported_rates_bg\n",
+                                   adapter->config_bands);
+                       k = mwifiex_copy_rates(rates, k, supported_rates_bg,
+                                              sizeof(supported_rates_bg));
+                       break;
+               case BAND_A:
+               case BAND_A | BAND_G:
+                       mwifiex_dbg(adapter, INFO, "info: infra band=%d\t"
+                                   "supported_rates_a\n",
+                                   adapter->config_bands);
+                       k = mwifiex_copy_rates(rates, k, supported_rates_a,
+                                              sizeof(supported_rates_a));
+                       break;
+               case BAND_AN:
+               case BAND_A | BAND_AN:
+               case BAND_A | BAND_AN | BAND_AAC:
+               case BAND_A | BAND_G | BAND_AN | BAND_GN:
+               case BAND_A | BAND_G | BAND_AN | BAND_GN | BAND_AAC:
+                       mwifiex_dbg(adapter, INFO, "info: infra band=%d\t"
+                                   "supported_rates_a\n",
+                                   adapter->config_bands);
+                       k = mwifiex_copy_rates(rates, k, supported_rates_a,
+                                              sizeof(supported_rates_a));
+                       break;
+               case BAND_GN:
+                       mwifiex_dbg(adapter, INFO, "info: infra band=%d\t"
+                                   "supported_rates_n\n",
+                                   adapter->config_bands);
+                       k = mwifiex_copy_rates(rates, k, supported_rates_n,
+                                              sizeof(supported_rates_n));
+                       break;
+               }
+       } else {
+               /* Ad-hoc mode */
+               switch (adapter->adhoc_start_band) {
+               case BAND_B:
+                       mwifiex_dbg(adapter, INFO, "info: adhoc B\n");
+                       k = mwifiex_copy_rates(rates, k, adhoc_rates_b,
+                                              sizeof(adhoc_rates_b));
+                       break;
+               case BAND_G:
+               case BAND_G | BAND_GN:
+                       mwifiex_dbg(adapter, INFO, "info: adhoc G only\n");
+                       k = mwifiex_copy_rates(rates, k, adhoc_rates_g,
+                                              sizeof(adhoc_rates_g));
+                       break;
+               case BAND_B | BAND_G:
+               case BAND_B | BAND_G | BAND_GN:
+                       mwifiex_dbg(adapter, INFO, "info: adhoc BG\n");
+                       k = mwifiex_copy_rates(rates, k, adhoc_rates_bg,
+                                              sizeof(adhoc_rates_bg));
+                       break;
+               case BAND_A:
+               case BAND_A | BAND_AN:
+                       mwifiex_dbg(adapter, INFO, "info: adhoc A\n");
+                       k = mwifiex_copy_rates(rates, k, adhoc_rates_a,
+                                              sizeof(adhoc_rates_a));
+                       break;
+               }
+       }
+
+       return k;
+}
+
+u8 mwifiex_adjust_data_rate(struct mwifiex_private *priv,
+                           u8 rx_rate, u8 rate_info)
+{
+       u8 rate_index = 0;
+
+       /* HT40 */
+       if ((rate_info & BIT(0)) && (rate_info & BIT(1)))
+               rate_index = MWIFIEX_RATE_INDEX_MCS0 +
+                            MWIFIEX_BW20_MCS_NUM + rx_rate;
+       else if (rate_info & BIT(0)) /* HT20 */
+               rate_index = MWIFIEX_RATE_INDEX_MCS0 + rx_rate;
+       else
+               rate_index = (rx_rate > MWIFIEX_RATE_INDEX_OFDM0) ?
+                             rx_rate - 1 : rx_rate;
+
+       return rate_index;
+}
diff --git a/drivers/net/wireless/marvell/mwifiex/cmdevt.c b/drivers/net/wireless/marvell/mwifiex/cmdevt.c
new file mode 100644 (file)
index 0000000..45ae38e
--- /dev/null
@@ -0,0 +1,1659 @@
+/*
+ * Marvell Wireless LAN device driver: commands and events
+ *
+ * Copyright (C) 2011-2014, Marvell International Ltd.
+ *
+ * This software file (the "File") is distributed by Marvell International
+ * Ltd. under the terms of the GNU General Public License Version 2, June 1991
+ * (the "License").  You may use, redistribute and/or modify this File in
+ * accordance with the terms and conditions of the License, a copy of which
+ * is available by writing to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the
+ * worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
+ *
+ * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
+ * ARE EXPRESSLY DISCLAIMED.  The License provides additional details about
+ * this warranty disclaimer.
+ */
+
+#include "decl.h"
+#include "ioctl.h"
+#include "util.h"
+#include "fw.h"
+#include "main.h"
+#include "wmm.h"
+#include "11n.h"
+#include "11ac.h"
+
+/*
+ * This function initializes a command node.
+ *
+ * The actual allocation of the node is not done by this function. It only
+ * initiates a node by filling it with default parameters. Similarly,
+ * allocation of the different buffers used (IOCTL buffer, data buffer) are
+ * not done by this function either.
+ */
+static void
+mwifiex_init_cmd_node(struct mwifiex_private *priv,
+                     struct cmd_ctrl_node *cmd_node,
+                     u32 cmd_oid, void *data_buf, bool sync)
+{
+       cmd_node->priv = priv;
+       cmd_node->cmd_oid = cmd_oid;
+       if (sync) {
+               cmd_node->wait_q_enabled = true;
+               cmd_node->cmd_wait_q_woken = false;
+               cmd_node->condition = &cmd_node->cmd_wait_q_woken;
+       }
+       cmd_node->data_buf = data_buf;
+       cmd_node->cmd_skb = cmd_node->skb;
+}
+
+/*
+ * This function returns a command node from the free queue depending upon
+ * availability.
+ */
+static struct cmd_ctrl_node *
+mwifiex_get_cmd_node(struct mwifiex_adapter *adapter)
+{
+       struct cmd_ctrl_node *cmd_node;
+       unsigned long flags;
+
+       spin_lock_irqsave(&adapter->cmd_free_q_lock, flags);
+       if (list_empty(&adapter->cmd_free_q)) {
+               mwifiex_dbg(adapter, ERROR,
+                           "GET_CMD_NODE: cmd node not available\n");
+               spin_unlock_irqrestore(&adapter->cmd_free_q_lock, flags);
+               return NULL;
+       }
+       cmd_node = list_first_entry(&adapter->cmd_free_q,
+                                   struct cmd_ctrl_node, list);
+       list_del(&cmd_node->list);
+       spin_unlock_irqrestore(&adapter->cmd_free_q_lock, flags);
+
+       return cmd_node;
+}
+
+/*
+ * This function cleans up a command node.
+ *
+ * The function resets the fields including the buffer pointers.
+ * This function does not try to free the buffers. They must be
+ * freed before calling this function.
+ *
+ * This function will however call the receive completion callback
+ * in case a response buffer is still available before resetting
+ * the pointer.
+ */
+static void
+mwifiex_clean_cmd_node(struct mwifiex_adapter *adapter,
+                      struct cmd_ctrl_node *cmd_node)
+{
+       cmd_node->cmd_oid = 0;
+       cmd_node->cmd_flag = 0;
+       cmd_node->data_buf = NULL;
+       cmd_node->wait_q_enabled = false;
+
+       if (cmd_node->cmd_skb)
+               skb_trim(cmd_node->cmd_skb, 0);
+
+       if (cmd_node->resp_skb) {
+               adapter->if_ops.cmdrsp_complete(adapter, cmd_node->resp_skb);
+               cmd_node->resp_skb = NULL;
+       }
+}
+
+/*
+ * This function sends a host command to the firmware.
+ *
+ * The function copies the host command into the driver command
+ * buffer, which will be transferred to the firmware later by the
+ * main thread.
+ */
+static int mwifiex_cmd_host_cmd(struct mwifiex_private *priv,
+                               struct host_cmd_ds_command *cmd,
+                               struct mwifiex_ds_misc_cmd *pcmd_ptr)
+{
+       /* Copy the HOST command to command buffer */
+       memcpy(cmd, pcmd_ptr->cmd, pcmd_ptr->len);
+       mwifiex_dbg(priv->adapter, CMD,
+                   "cmd: host cmd size = %d\n", pcmd_ptr->len);
+       return 0;
+}
+
+/*
+ * This function downloads a command to the firmware.
+ *
+ * The function performs sanity tests, sets the command sequence
+ * number and size, converts the header fields to CPU format before
+ * sending. Afterwards, it logs the command ID and action for debugging
+ * and sets up the command timeout timer.
+ */
+static int mwifiex_dnld_cmd_to_fw(struct mwifiex_private *priv,
+                                 struct cmd_ctrl_node *cmd_node)
+{
+
+       struct mwifiex_adapter *adapter = priv->adapter;
+       int ret;
+       struct host_cmd_ds_command *host_cmd;
+       uint16_t cmd_code;
+       uint16_t cmd_size;
+       unsigned long flags;
+       __le32 tmp;
+
+       if (!adapter || !cmd_node)
+               return -1;
+
+       host_cmd = (struct host_cmd_ds_command *) (cmd_node->cmd_skb->data);
+
+       /* Sanity test */
+       if (host_cmd == NULL || host_cmd->size == 0) {
+               mwifiex_dbg(adapter, ERROR,
+                           "DNLD_CMD: host_cmd is null\t"
+                           "or cmd size is 0, not sending\n");
+               if (cmd_node->wait_q_enabled)
+                       adapter->cmd_wait_q.status = -1;
+               mwifiex_recycle_cmd_node(adapter, cmd_node);
+               return -1;
+       }
+
+       cmd_code = le16_to_cpu(host_cmd->command);
+       cmd_size = le16_to_cpu(host_cmd->size);
+
+       if (adapter->hw_status == MWIFIEX_HW_STATUS_RESET &&
+           cmd_code != HostCmd_CMD_FUNC_SHUTDOWN &&
+           cmd_code != HostCmd_CMD_FUNC_INIT) {
+               mwifiex_dbg(adapter, ERROR,
+                           "DNLD_CMD: FW in reset state, ignore cmd %#x\n",
+                       cmd_code);
+               mwifiex_recycle_cmd_node(adapter, cmd_node);
+               queue_work(adapter->workqueue, &adapter->main_work);
+               return -1;
+       }
+
+       /* Set command sequence number */
+       adapter->seq_num++;
+       host_cmd->seq_num = cpu_to_le16(HostCmd_SET_SEQ_NO_BSS_INFO
+                                       (adapter->seq_num,
+                                        cmd_node->priv->bss_num,
+                                        cmd_node->priv->bss_type));
+
+       spin_lock_irqsave(&adapter->mwifiex_cmd_lock, flags);
+       adapter->curr_cmd = cmd_node;
+       spin_unlock_irqrestore(&adapter->mwifiex_cmd_lock, flags);
+
+       /* Adjust skb length */
+       if (cmd_node->cmd_skb->len > cmd_size)
+               /*
+                * cmd_size is less than sizeof(struct host_cmd_ds_command).
+                * Trim off the unused portion.
+                */
+               skb_trim(cmd_node->cmd_skb, cmd_size);
+       else if (cmd_node->cmd_skb->len < cmd_size)
+               /*
+                * cmd_size is larger than sizeof(struct host_cmd_ds_command)
+                * because we have appended custom IE TLV. Increase skb length
+                * accordingly.
+                */
+               skb_put(cmd_node->cmd_skb, cmd_size - cmd_node->cmd_skb->len);
+
+       mwifiex_dbg(adapter, CMD,
+                   "cmd: DNLD_CMD: %#x, act %#x, len %d, seqno %#x\n",
+                   cmd_code,
+                   le16_to_cpu(*(__le16 *)((u8 *)host_cmd + S_DS_GEN)),
+                   cmd_size, le16_to_cpu(host_cmd->seq_num));
+       mwifiex_dbg_dump(adapter, CMD_D, "cmd buffer:", host_cmd, cmd_size);
+
+       if (adapter->iface_type == MWIFIEX_USB) {
+               tmp = cpu_to_le32(MWIFIEX_USB_TYPE_CMD);
+               skb_push(cmd_node->cmd_skb, MWIFIEX_TYPE_LEN);
+               memcpy(cmd_node->cmd_skb->data, &tmp, MWIFIEX_TYPE_LEN);
+               adapter->cmd_sent = true;
+               ret = adapter->if_ops.host_to_card(adapter,
+                                                  MWIFIEX_USB_EP_CMD_EVENT,
+                                                  cmd_node->cmd_skb, NULL);
+               skb_pull(cmd_node->cmd_skb, MWIFIEX_TYPE_LEN);
+               if (ret == -EBUSY)
+                       cmd_node->cmd_skb = NULL;
+       } else {
+               skb_push(cmd_node->cmd_skb, INTF_HEADER_LEN);
+               ret = adapter->if_ops.host_to_card(adapter, MWIFIEX_TYPE_CMD,
+                                                  cmd_node->cmd_skb, NULL);
+               skb_pull(cmd_node->cmd_skb, INTF_HEADER_LEN);
+       }
+
+       if (ret == -1) {
+               mwifiex_dbg(adapter, ERROR,
+                           "DNLD_CMD: host to card failed\n");
+               if (adapter->iface_type == MWIFIEX_USB)
+                       adapter->cmd_sent = false;
+               if (cmd_node->wait_q_enabled)
+                       adapter->cmd_wait_q.status = -1;
+               mwifiex_recycle_cmd_node(adapter, adapter->curr_cmd);
+
+               spin_lock_irqsave(&adapter->mwifiex_cmd_lock, flags);
+               adapter->curr_cmd = NULL;
+               spin_unlock_irqrestore(&adapter->mwifiex_cmd_lock, flags);
+
+               adapter->dbg.num_cmd_host_to_card_failure++;
+               return -1;
+       }
+
+       /* Save the last command id and action to debug log */
+       adapter->dbg.last_cmd_index =
+                       (adapter->dbg.last_cmd_index + 1) % DBG_CMD_NUM;
+       adapter->dbg.last_cmd_id[adapter->dbg.last_cmd_index] = cmd_code;
+       adapter->dbg.last_cmd_act[adapter->dbg.last_cmd_index] =
+                       le16_to_cpu(*(__le16 *) ((u8 *) host_cmd + S_DS_GEN));
+
+       /* Clear BSS_NO_BITS from HostCmd */
+       cmd_code &= HostCmd_CMD_ID_MASK;
+
+       /* Setup the timer after transmit command */
+       mod_timer(&adapter->cmd_timer,
+                 jiffies + msecs_to_jiffies(MWIFIEX_TIMER_10S));
+
+       return 0;
+}
+
+/*
+ * This function downloads a sleep confirm command to the firmware.
+ *
+ * The function performs sanity tests, sets the command sequence
+ * number and size, converts the header fields to CPU format before
+ * sending.
+ *
+ * No responses are needed for sleep confirm command.
+ */
+static int mwifiex_dnld_sleep_confirm_cmd(struct mwifiex_adapter *adapter)
+{
+       int ret;
+       struct mwifiex_private *priv;
+       struct mwifiex_opt_sleep_confirm *sleep_cfm_buf =
+                               (struct mwifiex_opt_sleep_confirm *)
+                                               adapter->sleep_cfm->data;
+       struct sk_buff *sleep_cfm_tmp;
+       __le32 tmp;
+
+       priv = mwifiex_get_priv(adapter, MWIFIEX_BSS_ROLE_ANY);
+
+       adapter->seq_num++;
+       sleep_cfm_buf->seq_num =
+               cpu_to_le16((HostCmd_SET_SEQ_NO_BSS_INFO
+                                       (adapter->seq_num, priv->bss_num,
+                                        priv->bss_type)));
+
+       mwifiex_dbg(adapter, CMD,
+                   "cmd: DNLD_CMD: %#x, act %#x, len %d, seqno %#x\n",
+               le16_to_cpu(sleep_cfm_buf->command),
+               le16_to_cpu(sleep_cfm_buf->action),
+               le16_to_cpu(sleep_cfm_buf->size),
+               le16_to_cpu(sleep_cfm_buf->seq_num));
+       mwifiex_dbg_dump(adapter, CMD_D, "SLEEP_CFM buffer: ", sleep_cfm_buf,
+                        le16_to_cpu(sleep_cfm_buf->size));
+
+       if (adapter->iface_type == MWIFIEX_USB) {
+               sleep_cfm_tmp =
+                       dev_alloc_skb(sizeof(struct mwifiex_opt_sleep_confirm)
+                                     + MWIFIEX_TYPE_LEN);
+               skb_put(sleep_cfm_tmp, sizeof(struct mwifiex_opt_sleep_confirm)
+                       + MWIFIEX_TYPE_LEN);
+               tmp = cpu_to_le32(MWIFIEX_USB_TYPE_CMD);
+               memcpy(sleep_cfm_tmp->data, &tmp, MWIFIEX_TYPE_LEN);
+               memcpy(sleep_cfm_tmp->data + MWIFIEX_TYPE_LEN,
+                      adapter->sleep_cfm->data,
+                      sizeof(struct mwifiex_opt_sleep_confirm));
+               ret = adapter->if_ops.host_to_card(adapter,
+                                                  MWIFIEX_USB_EP_CMD_EVENT,
+                                                  sleep_cfm_tmp, NULL);
+               if (ret != -EBUSY)
+                       dev_kfree_skb_any(sleep_cfm_tmp);
+       } else {
+               skb_push(adapter->sleep_cfm, INTF_HEADER_LEN);
+               ret = adapter->if_ops.host_to_card(adapter, MWIFIEX_TYPE_CMD,
+                                                  adapter->sleep_cfm, NULL);
+               skb_pull(adapter->sleep_cfm, INTF_HEADER_LEN);
+       }
+
+       if (ret == -1) {
+               mwifiex_dbg(adapter, ERROR, "SLEEP_CFM: failed\n");
+               adapter->dbg.num_cmd_sleep_cfm_host_to_card_failure++;
+               return -1;
+       }
+
+       if (!le16_to_cpu(sleep_cfm_buf->resp_ctrl))
+               /* Response is not needed for sleep confirm command */
+               adapter->ps_state = PS_STATE_SLEEP;
+       else
+               adapter->ps_state = PS_STATE_SLEEP_CFM;
+
+       if (!le16_to_cpu(sleep_cfm_buf->resp_ctrl) &&
+           (adapter->is_hs_configured &&
+            !adapter->sleep_period.period)) {
+               adapter->pm_wakeup_card_req = true;
+               mwifiex_hs_activated_event(mwifiex_get_priv
+                               (adapter, MWIFIEX_BSS_ROLE_ANY), true);
+       }
+
+       return ret;
+}
+
+/*
+ * This function allocates the command buffers and links them to
+ * the command free queue.
+ *
+ * The driver uses a pre allocated number of command buffers, which
+ * are created at driver initializations and freed at driver cleanup.
+ * Every command needs to obtain a command buffer from this pool before
+ * it can be issued. The command free queue lists the command buffers
+ * currently free to use, while the command pending queue lists the
+ * command buffers already in use and awaiting handling. Command buffers
+ * are returned to the free queue after use.
+ */
+int mwifiex_alloc_cmd_buffer(struct mwifiex_adapter *adapter)
+{
+       struct cmd_ctrl_node *cmd_array;
+       u32 i;
+
+       /* Allocate and initialize struct cmd_ctrl_node */
+       cmd_array = kcalloc(MWIFIEX_NUM_OF_CMD_BUFFER,
+                           sizeof(struct cmd_ctrl_node), GFP_KERNEL);
+       if (!cmd_array)
+               return -ENOMEM;
+
+       adapter->cmd_pool = cmd_array;
+
+       /* Allocate and initialize command buffers */
+       for (i = 0; i < MWIFIEX_NUM_OF_CMD_BUFFER; i++) {
+               cmd_array[i].skb = dev_alloc_skb(MWIFIEX_SIZE_OF_CMD_BUFFER);
+               if (!cmd_array[i].skb) {
+                       mwifiex_dbg(adapter, ERROR,
+                                   "unable to allocate command buffer\n");
+                       return -ENOMEM;
+               }
+       }
+
+       for (i = 0; i < MWIFIEX_NUM_OF_CMD_BUFFER; i++)
+               mwifiex_insert_cmd_to_free_q(adapter, &cmd_array[i]);
+
+       return 0;
+}
+
+/*
+ * This function frees the command buffers.
+ *
+ * The function calls the completion callback for all the command
+ * buffers that still have response buffers associated with them.
+ */
+int mwifiex_free_cmd_buffer(struct mwifiex_adapter *adapter)
+{
+       struct cmd_ctrl_node *cmd_array;
+       u32 i;
+
+       /* Need to check if cmd pool is allocated or not */
+       if (!adapter->cmd_pool) {
+               mwifiex_dbg(adapter, FATAL,
+                           "info: FREE_CMD_BUF: cmd_pool is null\n");
+               return 0;
+       }
+
+       cmd_array = adapter->cmd_pool;
+
+       /* Release shared memory buffers */
+       for (i = 0; i < MWIFIEX_NUM_OF_CMD_BUFFER; i++) {
+               if (cmd_array[i].skb) {
+                       mwifiex_dbg(adapter, CMD,
+                                   "cmd: free cmd buffer %d\n", i);
+                       dev_kfree_skb_any(cmd_array[i].skb);
+               }
+               if (!cmd_array[i].resp_skb)
+                       continue;
+
+               if (adapter->iface_type == MWIFIEX_USB)
+                       adapter->if_ops.cmdrsp_complete(adapter,
+                                                       cmd_array[i].resp_skb);
+               else
+                       dev_kfree_skb_any(cmd_array[i].resp_skb);
+       }
+       /* Release struct cmd_ctrl_node */
+       if (adapter->cmd_pool) {
+               mwifiex_dbg(adapter, CMD,
+                           "cmd: free cmd pool\n");
+               kfree(adapter->cmd_pool);
+               adapter->cmd_pool = NULL;
+       }
+
+       return 0;
+}
+
+/*
+ * This function handles events generated by firmware.
+ *
+ * Event body of events received from firmware are not used (though they are
+ * saved), only the event ID is used. Some events are re-invoked by
+ * the driver, with a new event body.
+ *
+ * After processing, the function calls the completion callback
+ * for cleanup.
+ */
+int mwifiex_process_event(struct mwifiex_adapter *adapter)
+{
+       int ret;
+       struct mwifiex_private *priv =
+               mwifiex_get_priv(adapter, MWIFIEX_BSS_ROLE_ANY);
+       struct sk_buff *skb = adapter->event_skb;
+       u32 eventcause = adapter->event_cause;
+       struct mwifiex_rxinfo *rx_info;
+
+       /* Save the last event to debug log */
+       adapter->dbg.last_event_index =
+                       (adapter->dbg.last_event_index + 1) % DBG_CMD_NUM;
+       adapter->dbg.last_event[adapter->dbg.last_event_index] =
+                                                       (u16) eventcause;
+
+       /* Get BSS number and corresponding priv */
+       priv = mwifiex_get_priv_by_id(adapter, EVENT_GET_BSS_NUM(eventcause),
+                                     EVENT_GET_BSS_TYPE(eventcause));
+       if (!priv)
+               priv = mwifiex_get_priv(adapter, MWIFIEX_BSS_ROLE_ANY);
+
+       /* Clear BSS_NO_BITS from event */
+       eventcause &= EVENT_ID_MASK;
+       adapter->event_cause = eventcause;
+
+       if (skb) {
+               rx_info = MWIFIEX_SKB_RXCB(skb);
+               memset(rx_info, 0, sizeof(*rx_info));
+               rx_info->bss_num = priv->bss_num;
+               rx_info->bss_type = priv->bss_type;
+               mwifiex_dbg_dump(adapter, EVT_D, "Event Buf:",
+                                skb->data, skb->len);
+       }
+
+       mwifiex_dbg(adapter, EVENT, "EVENT: cause: %#x\n", eventcause);
+
+       if (priv->bss_role == MWIFIEX_BSS_ROLE_UAP)
+               ret = mwifiex_process_uap_event(priv);
+       else
+               ret = mwifiex_process_sta_event(priv);
+
+       adapter->event_cause = 0;
+       adapter->event_skb = NULL;
+       adapter->if_ops.event_complete(adapter, skb);
+
+       return ret;
+}
+
+/*
+ * This function prepares a command and send it to the firmware.
+ *
+ * Preparation includes -
+ *      - Sanity tests to make sure the card is still present or the FW
+ *        is not reset
+ *      - Getting a new command node from the command free queue
+ *      - Initializing the command node for default parameters
+ *      - Fill up the non-default parameters and buffer pointers
+ *      - Add the command to pending queue
+ */
+int mwifiex_send_cmd(struct mwifiex_private *priv, u16 cmd_no,
+                    u16 cmd_action, u32 cmd_oid, void *data_buf, bool sync)
+{
+       int ret;
+       struct mwifiex_adapter *adapter = priv->adapter;
+       struct cmd_ctrl_node *cmd_node;
+       struct host_cmd_ds_command *cmd_ptr;
+
+       if (!adapter) {
+               pr_err("PREP_CMD: adapter is NULL\n");
+               return -1;
+       }
+
+       if (adapter->is_suspended) {
+               mwifiex_dbg(adapter, ERROR,
+                           "PREP_CMD: device in suspended state\n");
+               return -1;
+       }
+
+       if (adapter->hs_enabling && cmd_no != HostCmd_CMD_802_11_HS_CFG_ENH) {
+               mwifiex_dbg(adapter, ERROR,
+                           "PREP_CMD: host entering sleep state\n");
+               return -1;
+       }
+
+       if (adapter->surprise_removed) {
+               mwifiex_dbg(adapter, ERROR,
+                           "PREP_CMD: card is removed\n");
+               return -1;
+       }
+
+       if (adapter->is_cmd_timedout) {
+               mwifiex_dbg(adapter, ERROR,
+                           "PREP_CMD: FW is in bad state\n");
+               return -1;
+       }
+
+       if (adapter->hw_status == MWIFIEX_HW_STATUS_RESET) {
+               if (cmd_no != HostCmd_CMD_FUNC_INIT) {
+                       mwifiex_dbg(adapter, ERROR,
+                                   "PREP_CMD: FW in reset state\n");
+                       return -1;
+               }
+       }
+
+       /* Get a new command node */
+       cmd_node = mwifiex_get_cmd_node(adapter);
+
+       if (!cmd_node) {
+               mwifiex_dbg(adapter, ERROR,
+                           "PREP_CMD: no free cmd node\n");
+               return -1;
+       }
+
+       /* Initialize the command node */
+       mwifiex_init_cmd_node(priv, cmd_node, cmd_oid, data_buf, sync);
+
+       if (!cmd_node->cmd_skb) {
+               mwifiex_dbg(adapter, ERROR,
+                           "PREP_CMD: no free cmd buf\n");
+               return -1;
+       }
+
+       memset(skb_put(cmd_node->cmd_skb, sizeof(struct host_cmd_ds_command)),
+              0, sizeof(struct host_cmd_ds_command));
+
+       cmd_ptr = (struct host_cmd_ds_command *) (cmd_node->cmd_skb->data);
+       cmd_ptr->command = cpu_to_le16(cmd_no);
+       cmd_ptr->result = 0;
+
+       /* Prepare command */
+       if (cmd_no) {
+               switch (cmd_no) {
+               case HostCmd_CMD_UAP_SYS_CONFIG:
+               case HostCmd_CMD_UAP_BSS_START:
+               case HostCmd_CMD_UAP_BSS_STOP:
+               case HostCmd_CMD_UAP_STA_DEAUTH:
+               case HOST_CMD_APCMD_SYS_RESET:
+               case HOST_CMD_APCMD_STA_LIST:
+                       ret = mwifiex_uap_prepare_cmd(priv, cmd_no, cmd_action,
+                                                     cmd_oid, data_buf,
+                                                     cmd_ptr);
+                       break;
+               default:
+                       ret = mwifiex_sta_prepare_cmd(priv, cmd_no, cmd_action,
+                                                     cmd_oid, data_buf,
+                                                     cmd_ptr);
+                       break;
+               }
+       } else {
+               ret = mwifiex_cmd_host_cmd(priv, cmd_ptr, data_buf);
+               cmd_node->cmd_flag |= CMD_F_HOSTCMD;
+       }
+
+       /* Return error, since the command preparation failed */
+       if (ret) {
+               mwifiex_dbg(adapter, ERROR,
+                           "PREP_CMD: cmd %#x preparation failed\n",
+                       cmd_no);
+               mwifiex_insert_cmd_to_free_q(adapter, cmd_node);
+               return -1;
+       }
+
+       /* Send command */
+       if (cmd_no == HostCmd_CMD_802_11_SCAN ||
+           cmd_no == HostCmd_CMD_802_11_SCAN_EXT) {
+               mwifiex_queue_scan_cmd(priv, cmd_node);
+       } else {
+               mwifiex_insert_cmd_to_pending_q(adapter, cmd_node, true);
+               queue_work(adapter->workqueue, &adapter->main_work);
+               if (cmd_node->wait_q_enabled)
+                       ret = mwifiex_wait_queue_complete(adapter, cmd_node);
+       }
+
+       return ret;
+}
+
+/*
+ * This function returns a command to the command free queue.
+ *
+ * The function also calls the completion callback if required, before
+ * cleaning the command node and re-inserting it into the free queue.
+ */
+void
+mwifiex_insert_cmd_to_free_q(struct mwifiex_adapter *adapter,
+                            struct cmd_ctrl_node *cmd_node)
+{
+       unsigned long flags;
+
+       if (!cmd_node)
+               return;
+
+       if (cmd_node->wait_q_enabled)
+               mwifiex_complete_cmd(adapter, cmd_node);
+       /* Clean the node */
+       mwifiex_clean_cmd_node(adapter, cmd_node);
+
+       /* Insert node into cmd_free_q */
+       spin_lock_irqsave(&adapter->cmd_free_q_lock, flags);
+       list_add_tail(&cmd_node->list, &adapter->cmd_free_q);
+       spin_unlock_irqrestore(&adapter->cmd_free_q_lock, flags);
+}
+
+/* This function reuses a command node. */
+void mwifiex_recycle_cmd_node(struct mwifiex_adapter *adapter,
+                             struct cmd_ctrl_node *cmd_node)
+{
+       struct host_cmd_ds_command *host_cmd = (void *)cmd_node->cmd_skb->data;
+
+       mwifiex_insert_cmd_to_free_q(adapter, cmd_node);
+
+       atomic_dec(&adapter->cmd_pending);
+       mwifiex_dbg(adapter, CMD,
+                   "cmd: FREE_CMD: cmd=%#x, cmd_pending=%d\n",
+               le16_to_cpu(host_cmd->command),
+               atomic_read(&adapter->cmd_pending));
+}
+
+/*
+ * This function queues a command to the command pending queue.
+ *
+ * This in effect adds the command to the command list to be executed.
+ * Exit PS command is handled specially, by placing it always to the
+ * front of the command queue.
+ */
+void
+mwifiex_insert_cmd_to_pending_q(struct mwifiex_adapter *adapter,
+                               struct cmd_ctrl_node *cmd_node, u32 add_tail)
+{
+       struct host_cmd_ds_command *host_cmd = NULL;
+       u16 command;
+       unsigned long flags;
+
+       host_cmd = (struct host_cmd_ds_command *) (cmd_node->cmd_skb->data);
+       if (!host_cmd) {
+               mwifiex_dbg(adapter, ERROR, "QUEUE_CMD: host_cmd is NULL\n");
+               return;
+       }
+
+       command = le16_to_cpu(host_cmd->command);
+
+       /* Exit_PS command needs to be queued in the header always. */
+       if (command == HostCmd_CMD_802_11_PS_MODE_ENH) {
+               struct host_cmd_ds_802_11_ps_mode_enh *pm =
+                                               &host_cmd->params.psmode_enh;
+               if ((le16_to_cpu(pm->action) == DIS_PS) ||
+                   (le16_to_cpu(pm->action) == DIS_AUTO_PS)) {
+                       if (adapter->ps_state != PS_STATE_AWAKE)
+                               add_tail = false;
+               }
+       }
+
+       spin_lock_irqsave(&adapter->cmd_pending_q_lock, flags);
+       if (add_tail)
+               list_add_tail(&cmd_node->list, &adapter->cmd_pending_q);
+       else
+               list_add(&cmd_node->list, &adapter->cmd_pending_q);
+       spin_unlock_irqrestore(&adapter->cmd_pending_q_lock, flags);
+
+       atomic_inc(&adapter->cmd_pending);
+       mwifiex_dbg(adapter, CMD,
+                   "cmd: QUEUE_CMD: cmd=%#x, cmd_pending=%d\n",
+               command, atomic_read(&adapter->cmd_pending));
+}
+
+/*
+ * This function executes the next command in command pending queue.
+ *
+ * This function will fail if a command is already in processing stage,
+ * otherwise it will dequeue the first command from the command pending
+ * queue and send to the firmware.
+ *
+ * If the device is currently in host sleep mode, any commands, except the
+ * host sleep configuration command will de-activate the host sleep. For PS
+ * mode, the function will put the firmware back to sleep if applicable.
+ */
+int mwifiex_exec_next_cmd(struct mwifiex_adapter *adapter)
+{
+       struct mwifiex_private *priv;
+       struct cmd_ctrl_node *cmd_node;
+       int ret = 0;
+       struct host_cmd_ds_command *host_cmd;
+       unsigned long cmd_flags;
+       unsigned long cmd_pending_q_flags;
+
+       /* Check if already in processing */
+       if (adapter->curr_cmd) {
+               mwifiex_dbg(adapter, FATAL,
+                           "EXEC_NEXT_CMD: cmd in processing\n");
+               return -1;
+       }
+
+       spin_lock_irqsave(&adapter->mwifiex_cmd_lock, cmd_flags);
+       /* Check if any command is pending */
+       spin_lock_irqsave(&adapter->cmd_pending_q_lock, cmd_pending_q_flags);
+       if (list_empty(&adapter->cmd_pending_q)) {
+               spin_unlock_irqrestore(&adapter->cmd_pending_q_lock,
+                                      cmd_pending_q_flags);
+               spin_unlock_irqrestore(&adapter->mwifiex_cmd_lock, cmd_flags);
+               return 0;
+       }
+       cmd_node = list_first_entry(&adapter->cmd_pending_q,
+                                   struct cmd_ctrl_node, list);
+       spin_unlock_irqrestore(&adapter->cmd_pending_q_lock,
+                              cmd_pending_q_flags);
+
+       host_cmd = (struct host_cmd_ds_command *) (cmd_node->cmd_skb->data);
+       priv = cmd_node->priv;
+
+       if (adapter->ps_state != PS_STATE_AWAKE) {
+               mwifiex_dbg(adapter, ERROR,
+                           "%s: cannot send cmd in sleep state,\t"
+                           "this should not happen\n", __func__);
+               spin_unlock_irqrestore(&adapter->mwifiex_cmd_lock, cmd_flags);
+               return ret;
+       }
+
+       spin_lock_irqsave(&adapter->cmd_pending_q_lock, cmd_pending_q_flags);
+       list_del(&cmd_node->list);
+       spin_unlock_irqrestore(&adapter->cmd_pending_q_lock,
+                              cmd_pending_q_flags);
+
+       spin_unlock_irqrestore(&adapter->mwifiex_cmd_lock, cmd_flags);
+       ret = mwifiex_dnld_cmd_to_fw(priv, cmd_node);
+       priv = mwifiex_get_priv(adapter, MWIFIEX_BSS_ROLE_ANY);
+       /* Any command sent to the firmware when host is in sleep
+        * mode should de-configure host sleep. We should skip the
+        * host sleep configuration command itself though
+        */
+       if (priv && (host_cmd->command !=
+            cpu_to_le16(HostCmd_CMD_802_11_HS_CFG_ENH))) {
+               if (adapter->hs_activated) {
+                       adapter->is_hs_configured = false;
+                       mwifiex_hs_activated_event(priv, false);
+               }
+       }
+
+       return ret;
+}
+
+/*
+ * This function handles the command response.
+ *
+ * After processing, the function cleans the command node and puts
+ * it back to the command free queue.
+ */
+int mwifiex_process_cmdresp(struct mwifiex_adapter *adapter)
+{
+       struct host_cmd_ds_command *resp;
+       struct mwifiex_private *priv =
+               mwifiex_get_priv(adapter, MWIFIEX_BSS_ROLE_ANY);
+       int ret = 0;
+       uint16_t orig_cmdresp_no;
+       uint16_t cmdresp_no;
+       uint16_t cmdresp_result;
+       unsigned long flags;
+
+       /* Now we got response from FW, cancel the command timer */
+       del_timer_sync(&adapter->cmd_timer);
+
+       if (!adapter->curr_cmd || !adapter->curr_cmd->resp_skb) {
+               resp = (struct host_cmd_ds_command *) adapter->upld_buf;
+               mwifiex_dbg(adapter, ERROR,
+                           "CMD_RESP: NULL curr_cmd, %#x\n",
+                           le16_to_cpu(resp->command));
+               return -1;
+       }
+
+       adapter->is_cmd_timedout = 0;
+
+       resp = (struct host_cmd_ds_command *) adapter->curr_cmd->resp_skb->data;
+       if (adapter->curr_cmd->cmd_flag & CMD_F_HOSTCMD) {
+               /* Copy original response back to response buffer */
+               struct mwifiex_ds_misc_cmd *hostcmd;
+               uint16_t size = le16_to_cpu(resp->size);
+               mwifiex_dbg(adapter, INFO,
+                           "info: host cmd resp size = %d\n", size);
+               size = min_t(u16, size, MWIFIEX_SIZE_OF_CMD_BUFFER);
+               if (adapter->curr_cmd->data_buf) {
+                       hostcmd = adapter->curr_cmd->data_buf;
+                       hostcmd->len = size;
+                       memcpy(hostcmd->cmd, resp, size);
+               }
+       }
+       orig_cmdresp_no = le16_to_cpu(resp->command);
+
+       /* Get BSS number and corresponding priv */
+       priv = mwifiex_get_priv_by_id(adapter,
+                            HostCmd_GET_BSS_NO(le16_to_cpu(resp->seq_num)),
+                            HostCmd_GET_BSS_TYPE(le16_to_cpu(resp->seq_num)));
+       if (!priv)
+               priv = mwifiex_get_priv(adapter, MWIFIEX_BSS_ROLE_ANY);
+       /* Clear RET_BIT from HostCmd */
+       resp->command = cpu_to_le16(orig_cmdresp_no & HostCmd_CMD_ID_MASK);
+
+       cmdresp_no = le16_to_cpu(resp->command);
+       cmdresp_result = le16_to_cpu(resp->result);
+
+       /* Save the last command response to debug log */
+       adapter->dbg.last_cmd_resp_index =
+                       (adapter->dbg.last_cmd_resp_index + 1) % DBG_CMD_NUM;
+       adapter->dbg.last_cmd_resp_id[adapter->dbg.last_cmd_resp_index] =
+                                                               orig_cmdresp_no;
+
+       mwifiex_dbg(adapter, CMD,
+                   "cmd: CMD_RESP: 0x%x, result %d, len %d, seqno 0x%x\n",
+                   orig_cmdresp_no, cmdresp_result,
+                   le16_to_cpu(resp->size), le16_to_cpu(resp->seq_num));
+       mwifiex_dbg_dump(adapter, CMD_D, "CMD_RESP buffer:", resp,
+                        le16_to_cpu(resp->size));
+
+       if (!(orig_cmdresp_no & HostCmd_RET_BIT)) {
+               mwifiex_dbg(adapter, ERROR, "CMD_RESP: invalid cmd resp\n");
+               if (adapter->curr_cmd->wait_q_enabled)
+                       adapter->cmd_wait_q.status = -1;
+
+               mwifiex_recycle_cmd_node(adapter, adapter->curr_cmd);
+               spin_lock_irqsave(&adapter->mwifiex_cmd_lock, flags);
+               adapter->curr_cmd = NULL;
+               spin_unlock_irqrestore(&adapter->mwifiex_cmd_lock, flags);
+               return -1;
+       }
+
+       if (adapter->curr_cmd->cmd_flag & CMD_F_HOSTCMD) {
+               adapter->curr_cmd->cmd_flag &= ~CMD_F_HOSTCMD;
+               if ((cmdresp_result == HostCmd_RESULT_OK) &&
+                   (cmdresp_no == HostCmd_CMD_802_11_HS_CFG_ENH))
+                       ret = mwifiex_ret_802_11_hs_cfg(priv, resp);
+       } else {
+               /* handle response */
+               ret = mwifiex_process_sta_cmdresp(priv, cmdresp_no, resp);
+       }
+
+       /* Check init command response */
+       if (adapter->hw_status == MWIFIEX_HW_STATUS_INITIALIZING) {
+               if (ret) {
+                       mwifiex_dbg(adapter, ERROR,
+                                   "%s: cmd %#x failed during\t"
+                                   "initialization\n", __func__, cmdresp_no);
+                       mwifiex_init_fw_complete(adapter);
+                       return -1;
+               } else if (adapter->last_init_cmd == cmdresp_no)
+                       adapter->hw_status = MWIFIEX_HW_STATUS_INIT_DONE;
+       }
+
+       if (adapter->curr_cmd) {
+               if (adapter->curr_cmd->wait_q_enabled)
+                       adapter->cmd_wait_q.status = ret;
+
+               mwifiex_recycle_cmd_node(adapter, adapter->curr_cmd);
+
+               spin_lock_irqsave(&adapter->mwifiex_cmd_lock, flags);
+               adapter->curr_cmd = NULL;
+               spin_unlock_irqrestore(&adapter->mwifiex_cmd_lock, flags);
+       }
+
+       return ret;
+}
+
+/*
+ * This function handles the timeout of command sending.
+ *
+ * It will re-send the same command again.
+ */
+void
+mwifiex_cmd_timeout_func(unsigned long function_context)
+{
+       struct mwifiex_adapter *adapter =
+               (struct mwifiex_adapter *) function_context;
+       struct cmd_ctrl_node *cmd_node;
+
+       adapter->is_cmd_timedout = 1;
+       if (!adapter->curr_cmd) {
+               mwifiex_dbg(adapter, ERROR,
+                           "cmd: empty curr_cmd\n");
+               return;
+       }
+       cmd_node = adapter->curr_cmd;
+       if (cmd_node) {
+               adapter->dbg.timeout_cmd_id =
+                       adapter->dbg.last_cmd_id[adapter->dbg.last_cmd_index];
+               adapter->dbg.timeout_cmd_act =
+                       adapter->dbg.last_cmd_act[adapter->dbg.last_cmd_index];
+               mwifiex_dbg(adapter, MSG,
+                           "%s: Timeout cmd id = %#x, act = %#x\n", __func__,
+                           adapter->dbg.timeout_cmd_id,
+                           adapter->dbg.timeout_cmd_act);
+
+               mwifiex_dbg(adapter, MSG,
+                           "num_data_h2c_failure = %d\n",
+                           adapter->dbg.num_tx_host_to_card_failure);
+               mwifiex_dbg(adapter, MSG,
+                           "num_cmd_h2c_failure = %d\n",
+                           adapter->dbg.num_cmd_host_to_card_failure);
+
+               mwifiex_dbg(adapter, MSG,
+                           "is_cmd_timedout = %d\n",
+                           adapter->is_cmd_timedout);
+               mwifiex_dbg(adapter, MSG,
+                           "num_tx_timeout = %d\n",
+                           adapter->dbg.num_tx_timeout);
+
+               mwifiex_dbg(adapter, MSG,
+                           "last_cmd_index = %d\n",
+                           adapter->dbg.last_cmd_index);
+               mwifiex_dbg(adapter, MSG,
+                           "last_cmd_id: %*ph\n",
+                           (int)sizeof(adapter->dbg.last_cmd_id),
+                           adapter->dbg.last_cmd_id);
+               mwifiex_dbg(adapter, MSG,
+                           "last_cmd_act: %*ph\n",
+                           (int)sizeof(adapter->dbg.last_cmd_act),
+                           adapter->dbg.last_cmd_act);
+
+               mwifiex_dbg(adapter, MSG,
+                           "last_cmd_resp_index = %d\n",
+                           adapter->dbg.last_cmd_resp_index);
+               mwifiex_dbg(adapter, MSG,
+                           "last_cmd_resp_id: %*ph\n",
+                           (int)sizeof(adapter->dbg.last_cmd_resp_id),
+                           adapter->dbg.last_cmd_resp_id);
+
+               mwifiex_dbg(adapter, MSG,
+                           "last_event_index = %d\n",
+                           adapter->dbg.last_event_index);
+               mwifiex_dbg(adapter, MSG,
+                           "last_event: %*ph\n",
+                           (int)sizeof(adapter->dbg.last_event),
+                           adapter->dbg.last_event);
+
+               mwifiex_dbg(adapter, MSG,
+                           "data_sent=%d cmd_sent=%d\n",
+                           adapter->data_sent, adapter->cmd_sent);
+
+               mwifiex_dbg(adapter, MSG,
+                           "ps_mode=%d ps_state=%d\n",
+                           adapter->ps_mode, adapter->ps_state);
+
+               if (cmd_node->wait_q_enabled) {
+                       adapter->cmd_wait_q.status = -ETIMEDOUT;
+                       mwifiex_cancel_pending_ioctl(adapter);
+               }
+       }
+       if (adapter->hw_status == MWIFIEX_HW_STATUS_INITIALIZING) {
+               mwifiex_init_fw_complete(adapter);
+               return;
+       }
+
+       if (adapter->if_ops.device_dump)
+               adapter->if_ops.device_dump(adapter);
+
+       if (adapter->if_ops.card_reset)
+               adapter->if_ops.card_reset(adapter);
+}
+
+/*
+ * This function cancels all the pending commands.
+ *
+ * The current command, all commands in command pending queue and all scan
+ * commands in scan pending queue are cancelled. All the completion callbacks
+ * are called with failure status to ensure cleanup.
+ */
+void
+mwifiex_cancel_all_pending_cmd(struct mwifiex_adapter *adapter)
+{
+       struct cmd_ctrl_node *cmd_node = NULL, *tmp_node;
+       unsigned long flags, cmd_flags;
+       struct mwifiex_private *priv;
+       int i;
+
+       spin_lock_irqsave(&adapter->mwifiex_cmd_lock, cmd_flags);
+       /* Cancel current cmd */
+       if ((adapter->curr_cmd) && (adapter->curr_cmd->wait_q_enabled)) {
+               adapter->curr_cmd->wait_q_enabled = false;
+               adapter->cmd_wait_q.status = -1;
+               mwifiex_complete_cmd(adapter, adapter->curr_cmd);
+               /* no recycle probably wait for response */
+       }
+       /* Cancel all pending command */
+       spin_lock_irqsave(&adapter->cmd_pending_q_lock, flags);
+       list_for_each_entry_safe(cmd_node, tmp_node,
+                                &adapter->cmd_pending_q, list) {
+               list_del(&cmd_node->list);
+               spin_unlock_irqrestore(&adapter->cmd_pending_q_lock, flags);
+
+               if (cmd_node->wait_q_enabled)
+                       adapter->cmd_wait_q.status = -1;
+               mwifiex_recycle_cmd_node(adapter, cmd_node);
+               spin_lock_irqsave(&adapter->cmd_pending_q_lock, flags);
+       }
+       spin_unlock_irqrestore(&adapter->cmd_pending_q_lock, flags);
+       spin_unlock_irqrestore(&adapter->mwifiex_cmd_lock, cmd_flags);
+
+       /* Cancel all pending scan command */
+       spin_lock_irqsave(&adapter->scan_pending_q_lock, flags);
+       list_for_each_entry_safe(cmd_node, tmp_node,
+                                &adapter->scan_pending_q, list) {
+               list_del(&cmd_node->list);
+
+               cmd_node->wait_q_enabled = false;
+               mwifiex_insert_cmd_to_free_q(adapter, cmd_node);
+       }
+       spin_unlock_irqrestore(&adapter->scan_pending_q_lock, flags);
+
+       if (adapter->scan_processing) {
+               spin_lock_irqsave(&adapter->mwifiex_cmd_lock, cmd_flags);
+               adapter->scan_processing = false;
+               spin_unlock_irqrestore(&adapter->mwifiex_cmd_lock, cmd_flags);
+               for (i = 0; i < adapter->priv_num; i++) {
+                       priv = adapter->priv[i];
+                       if (!priv)
+                               continue;
+                       if (priv->scan_request) {
+                               mwifiex_dbg(adapter, WARN, "info: aborting scan\n");
+                               cfg80211_scan_done(priv->scan_request, 1);
+                               priv->scan_request = NULL;
+                       }
+               }
+       }
+}
+
+/*
+ * This function cancels all pending commands that matches with
+ * the given IOCTL request.
+ *
+ * Both the current command buffer and the pending command queue are
+ * searched for matching IOCTL request. The completion callback of
+ * the matched command is called with failure status to ensure cleanup.
+ * In case of scan commands, all pending commands in scan pending queue
+ * are cancelled.
+ */
+void
+mwifiex_cancel_pending_ioctl(struct mwifiex_adapter *adapter)
+{
+       struct cmd_ctrl_node *cmd_node = NULL, *tmp_node = NULL;
+       unsigned long cmd_flags;
+       unsigned long scan_pending_q_flags;
+       struct mwifiex_private *priv;
+       int i;
+
+       if ((adapter->curr_cmd) &&
+           (adapter->curr_cmd->wait_q_enabled)) {
+               spin_lock_irqsave(&adapter->mwifiex_cmd_lock, cmd_flags);
+               cmd_node = adapter->curr_cmd;
+               /* setting curr_cmd to NULL is quite dangerous, because
+                * mwifiex_process_cmdresp checks curr_cmd to be != NULL
+                * at the beginning then relies on it and dereferences
+                * it at will
+                * this probably works since mwifiex_cmd_timeout_func
+                * is the only caller of this function and responses
+                * at that point
+                */
+               adapter->curr_cmd = NULL;
+               spin_unlock_irqrestore(&adapter->mwifiex_cmd_lock, cmd_flags);
+
+               mwifiex_recycle_cmd_node(adapter, cmd_node);
+       }
+
+       /* Cancel all pending scan command */
+       spin_lock_irqsave(&adapter->scan_pending_q_lock,
+                         scan_pending_q_flags);
+       list_for_each_entry_safe(cmd_node, tmp_node,
+                                &adapter->scan_pending_q, list) {
+               list_del(&cmd_node->list);
+               cmd_node->wait_q_enabled = false;
+               mwifiex_insert_cmd_to_free_q(adapter, cmd_node);
+       }
+       spin_unlock_irqrestore(&adapter->scan_pending_q_lock,
+                              scan_pending_q_flags);
+
+       if (adapter->scan_processing) {
+               spin_lock_irqsave(&adapter->mwifiex_cmd_lock, cmd_flags);
+               adapter->scan_processing = false;
+               spin_unlock_irqrestore(&adapter->mwifiex_cmd_lock, cmd_flags);
+               for (i = 0; i < adapter->priv_num; i++) {
+                       priv = adapter->priv[i];
+                       if (!priv)
+                               continue;
+                       if (priv->scan_request) {
+                               mwifiex_dbg(adapter, WARN, "info: aborting scan\n");
+                               cfg80211_scan_done(priv->scan_request, 1);
+                               priv->scan_request = NULL;
+                       }
+               }
+       }
+}
+
+/*
+ * This function sends the sleep confirm command to firmware, if
+ * possible.
+ *
+ * The sleep confirm command cannot be issued if command response,
+ * data response or event response is awaiting handling, or if we
+ * are in the middle of sending a command, or expecting a command
+ * response.
+ */
+void
+mwifiex_check_ps_cond(struct mwifiex_adapter *adapter)
+{
+       if (!adapter->cmd_sent &&
+           !adapter->curr_cmd && !IS_CARD_RX_RCVD(adapter))
+               mwifiex_dnld_sleep_confirm_cmd(adapter);
+       else
+               mwifiex_dbg(adapter, CMD,
+                           "cmd: Delay Sleep Confirm (%s%s%s)\n",
+                           (adapter->cmd_sent) ? "D" : "",
+                           (adapter->curr_cmd) ? "C" : "",
+                           (IS_CARD_RX_RCVD(adapter)) ? "R" : "");
+}
+
+/*
+ * This function sends a Host Sleep activated event to applications.
+ *
+ * This event is generated by the driver, with a blank event body.
+ */
+void
+mwifiex_hs_activated_event(struct mwifiex_private *priv, u8 activated)
+{
+       if (activated) {
+               if (priv->adapter->is_hs_configured) {
+                       priv->adapter->hs_activated = true;
+                       mwifiex_update_rxreor_flags(priv->adapter,
+                                                   RXREOR_FORCE_NO_DROP);
+                       mwifiex_dbg(priv->adapter, EVENT,
+                                   "event: hs_activated\n");
+                       priv->adapter->hs_activate_wait_q_woken = true;
+                       wake_up_interruptible(
+                               &priv->adapter->hs_activate_wait_q);
+               } else {
+                       mwifiex_dbg(priv->adapter, EVENT,
+                                   "event: HS not configured\n");
+               }
+       } else {
+               mwifiex_dbg(priv->adapter, EVENT,
+                           "event: hs_deactivated\n");
+               priv->adapter->hs_activated = false;
+       }
+}
+
+/*
+ * This function handles the command response of a Host Sleep configuration
+ * command.
+ *
+ * Handling includes changing the header fields into CPU format
+ * and setting the current host sleep activation status in driver.
+ *
+ * In case host sleep status change, the function generates an event to
+ * notify the applications.
+ */
+int mwifiex_ret_802_11_hs_cfg(struct mwifiex_private *priv,
+                             struct host_cmd_ds_command *resp)
+{
+       struct mwifiex_adapter *adapter = priv->adapter;
+       struct host_cmd_ds_802_11_hs_cfg_enh *phs_cfg =
+               &resp->params.opt_hs_cfg;
+       uint32_t conditions = le32_to_cpu(phs_cfg->params.hs_config.conditions);
+
+       if (phs_cfg->action == cpu_to_le16(HS_ACTIVATE) &&
+           adapter->iface_type != MWIFIEX_USB) {
+               mwifiex_hs_activated_event(priv, true);
+               return 0;
+       } else {
+               mwifiex_dbg(adapter, CMD,
+                           "cmd: CMD_RESP: HS_CFG cmd reply\t"
+                           " result=%#x, conditions=0x%x gpio=0x%x gap=0x%x\n",
+                           resp->result, conditions,
+                           phs_cfg->params.hs_config.gpio,
+                           phs_cfg->params.hs_config.gap);
+       }
+       if (conditions != HS_CFG_CANCEL) {
+               adapter->is_hs_configured = true;
+               if (adapter->iface_type == MWIFIEX_USB)
+                       mwifiex_hs_activated_event(priv, true);
+       } else {
+               adapter->is_hs_configured = false;
+               if (adapter->hs_activated)
+                       mwifiex_hs_activated_event(priv, false);
+       }
+
+       return 0;
+}
+
+/*
+ * This function wakes up the adapter and generates a Host Sleep
+ * cancel event on receiving the power up interrupt.
+ */
+void
+mwifiex_process_hs_config(struct mwifiex_adapter *adapter)
+{
+       mwifiex_dbg(adapter, INFO,
+                   "info: %s: auto cancelling host sleep\t"
+                   "since there is interrupt from the firmware\n",
+                   __func__);
+
+       adapter->if_ops.wakeup(adapter);
+       adapter->hs_activated = false;
+       adapter->is_hs_configured = false;
+       adapter->is_suspended = false;
+       mwifiex_hs_activated_event(mwifiex_get_priv(adapter,
+                                                   MWIFIEX_BSS_ROLE_ANY),
+                                  false);
+}
+EXPORT_SYMBOL_GPL(mwifiex_process_hs_config);
+
+/*
+ * This function handles the command response of a sleep confirm command.
+ *
+ * The function sets the card state to SLEEP if the response indicates success.
+ */
+void
+mwifiex_process_sleep_confirm_resp(struct mwifiex_adapter *adapter,
+                                  u8 *pbuf, u32 upld_len)
+{
+       struct host_cmd_ds_command *cmd = (struct host_cmd_ds_command *) pbuf;
+       struct mwifiex_private *priv =
+               mwifiex_get_priv(adapter, MWIFIEX_BSS_ROLE_ANY);
+       uint16_t result = le16_to_cpu(cmd->result);
+       uint16_t command = le16_to_cpu(cmd->command);
+       uint16_t seq_num = le16_to_cpu(cmd->seq_num);
+
+       if (!upld_len) {
+               mwifiex_dbg(adapter, ERROR,
+                           "%s: cmd size is 0\n", __func__);
+               return;
+       }
+
+       mwifiex_dbg(adapter, CMD,
+                   "cmd: CMD_RESP: 0x%x, result %d, len %d, seqno 0x%x\n",
+                   command, result, le16_to_cpu(cmd->size), seq_num);
+
+       /* Get BSS number and corresponding priv */
+       priv = mwifiex_get_priv_by_id(adapter, HostCmd_GET_BSS_NO(seq_num),
+                                     HostCmd_GET_BSS_TYPE(seq_num));
+       if (!priv)
+               priv = mwifiex_get_priv(adapter, MWIFIEX_BSS_ROLE_ANY);
+
+       /* Update sequence number */
+       seq_num = HostCmd_GET_SEQ_NO(seq_num);
+       /* Clear RET_BIT from HostCmd */
+       command &= HostCmd_CMD_ID_MASK;
+
+       if (command != HostCmd_CMD_802_11_PS_MODE_ENH) {
+               mwifiex_dbg(adapter, ERROR,
+                           "%s: rcvd unexpected resp for cmd %#x, result = %x\n",
+                           __func__, command, result);
+               return;
+       }
+
+       if (result) {
+               mwifiex_dbg(adapter, ERROR,
+                           "%s: sleep confirm cmd failed\n",
+                           __func__);
+               adapter->pm_wakeup_card_req = false;
+               adapter->ps_state = PS_STATE_AWAKE;
+               return;
+       }
+       adapter->pm_wakeup_card_req = true;
+       if (adapter->is_hs_configured)
+               mwifiex_hs_activated_event(mwifiex_get_priv
+                                               (adapter, MWIFIEX_BSS_ROLE_ANY),
+                                          true);
+       adapter->ps_state = PS_STATE_SLEEP;
+       cmd->command = cpu_to_le16(command);
+       cmd->seq_num = cpu_to_le16(seq_num);
+}
+EXPORT_SYMBOL_GPL(mwifiex_process_sleep_confirm_resp);
+
+/*
+ * This function prepares an enhanced power mode command.
+ *
+ * This function can be used to disable power save or to configure
+ * power save with auto PS or STA PS or auto deep sleep.
+ *
+ * Preparation includes -
+ *      - Setting command ID, action and proper size
+ *      - Setting Power Save bitmap, PS parameters TLV, PS mode TLV,
+ *        auto deep sleep TLV (as required)
+ *      - Ensuring correct endian-ness
+ */
+int mwifiex_cmd_enh_power_mode(struct mwifiex_private *priv,
+                              struct host_cmd_ds_command *cmd,
+                              u16 cmd_action, uint16_t ps_bitmap,
+                              struct mwifiex_ds_auto_ds *auto_ds)
+{
+       struct host_cmd_ds_802_11_ps_mode_enh *psmode_enh =
+               &cmd->params.psmode_enh;
+       u8 *tlv;
+       u16 cmd_size = 0;
+
+       cmd->command = cpu_to_le16(HostCmd_CMD_802_11_PS_MODE_ENH);
+       if (cmd_action == DIS_AUTO_PS) {
+               psmode_enh->action = cpu_to_le16(DIS_AUTO_PS);
+               psmode_enh->params.ps_bitmap = cpu_to_le16(ps_bitmap);
+               cmd->size = cpu_to_le16(S_DS_GEN + sizeof(psmode_enh->action) +
+                                       sizeof(psmode_enh->params.ps_bitmap));
+       } else if (cmd_action == GET_PS) {
+               psmode_enh->action = cpu_to_le16(GET_PS);
+               psmode_enh->params.ps_bitmap = cpu_to_le16(ps_bitmap);
+               cmd->size = cpu_to_le16(S_DS_GEN + sizeof(psmode_enh->action) +
+                                       sizeof(psmode_enh->params.ps_bitmap));
+       } else if (cmd_action == EN_AUTO_PS) {
+               psmode_enh->action = cpu_to_le16(EN_AUTO_PS);
+               psmode_enh->params.ps_bitmap = cpu_to_le16(ps_bitmap);
+               cmd_size = S_DS_GEN + sizeof(psmode_enh->action) +
+                                       sizeof(psmode_enh->params.ps_bitmap);
+               tlv = (u8 *) cmd + cmd_size;
+               if (ps_bitmap & BITMAP_STA_PS) {
+                       struct mwifiex_adapter *adapter = priv->adapter;
+                       struct mwifiex_ie_types_ps_param *ps_tlv =
+                               (struct mwifiex_ie_types_ps_param *) tlv;
+                       struct mwifiex_ps_param *ps_mode = &ps_tlv->param;
+                       ps_tlv->header.type = cpu_to_le16(TLV_TYPE_PS_PARAM);
+                       ps_tlv->header.len = cpu_to_le16(sizeof(*ps_tlv) -
+                                       sizeof(struct mwifiex_ie_types_header));
+                       cmd_size += sizeof(*ps_tlv);
+                       tlv += sizeof(*ps_tlv);
+                       mwifiex_dbg(priv->adapter, CMD,
+                                   "cmd: PS Command: Enter PS\n");
+                       ps_mode->null_pkt_interval =
+                                       cpu_to_le16(adapter->null_pkt_interval);
+                       ps_mode->multiple_dtims =
+                                       cpu_to_le16(adapter->multiple_dtim);
+                       ps_mode->bcn_miss_timeout =
+                                       cpu_to_le16(adapter->bcn_miss_time_out);
+                       ps_mode->local_listen_interval =
+                               cpu_to_le16(adapter->local_listen_interval);
+                       ps_mode->adhoc_wake_period =
+                               cpu_to_le16(adapter->adhoc_awake_period);
+                       ps_mode->delay_to_ps =
+                                       cpu_to_le16(adapter->delay_to_ps);
+                       ps_mode->mode = cpu_to_le16(adapter->enhanced_ps_mode);
+
+               }
+               if (ps_bitmap & BITMAP_AUTO_DS) {
+                       struct mwifiex_ie_types_auto_ds_param *auto_ds_tlv =
+                               (struct mwifiex_ie_types_auto_ds_param *) tlv;
+                       u16 idletime = 0;
+
+                       auto_ds_tlv->header.type =
+                               cpu_to_le16(TLV_TYPE_AUTO_DS_PARAM);
+                       auto_ds_tlv->header.len =
+                               cpu_to_le16(sizeof(*auto_ds_tlv) -
+                                       sizeof(struct mwifiex_ie_types_header));
+                       cmd_size += sizeof(*auto_ds_tlv);
+                       tlv += sizeof(*auto_ds_tlv);
+                       if (auto_ds)
+                               idletime = auto_ds->idle_time;
+                       mwifiex_dbg(priv->adapter, CMD,
+                                   "cmd: PS Command: Enter Auto Deep Sleep\n");
+                       auto_ds_tlv->deep_sleep_timeout = cpu_to_le16(idletime);
+               }
+               cmd->size = cpu_to_le16(cmd_size);
+       }
+       return 0;
+}
+
+/*
+ * This function handles the command response of an enhanced power mode
+ * command.
+ *
+ * Handling includes changing the header fields into CPU format
+ * and setting the current enhanced power mode in driver.
+ */
+int mwifiex_ret_enh_power_mode(struct mwifiex_private *priv,
+                              struct host_cmd_ds_command *resp,
+                              struct mwifiex_ds_pm_cfg *pm_cfg)
+{
+       struct mwifiex_adapter *adapter = priv->adapter;
+       struct host_cmd_ds_802_11_ps_mode_enh *ps_mode =
+               &resp->params.psmode_enh;
+       uint16_t action = le16_to_cpu(ps_mode->action);
+       uint16_t ps_bitmap = le16_to_cpu(ps_mode->params.ps_bitmap);
+       uint16_t auto_ps_bitmap =
+               le16_to_cpu(ps_mode->params.ps_bitmap);
+
+       mwifiex_dbg(adapter, INFO,
+                   "info: %s: PS_MODE cmd reply result=%#x action=%#X\n",
+                   __func__, resp->result, action);
+       if (action == EN_AUTO_PS) {
+               if (auto_ps_bitmap & BITMAP_AUTO_DS) {
+                       mwifiex_dbg(adapter, CMD,
+                                   "cmd: Enabled auto deep sleep\n");
+                       priv->adapter->is_deep_sleep = true;
+               }
+               if (auto_ps_bitmap & BITMAP_STA_PS) {
+                       mwifiex_dbg(adapter, CMD,
+                                   "cmd: Enabled STA power save\n");
+                       if (adapter->sleep_period.period)
+                               mwifiex_dbg(adapter, CMD,
+                                           "cmd: set to uapsd/pps mode\n");
+               }
+       } else if (action == DIS_AUTO_PS) {
+               if (ps_bitmap & BITMAP_AUTO_DS) {
+                       priv->adapter->is_deep_sleep = false;
+                       mwifiex_dbg(adapter, CMD,
+                                   "cmd: Disabled auto deep sleep\n");
+               }
+               if (ps_bitmap & BITMAP_STA_PS) {
+                       mwifiex_dbg(adapter, CMD,
+                                   "cmd: Disabled STA power save\n");
+                       if (adapter->sleep_period.period) {
+                               adapter->delay_null_pkt = false;
+                               adapter->tx_lock_flag = false;
+                               adapter->pps_uapsd_mode = false;
+                       }
+               }
+       } else if (action == GET_PS) {
+               if (ps_bitmap & BITMAP_STA_PS)
+                       adapter->ps_mode = MWIFIEX_802_11_POWER_MODE_PSP;
+               else
+                       adapter->ps_mode = MWIFIEX_802_11_POWER_MODE_CAM;
+
+               mwifiex_dbg(adapter, CMD,
+                           "cmd: ps_bitmap=%#x\n", ps_bitmap);
+
+               if (pm_cfg) {
+                       /* This section is for get power save mode */
+                       if (ps_bitmap & BITMAP_STA_PS)
+                               pm_cfg->param.ps_mode = 1;
+                       else
+                               pm_cfg->param.ps_mode = 0;
+               }
+       }
+       return 0;
+}
+
+/*
+ * This function prepares command to get hardware specifications.
+ *
+ * Preparation includes -
+ *      - Setting command ID, action and proper size
+ *      - Setting permanent address parameter
+ *      - Ensuring correct endian-ness
+ */
+int mwifiex_cmd_get_hw_spec(struct mwifiex_private *priv,
+                           struct host_cmd_ds_command *cmd)
+{
+       struct host_cmd_ds_get_hw_spec *hw_spec = &cmd->params.hw_spec;
+
+       cmd->command = cpu_to_le16(HostCmd_CMD_GET_HW_SPEC);
+       cmd->size =
+               cpu_to_le16(sizeof(struct host_cmd_ds_get_hw_spec) + S_DS_GEN);
+       memcpy(hw_spec->permanent_addr, priv->curr_addr, ETH_ALEN);
+
+       return 0;
+}
+
+/*
+ * This function handles the command response of get hardware
+ * specifications.
+ *
+ * Handling includes changing the header fields into CPU format
+ * and saving/updating the following parameters in driver -
+ *      - Firmware capability information
+ *      - Firmware band settings
+ *      - Ad-hoc start band and channel
+ *      - Ad-hoc 11n activation status
+ *      - Firmware release number
+ *      - Number of antennas
+ *      - Hardware address
+ *      - Hardware interface version
+ *      - Firmware version
+ *      - Region code
+ *      - 11n capabilities
+ *      - MCS support fields
+ *      - MP end port
+ */
+int mwifiex_ret_get_hw_spec(struct mwifiex_private *priv,
+                           struct host_cmd_ds_command *resp)
+{
+       struct host_cmd_ds_get_hw_spec *hw_spec = &resp->params.hw_spec;
+       struct mwifiex_adapter *adapter = priv->adapter;
+       struct mwifiex_ie_types_header *tlv;
+       struct hw_spec_api_rev *api_rev;
+       u16 resp_size, api_id;
+       int i, left_len, parsed_len = 0;
+
+       adapter->fw_cap_info = le32_to_cpu(hw_spec->fw_cap_info);
+
+       if (IS_SUPPORT_MULTI_BANDS(adapter))
+               adapter->fw_bands = (u8) GET_FW_DEFAULT_BANDS(adapter);
+       else
+               adapter->fw_bands = BAND_B;
+
+       adapter->config_bands = adapter->fw_bands;
+
+       if (adapter->fw_bands & BAND_A) {
+               if (adapter->fw_bands & BAND_GN) {
+                       adapter->config_bands |= BAND_AN;
+                       adapter->fw_bands |= BAND_AN;
+               }
+               if (adapter->fw_bands & BAND_AN) {
+                       adapter->adhoc_start_band = BAND_A | BAND_AN;
+                       adapter->adhoc_11n_enabled = true;
+               } else {
+                       adapter->adhoc_start_band = BAND_A;
+               }
+               priv->adhoc_channel = DEFAULT_AD_HOC_CHANNEL_A;
+       } else if (adapter->fw_bands & BAND_GN) {
+               adapter->adhoc_start_band = BAND_G | BAND_B | BAND_GN;
+               priv->adhoc_channel = DEFAULT_AD_HOC_CHANNEL;
+               adapter->adhoc_11n_enabled = true;
+       } else if (adapter->fw_bands & BAND_G) {
+               adapter->adhoc_start_band = BAND_G | BAND_B;
+               priv->adhoc_channel = DEFAULT_AD_HOC_CHANNEL;
+       } else if (adapter->fw_bands & BAND_B) {
+               adapter->adhoc_start_band = BAND_B;
+               priv->adhoc_channel = DEFAULT_AD_HOC_CHANNEL;
+       }
+
+       adapter->fw_release_number = le32_to_cpu(hw_spec->fw_release_number);
+       adapter->fw_api_ver = (adapter->fw_release_number >> 16) & 0xff;
+       adapter->number_of_antenna = le16_to_cpu(hw_spec->number_of_antenna);
+
+       if (le32_to_cpu(hw_spec->dot_11ac_dev_cap)) {
+               adapter->is_hw_11ac_capable = true;
+
+               /* Copy 11AC cap */
+               adapter->hw_dot_11ac_dev_cap =
+                                       le32_to_cpu(hw_spec->dot_11ac_dev_cap);
+               adapter->usr_dot_11ac_dev_cap_bg = adapter->hw_dot_11ac_dev_cap
+                                       & ~MWIFIEX_DEF_11AC_CAP_BF_RESET_MASK;
+               adapter->usr_dot_11ac_dev_cap_a = adapter->hw_dot_11ac_dev_cap
+                                       & ~MWIFIEX_DEF_11AC_CAP_BF_RESET_MASK;
+
+               /* Copy 11AC mcs */
+               adapter->hw_dot_11ac_mcs_support =
+                               le32_to_cpu(hw_spec->dot_11ac_mcs_support);
+               adapter->usr_dot_11ac_mcs_support =
+                                       adapter->hw_dot_11ac_mcs_support;
+       } else {
+               adapter->is_hw_11ac_capable = false;
+       }
+
+       resp_size = le16_to_cpu(resp->size) - S_DS_GEN;
+       if (resp_size > sizeof(struct host_cmd_ds_get_hw_spec)) {
+               /* we have variable HW SPEC information */
+               left_len = resp_size - sizeof(struct host_cmd_ds_get_hw_spec);
+               while (left_len > sizeof(struct mwifiex_ie_types_header)) {
+                       tlv = (void *)&hw_spec->tlvs + parsed_len;
+                       switch (le16_to_cpu(tlv->type)) {
+                       case TLV_TYPE_API_REV:
+                               api_rev = (struct hw_spec_api_rev *)tlv;
+                               api_id = le16_to_cpu(api_rev->api_id);
+                               switch (api_id) {
+                               case KEY_API_VER_ID:
+                                       adapter->key_api_major_ver =
+                                                       api_rev->major_ver;
+                                       adapter->key_api_minor_ver =
+                                                       api_rev->minor_ver;
+                                       mwifiex_dbg(adapter, INFO,
+                                                   "key_api v%d.%d\n",
+                                                   adapter->key_api_major_ver,
+                                                   adapter->key_api_minor_ver);
+                                       break;
+                               case FW_API_VER_ID:
+                                       adapter->fw_api_ver =
+                                                       api_rev->major_ver;
+                                       mwifiex_dbg(adapter, INFO,
+                                                   "Firmware api version %d\n",
+                                                   adapter->fw_api_ver);
+                                       break;
+                               default:
+                                       mwifiex_dbg(adapter, FATAL,
+                                                   "Unknown api_id: %d\n",
+                                                   api_id);
+                                       break;
+                               }
+                               break;
+                       default:
+                               mwifiex_dbg(adapter, FATAL,
+                                           "Unknown GET_HW_SPEC TLV type: %#x\n",
+                                           le16_to_cpu(tlv->type));
+                               break;
+                       }
+                       parsed_len += le16_to_cpu(tlv->len) +
+                                     sizeof(struct mwifiex_ie_types_header);
+                       left_len -= le16_to_cpu(tlv->len) +
+                                     sizeof(struct mwifiex_ie_types_header);
+               }
+       }
+
+       mwifiex_dbg(adapter, INFO,
+                   "info: GET_HW_SPEC: fw_release_number- %#x\n",
+                   adapter->fw_release_number);
+       mwifiex_dbg(adapter, INFO,
+                   "info: GET_HW_SPEC: permanent addr: %pM\n",
+                   hw_spec->permanent_addr);
+       mwifiex_dbg(adapter, INFO,
+                   "info: GET_HW_SPEC: hw_if_version=%#x version=%#x\n",
+                   le16_to_cpu(hw_spec->hw_if_version),
+                   le16_to_cpu(hw_spec->version));
+
+       ether_addr_copy(priv->adapter->perm_addr, hw_spec->permanent_addr);
+       adapter->region_code = le16_to_cpu(hw_spec->region_code);
+
+       for (i = 0; i < MWIFIEX_MAX_REGION_CODE; i++)
+               /* Use the region code to search for the index */
+               if (adapter->region_code == region_code_index[i])
+                       break;
+
+       /* If it's unidentified region code, use the default (USA) */
+       if (i >= MWIFIEX_MAX_REGION_CODE) {
+               adapter->region_code = 0x10;
+               mwifiex_dbg(adapter, WARN,
+                           "cmd: unknown region code, use default (USA)\n");
+       }
+
+       adapter->hw_dot_11n_dev_cap = le32_to_cpu(hw_spec->dot_11n_dev_cap);
+       adapter->hw_dev_mcs_support = hw_spec->dev_mcs_support;
+       adapter->user_dev_mcs_support = adapter->hw_dev_mcs_support;
+
+       if (adapter->if_ops.update_mp_end_port)
+               adapter->if_ops.update_mp_end_port(adapter,
+                                       le16_to_cpu(hw_spec->mp_end_port));
+
+       if (adapter->fw_api_ver == MWIFIEX_FW_V15)
+               adapter->scan_chan_gap_enabled = true;
+
+       return 0;
+}
diff --git a/drivers/net/wireless/marvell/mwifiex/debugfs.c b/drivers/net/wireless/marvell/mwifiex/debugfs.c
new file mode 100644 (file)
index 0000000..9824d8d
--- /dev/null
@@ -0,0 +1,1005 @@
+/*
+ * Marvell Wireless LAN device driver: debugfs
+ *
+ * Copyright (C) 2011-2014, Marvell International Ltd.
+ *
+ * This software file (the "File") is distributed by Marvell International
+ * Ltd. under the terms of the GNU General Public License Version 2, June 1991
+ * (the "License").  You may use, redistribute and/or modify this File in
+ * accordance with the terms and conditions of the License, a copy of which
+ * is available by writing to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the
+ * worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
+ *
+ * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
+ * ARE EXPRESSLY DISCLAIMED.  The License provides additional details about
+ * this warranty disclaimer.
+ */
+
+#include <linux/debugfs.h>
+
+#include "main.h"
+#include "11n.h"
+
+
+static struct dentry *mwifiex_dfs_dir;
+
+static char *bss_modes[] = {
+       "UNSPECIFIED",
+       "ADHOC",
+       "STATION",
+       "AP",
+       "AP_VLAN",
+       "WDS",
+       "MONITOR",
+       "MESH_POINT",
+       "P2P_CLIENT",
+       "P2P_GO",
+       "P2P_DEVICE",
+};
+
+/*
+ * Proc info file read handler.
+ *
+ * This function is called when the 'info' file is opened for reading.
+ * It prints the following driver related information -
+ *      - Driver name
+ *      - Driver version
+ *      - Driver extended version
+ *      - Interface name
+ *      - BSS mode
+ *      - Media state (connected or disconnected)
+ *      - MAC address
+ *      - Total number of Tx bytes
+ *      - Total number of Rx bytes
+ *      - Total number of Tx packets
+ *      - Total number of Rx packets
+ *      - Total number of dropped Tx packets
+ *      - Total number of dropped Rx packets
+ *      - Total number of corrupted Tx packets
+ *      - Total number of corrupted Rx packets
+ *      - Carrier status (on or off)
+ *      - Tx queue status (started or stopped)
+ *
+ * For STA mode drivers, it also prints the following extra -
+ *      - ESSID
+ *      - BSSID
+ *      - Channel
+ *      - Region code
+ *      - Multicast count
+ *      - Multicast addresses
+ */
+static ssize_t
+mwifiex_info_read(struct file *file, char __user *ubuf,
+                 size_t count, loff_t *ppos)
+{
+       struct mwifiex_private *priv =
+               (struct mwifiex_private *) file->private_data;
+       struct net_device *netdev = priv->netdev;
+       struct netdev_hw_addr *ha;
+       struct netdev_queue *txq;
+       unsigned long page = get_zeroed_page(GFP_KERNEL);
+       char *p = (char *) page, fmt[64];
+       struct mwifiex_bss_info info;
+       ssize_t ret;
+       int i = 0;
+
+       if (!p)
+               return -ENOMEM;
+
+       memset(&info, 0, sizeof(info));
+       ret = mwifiex_get_bss_info(priv, &info);
+       if (ret)
+               goto free_and_exit;
+
+       mwifiex_drv_get_driver_version(priv->adapter, fmt, sizeof(fmt) - 1);
+
+       if (!priv->version_str[0])
+               mwifiex_get_ver_ext(priv);
+
+       p += sprintf(p, "driver_name = " "\"mwifiex\"\n");
+       p += sprintf(p, "driver_version = %s", fmt);
+       p += sprintf(p, "\nverext = %s", priv->version_str);
+       p += sprintf(p, "\ninterface_name=\"%s\"\n", netdev->name);
+
+       if (info.bss_mode >= ARRAY_SIZE(bss_modes))
+               p += sprintf(p, "bss_mode=\"%d\"\n", info.bss_mode);
+       else
+               p += sprintf(p, "bss_mode=\"%s\"\n", bss_modes[info.bss_mode]);
+
+       p += sprintf(p, "media_state=\"%s\"\n",
+                    (!priv->media_connected ? "Disconnected" : "Connected"));
+       p += sprintf(p, "mac_address=\"%pM\"\n", netdev->dev_addr);
+
+       if (GET_BSS_ROLE(priv) == MWIFIEX_BSS_ROLE_STA) {
+               p += sprintf(p, "multicast_count=\"%d\"\n",
+                            netdev_mc_count(netdev));
+               p += sprintf(p, "essid=\"%s\"\n", info.ssid.ssid);
+               p += sprintf(p, "bssid=\"%pM\"\n", info.bssid);
+               p += sprintf(p, "channel=\"%d\"\n", (int) info.bss_chan);
+               p += sprintf(p, "country_code = \"%s\"\n", info.country_code);
+
+               netdev_for_each_mc_addr(ha, netdev)
+                       p += sprintf(p, "multicast_address[%d]=\"%pM\"\n",
+                                       i++, ha->addr);
+       }
+
+       p += sprintf(p, "num_tx_bytes = %lu\n", priv->stats.tx_bytes);
+       p += sprintf(p, "num_rx_bytes = %lu\n", priv->stats.rx_bytes);
+       p += sprintf(p, "num_tx_pkts = %lu\n", priv->stats.tx_packets);
+       p += sprintf(p, "num_rx_pkts = %lu\n", priv->stats.rx_packets);
+       p += sprintf(p, "num_tx_pkts_dropped = %lu\n", priv->stats.tx_dropped);
+       p += sprintf(p, "num_rx_pkts_dropped = %lu\n", priv->stats.rx_dropped);
+       p += sprintf(p, "num_tx_pkts_err = %lu\n", priv->stats.tx_errors);
+       p += sprintf(p, "num_rx_pkts_err = %lu\n", priv->stats.rx_errors);
+       p += sprintf(p, "carrier %s\n", ((netif_carrier_ok(priv->netdev))
+                                        ? "on" : "off"));
+       p += sprintf(p, "tx queue");
+       for (i = 0; i < netdev->num_tx_queues; i++) {
+               txq = netdev_get_tx_queue(netdev, i);
+               p += sprintf(p, " %d:%s", i, netif_tx_queue_stopped(txq) ?
+                            "stopped" : "started");
+       }
+       p += sprintf(p, "\n");
+
+       ret = simple_read_from_buffer(ubuf, count, ppos, (char *) page,
+                                     (unsigned long) p - page);
+
+free_and_exit:
+       free_page(page);
+       return ret;
+}
+
+/*
+ * Proc device dump read handler.
+ *
+ * This function is called when the 'device_dump' file is opened for
+ * reading.
+ * This function dumps driver information and firmware memory segments
+ * (ex. DTCM, ITCM, SQRAM etc.) for
+ * debugging.
+ */
+static ssize_t
+mwifiex_device_dump_read(struct file *file, char __user *ubuf,
+                        size_t count, loff_t *ppos)
+{
+       struct mwifiex_private *priv = file->private_data;
+
+       if (!priv->adapter->if_ops.device_dump)
+               return -EIO;
+
+       priv->adapter->if_ops.device_dump(priv->adapter);
+
+       return 0;
+}
+
+/*
+ * Proc getlog file read handler.
+ *
+ * This function is called when the 'getlog' file is opened for reading
+ * It prints the following log information -
+ *      - Number of multicast Tx frames
+ *      - Number of failed packets
+ *      - Number of Tx retries
+ *      - Number of multicast Tx retries
+ *      - Number of duplicate frames
+ *      - Number of RTS successes
+ *      - Number of RTS failures
+ *      - Number of ACK failures
+ *      - Number of fragmented Rx frames
+ *      - Number of multicast Rx frames
+ *      - Number of FCS errors
+ *      - Number of Tx frames
+ *      - WEP ICV error counts
+ *      - Number of received beacons
+ *      - Number of missed beacons
+ */
+static ssize_t
+mwifiex_getlog_read(struct file *file, char __user *ubuf,
+                   size_t count, loff_t *ppos)
+{
+       struct mwifiex_private *priv =
+               (struct mwifiex_private *) file->private_data;
+       unsigned long page = get_zeroed_page(GFP_KERNEL);
+       char *p = (char *) page;
+       ssize_t ret;
+       struct mwifiex_ds_get_stats stats;
+
+       if (!p)
+               return -ENOMEM;
+
+       memset(&stats, 0, sizeof(stats));
+       ret = mwifiex_get_stats_info(priv, &stats);
+       if (ret)
+               goto free_and_exit;
+
+       p += sprintf(p, "\n"
+                    "mcasttxframe     %u\n"
+                    "failed           %u\n"
+                    "retry            %u\n"
+                    "multiretry       %u\n"
+                    "framedup         %u\n"
+                    "rtssuccess       %u\n"
+                    "rtsfailure       %u\n"
+                    "ackfailure       %u\n"
+                    "rxfrag           %u\n"
+                    "mcastrxframe     %u\n"
+                    "fcserror         %u\n"
+                    "txframe          %u\n"
+                    "wepicverrcnt-1   %u\n"
+                    "wepicverrcnt-2   %u\n"
+                    "wepicverrcnt-3   %u\n"
+                    "wepicverrcnt-4   %u\n"
+                    "bcn_rcv_cnt   %u\n"
+                    "bcn_miss_cnt   %u\n",
+                    stats.mcast_tx_frame,
+                    stats.failed,
+                    stats.retry,
+                    stats.multi_retry,
+                    stats.frame_dup,
+                    stats.rts_success,
+                    stats.rts_failure,
+                    stats.ack_failure,
+                    stats.rx_frag,
+                    stats.mcast_rx_frame,
+                    stats.fcs_error,
+                    stats.tx_frame,
+                    stats.wep_icv_error[0],
+                    stats.wep_icv_error[1],
+                    stats.wep_icv_error[2],
+                    stats.wep_icv_error[3],
+                    stats.bcn_rcv_cnt,
+                    stats.bcn_miss_cnt);
+
+
+       ret = simple_read_from_buffer(ubuf, count, ppos, (char *) page,
+                                     (unsigned long) p - page);
+
+free_and_exit:
+       free_page(page);
+       return ret;
+}
+
+/* Sysfs histogram file read handler.
+ *
+ * This function is called when the 'histogram' file is opened for reading
+ * It prints the following histogram information -
+ *      - Number of histogram samples
+ *      - Receive packet number of each rx_rate
+ *      - Receive packet number of each snr
+ *      - Receive packet number of each nosie_flr
+ *      - Receive packet number of each signal streath
+ */
+static ssize_t
+mwifiex_histogram_read(struct file *file, char __user *ubuf,
+                      size_t count, loff_t *ppos)
+{
+       struct mwifiex_private *priv =
+               (struct mwifiex_private *)file->private_data;
+       ssize_t ret;
+       struct mwifiex_histogram_data *phist_data;
+       int i, value;
+       unsigned long page = get_zeroed_page(GFP_KERNEL);
+       char *p = (char *)page;
+
+       if (!p)
+               return -ENOMEM;
+
+       if (!priv || !priv->hist_data)
+               return -EFAULT;
+       phist_data = priv->hist_data;
+
+       p += sprintf(p, "\n"
+                    "total samples = %d\n",
+                    atomic_read(&phist_data->num_samples));
+
+       p += sprintf(p, "rx rates (in Mbps): 0=1M   1=2M");
+       p += sprintf(p, "2=5.5M  3=11M   4=6M   5=9M  6=12M\n");
+       p += sprintf(p, "7=18M  8=24M  9=36M  10=48M  11=54M");
+       p += sprintf(p, "12-27=MCS0-15(BW20) 28-43=MCS0-15(BW40)\n");
+
+       if (ISSUPP_11ACENABLED(priv->adapter->fw_cap_info)) {
+               p += sprintf(p, "44-53=MCS0-9(VHT:BW20)");
+               p += sprintf(p, "54-63=MCS0-9(VHT:BW40)");
+               p += sprintf(p, "64-73=MCS0-9(VHT:BW80)\n\n");
+       } else {
+               p += sprintf(p, "\n");
+       }
+
+       for (i = 0; i < MWIFIEX_MAX_RX_RATES; i++) {
+               value = atomic_read(&phist_data->rx_rate[i]);
+               if (value)
+                       p += sprintf(p, "rx_rate[%02d] = %d\n", i, value);
+       }
+
+       if (ISSUPP_11ACENABLED(priv->adapter->fw_cap_info)) {
+               for (i = MWIFIEX_MAX_RX_RATES; i < MWIFIEX_MAX_AC_RX_RATES;
+                    i++) {
+                       value = atomic_read(&phist_data->rx_rate[i]);
+                       if (value)
+                               p += sprintf(p, "rx_rate[%02d] = %d\n",
+                                          i, value);
+               }
+       }
+
+       for (i = 0; i < MWIFIEX_MAX_SNR; i++) {
+               value =  atomic_read(&phist_data->snr[i]);
+               if (value)
+                       p += sprintf(p, "snr[%02ddB] = %d\n", i, value);
+       }
+       for (i = 0; i < MWIFIEX_MAX_NOISE_FLR; i++) {
+               value = atomic_read(&phist_data->noise_flr[i]);
+               if (value)
+                       p += sprintf(p, "noise_flr[-%02ddBm] = %d\n",
+                               (int)(i-128), value);
+       }
+       for (i = 0; i < MWIFIEX_MAX_SIG_STRENGTH; i++) {
+               value = atomic_read(&phist_data->sig_str[i]);
+               if (value)
+                       p += sprintf(p, "sig_strength[-%02ddBm] = %d\n",
+                               i, value);
+       }
+
+       ret = simple_read_from_buffer(ubuf, count, ppos, (char *)page,
+                                     (unsigned long)p - page);
+
+       return ret;
+}
+
+static ssize_t
+mwifiex_histogram_write(struct file *file, const char __user *ubuf,
+                       size_t count, loff_t *ppos)
+{
+       struct mwifiex_private *priv = (void *)file->private_data;
+
+       if (priv && priv->hist_data)
+               mwifiex_hist_data_reset(priv);
+       return 0;
+}
+
+static struct mwifiex_debug_info info;
+
+/*
+ * Proc debug file read handler.
+ *
+ * This function is called when the 'debug' file is opened for reading
+ * It prints the following log information -
+ *      - Interrupt count
+ *      - WMM AC VO packets count
+ *      - WMM AC VI packets count
+ *      - WMM AC BE packets count
+ *      - WMM AC BK packets count
+ *      - Maximum Tx buffer size
+ *      - Tx buffer size
+ *      - Current Tx buffer size
+ *      - Power Save mode
+ *      - Power Save state
+ *      - Deep Sleep status
+ *      - Device wakeup required status
+ *      - Number of wakeup tries
+ *      - Host Sleep configured status
+ *      - Host Sleep activated status
+ *      - Number of Tx timeouts
+ *      - Number of command timeouts
+ *      - Last timed out command ID
+ *      - Last timed out command action
+ *      - Last command ID
+ *      - Last command action
+ *      - Last command index
+ *      - Last command response ID
+ *      - Last command response index
+ *      - Last event
+ *      - Last event index
+ *      - Number of host to card command failures
+ *      - Number of sleep confirm command failures
+ *      - Number of host to card data failure
+ *      - Number of deauthentication events
+ *      - Number of disassociation events
+ *      - Number of link lost events
+ *      - Number of deauthentication commands
+ *      - Number of association success commands
+ *      - Number of association failure commands
+ *      - Number of commands sent
+ *      - Number of data packets sent
+ *      - Number of command responses received
+ *      - Number of events received
+ *      - Tx BA stream table (TID, RA)
+ *      - Rx reorder table (TID, TA, Start window, Window size, Buffer)
+ */
+static ssize_t
+mwifiex_debug_read(struct file *file, char __user *ubuf,
+                  size_t count, loff_t *ppos)
+{
+       struct mwifiex_private *priv =
+               (struct mwifiex_private *) file->private_data;
+       unsigned long page = get_zeroed_page(GFP_KERNEL);
+       char *p = (char *) page;
+       ssize_t ret;
+
+       if (!p)
+               return -ENOMEM;
+
+       ret = mwifiex_get_debug_info(priv, &info);
+       if (ret)
+               goto free_and_exit;
+
+       p += mwifiex_debug_info_to_buffer(priv, p, &info);
+
+       ret = simple_read_from_buffer(ubuf, count, ppos, (char *) page,
+                                     (unsigned long) p - page);
+
+free_and_exit:
+       free_page(page);
+       return ret;
+}
+
+static u32 saved_reg_type, saved_reg_offset, saved_reg_value;
+
+/*
+ * Proc regrdwr file write handler.
+ *
+ * This function is called when the 'regrdwr' file is opened for writing
+ *
+ * This function can be used to write to a register.
+ */
+static ssize_t
+mwifiex_regrdwr_write(struct file *file,
+                     const char __user *ubuf, size_t count, loff_t *ppos)
+{
+       unsigned long addr = get_zeroed_page(GFP_KERNEL);
+       char *buf = (char *) addr;
+       size_t buf_size = min_t(size_t, count, PAGE_SIZE - 1);
+       int ret;
+       u32 reg_type = 0, reg_offset = 0, reg_value = UINT_MAX;
+
+       if (!buf)
+               return -ENOMEM;
+
+
+       if (copy_from_user(buf, ubuf, buf_size)) {
+               ret = -EFAULT;
+               goto done;
+       }
+
+       sscanf(buf, "%u %x %x", &reg_type, &reg_offset, &reg_value);
+
+       if (reg_type == 0 || reg_offset == 0) {
+               ret = -EINVAL;
+               goto done;
+       } else {
+               saved_reg_type = reg_type;
+               saved_reg_offset = reg_offset;
+               saved_reg_value = reg_value;
+               ret = count;
+       }
+done:
+       free_page(addr);
+       return ret;
+}
+
+/*
+ * Proc regrdwr file read handler.
+ *
+ * This function is called when the 'regrdwr' file is opened for reading
+ *
+ * This function can be used to read from a register.
+ */
+static ssize_t
+mwifiex_regrdwr_read(struct file *file, char __user *ubuf,
+                    size_t count, loff_t *ppos)
+{
+       struct mwifiex_private *priv =
+               (struct mwifiex_private *) file->private_data;
+       unsigned long addr = get_zeroed_page(GFP_KERNEL);
+       char *buf = (char *) addr;
+       int pos = 0, ret = 0;
+       u32 reg_value;
+
+       if (!buf)
+               return -ENOMEM;
+
+       if (!saved_reg_type) {
+               /* No command has been given */
+               pos += snprintf(buf, PAGE_SIZE, "0");
+               goto done;
+       }
+       /* Set command has been given */
+       if (saved_reg_value != UINT_MAX) {
+               ret = mwifiex_reg_write(priv, saved_reg_type, saved_reg_offset,
+                                       saved_reg_value);
+
+               pos += snprintf(buf, PAGE_SIZE, "%u 0x%x 0x%x\n",
+                               saved_reg_type, saved_reg_offset,
+                               saved_reg_value);
+
+               ret = simple_read_from_buffer(ubuf, count, ppos, buf, pos);
+
+               goto done;
+       }
+       /* Get command has been given */
+       ret = mwifiex_reg_read(priv, saved_reg_type,
+                              saved_reg_offset, &reg_value);
+       if (ret) {
+               ret = -EINVAL;
+               goto done;
+       }
+
+       pos += snprintf(buf, PAGE_SIZE, "%u 0x%x 0x%x\n", saved_reg_type,
+                       saved_reg_offset, reg_value);
+
+       ret = simple_read_from_buffer(ubuf, count, ppos, buf, pos);
+
+done:
+       free_page(addr);
+       return ret;
+}
+
+/* Proc debug_mask file read handler.
+ * This function is called when the 'debug_mask' file is opened for reading
+ * This function can be used read driver debugging mask value.
+ */
+static ssize_t
+mwifiex_debug_mask_read(struct file *file, char __user *ubuf,
+                       size_t count, loff_t *ppos)
+{
+       struct mwifiex_private *priv =
+               (struct mwifiex_private *)file->private_data;
+       unsigned long page = get_zeroed_page(GFP_KERNEL);
+       char *buf = (char *)page;
+       size_t ret = 0;
+       int pos = 0;
+
+       if (!buf)
+               return -ENOMEM;
+
+       pos += snprintf(buf, PAGE_SIZE, "debug mask=0x%08x\n",
+                       priv->adapter->debug_mask);
+       ret = simple_read_from_buffer(ubuf, count, ppos, buf, pos);
+
+       free_page(page);
+       return ret;
+}
+
+/* Proc debug_mask file read handler.
+ * This function is called when the 'debug_mask' file is opened for reading
+ * This function can be used read driver debugging mask value.
+ */
+static ssize_t
+mwifiex_debug_mask_write(struct file *file, const char __user *ubuf,
+                        size_t count, loff_t *ppos)
+{
+       int ret;
+       unsigned long debug_mask;
+       struct mwifiex_private *priv = (void *)file->private_data;
+       unsigned long addr = get_zeroed_page(GFP_KERNEL);
+       char *buf = (void *)addr;
+       size_t buf_size = min(count, (size_t)(PAGE_SIZE - 1));
+
+       if (!buf)
+               return -ENOMEM;
+
+       if (copy_from_user(buf, ubuf, buf_size)) {
+               ret = -EFAULT;
+               goto done;
+       }
+
+       if (kstrtoul(buf, 0, &debug_mask)) {
+               ret = -EINVAL;
+               goto done;
+       }
+
+       priv->adapter->debug_mask = debug_mask;
+       ret = count;
+done:
+       free_page(addr);
+       return ret;
+}
+
+/* Proc memrw file write handler.
+ * This function is called when the 'memrw' file is opened for writing
+ * This function can be used to write to a memory location.
+ */
+static ssize_t
+mwifiex_memrw_write(struct file *file, const char __user *ubuf, size_t count,
+                   loff_t *ppos)
+{
+       int ret;
+       char cmd;
+       struct mwifiex_ds_mem_rw mem_rw;
+       u16 cmd_action;
+       struct mwifiex_private *priv = (void *)file->private_data;
+       unsigned long addr = get_zeroed_page(GFP_KERNEL);
+       char *buf = (void *)addr;
+       size_t buf_size = min(count, (size_t)(PAGE_SIZE - 1));
+
+       if (!buf)
+               return -ENOMEM;
+
+       if (copy_from_user(buf, ubuf, buf_size)) {
+               ret = -EFAULT;
+               goto done;
+       }
+
+       ret = sscanf(buf, "%c %x %x", &cmd, &mem_rw.addr, &mem_rw.value);
+       if (ret != 3) {
+               ret = -EINVAL;
+               goto done;
+       }
+
+       if ((cmd == 'r') || (cmd == 'R')) {
+               cmd_action = HostCmd_ACT_GEN_GET;
+               mem_rw.value = 0;
+       } else if ((cmd == 'w') || (cmd == 'W')) {
+               cmd_action = HostCmd_ACT_GEN_SET;
+       } else {
+               ret = -EINVAL;
+               goto done;
+       }
+
+       memcpy(&priv->mem_rw, &mem_rw, sizeof(mem_rw));
+       if (mwifiex_send_cmd(priv, HostCmd_CMD_MEM_ACCESS, cmd_action, 0,
+                            &mem_rw, true))
+               ret = -1;
+       else
+               ret = count;
+
+done:
+       free_page(addr);
+       return ret;
+}
+
+/* Proc memrw file read handler.
+ * This function is called when the 'memrw' file is opened for reading
+ * This function can be used to read from a memory location.
+ */
+static ssize_t
+mwifiex_memrw_read(struct file *file, char __user *ubuf,
+                  size_t count, loff_t *ppos)
+{
+       struct mwifiex_private *priv = (void *)file->private_data;
+       unsigned long addr = get_zeroed_page(GFP_KERNEL);
+       char *buf = (char *)addr;
+       int ret, pos = 0;
+
+       if (!buf)
+               return -ENOMEM;
+
+       pos += snprintf(buf, PAGE_SIZE, "0x%x 0x%x\n", priv->mem_rw.addr,
+                       priv->mem_rw.value);
+       ret = simple_read_from_buffer(ubuf, count, ppos, buf, pos);
+
+       free_page(addr);
+       return ret;
+}
+
+static u32 saved_offset = -1, saved_bytes = -1;
+
+/*
+ * Proc rdeeprom file write handler.
+ *
+ * This function is called when the 'rdeeprom' file is opened for writing
+ *
+ * This function can be used to write to a RDEEPROM location.
+ */
+static ssize_t
+mwifiex_rdeeprom_write(struct file *file,
+                      const char __user *ubuf, size_t count, loff_t *ppos)
+{
+       unsigned long addr = get_zeroed_page(GFP_KERNEL);
+       char *buf = (char *) addr;
+       size_t buf_size = min_t(size_t, count, PAGE_SIZE - 1);
+       int ret = 0;
+       int offset = -1, bytes = -1;
+
+       if (!buf)
+               return -ENOMEM;
+
+
+       if (copy_from_user(buf, ubuf, buf_size)) {
+               ret = -EFAULT;
+               goto done;
+       }
+
+       sscanf(buf, "%d %d", &offset, &bytes);
+
+       if (offset == -1 || bytes == -1) {
+               ret = -EINVAL;
+               goto done;
+       } else {
+               saved_offset = offset;
+               saved_bytes = bytes;
+               ret = count;
+       }
+done:
+       free_page(addr);
+       return ret;
+}
+
+/*
+ * Proc rdeeprom read write handler.
+ *
+ * This function is called when the 'rdeeprom' file is opened for reading
+ *
+ * This function can be used to read from a RDEEPROM location.
+ */
+static ssize_t
+mwifiex_rdeeprom_read(struct file *file, char __user *ubuf,
+                     size_t count, loff_t *ppos)
+{
+       struct mwifiex_private *priv =
+               (struct mwifiex_private *) file->private_data;
+       unsigned long addr = get_zeroed_page(GFP_KERNEL);
+       char *buf = (char *) addr;
+       int pos, ret, i;
+       u8 value[MAX_EEPROM_DATA];
+
+       if (!buf)
+               return -ENOMEM;
+
+       if (saved_offset == -1) {
+               /* No command has been given */
+               pos = snprintf(buf, PAGE_SIZE, "0");
+               goto done;
+       }
+
+       /* Get command has been given */
+       ret = mwifiex_eeprom_read(priv, (u16) saved_offset,
+                                 (u16) saved_bytes, value);
+       if (ret) {
+               ret = -EINVAL;
+               goto out_free;
+       }
+
+       pos = snprintf(buf, PAGE_SIZE, "%d %d ", saved_offset, saved_bytes);
+
+       for (i = 0; i < saved_bytes; i++)
+               pos += scnprintf(buf + pos, PAGE_SIZE - pos, "%d ", value[i]);
+
+done:
+       ret = simple_read_from_buffer(ubuf, count, ppos, buf, pos);
+out_free:
+       free_page(addr);
+       return ret;
+}
+
+/* Proc hscfg file write handler
+ * This function can be used to configure the host sleep parameters.
+ */
+static ssize_t
+mwifiex_hscfg_write(struct file *file, const char __user *ubuf,
+                   size_t count, loff_t *ppos)
+{
+       struct mwifiex_private *priv = (void *)file->private_data;
+       unsigned long addr = get_zeroed_page(GFP_KERNEL);
+       char *buf = (char *)addr;
+       size_t buf_size = min_t(size_t, count, PAGE_SIZE - 1);
+       int ret, arg_num;
+       struct mwifiex_ds_hs_cfg hscfg;
+       int conditions = HS_CFG_COND_DEF;
+       u32 gpio = HS_CFG_GPIO_DEF, gap = HS_CFG_GAP_DEF;
+
+       if (!buf)
+               return -ENOMEM;
+
+       if (copy_from_user(buf, ubuf, buf_size)) {
+               ret = -EFAULT;
+               goto done;
+       }
+
+       arg_num = sscanf(buf, "%d %x %x", &conditions, &gpio, &gap);
+
+       memset(&hscfg, 0, sizeof(struct mwifiex_ds_hs_cfg));
+
+       if (arg_num > 3) {
+               mwifiex_dbg(priv->adapter, ERROR,
+                           "Too many arguments\n");
+               ret = -EINVAL;
+               goto done;
+       }
+
+       if (arg_num >= 1 && arg_num < 3)
+               mwifiex_set_hs_params(priv, HostCmd_ACT_GEN_GET,
+                                     MWIFIEX_SYNC_CMD, &hscfg);
+
+       if (arg_num) {
+               if (conditions == HS_CFG_CANCEL) {
+                       mwifiex_cancel_hs(priv, MWIFIEX_ASYNC_CMD);
+                       ret = count;
+                       goto done;
+               }
+               hscfg.conditions = conditions;
+       }
+       if (arg_num >= 2)
+               hscfg.gpio = gpio;
+       if (arg_num == 3)
+               hscfg.gap = gap;
+
+       hscfg.is_invoke_hostcmd = false;
+       mwifiex_set_hs_params(priv, HostCmd_ACT_GEN_SET,
+                             MWIFIEX_SYNC_CMD, &hscfg);
+
+       mwifiex_enable_hs(priv->adapter);
+       priv->adapter->hs_enabling = false;
+       ret = count;
+done:
+       free_page(addr);
+       return ret;
+}
+
+/* Proc hscfg file read handler
+ * This function can be used to read host sleep configuration
+ * parameters from driver.
+ */
+static ssize_t
+mwifiex_hscfg_read(struct file *file, char __user *ubuf,
+                  size_t count, loff_t *ppos)
+{
+       struct mwifiex_private *priv = (void *)file->private_data;
+       unsigned long addr = get_zeroed_page(GFP_KERNEL);
+       char *buf = (char *)addr;
+       int pos, ret;
+       struct mwifiex_ds_hs_cfg hscfg;
+
+       if (!buf)
+               return -ENOMEM;
+
+       mwifiex_set_hs_params(priv, HostCmd_ACT_GEN_GET,
+                             MWIFIEX_SYNC_CMD, &hscfg);
+
+       pos = snprintf(buf, PAGE_SIZE, "%u 0x%x 0x%x\n", hscfg.conditions,
+                      hscfg.gpio, hscfg.gap);
+
+       ret = simple_read_from_buffer(ubuf, count, ppos, buf, pos);
+
+       free_page(addr);
+       return ret;
+}
+
+static ssize_t
+mwifiex_timeshare_coex_read(struct file *file, char __user *ubuf,
+                           size_t count, loff_t *ppos)
+{
+       struct mwifiex_private *priv = file->private_data;
+       char buf[3];
+       bool timeshare_coex;
+       int ret;
+       unsigned int len;
+
+       if (priv->adapter->fw_api_ver != MWIFIEX_FW_V15)
+               return -EOPNOTSUPP;
+
+       ret = mwifiex_send_cmd(priv, HostCmd_CMD_ROBUST_COEX,
+                              HostCmd_ACT_GEN_GET, 0, &timeshare_coex, true);
+       if (ret)
+               return ret;
+
+       len = sprintf(buf, "%d\n", timeshare_coex);
+       return simple_read_from_buffer(ubuf, count, ppos, buf, len);
+}
+
+static ssize_t
+mwifiex_timeshare_coex_write(struct file *file, const char __user *ubuf,
+                            size_t count, loff_t *ppos)
+{
+       bool timeshare_coex;
+       struct mwifiex_private *priv = file->private_data;
+       char kbuf[16];
+       int ret;
+
+       if (priv->adapter->fw_api_ver != MWIFIEX_FW_V15)
+               return -EOPNOTSUPP;
+
+       memset(kbuf, 0, sizeof(kbuf));
+
+       if (copy_from_user(&kbuf, ubuf, min_t(size_t, sizeof(kbuf) - 1, count)))
+               return -EFAULT;
+
+       if (strtobool(kbuf, &timeshare_coex))
+               return -EINVAL;
+
+       ret = mwifiex_send_cmd(priv, HostCmd_CMD_ROBUST_COEX,
+                              HostCmd_ACT_GEN_SET, 0, &timeshare_coex, true);
+       if (ret)
+               return ret;
+       else
+               return count;
+}
+
+#define MWIFIEX_DFS_ADD_FILE(name) do {                                 \
+       if (!debugfs_create_file(#name, 0644, priv->dfs_dev_dir,        \
+                       priv, &mwifiex_dfs_##name##_fops))              \
+               return;                                                 \
+} while (0);
+
+#define MWIFIEX_DFS_FILE_OPS(name)                                      \
+static const struct file_operations mwifiex_dfs_##name##_fops = {       \
+       .read = mwifiex_##name##_read,                                  \
+       .write = mwifiex_##name##_write,                                \
+       .open = simple_open,                                            \
+};
+
+#define MWIFIEX_DFS_FILE_READ_OPS(name)                                 \
+static const struct file_operations mwifiex_dfs_##name##_fops = {       \
+       .read = mwifiex_##name##_read,                                  \
+       .open = simple_open,                                            \
+};
+
+#define MWIFIEX_DFS_FILE_WRITE_OPS(name)                                \
+static const struct file_operations mwifiex_dfs_##name##_fops = {       \
+       .write = mwifiex_##name##_write,                                \
+       .open = simple_open,                                            \
+};
+
+
+MWIFIEX_DFS_FILE_READ_OPS(info);
+MWIFIEX_DFS_FILE_READ_OPS(debug);
+MWIFIEX_DFS_FILE_READ_OPS(getlog);
+MWIFIEX_DFS_FILE_READ_OPS(device_dump);
+MWIFIEX_DFS_FILE_OPS(regrdwr);
+MWIFIEX_DFS_FILE_OPS(rdeeprom);
+MWIFIEX_DFS_FILE_OPS(memrw);
+MWIFIEX_DFS_FILE_OPS(hscfg);
+MWIFIEX_DFS_FILE_OPS(histogram);
+MWIFIEX_DFS_FILE_OPS(debug_mask);
+MWIFIEX_DFS_FILE_OPS(timeshare_coex);
+
+/*
+ * This function creates the debug FS directory structure and the files.
+ */
+void
+mwifiex_dev_debugfs_init(struct mwifiex_private *priv)
+{
+       if (!mwifiex_dfs_dir || !priv)
+               return;
+
+       priv->dfs_dev_dir = debugfs_create_dir(priv->netdev->name,
+                                              mwifiex_dfs_dir);
+
+       if (!priv->dfs_dev_dir)
+               return;
+
+       MWIFIEX_DFS_ADD_FILE(info);
+       MWIFIEX_DFS_ADD_FILE(debug);
+       MWIFIEX_DFS_ADD_FILE(getlog);
+       MWIFIEX_DFS_ADD_FILE(regrdwr);
+       MWIFIEX_DFS_ADD_FILE(rdeeprom);
+       MWIFIEX_DFS_ADD_FILE(device_dump);
+       MWIFIEX_DFS_ADD_FILE(memrw);
+       MWIFIEX_DFS_ADD_FILE(hscfg);
+       MWIFIEX_DFS_ADD_FILE(histogram);
+       MWIFIEX_DFS_ADD_FILE(debug_mask);
+       MWIFIEX_DFS_ADD_FILE(timeshare_coex);
+}
+
+/*
+ * This function removes the debug FS directory structure and the files.
+ */
+void
+mwifiex_dev_debugfs_remove(struct mwifiex_private *priv)
+{
+       if (!priv)
+               return;
+
+       debugfs_remove_recursive(priv->dfs_dev_dir);
+}
+
+/*
+ * This function creates the top level proc directory.
+ */
+void
+mwifiex_debugfs_init(void)
+{
+       if (!mwifiex_dfs_dir)
+               mwifiex_dfs_dir = debugfs_create_dir("mwifiex", NULL);
+}
+
+/*
+ * This function removes the top level proc directory.
+ */
+void
+mwifiex_debugfs_remove(void)
+{
+       if (mwifiex_dfs_dir)
+               debugfs_remove(mwifiex_dfs_dir);
+}
diff --git a/drivers/net/wireless/marvell/mwifiex/decl.h b/drivers/net/wireless/marvell/mwifiex/decl.h
new file mode 100644 (file)
index 0000000..098e1f1
--- /dev/null
@@ -0,0 +1,273 @@
+/*
+ * Marvell Wireless LAN device driver: generic data structures and APIs
+ *
+ * Copyright (C) 2011-2014, Marvell International Ltd.
+ *
+ * This software file (the "File") is distributed by Marvell International
+ * Ltd. under the terms of the GNU General Public License Version 2, June 1991
+ * (the "License").  You may use, redistribute and/or modify this File in
+ * accordance with the terms and conditions of the License, a copy of which
+ * is available by writing to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the
+ * worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
+ *
+ * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
+ * ARE EXPRESSLY DISCLAIMED.  The License provides additional details about
+ * this warranty disclaimer.
+ */
+
+#ifndef _MWIFIEX_DECL_H_
+#define _MWIFIEX_DECL_H_
+
+#undef pr_fmt
+#define pr_fmt(fmt)    KBUILD_MODNAME ": " fmt
+
+#include <linux/wait.h>
+#include <linux/timer.h>
+#include <linux/ieee80211.h>
+#include <uapi/linux/if_arp.h>
+#include <net/mac80211.h>
+
+#define MWIFIEX_BSS_COEX_COUNT      2
+#define MWIFIEX_MAX_BSS_NUM         (3)
+
+#define MWIFIEX_DMA_ALIGN_SZ       64
+#define MWIFIEX_RX_HEADROOM        64
+#define MAX_TXPD_SZ                32
+#define INTF_HDR_ALIGN              4
+
+#define MWIFIEX_MIN_DATA_HEADER_LEN (MWIFIEX_DMA_ALIGN_SZ + INTF_HDR_ALIGN + \
+                                    MAX_TXPD_SZ)
+#define MWIFIEX_MGMT_FRAME_HEADER_SIZE 8       /* sizeof(pkt_type)
+                                                *   + sizeof(tx_control)
+                                                */
+
+#define MWIFIEX_MAX_TX_BASTREAM_SUPPORTED      2
+#define MWIFIEX_MAX_RX_BASTREAM_SUPPORTED      16
+#define MWIFIEX_MAX_TDLS_PEER_SUPPORTED 8
+
+#define MWIFIEX_STA_AMPDU_DEF_TXWINSIZE        64
+#define MWIFIEX_STA_AMPDU_DEF_RXWINSIZE        64
+#define MWIFIEX_STA_COEX_AMPDU_DEF_RXWINSIZE   16
+
+#define MWIFIEX_UAP_AMPDU_DEF_TXWINSIZE        32
+
+#define MWIFIEX_UAP_COEX_AMPDU_DEF_RXWINSIZE   16
+
+#define MWIFIEX_UAP_AMPDU_DEF_RXWINSIZE        16
+#define MWIFIEX_11AC_STA_AMPDU_DEF_TXWINSIZE   64
+#define MWIFIEX_11AC_STA_AMPDU_DEF_RXWINSIZE   64
+#define MWIFIEX_11AC_UAP_AMPDU_DEF_TXWINSIZE   64
+#define MWIFIEX_11AC_UAP_AMPDU_DEF_RXWINSIZE   64
+
+#define MWIFIEX_DEFAULT_BLOCK_ACK_TIMEOUT  0xffff
+
+#define MWIFIEX_RATE_BITMAP_MCS0   32
+
+#define MWIFIEX_RX_DATA_BUF_SIZE     (4 * 1024)
+#define MWIFIEX_RX_CMD_BUF_SIZE             (2 * 1024)
+
+#define MAX_BEACON_PERIOD                  (4000)
+#define MIN_BEACON_PERIOD                  (50)
+#define MAX_DTIM_PERIOD                    (100)
+#define MIN_DTIM_PERIOD                    (1)
+
+#define MWIFIEX_RTS_MIN_VALUE              (0)
+#define MWIFIEX_RTS_MAX_VALUE              (2347)
+#define MWIFIEX_FRAG_MIN_VALUE             (256)
+#define MWIFIEX_FRAG_MAX_VALUE             (2346)
+#define MWIFIEX_WMM_VERSION                0x01
+#define MWIFIEX_WMM_SUBTYPE                0x01
+
+#define MWIFIEX_RETRY_LIMIT                14
+#define MWIFIEX_SDIO_BLOCK_SIZE            256
+
+#define MWIFIEX_BUF_FLAG_REQUEUED_PKT      BIT(0)
+#define MWIFIEX_BUF_FLAG_BRIDGED_PKT      BIT(1)
+#define MWIFIEX_BUF_FLAG_TDLS_PKT         BIT(2)
+#define MWIFIEX_BUF_FLAG_EAPOL_TX_STATUS   BIT(3)
+#define MWIFIEX_BUF_FLAG_ACTION_TX_STATUS  BIT(4)
+#define MWIFIEX_BUF_FLAG_AGGR_PKT          BIT(5)
+
+#define MWIFIEX_BRIDGED_PKTS_THR_HIGH      1024
+#define MWIFIEX_BRIDGED_PKTS_THR_LOW        128
+
+#define MWIFIEX_TDLS_DISABLE_LINK             0x00
+#define MWIFIEX_TDLS_ENABLE_LINK              0x01
+#define MWIFIEX_TDLS_CREATE_LINK              0x02
+#define MWIFIEX_TDLS_CONFIG_LINK              0x03
+
+#define MWIFIEX_TDLS_RSSI_HIGH         50
+#define MWIFIEX_TDLS_RSSI_LOW          55
+#define MWIFIEX_TDLS_MAX_FAIL_COUNT      4
+#define MWIFIEX_AUTO_TDLS_IDLE_TIME     10
+
+/* 54M rates, index from 0 to 11 */
+#define MWIFIEX_RATE_INDEX_MCS0 12
+/* 12-27=MCS0-15(BW20) */
+#define MWIFIEX_BW20_MCS_NUM 15
+
+/* Rate index for OFDM 0 */
+#define MWIFIEX_RATE_INDEX_OFDM0   4
+
+#define MWIFIEX_MAX_STA_NUM            1
+#define MWIFIEX_MAX_UAP_NUM            1
+#define MWIFIEX_MAX_P2P_NUM            1
+
+#define MWIFIEX_A_BAND_START_FREQ      5000
+
+/* SDIO Aggr data packet special info */
+#define SDIO_MAX_AGGR_BUF_SIZE         (256 * 255)
+#define BLOCK_NUMBER_OFFSET            15
+#define SDIO_HEADER_OFFSET             28
+
+enum mwifiex_bss_type {
+       MWIFIEX_BSS_TYPE_STA = 0,
+       MWIFIEX_BSS_TYPE_UAP = 1,
+       MWIFIEX_BSS_TYPE_P2P = 2,
+       MWIFIEX_BSS_TYPE_ANY = 0xff,
+};
+
+enum mwifiex_bss_role {
+       MWIFIEX_BSS_ROLE_STA = 0,
+       MWIFIEX_BSS_ROLE_UAP = 1,
+       MWIFIEX_BSS_ROLE_ANY = 0xff,
+};
+
+enum mwifiex_tdls_status {
+       TDLS_NOT_SETUP = 0,
+       TDLS_SETUP_INPROGRESS,
+       TDLS_SETUP_COMPLETE,
+       TDLS_SETUP_FAILURE,
+       TDLS_LINK_TEARDOWN,
+       TDLS_CHAN_SWITCHING,
+       TDLS_IN_BASE_CHAN,
+       TDLS_IN_OFF_CHAN,
+};
+
+enum mwifiex_tdls_error_code {
+       TDLS_ERR_NO_ERROR = 0,
+       TDLS_ERR_INTERNAL_ERROR,
+       TDLS_ERR_MAX_LINKS_EST,
+       TDLS_ERR_LINK_EXISTS,
+       TDLS_ERR_LINK_NONEXISTENT,
+       TDLS_ERR_PEER_STA_UNREACHABLE = 25,
+};
+
+#define BSS_ROLE_BIT_MASK    BIT(0)
+
+#define GET_BSS_ROLE(priv)   ((priv)->bss_role & BSS_ROLE_BIT_MASK)
+
+enum mwifiex_data_frame_type {
+       MWIFIEX_DATA_FRAME_TYPE_ETH_II = 0,
+       MWIFIEX_DATA_FRAME_TYPE_802_11,
+};
+
+struct mwifiex_fw_image {
+       u8 *helper_buf;
+       u32 helper_len;
+       u8 *fw_buf;
+       u32 fw_len;
+};
+
+struct mwifiex_802_11_ssid {
+       u32 ssid_len;
+       u8 ssid[IEEE80211_MAX_SSID_LEN];
+};
+
+struct mwifiex_wait_queue {
+       wait_queue_head_t wait;
+       int status;
+};
+
+struct mwifiex_rxinfo {
+       struct sk_buff *parent;
+       u8 bss_num;
+       u8 bss_type;
+       u8 use_count;
+       u8 buf_type;
+};
+
+struct mwifiex_txinfo {
+       u32 status_code;
+       u8 flags;
+       u8 bss_num;
+       u8 bss_type;
+       u8 aggr_num;
+       u32 pkt_len;
+       u8 ack_frame_id;
+       u64 cookie;
+};
+
+enum mwifiex_wmm_ac_e {
+       WMM_AC_BK,
+       WMM_AC_BE,
+       WMM_AC_VI,
+       WMM_AC_VO
+} __packed;
+
+struct ieee_types_wmm_ac_parameters {
+       u8 aci_aifsn_bitmap;
+       u8 ecw_bitmap;
+       __le16 tx_op_limit;
+} __packed;
+
+struct mwifiex_types_wmm_info {
+       u8 oui[4];
+       u8 subtype;
+       u8 version;
+       u8 qos_info;
+       u8 reserved;
+       struct ieee_types_wmm_ac_parameters ac_params[IEEE80211_NUM_ACS];
+} __packed;
+
+struct mwifiex_arp_eth_header {
+       struct arphdr hdr;
+       u8 ar_sha[ETH_ALEN];
+       u8 ar_sip[4];
+       u8 ar_tha[ETH_ALEN];
+       u8 ar_tip[4];
+} __packed;
+
+struct mwifiex_chan_stats {
+       u8 chan_num;
+       u8 bandcfg;
+       u8 flags;
+       s8 noise;
+       u16 total_bss;
+       u16 cca_scan_dur;
+       u16 cca_busy_dur;
+} __packed;
+
+#define MWIFIEX_HIST_MAX_SAMPLES       1048576
+#define MWIFIEX_MAX_RX_RATES                44
+#define MWIFIEX_MAX_AC_RX_RATES                     74
+#define MWIFIEX_MAX_SNR                            256
+#define MWIFIEX_MAX_NOISE_FLR              256
+#define MWIFIEX_MAX_SIG_STRENGTH           256
+
+struct mwifiex_histogram_data {
+       atomic_t rx_rate[MWIFIEX_MAX_AC_RX_RATES];
+       atomic_t snr[MWIFIEX_MAX_SNR];
+       atomic_t noise_flr[MWIFIEX_MAX_NOISE_FLR];
+       atomic_t sig_str[MWIFIEX_MAX_SIG_STRENGTH];
+       atomic_t num_samples;
+};
+
+struct mwifiex_iface_comb {
+       u8 sta_intf;
+       u8 uap_intf;
+       u8 p2p_intf;
+};
+
+struct mwifiex_radar_params {
+       struct cfg80211_chan_def *chandef;
+       u32 cac_time_ms;
+} __packed;
+
+struct mwifiex_11h_intf_state {
+       bool is_11h_enabled;
+       bool is_11h_active;
+} __packed;
+#endif /* !_MWIFIEX_DECL_H_ */
diff --git a/drivers/net/wireless/marvell/mwifiex/ethtool.c b/drivers/net/wireless/marvell/mwifiex/ethtool.c
new file mode 100644 (file)
index 0000000..58400c6
--- /dev/null
@@ -0,0 +1,70 @@
+/*
+ * Marvell Wireless LAN device driver: ethtool
+ *
+ * Copyright (C) 2013-2014, Marvell International Ltd.
+ *
+ * This software file (the "File") is distributed by Marvell International
+ * Ltd. under the terms of the GNU General Public License Version 2, June 1991
+ * (the "License").  You may use, redistribute and/or modify this File in
+ * accordance with the terms and conditions of the License, a copy of which
+ * is available by writing to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the
+ * worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
+ *
+ * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
+ * ARE EXPRESSLY DISCLAIMED.  The License provides additional details about
+ * this warranty disclaimer.
+ */
+
+#include "main.h"
+
+static void mwifiex_ethtool_get_wol(struct net_device *dev,
+                                   struct ethtool_wolinfo *wol)
+{
+       struct mwifiex_private *priv = mwifiex_netdev_get_priv(dev);
+       u32 conditions = le32_to_cpu(priv->adapter->hs_cfg.conditions);
+
+       wol->supported = WAKE_UCAST|WAKE_MCAST|WAKE_BCAST|WAKE_PHY;
+
+       if (conditions == HS_CFG_COND_DEF)
+               return;
+
+       if (conditions & HS_CFG_COND_UNICAST_DATA)
+               wol->wolopts |= WAKE_UCAST;
+       if (conditions & HS_CFG_COND_MULTICAST_DATA)
+               wol->wolopts |= WAKE_MCAST;
+       if (conditions & HS_CFG_COND_BROADCAST_DATA)
+               wol->wolopts |= WAKE_BCAST;
+       if (conditions & HS_CFG_COND_MAC_EVENT)
+               wol->wolopts |= WAKE_PHY;
+}
+
+static int mwifiex_ethtool_set_wol(struct net_device *dev,
+                                  struct ethtool_wolinfo *wol)
+{
+       struct mwifiex_private *priv = mwifiex_netdev_get_priv(dev);
+       u32 conditions = 0;
+
+       if (wol->wolopts & ~(WAKE_UCAST|WAKE_MCAST|WAKE_BCAST|WAKE_PHY))
+               return -EOPNOTSUPP;
+
+       if (wol->wolopts & WAKE_UCAST)
+               conditions |= HS_CFG_COND_UNICAST_DATA;
+       if (wol->wolopts & WAKE_MCAST)
+               conditions |= HS_CFG_COND_MULTICAST_DATA;
+       if (wol->wolopts & WAKE_BCAST)
+               conditions |= HS_CFG_COND_BROADCAST_DATA;
+       if (wol->wolopts & WAKE_PHY)
+               conditions |= HS_CFG_COND_MAC_EVENT;
+       if (wol->wolopts == 0)
+               conditions |= HS_CFG_COND_DEF;
+       priv->adapter->hs_cfg.conditions = cpu_to_le32(conditions);
+
+       return 0;
+}
+
+const struct ethtool_ops mwifiex_ethtool_ops = {
+       .get_wol = mwifiex_ethtool_get_wol,
+       .set_wol = mwifiex_ethtool_set_wol,
+};
diff --git a/drivers/net/wireless/marvell/mwifiex/fw.h b/drivers/net/wireless/marvell/mwifiex/fw.h
new file mode 100644 (file)
index 0000000..1e1e81a
--- /dev/null
@@ -0,0 +1,2177 @@
+/*
+ * Marvell Wireless LAN device driver: Firmware specific macros & structures
+ *
+ * Copyright (C) 2011-2014, Marvell International Ltd.
+ *
+ * This software file (the "File") is distributed by Marvell International
+ * Ltd. under the terms of the GNU General Public License Version 2, June 1991
+ * (the "License").  You may use, redistribute and/or modify this File in
+ * accordance with the terms and conditions of the License, a copy of which
+ * is available by writing to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the
+ * worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
+ *
+ * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
+ * ARE EXPRESSLY DISCLAIMED.  The License provides additional details about
+ * this warranty disclaimer.
+ */
+
+#ifndef _MWIFIEX_FW_H_
+#define _MWIFIEX_FW_H_
+
+#include <linux/if_ether.h>
+
+
+#define INTF_HEADER_LEN     4
+
+struct rfc_1042_hdr {
+       u8 llc_dsap;
+       u8 llc_ssap;
+       u8 llc_ctrl;
+       u8 snap_oui[3];
+       __be16 snap_type;
+};
+
+struct rx_packet_hdr {
+       struct ethhdr eth803_hdr;
+       struct rfc_1042_hdr rfc1042_hdr;
+};
+
+struct tx_packet_hdr {
+       struct ethhdr eth803_hdr;
+       struct rfc_1042_hdr rfc1042_hdr;
+};
+
+#define B_SUPPORTED_RATES               5
+#define G_SUPPORTED_RATES               9
+#define BG_SUPPORTED_RATES              13
+#define A_SUPPORTED_RATES               9
+#define HOSTCMD_SUPPORTED_RATES         14
+#define N_SUPPORTED_RATES               3
+#define ALL_802_11_BANDS           (BAND_A | BAND_B | BAND_G | BAND_GN | \
+                                   BAND_AN | BAND_AAC)
+
+#define FW_MULTI_BANDS_SUPPORT  (BIT(8) | BIT(9) | BIT(10) | BIT(11) | \
+                                BIT(13))
+#define IS_SUPPORT_MULTI_BANDS(adapter)        \
+       (adapter->fw_cap_info & FW_MULTI_BANDS_SUPPORT)
+
+/* bit 13: 11ac BAND_AAC
+ * bit 12: reserved for lab testing, will be reused for BAND_AN
+ * bit 11: 11n  BAND_GN
+ * bit 10: 11a  BAND_A
+ * bit 9: 11g   BAND_G
+ * bit 8: 11b   BAND_B
+ * Map these bits to band capability by right shifting 8 bits.
+ */
+#define GET_FW_DEFAULT_BANDS(adapter)  \
+           (((adapter->fw_cap_info & 0x2f00) >> 8) & \
+            ALL_802_11_BANDS)
+
+#define HostCmd_WEP_KEY_INDEX_MASK              0x3fff
+
+#define KEY_INFO_ENABLED        0x01
+enum KEY_TYPE_ID {
+       KEY_TYPE_ID_WEP = 0,
+       KEY_TYPE_ID_TKIP,
+       KEY_TYPE_ID_AES,
+       KEY_TYPE_ID_WAPI,
+       KEY_TYPE_ID_AES_CMAC,
+};
+
+#define WPA_PN_SIZE            8
+#define KEY_PARAMS_FIXED_LEN   10
+#define KEY_INDEX_MASK         0xf
+#define KEY_API_VER_MAJOR_V2   2
+
+#define KEY_MCAST      BIT(0)
+#define KEY_UNICAST    BIT(1)
+#define KEY_ENABLED    BIT(2)
+#define KEY_DEFAULT    BIT(3)
+#define KEY_TX_KEY     BIT(4)
+#define KEY_RX_KEY     BIT(5)
+#define KEY_IGTK       BIT(10)
+
+#define WAPI_KEY_LEN                   (WLAN_KEY_LEN_SMS4 + PN_LEN + 2)
+
+#define MAX_POLL_TRIES                 100
+#define MAX_FIRMWARE_POLL_TRIES                        100
+
+#define FIRMWARE_READY_SDIO                            0xfedc
+#define FIRMWARE_READY_PCIE                            0xfedcba00
+
+#define MWIFIEX_COEX_MODE_TIMESHARE                    0x01
+#define MWIFIEX_COEX_MODE_SPATIAL                      0x82
+
+enum mwifiex_usb_ep {
+       MWIFIEX_USB_EP_CMD_EVENT = 1,
+       MWIFIEX_USB_EP_DATA = 2,
+       MWIFIEX_USB_EP_DATA_CH2 = 3,
+};
+
+enum MWIFIEX_802_11_PRIVACY_FILTER {
+       MWIFIEX_802_11_PRIV_FILTER_ACCEPT_ALL,
+       MWIFIEX_802_11_PRIV_FILTER_8021X_WEP
+};
+
+#define CAL_SNR(RSSI, NF)              ((s16)((s16)(RSSI)-(s16)(NF)))
+#define CAL_RSSI(SNR, NF)              ((s16)((s16)(SNR)+(s16)(NF)))
+
+#define UAP_BSS_PARAMS_I                       0
+#define UAP_CUSTOM_IE_I                                1
+#define MWIFIEX_AUTO_IDX_MASK                  0xffff
+#define MWIFIEX_DELETE_MASK                    0x0000
+#define MGMT_MASK_ASSOC_REQ                    0x01
+#define MGMT_MASK_REASSOC_REQ                  0x04
+#define MGMT_MASK_ASSOC_RESP                   0x02
+#define MGMT_MASK_REASSOC_RESP                 0x08
+#define MGMT_MASK_PROBE_REQ                    0x10
+#define MGMT_MASK_PROBE_RESP                   0x20
+#define MGMT_MASK_BEACON                       0x100
+
+#define TLV_TYPE_UAP_SSID                      0x0000
+#define TLV_TYPE_UAP_RATES                     0x0001
+#define TLV_TYPE_PWR_CONSTRAINT                        0x0020
+
+#define PROPRIETARY_TLV_BASE_ID                 0x0100
+#define TLV_TYPE_KEY_MATERIAL       (PROPRIETARY_TLV_BASE_ID + 0)
+#define TLV_TYPE_CHANLIST           (PROPRIETARY_TLV_BASE_ID + 1)
+#define TLV_TYPE_NUMPROBES          (PROPRIETARY_TLV_BASE_ID + 2)
+#define TLV_TYPE_RSSI_LOW           (PROPRIETARY_TLV_BASE_ID + 4)
+#define TLV_TYPE_PASSTHROUGH        (PROPRIETARY_TLV_BASE_ID + 10)
+#define TLV_TYPE_WMMQSTATUS         (PROPRIETARY_TLV_BASE_ID + 16)
+#define TLV_TYPE_WILDCARDSSID       (PROPRIETARY_TLV_BASE_ID + 18)
+#define TLV_TYPE_TSFTIMESTAMP       (PROPRIETARY_TLV_BASE_ID + 19)
+#define TLV_TYPE_RSSI_HIGH          (PROPRIETARY_TLV_BASE_ID + 22)
+#define TLV_TYPE_AUTH_TYPE          (PROPRIETARY_TLV_BASE_ID + 31)
+#define TLV_TYPE_STA_MAC_ADDR       (PROPRIETARY_TLV_BASE_ID + 32)
+#define TLV_TYPE_BSSID              (PROPRIETARY_TLV_BASE_ID + 35)
+#define TLV_TYPE_CHANNELBANDLIST    (PROPRIETARY_TLV_BASE_ID + 42)
+#define TLV_TYPE_UAP_BEACON_PERIOD  (PROPRIETARY_TLV_BASE_ID + 44)
+#define TLV_TYPE_UAP_DTIM_PERIOD    (PROPRIETARY_TLV_BASE_ID + 45)
+#define TLV_TYPE_UAP_BCAST_SSID     (PROPRIETARY_TLV_BASE_ID + 48)
+#define TLV_TYPE_UAP_RTS_THRESHOLD  (PROPRIETARY_TLV_BASE_ID + 51)
+#define TLV_TYPE_UAP_AO_TIMER       (PROPRIETARY_TLV_BASE_ID + 57)
+#define TLV_TYPE_UAP_WEP_KEY        (PROPRIETARY_TLV_BASE_ID + 59)
+#define TLV_TYPE_UAP_WPA_PASSPHRASE (PROPRIETARY_TLV_BASE_ID + 60)
+#define TLV_TYPE_UAP_ENCRY_PROTOCOL (PROPRIETARY_TLV_BASE_ID + 64)
+#define TLV_TYPE_UAP_AKMP           (PROPRIETARY_TLV_BASE_ID + 65)
+#define TLV_TYPE_UAP_FRAG_THRESHOLD (PROPRIETARY_TLV_BASE_ID + 70)
+#define TLV_TYPE_RATE_DROP_CONTROL  (PROPRIETARY_TLV_BASE_ID + 82)
+#define TLV_TYPE_RATE_SCOPE         (PROPRIETARY_TLV_BASE_ID + 83)
+#define TLV_TYPE_POWER_GROUP        (PROPRIETARY_TLV_BASE_ID + 84)
+#define TLV_TYPE_BSS_SCAN_RSP       (PROPRIETARY_TLV_BASE_ID + 86)
+#define TLV_TYPE_BSS_SCAN_INFO      (PROPRIETARY_TLV_BASE_ID + 87)
+#define TLV_TYPE_CHANRPT_11H_BASIC  (PROPRIETARY_TLV_BASE_ID + 91)
+#define TLV_TYPE_UAP_RETRY_LIMIT    (PROPRIETARY_TLV_BASE_ID + 93)
+#define TLV_TYPE_WAPI_IE            (PROPRIETARY_TLV_BASE_ID + 94)
+#define TLV_TYPE_ROBUST_COEX        (PROPRIETARY_TLV_BASE_ID + 96)
+#define TLV_TYPE_UAP_MGMT_FRAME     (PROPRIETARY_TLV_BASE_ID + 104)
+#define TLV_TYPE_MGMT_IE            (PROPRIETARY_TLV_BASE_ID + 105)
+#define TLV_TYPE_AUTO_DS_PARAM      (PROPRIETARY_TLV_BASE_ID + 113)
+#define TLV_TYPE_PS_PARAM           (PROPRIETARY_TLV_BASE_ID + 114)
+#define TLV_TYPE_UAP_PS_AO_TIMER    (PROPRIETARY_TLV_BASE_ID + 123)
+#define TLV_TYPE_PWK_CIPHER         (PROPRIETARY_TLV_BASE_ID + 145)
+#define TLV_TYPE_GWK_CIPHER         (PROPRIETARY_TLV_BASE_ID + 146)
+#define TLV_TYPE_TX_PAUSE           (PROPRIETARY_TLV_BASE_ID + 148)
+#define TLV_TYPE_COALESCE_RULE      (PROPRIETARY_TLV_BASE_ID + 154)
+#define TLV_TYPE_KEY_PARAM_V2       (PROPRIETARY_TLV_BASE_ID + 156)
+#define TLV_TYPE_MULTI_CHAN_INFO    (PROPRIETARY_TLV_BASE_ID + 183)
+#define TLV_TYPE_MC_GROUP_INFO      (PROPRIETARY_TLV_BASE_ID + 184)
+#define TLV_TYPE_TDLS_IDLE_TIMEOUT  (PROPRIETARY_TLV_BASE_ID + 194)
+#define TLV_TYPE_SCAN_CHANNEL_GAP   (PROPRIETARY_TLV_BASE_ID + 197)
+#define TLV_TYPE_API_REV            (PROPRIETARY_TLV_BASE_ID + 199)
+#define TLV_TYPE_CHANNEL_STATS      (PROPRIETARY_TLV_BASE_ID + 198)
+#define TLV_BTCOEX_WL_AGGR_WINSIZE  (PROPRIETARY_TLV_BASE_ID + 202)
+#define TLV_BTCOEX_WL_SCANTIME      (PROPRIETARY_TLV_BASE_ID + 203)
+#define TLV_TYPE_BSS_MODE           (PROPRIETARY_TLV_BASE_ID + 206)
+
+#define MWIFIEX_TX_DATA_BUF_SIZE_2K        2048
+
+#define SSN_MASK         0xfff0
+
+#define BA_RESULT_SUCCESS        0x0
+#define BA_RESULT_TIMEOUT        0x2
+
+#define IS_BASTREAM_SETUP(ptr)  (ptr->ba_status)
+
+#define BA_STREAM_NOT_ALLOWED   0xff
+
+#define IS_11N_ENABLED(priv) ((priv->adapter->config_bands & BAND_GN || \
+                       priv->adapter->config_bands & BAND_AN) && \
+                       priv->curr_bss_params.bss_descriptor.bcn_ht_cap)
+#define INITIATOR_BIT(DelBAParamSet) (((DelBAParamSet) &\
+                       BIT(DELBA_INITIATOR_POS)) >> DELBA_INITIATOR_POS)
+
+#define MWIFIEX_TX_DATA_BUF_SIZE_4K        4096
+#define MWIFIEX_TX_DATA_BUF_SIZE_8K        8192
+
+#define ISSUPP_11NENABLED(FwCapInfo) (FwCapInfo & BIT(11))
+#define ISSUPP_TDLS_ENABLED(FwCapInfo) (FwCapInfo & BIT(14))
+#define ISSUPP_DRCS_ENABLED(FwCapInfo) (FwCapInfo & BIT(15))
+#define ISSUPP_SDIO_SPA_ENABLED(FwCapInfo) (FwCapInfo & BIT(16))
+
+#define MWIFIEX_DEF_HT_CAP     (IEEE80211_HT_CAP_DSSSCCK40 | \
+                                (1 << IEEE80211_HT_CAP_RX_STBC_SHIFT) | \
+                                IEEE80211_HT_CAP_SM_PS)
+
+#define MWIFIEX_DEF_11N_TX_BF_CAP      0x09E1E008
+
+#define MWIFIEX_DEF_AMPDU      IEEE80211_HT_AMPDU_PARM_FACTOR
+
+#define GET_RXSTBC(x) (x & IEEE80211_HT_CAP_RX_STBC)
+#define MWIFIEX_RX_STBC1       0x0100
+#define MWIFIEX_RX_STBC12      0x0200
+#define MWIFIEX_RX_STBC123     0x0300
+
+/* dev_cap bitmap
+ * BIT
+ * 0-16                reserved
+ * 17          IEEE80211_HT_CAP_SUP_WIDTH_20_40
+ * 18-22       reserved
+ * 23          IEEE80211_HT_CAP_SGI_20
+ * 24          IEEE80211_HT_CAP_SGI_40
+ * 25          IEEE80211_HT_CAP_TX_STBC
+ * 26          IEEE80211_HT_CAP_RX_STBC
+ * 27-28       reserved
+ * 29          IEEE80211_HT_CAP_GRN_FLD
+ * 30-31       reserved
+ */
+#define ISSUPP_CHANWIDTH40(Dot11nDevCap) (Dot11nDevCap & BIT(17))
+#define ISSUPP_SHORTGI20(Dot11nDevCap) (Dot11nDevCap & BIT(23))
+#define ISSUPP_SHORTGI40(Dot11nDevCap) (Dot11nDevCap & BIT(24))
+#define ISSUPP_TXSTBC(Dot11nDevCap) (Dot11nDevCap & BIT(25))
+#define ISSUPP_RXSTBC(Dot11nDevCap) (Dot11nDevCap & BIT(26))
+#define ISSUPP_GREENFIELD(Dot11nDevCap) (Dot11nDevCap & BIT(29))
+#define ISENABLED_40MHZ_INTOLERANT(Dot11nDevCap) (Dot11nDevCap & BIT(8))
+#define ISSUPP_RXLDPC(Dot11nDevCap) (Dot11nDevCap & BIT(22))
+#define ISSUPP_BEAMFORMING(Dot11nDevCap) (Dot11nDevCap & BIT(30))
+#define ISALLOWED_CHANWIDTH40(ht_param) (ht_param & BIT(2))
+#define GETSUPP_TXBASTREAMS(Dot11nDevCap) ((Dot11nDevCap >> 18) & 0xF)
+
+/* httxcfg bitmap
+ * 0           reserved
+ * 1           20/40 Mhz enable(1)/disable(0)
+ * 2-3         reserved
+ * 4           green field enable(1)/disable(0)
+ * 5           short GI in 20 Mhz enable(1)/disable(0)
+ * 6           short GI in 40 Mhz enable(1)/disable(0)
+ * 7-15                reserved
+ */
+#define MWIFIEX_FW_DEF_HTTXCFG (BIT(1) | BIT(4) | BIT(5) | BIT(6))
+
+/* 11AC Tx and Rx MCS map for 1x1 mode:
+ * IEEE80211_VHT_MCS_SUPPORT_0_9 for stream 1
+ * IEEE80211_VHT_MCS_NOT_SUPPORTED for remaining 7 streams
+ */
+#define MWIFIEX_11AC_MCS_MAP_1X1       0xfffefffe
+
+/* 11AC Tx and Rx MCS map for 2x2 mode:
+ * IEEE80211_VHT_MCS_SUPPORT_0_9 for stream 1 and 2
+ * IEEE80211_VHT_MCS_NOT_SUPPORTED for remaining 6 streams
+ */
+#define MWIFIEX_11AC_MCS_MAP_2X2       0xfffafffa
+
+#define GET_RXMCSSUPP(DevMCSSupported) (DevMCSSupported & 0x0f)
+#define SETHT_MCS32(x) (x[4] |= 1)
+#define HT_STREAM_1X1  0x11
+#define HT_STREAM_2X2  0x22
+
+#define SET_SECONDARYCHAN(RadioType, SECCHAN) (RadioType |= (SECCHAN << 4))
+
+#define LLC_SNAP_LEN    8
+
+/* HW_SPEC fw_cap_info */
+
+#define ISSUPP_11ACENABLED(fw_cap_info) (fw_cap_info & BIT(13))
+
+#define GET_VHTCAP_CHWDSET(vht_cap_info)    ((vht_cap_info >> 2) & 0x3)
+#define GET_VHTNSSMCS(mcs_mapset, nss) ((mcs_mapset >> (2 * (nss - 1))) & 0x3)
+#define SET_VHTNSSMCS(mcs_mapset, nss, value) (mcs_mapset |= (value & 0x3) << \
+                                             (2 * (nss - 1)))
+#define GET_DEVTXMCSMAP(dev_mcs_map)      (dev_mcs_map >> 16)
+#define GET_DEVRXMCSMAP(dev_mcs_map)      (dev_mcs_map & 0xFFFF)
+
+/* Clear SU Beanformer, MU beanformer, MU beanformee and
+ * sounding dimensions bits
+ */
+#define MWIFIEX_DEF_11AC_CAP_BF_RESET_MASK \
+                       (IEEE80211_VHT_CAP_SU_BEAMFORMER_CAPABLE | \
+                        IEEE80211_VHT_CAP_MU_BEAMFORMER_CAPABLE | \
+                        IEEE80211_VHT_CAP_MU_BEAMFORMEE_CAPABLE | \
+                        IEEE80211_VHT_CAP_SOUNDING_DIMENSIONS_MASK)
+
+#define MOD_CLASS_HR_DSSS       0x03
+#define MOD_CLASS_OFDM          0x07
+#define MOD_CLASS_HT            0x08
+#define HT_BW_20    0
+#define HT_BW_40    1
+
+#define DFS_CHAN_MOVE_TIME      10000
+
+#define HostCmd_CMD_GET_HW_SPEC                       0x0003
+#define HostCmd_CMD_802_11_SCAN                       0x0006
+#define HostCmd_CMD_802_11_GET_LOG                    0x000b
+#define HostCmd_CMD_MAC_MULTICAST_ADR                 0x0010
+#define HostCmd_CMD_802_11_EEPROM_ACCESS              0x0059
+#define HostCmd_CMD_802_11_ASSOCIATE                  0x0012
+#define HostCmd_CMD_802_11_SNMP_MIB                   0x0016
+#define HostCmd_CMD_MAC_REG_ACCESS                    0x0019
+#define HostCmd_CMD_BBP_REG_ACCESS                    0x001a
+#define HostCmd_CMD_RF_REG_ACCESS                     0x001b
+#define HostCmd_CMD_PMIC_REG_ACCESS                   0x00ad
+#define HostCmd_CMD_RF_TX_PWR                         0x001e
+#define HostCmd_CMD_RF_ANTENNA                        0x0020
+#define HostCmd_CMD_802_11_DEAUTHENTICATE             0x0024
+#define HostCmd_CMD_MAC_CONTROL                       0x0028
+#define HostCmd_CMD_802_11_AD_HOC_START               0x002b
+#define HostCmd_CMD_802_11_AD_HOC_JOIN                0x002c
+#define HostCmd_CMD_802_11_AD_HOC_STOP                0x0040
+#define HostCmd_CMD_802_11_MAC_ADDRESS                0x004D
+#define HostCmd_CMD_802_11D_DOMAIN_INFO               0x005b
+#define HostCmd_CMD_802_11_KEY_MATERIAL               0x005e
+#define HostCmd_CMD_802_11_BG_SCAN_QUERY              0x006c
+#define HostCmd_CMD_WMM_GET_STATUS                    0x0071
+#define HostCmd_CMD_802_11_SUBSCRIBE_EVENT            0x0075
+#define HostCmd_CMD_802_11_TX_RATE_QUERY              0x007f
+#define HostCmd_CMD_802_11_IBSS_COALESCING_STATUS     0x0083
+#define HostCmd_CMD_MEM_ACCESS                        0x0086
+#define HostCmd_CMD_CFG_DATA                          0x008f
+#define HostCmd_CMD_VERSION_EXT                       0x0097
+#define HostCmd_CMD_MEF_CFG                           0x009a
+#define HostCmd_CMD_RSSI_INFO                         0x00a4
+#define HostCmd_CMD_FUNC_INIT                         0x00a9
+#define HostCmd_CMD_FUNC_SHUTDOWN                     0x00aa
+#define HOST_CMD_APCMD_SYS_RESET                      0x00af
+#define HostCmd_CMD_UAP_SYS_CONFIG                    0x00b0
+#define HostCmd_CMD_UAP_BSS_START                     0x00b1
+#define HostCmd_CMD_UAP_BSS_STOP                      0x00b2
+#define HOST_CMD_APCMD_STA_LIST                       0x00b3
+#define HostCmd_CMD_UAP_STA_DEAUTH                    0x00b5
+#define HostCmd_CMD_11N_CFG                           0x00cd
+#define HostCmd_CMD_11N_ADDBA_REQ                     0x00ce
+#define HostCmd_CMD_11N_ADDBA_RSP                     0x00cf
+#define HostCmd_CMD_11N_DELBA                         0x00d0
+#define HostCmd_CMD_RECONFIGURE_TX_BUFF               0x00d9
+#define HostCmd_CMD_CHAN_REPORT_REQUEST               0x00dd
+#define HostCmd_CMD_AMSDU_AGGR_CTRL                   0x00df
+#define HostCmd_CMD_TXPWR_CFG                         0x00d1
+#define HostCmd_CMD_TX_RATE_CFG                       0x00d6
+#define HostCmd_CMD_ROBUST_COEX                       0x00e0
+#define HostCmd_CMD_802_11_PS_MODE_ENH                0x00e4
+#define HostCmd_CMD_802_11_HS_CFG_ENH                 0x00e5
+#define HostCmd_CMD_P2P_MODE_CFG                      0x00eb
+#define HostCmd_CMD_CAU_REG_ACCESS                    0x00ed
+#define HostCmd_CMD_SET_BSS_MODE                      0x00f7
+#define HostCmd_CMD_PCIE_DESC_DETAILS                 0x00fa
+#define HostCmd_CMD_802_11_SCAN_EXT                   0x0107
+#define HostCmd_CMD_COALESCE_CFG                      0x010a
+#define HostCmd_CMD_MGMT_FRAME_REG                    0x010c
+#define HostCmd_CMD_REMAIN_ON_CHAN                    0x010d
+#define HostCmd_CMD_11AC_CFG                         0x0112
+#define HostCmd_CMD_TDLS_CONFIG                       0x0100
+#define HostCmd_CMD_MC_POLICY                         0x0121
+#define HostCmd_CMD_TDLS_OPER                         0x0122
+#define HostCmd_CMD_SDIO_SP_RX_AGGR_CFG               0x0223
+
+#define PROTOCOL_NO_SECURITY        0x01
+#define PROTOCOL_STATIC_WEP         0x02
+#define PROTOCOL_WPA                0x08
+#define PROTOCOL_WPA2               0x20
+#define PROTOCOL_WPA2_MIXED         0x28
+#define PROTOCOL_EAP                0x40
+#define KEY_MGMT_NONE               0x04
+#define KEY_MGMT_PSK                0x02
+#define KEY_MGMT_EAP                0x01
+#define CIPHER_TKIP                 0x04
+#define CIPHER_AES_CCMP             0x08
+#define VALID_CIPHER_BITMAP         0x0c
+
+enum ENH_PS_MODES {
+       EN_PS = 1,
+       DIS_PS = 2,
+       EN_AUTO_DS = 3,
+       DIS_AUTO_DS = 4,
+       SLEEP_CONFIRM = 5,
+       GET_PS = 0,
+       EN_AUTO_PS = 0xff,
+       DIS_AUTO_PS = 0xfe,
+};
+
+enum P2P_MODES {
+       P2P_MODE_DISABLE = 0,
+       P2P_MODE_DEVICE = 1,
+       P2P_MODE_GO = 2,
+       P2P_MODE_CLIENT = 3,
+};
+
+#define HostCmd_RET_BIT                       0x8000
+#define HostCmd_ACT_GEN_GET                   0x0000
+#define HostCmd_ACT_GEN_SET                   0x0001
+#define HostCmd_ACT_GEN_REMOVE                0x0004
+#define HostCmd_ACT_BITWISE_SET               0x0002
+#define HostCmd_ACT_BITWISE_CLR               0x0003
+#define HostCmd_RESULT_OK                     0x0000
+
+#define HostCmd_ACT_MAC_RX_ON                 0x0001
+#define HostCmd_ACT_MAC_TX_ON                 0x0002
+#define HostCmd_ACT_MAC_WEP_ENABLE            0x0008
+#define HostCmd_ACT_MAC_ETHERNETII_ENABLE     0x0010
+#define HostCmd_ACT_MAC_PROMISCUOUS_ENABLE    0x0080
+#define HostCmd_ACT_MAC_ALL_MULTICAST_ENABLE  0x0100
+#define HostCmd_ACT_MAC_ADHOC_G_PROTECTION_ON     0x2000
+
+#define HostCmd_BSS_MODE_IBSS               0x0002
+#define HostCmd_BSS_MODE_ANY                0x0003
+
+#define HostCmd_SCAN_RADIO_TYPE_BG          0
+#define HostCmd_SCAN_RADIO_TYPE_A           1
+
+#define HS_CFG_CANCEL                  0xffffffff
+#define HS_CFG_COND_DEF                        0x00000000
+#define HS_CFG_GPIO_DEF                        0xff
+#define HS_CFG_GAP_DEF                 0xff
+#define HS_CFG_COND_BROADCAST_DATA     0x00000001
+#define HS_CFG_COND_UNICAST_DATA       0x00000002
+#define HS_CFG_COND_MAC_EVENT          0x00000004
+#define HS_CFG_COND_MULTICAST_DATA     0x00000008
+
+#define CONNECT_ERR_AUTH_ERR_STA_FAILURE       0xFFFB
+#define CONNECT_ERR_ASSOC_ERR_TIMEOUT          0xFFFC
+#define CONNECT_ERR_ASSOC_ERR_AUTH_REFUSED     0xFFFD
+#define CONNECT_ERR_AUTH_MSG_UNHANDLED         0xFFFE
+#define CONNECT_ERR_STA_FAILURE                        0xFFFF
+
+
+#define CMD_F_HOSTCMD           (1 << 0)
+
+#define HostCmd_CMD_ID_MASK             0x0fff
+
+#define HostCmd_SEQ_NUM_MASK            0x00ff
+
+#define HostCmd_BSS_NUM_MASK            0x0f00
+
+#define HostCmd_BSS_TYPE_MASK           0xf000
+
+#define HostCmd_ACT_SET_RX              0x0001
+#define HostCmd_ACT_SET_TX              0x0002
+#define HostCmd_ACT_SET_BOTH            0x0003
+
+#define RF_ANTENNA_AUTO                 0xFFFF
+
+#define HostCmd_SET_SEQ_NO_BSS_INFO(seq, num, type) {   \
+       (((seq) & 0x00ff) |                             \
+        (((num) & 0x000f) << 8)) |                     \
+       (((type) & 0x000f) << 12);                  }
+
+#define HostCmd_GET_SEQ_NO(seq)       \
+       ((seq) & HostCmd_SEQ_NUM_MASK)
+
+#define HostCmd_GET_BSS_NO(seq)         \
+       (((seq) & HostCmd_BSS_NUM_MASK) >> 8)
+
+#define HostCmd_GET_BSS_TYPE(seq)       \
+       (((seq) & HostCmd_BSS_TYPE_MASK) >> 12)
+
+#define EVENT_DUMMY_HOST_WAKEUP_SIGNAL  0x00000001
+#define EVENT_LINK_LOST                 0x00000003
+#define EVENT_LINK_SENSED               0x00000004
+#define EVENT_MIB_CHANGED               0x00000006
+#define EVENT_INIT_DONE                 0x00000007
+#define EVENT_DEAUTHENTICATED           0x00000008
+#define EVENT_DISASSOCIATED             0x00000009
+#define EVENT_PS_AWAKE                  0x0000000a
+#define EVENT_PS_SLEEP                  0x0000000b
+#define EVENT_MIC_ERR_MULTICAST         0x0000000d
+#define EVENT_MIC_ERR_UNICAST           0x0000000e
+#define EVENT_DEEP_SLEEP_AWAKE          0x00000010
+#define EVENT_ADHOC_BCN_LOST            0x00000011
+
+#define EVENT_WMM_STATUS_CHANGE         0x00000017
+#define EVENT_BG_SCAN_REPORT            0x00000018
+#define EVENT_RSSI_LOW                  0x00000019
+#define EVENT_SNR_LOW                   0x0000001a
+#define EVENT_MAX_FAIL                  0x0000001b
+#define EVENT_RSSI_HIGH                 0x0000001c
+#define EVENT_SNR_HIGH                  0x0000001d
+#define EVENT_IBSS_COALESCED            0x0000001e
+#define EVENT_DATA_RSSI_LOW             0x00000024
+#define EVENT_DATA_SNR_LOW              0x00000025
+#define EVENT_DATA_RSSI_HIGH            0x00000026
+#define EVENT_DATA_SNR_HIGH             0x00000027
+#define EVENT_LINK_QUALITY              0x00000028
+#define EVENT_PORT_RELEASE              0x0000002b
+#define EVENT_UAP_STA_DEAUTH            0x0000002c
+#define EVENT_UAP_STA_ASSOC             0x0000002d
+#define EVENT_UAP_BSS_START             0x0000002e
+#define EVENT_PRE_BEACON_LOST           0x00000031
+#define EVENT_ADDBA                     0x00000033
+#define EVENT_DELBA                     0x00000034
+#define EVENT_BA_STREAM_TIEMOUT         0x00000037
+#define EVENT_AMSDU_AGGR_CTRL           0x00000042
+#define EVENT_UAP_BSS_IDLE              0x00000043
+#define EVENT_UAP_BSS_ACTIVE            0x00000044
+#define EVENT_WEP_ICV_ERR               0x00000046
+#define EVENT_HS_ACT_REQ                0x00000047
+#define EVENT_BW_CHANGE                 0x00000048
+#define EVENT_UAP_MIC_COUNTERMEASURES   0x0000004c
+#define EVENT_HOSTWAKE_STAIE           0x0000004d
+#define EVENT_CHANNEL_SWITCH_ANN        0x00000050
+#define EVENT_TDLS_GENERIC_EVENT        0x00000052
+#define EVENT_RADAR_DETECTED           0x00000053
+#define EVENT_CHANNEL_REPORT_RDY        0x00000054
+#define EVENT_TX_DATA_PAUSE             0x00000055
+#define EVENT_EXT_SCAN_REPORT           0x00000058
+#define EVENT_REMAIN_ON_CHAN_EXPIRED    0x0000005f
+#define EVENT_MULTI_CHAN_INFO           0x0000006a
+#define EVENT_TX_STATUS_REPORT         0x00000074
+#define EVENT_BT_COEX_WLAN_PARA_CHANGE 0X00000076
+
+#define EVENT_ID_MASK                   0xffff
+#define BSS_NUM_MASK                    0xf
+
+#define EVENT_GET_BSS_NUM(event_cause)          \
+       (((event_cause) >> 16) & BSS_NUM_MASK)
+
+#define EVENT_GET_BSS_TYPE(event_cause)         \
+       (((event_cause) >> 24) & 0x00ff)
+
+#define MWIFIEX_MAX_PATTERN_LEN                20
+#define MWIFIEX_MAX_OFFSET_LEN         100
+#define STACK_NBYTES                   100
+#define TYPE_DNUM                      1
+#define TYPE_BYTESEQ                   2
+#define MAX_OPERAND                    0x40
+#define TYPE_EQ                                (MAX_OPERAND+1)
+#define TYPE_EQ_DNUM                   (MAX_OPERAND+2)
+#define TYPE_EQ_BIT                    (MAX_OPERAND+3)
+#define TYPE_AND                       (MAX_OPERAND+4)
+#define TYPE_OR                                (MAX_OPERAND+5)
+#define MEF_MODE_HOST_SLEEP                    1
+#define MEF_ACTION_ALLOW_AND_WAKEUP_HOST       3
+#define MEF_ACTION_AUTO_ARP                    0x10
+#define MWIFIEX_CRITERIA_BROADCAST     BIT(0)
+#define MWIFIEX_CRITERIA_UNICAST       BIT(1)
+#define MWIFIEX_CRITERIA_MULTICAST     BIT(3)
+#define MWIFIEX_MAX_SUPPORTED_IPADDR              4
+
+#define ACT_TDLS_DELETE            0x00
+#define ACT_TDLS_CREATE            0x01
+#define ACT_TDLS_CONFIG            0x02
+
+#define TDLS_EVENT_LINK_TEAR_DOWN      3
+#define TDLS_EVENT_CHAN_SWITCH_RESULT  7
+#define TDLS_EVENT_START_CHAN_SWITCH   8
+#define TDLS_EVENT_CHAN_SWITCH_STOPPED 9
+
+#define TDLS_BASE_CHANNEL             0
+#define TDLS_OFF_CHANNEL              1
+
+#define ACT_TDLS_CS_ENABLE_CONFIG 0x00
+#define ACT_TDLS_CS_INIT         0x06
+#define ACT_TDLS_CS_STOP         0x07
+#define ACT_TDLS_CS_PARAMS       0x08
+
+#define MWIFIEX_DEF_CS_UNIT_TIME       2
+#define MWIFIEX_DEF_CS_THR_OTHERLINK   10
+#define MWIFIEX_DEF_THR_DIRECTLINK     0
+#define MWIFIEX_DEF_CS_TIME            10
+#define MWIFIEX_DEF_CS_TIMEOUT         16
+#define MWIFIEX_DEF_CS_REG_CLASS       12
+#define MWIFIEX_DEF_CS_PERIODICITY     1
+
+#define MWIFIEX_FW_V15            15
+
+#define MWIFIEX_MASTER_RADAR_DET_MASK BIT(1)
+
+struct mwifiex_ie_types_header {
+       __le16 type;
+       __le16 len;
+} __packed;
+
+struct mwifiex_ie_types_data {
+       struct mwifiex_ie_types_header header;
+       u8 data[1];
+} __packed;
+
+#define MWIFIEX_TxPD_POWER_MGMT_NULL_PACKET 0x01
+#define MWIFIEX_TxPD_POWER_MGMT_LAST_PACKET 0x08
+#define MWIFIEX_TXPD_FLAGS_TDLS_PACKET      0x10
+#define MWIFIEX_RXPD_FLAGS_TDLS_PACKET      0x01
+#define MWIFIEX_TXPD_FLAGS_REQ_TX_STATUS    0x20
+
+struct txpd {
+       u8 bss_type;
+       u8 bss_num;
+       __le16 tx_pkt_length;
+       __le16 tx_pkt_offset;
+       __le16 tx_pkt_type;
+       __le32 tx_control;
+       u8 priority;
+       u8 flags;
+       u8 pkt_delay_2ms;
+       u8 reserved1[2];
+       u8 tx_token_id;
+       u8 reserved[2];
+} __packed;
+
+struct rxpd {
+       u8 bss_type;
+       u8 bss_num;
+       __le16 rx_pkt_length;
+       __le16 rx_pkt_offset;
+       __le16 rx_pkt_type;
+       __le16 seq_num;
+       u8 priority;
+       u8 rx_rate;
+       s8 snr;
+       s8 nf;
+
+       /* For: Non-802.11 AC cards
+        *
+        * Ht Info [Bit 0] RxRate format: LG=0, HT=1
+        * [Bit 1]  HT Bandwidth: BW20 = 0, BW40 = 1
+        * [Bit 2]  HT Guard Interval: LGI = 0, SGI = 1
+        *
+        * For: 802.11 AC cards
+        * [Bit 1] [Bit 0] RxRate format: legacy rate = 00 HT = 01 VHT = 10
+        * [Bit 3] [Bit 2] HT/VHT Bandwidth BW20 = 00 BW40 = 01
+        *                                              BW80 = 10  BW160 = 11
+        * [Bit 4] HT/VHT Guard interval LGI = 0 SGI = 1
+        * [Bit 5] STBC support Enabled = 1
+        * [Bit 6] LDPC support Enabled = 1
+        * [Bit 7] Reserved
+        */
+       u8 ht_info;
+       u8 reserved[3];
+       u8 flags;
+} __packed;
+
+struct uap_txpd {
+       u8 bss_type;
+       u8 bss_num;
+       __le16 tx_pkt_length;
+       __le16 tx_pkt_offset;
+       __le16 tx_pkt_type;
+       __le32 tx_control;
+       u8 priority;
+       u8 flags;
+       u8 pkt_delay_2ms;
+       u8 reserved1[2];
+       u8 tx_token_id;
+       u8 reserved[2];
+};
+
+struct uap_rxpd {
+       u8 bss_type;
+       u8 bss_num;
+       __le16 rx_pkt_length;
+       __le16 rx_pkt_offset;
+       __le16 rx_pkt_type;
+       __le16 seq_num;
+       u8 priority;
+       u8 rx_rate;
+       s8 snr;
+       s8 nf;
+       u8 ht_info;
+       u8 reserved[3];
+       u8 flags;
+};
+
+struct mwifiex_fw_chan_stats {
+       u8 chan_num;
+       u8 bandcfg;
+       u8 flags;
+       s8 noise;
+       __le16 total_bss;
+       __le16 cca_scan_dur;
+       __le16 cca_busy_dur;
+} __packed;
+
+enum mwifiex_chan_scan_mode_bitmasks {
+       MWIFIEX_PASSIVE_SCAN = BIT(0),
+       MWIFIEX_DISABLE_CHAN_FILT = BIT(1),
+       MWIFIEX_HIDDEN_SSID_REPORT = BIT(4),
+};
+
+struct mwifiex_chan_scan_param_set {
+       u8 radio_type;
+       u8 chan_number;
+       u8 chan_scan_mode_bitmap;
+       __le16 min_scan_time;
+       __le16 max_scan_time;
+} __packed;
+
+struct mwifiex_ie_types_chan_list_param_set {
+       struct mwifiex_ie_types_header header;
+       struct mwifiex_chan_scan_param_set chan_scan_param[1];
+} __packed;
+
+struct chan_band_param_set {
+       u8 radio_type;
+       u8 chan_number;
+};
+
+struct mwifiex_ie_types_chan_band_list_param_set {
+       struct mwifiex_ie_types_header header;
+       struct chan_band_param_set chan_band_param[1];
+} __packed;
+
+struct mwifiex_ie_types_rates_param_set {
+       struct mwifiex_ie_types_header header;
+       u8 rates[1];
+} __packed;
+
+struct mwifiex_ie_types_ssid_param_set {
+       struct mwifiex_ie_types_header header;
+       u8 ssid[1];
+} __packed;
+
+struct mwifiex_ie_types_num_probes {
+       struct mwifiex_ie_types_header header;
+       __le16 num_probes;
+} __packed;
+
+struct mwifiex_ie_types_scan_chan_gap {
+       struct mwifiex_ie_types_header header;
+       /* time gap in TUs to be used between two consecutive channels scan */
+       __le16 chan_gap;
+} __packed;
+
+struct mwifiex_ietypes_chanstats {
+       struct mwifiex_ie_types_header header;
+       struct mwifiex_fw_chan_stats chanstats[0];
+} __packed;
+
+struct mwifiex_ie_types_wildcard_ssid_params {
+       struct mwifiex_ie_types_header header;
+       u8 max_ssid_length;
+       u8 ssid[1];
+} __packed;
+
+#define TSF_DATA_SIZE            8
+struct mwifiex_ie_types_tsf_timestamp {
+       struct mwifiex_ie_types_header header;
+       u8 tsf_data[1];
+} __packed;
+
+struct mwifiex_cf_param_set {
+       u8 cfp_cnt;
+       u8 cfp_period;
+       __le16 cfp_max_duration;
+       __le16 cfp_duration_remaining;
+} __packed;
+
+struct mwifiex_ibss_param_set {
+       __le16 atim_window;
+} __packed;
+
+struct mwifiex_ie_types_ss_param_set {
+       struct mwifiex_ie_types_header header;
+       union {
+               struct mwifiex_cf_param_set cf_param_set[1];
+               struct mwifiex_ibss_param_set ibss_param_set[1];
+       } cf_ibss;
+} __packed;
+
+struct mwifiex_fh_param_set {
+       __le16 dwell_time;
+       u8 hop_set;
+       u8 hop_pattern;
+       u8 hop_index;
+} __packed;
+
+struct mwifiex_ds_param_set {
+       u8 current_chan;
+} __packed;
+
+struct mwifiex_ie_types_phy_param_set {
+       struct mwifiex_ie_types_header header;
+       union {
+               struct mwifiex_fh_param_set fh_param_set[1];
+               struct mwifiex_ds_param_set ds_param_set[1];
+       } fh_ds;
+} __packed;
+
+struct mwifiex_ie_types_auth_type {
+       struct mwifiex_ie_types_header header;
+       __le16 auth_type;
+} __packed;
+
+struct mwifiex_ie_types_vendor_param_set {
+       struct mwifiex_ie_types_header header;
+       u8 ie[MWIFIEX_MAX_VSIE_LEN];
+};
+
+#define MWIFIEX_TDLS_IDLE_TIMEOUT_IN_SEC       60
+
+struct mwifiex_ie_types_tdls_idle_timeout {
+       struct mwifiex_ie_types_header header;
+       __le16 value;
+} __packed;
+
+struct mwifiex_ie_types_rsn_param_set {
+       struct mwifiex_ie_types_header header;
+       u8 rsn_ie[1];
+} __packed;
+
+#define KEYPARAMSET_FIXED_LEN 6
+
+struct mwifiex_ie_type_key_param_set {
+       __le16 type;
+       __le16 length;
+       __le16 key_type_id;
+       __le16 key_info;
+       __le16 key_len;
+       u8 key[50];
+} __packed;
+
+#define IGTK_PN_LEN            8
+
+struct mwifiex_cmac_param {
+       u8 ipn[IGTK_PN_LEN];
+       u8 key[WLAN_KEY_LEN_AES_CMAC];
+} __packed;
+
+struct mwifiex_wep_param {
+       __le16 key_len;
+       u8 key[WLAN_KEY_LEN_WEP104];
+} __packed;
+
+struct mwifiex_tkip_param {
+       u8 pn[WPA_PN_SIZE];
+       __le16 key_len;
+       u8 key[WLAN_KEY_LEN_TKIP];
+} __packed;
+
+struct mwifiex_aes_param {
+       u8 pn[WPA_PN_SIZE];
+       __le16 key_len;
+       u8 key[WLAN_KEY_LEN_CCMP];
+} __packed;
+
+struct mwifiex_wapi_param {
+       u8 pn[PN_LEN];
+       __le16 key_len;
+       u8 key[WLAN_KEY_LEN_SMS4];
+} __packed;
+
+struct mwifiex_cmac_aes_param {
+       u8 ipn[IGTK_PN_LEN];
+       __le16 key_len;
+       u8 key[WLAN_KEY_LEN_AES_CMAC];
+} __packed;
+
+struct mwifiex_ie_type_key_param_set_v2 {
+       __le16 type;
+       __le16 len;
+       u8 mac_addr[ETH_ALEN];
+       u8 key_idx;
+       u8 key_type;
+       __le16 key_info;
+       union {
+               struct mwifiex_wep_param wep;
+               struct mwifiex_tkip_param tkip;
+               struct mwifiex_aes_param aes;
+               struct mwifiex_wapi_param wapi;
+               struct mwifiex_cmac_aes_param cmac_aes;
+       } key_params;
+} __packed;
+
+struct host_cmd_ds_802_11_key_material_v2 {
+       __le16 action;
+       struct mwifiex_ie_type_key_param_set_v2 key_param_set;
+} __packed;
+
+struct host_cmd_ds_802_11_key_material {
+       __le16 action;
+       struct mwifiex_ie_type_key_param_set key_param_set;
+} __packed;
+
+struct host_cmd_ds_gen {
+       __le16 command;
+       __le16 size;
+       __le16 seq_num;
+       __le16 result;
+};
+
+#define S_DS_GEN        sizeof(struct host_cmd_ds_gen)
+
+enum sleep_resp_ctrl {
+       RESP_NOT_NEEDED = 0,
+       RESP_NEEDED,
+};
+
+struct mwifiex_ps_param {
+       __le16 null_pkt_interval;
+       __le16 multiple_dtims;
+       __le16 bcn_miss_timeout;
+       __le16 local_listen_interval;
+       __le16 adhoc_wake_period;
+       __le16 mode;
+       __le16 delay_to_ps;
+};
+
+#define BITMAP_AUTO_DS         0x01
+#define BITMAP_STA_PS          0x10
+
+struct mwifiex_ie_types_auto_ds_param {
+       struct mwifiex_ie_types_header header;
+       __le16 deep_sleep_timeout;
+} __packed;
+
+struct mwifiex_ie_types_ps_param {
+       struct mwifiex_ie_types_header header;
+       struct mwifiex_ps_param param;
+} __packed;
+
+struct host_cmd_ds_802_11_ps_mode_enh {
+       __le16 action;
+
+       union {
+               struct mwifiex_ps_param opt_ps;
+               __le16 ps_bitmap;
+       } params;
+} __packed;
+
+enum API_VER_ID {
+       KEY_API_VER_ID = 1,
+       FW_API_VER_ID = 2,
+};
+
+struct hw_spec_api_rev {
+       struct mwifiex_ie_types_header header;
+       __le16 api_id;
+       u8 major_ver;
+       u8 minor_ver;
+} __packed;
+
+struct host_cmd_ds_get_hw_spec {
+       __le16 hw_if_version;
+       __le16 version;
+       __le16 reserved;
+       __le16 num_of_mcast_adr;
+       u8 permanent_addr[ETH_ALEN];
+       __le16 region_code;
+       __le16 number_of_antenna;
+       __le32 fw_release_number;
+       __le32 reserved_1;
+       __le32 reserved_2;
+       __le32 reserved_3;
+       __le32 fw_cap_info;
+       __le32 dot_11n_dev_cap;
+       u8 dev_mcs_support;
+       __le16 mp_end_port;     /* SDIO only, reserved for other interfacces */
+       __le16 mgmt_buf_count;  /* mgmt IE buffer count */
+       __le32 reserved_5;
+       __le32 reserved_6;
+       __le32 dot_11ac_dev_cap;
+       __le32 dot_11ac_mcs_support;
+       u8 tlvs[0];
+} __packed;
+
+struct host_cmd_ds_802_11_rssi_info {
+       __le16 action;
+       __le16 ndata;
+       __le16 nbcn;
+       __le16 reserved[9];
+       long long reserved_1;
+};
+
+struct host_cmd_ds_802_11_rssi_info_rsp {
+       __le16 action;
+       __le16 ndata;
+       __le16 nbcn;
+       __le16 data_rssi_last;
+       __le16 data_nf_last;
+       __le16 data_rssi_avg;
+       __le16 data_nf_avg;
+       __le16 bcn_rssi_last;
+       __le16 bcn_nf_last;
+       __le16 bcn_rssi_avg;
+       __le16 bcn_nf_avg;
+       long long tsf_bcn;
+};
+
+struct host_cmd_ds_802_11_mac_address {
+       __le16 action;
+       u8 mac_addr[ETH_ALEN];
+};
+
+struct host_cmd_ds_mac_control {
+       __le16 action;
+       __le16 reserved;
+};
+
+struct host_cmd_ds_mac_multicast_adr {
+       __le16 action;
+       __le16 num_of_adrs;
+       u8 mac_list[MWIFIEX_MAX_MULTICAST_LIST_SIZE][ETH_ALEN];
+} __packed;
+
+struct host_cmd_ds_802_11_deauthenticate {
+       u8 mac_addr[ETH_ALEN];
+       __le16 reason_code;
+} __packed;
+
+struct host_cmd_ds_802_11_associate {
+       u8 peer_sta_addr[ETH_ALEN];
+       __le16 cap_info_bitmap;
+       __le16 listen_interval;
+       __le16 beacon_period;
+       u8 dtim_period;
+} __packed;
+
+struct ieee_types_assoc_rsp {
+       __le16 cap_info_bitmap;
+       __le16 status_code;
+       __le16 a_id;
+       u8 ie_buffer[1];
+} __packed;
+
+struct host_cmd_ds_802_11_associate_rsp {
+       struct ieee_types_assoc_rsp assoc_rsp;
+} __packed;
+
+struct ieee_types_cf_param_set {
+       u8 element_id;
+       u8 len;
+       u8 cfp_cnt;
+       u8 cfp_period;
+       __le16 cfp_max_duration;
+       __le16 cfp_duration_remaining;
+} __packed;
+
+struct ieee_types_ibss_param_set {
+       u8 element_id;
+       u8 len;
+       __le16 atim_window;
+} __packed;
+
+union ieee_types_ss_param_set {
+       struct ieee_types_cf_param_set cf_param_set;
+       struct ieee_types_ibss_param_set ibss_param_set;
+} __packed;
+
+struct ieee_types_fh_param_set {
+       u8 element_id;
+       u8 len;
+       __le16 dwell_time;
+       u8 hop_set;
+       u8 hop_pattern;
+       u8 hop_index;
+} __packed;
+
+struct ieee_types_ds_param_set {
+       u8 element_id;
+       u8 len;
+       u8 current_chan;
+} __packed;
+
+union ieee_types_phy_param_set {
+       struct ieee_types_fh_param_set fh_param_set;
+       struct ieee_types_ds_param_set ds_param_set;
+} __packed;
+
+struct ieee_types_oper_mode_ntf {
+       u8 element_id;
+       u8 len;
+       u8 oper_mode;
+} __packed;
+
+struct host_cmd_ds_802_11_ad_hoc_start {
+       u8 ssid[IEEE80211_MAX_SSID_LEN];
+       u8 bss_mode;
+       __le16 beacon_period;
+       u8 dtim_period;
+       union ieee_types_ss_param_set ss_param_set;
+       union ieee_types_phy_param_set phy_param_set;
+       u16 reserved1;
+       __le16 cap_info_bitmap;
+       u8 data_rate[HOSTCMD_SUPPORTED_RATES];
+} __packed;
+
+struct host_cmd_ds_802_11_ad_hoc_result {
+       u8 pad[3];
+       u8 bssid[ETH_ALEN];
+} __packed;
+
+struct adhoc_bss_desc {
+       u8 bssid[ETH_ALEN];
+       u8 ssid[IEEE80211_MAX_SSID_LEN];
+       u8 bss_mode;
+       __le16 beacon_period;
+       u8 dtim_period;
+       u8 time_stamp[8];
+       u8 local_time[8];
+       union ieee_types_phy_param_set phy_param_set;
+       union ieee_types_ss_param_set ss_param_set;
+       __le16 cap_info_bitmap;
+       u8 data_rates[HOSTCMD_SUPPORTED_RATES];
+
+       /*
+        *  DO NOT ADD ANY FIELDS TO THIS STRUCTURE.
+        *  It is used in the Adhoc join command and will cause a
+        *  binary layout mismatch with the firmware
+        */
+} __packed;
+
+struct host_cmd_ds_802_11_ad_hoc_join {
+       struct adhoc_bss_desc bss_descriptor;
+       u16 reserved1;
+       u16 reserved2;
+} __packed;
+
+struct host_cmd_ds_802_11_get_log {
+       __le32 mcast_tx_frame;
+       __le32 failed;
+       __le32 retry;
+       __le32 multi_retry;
+       __le32 frame_dup;
+       __le32 rts_success;
+       __le32 rts_failure;
+       __le32 ack_failure;
+       __le32 rx_frag;
+       __le32 mcast_rx_frame;
+       __le32 fcs_error;
+       __le32 tx_frame;
+       __le32 reserved;
+       __le32 wep_icv_err_cnt[4];
+       __le32 bcn_rcv_cnt;
+       __le32 bcn_miss_cnt;
+};
+
+/* Enumeration for rate format */
+enum _mwifiex_rate_format {
+       MWIFIEX_RATE_FORMAT_LG = 0,
+       MWIFIEX_RATE_FORMAT_HT,
+       MWIFIEX_RATE_FORMAT_VHT,
+       MWIFIEX_RATE_FORMAT_AUTO = 0xFF,
+};
+
+struct host_cmd_ds_tx_rate_query {
+       u8 tx_rate;
+       /* Tx Rate Info: For 802.11 AC cards
+        *
+        * [Bit 0-1] tx rate formate: LG = 0, HT = 1, VHT = 2
+        * [Bit 2-3] HT/VHT Bandwidth: BW20 = 0, BW40 = 1, BW80 = 2, BW160 = 3
+        * [Bit 4]   HT/VHT Guard Interval: LGI = 0, SGI = 1
+        *
+        * For non-802.11 AC cards
+        * Ht Info [Bit 0] RxRate format: LG=0, HT=1
+        * [Bit 1]  HT Bandwidth: BW20 = 0, BW40 = 1
+        * [Bit 2]  HT Guard Interval: LGI = 0, SGI = 1
+        */
+       u8 ht_info;
+} __packed;
+
+struct mwifiex_tx_pause_tlv {
+       struct mwifiex_ie_types_header header;
+       u8 peermac[ETH_ALEN];
+       u8 tx_pause;
+       u8 pkt_cnt;
+} __packed;
+
+enum Host_Sleep_Action {
+       HS_CONFIGURE = 0x0001,
+       HS_ACTIVATE  = 0x0002,
+};
+
+struct mwifiex_hs_config_param {
+       __le32 conditions;
+       u8 gpio;
+       u8 gap;
+} __packed;
+
+struct hs_activate_param {
+       __le16 resp_ctrl;
+} __packed;
+
+struct host_cmd_ds_802_11_hs_cfg_enh {
+       __le16 action;
+
+       union {
+               struct mwifiex_hs_config_param hs_config;
+               struct hs_activate_param hs_activate;
+       } params;
+} __packed;
+
+enum SNMP_MIB_INDEX {
+       OP_RATE_SET_I = 1,
+       DTIM_PERIOD_I = 3,
+       RTS_THRESH_I = 5,
+       SHORT_RETRY_LIM_I = 6,
+       LONG_RETRY_LIM_I = 7,
+       FRAG_THRESH_I = 8,
+       DOT11D_I = 9,
+       DOT11H_I = 10,
+};
+
+enum mwifiex_assocmd_failurepoint {
+       MWIFIEX_ASSOC_CMD_SUCCESS = 0,
+       MWIFIEX_ASSOC_CMD_FAILURE_ASSOC,
+       MWIFIEX_ASSOC_CMD_FAILURE_AUTH,
+       MWIFIEX_ASSOC_CMD_FAILURE_JOIN
+};
+
+#define MAX_SNMP_BUF_SIZE   128
+
+struct host_cmd_ds_802_11_snmp_mib {
+       __le16 query_type;
+       __le16 oid;
+       __le16 buf_size;
+       u8 value[1];
+} __packed;
+
+struct mwifiex_rate_scope {
+       __le16 type;
+       __le16 length;
+       __le16 hr_dsss_rate_bitmap;
+       __le16 ofdm_rate_bitmap;
+       __le16 ht_mcs_rate_bitmap[8];
+       __le16 vht_mcs_rate_bitmap[8];
+} __packed;
+
+struct mwifiex_rate_drop_pattern {
+       __le16 type;
+       __le16 length;
+       __le32 rate_drop_mode;
+} __packed;
+
+struct host_cmd_ds_tx_rate_cfg {
+       __le16 action;
+       __le16 cfg_index;
+} __packed;
+
+struct mwifiex_power_group {
+       u8 modulation_class;
+       u8 first_rate_code;
+       u8 last_rate_code;
+       s8 power_step;
+       s8 power_min;
+       s8 power_max;
+       u8 ht_bandwidth;
+       u8 reserved;
+} __packed;
+
+struct mwifiex_types_power_group {
+       __le16 type;
+       __le16 length;
+} __packed;
+
+struct host_cmd_ds_txpwr_cfg {
+       __le16 action;
+       __le16 cfg_index;
+       __le32 mode;
+} __packed;
+
+struct host_cmd_ds_rf_tx_pwr {
+       __le16 action;
+       __le16 cur_level;
+       u8 max_power;
+       u8 min_power;
+} __packed;
+
+struct host_cmd_ds_rf_ant_mimo {
+       __le16 action_tx;
+       __le16 tx_ant_mode;
+       __le16 action_rx;
+       __le16 rx_ant_mode;
+};
+
+struct host_cmd_ds_rf_ant_siso {
+       __le16 action;
+       __le16 ant_mode;
+};
+
+struct host_cmd_ds_tdls_oper {
+       __le16 tdls_action;
+       __le16 reason;
+       u8 peer_mac[ETH_ALEN];
+} __packed;
+
+struct mwifiex_tdls_config {
+       __le16 enable;
+};
+
+struct mwifiex_tdls_config_cs_params {
+       u8 unit_time;
+       u8 thr_otherlink;
+       u8 thr_directlink;
+};
+
+struct mwifiex_tdls_init_cs_params {
+       u8 peer_mac[ETH_ALEN];
+       u8 primary_chan;
+       u8 second_chan_offset;
+       u8 band;
+       __le16 switch_time;
+       __le16 switch_timeout;
+       u8 reg_class;
+       u8 periodicity;
+} __packed;
+
+struct mwifiex_tdls_stop_cs_params {
+       u8 peer_mac[ETH_ALEN];
+};
+
+struct host_cmd_ds_tdls_config {
+       __le16 tdls_action;
+       u8 tdls_data[1];
+} __packed;
+
+struct mwifiex_chan_desc {
+       __le16 start_freq;
+       u8 chan_width;
+       u8 chan_num;
+} __packed;
+
+struct host_cmd_ds_chan_rpt_req {
+       struct mwifiex_chan_desc chan_desc;
+       __le32 msec_dwell_time;
+} __packed;
+
+struct host_cmd_ds_chan_rpt_event {
+       __le32 result;
+       __le64 start_tsf;
+       __le32 duration;
+       u8 tlvbuf[0];
+} __packed;
+
+struct host_cmd_sdio_sp_rx_aggr_cfg {
+       u8 action;
+       u8 enable;
+       __le16 block_size;
+} __packed;
+
+struct mwifiex_fixed_bcn_param {
+       __le64 timestamp;
+       __le16 beacon_period;
+       __le16 cap_info_bitmap;
+} __packed;
+
+struct mwifiex_event_scan_result {
+       __le16 event_id;
+       u8 bss_index;
+       u8 bss_type;
+       u8 more_event;
+       u8 reserved[3];
+       __le16 buf_size;
+       u8 num_of_set;
+} __packed;
+
+struct tx_status_event {
+       u8 packet_type;
+       u8 tx_token_id;
+       u8 status;
+} __packed;
+
+#define MWIFIEX_USER_SCAN_CHAN_MAX             50
+
+#define MWIFIEX_MAX_SSID_LIST_LENGTH         10
+
+struct mwifiex_scan_cmd_config {
+       /*
+        *  BSS mode to be sent in the firmware command
+        */
+       u8 bss_mode;
+
+       /* Specific BSSID used to filter scan results in the firmware */
+       u8 specific_bssid[ETH_ALEN];
+
+       /* Length of TLVs sent in command starting at tlvBuffer */
+       u32 tlv_buf_len;
+
+       /*
+        *  SSID TLV(s) and ChanList TLVs to be sent in the firmware command
+        *
+        *  TLV_TYPE_CHANLIST, mwifiex_ie_types_chan_list_param_set
+        *  WLAN_EID_SSID, mwifiex_ie_types_ssid_param_set
+        */
+       u8 tlv_buf[1];  /* SSID TLV(s) and ChanList TLVs are stored
+                                  here */
+} __packed;
+
+struct mwifiex_user_scan_chan {
+       u8 chan_number;
+       u8 radio_type;
+       u8 scan_type;
+       u8 reserved;
+       u32 scan_time;
+} __packed;
+
+struct mwifiex_user_scan_cfg {
+       /*
+        *  BSS mode to be sent in the firmware command
+        */
+       u8 bss_mode;
+       /* Configure the number of probe requests for active chan scans */
+       u8 num_probes;
+       u8 reserved;
+       /* BSSID filter sent in the firmware command to limit the results */
+       u8 specific_bssid[ETH_ALEN];
+       /* SSID filter list used in the firmware to limit the scan results */
+       struct cfg80211_ssid *ssid_list;
+       u8 num_ssids;
+       /* Variable number (fixed maximum) of channels to scan up */
+       struct mwifiex_user_scan_chan chan_list[MWIFIEX_USER_SCAN_CHAN_MAX];
+       u16 scan_chan_gap;
+} __packed;
+
+struct ie_body {
+       u8 grp_key_oui[4];
+       u8 ptk_cnt[2];
+       u8 ptk_body[4];
+} __packed;
+
+struct host_cmd_ds_802_11_scan {
+       u8 bss_mode;
+       u8 bssid[ETH_ALEN];
+       u8 tlv_buffer[1];
+} __packed;
+
+struct host_cmd_ds_802_11_scan_rsp {
+       __le16 bss_descript_size;
+       u8 number_of_sets;
+       u8 bss_desc_and_tlv_buffer[1];
+} __packed;
+
+struct host_cmd_ds_802_11_scan_ext {
+       u32   reserved;
+       u8    tlv_buffer[1];
+} __packed;
+
+struct mwifiex_ie_types_bss_mode {
+       struct mwifiex_ie_types_header  header;
+       u8 bss_mode;
+} __packed;
+
+struct mwifiex_ie_types_bss_scan_rsp {
+       struct mwifiex_ie_types_header header;
+       u8 bssid[ETH_ALEN];
+       u8 frame_body[1];
+} __packed;
+
+struct mwifiex_ie_types_bss_scan_info {
+       struct mwifiex_ie_types_header header;
+       __le16 rssi;
+       __le16 anpi;
+       u8 cca_busy_fraction;
+       u8 radio_type;
+       u8 channel;
+       u8 reserved;
+       __le64 tsf;
+} __packed;
+
+struct host_cmd_ds_802_11_bg_scan_query {
+       u8 flush;
+} __packed;
+
+struct host_cmd_ds_802_11_bg_scan_query_rsp {
+       __le32 report_condition;
+       struct host_cmd_ds_802_11_scan_rsp scan_resp;
+} __packed;
+
+struct mwifiex_ietypes_domain_param_set {
+       struct mwifiex_ie_types_header header;
+       u8 country_code[IEEE80211_COUNTRY_STRING_LEN];
+       struct ieee80211_country_ie_triplet triplet[1];
+} __packed;
+
+struct host_cmd_ds_802_11d_domain_info {
+       __le16 action;
+       struct mwifiex_ietypes_domain_param_set domain;
+} __packed;
+
+struct host_cmd_ds_802_11d_domain_info_rsp {
+       __le16 action;
+       struct mwifiex_ietypes_domain_param_set domain;
+} __packed;
+
+struct host_cmd_ds_11n_addba_req {
+       u8 add_req_result;
+       u8 peer_mac_addr[ETH_ALEN];
+       u8 dialog_token;
+       __le16 block_ack_param_set;
+       __le16 block_ack_tmo;
+       __le16 ssn;
+} __packed;
+
+struct host_cmd_ds_11n_addba_rsp {
+       u8 add_rsp_result;
+       u8 peer_mac_addr[ETH_ALEN];
+       u8 dialog_token;
+       __le16 status_code;
+       __le16 block_ack_param_set;
+       __le16 block_ack_tmo;
+       __le16 ssn;
+} __packed;
+
+struct host_cmd_ds_11n_delba {
+       u8 del_result;
+       u8 peer_mac_addr[ETH_ALEN];
+       __le16 del_ba_param_set;
+       __le16 reason_code;
+       u8 reserved;
+} __packed;
+
+struct host_cmd_ds_11n_batimeout {
+       u8 tid;
+       u8 peer_mac_addr[ETH_ALEN];
+       u8 origninator;
+} __packed;
+
+struct host_cmd_ds_11n_cfg {
+       __le16 action;
+       __le16 ht_tx_cap;
+       __le16 ht_tx_info;
+       __le16 misc_config;     /* Needed for 802.11AC cards only */
+} __packed;
+
+struct host_cmd_ds_txbuf_cfg {
+       __le16 action;
+       __le16 buff_size;
+       __le16 mp_end_port;     /* SDIO only, reserved for other interfacces */
+       __le16 reserved3;
+} __packed;
+
+struct host_cmd_ds_amsdu_aggr_ctrl {
+       __le16 action;
+       __le16 enable;
+       __le16 curr_buf_size;
+} __packed;
+
+struct host_cmd_ds_sta_deauth {
+       u8 mac[ETH_ALEN];
+       __le16 reason;
+} __packed;
+
+struct mwifiex_ie_types_sta_info {
+       struct mwifiex_ie_types_header header;
+       u8 mac[ETH_ALEN];
+       u8 power_mfg_status;
+       s8 rssi;
+};
+
+struct host_cmd_ds_sta_list {
+       u16 sta_count;
+       u8 tlv[0];
+} __packed;
+
+struct mwifiex_ie_types_pwr_capability {
+       struct mwifiex_ie_types_header header;
+       s8 min_pwr;
+       s8 max_pwr;
+};
+
+struct mwifiex_ie_types_local_pwr_constraint {
+       struct mwifiex_ie_types_header header;
+       u8 chan;
+       u8 constraint;
+};
+
+struct mwifiex_ie_types_wmm_param_set {
+       struct mwifiex_ie_types_header header;
+       u8 wmm_ie[1];
+};
+
+struct mwifiex_ie_types_wmm_queue_status {
+       struct mwifiex_ie_types_header header;
+       u8 queue_index;
+       u8 disabled;
+       __le16 medium_time;
+       u8 flow_required;
+       u8 flow_created;
+       u32 reserved;
+};
+
+struct ieee_types_vendor_header {
+       u8 element_id;
+       u8 len;
+       u8 oui[4];      /* 0~2: oui, 3: oui_type */
+       u8 oui_subtype;
+       u8 version;
+} __packed;
+
+struct ieee_types_wmm_parameter {
+       /*
+        * WMM Parameter IE - Vendor Specific Header:
+        *   element_id  [221/0xdd]
+        *   Len         [24]
+        *   Oui         [00:50:f2]
+        *   OuiType     [2]
+        *   OuiSubType  [1]
+        *   Version     [1]
+        */
+       struct ieee_types_vendor_header vend_hdr;
+       u8 qos_info_bitmap;
+       u8 reserved;
+       struct ieee_types_wmm_ac_parameters ac_params[IEEE80211_NUM_ACS];
+} __packed;
+
+struct ieee_types_wmm_info {
+
+       /*
+        * WMM Info IE - Vendor Specific Header:
+        *   element_id  [221/0xdd]
+        *   Len         [7]
+        *   Oui         [00:50:f2]
+        *   OuiType     [2]
+        *   OuiSubType  [0]
+        *   Version     [1]
+        */
+       struct ieee_types_vendor_header vend_hdr;
+
+       u8 qos_info_bitmap;
+} __packed;
+
+struct host_cmd_ds_wmm_get_status {
+       u8 queue_status_tlv[sizeof(struct mwifiex_ie_types_wmm_queue_status) *
+                             IEEE80211_NUM_ACS];
+       u8 wmm_param_tlv[sizeof(struct ieee_types_wmm_parameter) + 2];
+} __packed;
+
+struct mwifiex_wmm_ac_status {
+       u8 disabled;
+       u8 flow_required;
+       u8 flow_created;
+};
+
+struct mwifiex_ie_types_htcap {
+       struct mwifiex_ie_types_header header;
+       struct ieee80211_ht_cap ht_cap;
+} __packed;
+
+struct mwifiex_ie_types_vhtcap {
+       struct mwifiex_ie_types_header header;
+       struct ieee80211_vht_cap vht_cap;
+} __packed;
+
+struct mwifiex_ie_types_aid {
+       struct mwifiex_ie_types_header header;
+       __le16 aid;
+} __packed;
+
+struct mwifiex_ie_types_oper_mode_ntf {
+       struct mwifiex_ie_types_header header;
+       u8 oper_mode;
+} __packed;
+
+/* VHT Operations IE */
+struct mwifiex_ie_types_vht_oper {
+       struct mwifiex_ie_types_header header;
+       u8 chan_width;
+       u8 chan_center_freq_1;
+       u8 chan_center_freq_2;
+       /* Basic MCS set map, each 2 bits stands for a NSS */
+       __le16 basic_mcs_map;
+} __packed;
+
+struct mwifiex_ie_types_wmmcap {
+       struct mwifiex_ie_types_header header;
+       struct mwifiex_types_wmm_info wmm_info;
+} __packed;
+
+struct mwifiex_ie_types_htinfo {
+       struct mwifiex_ie_types_header header;
+       struct ieee80211_ht_operation ht_oper;
+} __packed;
+
+struct mwifiex_ie_types_2040bssco {
+       struct mwifiex_ie_types_header header;
+       u8 bss_co_2040;
+} __packed;
+
+struct mwifiex_ie_types_extcap {
+       struct mwifiex_ie_types_header header;
+       u8 ext_capab[0];
+} __packed;
+
+struct host_cmd_ds_mem_access {
+       __le16 action;
+       __le16 reserved;
+       __le32 addr;
+       __le32 value;
+};
+
+struct mwifiex_ie_types_qos_info {
+       struct mwifiex_ie_types_header header;
+       u8 qos_info;
+} __packed;
+
+struct host_cmd_ds_mac_reg_access {
+       __le16 action;
+       __le16 offset;
+       __le32 value;
+} __packed;
+
+struct host_cmd_ds_bbp_reg_access {
+       __le16 action;
+       __le16 offset;
+       u8 value;
+       u8 reserved[3];
+} __packed;
+
+struct host_cmd_ds_rf_reg_access {
+       __le16 action;
+       __le16 offset;
+       u8 value;
+       u8 reserved[3];
+} __packed;
+
+struct host_cmd_ds_pmic_reg_access {
+       __le16 action;
+       __le16 offset;
+       u8 value;
+       u8 reserved[3];
+} __packed;
+
+struct host_cmd_ds_802_11_eeprom_access {
+       __le16 action;
+
+       __le16 offset;
+       __le16 byte_count;
+       u8 value;
+} __packed;
+
+struct mwifiex_assoc_event {
+       u8 sta_addr[ETH_ALEN];
+       __le16 type;
+       __le16 len;
+       __le16 frame_control;
+       __le16 cap_info;
+       __le16 listen_interval;
+       u8 data[0];
+} __packed;
+
+struct host_cmd_ds_sys_config {
+       __le16 action;
+       u8 tlv[0];
+};
+
+struct host_cmd_11ac_vht_cfg {
+       __le16 action;
+       u8 band_config;
+       u8 misc_config;
+       __le32 cap_info;
+       __le32 mcs_tx_set;
+       __le32 mcs_rx_set;
+} __packed;
+
+struct host_cmd_tlv_akmp {
+       struct mwifiex_ie_types_header header;
+       __le16 key_mgmt;
+       __le16 key_mgmt_operation;
+} __packed;
+
+struct host_cmd_tlv_pwk_cipher {
+       struct mwifiex_ie_types_header header;
+       __le16 proto;
+       u8 cipher;
+       u8 reserved;
+} __packed;
+
+struct host_cmd_tlv_gwk_cipher {
+       struct mwifiex_ie_types_header header;
+       u8 cipher;
+       u8 reserved;
+} __packed;
+
+struct host_cmd_tlv_passphrase {
+       struct mwifiex_ie_types_header header;
+       u8 passphrase[0];
+} __packed;
+
+struct host_cmd_tlv_wep_key {
+       struct mwifiex_ie_types_header header;
+       u8 key_index;
+       u8 is_default;
+       u8 key[1];
+};
+
+struct host_cmd_tlv_auth_type {
+       struct mwifiex_ie_types_header header;
+       u8 auth_type;
+} __packed;
+
+struct host_cmd_tlv_encrypt_protocol {
+       struct mwifiex_ie_types_header header;
+       __le16 proto;
+} __packed;
+
+struct host_cmd_tlv_ssid {
+       struct mwifiex_ie_types_header header;
+       u8 ssid[0];
+} __packed;
+
+struct host_cmd_tlv_rates {
+       struct mwifiex_ie_types_header header;
+       u8 rates[0];
+} __packed;
+
+struct mwifiex_ie_types_bssid_list {
+       struct mwifiex_ie_types_header header;
+       u8 bssid[ETH_ALEN];
+} __packed;
+
+struct host_cmd_tlv_bcast_ssid {
+       struct mwifiex_ie_types_header header;
+       u8 bcast_ctl;
+} __packed;
+
+struct host_cmd_tlv_beacon_period {
+       struct mwifiex_ie_types_header header;
+       __le16 period;
+} __packed;
+
+struct host_cmd_tlv_dtim_period {
+       struct mwifiex_ie_types_header header;
+       u8 period;
+} __packed;
+
+struct host_cmd_tlv_frag_threshold {
+       struct mwifiex_ie_types_header header;
+       __le16 frag_thr;
+} __packed;
+
+struct host_cmd_tlv_rts_threshold {
+       struct mwifiex_ie_types_header header;
+       __le16 rts_thr;
+} __packed;
+
+struct host_cmd_tlv_retry_limit {
+       struct mwifiex_ie_types_header header;
+       u8 limit;
+} __packed;
+
+struct host_cmd_tlv_mac_addr {
+       struct mwifiex_ie_types_header header;
+       u8 mac_addr[ETH_ALEN];
+} __packed;
+
+struct host_cmd_tlv_channel_band {
+       struct mwifiex_ie_types_header header;
+       u8 band_config;
+       u8 channel;
+} __packed;
+
+struct host_cmd_tlv_ageout_timer {
+       struct mwifiex_ie_types_header header;
+       __le32 sta_ao_timer;
+} __packed;
+
+struct host_cmd_tlv_power_constraint {
+       struct mwifiex_ie_types_header header;
+       u8 constraint;
+} __packed;
+
+struct mwifiex_ie_types_btcoex_scan_time {
+       struct mwifiex_ie_types_header header;
+       u8 coex_scan;
+       u8 reserved;
+       u16 min_scan_time;
+       u16 max_scan_time;
+} __packed;
+
+struct mwifiex_ie_types_btcoex_aggr_win_size {
+       struct mwifiex_ie_types_header header;
+       u8 coex_win_size;
+       u8 tx_win_size;
+       u8 rx_win_size;
+       u8 reserved;
+} __packed;
+
+struct mwifiex_ie_types_robust_coex {
+       struct mwifiex_ie_types_header header;
+       __le32 mode;
+} __packed;
+
+struct host_cmd_ds_version_ext {
+       u8 version_str_sel;
+       char version_str[128];
+} __packed;
+
+struct host_cmd_ds_mgmt_frame_reg {
+       __le16 action;
+       __le32 mask;
+} __packed;
+
+struct host_cmd_ds_p2p_mode_cfg {
+       __le16 action;
+       __le16 mode;
+} __packed;
+
+struct host_cmd_ds_remain_on_chan {
+       __le16 action;
+       u8 status;
+       u8 reserved;
+       u8 band_cfg;
+       u8 channel;
+       __le32 duration;
+} __packed;
+
+struct host_cmd_ds_802_11_ibss_status {
+       __le16 action;
+       __le16 enable;
+       u8 bssid[ETH_ALEN];
+       __le16 beacon_interval;
+       __le16 atim_window;
+       __le16 use_g_rate_protect;
+} __packed;
+
+struct mwifiex_fw_mef_entry {
+       u8 mode;
+       u8 action;
+       __le16 exprsize;
+       u8 expr[0];
+} __packed;
+
+struct host_cmd_ds_mef_cfg {
+       __le32 criteria;
+       __le16 num_entries;
+       struct mwifiex_fw_mef_entry mef_entry[0];
+} __packed;
+
+#define CONNECTION_TYPE_INFRA   0
+#define CONNECTION_TYPE_ADHOC   1
+#define CONNECTION_TYPE_AP      2
+
+struct host_cmd_ds_set_bss_mode {
+       u8 con_type;
+} __packed;
+
+struct host_cmd_ds_pcie_details {
+       /* TX buffer descriptor ring address */
+       u32 txbd_addr_lo;
+       u32 txbd_addr_hi;
+       /* TX buffer descriptor ring count */
+       u32 txbd_count;
+
+       /* RX buffer descriptor ring address */
+       u32 rxbd_addr_lo;
+       u32 rxbd_addr_hi;
+       /* RX buffer descriptor ring count */
+       u32 rxbd_count;
+
+       /* Event buffer descriptor ring address */
+       u32 evtbd_addr_lo;
+       u32 evtbd_addr_hi;
+       /* Event buffer descriptor ring count */
+       u32 evtbd_count;
+
+       /* Sleep cookie buffer physical address */
+       u32 sleep_cookie_addr_lo;
+       u32 sleep_cookie_addr_hi;
+} __packed;
+
+struct mwifiex_ie_types_rssi_threshold {
+       struct mwifiex_ie_types_header header;
+       u8 abs_value;
+       u8 evt_freq;
+} __packed;
+
+#define MWIFIEX_DFS_REC_HDR_LEN                8
+#define MWIFIEX_DFS_REC_HDR_NUM                10
+#define MWIFIEX_BIN_COUNTER_LEN                7
+
+struct mwifiex_radar_det_event {
+       __le32 detect_count;
+       u8 reg_domain;  /*1=fcc, 2=etsi, 3=mic*/
+       u8 det_type;  /*0=none, 1=pw(chirp), 2=pri(radar)*/
+       __le16 pw_chirp_type;
+       u8 pw_chirp_idx;
+       u8 pw_value;
+       u8 pri_radar_type;
+       u8 pri_bincnt;
+       u8 bin_counter[MWIFIEX_BIN_COUNTER_LEN];
+       u8 num_dfs_records;
+       u8 dfs_record_hdr[MWIFIEX_DFS_REC_HDR_NUM][MWIFIEX_DFS_REC_HDR_LEN];
+       __le32 passed;
+} __packed;
+
+struct mwifiex_ie_types_multi_chan_info {
+       struct mwifiex_ie_types_header header;
+       __le16 status;
+       u8 tlv_buffer[0];
+} __packed;
+
+struct mwifiex_ie_types_mc_group_info {
+       struct mwifiex_ie_types_header header;
+       u8 chan_group_id;
+       u8 chan_buf_weight;
+       u8 band_config;
+       u8 chan_num;
+       u32 chan_time;
+       u32 reserved;
+       union {
+               u8 sdio_func_num;
+               u8 usb_ep_num;
+       } hid_num;
+       u8 intf_num;
+       u8 bss_type_numlist[0];
+} __packed;
+
+struct meas_rpt_map {
+       u8 rssi:3;
+       u8 unmeasured:1;
+       u8 radar:1;
+       u8 unidentified_sig:1;
+       u8 ofdm_preamble:1;
+       u8 bss:1;
+} __packed;
+
+struct mwifiex_ie_types_chan_rpt_data {
+       struct mwifiex_ie_types_header header;
+       struct meas_rpt_map map;
+} __packed;
+
+struct host_cmd_ds_802_11_subsc_evt {
+       __le16 action;
+       __le16 events;
+} __packed;
+
+struct chan_switch_result {
+       u8 cur_chan;
+       u8 status;
+       u8 reason;
+} __packed;
+
+struct mwifiex_tdls_generic_event {
+       __le16 type;
+       u8 peer_mac[ETH_ALEN];
+       union {
+               struct chan_switch_result switch_result;
+               u8 cs_stop_reason;
+               __le16 reason_code;
+               __le16 reserved;
+       } u;
+} __packed;
+
+struct mwifiex_ie {
+       __le16 ie_index;
+       __le16 mgmt_subtype_mask;
+       __le16 ie_length;
+       u8 ie_buffer[IEEE_MAX_IE_SIZE];
+} __packed;
+
+#define MAX_MGMT_IE_INDEX      16
+struct mwifiex_ie_list {
+       __le16 type;
+       __le16 len;
+       struct mwifiex_ie ie_list[MAX_MGMT_IE_INDEX];
+} __packed;
+
+struct coalesce_filt_field_param {
+       u8 operation;
+       u8 operand_len;
+       __le16 offset;
+       u8 operand_byte_stream[4];
+};
+
+struct coalesce_receive_filt_rule {
+       struct mwifiex_ie_types_header header;
+       u8 num_of_fields;
+       u8 pkt_type;
+       __le16 max_coalescing_delay;
+       struct coalesce_filt_field_param params[0];
+} __packed;
+
+struct host_cmd_ds_coalesce_cfg {
+       __le16 action;
+       __le16 num_of_rules;
+       struct coalesce_receive_filt_rule rule[0];
+} __packed;
+
+struct host_cmd_ds_multi_chan_policy {
+       __le16 action;
+       __le16 policy;
+} __packed;
+
+struct host_cmd_ds_robust_coex {
+       __le16 action;
+       __le16 reserved;
+} __packed;
+
+struct host_cmd_ds_command {
+       __le16 command;
+       __le16 size;
+       __le16 seq_num;
+       __le16 result;
+       union {
+               struct host_cmd_ds_get_hw_spec hw_spec;
+               struct host_cmd_ds_mac_control mac_ctrl;
+               struct host_cmd_ds_802_11_mac_address mac_addr;
+               struct host_cmd_ds_mac_multicast_adr mc_addr;
+               struct host_cmd_ds_802_11_get_log get_log;
+               struct host_cmd_ds_802_11_rssi_info rssi_info;
+               struct host_cmd_ds_802_11_rssi_info_rsp rssi_info_rsp;
+               struct host_cmd_ds_802_11_snmp_mib smib;
+               struct host_cmd_ds_tx_rate_query tx_rate;
+               struct host_cmd_ds_tx_rate_cfg tx_rate_cfg;
+               struct host_cmd_ds_txpwr_cfg txp_cfg;
+               struct host_cmd_ds_rf_tx_pwr txp;
+               struct host_cmd_ds_rf_ant_mimo ant_mimo;
+               struct host_cmd_ds_rf_ant_siso ant_siso;
+               struct host_cmd_ds_802_11_ps_mode_enh psmode_enh;
+               struct host_cmd_ds_802_11_hs_cfg_enh opt_hs_cfg;
+               struct host_cmd_ds_802_11_scan scan;
+               struct host_cmd_ds_802_11_scan_ext ext_scan;
+               struct host_cmd_ds_802_11_scan_rsp scan_resp;
+               struct host_cmd_ds_802_11_bg_scan_query bg_scan_query;
+               struct host_cmd_ds_802_11_bg_scan_query_rsp bg_scan_query_resp;
+               struct host_cmd_ds_802_11_associate associate;
+               struct host_cmd_ds_802_11_associate_rsp associate_rsp;
+               struct host_cmd_ds_802_11_deauthenticate deauth;
+               struct host_cmd_ds_802_11_ad_hoc_start adhoc_start;
+               struct host_cmd_ds_802_11_ad_hoc_result adhoc_result;
+               struct host_cmd_ds_802_11_ad_hoc_join adhoc_join;
+               struct host_cmd_ds_802_11d_domain_info domain_info;
+               struct host_cmd_ds_802_11d_domain_info_rsp domain_info_resp;
+               struct host_cmd_ds_11n_addba_req add_ba_req;
+               struct host_cmd_ds_11n_addba_rsp add_ba_rsp;
+               struct host_cmd_ds_11n_delba del_ba;
+               struct host_cmd_ds_txbuf_cfg tx_buf;
+               struct host_cmd_ds_amsdu_aggr_ctrl amsdu_aggr_ctrl;
+               struct host_cmd_ds_11n_cfg htcfg;
+               struct host_cmd_ds_wmm_get_status get_wmm_status;
+               struct host_cmd_ds_802_11_key_material key_material;
+               struct host_cmd_ds_802_11_key_material_v2 key_material_v2;
+               struct host_cmd_ds_version_ext verext;
+               struct host_cmd_ds_mgmt_frame_reg reg_mask;
+               struct host_cmd_ds_remain_on_chan roc_cfg;
+               struct host_cmd_ds_p2p_mode_cfg mode_cfg;
+               struct host_cmd_ds_802_11_ibss_status ibss_coalescing;
+               struct host_cmd_ds_mef_cfg mef_cfg;
+               struct host_cmd_ds_mem_access mem;
+               struct host_cmd_ds_mac_reg_access mac_reg;
+               struct host_cmd_ds_bbp_reg_access bbp_reg;
+               struct host_cmd_ds_rf_reg_access rf_reg;
+               struct host_cmd_ds_pmic_reg_access pmic_reg;
+               struct host_cmd_ds_set_bss_mode bss_mode;
+               struct host_cmd_ds_pcie_details pcie_host_spec;
+               struct host_cmd_ds_802_11_eeprom_access eeprom;
+               struct host_cmd_ds_802_11_subsc_evt subsc_evt;
+               struct host_cmd_ds_sys_config uap_sys_config;
+               struct host_cmd_ds_sta_deauth sta_deauth;
+               struct host_cmd_ds_sta_list sta_list;
+               struct host_cmd_11ac_vht_cfg vht_cfg;
+               struct host_cmd_ds_coalesce_cfg coalesce_cfg;
+               struct host_cmd_ds_tdls_config tdls_config;
+               struct host_cmd_ds_tdls_oper tdls_oper;
+               struct host_cmd_ds_chan_rpt_req chan_rpt_req;
+               struct host_cmd_sdio_sp_rx_aggr_cfg sdio_rx_aggr_cfg;
+               struct host_cmd_ds_multi_chan_policy mc_policy;
+               struct host_cmd_ds_robust_coex coex;
+       } params;
+} __packed;
+
+struct mwifiex_opt_sleep_confirm {
+       __le16 command;
+       __le16 size;
+       __le16 seq_num;
+       __le16 result;
+       __le16 action;
+       __le16 resp_ctrl;
+} __packed;
+#endif /* !_MWIFIEX_FW_H_ */
diff --git a/drivers/net/wireless/marvell/mwifiex/ie.c b/drivers/net/wireless/marvell/mwifiex/ie.c
new file mode 100644 (file)
index 0000000..abf52d2
--- /dev/null
@@ -0,0 +1,488 @@
+/*
+ * Marvell Wireless LAN device driver: management IE handling- setting and
+ * deleting IE.
+ *
+ * Copyright (C) 2012-2014, Marvell International Ltd.
+ *
+ * This software file (the "File") is distributed by Marvell International
+ * Ltd. under the terms of the GNU General Public License Version 2, June 1991
+ * (the "License").  You may use, redistribute and/or modify this File in
+ * accordance with the terms and conditions of the License, a copy of which
+ * is available by writing to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the
+ * worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
+ *
+ * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
+ * ARE EXPRESSLY DISCLAIMED.  The License provides additional details about
+ * this warranty disclaimer.
+ */
+
+#include "main.h"
+
+/* This function checks if current IE index is used by any on other interface.
+ * Return: -1: yes, current IE index is used by someone else.
+ *          0: no, current IE index is NOT used by other interface.
+ */
+static int
+mwifiex_ie_index_used_by_other_intf(struct mwifiex_private *priv, u16 idx)
+{
+       int i;
+       struct mwifiex_adapter *adapter = priv->adapter;
+       struct mwifiex_ie *ie;
+
+       for (i = 0; i < adapter->priv_num; i++) {
+               if (adapter->priv[i] != priv) {
+                       ie = &adapter->priv[i]->mgmt_ie[idx];
+                       if (ie->mgmt_subtype_mask && ie->ie_length)
+                               return -1;
+               }
+       }
+
+       return 0;
+}
+
+/* Get unused IE index. This index will be used for setting new IE */
+static int
+mwifiex_ie_get_autoidx(struct mwifiex_private *priv, u16 subtype_mask,
+                      struct mwifiex_ie *ie, u16 *index)
+{
+       u16 mask, len, i;
+
+       for (i = 0; i < priv->adapter->max_mgmt_ie_index; i++) {
+               mask = le16_to_cpu(priv->mgmt_ie[i].mgmt_subtype_mask);
+               len = le16_to_cpu(ie->ie_length);
+
+               if (mask == MWIFIEX_AUTO_IDX_MASK)
+                       continue;
+
+               if (mask == subtype_mask) {
+                       if (len > IEEE_MAX_IE_SIZE)
+                               continue;
+
+                       *index = i;
+                       return 0;
+               }
+
+               if (!priv->mgmt_ie[i].ie_length) {
+                       if (mwifiex_ie_index_used_by_other_intf(priv, i))
+                               continue;
+
+                       *index = i;
+                       return 0;
+               }
+       }
+
+       return -1;
+}
+
+/* This function prepares IE data buffer for command to be sent to FW */
+static int
+mwifiex_update_autoindex_ies(struct mwifiex_private *priv,
+                            struct mwifiex_ie_list *ie_list)
+{
+       u16 travel_len, index, mask;
+       s16 input_len, tlv_len;
+       struct mwifiex_ie *ie;
+       u8 *tmp;
+
+       input_len = le16_to_cpu(ie_list->len);
+       travel_len = sizeof(struct mwifiex_ie_types_header);
+
+       ie_list->len = 0;
+
+       while (input_len >= sizeof(struct mwifiex_ie_types_header)) {
+               ie = (struct mwifiex_ie *)(((u8 *)ie_list) + travel_len);
+               tlv_len = le16_to_cpu(ie->ie_length);
+               travel_len += tlv_len + MWIFIEX_IE_HDR_SIZE;
+
+               if (input_len < tlv_len + MWIFIEX_IE_HDR_SIZE)
+                       return -1;
+               index = le16_to_cpu(ie->ie_index);
+               mask = le16_to_cpu(ie->mgmt_subtype_mask);
+
+               if (index == MWIFIEX_AUTO_IDX_MASK) {
+                       /* automatic addition */
+                       if (mwifiex_ie_get_autoidx(priv, mask, ie, &index))
+                               return -1;
+                       if (index == MWIFIEX_AUTO_IDX_MASK)
+                               return -1;
+
+                       tmp = (u8 *)&priv->mgmt_ie[index].ie_buffer;
+                       memcpy(tmp, &ie->ie_buffer, le16_to_cpu(ie->ie_length));
+                       priv->mgmt_ie[index].ie_length = ie->ie_length;
+                       priv->mgmt_ie[index].ie_index = cpu_to_le16(index);
+                       priv->mgmt_ie[index].mgmt_subtype_mask =
+                                                       cpu_to_le16(mask);
+
+                       ie->ie_index = cpu_to_le16(index);
+               } else {
+                       if (mask != MWIFIEX_DELETE_MASK)
+                               return -1;
+                       /*
+                        * Check if this index is being used on any
+                        * other interface.
+                        */
+                       if (mwifiex_ie_index_used_by_other_intf(priv, index))
+                               return -1;
+
+                       ie->ie_length = 0;
+                       memcpy(&priv->mgmt_ie[index], ie,
+                              sizeof(struct mwifiex_ie));
+               }
+
+               le16_add_cpu(&ie_list->len,
+                            le16_to_cpu(priv->mgmt_ie[index].ie_length) +
+                            MWIFIEX_IE_HDR_SIZE);
+               input_len -= tlv_len + MWIFIEX_IE_HDR_SIZE;
+       }
+
+       if (GET_BSS_ROLE(priv) == MWIFIEX_BSS_ROLE_UAP)
+               return mwifiex_send_cmd(priv, HostCmd_CMD_UAP_SYS_CONFIG,
+                                       HostCmd_ACT_GEN_SET,
+                                       UAP_CUSTOM_IE_I, ie_list, false);
+
+       return 0;
+}
+
+/* Copy individual custom IEs for beacon, probe response and assoc response
+ * and prepare single structure for IE setting.
+ * This function also updates allocated IE indices from driver.
+ */
+static int
+mwifiex_update_uap_custom_ie(struct mwifiex_private *priv,
+                            struct mwifiex_ie *beacon_ie, u16 *beacon_idx,
+                            struct mwifiex_ie *pr_ie, u16 *probe_idx,
+                            struct mwifiex_ie *ar_ie, u16 *assoc_idx)
+{
+       struct mwifiex_ie_list *ap_custom_ie;
+       u8 *pos;
+       u16 len;
+       int ret;
+
+       ap_custom_ie = kzalloc(sizeof(*ap_custom_ie), GFP_KERNEL);
+       if (!ap_custom_ie)
+               return -ENOMEM;
+
+       ap_custom_ie->type = cpu_to_le16(TLV_TYPE_MGMT_IE);
+       pos = (u8 *)ap_custom_ie->ie_list;
+
+       if (beacon_ie) {
+               len = sizeof(struct mwifiex_ie) - IEEE_MAX_IE_SIZE +
+                     le16_to_cpu(beacon_ie->ie_length);
+               memcpy(pos, beacon_ie, len);
+               pos += len;
+               le16_add_cpu(&ap_custom_ie->len, len);
+       }
+       if (pr_ie) {
+               len = sizeof(struct mwifiex_ie) - IEEE_MAX_IE_SIZE +
+                     le16_to_cpu(pr_ie->ie_length);
+               memcpy(pos, pr_ie, len);
+               pos += len;
+               le16_add_cpu(&ap_custom_ie->len, len);
+       }
+       if (ar_ie) {
+               len = sizeof(struct mwifiex_ie) - IEEE_MAX_IE_SIZE +
+                     le16_to_cpu(ar_ie->ie_length);
+               memcpy(pos, ar_ie, len);
+               pos += len;
+               le16_add_cpu(&ap_custom_ie->len, len);
+       }
+
+       ret = mwifiex_update_autoindex_ies(priv, ap_custom_ie);
+
+       pos = (u8 *)(&ap_custom_ie->ie_list[0].ie_index);
+       if (beacon_ie && *beacon_idx == MWIFIEX_AUTO_IDX_MASK) {
+               /* save beacon ie index after auto-indexing */
+               *beacon_idx = le16_to_cpu(ap_custom_ie->ie_list[0].ie_index);
+               len = sizeof(*beacon_ie) - IEEE_MAX_IE_SIZE +
+                     le16_to_cpu(beacon_ie->ie_length);
+               pos += len;
+       }
+       if (pr_ie && le16_to_cpu(pr_ie->ie_index) == MWIFIEX_AUTO_IDX_MASK) {
+               /* save probe resp ie index after auto-indexing */
+               *probe_idx = *((u16 *)pos);
+               len = sizeof(*pr_ie) - IEEE_MAX_IE_SIZE +
+                     le16_to_cpu(pr_ie->ie_length);
+               pos += len;
+       }
+       if (ar_ie && le16_to_cpu(ar_ie->ie_index) == MWIFIEX_AUTO_IDX_MASK)
+               /* save assoc resp ie index after auto-indexing */
+               *assoc_idx = *((u16 *)pos);
+
+       kfree(ap_custom_ie);
+       return ret;
+}
+
+/* This function checks if the vendor specified IE is present in passed buffer
+ * and copies it to mwifiex_ie structure.
+ * Function takes pointer to struct mwifiex_ie pointer as argument.
+ * If the vendor specified IE is present then memory is allocated for
+ * mwifiex_ie pointer and filled in with IE. Caller should take care of freeing
+ * this memory.
+ */
+static int mwifiex_update_vs_ie(const u8 *ies, int ies_len,
+                               struct mwifiex_ie **ie_ptr, u16 mask,
+                               unsigned int oui, u8 oui_type)
+{
+       struct ieee_types_header *vs_ie;
+       struct mwifiex_ie *ie = *ie_ptr;
+       const u8 *vendor_ie;
+
+       vendor_ie = cfg80211_find_vendor_ie(oui, oui_type, ies, ies_len);
+       if (vendor_ie) {
+               if (!*ie_ptr) {
+                       *ie_ptr = kzalloc(sizeof(struct mwifiex_ie),
+                                         GFP_KERNEL);
+                       if (!*ie_ptr)
+                               return -ENOMEM;
+                       ie = *ie_ptr;
+               }
+
+               vs_ie = (struct ieee_types_header *)vendor_ie;
+               memcpy(ie->ie_buffer + le16_to_cpu(ie->ie_length),
+                      vs_ie, vs_ie->len + 2);
+               le16_add_cpu(&ie->ie_length, vs_ie->len + 2);
+               ie->mgmt_subtype_mask = cpu_to_le16(mask);
+               ie->ie_index = cpu_to_le16(MWIFIEX_AUTO_IDX_MASK);
+       }
+
+       *ie_ptr = ie;
+       return 0;
+}
+
+/* This function parses beacon IEs, probe response IEs, association response IEs
+ * from cfg80211_ap_settings->beacon and sets these IE to FW.
+ */
+static int mwifiex_set_mgmt_beacon_data_ies(struct mwifiex_private *priv,
+                                           struct cfg80211_beacon_data *data)
+{
+       struct mwifiex_ie *beacon_ie = NULL, *pr_ie = NULL, *ar_ie = NULL;
+       u16 beacon_idx = MWIFIEX_AUTO_IDX_MASK, pr_idx = MWIFIEX_AUTO_IDX_MASK;
+       u16 ar_idx = MWIFIEX_AUTO_IDX_MASK;
+       int ret = 0;
+
+       if (data->beacon_ies && data->beacon_ies_len) {
+               mwifiex_update_vs_ie(data->beacon_ies, data->beacon_ies_len,
+                                    &beacon_ie, MGMT_MASK_BEACON,
+                                    WLAN_OUI_MICROSOFT,
+                                    WLAN_OUI_TYPE_MICROSOFT_WPS);
+               mwifiex_update_vs_ie(data->beacon_ies, data->beacon_ies_len,
+                                    &beacon_ie, MGMT_MASK_BEACON,
+                                    WLAN_OUI_WFA, WLAN_OUI_TYPE_WFA_P2P);
+       }
+
+       if (data->proberesp_ies && data->proberesp_ies_len) {
+               mwifiex_update_vs_ie(data->proberesp_ies,
+                                    data->proberesp_ies_len, &pr_ie,
+                                    MGMT_MASK_PROBE_RESP, WLAN_OUI_MICROSOFT,
+                                    WLAN_OUI_TYPE_MICROSOFT_WPS);
+               mwifiex_update_vs_ie(data->proberesp_ies,
+                                    data->proberesp_ies_len, &pr_ie,
+                                    MGMT_MASK_PROBE_RESP,
+                                    WLAN_OUI_WFA, WLAN_OUI_TYPE_WFA_P2P);
+       }
+
+       if (data->assocresp_ies && data->assocresp_ies_len) {
+               mwifiex_update_vs_ie(data->assocresp_ies,
+                                    data->assocresp_ies_len, &ar_ie,
+                                    MGMT_MASK_ASSOC_RESP |
+                                    MGMT_MASK_REASSOC_RESP,
+                                    WLAN_OUI_MICROSOFT,
+                                    WLAN_OUI_TYPE_MICROSOFT_WPS);
+               mwifiex_update_vs_ie(data->assocresp_ies,
+                                    data->assocresp_ies_len, &ar_ie,
+                                    MGMT_MASK_ASSOC_RESP |
+                                    MGMT_MASK_REASSOC_RESP, WLAN_OUI_WFA,
+                                    WLAN_OUI_TYPE_WFA_P2P);
+       }
+
+       if (beacon_ie || pr_ie || ar_ie) {
+               ret = mwifiex_update_uap_custom_ie(priv, beacon_ie,
+                                                  &beacon_idx, pr_ie,
+                                                  &pr_idx, ar_ie, &ar_idx);
+               if (ret)
+                       goto done;
+       }
+
+       priv->beacon_idx = beacon_idx;
+       priv->proberesp_idx = pr_idx;
+       priv->assocresp_idx = ar_idx;
+
+done:
+       kfree(beacon_ie);
+       kfree(pr_ie);
+       kfree(ar_ie);
+
+       return ret;
+}
+
+/* This function parses  head and tail IEs, from cfg80211_beacon_data and sets
+ * these IE to FW.
+ */
+static int mwifiex_uap_parse_tail_ies(struct mwifiex_private *priv,
+                                     struct cfg80211_beacon_data *info)
+{
+       struct mwifiex_ie *gen_ie;
+       struct ieee_types_header *hdr;
+       struct ieee80211_vendor_ie *vendorhdr;
+       u16 gen_idx = MWIFIEX_AUTO_IDX_MASK, ie_len = 0;
+       int left_len, parsed_len = 0;
+
+       if (!info->tail || !info->tail_len)
+               return 0;
+
+       gen_ie = kzalloc(sizeof(*gen_ie), GFP_KERNEL);
+       if (!gen_ie)
+               return -ENOMEM;
+
+       left_len = info->tail_len;
+
+       /* Many IEs are generated in FW by parsing bss configuration.
+        * Let's not add them here; else we may end up duplicating these IEs
+        */
+       while (left_len > sizeof(struct ieee_types_header)) {
+               hdr = (void *)(info->tail + parsed_len);
+               switch (hdr->element_id) {
+               case WLAN_EID_SSID:
+               case WLAN_EID_SUPP_RATES:
+               case WLAN_EID_COUNTRY:
+               case WLAN_EID_PWR_CONSTRAINT:
+               case WLAN_EID_EXT_SUPP_RATES:
+               case WLAN_EID_HT_CAPABILITY:
+               case WLAN_EID_HT_OPERATION:
+               case WLAN_EID_VHT_CAPABILITY:
+               case WLAN_EID_VHT_OPERATION:
+               case WLAN_EID_VENDOR_SPECIFIC:
+                       break;
+               default:
+                       memcpy(gen_ie->ie_buffer + ie_len, hdr,
+                              hdr->len + sizeof(struct ieee_types_header));
+                       ie_len += hdr->len + sizeof(struct ieee_types_header);
+                       break;
+               }
+               left_len -= hdr->len + sizeof(struct ieee_types_header);
+               parsed_len += hdr->len + sizeof(struct ieee_types_header);
+       }
+
+       /* parse only WPA vendor IE from tail, WMM IE is configured by
+        * bss_config command
+        */
+       vendorhdr = (void *)cfg80211_find_vendor_ie(WLAN_OUI_MICROSOFT,
+                                                   WLAN_OUI_TYPE_MICROSOFT_WPA,
+                                                   info->tail, info->tail_len);
+       if (vendorhdr) {
+               memcpy(gen_ie->ie_buffer + ie_len, vendorhdr,
+                      vendorhdr->len + sizeof(struct ieee_types_header));
+               ie_len += vendorhdr->len + sizeof(struct ieee_types_header);
+       }
+
+       if (!ie_len) {
+               kfree(gen_ie);
+               return 0;
+       }
+
+       gen_ie->ie_index = cpu_to_le16(gen_idx);
+       gen_ie->mgmt_subtype_mask = cpu_to_le16(MGMT_MASK_BEACON |
+                                               MGMT_MASK_PROBE_RESP |
+                                               MGMT_MASK_ASSOC_RESP);
+       gen_ie->ie_length = cpu_to_le16(ie_len);
+
+       if (mwifiex_update_uap_custom_ie(priv, gen_ie, &gen_idx, NULL, NULL,
+                                        NULL, NULL)) {
+               kfree(gen_ie);
+               return -1;
+       }
+
+       priv->gen_idx = gen_idx;
+       kfree(gen_ie);
+       return 0;
+}
+
+/* This function parses different IEs-head & tail IEs, beacon IEs,
+ * probe response IEs, association response IEs from cfg80211_ap_settings
+ * function and sets these IE to FW.
+ */
+int mwifiex_set_mgmt_ies(struct mwifiex_private *priv,
+                        struct cfg80211_beacon_data *info)
+{
+       int ret;
+
+       ret = mwifiex_uap_parse_tail_ies(priv, info);
+
+       if (ret)
+               return ret;
+
+       return mwifiex_set_mgmt_beacon_data_ies(priv, info);
+}
+
+/* This function removes management IE set */
+int mwifiex_del_mgmt_ies(struct mwifiex_private *priv)
+{
+       struct mwifiex_ie *beacon_ie = NULL, *pr_ie = NULL;
+       struct mwifiex_ie *ar_ie = NULL, *gen_ie = NULL;
+       int ret = 0;
+
+       if (priv->gen_idx != MWIFIEX_AUTO_IDX_MASK) {
+               gen_ie = kmalloc(sizeof(*gen_ie), GFP_KERNEL);
+               if (!gen_ie)
+                       return -ENOMEM;
+
+               gen_ie->ie_index = cpu_to_le16(priv->gen_idx);
+               gen_ie->mgmt_subtype_mask = cpu_to_le16(MWIFIEX_DELETE_MASK);
+               gen_ie->ie_length = 0;
+               if (mwifiex_update_uap_custom_ie(priv, gen_ie, &priv->gen_idx,
+                                                NULL, &priv->proberesp_idx,
+                                                NULL, &priv->assocresp_idx)) {
+                       ret = -1;
+                       goto done;
+               }
+
+               priv->gen_idx = MWIFIEX_AUTO_IDX_MASK;
+       }
+
+       if (priv->beacon_idx != MWIFIEX_AUTO_IDX_MASK) {
+               beacon_ie = kmalloc(sizeof(struct mwifiex_ie), GFP_KERNEL);
+               if (!beacon_ie) {
+                       ret = -ENOMEM;
+                       goto done;
+               }
+               beacon_ie->ie_index = cpu_to_le16(priv->beacon_idx);
+               beacon_ie->mgmt_subtype_mask = cpu_to_le16(MWIFIEX_DELETE_MASK);
+               beacon_ie->ie_length = 0;
+       }
+       if (priv->proberesp_idx != MWIFIEX_AUTO_IDX_MASK) {
+               pr_ie = kmalloc(sizeof(struct mwifiex_ie), GFP_KERNEL);
+               if (!pr_ie) {
+                       ret = -ENOMEM;
+                       goto done;
+               }
+               pr_ie->ie_index = cpu_to_le16(priv->proberesp_idx);
+               pr_ie->mgmt_subtype_mask = cpu_to_le16(MWIFIEX_DELETE_MASK);
+               pr_ie->ie_length = 0;
+       }
+       if (priv->assocresp_idx != MWIFIEX_AUTO_IDX_MASK) {
+               ar_ie = kmalloc(sizeof(struct mwifiex_ie), GFP_KERNEL);
+               if (!ar_ie) {
+                       ret = -ENOMEM;
+                       goto done;
+               }
+               ar_ie->ie_index = cpu_to_le16(priv->assocresp_idx);
+               ar_ie->mgmt_subtype_mask = cpu_to_le16(MWIFIEX_DELETE_MASK);
+               ar_ie->ie_length = 0;
+       }
+
+       if (beacon_ie || pr_ie || ar_ie)
+               ret = mwifiex_update_uap_custom_ie(priv,
+                                                  beacon_ie, &priv->beacon_idx,
+                                                  pr_ie, &priv->proberesp_idx,
+                                                  ar_ie, &priv->assocresp_idx);
+
+done:
+       kfree(gen_ie);
+       kfree(beacon_ie);
+       kfree(pr_ie);
+       kfree(ar_ie);
+
+       return ret;
+}
diff --git a/drivers/net/wireless/marvell/mwifiex/init.c b/drivers/net/wireless/marvell/mwifiex/init.c
new file mode 100644 (file)
index 0000000..de74a77
--- /dev/null
@@ -0,0 +1,782 @@
+/*
+ * Marvell Wireless LAN device driver: HW/FW Initialization
+ *
+ * Copyright (C) 2011-2014, Marvell International Ltd.
+ *
+ * This software file (the "File") is distributed by Marvell International
+ * Ltd. under the terms of the GNU General Public License Version 2, June 1991
+ * (the "License").  You may use, redistribute and/or modify this File in
+ * accordance with the terms and conditions of the License, a copy of which
+ * is available by writing to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the
+ * worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
+ *
+ * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
+ * ARE EXPRESSLY DISCLAIMED.  The License provides additional details about
+ * this warranty disclaimer.
+ */
+
+#include "decl.h"
+#include "ioctl.h"
+#include "util.h"
+#include "fw.h"
+#include "main.h"
+#include "wmm.h"
+#include "11n.h"
+
+/*
+ * This function adds a BSS priority table to the table list.
+ *
+ * The function allocates a new BSS priority table node and adds it to
+ * the end of BSS priority table list, kept in driver memory.
+ */
+static int mwifiex_add_bss_prio_tbl(struct mwifiex_private *priv)
+{
+       struct mwifiex_adapter *adapter = priv->adapter;
+       struct mwifiex_bss_prio_node *bss_prio;
+       struct mwifiex_bss_prio_tbl *tbl = adapter->bss_prio_tbl;
+       unsigned long flags;
+
+       bss_prio = kzalloc(sizeof(struct mwifiex_bss_prio_node), GFP_KERNEL);
+       if (!bss_prio)
+               return -ENOMEM;
+
+       bss_prio->priv = priv;
+       INIT_LIST_HEAD(&bss_prio->list);
+
+       spin_lock_irqsave(&tbl[priv->bss_priority].bss_prio_lock, flags);
+       list_add_tail(&bss_prio->list, &tbl[priv->bss_priority].bss_prio_head);
+       spin_unlock_irqrestore(&tbl[priv->bss_priority].bss_prio_lock, flags);
+
+       return 0;
+}
+
+static void wakeup_timer_fn(unsigned long data)
+{
+       struct mwifiex_adapter *adapter = (struct mwifiex_adapter *)data;
+
+       mwifiex_dbg(adapter, ERROR, "Firmware wakeup failed\n");
+       adapter->hw_status = MWIFIEX_HW_STATUS_RESET;
+       mwifiex_cancel_all_pending_cmd(adapter);
+
+       if (adapter->if_ops.card_reset)
+               adapter->if_ops.card_reset(adapter);
+}
+
+/*
+ * This function initializes the private structure and sets default
+ * values to the members.
+ *
+ * Additionally, it also initializes all the locks and sets up all the
+ * lists.
+ */
+int mwifiex_init_priv(struct mwifiex_private *priv)
+{
+       u32 i;
+
+       priv->media_connected = false;
+       eth_broadcast_addr(priv->curr_addr);
+       priv->port_open = false;
+       priv->usb_port = MWIFIEX_USB_EP_DATA;
+       priv->pkt_tx_ctrl = 0;
+       priv->bss_mode = NL80211_IFTYPE_UNSPECIFIED;
+       priv->data_rate = 0;    /* Initially indicate the rate as auto */
+       priv->is_data_rate_auto = true;
+       priv->bcn_avg_factor = DEFAULT_BCN_AVG_FACTOR;
+       priv->data_avg_factor = DEFAULT_DATA_AVG_FACTOR;
+
+       priv->sec_info.wep_enabled = 0;
+       priv->sec_info.authentication_mode = NL80211_AUTHTYPE_OPEN_SYSTEM;
+       priv->sec_info.encryption_mode = 0;
+       for (i = 0; i < ARRAY_SIZE(priv->wep_key); i++)
+               memset(&priv->wep_key[i], 0, sizeof(struct mwifiex_wep_key));
+       priv->wep_key_curr_index = 0;
+       priv->curr_pkt_filter = HostCmd_ACT_MAC_RX_ON | HostCmd_ACT_MAC_TX_ON |
+                               HostCmd_ACT_MAC_ETHERNETII_ENABLE;
+
+       priv->beacon_period = 100; /* beacon interval */ ;
+       priv->attempted_bss_desc = NULL;
+       memset(&priv->curr_bss_params, 0, sizeof(priv->curr_bss_params));
+       priv->listen_interval = MWIFIEX_DEFAULT_LISTEN_INTERVAL;
+
+       memset(&priv->prev_ssid, 0, sizeof(priv->prev_ssid));
+       memset(&priv->prev_bssid, 0, sizeof(priv->prev_bssid));
+       memset(&priv->assoc_rsp_buf, 0, sizeof(priv->assoc_rsp_buf));
+       priv->assoc_rsp_size = 0;
+       priv->adhoc_channel = DEFAULT_AD_HOC_CHANNEL;
+       priv->atim_window = 0;
+       priv->adhoc_state = ADHOC_IDLE;
+       priv->tx_power_level = 0;
+       priv->max_tx_power_level = 0;
+       priv->min_tx_power_level = 0;
+       priv->tx_rate = 0;
+       priv->rxpd_htinfo = 0;
+       priv->rxpd_rate = 0;
+       priv->rate_bitmap = 0;
+       priv->data_rssi_last = 0;
+       priv->data_rssi_avg = 0;
+       priv->data_nf_avg = 0;
+       priv->data_nf_last = 0;
+       priv->bcn_rssi_last = 0;
+       priv->bcn_rssi_avg = 0;
+       priv->bcn_nf_avg = 0;
+       priv->bcn_nf_last = 0;
+       memset(&priv->wpa_ie, 0, sizeof(priv->wpa_ie));
+       memset(&priv->aes_key, 0, sizeof(priv->aes_key));
+       priv->wpa_ie_len = 0;
+       priv->wpa_is_gtk_set = false;
+
+       memset(&priv->assoc_tlv_buf, 0, sizeof(priv->assoc_tlv_buf));
+       priv->assoc_tlv_buf_len = 0;
+       memset(&priv->wps, 0, sizeof(priv->wps));
+       memset(&priv->gen_ie_buf, 0, sizeof(priv->gen_ie_buf));
+       priv->gen_ie_buf_len = 0;
+       memset(priv->vs_ie, 0, sizeof(priv->vs_ie));
+
+       priv->wmm_required = true;
+       priv->wmm_enabled = false;
+       priv->wmm_qosinfo = 0;
+       priv->curr_bcn_buf = NULL;
+       priv->curr_bcn_size = 0;
+       priv->wps_ie = NULL;
+       priv->wps_ie_len = 0;
+       priv->ap_11n_enabled = 0;
+       memset(&priv->roc_cfg, 0, sizeof(priv->roc_cfg));
+
+       priv->scan_block = false;
+
+       priv->csa_chan = 0;
+       priv->csa_expire_time = 0;
+       priv->del_list_idx = 0;
+       priv->hs2_enabled = false;
+       priv->check_tdls_tx = false;
+       memcpy(priv->tos_to_tid_inv, tos_to_tid_inv, MAX_NUM_TID);
+
+       mwifiex_init_11h_params(priv);
+
+       return mwifiex_add_bss_prio_tbl(priv);
+}
+
+/*
+ * This function allocates buffers for members of the adapter
+ * structure.
+ *
+ * The memory allocated includes scan table, command buffers, and
+ * sleep confirm command buffer. In addition, the queues are
+ * also initialized.
+ */
+static int mwifiex_allocate_adapter(struct mwifiex_adapter *adapter)
+{
+       int ret;
+
+       /* Allocate command buffer */
+       ret = mwifiex_alloc_cmd_buffer(adapter);
+       if (ret) {
+               mwifiex_dbg(adapter, ERROR,
+                           "%s: failed to alloc cmd buffer\n",
+                           __func__);
+               return -1;
+       }
+
+       adapter->sleep_cfm =
+               dev_alloc_skb(sizeof(struct mwifiex_opt_sleep_confirm)
+                             + INTF_HEADER_LEN);
+
+       if (!adapter->sleep_cfm) {
+               mwifiex_dbg(adapter, ERROR,
+                           "%s: failed to alloc sleep cfm\t"
+                           " cmd buffer\n", __func__);
+               return -1;
+       }
+       skb_reserve(adapter->sleep_cfm, INTF_HEADER_LEN);
+
+       return 0;
+}
+
+/*
+ * This function initializes the adapter structure and sets default
+ * values to the members of adapter.
+ *
+ * This also initializes the WMM related parameters in the driver private
+ * structures.
+ */
+static void mwifiex_init_adapter(struct mwifiex_adapter *adapter)
+{
+       struct mwifiex_opt_sleep_confirm *sleep_cfm_buf = NULL;
+
+       skb_put(adapter->sleep_cfm, sizeof(struct mwifiex_opt_sleep_confirm));
+
+       adapter->cmd_sent = false;
+
+       if (adapter->iface_type == MWIFIEX_SDIO)
+               adapter->data_sent = true;
+       else
+               adapter->data_sent = false;
+
+       adapter->cmd_resp_received = false;
+       adapter->event_received = false;
+       adapter->data_received = false;
+
+       adapter->surprise_removed = false;
+
+       adapter->hw_status = MWIFIEX_HW_STATUS_INITIALIZING;
+
+       adapter->ps_mode = MWIFIEX_802_11_POWER_MODE_CAM;
+       adapter->ps_state = PS_STATE_AWAKE;
+       adapter->need_to_wakeup = false;
+
+       adapter->scan_mode = HostCmd_BSS_MODE_ANY;
+       adapter->specific_scan_time = MWIFIEX_SPECIFIC_SCAN_CHAN_TIME;
+       adapter->active_scan_time = MWIFIEX_ACTIVE_SCAN_CHAN_TIME;
+       adapter->passive_scan_time = MWIFIEX_PASSIVE_SCAN_CHAN_TIME;
+       adapter->scan_chan_gap_time = MWIFIEX_DEF_SCAN_CHAN_GAP_TIME;
+
+       adapter->scan_probes = 1;
+
+       adapter->multiple_dtim = 1;
+
+       adapter->local_listen_interval = 0;     /* default value in firmware
+                                                  will be used */
+
+       adapter->is_deep_sleep = false;
+
+       adapter->delay_null_pkt = false;
+       adapter->delay_to_ps = 1000;
+       adapter->enhanced_ps_mode = PS_MODE_AUTO;
+
+       adapter->gen_null_pkt = false;  /* Disable NULL Pkg generation by
+                                          default */
+       adapter->pps_uapsd_mode = false; /* Disable pps/uapsd mode by
+                                          default */
+       adapter->pm_wakeup_card_req = false;
+
+       adapter->pm_wakeup_fw_try = false;
+
+       adapter->curr_tx_buf_size = MWIFIEX_TX_DATA_BUF_SIZE_2K;
+
+       adapter->is_hs_configured = false;
+       adapter->hs_cfg.conditions = cpu_to_le32(HS_CFG_COND_DEF);
+       adapter->hs_cfg.gpio = HS_CFG_GPIO_DEF;
+       adapter->hs_cfg.gap = HS_CFG_GAP_DEF;
+       adapter->hs_activated = false;
+
+       memset(adapter->event_body, 0, sizeof(adapter->event_body));
+       adapter->hw_dot_11n_dev_cap = 0;
+       adapter->hw_dev_mcs_support = 0;
+       adapter->sec_chan_offset = 0;
+       adapter->adhoc_11n_enabled = false;
+
+       mwifiex_wmm_init(adapter);
+
+       sleep_cfm_buf = (struct mwifiex_opt_sleep_confirm *)
+                                       adapter->sleep_cfm->data;
+       memset(sleep_cfm_buf, 0, adapter->sleep_cfm->len);
+       sleep_cfm_buf->command = cpu_to_le16(HostCmd_CMD_802_11_PS_MODE_ENH);
+       sleep_cfm_buf->size = cpu_to_le16(adapter->sleep_cfm->len);
+       sleep_cfm_buf->result = 0;
+       sleep_cfm_buf->action = cpu_to_le16(SLEEP_CONFIRM);
+       sleep_cfm_buf->resp_ctrl = cpu_to_le16(RESP_NEEDED);
+
+       memset(&adapter->sleep_params, 0, sizeof(adapter->sleep_params));
+       memset(&adapter->sleep_period, 0, sizeof(adapter->sleep_period));
+       adapter->tx_lock_flag = false;
+       adapter->null_pkt_interval = 0;
+       adapter->fw_bands = 0;
+       adapter->config_bands = 0;
+       adapter->adhoc_start_band = 0;
+       adapter->scan_channels = NULL;
+       adapter->fw_release_number = 0;
+       adapter->fw_cap_info = 0;
+       memset(&adapter->upld_buf, 0, sizeof(adapter->upld_buf));
+       adapter->event_cause = 0;
+       adapter->region_code = 0;
+       adapter->bcn_miss_time_out = DEFAULT_BCN_MISS_TIMEOUT;
+       adapter->adhoc_awake_period = 0;
+       memset(&adapter->arp_filter, 0, sizeof(adapter->arp_filter));
+       adapter->arp_filter_size = 0;
+       adapter->max_mgmt_ie_index = MAX_MGMT_IE_INDEX;
+       adapter->key_api_major_ver = 0;
+       adapter->key_api_minor_ver = 0;
+       eth_broadcast_addr(adapter->perm_addr);
+       adapter->iface_limit.sta_intf = MWIFIEX_MAX_STA_NUM;
+       adapter->iface_limit.uap_intf = MWIFIEX_MAX_UAP_NUM;
+       adapter->iface_limit.p2p_intf = MWIFIEX_MAX_P2P_NUM;
+       adapter->active_scan_triggered = false;
+       setup_timer(&adapter->wakeup_timer, wakeup_timer_fn,
+                   (unsigned long)adapter);
+}
+
+/*
+ * This function sets trans_start per tx_queue
+ */
+void mwifiex_set_trans_start(struct net_device *dev)
+{
+       int i;
+
+       for (i = 0; i < dev->num_tx_queues; i++)
+               netdev_get_tx_queue(dev, i)->trans_start = jiffies;
+
+       dev->trans_start = jiffies;
+}
+
+/*
+ * This function wakes up all queues in net_device
+ */
+void mwifiex_wake_up_net_dev_queue(struct net_device *netdev,
+                                       struct mwifiex_adapter *adapter)
+{
+       unsigned long dev_queue_flags;
+       unsigned int i;
+
+       spin_lock_irqsave(&adapter->queue_lock, dev_queue_flags);
+
+       for (i = 0; i < netdev->num_tx_queues; i++) {
+               struct netdev_queue *txq = netdev_get_tx_queue(netdev, i);
+
+               if (netif_tx_queue_stopped(txq))
+                       netif_tx_wake_queue(txq);
+       }
+
+       spin_unlock_irqrestore(&adapter->queue_lock, dev_queue_flags);
+}
+
+/*
+ * This function stops all queues in net_device
+ */
+void mwifiex_stop_net_dev_queue(struct net_device *netdev,
+                                       struct mwifiex_adapter *adapter)
+{
+       unsigned long dev_queue_flags;
+       unsigned int i;
+
+       spin_lock_irqsave(&adapter->queue_lock, dev_queue_flags);
+
+       for (i = 0; i < netdev->num_tx_queues; i++) {
+               struct netdev_queue *txq = netdev_get_tx_queue(netdev, i);
+
+               if (!netif_tx_queue_stopped(txq))
+                       netif_tx_stop_queue(txq);
+       }
+
+       spin_unlock_irqrestore(&adapter->queue_lock, dev_queue_flags);
+}
+
+/*
+ *  This function releases the lock variables and frees the locks and
+ *  associated locks.
+ */
+static void mwifiex_free_lock_list(struct mwifiex_adapter *adapter)
+{
+       struct mwifiex_private *priv;
+       s32 i, j;
+
+       /* Free lists */
+       list_del(&adapter->cmd_free_q);
+       list_del(&adapter->cmd_pending_q);
+       list_del(&adapter->scan_pending_q);
+
+       for (i = 0; i < adapter->priv_num; i++)
+               list_del(&adapter->bss_prio_tbl[i].bss_prio_head);
+
+       for (i = 0; i < adapter->priv_num; i++) {
+               if (adapter->priv[i]) {
+                       priv = adapter->priv[i];
+                       for (j = 0; j < MAX_NUM_TID; ++j)
+                               list_del(&priv->wmm.tid_tbl_ptr[j].ra_list);
+                       list_del(&priv->tx_ba_stream_tbl_ptr);
+                       list_del(&priv->rx_reorder_tbl_ptr);
+                       list_del(&priv->sta_list);
+                       list_del(&priv->auto_tdls_list);
+               }
+       }
+}
+
+/*
+ * This function performs cleanup for adapter structure.
+ *
+ * The cleanup is done recursively, by canceling all pending
+ * commands, freeing the member buffers previously allocated
+ * (command buffers, scan table buffer, sleep confirm command
+ * buffer), stopping the timers and calling the cleanup routines
+ * for every interface.
+ */
+static void
+mwifiex_adapter_cleanup(struct mwifiex_adapter *adapter)
+{
+       int idx;
+
+       if (!adapter) {
+               pr_err("%s: adapter is NULL\n", __func__);
+               return;
+       }
+
+       del_timer(&adapter->wakeup_timer);
+       mwifiex_cancel_all_pending_cmd(adapter);
+       wake_up_interruptible(&adapter->cmd_wait_q.wait);
+       wake_up_interruptible(&adapter->hs_activate_wait_q);
+
+       /* Free lock variables */
+       mwifiex_free_lock_list(adapter);
+
+       /* Free command buffer */
+       mwifiex_dbg(adapter, INFO, "info: free cmd buffer\n");
+       mwifiex_free_cmd_buffer(adapter);
+
+       for (idx = 0; idx < adapter->num_mem_types; idx++) {
+               struct memory_type_mapping *entry =
+                               &adapter->mem_type_mapping_tbl[idx];
+
+               if (entry->mem_ptr) {
+                       vfree(entry->mem_ptr);
+                       entry->mem_ptr = NULL;
+               }
+               entry->mem_size = 0;
+       }
+
+       if (adapter->drv_info_dump) {
+               vfree(adapter->drv_info_dump);
+               adapter->drv_info_dump = NULL;
+               adapter->drv_info_size = 0;
+       }
+
+       if (adapter->sleep_cfm)
+               dev_kfree_skb_any(adapter->sleep_cfm);
+}
+
+/*
+ *  This function intializes the lock variables and
+ *  the list heads.
+ */
+int mwifiex_init_lock_list(struct mwifiex_adapter *adapter)
+{
+       struct mwifiex_private *priv;
+       s32 i, j;
+
+       spin_lock_init(&adapter->mwifiex_lock);
+       spin_lock_init(&adapter->int_lock);
+       spin_lock_init(&adapter->main_proc_lock);
+       spin_lock_init(&adapter->mwifiex_cmd_lock);
+       spin_lock_init(&adapter->queue_lock);
+       for (i = 0; i < adapter->priv_num; i++) {
+               if (adapter->priv[i]) {
+                       priv = adapter->priv[i];
+                       spin_lock_init(&priv->rx_pkt_lock);
+                       spin_lock_init(&priv->wmm.ra_list_spinlock);
+                       spin_lock_init(&priv->curr_bcn_buf_lock);
+                       spin_lock_init(&priv->sta_list_spinlock);
+                       spin_lock_init(&priv->auto_tdls_lock);
+               }
+       }
+
+       /* Initialize cmd_free_q */
+       INIT_LIST_HEAD(&adapter->cmd_free_q);
+       /* Initialize cmd_pending_q */
+       INIT_LIST_HEAD(&adapter->cmd_pending_q);
+       /* Initialize scan_pending_q */
+       INIT_LIST_HEAD(&adapter->scan_pending_q);
+
+       spin_lock_init(&adapter->cmd_free_q_lock);
+       spin_lock_init(&adapter->cmd_pending_q_lock);
+       spin_lock_init(&adapter->scan_pending_q_lock);
+       spin_lock_init(&adapter->rx_proc_lock);
+
+       skb_queue_head_init(&adapter->rx_data_q);
+       skb_queue_head_init(&adapter->tx_data_q);
+
+       for (i = 0; i < adapter->priv_num; ++i) {
+               INIT_LIST_HEAD(&adapter->bss_prio_tbl[i].bss_prio_head);
+               spin_lock_init(&adapter->bss_prio_tbl[i].bss_prio_lock);
+       }
+
+       for (i = 0; i < adapter->priv_num; i++) {
+               if (!adapter->priv[i])
+                       continue;
+               priv = adapter->priv[i];
+               for (j = 0; j < MAX_NUM_TID; ++j)
+                       INIT_LIST_HEAD(&priv->wmm.tid_tbl_ptr[j].ra_list);
+               INIT_LIST_HEAD(&priv->tx_ba_stream_tbl_ptr);
+               INIT_LIST_HEAD(&priv->rx_reorder_tbl_ptr);
+               INIT_LIST_HEAD(&priv->sta_list);
+               INIT_LIST_HEAD(&priv->auto_tdls_list);
+               skb_queue_head_init(&priv->tdls_txq);
+               skb_queue_head_init(&priv->bypass_txq);
+
+               spin_lock_init(&priv->tx_ba_stream_tbl_lock);
+               spin_lock_init(&priv->rx_reorder_tbl_lock);
+
+               spin_lock_init(&priv->ack_status_lock);
+               idr_init(&priv->ack_status_frames);
+       }
+
+       return 0;
+}
+
+/*
+ * This function initializes the firmware.
+ *
+ * The following operations are performed sequentially -
+ *      - Allocate adapter structure
+ *      - Initialize the adapter structure
+ *      - Initialize the private structure
+ *      - Add BSS priority tables to the adapter structure
+ *      - For each interface, send the init commands to firmware
+ *      - Send the first command in command pending queue, if available
+ */
+int mwifiex_init_fw(struct mwifiex_adapter *adapter)
+{
+       int ret;
+       struct mwifiex_private *priv;
+       u8 i, first_sta = true;
+       int is_cmd_pend_q_empty;
+       unsigned long flags;
+
+       adapter->hw_status = MWIFIEX_HW_STATUS_INITIALIZING;
+
+       /* Allocate memory for member of adapter structure */
+       ret = mwifiex_allocate_adapter(adapter);
+       if (ret)
+               return -1;
+
+       /* Initialize adapter structure */
+       mwifiex_init_adapter(adapter);
+
+       for (i = 0; i < adapter->priv_num; i++) {
+               if (adapter->priv[i]) {
+                       priv = adapter->priv[i];
+
+                       /* Initialize private structure */
+                       ret = mwifiex_init_priv(priv);
+                       if (ret)
+                               return -1;
+               }
+       }
+
+       for (i = 0; i < adapter->priv_num; i++) {
+               if (adapter->priv[i]) {
+                       ret = mwifiex_sta_init_cmd(adapter->priv[i], first_sta,
+                                                  true);
+                       if (ret == -1)
+                               return -1;
+
+                       first_sta = false;
+               }
+       }
+
+       spin_lock_irqsave(&adapter->cmd_pending_q_lock, flags);
+       is_cmd_pend_q_empty = list_empty(&adapter->cmd_pending_q);
+       spin_unlock_irqrestore(&adapter->cmd_pending_q_lock, flags);
+       if (!is_cmd_pend_q_empty) {
+               /* Send the first command in queue and return */
+               if (mwifiex_main_process(adapter) != -1)
+                       ret = -EINPROGRESS;
+       } else {
+               adapter->hw_status = MWIFIEX_HW_STATUS_READY;
+       }
+
+       return ret;
+}
+
+/*
+ * This function deletes the BSS priority tables.
+ *
+ * The function traverses through all the allocated BSS priority nodes
+ * in every BSS priority table and frees them.
+ */
+static void mwifiex_delete_bss_prio_tbl(struct mwifiex_private *priv)
+{
+       int i;
+       struct mwifiex_adapter *adapter = priv->adapter;
+       struct mwifiex_bss_prio_node *bssprio_node, *tmp_node;
+       struct list_head *head;
+       spinlock_t *lock; /* bss priority lock */
+       unsigned long flags;
+
+       for (i = 0; i < adapter->priv_num; ++i) {
+               head = &adapter->bss_prio_tbl[i].bss_prio_head;
+               lock = &adapter->bss_prio_tbl[i].bss_prio_lock;
+               mwifiex_dbg(adapter, INFO,
+                           "info: delete BSS priority table,\t"
+                           "bss_type = %d, bss_num = %d, i = %d,\t"
+                           "head = %p\n",
+                           priv->bss_type, priv->bss_num, i, head);
+
+               {
+                       spin_lock_irqsave(lock, flags);
+                       if (list_empty(head)) {
+                               spin_unlock_irqrestore(lock, flags);
+                               continue;
+                       }
+                       list_for_each_entry_safe(bssprio_node, tmp_node, head,
+                                                list) {
+                               if (bssprio_node->priv == priv) {
+                                       mwifiex_dbg(adapter, INFO,
+                                                   "info: Delete\t"
+                                                   "node %p, next = %p\n",
+                                                   bssprio_node, tmp_node);
+                                       list_del(&bssprio_node->list);
+                                       kfree(bssprio_node);
+                               }
+                       }
+                       spin_unlock_irqrestore(lock, flags);
+               }
+       }
+}
+
+/*
+ * This function frees the private structure, including cleans
+ * up the TX and RX queues and frees the BSS priority tables.
+ */
+void mwifiex_free_priv(struct mwifiex_private *priv)
+{
+       mwifiex_clean_txrx(priv);
+       mwifiex_delete_bss_prio_tbl(priv);
+       mwifiex_free_curr_bcn(priv);
+}
+
+/*
+ * This function is used to shutdown the driver.
+ *
+ * The following operations are performed sequentially -
+ *      - Check if already shut down
+ *      - Make sure the main process has stopped
+ *      - Clean up the Tx and Rx queues
+ *      - Delete BSS priority tables
+ *      - Free the adapter
+ *      - Notify completion
+ */
+int
+mwifiex_shutdown_drv(struct mwifiex_adapter *adapter)
+{
+       int ret = -EINPROGRESS;
+       struct mwifiex_private *priv;
+       s32 i;
+       unsigned long flags;
+       struct sk_buff *skb;
+
+       /* mwifiex already shutdown */
+       if (adapter->hw_status == MWIFIEX_HW_STATUS_NOT_READY)
+               return 0;
+
+       adapter->hw_status = MWIFIEX_HW_STATUS_CLOSING;
+       /* wait for mwifiex_process to complete */
+       if (adapter->mwifiex_processing) {
+               mwifiex_dbg(adapter, WARN,
+                           "main process is still running\n");
+               return ret;
+       }
+
+       /* cancel current command */
+       if (adapter->curr_cmd) {
+               mwifiex_dbg(adapter, WARN,
+                           "curr_cmd is still in processing\n");
+               del_timer_sync(&adapter->cmd_timer);
+               mwifiex_recycle_cmd_node(adapter, adapter->curr_cmd);
+               adapter->curr_cmd = NULL;
+       }
+
+       /* shut down mwifiex */
+       mwifiex_dbg(adapter, MSG,
+                   "info: shutdown mwifiex...\n");
+
+       /* Clean up Tx/Rx queues and delete BSS priority table */
+       for (i = 0; i < adapter->priv_num; i++) {
+               if (adapter->priv[i]) {
+                       priv = adapter->priv[i];
+
+                       mwifiex_clean_auto_tdls(priv);
+                       mwifiex_abort_cac(priv);
+                       mwifiex_clean_txrx(priv);
+                       mwifiex_delete_bss_prio_tbl(priv);
+               }
+       }
+
+       atomic_set(&adapter->tx_queued, 0);
+       while ((skb = skb_dequeue(&adapter->tx_data_q)))
+               mwifiex_write_data_complete(adapter, skb, 0, 0);
+
+       spin_lock_irqsave(&adapter->rx_proc_lock, flags);
+
+       while ((skb = skb_dequeue(&adapter->rx_data_q))) {
+               struct mwifiex_rxinfo *rx_info = MWIFIEX_SKB_RXCB(skb);
+
+               atomic_dec(&adapter->rx_pending);
+               priv = adapter->priv[rx_info->bss_num];
+               if (priv)
+                       priv->stats.rx_dropped++;
+
+               dev_kfree_skb_any(skb);
+       }
+
+       spin_unlock_irqrestore(&adapter->rx_proc_lock, flags);
+
+       spin_lock(&adapter->mwifiex_lock);
+
+       mwifiex_adapter_cleanup(adapter);
+
+       spin_unlock(&adapter->mwifiex_lock);
+
+       /* Notify completion */
+       ret = mwifiex_shutdown_fw_complete(adapter);
+
+       return ret;
+}
+
+/*
+ * This function downloads the firmware to the card.
+ *
+ * The actual download is preceded by two sanity checks -
+ *      - Check if firmware is already running
+ *      - Check if the interface is the winner to download the firmware
+ *
+ * ...and followed by another -
+ *      - Check if the firmware is downloaded successfully
+ *
+ * After download is successfully completed, the host interrupts are enabled.
+ */
+int mwifiex_dnld_fw(struct mwifiex_adapter *adapter,
+                   struct mwifiex_fw_image *pmfw)
+{
+       int ret;
+       u32 poll_num = 1;
+
+       if (adapter->if_ops.check_fw_status) {
+               adapter->winner = 0;
+
+               /* check if firmware is already running */
+               ret = adapter->if_ops.check_fw_status(adapter, poll_num);
+               if (!ret) {
+                       mwifiex_dbg(adapter, MSG,
+                                   "WLAN FW already running! Skip FW dnld\n");
+                       return 0;
+               }
+
+               poll_num = MAX_FIRMWARE_POLL_TRIES;
+
+               /* check if we are the winner for downloading FW */
+               if (!adapter->winner) {
+                       mwifiex_dbg(adapter, MSG,
+                                   "FW already running! Skip FW dnld\n");
+                       goto poll_fw;
+               }
+       }
+
+       if (pmfw) {
+               /* Download firmware with helper */
+               ret = adapter->if_ops.prog_fw(adapter, pmfw);
+               if (ret) {
+                       mwifiex_dbg(adapter, ERROR,
+                                   "prog_fw failed ret=%#x\n", ret);
+                       return ret;
+               }
+       }
+
+poll_fw:
+       /* Check if the firmware is downloaded successfully or not */
+       ret = adapter->if_ops.check_fw_status(adapter, poll_num);
+       if (ret)
+               mwifiex_dbg(adapter, ERROR,
+                           "FW failed to be active in time\n");
+
+       return ret;
+}
diff --git a/drivers/net/wireless/marvell/mwifiex/ioctl.h b/drivers/net/wireless/marvell/mwifiex/ioctl.h
new file mode 100644 (file)
index 0000000..4f0174c
--- /dev/null
@@ -0,0 +1,470 @@
+/*
+ * Marvell Wireless LAN device driver: ioctl data structures & APIs
+ *
+ * Copyright (C) 2011-2014, Marvell International Ltd.
+ *
+ * This software file (the "File") is distributed by Marvell International
+ * Ltd. under the terms of the GNU General Public License Version 2, June 1991
+ * (the "License").  You may use, redistribute and/or modify this File in
+ * accordance with the terms and conditions of the License, a copy of which
+ * is available by writing to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the
+ * worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
+ *
+ * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
+ * ARE EXPRESSLY DISCLAIMED.  The License provides additional details about
+ * this warranty disclaimer.
+ */
+
+#ifndef _MWIFIEX_IOCTL_H_
+#define _MWIFIEX_IOCTL_H_
+
+#include <net/lib80211.h>
+
+enum {
+       MWIFIEX_SCAN_TYPE_UNCHANGED = 0,
+       MWIFIEX_SCAN_TYPE_ACTIVE,
+       MWIFIEX_SCAN_TYPE_PASSIVE
+};
+
+struct mwifiex_user_scan {
+       u32 scan_cfg_len;
+       u8 scan_cfg_buf[1];
+};
+
+#define MWIFIEX_PROMISC_MODE            1
+#define MWIFIEX_MULTICAST_MODE         2
+#define        MWIFIEX_ALL_MULTI_MODE          4
+#define MWIFIEX_MAX_MULTICAST_LIST_SIZE        32
+
+struct mwifiex_multicast_list {
+       u32 mode;
+       u32 num_multicast_addr;
+       u8 mac_list[MWIFIEX_MAX_MULTICAST_LIST_SIZE][ETH_ALEN];
+};
+
+struct mwifiex_chan_freq {
+       u32 channel;
+       u32 freq;
+};
+
+struct mwifiex_ssid_bssid {
+       struct cfg80211_ssid ssid;
+       u8 bssid[ETH_ALEN];
+};
+
+enum {
+       BAND_B = 1,
+       BAND_G = 2,
+       BAND_A = 4,
+       BAND_GN = 8,
+       BAND_AN = 16,
+       BAND_AAC = 32,
+};
+
+#define MWIFIEX_WPA_PASSHPHRASE_LEN 64
+struct wpa_param {
+       u8 pairwise_cipher_wpa;
+       u8 pairwise_cipher_wpa2;
+       u8 group_cipher;
+       u32 length;
+       u8 passphrase[MWIFIEX_WPA_PASSHPHRASE_LEN];
+};
+
+struct wep_key {
+       u8 key_index;
+       u8 is_default;
+       u16 length;
+       u8 key[WLAN_KEY_LEN_WEP104];
+};
+
+#define KEY_MGMT_ON_HOST        0x03
+#define MWIFIEX_AUTH_MODE_AUTO  0xFF
+#define BAND_CONFIG_BG          0x00
+#define BAND_CONFIG_A           0x01
+#define MWIFIEX_SUPPORTED_RATES                 14
+#define MWIFIEX_SUPPORTED_RATES_EXT             32
+#define MWIFIEX_TDLS_SUPPORTED_RATES           8
+#define MWIFIEX_TDLS_DEF_QOS_CAPAB             0xf
+#define MWIFIEX_PRIO_BK                                2
+#define MWIFIEX_PRIO_VI                                5
+
+struct mwifiex_uap_bss_param {
+       u8 channel;
+       u8 band_cfg;
+       u16 rts_threshold;
+       u16 frag_threshold;
+       u8 retry_limit;
+       struct mwifiex_802_11_ssid ssid;
+       u8 bcast_ssid_ctl;
+       u8 radio_ctl;
+       u8 dtim_period;
+       u16 beacon_period;
+       u16 auth_mode;
+       u16 protocol;
+       u16 key_mgmt;
+       u16 key_mgmt_operation;
+       struct wpa_param wpa_cfg;
+       struct wep_key wep_cfg[NUM_WEP_KEYS];
+       struct ieee80211_ht_cap ht_cap;
+       struct ieee80211_vht_cap vht_cap;
+       u8 rates[MWIFIEX_SUPPORTED_RATES];
+       u32 sta_ao_timer;
+       u32 ps_sta_ao_timer;
+       u8 qos_info;
+       u8 power_constraint;
+       struct mwifiex_types_wmm_info wmm_info;
+};
+
+enum {
+       ADHOC_IDLE,
+       ADHOC_STARTED,
+       ADHOC_JOINED,
+       ADHOC_COALESCED
+};
+
+struct mwifiex_ds_get_stats {
+       u32 mcast_tx_frame;
+       u32 failed;
+       u32 retry;
+       u32 multi_retry;
+       u32 frame_dup;
+       u32 rts_success;
+       u32 rts_failure;
+       u32 ack_failure;
+       u32 rx_frag;
+       u32 mcast_rx_frame;
+       u32 fcs_error;
+       u32 tx_frame;
+       u32 wep_icv_error[4];
+       u32 bcn_rcv_cnt;
+       u32 bcn_miss_cnt;
+};
+
+#define MWIFIEX_MAX_VER_STR_LEN    128
+
+struct mwifiex_ver_ext {
+       u32 version_str_sel;
+       char version_str[MWIFIEX_MAX_VER_STR_LEN];
+};
+
+struct mwifiex_bss_info {
+       u32 bss_mode;
+       struct cfg80211_ssid ssid;
+       u32 bss_chan;
+       u8 country_code[3];
+       u32 media_connected;
+       u32 max_power_level;
+       u32 min_power_level;
+       u32 adhoc_state;
+       signed int bcn_nf_last;
+       u32 wep_status;
+       u32 is_hs_configured;
+       u32 is_deep_sleep;
+       u8 bssid[ETH_ALEN];
+};
+
+#define MAX_NUM_TID     8
+
+#define MAX_RX_WINSIZE  64
+
+struct mwifiex_ds_rx_reorder_tbl {
+       u16 tid;
+       u8 ta[ETH_ALEN];
+       u32 start_win;
+       u32 win_size;
+       u32 buffer[MAX_RX_WINSIZE];
+};
+
+struct mwifiex_ds_tx_ba_stream_tbl {
+       u16 tid;
+       u8 ra[ETH_ALEN];
+       u8 amsdu;
+};
+
+#define DBG_CMD_NUM    5
+
+struct tdls_peer_info {
+       u8 peer_addr[ETH_ALEN];
+};
+
+struct mwifiex_debug_info {
+       unsigned int debug_mask;
+       u32 int_counter;
+       u32 packets_out[MAX_NUM_TID];
+       u32 tx_buf_size;
+       u32 curr_tx_buf_size;
+       u32 tx_tbl_num;
+       struct mwifiex_ds_tx_ba_stream_tbl
+               tx_tbl[MWIFIEX_MAX_TX_BASTREAM_SUPPORTED];
+       u32 rx_tbl_num;
+       struct mwifiex_ds_rx_reorder_tbl rx_tbl
+               [MWIFIEX_MAX_RX_BASTREAM_SUPPORTED];
+       u32 tdls_peer_num;
+       struct tdls_peer_info tdls_list
+               [MWIFIEX_MAX_TDLS_PEER_SUPPORTED];
+       u16 ps_mode;
+       u32 ps_state;
+       u8 is_deep_sleep;
+       u8 pm_wakeup_card_req;
+       u32 pm_wakeup_fw_try;
+       u8 is_hs_configured;
+       u8 hs_activated;
+       u32 num_cmd_host_to_card_failure;
+       u32 num_cmd_sleep_cfm_host_to_card_failure;
+       u32 num_tx_host_to_card_failure;
+       u32 num_event_deauth;
+       u32 num_event_disassoc;
+       u32 num_event_link_lost;
+       u32 num_cmd_deauth;
+       u32 num_cmd_assoc_success;
+       u32 num_cmd_assoc_failure;
+       u32 num_tx_timeout;
+       u8 is_cmd_timedout;
+       u16 timeout_cmd_id;
+       u16 timeout_cmd_act;
+       u16 last_cmd_id[DBG_CMD_NUM];
+       u16 last_cmd_act[DBG_CMD_NUM];
+       u16 last_cmd_index;
+       u16 last_cmd_resp_id[DBG_CMD_NUM];
+       u16 last_cmd_resp_index;
+       u16 last_event[DBG_CMD_NUM];
+       u16 last_event_index;
+       u8 data_sent;
+       u8 cmd_sent;
+       u8 cmd_resp_received;
+       u8 event_received;
+};
+
+#define MWIFIEX_KEY_INDEX_UNICAST      0x40000000
+#define PN_LEN                         16
+
+struct mwifiex_ds_encrypt_key {
+       u32 key_disable;
+       u32 key_index;
+       u32 key_len;
+       u8 key_material[WLAN_MAX_KEY_LEN];
+       u8 mac_addr[ETH_ALEN];
+       u32 is_wapi_key;
+       u8 pn[PN_LEN];          /* packet number */
+       u8 pn_len;
+       u8 is_igtk_key;
+       u8 is_current_wep_key;
+       u8 is_rx_seq_valid;
+};
+
+struct mwifiex_power_cfg {
+       u32 is_power_auto;
+       u32 power_level;
+};
+
+struct mwifiex_ds_hs_cfg {
+       u32 is_invoke_hostcmd;
+       /*  Bit0: non-unicast data
+        *  Bit1: unicast data
+        *  Bit2: mac events
+        *  Bit3: magic packet
+        */
+       u32 conditions;
+       u32 gpio;
+       u32 gap;
+};
+
+#define DEEP_SLEEP_ON  1
+#define DEEP_SLEEP_OFF 0
+#define DEEP_SLEEP_IDLE_TIME   100
+#define PS_MODE_AUTO           1
+
+struct mwifiex_ds_auto_ds {
+       u16 auto_ds;
+       u16 idle_time;
+};
+
+struct mwifiex_ds_pm_cfg {
+       union {
+               u32 ps_mode;
+               struct mwifiex_ds_hs_cfg hs_cfg;
+               struct mwifiex_ds_auto_ds auto_deep_sleep;
+               u32 sleep_period;
+       } param;
+};
+
+struct mwifiex_11ac_vht_cfg {
+       u8 band_config;
+       u8 misc_config;
+       u32 cap_info;
+       u32 mcs_tx_set;
+       u32 mcs_rx_set;
+};
+
+struct mwifiex_ds_11n_tx_cfg {
+       u16 tx_htcap;
+       u16 tx_htinfo;
+       u16 misc_config; /* Needed for 802.11AC cards only */
+};
+
+struct mwifiex_ds_11n_amsdu_aggr_ctrl {
+       u16 enable;
+       u16 curr_buf_size;
+};
+
+struct mwifiex_ds_ant_cfg {
+       u32 tx_ant;
+       u32 rx_ant;
+};
+
+#define MWIFIEX_NUM_OF_CMD_BUFFER      50
+#define MWIFIEX_SIZE_OF_CMD_BUFFER     2048
+
+enum {
+       MWIFIEX_IE_TYPE_GEN_IE = 0,
+       MWIFIEX_IE_TYPE_ARP_FILTER,
+};
+
+enum {
+       MWIFIEX_REG_MAC = 1,
+       MWIFIEX_REG_BBP,
+       MWIFIEX_REG_RF,
+       MWIFIEX_REG_PMIC,
+       MWIFIEX_REG_CAU,
+};
+
+struct mwifiex_ds_reg_rw {
+       __le32 type;
+       __le32 offset;
+       __le32 value;
+};
+
+#define MAX_EEPROM_DATA 256
+
+struct mwifiex_ds_read_eeprom {
+       __le16 offset;
+       __le16 byte_count;
+       u8 value[MAX_EEPROM_DATA];
+};
+
+struct mwifiex_ds_mem_rw {
+       u32 addr;
+       u32 value;
+};
+
+#define IEEE_MAX_IE_SIZE               256
+
+#define MWIFIEX_IE_HDR_SIZE    (sizeof(struct mwifiex_ie) - IEEE_MAX_IE_SIZE)
+
+struct mwifiex_ds_misc_gen_ie {
+       u32 type;
+       u32 len;
+       u8 ie_data[IEEE_MAX_IE_SIZE];
+};
+
+struct mwifiex_ds_misc_cmd {
+       u32 len;
+       u8 cmd[MWIFIEX_SIZE_OF_CMD_BUFFER];
+};
+
+#define BITMASK_BCN_RSSI_LOW   BIT(0)
+#define BITMASK_BCN_RSSI_HIGH  BIT(4)
+
+enum subsc_evt_rssi_state {
+       EVENT_HANDLED,
+       RSSI_LOW_RECVD,
+       RSSI_HIGH_RECVD
+};
+
+struct subsc_evt_cfg {
+       u8 abs_value;
+       u8 evt_freq;
+};
+
+struct mwifiex_ds_misc_subsc_evt {
+       u16 action;
+       u16 events;
+       struct subsc_evt_cfg bcn_l_rssi_cfg;
+       struct subsc_evt_cfg bcn_h_rssi_cfg;
+};
+
+#define MWIFIEX_MEF_MAX_BYTESEQ                6       /* non-adjustable */
+#define MWIFIEX_MEF_MAX_FILTERS                10
+
+struct mwifiex_mef_filter {
+       u16 repeat;
+       u16 offset;
+       s8 byte_seq[MWIFIEX_MEF_MAX_BYTESEQ + 1];
+       u8 filt_type;
+       u8 filt_action;
+};
+
+struct mwifiex_mef_entry {
+       u8 mode;
+       u8 action;
+       struct mwifiex_mef_filter filter[MWIFIEX_MEF_MAX_FILTERS];
+};
+
+struct mwifiex_ds_mef_cfg {
+       u32 criteria;
+       u16 num_entries;
+       struct mwifiex_mef_entry *mef_entry;
+};
+
+#define MWIFIEX_MAX_VSIE_LEN       (256)
+#define MWIFIEX_MAX_VSIE_NUM       (8)
+#define MWIFIEX_VSIE_MASK_CLEAR    0x00
+#define MWIFIEX_VSIE_MASK_SCAN     0x01
+#define MWIFIEX_VSIE_MASK_ASSOC    0x02
+#define MWIFIEX_VSIE_MASK_ADHOC    0x04
+
+enum {
+       MWIFIEX_FUNC_INIT = 1,
+       MWIFIEX_FUNC_SHUTDOWN,
+};
+
+enum COALESCE_OPERATION {
+       RECV_FILTER_MATCH_TYPE_EQ = 0x80,
+       RECV_FILTER_MATCH_TYPE_NE,
+};
+
+enum COALESCE_PACKET_TYPE {
+       PACKET_TYPE_UNICAST = 1,
+       PACKET_TYPE_MULTICAST = 2,
+       PACKET_TYPE_BROADCAST = 3
+};
+
+#define MWIFIEX_COALESCE_MAX_RULES     8
+#define MWIFIEX_COALESCE_MAX_BYTESEQ   4       /* non-adjustable */
+#define MWIFIEX_COALESCE_MAX_FILTERS   4
+#define MWIFIEX_MAX_COALESCING_DELAY   100     /* in msecs */
+
+struct filt_field_param {
+       u8 operation;
+       u8 operand_len;
+       u16 offset;
+       u8 operand_byte_stream[MWIFIEX_COALESCE_MAX_BYTESEQ];
+};
+
+struct mwifiex_coalesce_rule {
+       u16 max_coalescing_delay;
+       u8 num_of_fields;
+       u8 pkt_type;
+       struct filt_field_param params[MWIFIEX_COALESCE_MAX_FILTERS];
+};
+
+struct mwifiex_ds_coalesce_cfg {
+       u16 num_of_rules;
+       struct mwifiex_coalesce_rule rule[MWIFIEX_COALESCE_MAX_RULES];
+};
+
+struct mwifiex_ds_tdls_oper {
+       u16 tdls_action;
+       u8 peer_mac[ETH_ALEN];
+       u16 capability;
+       u8 qos_info;
+       u8 *ext_capab;
+       u8 ext_capab_len;
+       u8 *supp_rates;
+       u8 supp_rates_len;
+       u8 *ht_capab;
+};
+
+#endif /* !_MWIFIEX_IOCTL_H_ */
diff --git a/drivers/net/wireless/marvell/mwifiex/join.c b/drivers/net/wireless/marvell/mwifiex/join.c
new file mode 100644 (file)
index 0000000..3cda1f9
--- /dev/null
@@ -0,0 +1,1525 @@
+/*
+ * Marvell Wireless LAN device driver: association and ad-hoc start/join
+ *
+ * Copyright (C) 2011-2014, Marvell International Ltd.
+ *
+ * This software file (the "File") is distributed by Marvell International
+ * Ltd. under the terms of the GNU General Public License Version 2, June 1991
+ * (the "License").  You may use, redistribute and/or modify this File in
+ * accordance with the terms and conditions of the License, a copy of which
+ * is available by writing to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the
+ * worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
+ *
+ * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
+ * ARE EXPRESSLY DISCLAIMED.  The License provides additional details about
+ * this warranty disclaimer.
+ */
+
+#include "decl.h"
+#include "ioctl.h"
+#include "util.h"
+#include "fw.h"
+#include "main.h"
+#include "wmm.h"
+#include "11n.h"
+#include "11ac.h"
+
+#define CAPINFO_MASK    (~(BIT(15) | BIT(14) | BIT(12) | BIT(11) | BIT(9)))
+
+/*
+ * Append a generic IE as a pass through TLV to a TLV buffer.
+ *
+ * This function is called from the network join command preparation routine.
+ *
+ * If the IE buffer has been setup by the application, this routine appends
+ * the buffer as a pass through TLV type to the request.
+ */
+static int
+mwifiex_cmd_append_generic_ie(struct mwifiex_private *priv, u8 **buffer)
+{
+       int ret_len = 0;
+       struct mwifiex_ie_types_header ie_header;
+
+       /* Null Checks */
+       if (!buffer)
+               return 0;
+       if (!(*buffer))
+               return 0;
+
+       /*
+        * If there is a generic ie buffer setup, append it to the return
+        *   parameter buffer pointer.
+        */
+       if (priv->gen_ie_buf_len) {
+               mwifiex_dbg(priv->adapter, INFO,
+                           "info: %s: append generic ie len %d to %p\n",
+                           __func__, priv->gen_ie_buf_len, *buffer);
+
+               /* Wrap the generic IE buffer with a pass through TLV type */
+               ie_header.type = cpu_to_le16(TLV_TYPE_PASSTHROUGH);
+               ie_header.len = cpu_to_le16(priv->gen_ie_buf_len);
+               memcpy(*buffer, &ie_header, sizeof(ie_header));
+
+               /* Increment the return size and the return buffer pointer
+                  param */
+               *buffer += sizeof(ie_header);
+               ret_len += sizeof(ie_header);
+
+               /* Copy the generic IE buffer to the output buffer, advance
+                  pointer */
+               memcpy(*buffer, priv->gen_ie_buf, priv->gen_ie_buf_len);
+
+               /* Increment the return size and the return buffer pointer
+                  param */
+               *buffer += priv->gen_ie_buf_len;
+               ret_len += priv->gen_ie_buf_len;
+
+               /* Reset the generic IE buffer */
+               priv->gen_ie_buf_len = 0;
+       }
+
+       /* return the length appended to the buffer */
+       return ret_len;
+}
+
+/*
+ * Append TSF tracking info from the scan table for the target AP.
+ *
+ * This function is called from the network join command preparation routine.
+ *
+ * The TSF table TSF sent to the firmware contains two TSF values:
+ *      - The TSF of the target AP from its previous beacon/probe response
+ *      - The TSF timestamp of our local MAC at the time we observed the
+ *        beacon/probe response.
+ *
+ * The firmware uses the timestamp values to set an initial TSF value
+ * in the MAC for the new association after a reassociation attempt.
+ */
+static int
+mwifiex_cmd_append_tsf_tlv(struct mwifiex_private *priv, u8 **buffer,
+                          struct mwifiex_bssdescriptor *bss_desc)
+{
+       struct mwifiex_ie_types_tsf_timestamp tsf_tlv;
+       __le64 tsf_val;
+
+       /* Null Checks */
+       if (buffer == NULL)
+               return 0;
+       if (*buffer == NULL)
+               return 0;
+
+       memset(&tsf_tlv, 0x00, sizeof(struct mwifiex_ie_types_tsf_timestamp));
+
+       tsf_tlv.header.type = cpu_to_le16(TLV_TYPE_TSFTIMESTAMP);
+       tsf_tlv.header.len = cpu_to_le16(2 * sizeof(tsf_val));
+
+       memcpy(*buffer, &tsf_tlv, sizeof(tsf_tlv.header));
+       *buffer += sizeof(tsf_tlv.header);
+
+       /* TSF at the time when beacon/probe_response was received */
+       tsf_val = cpu_to_le64(bss_desc->fw_tsf);
+       memcpy(*buffer, &tsf_val, sizeof(tsf_val));
+       *buffer += sizeof(tsf_val);
+
+       tsf_val = cpu_to_le64(bss_desc->timestamp);
+
+       mwifiex_dbg(priv->adapter, INFO,
+                   "info: %s: TSF offset calc: %016llx - %016llx\n",
+                   __func__, bss_desc->timestamp, bss_desc->fw_tsf);
+
+       memcpy(*buffer, &tsf_val, sizeof(tsf_val));
+       *buffer += sizeof(tsf_val);
+
+       return sizeof(tsf_tlv.header) + (2 * sizeof(tsf_val));
+}
+
+/*
+ * This function finds out the common rates between rate1 and rate2.
+ *
+ * It will fill common rates in rate1 as output if found.
+ *
+ * NOTE: Setting the MSB of the basic rates needs to be taken
+ * care of, either before or after calling this function.
+ */
+static int mwifiex_get_common_rates(struct mwifiex_private *priv, u8 *rate1,
+                                   u32 rate1_size, u8 *rate2, u32 rate2_size)
+{
+       int ret;
+       u8 *ptr = rate1, *tmp;
+       u32 i, j;
+
+       tmp = kmemdup(rate1, rate1_size, GFP_KERNEL);
+       if (!tmp) {
+               mwifiex_dbg(priv->adapter, ERROR, "failed to alloc tmp buf\n");
+               return -ENOMEM;
+       }
+
+       memset(rate1, 0, rate1_size);
+
+       for (i = 0; i < rate2_size && rate2[i]; i++) {
+               for (j = 0; j < rate1_size && tmp[j]; j++) {
+                       /* Check common rate, excluding the bit for
+                          basic rate */
+                       if ((rate2[i] & 0x7F) == (tmp[j] & 0x7F)) {
+                               *rate1++ = tmp[j];
+                               break;
+                       }
+               }
+       }
+
+       mwifiex_dbg(priv->adapter, INFO, "info: Tx data rate set to %#x\n",
+                   priv->data_rate);
+
+       if (!priv->is_data_rate_auto) {
+               while (*ptr) {
+                       if ((*ptr & 0x7f) == priv->data_rate) {
+                               ret = 0;
+                               goto done;
+                       }
+                       ptr++;
+               }
+               mwifiex_dbg(priv->adapter, ERROR,
+                           "previously set fixed data rate %#x\t"
+                           "is not compatible with the network\n",
+                           priv->data_rate);
+
+               ret = -1;
+               goto done;
+       }
+
+       ret = 0;
+done:
+       kfree(tmp);
+       return ret;
+}
+
+/*
+ * This function creates the intersection of the rates supported by a
+ * target BSS and our adapter settings for use in an assoc/join command.
+ */
+static int
+mwifiex_setup_rates_from_bssdesc(struct mwifiex_private *priv,
+                                struct mwifiex_bssdescriptor *bss_desc,
+                                u8 *out_rates, u32 *out_rates_size)
+{
+       u8 card_rates[MWIFIEX_SUPPORTED_RATES];
+       u32 card_rates_size;
+
+       /* Copy AP supported rates */
+       memcpy(out_rates, bss_desc->supported_rates, MWIFIEX_SUPPORTED_RATES);
+       /* Get the STA supported rates */
+       card_rates_size = mwifiex_get_active_data_rates(priv, card_rates);
+       /* Get the common rates between AP and STA supported rates */
+       if (mwifiex_get_common_rates(priv, out_rates, MWIFIEX_SUPPORTED_RATES,
+                                    card_rates, card_rates_size)) {
+               *out_rates_size = 0;
+               mwifiex_dbg(priv->adapter, ERROR,
+                           "%s: cannot get common rates\n",
+                           __func__);
+               return -1;
+       }
+
+       *out_rates_size =
+               min_t(size_t, strlen(out_rates), MWIFIEX_SUPPORTED_RATES);
+
+       return 0;
+}
+
+/*
+ * This function appends a WPS IE. It is called from the network join command
+ * preparation routine.
+ *
+ * If the IE buffer has been setup by the application, this routine appends
+ * the buffer as a WPS TLV type to the request.
+ */
+static int
+mwifiex_cmd_append_wps_ie(struct mwifiex_private *priv, u8 **buffer)
+{
+       int retLen = 0;
+       struct mwifiex_ie_types_header ie_header;
+
+       if (!buffer || !*buffer)
+               return 0;
+
+       /*
+        * If there is a wps ie buffer setup, append it to the return
+        * parameter buffer pointer.
+        */
+       if (priv->wps_ie_len) {
+               mwifiex_dbg(priv->adapter, CMD,
+                           "cmd: append wps ie %d to %p\n",
+                           priv->wps_ie_len, *buffer);
+
+               /* Wrap the generic IE buffer with a pass through TLV type */
+               ie_header.type = cpu_to_le16(TLV_TYPE_MGMT_IE);
+               ie_header.len = cpu_to_le16(priv->wps_ie_len);
+               memcpy(*buffer, &ie_header, sizeof(ie_header));
+               *buffer += sizeof(ie_header);
+               retLen += sizeof(ie_header);
+
+               memcpy(*buffer, priv->wps_ie, priv->wps_ie_len);
+               *buffer += priv->wps_ie_len;
+               retLen += priv->wps_ie_len;
+
+       }
+
+       kfree(priv->wps_ie);
+       priv->wps_ie_len = 0;
+       return retLen;
+}
+
+/*
+ * This function appends a WAPI IE.
+ *
+ * This function is called from the network join command preparation routine.
+ *
+ * If the IE buffer has been setup by the application, this routine appends
+ * the buffer as a WAPI TLV type to the request.
+ */
+static int
+mwifiex_cmd_append_wapi_ie(struct mwifiex_private *priv, u8 **buffer)
+{
+       int retLen = 0;
+       struct mwifiex_ie_types_header ie_header;
+
+       /* Null Checks */
+       if (buffer == NULL)
+               return 0;
+       if (*buffer == NULL)
+               return 0;
+
+       /*
+        * If there is a wapi ie buffer setup, append it to the return
+        *   parameter buffer pointer.
+        */
+       if (priv->wapi_ie_len) {
+               mwifiex_dbg(priv->adapter, CMD,
+                           "cmd: append wapi ie %d to %p\n",
+                           priv->wapi_ie_len, *buffer);
+
+               /* Wrap the generic IE buffer with a pass through TLV type */
+               ie_header.type = cpu_to_le16(TLV_TYPE_WAPI_IE);
+               ie_header.len = cpu_to_le16(priv->wapi_ie_len);
+               memcpy(*buffer, &ie_header, sizeof(ie_header));
+
+               /* Increment the return size and the return buffer pointer
+                  param */
+               *buffer += sizeof(ie_header);
+               retLen += sizeof(ie_header);
+
+               /* Copy the wapi IE buffer to the output buffer, advance
+                  pointer */
+               memcpy(*buffer, priv->wapi_ie, priv->wapi_ie_len);
+
+               /* Increment the return size and the return buffer pointer
+                  param */
+               *buffer += priv->wapi_ie_len;
+               retLen += priv->wapi_ie_len;
+
+       }
+       /* return the length appended to the buffer */
+       return retLen;
+}
+
+/*
+ * This function appends rsn ie tlv for wpa/wpa2 security modes.
+ * It is called from the network join command preparation routine.
+ */
+static int mwifiex_append_rsn_ie_wpa_wpa2(struct mwifiex_private *priv,
+                                         u8 **buffer)
+{
+       struct mwifiex_ie_types_rsn_param_set *rsn_ie_tlv;
+       int rsn_ie_len;
+
+       if (!buffer || !(*buffer))
+               return 0;
+
+       rsn_ie_tlv = (struct mwifiex_ie_types_rsn_param_set *) (*buffer);
+       rsn_ie_tlv->header.type = cpu_to_le16((u16) priv->wpa_ie[0]);
+       rsn_ie_tlv->header.type = cpu_to_le16(
+                                le16_to_cpu(rsn_ie_tlv->header.type) & 0x00FF);
+       rsn_ie_tlv->header.len = cpu_to_le16((u16) priv->wpa_ie[1]);
+       rsn_ie_tlv->header.len = cpu_to_le16(le16_to_cpu(rsn_ie_tlv->header.len)
+                                                        & 0x00FF);
+       if (le16_to_cpu(rsn_ie_tlv->header.len) <= (sizeof(priv->wpa_ie) - 2))
+               memcpy(rsn_ie_tlv->rsn_ie, &priv->wpa_ie[2],
+                      le16_to_cpu(rsn_ie_tlv->header.len));
+       else
+               return -1;
+
+       rsn_ie_len = sizeof(rsn_ie_tlv->header) +
+                                       le16_to_cpu(rsn_ie_tlv->header.len);
+       *buffer += rsn_ie_len;
+
+       return rsn_ie_len;
+}
+
+/*
+ * This function prepares command for association.
+ *
+ * This sets the following parameters -
+ *      - Peer MAC address
+ *      - Listen interval
+ *      - Beacon interval
+ *      - Capability information
+ *
+ * ...and the following TLVs, as required -
+ *      - SSID TLV
+ *      - PHY TLV
+ *      - SS TLV
+ *      - Rates TLV
+ *      - Authentication TLV
+ *      - Channel TLV
+ *      - WPA/WPA2 IE
+ *      - 11n TLV
+ *      - Vendor specific TLV
+ *      - WMM TLV
+ *      - WAPI IE
+ *      - Generic IE
+ *      - TSF TLV
+ *
+ * Preparation also includes -
+ *      - Setting command ID and proper size
+ *      - Ensuring correct endian-ness
+ */
+int mwifiex_cmd_802_11_associate(struct mwifiex_private *priv,
+                                struct host_cmd_ds_command *cmd,
+                                struct mwifiex_bssdescriptor *bss_desc)
+{
+       struct host_cmd_ds_802_11_associate *assoc = &cmd->params.associate;
+       struct mwifiex_ie_types_ssid_param_set *ssid_tlv;
+       struct mwifiex_ie_types_phy_param_set *phy_tlv;
+       struct mwifiex_ie_types_ss_param_set *ss_tlv;
+       struct mwifiex_ie_types_rates_param_set *rates_tlv;
+       struct mwifiex_ie_types_auth_type *auth_tlv;
+       struct mwifiex_ie_types_chan_list_param_set *chan_tlv;
+       u8 rates[MWIFIEX_SUPPORTED_RATES];
+       u32 rates_size;
+       u16 tmp_cap;
+       u8 *pos;
+       int rsn_ie_len = 0;
+
+       pos = (u8 *) assoc;
+
+       cmd->command = cpu_to_le16(HostCmd_CMD_802_11_ASSOCIATE);
+
+       /* Save so we know which BSS Desc to use in the response handler */
+       priv->attempted_bss_desc = bss_desc;
+
+       memcpy(assoc->peer_sta_addr,
+              bss_desc->mac_address, sizeof(assoc->peer_sta_addr));
+       pos += sizeof(assoc->peer_sta_addr);
+
+       /* Set the listen interval */
+       assoc->listen_interval = cpu_to_le16(priv->listen_interval);
+       /* Set the beacon period */
+       assoc->beacon_period = cpu_to_le16(bss_desc->beacon_period);
+
+       pos += sizeof(assoc->cap_info_bitmap);
+       pos += sizeof(assoc->listen_interval);
+       pos += sizeof(assoc->beacon_period);
+       pos += sizeof(assoc->dtim_period);
+
+       ssid_tlv = (struct mwifiex_ie_types_ssid_param_set *) pos;
+       ssid_tlv->header.type = cpu_to_le16(WLAN_EID_SSID);
+       ssid_tlv->header.len = cpu_to_le16((u16) bss_desc->ssid.ssid_len);
+       memcpy(ssid_tlv->ssid, bss_desc->ssid.ssid,
+              le16_to_cpu(ssid_tlv->header.len));
+       pos += sizeof(ssid_tlv->header) + le16_to_cpu(ssid_tlv->header.len);
+
+       phy_tlv = (struct mwifiex_ie_types_phy_param_set *) pos;
+       phy_tlv->header.type = cpu_to_le16(WLAN_EID_DS_PARAMS);
+       phy_tlv->header.len = cpu_to_le16(sizeof(phy_tlv->fh_ds.ds_param_set));
+       memcpy(&phy_tlv->fh_ds.ds_param_set,
+              &bss_desc->phy_param_set.ds_param_set.current_chan,
+              sizeof(phy_tlv->fh_ds.ds_param_set));
+       pos += sizeof(phy_tlv->header) + le16_to_cpu(phy_tlv->header.len);
+
+       ss_tlv = (struct mwifiex_ie_types_ss_param_set *) pos;
+       ss_tlv->header.type = cpu_to_le16(WLAN_EID_CF_PARAMS);
+       ss_tlv->header.len = cpu_to_le16(sizeof(ss_tlv->cf_ibss.cf_param_set));
+       pos += sizeof(ss_tlv->header) + le16_to_cpu(ss_tlv->header.len);
+
+       /* Get the common rates supported between the driver and the BSS Desc */
+       if (mwifiex_setup_rates_from_bssdesc
+           (priv, bss_desc, rates, &rates_size))
+               return -1;
+
+       /* Save the data rates into Current BSS state structure */
+       priv->curr_bss_params.num_of_rates = rates_size;
+       memcpy(&priv->curr_bss_params.data_rates, rates, rates_size);
+
+       /* Setup the Rates TLV in the association command */
+       rates_tlv = (struct mwifiex_ie_types_rates_param_set *) pos;
+       rates_tlv->header.type = cpu_to_le16(WLAN_EID_SUPP_RATES);
+       rates_tlv->header.len = cpu_to_le16((u16) rates_size);
+       memcpy(rates_tlv->rates, rates, rates_size);
+       pos += sizeof(rates_tlv->header) + rates_size;
+       mwifiex_dbg(priv->adapter, INFO, "info: ASSOC_CMD: rates size = %d\n",
+                   rates_size);
+
+       /* Add the Authentication type to be used for Auth frames */
+       auth_tlv = (struct mwifiex_ie_types_auth_type *) pos;
+       auth_tlv->header.type = cpu_to_le16(TLV_TYPE_AUTH_TYPE);
+       auth_tlv->header.len = cpu_to_le16(sizeof(auth_tlv->auth_type));
+       if (priv->sec_info.wep_enabled)
+               auth_tlv->auth_type = cpu_to_le16(
+                               (u16) priv->sec_info.authentication_mode);
+       else
+               auth_tlv->auth_type = cpu_to_le16(NL80211_AUTHTYPE_OPEN_SYSTEM);
+
+       pos += sizeof(auth_tlv->header) + le16_to_cpu(auth_tlv->header.len);
+
+       if (IS_SUPPORT_MULTI_BANDS(priv->adapter) &&
+           !(ISSUPP_11NENABLED(priv->adapter->fw_cap_info) &&
+           (!bss_desc->disable_11n) &&
+           (priv->adapter->config_bands & BAND_GN ||
+            priv->adapter->config_bands & BAND_AN) &&
+           (bss_desc->bcn_ht_cap)
+           )
+               ) {
+               /* Append a channel TLV for the channel the attempted AP was
+                  found on */
+               chan_tlv = (struct mwifiex_ie_types_chan_list_param_set *) pos;
+               chan_tlv->header.type = cpu_to_le16(TLV_TYPE_CHANLIST);
+               chan_tlv->header.len =
+                       cpu_to_le16(sizeof(struct mwifiex_chan_scan_param_set));
+
+               memset(chan_tlv->chan_scan_param, 0x00,
+                      sizeof(struct mwifiex_chan_scan_param_set));
+               chan_tlv->chan_scan_param[0].chan_number =
+                       (bss_desc->phy_param_set.ds_param_set.current_chan);
+               mwifiex_dbg(priv->adapter, INFO, "info: Assoc: TLV Chan = %d\n",
+                           chan_tlv->chan_scan_param[0].chan_number);
+
+               chan_tlv->chan_scan_param[0].radio_type =
+                       mwifiex_band_to_radio_type((u8) bss_desc->bss_band);
+
+               mwifiex_dbg(priv->adapter, INFO, "info: Assoc: TLV Band = %d\n",
+                           chan_tlv->chan_scan_param[0].radio_type);
+               pos += sizeof(chan_tlv->header) +
+                       sizeof(struct mwifiex_chan_scan_param_set);
+       }
+
+       if (!priv->wps.session_enable) {
+               if (priv->sec_info.wpa_enabled || priv->sec_info.wpa2_enabled)
+                       rsn_ie_len = mwifiex_append_rsn_ie_wpa_wpa2(priv, &pos);
+
+               if (rsn_ie_len == -1)
+                       return -1;
+       }
+
+       if (ISSUPP_11NENABLED(priv->adapter->fw_cap_info) &&
+           (!bss_desc->disable_11n) &&
+           (priv->adapter->config_bands & BAND_GN ||
+            priv->adapter->config_bands & BAND_AN))
+               mwifiex_cmd_append_11n_tlv(priv, bss_desc, &pos);
+
+       if (ISSUPP_11ACENABLED(priv->adapter->fw_cap_info) &&
+           !bss_desc->disable_11n && !bss_desc->disable_11ac &&
+           priv->adapter->config_bands & BAND_AAC)
+               mwifiex_cmd_append_11ac_tlv(priv, bss_desc, &pos);
+
+       /* Append vendor specific IE TLV */
+       mwifiex_cmd_append_vsie_tlv(priv, MWIFIEX_VSIE_MASK_ASSOC, &pos);
+
+       mwifiex_wmm_process_association_req(priv, &pos, &bss_desc->wmm_ie,
+                                           bss_desc->bcn_ht_cap);
+       if (priv->sec_info.wapi_enabled && priv->wapi_ie_len)
+               mwifiex_cmd_append_wapi_ie(priv, &pos);
+
+       if (priv->wps.session_enable && priv->wps_ie_len)
+               mwifiex_cmd_append_wps_ie(priv, &pos);
+
+       mwifiex_cmd_append_generic_ie(priv, &pos);
+
+       mwifiex_cmd_append_tsf_tlv(priv, &pos, bss_desc);
+
+       mwifiex_11h_process_join(priv, &pos, bss_desc);
+
+       cmd->size = cpu_to_le16((u16) (pos - (u8 *) assoc) + S_DS_GEN);
+
+       /* Set the Capability info at last */
+       tmp_cap = bss_desc->cap_info_bitmap;
+
+       if (priv->adapter->config_bands == BAND_B)
+               tmp_cap &= ~WLAN_CAPABILITY_SHORT_SLOT_TIME;
+
+       tmp_cap &= CAPINFO_MASK;
+       mwifiex_dbg(priv->adapter, INFO,
+                   "info: ASSOC_CMD: tmp_cap=%4X CAPINFO_MASK=%4lX\n",
+                   tmp_cap, CAPINFO_MASK);
+       assoc->cap_info_bitmap = cpu_to_le16(tmp_cap);
+
+       return 0;
+}
+
+static const char *assoc_failure_reason_to_str(u16 cap_info)
+{
+       switch (cap_info) {
+       case CONNECT_ERR_AUTH_ERR_STA_FAILURE:
+               return "CONNECT_ERR_AUTH_ERR_STA_FAILURE";
+       case CONNECT_ERR_AUTH_MSG_UNHANDLED:
+               return "CONNECT_ERR_AUTH_MSG_UNHANDLED";
+       case CONNECT_ERR_ASSOC_ERR_TIMEOUT:
+               return "CONNECT_ERR_ASSOC_ERR_TIMEOUT";
+       case CONNECT_ERR_ASSOC_ERR_AUTH_REFUSED:
+               return "CONNECT_ERR_ASSOC_ERR_AUTH_REFUSED";
+       case CONNECT_ERR_STA_FAILURE:
+               return "CONNECT_ERR_STA_FAILURE";
+       }
+
+       return "Unknown connect failure";
+}
+/*
+ * Association firmware command response handler
+ *
+ * The response buffer for the association command has the following
+ * memory layout.
+ *
+ * For cases where an association response was not received (indicated
+ * by the CapInfo and AId field):
+ *
+ *     .------------------------------------------------------------.
+ *     |  Header(4 * sizeof(t_u16)):  Standard command response hdr |
+ *     .------------------------------------------------------------.
+ *     |  cap_info/Error Return(t_u16):                             |
+ *     |           0xFFFF(-1): Internal error                       |
+ *     |           0xFFFE(-2): Authentication unhandled message     |
+ *     |           0xFFFD(-3): Authentication refused               |
+ *     |           0xFFFC(-4): Timeout waiting for AP response      |
+ *     .------------------------------------------------------------.
+ *     |  status_code(t_u16):                                       |
+ *     |        If cap_info is -1:                                  |
+ *     |           An internal firmware failure prevented the       |
+ *     |           command from being processed.  The status_code   |
+ *     |           will be set to 1.                                |
+ *     |                                                            |
+ *     |        If cap_info is -2:                                  |
+ *     |           An authentication frame was received but was     |
+ *     |           not handled by the firmware.  IEEE Status        |
+ *     |           code for the failure is returned.                |
+ *     |                                                            |
+ *     |        If cap_info is -3:                                  |
+ *     |           An authentication frame was received and the     |
+ *     |           status_code is the IEEE Status reported in the   |
+ *     |           response.                                        |
+ *     |                                                            |
+ *     |        If cap_info is -4:                                  |
+ *     |           (1) Association response timeout                 |
+ *     |           (2) Authentication response timeout              |
+ *     .------------------------------------------------------------.
+ *     |  a_id(t_u16): 0xFFFF                                       |
+ *     .------------------------------------------------------------.
+ *
+ *
+ * For cases where an association response was received, the IEEE
+ * standard association response frame is returned:
+ *
+ *     .------------------------------------------------------------.
+ *     |  Header(4 * sizeof(t_u16)):  Standard command response hdr |
+ *     .------------------------------------------------------------.
+ *     |  cap_info(t_u16): IEEE Capability                          |
+ *     .------------------------------------------------------------.
+ *     |  status_code(t_u16): IEEE Status Code                      |
+ *     .------------------------------------------------------------.
+ *     |  a_id(t_u16): IEEE Association ID                          |
+ *     .------------------------------------------------------------.
+ *     |  IEEE IEs(variable): Any received IEs comprising the       |
+ *     |                      remaining portion of a received       |
+ *     |                      association response frame.           |
+ *     .------------------------------------------------------------.
+ *
+ * For simplistic handling, the status_code field can be used to determine
+ * an association success (0) or failure (non-zero).
+ */
+int mwifiex_ret_802_11_associate(struct mwifiex_private *priv,
+                            struct host_cmd_ds_command *resp)
+{
+       struct mwifiex_adapter *adapter = priv->adapter;
+       int ret = 0;
+       struct ieee_types_assoc_rsp *assoc_rsp;
+       struct mwifiex_bssdescriptor *bss_desc;
+       bool enable_data = true;
+       u16 cap_info, status_code, aid;
+
+       assoc_rsp = (struct ieee_types_assoc_rsp *) &resp->params;
+
+       cap_info = le16_to_cpu(assoc_rsp->cap_info_bitmap);
+       status_code = le16_to_cpu(assoc_rsp->status_code);
+       aid = le16_to_cpu(assoc_rsp->a_id);
+
+       if ((aid & (BIT(15) | BIT(14))) != (BIT(15) | BIT(14)))
+               dev_err(priv->adapter->dev,
+                       "invalid AID value 0x%x; bits 15:14 not set\n",
+                       aid);
+
+       aid &= ~(BIT(15) | BIT(14));
+
+       priv->assoc_rsp_size = min(le16_to_cpu(resp->size) - S_DS_GEN,
+                                  sizeof(priv->assoc_rsp_buf));
+
+       memcpy(priv->assoc_rsp_buf, &resp->params, priv->assoc_rsp_size);
+
+       assoc_rsp->a_id = cpu_to_le16(aid);
+
+       if (status_code) {
+               priv->adapter->dbg.num_cmd_assoc_failure++;
+               mwifiex_dbg(priv->adapter, ERROR,
+                           "ASSOC_RESP: failed,\t"
+                           "status code=%d err=%#x a_id=%#x\n",
+                           status_code, cap_info,
+                           le16_to_cpu(assoc_rsp->a_id));
+
+               mwifiex_dbg(priv->adapter, ERROR, "assoc failure: reason %s\n",
+                           assoc_failure_reason_to_str(cap_info));
+               if (cap_info == CONNECT_ERR_ASSOC_ERR_TIMEOUT) {
+                       if (status_code == MWIFIEX_ASSOC_CMD_FAILURE_AUTH) {
+                               ret = WLAN_STATUS_AUTH_TIMEOUT;
+                               mwifiex_dbg(priv->adapter, ERROR,
+                                           "ASSOC_RESP: AUTH timeout\n");
+                       } else {
+                               ret = WLAN_STATUS_UNSPECIFIED_FAILURE;
+                               mwifiex_dbg(priv->adapter, ERROR,
+                                           "ASSOC_RESP: UNSPECIFIED failure\n");
+                       }
+               } else {
+                       ret = status_code;
+               }
+
+               goto done;
+       }
+
+       /* Send a Media Connected event, according to the Spec */
+       priv->media_connected = true;
+
+       priv->adapter->ps_state = PS_STATE_AWAKE;
+       priv->adapter->pps_uapsd_mode = false;
+       priv->adapter->tx_lock_flag = false;
+
+       /* Set the attempted BSSID Index to current */
+       bss_desc = priv->attempted_bss_desc;
+
+       mwifiex_dbg(priv->adapter, INFO, "info: ASSOC_RESP: %s\n",
+                   bss_desc->ssid.ssid);
+
+       /* Make a copy of current BSSID descriptor */
+       memcpy(&priv->curr_bss_params.bss_descriptor,
+              bss_desc, sizeof(struct mwifiex_bssdescriptor));
+
+       /* Update curr_bss_params */
+       priv->curr_bss_params.bss_descriptor.channel
+               = bss_desc->phy_param_set.ds_param_set.current_chan;
+
+       priv->curr_bss_params.band = (u8) bss_desc->bss_band;
+
+       if (bss_desc->wmm_ie.vend_hdr.element_id == WLAN_EID_VENDOR_SPECIFIC)
+               priv->curr_bss_params.wmm_enabled = true;
+       else
+               priv->curr_bss_params.wmm_enabled = false;
+
+       if ((priv->wmm_required || bss_desc->bcn_ht_cap) &&
+           priv->curr_bss_params.wmm_enabled)
+               priv->wmm_enabled = true;
+       else
+               priv->wmm_enabled = false;
+
+       priv->curr_bss_params.wmm_uapsd_enabled = false;
+
+       if (priv->wmm_enabled)
+               priv->curr_bss_params.wmm_uapsd_enabled
+                       = ((bss_desc->wmm_ie.qos_info_bitmap &
+                               IEEE80211_WMM_IE_AP_QOSINFO_UAPSD) ? 1 : 0);
+
+       mwifiex_dbg(priv->adapter, INFO,
+                   "info: ASSOC_RESP: curr_pkt_filter is %#x\n",
+                   priv->curr_pkt_filter);
+       if (priv->sec_info.wpa_enabled || priv->sec_info.wpa2_enabled)
+               priv->wpa_is_gtk_set = false;
+
+       if (priv->wmm_enabled) {
+               /* Don't re-enable carrier until we get the WMM_GET_STATUS
+                  event */
+               enable_data = false;
+       } else {
+               /* Since WMM is not enabled, setup the queues with the
+                  defaults */
+               mwifiex_wmm_setup_queue_priorities(priv, NULL);
+               mwifiex_wmm_setup_ac_downgrade(priv);
+       }
+
+       if (enable_data)
+               mwifiex_dbg(priv->adapter, INFO,
+                           "info: post association, re-enabling data flow\n");
+
+       /* Reset SNR/NF/RSSI values */
+       priv->data_rssi_last = 0;
+       priv->data_nf_last = 0;
+       priv->data_rssi_avg = 0;
+       priv->data_nf_avg = 0;
+       priv->bcn_rssi_last = 0;
+       priv->bcn_nf_last = 0;
+       priv->bcn_rssi_avg = 0;
+       priv->bcn_nf_avg = 0;
+       priv->rxpd_rate = 0;
+       priv->rxpd_htinfo = 0;
+
+       mwifiex_save_curr_bcn(priv);
+
+       priv->adapter->dbg.num_cmd_assoc_success++;
+
+       mwifiex_dbg(priv->adapter, INFO, "info: ASSOC_RESP: associated\n");
+
+       /* Add the ra_list here for infra mode as there will be only 1 ra
+          always */
+       mwifiex_ralist_add(priv,
+                          priv->curr_bss_params.bss_descriptor.mac_address);
+
+       if (!netif_carrier_ok(priv->netdev))
+               netif_carrier_on(priv->netdev);
+       mwifiex_wake_up_net_dev_queue(priv->netdev, adapter);
+
+       if (priv->sec_info.wpa_enabled || priv->sec_info.wpa2_enabled)
+               priv->scan_block = true;
+       else
+               priv->port_open = true;
+
+done:
+       /* Need to indicate IOCTL complete */
+       if (adapter->curr_cmd->wait_q_enabled) {
+               if (ret)
+                       adapter->cmd_wait_q.status = -1;
+               else
+                       adapter->cmd_wait_q.status = 0;
+       }
+
+       return ret;
+}
+
+/*
+ * This function prepares command for ad-hoc start.
+ *
+ * Driver will fill up SSID, BSS mode, IBSS parameters, physical
+ * parameters, probe delay, and capability information. Firmware
+ * will fill up beacon period, basic rates and operational rates.
+ *
+ * In addition, the following TLVs are added -
+ *      - Channel TLV
+ *      - Vendor specific IE
+ *      - WPA/WPA2 IE
+ *      - HT Capabilities IE
+ *      - HT Information IE
+ *
+ * Preparation also includes -
+ *      - Setting command ID and proper size
+ *      - Ensuring correct endian-ness
+ */
+int
+mwifiex_cmd_802_11_ad_hoc_start(struct mwifiex_private *priv,
+                               struct host_cmd_ds_command *cmd,
+                               struct cfg80211_ssid *req_ssid)
+{
+       int rsn_ie_len = 0;
+       struct mwifiex_adapter *adapter = priv->adapter;
+       struct host_cmd_ds_802_11_ad_hoc_start *adhoc_start =
+               &cmd->params.adhoc_start;
+       struct mwifiex_bssdescriptor *bss_desc;
+       u32 cmd_append_size = 0;
+       u32 i;
+       u16 tmp_cap;
+       struct mwifiex_ie_types_chan_list_param_set *chan_tlv;
+       u8 radio_type;
+
+       struct mwifiex_ie_types_htcap *ht_cap;
+       struct mwifiex_ie_types_htinfo *ht_info;
+       u8 *pos = (u8 *) adhoc_start +
+                       sizeof(struct host_cmd_ds_802_11_ad_hoc_start);
+
+       if (!adapter)
+               return -1;
+
+       cmd->command = cpu_to_le16(HostCmd_CMD_802_11_AD_HOC_START);
+
+       bss_desc = &priv->curr_bss_params.bss_descriptor;
+       priv->attempted_bss_desc = bss_desc;
+
+       /*
+        * Fill in the parameters for 2 data structures:
+        *   1. struct host_cmd_ds_802_11_ad_hoc_start command
+        *   2. bss_desc
+        * Driver will fill up SSID, bss_mode,IBSS param, Physical Param,
+        * probe delay, and Cap info.
+        * Firmware will fill up beacon period, Basic rates
+        * and operational rates.
+        */
+
+       memset(adhoc_start->ssid, 0, IEEE80211_MAX_SSID_LEN);
+
+       memcpy(adhoc_start->ssid, req_ssid->ssid, req_ssid->ssid_len);
+
+       mwifiex_dbg(adapter, INFO, "info: ADHOC_S_CMD: SSID = %s\n",
+                   adhoc_start->ssid);
+
+       memset(bss_desc->ssid.ssid, 0, IEEE80211_MAX_SSID_LEN);
+       memcpy(bss_desc->ssid.ssid, req_ssid->ssid, req_ssid->ssid_len);
+
+       bss_desc->ssid.ssid_len = req_ssid->ssid_len;
+
+       /* Set the BSS mode */
+       adhoc_start->bss_mode = HostCmd_BSS_MODE_IBSS;
+       bss_desc->bss_mode = NL80211_IFTYPE_ADHOC;
+       adhoc_start->beacon_period = cpu_to_le16(priv->beacon_period);
+       bss_desc->beacon_period = priv->beacon_period;
+
+       /* Set Physical param set */
+/* Parameter IE Id */
+#define DS_PARA_IE_ID   3
+/* Parameter IE length */
+#define DS_PARA_IE_LEN  1
+
+       adhoc_start->phy_param_set.ds_param_set.element_id = DS_PARA_IE_ID;
+       adhoc_start->phy_param_set.ds_param_set.len = DS_PARA_IE_LEN;
+
+       if (!mwifiex_get_cfp(priv, adapter->adhoc_start_band,
+                            (u16) priv->adhoc_channel, 0)) {
+               struct mwifiex_chan_freq_power *cfp;
+               cfp = mwifiex_get_cfp(priv, adapter->adhoc_start_band,
+                                     FIRST_VALID_CHANNEL, 0);
+               if (cfp)
+                       priv->adhoc_channel = (u8) cfp->channel;
+       }
+
+       if (!priv->adhoc_channel) {
+               mwifiex_dbg(adapter, ERROR,
+                           "ADHOC_S_CMD: adhoc_channel cannot be 0\n");
+               return -1;
+       }
+
+       mwifiex_dbg(adapter, INFO,
+                   "info: ADHOC_S_CMD: creating ADHOC on channel %d\n",
+                   priv->adhoc_channel);
+
+       priv->curr_bss_params.bss_descriptor.channel = priv->adhoc_channel;
+       priv->curr_bss_params.band = adapter->adhoc_start_band;
+
+       bss_desc->channel = priv->adhoc_channel;
+       adhoc_start->phy_param_set.ds_param_set.current_chan =
+               priv->adhoc_channel;
+
+       memcpy(&bss_desc->phy_param_set, &adhoc_start->phy_param_set,
+              sizeof(union ieee_types_phy_param_set));
+
+       /* Set IBSS param set */
+/* IBSS parameter IE Id */
+#define IBSS_PARA_IE_ID   6
+/* IBSS parameter IE length */
+#define IBSS_PARA_IE_LEN  2
+
+       adhoc_start->ss_param_set.ibss_param_set.element_id = IBSS_PARA_IE_ID;
+       adhoc_start->ss_param_set.ibss_param_set.len = IBSS_PARA_IE_LEN;
+       adhoc_start->ss_param_set.ibss_param_set.atim_window
+                                       = cpu_to_le16(priv->atim_window);
+       memcpy(&bss_desc->ss_param_set, &adhoc_start->ss_param_set,
+              sizeof(union ieee_types_ss_param_set));
+
+       /* Set Capability info */
+       bss_desc->cap_info_bitmap |= WLAN_CAPABILITY_IBSS;
+       tmp_cap = WLAN_CAPABILITY_IBSS;
+
+       /* Set up privacy in bss_desc */
+       if (priv->sec_info.encryption_mode) {
+               /* Ad-Hoc capability privacy on */
+               mwifiex_dbg(adapter, INFO,
+                           "info: ADHOC_S_CMD: wep_status set privacy to WEP\n");
+               bss_desc->privacy = MWIFIEX_802_11_PRIV_FILTER_8021X_WEP;
+               tmp_cap |= WLAN_CAPABILITY_PRIVACY;
+       } else {
+               mwifiex_dbg(adapter, INFO,
+                           "info: ADHOC_S_CMD: wep_status NOT set,\t"
+                           "setting privacy to ACCEPT ALL\n");
+               bss_desc->privacy = MWIFIEX_802_11_PRIV_FILTER_ACCEPT_ALL;
+       }
+
+       memset(adhoc_start->data_rate, 0, sizeof(adhoc_start->data_rate));
+       mwifiex_get_active_data_rates(priv, adhoc_start->data_rate);
+       if ((adapter->adhoc_start_band & BAND_G) &&
+           (priv->curr_pkt_filter & HostCmd_ACT_MAC_ADHOC_G_PROTECTION_ON)) {
+               if (mwifiex_send_cmd(priv, HostCmd_CMD_MAC_CONTROL,
+                                    HostCmd_ACT_GEN_SET, 0,
+                                    &priv->curr_pkt_filter, false)) {
+                       mwifiex_dbg(adapter, ERROR,
+                                   "ADHOC_S_CMD: G Protection config failed\n");
+                       return -1;
+               }
+       }
+       /* Find the last non zero */
+       for (i = 0; i < sizeof(adhoc_start->data_rate); i++)
+               if (!adhoc_start->data_rate[i])
+                       break;
+
+       priv->curr_bss_params.num_of_rates = i;
+
+       /* Copy the ad-hoc creating rates into Current BSS rate structure */
+       memcpy(&priv->curr_bss_params.data_rates,
+              &adhoc_start->data_rate, priv->curr_bss_params.num_of_rates);
+
+       mwifiex_dbg(adapter, INFO, "info: ADHOC_S_CMD: rates=%4ph\n",
+                   adhoc_start->data_rate);
+
+       mwifiex_dbg(adapter, INFO, "info: ADHOC_S_CMD: AD-HOC Start command is ready\n");
+
+       if (IS_SUPPORT_MULTI_BANDS(adapter)) {
+               /* Append a channel TLV */
+               chan_tlv = (struct mwifiex_ie_types_chan_list_param_set *) pos;
+               chan_tlv->header.type = cpu_to_le16(TLV_TYPE_CHANLIST);
+               chan_tlv->header.len =
+                       cpu_to_le16(sizeof(struct mwifiex_chan_scan_param_set));
+
+               memset(chan_tlv->chan_scan_param, 0x00,
+                      sizeof(struct mwifiex_chan_scan_param_set));
+               chan_tlv->chan_scan_param[0].chan_number =
+                       (u8) priv->curr_bss_params.bss_descriptor.channel;
+
+               mwifiex_dbg(adapter, INFO, "info: ADHOC_S_CMD: TLV Chan = %d\n",
+                           chan_tlv->chan_scan_param[0].chan_number);
+
+               chan_tlv->chan_scan_param[0].radio_type
+                      = mwifiex_band_to_radio_type(priv->curr_bss_params.band);
+               if (adapter->adhoc_start_band & BAND_GN ||
+                   adapter->adhoc_start_band & BAND_AN) {
+                       if (adapter->sec_chan_offset ==
+                                           IEEE80211_HT_PARAM_CHA_SEC_ABOVE)
+                               chan_tlv->chan_scan_param[0].radio_type |=
+                                       (IEEE80211_HT_PARAM_CHA_SEC_ABOVE << 4);
+                       else if (adapter->sec_chan_offset ==
+                                           IEEE80211_HT_PARAM_CHA_SEC_BELOW)
+                               chan_tlv->chan_scan_param[0].radio_type |=
+                                       (IEEE80211_HT_PARAM_CHA_SEC_BELOW << 4);
+               }
+               mwifiex_dbg(adapter, INFO, "info: ADHOC_S_CMD: TLV Band = %d\n",
+                           chan_tlv->chan_scan_param[0].radio_type);
+               pos += sizeof(chan_tlv->header) +
+                       sizeof(struct mwifiex_chan_scan_param_set);
+               cmd_append_size +=
+                       sizeof(chan_tlv->header) +
+                       sizeof(struct mwifiex_chan_scan_param_set);
+       }
+
+       /* Append vendor specific IE TLV */
+       cmd_append_size += mwifiex_cmd_append_vsie_tlv(priv,
+                               MWIFIEX_VSIE_MASK_ADHOC, &pos);
+
+       if (priv->sec_info.wpa_enabled) {
+               rsn_ie_len = mwifiex_append_rsn_ie_wpa_wpa2(priv, &pos);
+               if (rsn_ie_len == -1)
+                       return -1;
+               cmd_append_size += rsn_ie_len;
+       }
+
+       if (adapter->adhoc_11n_enabled) {
+               /* Fill HT CAPABILITY */
+               ht_cap = (struct mwifiex_ie_types_htcap *) pos;
+               memset(ht_cap, 0, sizeof(struct mwifiex_ie_types_htcap));
+               ht_cap->header.type = cpu_to_le16(WLAN_EID_HT_CAPABILITY);
+               ht_cap->header.len =
+                      cpu_to_le16(sizeof(struct ieee80211_ht_cap));
+               radio_type = mwifiex_band_to_radio_type(
+                                       priv->adapter->config_bands);
+               mwifiex_fill_cap_info(priv, radio_type, &ht_cap->ht_cap);
+
+               if (adapter->sec_chan_offset ==
+                                       IEEE80211_HT_PARAM_CHA_SEC_NONE) {
+                       u16 tmp_ht_cap;
+
+                       tmp_ht_cap = le16_to_cpu(ht_cap->ht_cap.cap_info);
+                       tmp_ht_cap &= ~IEEE80211_HT_CAP_SUP_WIDTH_20_40;
+                       tmp_ht_cap &= ~IEEE80211_HT_CAP_SGI_40;
+                       ht_cap->ht_cap.cap_info = cpu_to_le16(tmp_ht_cap);
+               }
+
+               pos += sizeof(struct mwifiex_ie_types_htcap);
+               cmd_append_size += sizeof(struct mwifiex_ie_types_htcap);
+
+               /* Fill HT INFORMATION */
+               ht_info = (struct mwifiex_ie_types_htinfo *) pos;
+               memset(ht_info, 0, sizeof(struct mwifiex_ie_types_htinfo));
+               ht_info->header.type = cpu_to_le16(WLAN_EID_HT_OPERATION);
+               ht_info->header.len =
+                       cpu_to_le16(sizeof(struct ieee80211_ht_operation));
+
+               ht_info->ht_oper.primary_chan =
+                       (u8) priv->curr_bss_params.bss_descriptor.channel;
+               if (adapter->sec_chan_offset) {
+                       ht_info->ht_oper.ht_param = adapter->sec_chan_offset;
+                       ht_info->ht_oper.ht_param |=
+                                       IEEE80211_HT_PARAM_CHAN_WIDTH_ANY;
+               }
+               ht_info->ht_oper.operation_mode =
+                    cpu_to_le16(IEEE80211_HT_OP_MODE_NON_GF_STA_PRSNT);
+               ht_info->ht_oper.basic_set[0] = 0xff;
+               pos += sizeof(struct mwifiex_ie_types_htinfo);
+               cmd_append_size +=
+                               sizeof(struct mwifiex_ie_types_htinfo);
+       }
+
+       cmd->size =
+               cpu_to_le16((u16)(sizeof(struct host_cmd_ds_802_11_ad_hoc_start)
+                                 + S_DS_GEN + cmd_append_size));
+
+       if (adapter->adhoc_start_band == BAND_B)
+               tmp_cap &= ~WLAN_CAPABILITY_SHORT_SLOT_TIME;
+       else
+               tmp_cap |= WLAN_CAPABILITY_SHORT_SLOT_TIME;
+
+       adhoc_start->cap_info_bitmap = cpu_to_le16(tmp_cap);
+
+       return 0;
+}
+
+/*
+ * This function prepares command for ad-hoc join.
+ *
+ * Most of the parameters are set up by copying from the target BSS descriptor
+ * from the scan response.
+ *
+ * In addition, the following TLVs are added -
+ *      - Channel TLV
+ *      - Vendor specific IE
+ *      - WPA/WPA2 IE
+ *      - 11n IE
+ *
+ * Preparation also includes -
+ *      - Setting command ID and proper size
+ *      - Ensuring correct endian-ness
+ */
+int
+mwifiex_cmd_802_11_ad_hoc_join(struct mwifiex_private *priv,
+                              struct host_cmd_ds_command *cmd,
+                              struct mwifiex_bssdescriptor *bss_desc)
+{
+       int rsn_ie_len = 0;
+       struct host_cmd_ds_802_11_ad_hoc_join *adhoc_join =
+               &cmd->params.adhoc_join;
+       struct mwifiex_ie_types_chan_list_param_set *chan_tlv;
+       u32 cmd_append_size = 0;
+       u16 tmp_cap;
+       u32 i, rates_size = 0;
+       u16 curr_pkt_filter;
+       u8 *pos =
+               (u8 *) adhoc_join +
+               sizeof(struct host_cmd_ds_802_11_ad_hoc_join);
+
+/* Use G protection */
+#define USE_G_PROTECTION        0x02
+       if (bss_desc->erp_flags & USE_G_PROTECTION) {
+               curr_pkt_filter =
+                       priv->
+                       curr_pkt_filter | HostCmd_ACT_MAC_ADHOC_G_PROTECTION_ON;
+
+               if (mwifiex_send_cmd(priv, HostCmd_CMD_MAC_CONTROL,
+                                    HostCmd_ACT_GEN_SET, 0,
+                                    &curr_pkt_filter, false)) {
+                       mwifiex_dbg(priv->adapter, ERROR,
+                                   "ADHOC_J_CMD: G Protection config failed\n");
+                       return -1;
+               }
+       }
+
+       priv->attempted_bss_desc = bss_desc;
+
+       cmd->command = cpu_to_le16(HostCmd_CMD_802_11_AD_HOC_JOIN);
+
+       adhoc_join->bss_descriptor.bss_mode = HostCmd_BSS_MODE_IBSS;
+
+       adhoc_join->bss_descriptor.beacon_period
+               = cpu_to_le16(bss_desc->beacon_period);
+
+       memcpy(&adhoc_join->bss_descriptor.bssid,
+              &bss_desc->mac_address, ETH_ALEN);
+
+       memcpy(&adhoc_join->bss_descriptor.ssid,
+              &bss_desc->ssid.ssid, bss_desc->ssid.ssid_len);
+
+       memcpy(&adhoc_join->bss_descriptor.phy_param_set,
+              &bss_desc->phy_param_set,
+              sizeof(union ieee_types_phy_param_set));
+
+       memcpy(&adhoc_join->bss_descriptor.ss_param_set,
+              &bss_desc->ss_param_set, sizeof(union ieee_types_ss_param_set));
+
+       tmp_cap = bss_desc->cap_info_bitmap;
+
+       tmp_cap &= CAPINFO_MASK;
+
+       mwifiex_dbg(priv->adapter, INFO,
+                   "info: ADHOC_J_CMD: tmp_cap=%4X CAPINFO_MASK=%4lX\n",
+                   tmp_cap, CAPINFO_MASK);
+
+       /* Information on BSSID descriptor passed to FW */
+       mwifiex_dbg(priv->adapter, INFO,
+                   "info: ADHOC_J_CMD: BSSID=%pM, SSID='%s'\n",
+                   adhoc_join->bss_descriptor.bssid,
+                   adhoc_join->bss_descriptor.ssid);
+
+       for (i = 0; i < MWIFIEX_SUPPORTED_RATES &&
+                   bss_desc->supported_rates[i]; i++)
+               ;
+       rates_size = i;
+
+       /* Copy Data Rates from the Rates recorded in scan response */
+       memset(adhoc_join->bss_descriptor.data_rates, 0,
+              sizeof(adhoc_join->bss_descriptor.data_rates));
+       memcpy(adhoc_join->bss_descriptor.data_rates,
+              bss_desc->supported_rates, rates_size);
+
+       /* Copy the adhoc join rates into Current BSS state structure */
+       priv->curr_bss_params.num_of_rates = rates_size;
+       memcpy(&priv->curr_bss_params.data_rates, bss_desc->supported_rates,
+              rates_size);
+
+       /* Copy the channel information */
+       priv->curr_bss_params.bss_descriptor.channel = bss_desc->channel;
+       priv->curr_bss_params.band = (u8) bss_desc->bss_band;
+
+       if (priv->sec_info.wep_enabled || priv->sec_info.wpa_enabled)
+               tmp_cap |= WLAN_CAPABILITY_PRIVACY;
+
+       if (IS_SUPPORT_MULTI_BANDS(priv->adapter)) {
+               /* Append a channel TLV */
+               chan_tlv = (struct mwifiex_ie_types_chan_list_param_set *) pos;
+               chan_tlv->header.type = cpu_to_le16(TLV_TYPE_CHANLIST);
+               chan_tlv->header.len =
+                       cpu_to_le16(sizeof(struct mwifiex_chan_scan_param_set));
+
+               memset(chan_tlv->chan_scan_param, 0x00,
+                      sizeof(struct mwifiex_chan_scan_param_set));
+               chan_tlv->chan_scan_param[0].chan_number =
+                       (bss_desc->phy_param_set.ds_param_set.current_chan);
+               mwifiex_dbg(priv->adapter, INFO, "info: ADHOC_J_CMD: TLV Chan=%d\n",
+                           chan_tlv->chan_scan_param[0].chan_number);
+
+               chan_tlv->chan_scan_param[0].radio_type =
+                       mwifiex_band_to_radio_type((u8) bss_desc->bss_band);
+
+               mwifiex_dbg(priv->adapter, INFO, "info: ADHOC_J_CMD: TLV Band=%d\n",
+                           chan_tlv->chan_scan_param[0].radio_type);
+               pos += sizeof(chan_tlv->header) +
+                               sizeof(struct mwifiex_chan_scan_param_set);
+               cmd_append_size += sizeof(chan_tlv->header) +
+                               sizeof(struct mwifiex_chan_scan_param_set);
+       }
+
+       if (priv->sec_info.wpa_enabled)
+               rsn_ie_len = mwifiex_append_rsn_ie_wpa_wpa2(priv, &pos);
+       if (rsn_ie_len == -1)
+               return -1;
+       cmd_append_size += rsn_ie_len;
+
+       if (ISSUPP_11NENABLED(priv->adapter->fw_cap_info))
+               cmd_append_size += mwifiex_cmd_append_11n_tlv(priv,
+                       bss_desc, &pos);
+
+       /* Append vendor specific IE TLV */
+       cmd_append_size += mwifiex_cmd_append_vsie_tlv(priv,
+                       MWIFIEX_VSIE_MASK_ADHOC, &pos);
+
+       cmd->size = cpu_to_le16
+               ((u16) (sizeof(struct host_cmd_ds_802_11_ad_hoc_join)
+                       + S_DS_GEN + cmd_append_size));
+
+       adhoc_join->bss_descriptor.cap_info_bitmap = cpu_to_le16(tmp_cap);
+
+       return 0;
+}
+
+/*
+ * This function handles the command response of ad-hoc start and
+ * ad-hoc join.
+ *
+ * The function generates a device-connected event to notify
+ * the applications, in case of successful ad-hoc start/join, and
+ * saves the beacon buffer.
+ */
+int mwifiex_ret_802_11_ad_hoc(struct mwifiex_private *priv,
+                             struct host_cmd_ds_command *resp)
+{
+       int ret = 0;
+       struct mwifiex_adapter *adapter = priv->adapter;
+       struct host_cmd_ds_802_11_ad_hoc_result *adhoc_result;
+       struct mwifiex_bssdescriptor *bss_desc;
+       u16 reason_code;
+
+       adhoc_result = &resp->params.adhoc_result;
+
+       bss_desc = priv->attempted_bss_desc;
+
+       /* Join result code 0 --> SUCCESS */
+       reason_code = le16_to_cpu(resp->result);
+       if (reason_code) {
+               mwifiex_dbg(priv->adapter, ERROR, "ADHOC_RESP: failed\n");
+               if (priv->media_connected)
+                       mwifiex_reset_connect_state(priv, reason_code);
+
+               memset(&priv->curr_bss_params.bss_descriptor,
+                      0x00, sizeof(struct mwifiex_bssdescriptor));
+
+               ret = -1;
+               goto done;
+       }
+
+       /* Send a Media Connected event, according to the Spec */
+       priv->media_connected = true;
+
+       if (le16_to_cpu(resp->command) == HostCmd_CMD_802_11_AD_HOC_START) {
+               mwifiex_dbg(priv->adapter, INFO, "info: ADHOC_S_RESP %s\n",
+                           bss_desc->ssid.ssid);
+
+               /* Update the created network descriptor with the new BSSID */
+               memcpy(bss_desc->mac_address,
+                      adhoc_result->bssid, ETH_ALEN);
+
+               priv->adhoc_state = ADHOC_STARTED;
+       } else {
+               /*
+                * Now the join cmd should be successful.
+                * If BSSID has changed use SSID to compare instead of BSSID
+                */
+               mwifiex_dbg(priv->adapter, INFO,
+                           "info: ADHOC_J_RESP %s\n",
+                           bss_desc->ssid.ssid);
+
+               /*
+                * Make a copy of current BSSID descriptor, only needed for
+                * join since the current descriptor is already being used
+                * for adhoc start
+                */
+               memcpy(&priv->curr_bss_params.bss_descriptor,
+                      bss_desc, sizeof(struct mwifiex_bssdescriptor));
+
+               priv->adhoc_state = ADHOC_JOINED;
+       }
+
+       mwifiex_dbg(priv->adapter, INFO, "info: ADHOC_RESP: channel = %d\n",
+                   priv->adhoc_channel);
+       mwifiex_dbg(priv->adapter, INFO, "info: ADHOC_RESP: BSSID = %pM\n",
+                   priv->curr_bss_params.bss_descriptor.mac_address);
+
+       if (!netif_carrier_ok(priv->netdev))
+               netif_carrier_on(priv->netdev);
+       mwifiex_wake_up_net_dev_queue(priv->netdev, adapter);
+
+       mwifiex_save_curr_bcn(priv);
+
+done:
+       /* Need to indicate IOCTL complete */
+       if (adapter->curr_cmd->wait_q_enabled) {
+               if (ret)
+                       adapter->cmd_wait_q.status = -1;
+               else
+                       adapter->cmd_wait_q.status = 0;
+
+       }
+
+       return ret;
+}
+
+/*
+ * This function associates to a specific BSS discovered in a scan.
+ *
+ * It clears any past association response stored for application
+ * retrieval and calls the command preparation routine to send the
+ * command to firmware.
+ */
+int mwifiex_associate(struct mwifiex_private *priv,
+                     struct mwifiex_bssdescriptor *bss_desc)
+{
+       /* Return error if the adapter is not STA role or table entry
+        * is not marked as infra.
+        */
+       if ((GET_BSS_ROLE(priv) != MWIFIEX_BSS_ROLE_STA) ||
+           (bss_desc->bss_mode != NL80211_IFTYPE_STATION))
+               return -1;
+
+       if (ISSUPP_11ACENABLED(priv->adapter->fw_cap_info) &&
+           !bss_desc->disable_11n && !bss_desc->disable_11ac &&
+           priv->adapter->config_bands & BAND_AAC)
+               mwifiex_set_11ac_ba_params(priv);
+       else
+               mwifiex_set_ba_params(priv);
+
+       /* Clear any past association response stored for application
+          retrieval */
+       priv->assoc_rsp_size = 0;
+
+       return mwifiex_send_cmd(priv, HostCmd_CMD_802_11_ASSOCIATE,
+                               HostCmd_ACT_GEN_SET, 0, bss_desc, true);
+}
+
+/*
+ * This function starts an ad-hoc network.
+ *
+ * It calls the command preparation routine to send the command to firmware.
+ */
+int
+mwifiex_adhoc_start(struct mwifiex_private *priv,
+                   struct cfg80211_ssid *adhoc_ssid)
+{
+       mwifiex_dbg(priv->adapter, INFO, "info: Adhoc Channel = %d\n",
+                   priv->adhoc_channel);
+       mwifiex_dbg(priv->adapter, INFO, "info: curr_bss_params.channel = %d\n",
+                   priv->curr_bss_params.bss_descriptor.channel);
+       mwifiex_dbg(priv->adapter, INFO, "info: curr_bss_params.band = %d\n",
+                   priv->curr_bss_params.band);
+
+       if (ISSUPP_11ACENABLED(priv->adapter->fw_cap_info) &&
+           priv->adapter->config_bands & BAND_AAC)
+               mwifiex_set_11ac_ba_params(priv);
+       else
+               mwifiex_set_ba_params(priv);
+
+       return mwifiex_send_cmd(priv, HostCmd_CMD_802_11_AD_HOC_START,
+                               HostCmd_ACT_GEN_SET, 0, adhoc_ssid, true);
+}
+
+/*
+ * This function joins an ad-hoc network found in a previous scan.
+ *
+ * It calls the command preparation routine to send the command to firmware,
+ * if already not connected to the requested SSID.
+ */
+int mwifiex_adhoc_join(struct mwifiex_private *priv,
+                      struct mwifiex_bssdescriptor *bss_desc)
+{
+       mwifiex_dbg(priv->adapter, INFO,
+                   "info: adhoc join: curr_bss ssid =%s\n",
+                   priv->curr_bss_params.bss_descriptor.ssid.ssid);
+       mwifiex_dbg(priv->adapter, INFO,
+                   "info: adhoc join: curr_bss ssid_len =%u\n",
+                   priv->curr_bss_params.bss_descriptor.ssid.ssid_len);
+       mwifiex_dbg(priv->adapter, INFO, "info: adhoc join: ssid =%s\n",
+                   bss_desc->ssid.ssid);
+       mwifiex_dbg(priv->adapter, INFO, "info: adhoc join: ssid_len =%u\n",
+                   bss_desc->ssid.ssid_len);
+
+       /* Check if the requested SSID is already joined */
+       if (priv->curr_bss_params.bss_descriptor.ssid.ssid_len &&
+           !mwifiex_ssid_cmp(&bss_desc->ssid,
+                             &priv->curr_bss_params.bss_descriptor.ssid) &&
+           (priv->curr_bss_params.bss_descriptor.bss_mode ==
+                                                       NL80211_IFTYPE_ADHOC)) {
+               mwifiex_dbg(priv->adapter, INFO,
+                           "info: ADHOC_J_CMD: new ad-hoc SSID\t"
+                           "is the same as current; not attempting to re-join\n");
+               return -1;
+       }
+
+       if (ISSUPP_11ACENABLED(priv->adapter->fw_cap_info) &&
+           !bss_desc->disable_11n && !bss_desc->disable_11ac &&
+           priv->adapter->config_bands & BAND_AAC)
+               mwifiex_set_11ac_ba_params(priv);
+       else
+               mwifiex_set_ba_params(priv);
+
+       mwifiex_dbg(priv->adapter, INFO,
+                   "info: curr_bss_params.channel = %d\n",
+                   priv->curr_bss_params.bss_descriptor.channel);
+       mwifiex_dbg(priv->adapter, INFO,
+                   "info: curr_bss_params.band = %c\n",
+                   priv->curr_bss_params.band);
+
+       return mwifiex_send_cmd(priv, HostCmd_CMD_802_11_AD_HOC_JOIN,
+                               HostCmd_ACT_GEN_SET, 0, bss_desc, true);
+}
+
+/*
+ * This function deauthenticates/disconnects from infra network by sending
+ * deauthentication request.
+ */
+static int mwifiex_deauthenticate_infra(struct mwifiex_private *priv, u8 *mac)
+{
+       u8 mac_address[ETH_ALEN];
+       int ret;
+
+       if (!mac || is_zero_ether_addr(mac))
+               memcpy(mac_address,
+                      priv->curr_bss_params.bss_descriptor.mac_address,
+                      ETH_ALEN);
+       else
+               memcpy(mac_address, mac, ETH_ALEN);
+
+       ret = mwifiex_send_cmd(priv, HostCmd_CMD_802_11_DEAUTHENTICATE,
+                              HostCmd_ACT_GEN_SET, 0, mac_address, true);
+
+       return ret;
+}
+
+/*
+ * This function deauthenticates/disconnects from a BSS.
+ *
+ * In case of infra made, it sends deauthentication request, and
+ * in case of ad-hoc mode, a stop network request is sent to the firmware.
+ * In AP mode, a command to stop bss is sent to firmware.
+ */
+int mwifiex_deauthenticate(struct mwifiex_private *priv, u8 *mac)
+{
+       int ret = 0;
+
+       if (!priv->media_connected)
+               return 0;
+
+       switch (priv->bss_mode) {
+       case NL80211_IFTYPE_STATION:
+       case NL80211_IFTYPE_P2P_CLIENT:
+               ret = mwifiex_deauthenticate_infra(priv, mac);
+               if (ret)
+                       cfg80211_disconnected(priv->netdev, 0, NULL, 0,
+                                             true, GFP_KERNEL);
+               break;
+       case NL80211_IFTYPE_ADHOC:
+               return mwifiex_send_cmd(priv, HostCmd_CMD_802_11_AD_HOC_STOP,
+                                       HostCmd_ACT_GEN_SET, 0, NULL, true);
+       case NL80211_IFTYPE_AP:
+               return mwifiex_send_cmd(priv, HostCmd_CMD_UAP_BSS_STOP,
+                                       HostCmd_ACT_GEN_SET, 0, NULL, true);
+       default:
+               break;
+       }
+
+       return ret;
+}
+
+/* This function deauthenticates/disconnects from all BSS. */
+void mwifiex_deauthenticate_all(struct mwifiex_adapter *adapter)
+{
+       struct mwifiex_private *priv;
+       int i;
+
+       for (i = 0; i < adapter->priv_num; i++) {
+               priv = adapter->priv[i];
+               if (priv)
+                       mwifiex_deauthenticate(priv, NULL);
+       }
+}
+EXPORT_SYMBOL_GPL(mwifiex_deauthenticate_all);
+
+/*
+ * This function converts band to radio type used in channel TLV.
+ */
+u8
+mwifiex_band_to_radio_type(u8 band)
+{
+       switch (band) {
+       case BAND_A:
+       case BAND_AN:
+       case BAND_A | BAND_AN:
+       case BAND_A | BAND_AN | BAND_AAC:
+               return HostCmd_SCAN_RADIO_TYPE_A;
+       case BAND_B:
+       case BAND_G:
+       case BAND_B | BAND_G:
+       default:
+               return HostCmd_SCAN_RADIO_TYPE_BG;
+       }
+}
diff --git a/drivers/net/wireless/marvell/mwifiex/main.c b/drivers/net/wireless/marvell/mwifiex/main.c
new file mode 100644 (file)
index 0000000..969ca1e
--- /dev/null
@@ -0,0 +1,1552 @@
+/*
+ * Marvell Wireless LAN device driver: major functions
+ *
+ * Copyright (C) 2011-2014, Marvell International Ltd.
+ *
+ * This software file (the "File") is distributed by Marvell International
+ * Ltd. under the terms of the GNU General Public License Version 2, June 1991
+ * (the "License").  You may use, redistribute and/or modify this File in
+ * accordance with the terms and conditions of the License, a copy of which
+ * is available by writing to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the
+ * worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
+ *
+ * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
+ * ARE EXPRESSLY DISCLAIMED.  The License provides additional details about
+ * this warranty disclaimer.
+ */
+
+#include "main.h"
+#include "wmm.h"
+#include "cfg80211.h"
+#include "11n.h"
+
+#define VERSION        "1.0"
+
+static unsigned int debug_mask = MWIFIEX_DEFAULT_DEBUG_MASK;
+module_param(debug_mask, uint, 0);
+MODULE_PARM_DESC(debug_mask, "bitmap for debug flags");
+
+const char driver_version[] = "mwifiex " VERSION " (%s) ";
+static char *cal_data_cfg;
+module_param(cal_data_cfg, charp, 0);
+
+static unsigned short driver_mode;
+module_param(driver_mode, ushort, 0);
+MODULE_PARM_DESC(driver_mode,
+                "station=0x1(default), ap-sta=0x3, station-p2p=0x5, ap-sta-p2p=0x7");
+
+/*
+ * This function registers the device and performs all the necessary
+ * initializations.
+ *
+ * The following initialization operations are performed -
+ *      - Allocate adapter structure
+ *      - Save interface specific operations table in adapter
+ *      - Call interface specific initialization routine
+ *      - Allocate private structures
+ *      - Set default adapter structure parameters
+ *      - Initialize locks
+ *
+ * In case of any errors during inittialization, this function also ensures
+ * proper cleanup before exiting.
+ */
+static int mwifiex_register(void *card, struct mwifiex_if_ops *if_ops,
+                           void **padapter)
+{
+       struct mwifiex_adapter *adapter;
+       int i;
+
+       adapter = kzalloc(sizeof(struct mwifiex_adapter), GFP_KERNEL);
+       if (!adapter)
+               return -ENOMEM;
+
+       *padapter = adapter;
+       adapter->card = card;
+
+       /* Save interface specific operations in adapter */
+       memmove(&adapter->if_ops, if_ops, sizeof(struct mwifiex_if_ops));
+       adapter->debug_mask = debug_mask;
+
+       /* card specific initialization has been deferred until now .. */
+       if (adapter->if_ops.init_if)
+               if (adapter->if_ops.init_if(adapter))
+                       goto error;
+
+       adapter->priv_num = 0;
+
+       for (i = 0; i < MWIFIEX_MAX_BSS_NUM; i++) {
+               /* Allocate memory for private structure */
+               adapter->priv[i] =
+                       kzalloc(sizeof(struct mwifiex_private), GFP_KERNEL);
+               if (!adapter->priv[i])
+                       goto error;
+
+               adapter->priv[i]->adapter = adapter;
+               adapter->priv_num++;
+       }
+       mwifiex_init_lock_list(adapter);
+
+       setup_timer(&adapter->cmd_timer, mwifiex_cmd_timeout_func,
+                   (unsigned long)adapter);
+
+       return 0;
+
+error:
+       mwifiex_dbg(adapter, ERROR,
+                   "info: leave mwifiex_register with error\n");
+
+       for (i = 0; i < adapter->priv_num; i++)
+               kfree(adapter->priv[i]);
+
+       kfree(adapter);
+
+       return -1;
+}
+
+/*
+ * This function unregisters the device and performs all the necessary
+ * cleanups.
+ *
+ * The following cleanup operations are performed -
+ *      - Free the timers
+ *      - Free beacon buffers
+ *      - Free private structures
+ *      - Free adapter structure
+ */
+static int mwifiex_unregister(struct mwifiex_adapter *adapter)
+{
+       s32 i;
+
+       if (adapter->if_ops.cleanup_if)
+               adapter->if_ops.cleanup_if(adapter);
+
+       del_timer_sync(&adapter->cmd_timer);
+
+       /* Free private structures */
+       for (i = 0; i < adapter->priv_num; i++) {
+               if (adapter->priv[i]) {
+                       mwifiex_free_curr_bcn(adapter->priv[i]);
+                       kfree(adapter->priv[i]);
+               }
+       }
+
+       vfree(adapter->chan_stats);
+       kfree(adapter);
+       return 0;
+}
+
+void mwifiex_queue_main_work(struct mwifiex_adapter *adapter)
+{
+       unsigned long flags;
+
+       spin_lock_irqsave(&adapter->main_proc_lock, flags);
+       if (adapter->mwifiex_processing) {
+               adapter->more_task_flag = true;
+               spin_unlock_irqrestore(&adapter->main_proc_lock, flags);
+       } else {
+               spin_unlock_irqrestore(&adapter->main_proc_lock, flags);
+               queue_work(adapter->workqueue, &adapter->main_work);
+       }
+}
+EXPORT_SYMBOL_GPL(mwifiex_queue_main_work);
+
+static void mwifiex_queue_rx_work(struct mwifiex_adapter *adapter)
+{
+       unsigned long flags;
+
+       spin_lock_irqsave(&adapter->rx_proc_lock, flags);
+       if (adapter->rx_processing) {
+               spin_unlock_irqrestore(&adapter->rx_proc_lock, flags);
+       } else {
+               spin_unlock_irqrestore(&adapter->rx_proc_lock, flags);
+               queue_work(adapter->rx_workqueue, &adapter->rx_work);
+       }
+}
+
+static int mwifiex_process_rx(struct mwifiex_adapter *adapter)
+{
+       unsigned long flags;
+       struct sk_buff *skb;
+       struct mwifiex_rxinfo *rx_info;
+
+       spin_lock_irqsave(&adapter->rx_proc_lock, flags);
+       if (adapter->rx_processing || adapter->rx_locked) {
+               spin_unlock_irqrestore(&adapter->rx_proc_lock, flags);
+               goto exit_rx_proc;
+       } else {
+               adapter->rx_processing = true;
+               spin_unlock_irqrestore(&adapter->rx_proc_lock, flags);
+       }
+
+       /* Check for Rx data */
+       while ((skb = skb_dequeue(&adapter->rx_data_q))) {
+               atomic_dec(&adapter->rx_pending);
+               if ((adapter->delay_main_work ||
+                    adapter->iface_type == MWIFIEX_USB) &&
+                   (atomic_read(&adapter->rx_pending) < LOW_RX_PENDING)) {
+                       if (adapter->if_ops.submit_rem_rx_urbs)
+                               adapter->if_ops.submit_rem_rx_urbs(adapter);
+                       adapter->delay_main_work = false;
+                       mwifiex_queue_main_work(adapter);
+               }
+               rx_info = MWIFIEX_SKB_RXCB(skb);
+               if (rx_info->buf_type == MWIFIEX_TYPE_AGGR_DATA) {
+                       if (adapter->if_ops.deaggr_pkt)
+                               adapter->if_ops.deaggr_pkt(adapter, skb);
+                       dev_kfree_skb_any(skb);
+               } else {
+                       mwifiex_handle_rx_packet(adapter, skb);
+               }
+       }
+       spin_lock_irqsave(&adapter->rx_proc_lock, flags);
+       adapter->rx_processing = false;
+       spin_unlock_irqrestore(&adapter->rx_proc_lock, flags);
+
+exit_rx_proc:
+       return 0;
+}
+
+/*
+ * The main process.
+ *
+ * This function is the main procedure of the driver and handles various driver
+ * operations. It runs in a loop and provides the core functionalities.
+ *
+ * The main responsibilities of this function are -
+ *      - Ensure concurrency control
+ *      - Handle pending interrupts and call interrupt handlers
+ *      - Wake up the card if required
+ *      - Handle command responses and call response handlers
+ *      - Handle events and call event handlers
+ *      - Execute pending commands
+ *      - Transmit pending data packets
+ */
+int mwifiex_main_process(struct mwifiex_adapter *adapter)
+{
+       int ret = 0;
+       unsigned long flags;
+
+       spin_lock_irqsave(&adapter->main_proc_lock, flags);
+
+       /* Check if already processing */
+       if (adapter->mwifiex_processing || adapter->main_locked) {
+               adapter->more_task_flag = true;
+               spin_unlock_irqrestore(&adapter->main_proc_lock, flags);
+               goto exit_main_proc;
+       } else {
+               adapter->mwifiex_processing = true;
+               spin_unlock_irqrestore(&adapter->main_proc_lock, flags);
+       }
+process_start:
+       do {
+               if ((adapter->hw_status == MWIFIEX_HW_STATUS_CLOSING) ||
+                   (adapter->hw_status == MWIFIEX_HW_STATUS_NOT_READY))
+                       break;
+
+               /* For non-USB interfaces, If we process interrupts first, it
+                * would increase RX pending even further. Avoid this by
+                * checking if rx_pending has crossed high threshold and
+                * schedule rx work queue and then process interrupts.
+                * For USB interface, there are no interrupts. We already have
+                * HIGH_RX_PENDING check in usb.c
+                */
+               if (atomic_read(&adapter->rx_pending) >= HIGH_RX_PENDING &&
+                   adapter->iface_type != MWIFIEX_USB) {
+                       adapter->delay_main_work = true;
+                       mwifiex_queue_rx_work(adapter);
+                       break;
+               }
+
+               /* Handle pending interrupt if any */
+               if (adapter->int_status) {
+                       if (adapter->hs_activated)
+                               mwifiex_process_hs_config(adapter);
+                       if (adapter->if_ops.process_int_status)
+                               adapter->if_ops.process_int_status(adapter);
+               }
+
+               if (adapter->rx_work_enabled && adapter->data_received)
+                       mwifiex_queue_rx_work(adapter);
+
+               /* Need to wake up the card ? */
+               if ((adapter->ps_state == PS_STATE_SLEEP) &&
+                   (adapter->pm_wakeup_card_req &&
+                    !adapter->pm_wakeup_fw_try) &&
+                   (is_command_pending(adapter) ||
+                    !skb_queue_empty(&adapter->tx_data_q) ||
+                    !mwifiex_bypass_txlist_empty(adapter) ||
+                    !mwifiex_wmm_lists_empty(adapter))) {
+                       adapter->pm_wakeup_fw_try = true;
+                       mod_timer(&adapter->wakeup_timer, jiffies + (HZ*3));
+                       adapter->if_ops.wakeup(adapter);
+                       continue;
+               }
+
+               if (IS_CARD_RX_RCVD(adapter)) {
+                       adapter->data_received = false;
+                       adapter->pm_wakeup_fw_try = false;
+                       del_timer(&adapter->wakeup_timer);
+                       if (adapter->ps_state == PS_STATE_SLEEP)
+                               adapter->ps_state = PS_STATE_AWAKE;
+               } else {
+                       /* We have tried to wakeup the card already */
+                       if (adapter->pm_wakeup_fw_try)
+                               break;
+                       if (adapter->ps_state != PS_STATE_AWAKE)
+                               break;
+                       if (adapter->tx_lock_flag) {
+                               if (adapter->iface_type == MWIFIEX_USB) {
+                                       if (!adapter->usb_mc_setup)
+                                               break;
+                               } else
+                                       break;
+                       }
+
+                       if ((!adapter->scan_chan_gap_enabled &&
+                            adapter->scan_processing) || adapter->data_sent ||
+                            mwifiex_is_tdls_chan_switching
+                            (mwifiex_get_priv(adapter,
+                                              MWIFIEX_BSS_ROLE_STA)) ||
+                           (mwifiex_wmm_lists_empty(adapter) &&
+                            mwifiex_bypass_txlist_empty(adapter) &&
+                            skb_queue_empty(&adapter->tx_data_q))) {
+                               if (adapter->cmd_sent || adapter->curr_cmd ||
+                                       !mwifiex_is_send_cmd_allowed
+                                               (mwifiex_get_priv(adapter,
+                                               MWIFIEX_BSS_ROLE_STA)) ||
+                                   (!is_command_pending(adapter)))
+                                       break;
+                       }
+               }
+
+               /* Check for event */
+               if (adapter->event_received) {
+                       adapter->event_received = false;
+                       mwifiex_process_event(adapter);
+               }
+
+               /* Check for Cmd Resp */
+               if (adapter->cmd_resp_received) {
+                       adapter->cmd_resp_received = false;
+                       mwifiex_process_cmdresp(adapter);
+
+                       /* call mwifiex back when init_fw is done */
+                       if (adapter->hw_status == MWIFIEX_HW_STATUS_INIT_DONE) {
+                               adapter->hw_status = MWIFIEX_HW_STATUS_READY;
+                               mwifiex_init_fw_complete(adapter);
+                       }
+               }
+
+               /* Check if we need to confirm Sleep Request
+                  received previously */
+               if (adapter->ps_state == PS_STATE_PRE_SLEEP) {
+                       if (!adapter->cmd_sent && !adapter->curr_cmd)
+                               mwifiex_check_ps_cond(adapter);
+               }
+
+               /* * The ps_state may have been changed during processing of
+                * Sleep Request event.
+                */
+               if ((adapter->ps_state == PS_STATE_SLEEP) ||
+                   (adapter->ps_state == PS_STATE_PRE_SLEEP) ||
+                   (adapter->ps_state == PS_STATE_SLEEP_CFM)) {
+                       continue;
+               }
+
+               if (adapter->tx_lock_flag) {
+                       if (adapter->iface_type == MWIFIEX_USB) {
+                               if (!adapter->usb_mc_setup)
+                                       continue;
+                       } else
+                               continue;
+               }
+
+               if (!adapter->cmd_sent && !adapter->curr_cmd &&
+                   mwifiex_is_send_cmd_allowed
+                   (mwifiex_get_priv(adapter, MWIFIEX_BSS_ROLE_STA))) {
+                       if (mwifiex_exec_next_cmd(adapter) == -1) {
+                               ret = -1;
+                               break;
+                       }
+               }
+
+               /** If USB Multi channel setup ongoing,
+                *  wait for ready to tx data.
+                */
+               if (adapter->iface_type == MWIFIEX_USB &&
+                   adapter->usb_mc_setup)
+                       continue;
+
+               if ((adapter->scan_chan_gap_enabled ||
+                    !adapter->scan_processing) &&
+                   !adapter->data_sent &&
+                   !skb_queue_empty(&adapter->tx_data_q)) {
+                       mwifiex_process_tx_queue(adapter);
+                       if (adapter->hs_activated) {
+                               adapter->is_hs_configured = false;
+                               mwifiex_hs_activated_event
+                                       (mwifiex_get_priv
+                                       (adapter, MWIFIEX_BSS_ROLE_ANY),
+                                       false);
+                       }
+               }
+
+               if ((adapter->scan_chan_gap_enabled ||
+                    !adapter->scan_processing) &&
+                   !adapter->data_sent &&
+                   !mwifiex_bypass_txlist_empty(adapter) &&
+                   !mwifiex_is_tdls_chan_switching
+                       (mwifiex_get_priv(adapter, MWIFIEX_BSS_ROLE_STA))) {
+                       mwifiex_process_bypass_tx(adapter);
+                       if (adapter->hs_activated) {
+                               adapter->is_hs_configured = false;
+                               mwifiex_hs_activated_event
+                                       (mwifiex_get_priv
+                                        (adapter, MWIFIEX_BSS_ROLE_ANY),
+                                        false);
+                       }
+               }
+
+               if ((adapter->scan_chan_gap_enabled ||
+                    !adapter->scan_processing) &&
+                   !adapter->data_sent && !mwifiex_wmm_lists_empty(adapter) &&
+                   !mwifiex_is_tdls_chan_switching
+                       (mwifiex_get_priv(adapter, MWIFIEX_BSS_ROLE_STA))) {
+                       mwifiex_wmm_process_tx(adapter);
+                       if (adapter->hs_activated) {
+                               adapter->is_hs_configured = false;
+                               mwifiex_hs_activated_event
+                                       (mwifiex_get_priv
+                                        (adapter, MWIFIEX_BSS_ROLE_ANY),
+                                        false);
+                       }
+               }
+
+               if (adapter->delay_null_pkt && !adapter->cmd_sent &&
+                   !adapter->curr_cmd && !is_command_pending(adapter) &&
+                   (mwifiex_wmm_lists_empty(adapter) &&
+                    mwifiex_bypass_txlist_empty(adapter) &&
+                    skb_queue_empty(&adapter->tx_data_q))) {
+                       if (!mwifiex_send_null_packet
+                           (mwifiex_get_priv(adapter, MWIFIEX_BSS_ROLE_STA),
+                            MWIFIEX_TxPD_POWER_MGMT_NULL_PACKET |
+                            MWIFIEX_TxPD_POWER_MGMT_LAST_PACKET)) {
+                               adapter->delay_null_pkt = false;
+                               adapter->ps_state = PS_STATE_SLEEP;
+                       }
+                       break;
+               }
+       } while (true);
+
+       spin_lock_irqsave(&adapter->main_proc_lock, flags);
+       if (adapter->more_task_flag) {
+               adapter->more_task_flag = false;
+               spin_unlock_irqrestore(&adapter->main_proc_lock, flags);
+               goto process_start;
+       }
+       adapter->mwifiex_processing = false;
+       spin_unlock_irqrestore(&adapter->main_proc_lock, flags);
+
+exit_main_proc:
+       if (adapter->hw_status == MWIFIEX_HW_STATUS_CLOSING)
+               mwifiex_shutdown_drv(adapter);
+       return ret;
+}
+EXPORT_SYMBOL_GPL(mwifiex_main_process);
+
+/*
+ * This function frees the adapter structure.
+ *
+ * Additionally, this closes the netlink socket, frees the timers
+ * and private structures.
+ */
+static void mwifiex_free_adapter(struct mwifiex_adapter *adapter)
+{
+       if (!adapter) {
+               pr_err("%s: adapter is NULL\n", __func__);
+               return;
+       }
+
+       mwifiex_unregister(adapter);
+       pr_debug("info: %s: free adapter\n", __func__);
+}
+
+/*
+ * This function cancels all works in the queue and destroys
+ * the main workqueue.
+ */
+static void mwifiex_terminate_workqueue(struct mwifiex_adapter *adapter)
+{
+       flush_workqueue(adapter->workqueue);
+       destroy_workqueue(adapter->workqueue);
+       adapter->workqueue = NULL;
+
+       if (adapter->rx_workqueue) {
+               flush_workqueue(adapter->rx_workqueue);
+               destroy_workqueue(adapter->rx_workqueue);
+               adapter->rx_workqueue = NULL;
+       }
+}
+
+/*
+ * This function gets firmware and initializes it.
+ *
+ * The main initialization steps followed are -
+ *      - Download the correct firmware to card
+ *      - Issue the init commands to firmware
+ */
+static void mwifiex_fw_dpc(const struct firmware *firmware, void *context)
+{
+       int ret;
+       char fmt[64];
+       struct mwifiex_private *priv;
+       struct mwifiex_adapter *adapter = context;
+       struct mwifiex_fw_image fw;
+       struct semaphore *sem = adapter->card_sem;
+       bool init_failed = false;
+       struct wireless_dev *wdev;
+
+       if (!firmware) {
+               mwifiex_dbg(adapter, ERROR,
+                           "Failed to get firmware %s\n", adapter->fw_name);
+               goto err_dnld_fw;
+       }
+
+       memset(&fw, 0, sizeof(struct mwifiex_fw_image));
+       adapter->firmware = firmware;
+       fw.fw_buf = (u8 *) adapter->firmware->data;
+       fw.fw_len = adapter->firmware->size;
+
+       if (adapter->if_ops.dnld_fw)
+               ret = adapter->if_ops.dnld_fw(adapter, &fw);
+       else
+               ret = mwifiex_dnld_fw(adapter, &fw);
+       if (ret == -1)
+               goto err_dnld_fw;
+
+       mwifiex_dbg(adapter, MSG, "WLAN FW is active\n");
+
+       if (cal_data_cfg) {
+               if ((request_firmware(&adapter->cal_data, cal_data_cfg,
+                                     adapter->dev)) < 0)
+                       mwifiex_dbg(adapter, ERROR,
+                                   "Cal data request_firmware() failed\n");
+       }
+
+       /* enable host interrupt after fw dnld is successful */
+       if (adapter->if_ops.enable_int) {
+               if (adapter->if_ops.enable_int(adapter))
+                       goto err_dnld_fw;
+       }
+
+       adapter->init_wait_q_woken = false;
+       ret = mwifiex_init_fw(adapter);
+       if (ret == -1) {
+               goto err_init_fw;
+       } else if (!ret) {
+               adapter->hw_status = MWIFIEX_HW_STATUS_READY;
+               goto done;
+       }
+       /* Wait for mwifiex_init to complete */
+       wait_event_interruptible(adapter->init_wait_q,
+                                adapter->init_wait_q_woken);
+       if (adapter->hw_status != MWIFIEX_HW_STATUS_READY)
+               goto err_init_fw;
+
+       priv = adapter->priv[MWIFIEX_BSS_ROLE_STA];
+       if (mwifiex_register_cfg80211(adapter)) {
+               mwifiex_dbg(adapter, ERROR,
+                           "cannot register with cfg80211\n");
+               goto err_init_fw;
+       }
+
+       if (mwifiex_init_channel_scan_gap(adapter)) {
+               mwifiex_dbg(adapter, ERROR,
+                           "could not init channel stats table\n");
+               goto err_init_fw;
+       }
+
+       if (driver_mode) {
+               driver_mode &= MWIFIEX_DRIVER_MODE_BITMASK;
+               driver_mode |= MWIFIEX_DRIVER_MODE_STA;
+       }
+
+       rtnl_lock();
+       /* Create station interface by default */
+       wdev = mwifiex_add_virtual_intf(adapter->wiphy, "mlan%d", NET_NAME_ENUM,
+                                       NL80211_IFTYPE_STATION, NULL, NULL);
+       if (IS_ERR(wdev)) {
+               mwifiex_dbg(adapter, ERROR,
+                           "cannot create default STA interface\n");
+               rtnl_unlock();
+               goto err_add_intf;
+       }
+
+       if (driver_mode & MWIFIEX_DRIVER_MODE_UAP) {
+               wdev = mwifiex_add_virtual_intf(adapter->wiphy, "uap%d", NET_NAME_ENUM,
+                                               NL80211_IFTYPE_AP, NULL, NULL);
+               if (IS_ERR(wdev)) {
+                       mwifiex_dbg(adapter, ERROR,
+                                   "cannot create AP interface\n");
+                       rtnl_unlock();
+                       goto err_add_intf;
+               }
+       }
+
+       if (driver_mode & MWIFIEX_DRIVER_MODE_P2P) {
+               wdev = mwifiex_add_virtual_intf(adapter->wiphy, "p2p%d", NET_NAME_ENUM,
+                                               NL80211_IFTYPE_P2P_CLIENT, NULL,
+                                               NULL);
+               if (IS_ERR(wdev)) {
+                       mwifiex_dbg(adapter, ERROR,
+                                   "cannot create p2p client interface\n");
+                       rtnl_unlock();
+                       goto err_add_intf;
+               }
+       }
+       rtnl_unlock();
+
+       mwifiex_drv_get_driver_version(adapter, fmt, sizeof(fmt) - 1);
+       mwifiex_dbg(adapter, MSG, "driver_version = %s\n", fmt);
+       goto done;
+
+err_add_intf:
+       wiphy_unregister(adapter->wiphy);
+       wiphy_free(adapter->wiphy);
+err_init_fw:
+       if (adapter->if_ops.disable_int)
+               adapter->if_ops.disable_int(adapter);
+err_dnld_fw:
+       mwifiex_dbg(adapter, ERROR,
+                   "info: %s: unregister device\n", __func__);
+       if (adapter->if_ops.unregister_dev)
+               adapter->if_ops.unregister_dev(adapter);
+
+       if (adapter->hw_status == MWIFIEX_HW_STATUS_READY) {
+               pr_debug("info: %s: shutdown mwifiex\n", __func__);
+               adapter->init_wait_q_woken = false;
+
+               if (mwifiex_shutdown_drv(adapter) == -EINPROGRESS)
+                       wait_event_interruptible(adapter->init_wait_q,
+                                                adapter->init_wait_q_woken);
+       }
+       adapter->surprise_removed = true;
+       mwifiex_terminate_workqueue(adapter);
+       init_failed = true;
+done:
+       if (adapter->cal_data) {
+               release_firmware(adapter->cal_data);
+               adapter->cal_data = NULL;
+       }
+       if (adapter->firmware) {
+               release_firmware(adapter->firmware);
+               adapter->firmware = NULL;
+       }
+       if (init_failed)
+               mwifiex_free_adapter(adapter);
+       up(sem);
+       return;
+}
+
+/*
+ * This function initializes the hardware and gets firmware.
+ */
+static int mwifiex_init_hw_fw(struct mwifiex_adapter *adapter)
+{
+       int ret;
+
+       ret = request_firmware_nowait(THIS_MODULE, 1, adapter->fw_name,
+                                     adapter->dev, GFP_KERNEL, adapter,
+                                     mwifiex_fw_dpc);
+       if (ret < 0)
+               mwifiex_dbg(adapter, ERROR,
+                           "request_firmware_nowait error %d\n", ret);
+       return ret;
+}
+
+/*
+ * CFG802.11 network device handler for open.
+ *
+ * Starts the data queue.
+ */
+static int
+mwifiex_open(struct net_device *dev)
+{
+       netif_carrier_off(dev);
+
+       return 0;
+}
+
+/*
+ * CFG802.11 network device handler for close.
+ */
+static int
+mwifiex_close(struct net_device *dev)
+{
+       struct mwifiex_private *priv = mwifiex_netdev_get_priv(dev);
+
+       if (priv->scan_request) {
+               mwifiex_dbg(priv->adapter, INFO,
+                           "aborting scan on ndo_stop\n");
+               cfg80211_scan_done(priv->scan_request, 1);
+               priv->scan_request = NULL;
+               priv->scan_aborting = true;
+       }
+
+       return 0;
+}
+
+static bool
+mwifiex_bypass_tx_queue(struct mwifiex_private *priv,
+                       struct sk_buff *skb)
+{
+       struct ethhdr *eth_hdr = (struct ethhdr *)skb->data;
+
+       if (ntohs(eth_hdr->h_proto) == ETH_P_PAE ||
+           mwifiex_is_skb_mgmt_frame(skb) ||
+           (GET_BSS_ROLE(priv) == MWIFIEX_BSS_ROLE_STA &&
+            ISSUPP_TDLS_ENABLED(priv->adapter->fw_cap_info) &&
+            (ntohs(eth_hdr->h_proto) == ETH_P_TDLS))) {
+               mwifiex_dbg(priv->adapter, DATA,
+                           "bypass txqueue; eth type %#x, mgmt %d\n",
+                            ntohs(eth_hdr->h_proto),
+                            mwifiex_is_skb_mgmt_frame(skb));
+               return true;
+       }
+
+       return false;
+}
+/*
+ * Add buffer into wmm tx queue and queue work to transmit it.
+ */
+int mwifiex_queue_tx_pkt(struct mwifiex_private *priv, struct sk_buff *skb)
+{
+       struct netdev_queue *txq;
+       int index = mwifiex_1d_to_wmm_queue[skb->priority];
+
+       if (atomic_inc_return(&priv->wmm_tx_pending[index]) >= MAX_TX_PENDING) {
+               txq = netdev_get_tx_queue(priv->netdev, index);
+               if (!netif_tx_queue_stopped(txq)) {
+                       netif_tx_stop_queue(txq);
+                       mwifiex_dbg(priv->adapter, DATA,
+                                   "stop queue: %d\n", index);
+               }
+       }
+
+       if (mwifiex_bypass_tx_queue(priv, skb)) {
+               atomic_inc(&priv->adapter->tx_pending);
+               atomic_inc(&priv->adapter->bypass_tx_pending);
+               mwifiex_wmm_add_buf_bypass_txqueue(priv, skb);
+        } else {
+               atomic_inc(&priv->adapter->tx_pending);
+               mwifiex_wmm_add_buf_txqueue(priv, skb);
+        }
+
+       mwifiex_queue_main_work(priv->adapter);
+
+       return 0;
+}
+
+struct sk_buff *
+mwifiex_clone_skb_for_tx_status(struct mwifiex_private *priv,
+                               struct sk_buff *skb, u8 flag, u64 *cookie)
+{
+       struct sk_buff *orig_skb = skb;
+       struct mwifiex_txinfo *tx_info, *orig_tx_info;
+
+       skb = skb_clone(skb, GFP_ATOMIC);
+       if (skb) {
+               unsigned long flags;
+               int id;
+
+               spin_lock_irqsave(&priv->ack_status_lock, flags);
+               id = idr_alloc(&priv->ack_status_frames, orig_skb,
+                              1, 0xff, GFP_ATOMIC);
+               spin_unlock_irqrestore(&priv->ack_status_lock, flags);
+
+               if (id >= 0) {
+                       tx_info = MWIFIEX_SKB_TXCB(skb);
+                       tx_info->ack_frame_id = id;
+                       tx_info->flags |= flag;
+                       orig_tx_info = MWIFIEX_SKB_TXCB(orig_skb);
+                       orig_tx_info->ack_frame_id = id;
+                       orig_tx_info->flags |= flag;
+
+                       if (flag == MWIFIEX_BUF_FLAG_ACTION_TX_STATUS && cookie)
+                               orig_tx_info->cookie = *cookie;
+
+               } else if (skb_shared(skb)) {
+                       kfree_skb(orig_skb);
+               } else {
+                       kfree_skb(skb);
+                       skb = orig_skb;
+               }
+       } else {
+               /* couldn't clone -- lose tx status ... */
+               skb = orig_skb;
+       }
+
+       return skb;
+}
+
+/*
+ * CFG802.11 network device handler for data transmission.
+ */
+static int
+mwifiex_hard_start_xmit(struct sk_buff *skb, struct net_device *dev)
+{
+       struct mwifiex_private *priv = mwifiex_netdev_get_priv(dev);
+       struct sk_buff *new_skb;
+       struct mwifiex_txinfo *tx_info;
+       bool multicast;
+
+       mwifiex_dbg(priv->adapter, DATA,
+                   "data: %lu BSS(%d-%d): Data <= kernel\n",
+                   jiffies, priv->bss_type, priv->bss_num);
+
+       if (priv->adapter->surprise_removed) {
+               kfree_skb(skb);
+               priv->stats.tx_dropped++;
+               return 0;
+       }
+       if (!skb->len || (skb->len > ETH_FRAME_LEN)) {
+               mwifiex_dbg(priv->adapter, ERROR,
+                           "Tx: bad skb len %d\n", skb->len);
+               kfree_skb(skb);
+               priv->stats.tx_dropped++;
+               return 0;
+       }
+       if (skb_headroom(skb) < MWIFIEX_MIN_DATA_HEADER_LEN) {
+               mwifiex_dbg(priv->adapter, DATA,
+                           "data: Tx: insufficient skb headroom %d\n",
+                           skb_headroom(skb));
+               /* Insufficient skb headroom - allocate a new skb */
+               new_skb =
+                       skb_realloc_headroom(skb, MWIFIEX_MIN_DATA_HEADER_LEN);
+               if (unlikely(!new_skb)) {
+                       mwifiex_dbg(priv->adapter, ERROR,
+                                   "Tx: cannot alloca new_skb\n");
+                       kfree_skb(skb);
+                       priv->stats.tx_dropped++;
+                       return 0;
+               }
+               kfree_skb(skb);
+               skb = new_skb;
+               mwifiex_dbg(priv->adapter, INFO,
+                           "info: new skb headroomd %d\n",
+                           skb_headroom(skb));
+       }
+
+       tx_info = MWIFIEX_SKB_TXCB(skb);
+       memset(tx_info, 0, sizeof(*tx_info));
+       tx_info->bss_num = priv->bss_num;
+       tx_info->bss_type = priv->bss_type;
+       tx_info->pkt_len = skb->len;
+
+       multicast = is_multicast_ether_addr(skb->data);
+
+       if (unlikely(!multicast && skb->sk &&
+                    skb_shinfo(skb)->tx_flags & SKBTX_WIFI_STATUS &&
+                    priv->adapter->fw_api_ver == MWIFIEX_FW_V15))
+               skb = mwifiex_clone_skb_for_tx_status(priv,
+                                                     skb,
+                                       MWIFIEX_BUF_FLAG_EAPOL_TX_STATUS, NULL);
+
+       /* Record the current time the packet was queued; used to
+        * determine the amount of time the packet was queued in
+        * the driver before it was sent to the firmware.
+        * The delay is then sent along with the packet to the
+        * firmware for aggregate delay calculation for stats and
+        * MSDU lifetime expiry.
+        */
+       __net_timestamp(skb);
+
+       if (ISSUPP_TDLS_ENABLED(priv->adapter->fw_cap_info) &&
+           priv->bss_type == MWIFIEX_BSS_TYPE_STA &&
+           !ether_addr_equal_unaligned(priv->cfg_bssid, skb->data)) {
+               if (priv->adapter->auto_tdls && priv->check_tdls_tx)
+                       mwifiex_tdls_check_tx(priv, skb);
+       }
+
+       mwifiex_queue_tx_pkt(priv, skb);
+
+       return 0;
+}
+
+/*
+ * CFG802.11 network device handler for setting MAC address.
+ */
+static int
+mwifiex_set_mac_address(struct net_device *dev, void *addr)
+{
+       struct mwifiex_private *priv = mwifiex_netdev_get_priv(dev);
+       struct sockaddr *hw_addr = addr;
+       int ret;
+
+       memcpy(priv->curr_addr, hw_addr->sa_data, ETH_ALEN);
+
+       /* Send request to firmware */
+       ret = mwifiex_send_cmd(priv, HostCmd_CMD_802_11_MAC_ADDRESS,
+                              HostCmd_ACT_GEN_SET, 0, NULL, true);
+
+       if (!ret)
+               memcpy(priv->netdev->dev_addr, priv->curr_addr, ETH_ALEN);
+       else
+               mwifiex_dbg(priv->adapter, ERROR,
+                           "set mac address failed: ret=%d\n", ret);
+
+       memcpy(dev->dev_addr, priv->curr_addr, ETH_ALEN);
+
+       return ret;
+}
+
+/*
+ * CFG802.11 network device handler for setting multicast list.
+ */
+static void mwifiex_set_multicast_list(struct net_device *dev)
+{
+       struct mwifiex_private *priv = mwifiex_netdev_get_priv(dev);
+       struct mwifiex_multicast_list mcast_list;
+
+       if (dev->flags & IFF_PROMISC) {
+               mcast_list.mode = MWIFIEX_PROMISC_MODE;
+       } else if (dev->flags & IFF_ALLMULTI ||
+                  netdev_mc_count(dev) > MWIFIEX_MAX_MULTICAST_LIST_SIZE) {
+               mcast_list.mode = MWIFIEX_ALL_MULTI_MODE;
+       } else {
+               mcast_list.mode = MWIFIEX_MULTICAST_MODE;
+               mcast_list.num_multicast_addr =
+                       mwifiex_copy_mcast_addr(&mcast_list, dev);
+       }
+       mwifiex_request_set_multicast_list(priv, &mcast_list);
+}
+
+/*
+ * CFG802.11 network device handler for transmission timeout.
+ */
+static void
+mwifiex_tx_timeout(struct net_device *dev)
+{
+       struct mwifiex_private *priv = mwifiex_netdev_get_priv(dev);
+
+       priv->num_tx_timeout++;
+       priv->tx_timeout_cnt++;
+       mwifiex_dbg(priv->adapter, ERROR,
+                   "%lu : Tx timeout(#%d), bss_type-num = %d-%d\n",
+                   jiffies, priv->tx_timeout_cnt, priv->bss_type,
+                   priv->bss_num);
+       mwifiex_set_trans_start(dev);
+
+       if (priv->tx_timeout_cnt > TX_TIMEOUT_THRESHOLD &&
+           priv->adapter->if_ops.card_reset) {
+               mwifiex_dbg(priv->adapter, ERROR,
+                           "tx_timeout_cnt exceeds threshold.\t"
+                           "Triggering card reset!\n");
+               priv->adapter->if_ops.card_reset(priv->adapter);
+       }
+}
+
+void mwifiex_multi_chan_resync(struct mwifiex_adapter *adapter)
+{
+       struct usb_card_rec *card = adapter->card;
+       struct mwifiex_private *priv;
+       u16 tx_buf_size;
+       int i, ret;
+
+       card->mc_resync_flag = true;
+       for (i = 0; i < MWIFIEX_TX_DATA_PORT; i++) {
+               if (atomic_read(&card->port[i].tx_data_urb_pending)) {
+                       mwifiex_dbg(adapter, WARN, "pending data urb in sys\n");
+                       return;
+               }
+       }
+
+       card->mc_resync_flag = false;
+       tx_buf_size = 0xffff;
+       priv = mwifiex_get_priv(adapter, MWIFIEX_BSS_ROLE_ANY);
+       ret = mwifiex_send_cmd(priv, HostCmd_CMD_RECONFIGURE_TX_BUFF,
+                              HostCmd_ACT_GEN_SET, 0, &tx_buf_size, false);
+       if (ret)
+               mwifiex_dbg(adapter, ERROR,
+                           "send reconfig tx buf size cmd err\n");
+}
+EXPORT_SYMBOL_GPL(mwifiex_multi_chan_resync);
+
+void mwifiex_drv_info_dump(struct mwifiex_adapter *adapter)
+{
+       void *p;
+       char drv_version[64];
+       struct usb_card_rec *cardp;
+       struct sdio_mmc_card *sdio_card;
+       struct mwifiex_private *priv;
+       int i, idx;
+       struct netdev_queue *txq;
+       struct mwifiex_debug_info *debug_info;
+
+       if (adapter->drv_info_dump) {
+               vfree(adapter->drv_info_dump);
+               adapter->drv_info_dump = NULL;
+               adapter->drv_info_size = 0;
+       }
+
+       mwifiex_dbg(adapter, MSG, "===mwifiex driverinfo dump start===\n");
+
+       adapter->drv_info_dump = vzalloc(MWIFIEX_DRV_INFO_SIZE_MAX);
+
+       if (!adapter->drv_info_dump)
+               return;
+
+       p = (char *)(adapter->drv_info_dump);
+       p += sprintf(p, "driver_name = " "\"mwifiex\"\n");
+
+       mwifiex_drv_get_driver_version(adapter, drv_version,
+                                      sizeof(drv_version) - 1);
+       p += sprintf(p, "driver_version = %s\n", drv_version);
+
+       if (adapter->iface_type == MWIFIEX_USB) {
+               cardp = (struct usb_card_rec *)adapter->card;
+               p += sprintf(p, "tx_cmd_urb_pending = %d\n",
+                            atomic_read(&cardp->tx_cmd_urb_pending));
+               p += sprintf(p, "tx_data_urb_pending_port_0 = %d\n",
+                            atomic_read(&cardp->port[0].tx_data_urb_pending));
+               p += sprintf(p, "tx_data_urb_pending_port_1 = %d\n",
+                            atomic_read(&cardp->port[1].tx_data_urb_pending));
+               p += sprintf(p, "rx_cmd_urb_pending = %d\n",
+                            atomic_read(&cardp->rx_cmd_urb_pending));
+               p += sprintf(p, "rx_data_urb_pending = %d\n",
+                            atomic_read(&cardp->rx_data_urb_pending));
+       }
+
+       p += sprintf(p, "tx_pending = %d\n",
+                    atomic_read(&adapter->tx_pending));
+       p += sprintf(p, "rx_pending = %d\n",
+                    atomic_read(&adapter->rx_pending));
+
+       if (adapter->iface_type == MWIFIEX_SDIO) {
+               sdio_card = (struct sdio_mmc_card *)adapter->card;
+               p += sprintf(p, "\nmp_rd_bitmap=0x%x curr_rd_port=0x%x\n",
+                            sdio_card->mp_rd_bitmap, sdio_card->curr_rd_port);
+               p += sprintf(p, "mp_wr_bitmap=0x%x curr_wr_port=0x%x\n",
+                            sdio_card->mp_wr_bitmap, sdio_card->curr_wr_port);
+       }
+
+       for (i = 0; i < adapter->priv_num; i++) {
+               if (!adapter->priv[i] || !adapter->priv[i]->netdev)
+                       continue;
+               priv = adapter->priv[i];
+               p += sprintf(p, "\n[interface  : \"%s\"]\n",
+                            priv->netdev->name);
+               p += sprintf(p, "wmm_tx_pending[0] = %d\n",
+                            atomic_read(&priv->wmm_tx_pending[0]));
+               p += sprintf(p, "wmm_tx_pending[1] = %d\n",
+                            atomic_read(&priv->wmm_tx_pending[1]));
+               p += sprintf(p, "wmm_tx_pending[2] = %d\n",
+                            atomic_read(&priv->wmm_tx_pending[2]));
+               p += sprintf(p, "wmm_tx_pending[3] = %d\n",
+                            atomic_read(&priv->wmm_tx_pending[3]));
+               p += sprintf(p, "media_state=\"%s\"\n", !priv->media_connected ?
+                            "Disconnected" : "Connected");
+               p += sprintf(p, "carrier %s\n", (netif_carrier_ok(priv->netdev)
+                            ? "on" : "off"));
+               for (idx = 0; idx < priv->netdev->num_tx_queues; idx++) {
+                       txq = netdev_get_tx_queue(priv->netdev, idx);
+                       p += sprintf(p, "tx queue %d:%s  ", idx,
+                                    netif_tx_queue_stopped(txq) ?
+                                    "stopped" : "started");
+               }
+               p += sprintf(p, "\n%s: num_tx_timeout = %d\n",
+                            priv->netdev->name, priv->num_tx_timeout);
+       }
+
+       if (adapter->iface_type == MWIFIEX_SDIO) {
+               p += sprintf(p, "\n=== SDIO register dump===\n");
+               if (adapter->if_ops.reg_dump)
+                       p += adapter->if_ops.reg_dump(adapter, p);
+       }
+
+       p += sprintf(p, "\n=== more debug information\n");
+       debug_info = kzalloc(sizeof(*debug_info), GFP_KERNEL);
+       if (debug_info) {
+               for (i = 0; i < adapter->priv_num; i++) {
+                       if (!adapter->priv[i] || !adapter->priv[i]->netdev)
+                               continue;
+                       priv = adapter->priv[i];
+                       mwifiex_get_debug_info(priv, debug_info);
+                       p += mwifiex_debug_info_to_buffer(priv, p, debug_info);
+                       break;
+               }
+               kfree(debug_info);
+       }
+
+       adapter->drv_info_size = p - adapter->drv_info_dump;
+       mwifiex_dbg(adapter, MSG, "===mwifiex driverinfo dump end===\n");
+}
+EXPORT_SYMBOL_GPL(mwifiex_drv_info_dump);
+
+void mwifiex_upload_device_dump(struct mwifiex_adapter *adapter)
+{
+       u8 idx, *dump_data, *fw_dump_ptr;
+       u32 dump_len;
+
+       dump_len = (strlen("========Start dump driverinfo========\n") +
+                      adapter->drv_info_size +
+                      strlen("\n========End dump========\n"));
+
+       for (idx = 0; idx < adapter->num_mem_types; idx++) {
+               struct memory_type_mapping *entry =
+                               &adapter->mem_type_mapping_tbl[idx];
+
+               if (entry->mem_ptr) {
+                       dump_len += (strlen("========Start dump ") +
+                                       strlen(entry->mem_name) +
+                                       strlen("========\n") +
+                                       (entry->mem_size + 1) +
+                                       strlen("\n========End dump========\n"));
+               }
+       }
+
+       dump_data = vzalloc(dump_len + 1);
+       if (!dump_data)
+               goto done;
+
+       fw_dump_ptr = dump_data;
+
+       /* Dump all the memory data into single file, a userspace script will
+        * be used to split all the memory data to multiple files
+        */
+       mwifiex_dbg(adapter, MSG,
+                   "== mwifiex dump information to /sys/class/devcoredump start");
+
+       strcpy(fw_dump_ptr, "========Start dump driverinfo========\n");
+       fw_dump_ptr += strlen("========Start dump driverinfo========\n");
+       memcpy(fw_dump_ptr, adapter->drv_info_dump, adapter->drv_info_size);
+       fw_dump_ptr += adapter->drv_info_size;
+       strcpy(fw_dump_ptr, "\n========End dump========\n");
+       fw_dump_ptr += strlen("\n========End dump========\n");
+
+       for (idx = 0; idx < adapter->num_mem_types; idx++) {
+               struct memory_type_mapping *entry =
+                                       &adapter->mem_type_mapping_tbl[idx];
+
+               if (entry->mem_ptr) {
+                       strcpy(fw_dump_ptr, "========Start dump ");
+                       fw_dump_ptr += strlen("========Start dump ");
+
+                       strcpy(fw_dump_ptr, entry->mem_name);
+                       fw_dump_ptr += strlen(entry->mem_name);
+
+                       strcpy(fw_dump_ptr, "========\n");
+                       fw_dump_ptr += strlen("========\n");
+
+                       memcpy(fw_dump_ptr, entry->mem_ptr, entry->mem_size);
+                       fw_dump_ptr += entry->mem_size;
+
+                       strcpy(fw_dump_ptr, "\n========End dump========\n");
+                       fw_dump_ptr += strlen("\n========End dump========\n");
+               }
+       }
+
+       /* device dump data will be free in device coredump release function
+        * after 5 min
+        */
+       dev_coredumpv(adapter->dev, dump_data, dump_len, GFP_KERNEL);
+       mwifiex_dbg(adapter, MSG,
+                   "== mwifiex dump information to /sys/class/devcoredump end");
+
+done:
+       for (idx = 0; idx < adapter->num_mem_types; idx++) {
+               struct memory_type_mapping *entry =
+                       &adapter->mem_type_mapping_tbl[idx];
+
+               if (entry->mem_ptr) {
+                       vfree(entry->mem_ptr);
+                       entry->mem_ptr = NULL;
+               }
+               entry->mem_size = 0;
+       }
+
+       if (adapter->drv_info_dump) {
+               vfree(adapter->drv_info_dump);
+               adapter->drv_info_dump = NULL;
+               adapter->drv_info_size = 0;
+       }
+}
+EXPORT_SYMBOL_GPL(mwifiex_upload_device_dump);
+
+/*
+ * CFG802.11 network device handler for statistics retrieval.
+ */
+static struct net_device_stats *mwifiex_get_stats(struct net_device *dev)
+{
+       struct mwifiex_private *priv = mwifiex_netdev_get_priv(dev);
+
+       return &priv->stats;
+}
+
+static u16
+mwifiex_netdev_select_wmm_queue(struct net_device *dev, struct sk_buff *skb,
+                               void *accel_priv, select_queue_fallback_t fallback)
+{
+       skb->priority = cfg80211_classify8021d(skb, NULL);
+       return mwifiex_1d_to_wmm_queue[skb->priority];
+}
+
+/* Network device handlers */
+static const struct net_device_ops mwifiex_netdev_ops = {
+       .ndo_open = mwifiex_open,
+       .ndo_stop = mwifiex_close,
+       .ndo_start_xmit = mwifiex_hard_start_xmit,
+       .ndo_set_mac_address = mwifiex_set_mac_address,
+       .ndo_validate_addr = eth_validate_addr,
+       .ndo_tx_timeout = mwifiex_tx_timeout,
+       .ndo_get_stats = mwifiex_get_stats,
+       .ndo_set_rx_mode = mwifiex_set_multicast_list,
+       .ndo_select_queue = mwifiex_netdev_select_wmm_queue,
+};
+
+/*
+ * This function initializes the private structure parameters.
+ *
+ * The following wait queues are initialized -
+ *      - IOCTL wait queue
+ *      - Command wait queue
+ *      - Statistics wait queue
+ *
+ * ...and the following default parameters are set -
+ *      - Current key index     : Set to 0
+ *      - Rate index            : Set to auto
+ *      - Media connected       : Set to disconnected
+ *      - Adhoc link sensed     : Set to false
+ *      - Nick name             : Set to null
+ *      - Number of Tx timeout  : Set to 0
+ *      - Device address        : Set to current address
+ *      - Rx histogram statistc : Set to 0
+ *
+ * In addition, the CFG80211 work queue is also created.
+ */
+void mwifiex_init_priv_params(struct mwifiex_private *priv,
+                             struct net_device *dev)
+{
+       dev->netdev_ops = &mwifiex_netdev_ops;
+       dev->destructor = free_netdev;
+       /* Initialize private structure */
+       priv->current_key_index = 0;
+       priv->media_connected = false;
+       memset(priv->mgmt_ie, 0,
+              sizeof(struct mwifiex_ie) * MAX_MGMT_IE_INDEX);
+       priv->beacon_idx = MWIFIEX_AUTO_IDX_MASK;
+       priv->proberesp_idx = MWIFIEX_AUTO_IDX_MASK;
+       priv->assocresp_idx = MWIFIEX_AUTO_IDX_MASK;
+       priv->gen_idx = MWIFIEX_AUTO_IDX_MASK;
+       priv->num_tx_timeout = 0;
+       ether_addr_copy(priv->curr_addr, priv->adapter->perm_addr);
+       memcpy(dev->dev_addr, priv->curr_addr, ETH_ALEN);
+
+       if (GET_BSS_ROLE(priv) == MWIFIEX_BSS_ROLE_STA ||
+           GET_BSS_ROLE(priv) == MWIFIEX_BSS_ROLE_UAP) {
+               priv->hist_data = kmalloc(sizeof(*priv->hist_data), GFP_KERNEL);
+               if (priv->hist_data)
+                       mwifiex_hist_data_reset(priv);
+       }
+}
+
+/*
+ * This function check if command is pending.
+ */
+int is_command_pending(struct mwifiex_adapter *adapter)
+{
+       unsigned long flags;
+       int is_cmd_pend_q_empty;
+
+       spin_lock_irqsave(&adapter->cmd_pending_q_lock, flags);
+       is_cmd_pend_q_empty = list_empty(&adapter->cmd_pending_q);
+       spin_unlock_irqrestore(&adapter->cmd_pending_q_lock, flags);
+
+       return !is_cmd_pend_q_empty;
+}
+
+/*
+ * This is the RX work queue function.
+ *
+ * It handles the RX operations.
+ */
+static void mwifiex_rx_work_queue(struct work_struct *work)
+{
+       struct mwifiex_adapter *adapter =
+               container_of(work, struct mwifiex_adapter, rx_work);
+
+       if (adapter->surprise_removed)
+               return;
+       mwifiex_process_rx(adapter);
+}
+
+/*
+ * This is the main work queue function.
+ *
+ * It handles the main process, which in turn handles the complete
+ * driver operations.
+ */
+static void mwifiex_main_work_queue(struct work_struct *work)
+{
+       struct mwifiex_adapter *adapter =
+               container_of(work, struct mwifiex_adapter, main_work);
+
+       if (adapter->surprise_removed)
+               return;
+       mwifiex_main_process(adapter);
+}
+
+/*
+ * This function adds the card.
+ *
+ * This function follows the following major steps to set up the device -
+ *      - Initialize software. This includes probing the card, registering
+ *        the interface operations table, and allocating/initializing the
+ *        adapter structure
+ *      - Set up the netlink socket
+ *      - Create and start the main work queue
+ *      - Register the device
+ *      - Initialize firmware and hardware
+ *      - Add logical interfaces
+ */
+int
+mwifiex_add_card(void *card, struct semaphore *sem,
+                struct mwifiex_if_ops *if_ops, u8 iface_type)
+{
+       struct mwifiex_adapter *adapter;
+
+       if (down_interruptible(sem))
+               goto exit_sem_err;
+
+       if (mwifiex_register(card, if_ops, (void **)&adapter)) {
+               pr_err("%s: software init failed\n", __func__);
+               goto err_init_sw;
+       }
+
+       adapter->iface_type = iface_type;
+       adapter->card_sem = sem;
+
+       adapter->hw_status = MWIFIEX_HW_STATUS_INITIALIZING;
+       adapter->surprise_removed = false;
+       init_waitqueue_head(&adapter->init_wait_q);
+       adapter->is_suspended = false;
+       adapter->hs_activated = false;
+       init_waitqueue_head(&adapter->hs_activate_wait_q);
+       init_waitqueue_head(&adapter->cmd_wait_q.wait);
+       adapter->cmd_wait_q.status = 0;
+       adapter->scan_wait_q_woken = false;
+
+       if ((num_possible_cpus() > 1) || adapter->iface_type == MWIFIEX_USB) {
+               adapter->rx_work_enabled = true;
+               pr_notice("rx work enabled, cpus %d\n", num_possible_cpus());
+       }
+
+       adapter->workqueue =
+               alloc_workqueue("MWIFIEX_WORK_QUEUE",
+                               WQ_HIGHPRI | WQ_MEM_RECLAIM | WQ_UNBOUND, 1);
+       if (!adapter->workqueue)
+               goto err_kmalloc;
+
+       INIT_WORK(&adapter->main_work, mwifiex_main_work_queue);
+
+       if (adapter->rx_work_enabled) {
+               adapter->rx_workqueue = alloc_workqueue("MWIFIEX_RX_WORK_QUEUE",
+                                                       WQ_HIGHPRI |
+                                                       WQ_MEM_RECLAIM |
+                                                       WQ_UNBOUND, 1);
+               if (!adapter->rx_workqueue)
+                       goto err_kmalloc;
+
+               INIT_WORK(&adapter->rx_work, mwifiex_rx_work_queue);
+       }
+
+       /* Register the device. Fill up the private data structure with relevant
+          information from the card. */
+       if (adapter->if_ops.register_dev(adapter)) {
+               pr_err("%s: failed to register mwifiex device\n", __func__);
+               goto err_registerdev;
+       }
+
+       if (mwifiex_init_hw_fw(adapter)) {
+               pr_err("%s: firmware init failed\n", __func__);
+               goto err_init_fw;
+       }
+
+       return 0;
+
+err_init_fw:
+       pr_debug("info: %s: unregister device\n", __func__);
+       if (adapter->if_ops.unregister_dev)
+               adapter->if_ops.unregister_dev(adapter);
+       if (adapter->hw_status == MWIFIEX_HW_STATUS_READY) {
+               pr_debug("info: %s: shutdown mwifiex\n", __func__);
+               adapter->init_wait_q_woken = false;
+
+               if (mwifiex_shutdown_drv(adapter) == -EINPROGRESS)
+                       wait_event_interruptible(adapter->init_wait_q,
+                                                adapter->init_wait_q_woken);
+       }
+err_registerdev:
+       adapter->surprise_removed = true;
+       mwifiex_terminate_workqueue(adapter);
+err_kmalloc:
+       mwifiex_free_adapter(adapter);
+
+err_init_sw:
+       up(sem);
+
+exit_sem_err:
+       return -1;
+}
+EXPORT_SYMBOL_GPL(mwifiex_add_card);
+
+/*
+ * This function removes the card.
+ *
+ * This function follows the following major steps to remove the device -
+ *      - Stop data traffic
+ *      - Shutdown firmware
+ *      - Remove the logical interfaces
+ *      - Terminate the work queue
+ *      - Unregister the device
+ *      - Free the adapter structure
+ */
+int mwifiex_remove_card(struct mwifiex_adapter *adapter, struct semaphore *sem)
+{
+       struct mwifiex_private *priv = NULL;
+       int i;
+
+       if (down_interruptible(sem))
+               goto exit_sem_err;
+
+       if (!adapter)
+               goto exit_remove;
+
+       /* We can no longer handle interrupts once we start doing the teardown
+        * below. */
+       if (adapter->if_ops.disable_int)
+               adapter->if_ops.disable_int(adapter);
+
+       adapter->surprise_removed = true;
+
+       mwifiex_terminate_workqueue(adapter);
+
+       /* Stop data */
+       for (i = 0; i < adapter->priv_num; i++) {
+               priv = adapter->priv[i];
+               if (priv && priv->netdev) {
+                       mwifiex_stop_net_dev_queue(priv->netdev, adapter);
+                       if (netif_carrier_ok(priv->netdev))
+                               netif_carrier_off(priv->netdev);
+               }
+       }
+
+       mwifiex_dbg(adapter, CMD,
+                   "cmd: calling mwifiex_shutdown_drv...\n");
+       adapter->init_wait_q_woken = false;
+
+       if (mwifiex_shutdown_drv(adapter) == -EINPROGRESS)
+               wait_event_interruptible(adapter->init_wait_q,
+                                        adapter->init_wait_q_woken);
+       mwifiex_dbg(adapter, CMD,
+                   "cmd: mwifiex_shutdown_drv done\n");
+       if (atomic_read(&adapter->rx_pending) ||
+           atomic_read(&adapter->tx_pending) ||
+           atomic_read(&adapter->cmd_pending)) {
+               mwifiex_dbg(adapter, ERROR,
+                           "rx_pending=%d, tx_pending=%d,\t"
+                           "cmd_pending=%d\n",
+                           atomic_read(&adapter->rx_pending),
+                           atomic_read(&adapter->tx_pending),
+                           atomic_read(&adapter->cmd_pending));
+       }
+
+       for (i = 0; i < adapter->priv_num; i++) {
+               priv = adapter->priv[i];
+
+               if (!priv)
+                       continue;
+
+               rtnl_lock();
+               if (priv->netdev &&
+                   priv->wdev.iftype != NL80211_IFTYPE_UNSPECIFIED)
+                       mwifiex_del_virtual_intf(adapter->wiphy, &priv->wdev);
+               rtnl_unlock();
+       }
+
+       wiphy_unregister(adapter->wiphy);
+       wiphy_free(adapter->wiphy);
+
+       /* Unregister device */
+       mwifiex_dbg(adapter, INFO,
+                   "info: unregister device\n");
+       if (adapter->if_ops.unregister_dev)
+               adapter->if_ops.unregister_dev(adapter);
+       /* Free adapter structure */
+       mwifiex_dbg(adapter, INFO,
+                   "info: free adapter\n");
+       mwifiex_free_adapter(adapter);
+
+exit_remove:
+       up(sem);
+exit_sem_err:
+       return 0;
+}
+EXPORT_SYMBOL_GPL(mwifiex_remove_card);
+
+void _mwifiex_dbg(const struct mwifiex_adapter *adapter, int mask,
+                 const char *fmt, ...)
+{
+       struct va_format vaf;
+       va_list args;
+
+       if (!adapter->dev || !(adapter->debug_mask & mask))
+               return;
+
+       va_start(args, fmt);
+
+       vaf.fmt = fmt;
+       vaf.va = &args;
+
+       dev_info(adapter->dev, "%pV", &vaf);
+
+       va_end(args);
+}
+EXPORT_SYMBOL_GPL(_mwifiex_dbg);
+
+/*
+ * This function initializes the module.
+ *
+ * The debug FS is also initialized if configured.
+ */
+static int
+mwifiex_init_module(void)
+{
+#ifdef CONFIG_DEBUG_FS
+       mwifiex_debugfs_init();
+#endif
+       return 0;
+}
+
+/*
+ * This function cleans up the module.
+ *
+ * The debug FS is removed if available.
+ */
+static void
+mwifiex_cleanup_module(void)
+{
+#ifdef CONFIG_DEBUG_FS
+       mwifiex_debugfs_remove();
+#endif
+}
+
+module_init(mwifiex_init_module);
+module_exit(mwifiex_cleanup_module);
+
+MODULE_AUTHOR("Marvell International Ltd.");
+MODULE_DESCRIPTION("Marvell WiFi-Ex Driver version " VERSION);
+MODULE_VERSION(VERSION);
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/net/wireless/marvell/mwifiex/main.h b/drivers/net/wireless/marvell/mwifiex/main.h
new file mode 100644 (file)
index 0000000..3959f1c
--- /dev/null
@@ -0,0 +1,1579 @@
+/*
+ * Marvell Wireless LAN device driver: major data structures and prototypes
+ *
+ * Copyright (C) 2011-2014, Marvell International Ltd.
+ *
+ * This software file (the "File") is distributed by Marvell International
+ * Ltd. under the terms of the GNU General Public License Version 2, June 1991
+ * (the "License").  You may use, redistribute and/or modify this File in
+ * accordance with the terms and conditions of the License, a copy of which
+ * is available by writing to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the
+ * worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
+ *
+ * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
+ * ARE EXPRESSLY DISCLAIMED.  The License provides additional details about
+ * this warranty disclaimer.
+ */
+
+#ifndef _MWIFIEX_MAIN_H_
+#define _MWIFIEX_MAIN_H_
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/sched.h>
+#include <linux/semaphore.h>
+#include <linux/ip.h>
+#include <linux/skbuff.h>
+#include <linux/if_arp.h>
+#include <linux/etherdevice.h>
+#include <net/sock.h>
+#include <net/lib80211.h>
+#include <linux/vmalloc.h>
+#include <linux/firmware.h>
+#include <linux/ctype.h>
+#include <linux/of.h>
+#include <linux/idr.h>
+#include <linux/inetdevice.h>
+#include <linux/devcoredump.h>
+
+#include "decl.h"
+#include "ioctl.h"
+#include "util.h"
+#include "fw.h"
+#include "pcie.h"
+#include "usb.h"
+#include "sdio.h"
+
+extern const char driver_version[];
+
+struct mwifiex_adapter;
+struct mwifiex_private;
+
+enum {
+       MWIFIEX_ASYNC_CMD,
+       MWIFIEX_SYNC_CMD
+};
+
+#define MWIFIEX_DRIVER_MODE_STA                        BIT(0)
+#define MWIFIEX_DRIVER_MODE_UAP                        BIT(1)
+#define MWIFIEX_DRIVER_MODE_P2P                        BIT(2)
+#define MWIFIEX_DRIVER_MODE_BITMASK            (BIT(0) | BIT(1) | BIT(2))
+
+#define MWIFIEX_MAX_AP                         64
+
+#define MWIFIEX_MAX_PKTS_TXQ                   16
+
+#define MWIFIEX_DEFAULT_WATCHDOG_TIMEOUT       (5 * HZ)
+
+#define MWIFIEX_TIMER_10S                      10000
+#define MWIFIEX_TIMER_1S                       1000
+
+#define MAX_TX_PENDING      100
+#define LOW_TX_PENDING      80
+
+#define HIGH_RX_PENDING     50
+#define LOW_RX_PENDING      20
+
+#define MWIFIEX_UPLD_SIZE               (2312)
+
+#define MAX_EVENT_SIZE                  2048
+
+#define ARP_FILTER_MAX_BUF_SIZE         68
+
+#define MWIFIEX_KEY_BUFFER_SIZE                        16
+#define MWIFIEX_DEFAULT_LISTEN_INTERVAL 10
+#define MWIFIEX_MAX_REGION_CODE         7
+
+#define DEFAULT_BCN_AVG_FACTOR          8
+#define DEFAULT_DATA_AVG_FACTOR         8
+
+#define FIRST_VALID_CHANNEL                            0xff
+#define DEFAULT_AD_HOC_CHANNEL                 6
+#define DEFAULT_AD_HOC_CHANNEL_A               36
+
+#define DEFAULT_BCN_MISS_TIMEOUT               5
+
+#define MAX_SCAN_BEACON_BUFFER                 8000
+
+#define SCAN_BEACON_ENTRY_PAD                  6
+
+#define MWIFIEX_PASSIVE_SCAN_CHAN_TIME 110
+#define MWIFIEX_ACTIVE_SCAN_CHAN_TIME  30
+#define MWIFIEX_SPECIFIC_SCAN_CHAN_TIME        30
+#define MWIFIEX_DEF_SCAN_CHAN_GAP_TIME  50
+
+#define SCAN_RSSI(RSSI)                                        (0x100 - ((u8)(RSSI)))
+
+#define MWIFIEX_MAX_TOTAL_SCAN_TIME    (MWIFIEX_TIMER_10S - MWIFIEX_TIMER_1S)
+
+#define RSN_GTK_OUI_OFFSET                             2
+
+#define MWIFIEX_OUI_NOT_PRESENT                        0
+#define MWIFIEX_OUI_PRESENT                            1
+
+#define PKT_TYPE_MGMT  0xE5
+
+/*
+ * Do not check for data_received for USB, as data_received
+ * is handled in mwifiex_usb_recv for USB
+ */
+#define IS_CARD_RX_RCVD(adapter) (adapter->cmd_resp_received || \
+                               adapter->event_received || \
+                               adapter->data_received)
+
+#define MWIFIEX_TYPE_CMD                               1
+#define MWIFIEX_TYPE_DATA                              0
+#define MWIFIEX_TYPE_AGGR_DATA                         10
+#define MWIFIEX_TYPE_EVENT                             3
+
+#define MAX_BITMAP_RATES_SIZE                  18
+
+#define MAX_CHANNEL_BAND_BG     14
+#define MAX_CHANNEL_BAND_A      165
+
+#define MAX_FREQUENCY_BAND_BG   2484
+
+#define MWIFIEX_EVENT_HEADER_LEN           4
+#define MWIFIEX_UAP_EVENT_EXTRA_HEADER    2
+
+#define MWIFIEX_TYPE_LEN                       4
+#define MWIFIEX_USB_TYPE_CMD                   0xF00DFACE
+#define MWIFIEX_USB_TYPE_DATA                  0xBEADC0DE
+#define MWIFIEX_USB_TYPE_EVENT                 0xBEEFFACE
+
+/* Threshold for tx_timeout_cnt before we trigger a card reset */
+#define TX_TIMEOUT_THRESHOLD   6
+
+#define MWIFIEX_DRV_INFO_SIZE_MAX 0x40000
+
+/* Address alignment */
+#define MWIFIEX_ALIGN_ADDR(p, a) (((long)(p) + (a) - 1) & ~((a) - 1))
+
+/**
+ *enum mwifiex_debug_level  -  marvell wifi debug level
+ */
+enum MWIFIEX_DEBUG_LEVEL {
+       MWIFIEX_DBG_MSG         = 0x00000001,
+       MWIFIEX_DBG_FATAL       = 0x00000002,
+       MWIFIEX_DBG_ERROR       = 0x00000004,
+       MWIFIEX_DBG_DATA        = 0x00000008,
+       MWIFIEX_DBG_CMD         = 0x00000010,
+       MWIFIEX_DBG_EVENT       = 0x00000020,
+       MWIFIEX_DBG_INTR        = 0x00000040,
+       MWIFIEX_DBG_IOCTL       = 0x00000080,
+
+       MWIFIEX_DBG_MPA_D       = 0x00008000,
+       MWIFIEX_DBG_DAT_D       = 0x00010000,
+       MWIFIEX_DBG_CMD_D       = 0x00020000,
+       MWIFIEX_DBG_EVT_D       = 0x00040000,
+       MWIFIEX_DBG_FW_D        = 0x00080000,
+       MWIFIEX_DBG_IF_D        = 0x00100000,
+
+       MWIFIEX_DBG_ENTRY       = 0x10000000,
+       MWIFIEX_DBG_WARN        = 0x20000000,
+       MWIFIEX_DBG_INFO        = 0x40000000,
+       MWIFIEX_DBG_DUMP        = 0x80000000,
+
+       MWIFIEX_DBG_ANY         = 0xffffffff
+};
+
+#define MWIFIEX_DEFAULT_DEBUG_MASK     (MWIFIEX_DBG_MSG | \
+                                       MWIFIEX_DBG_FATAL | \
+                                       MWIFIEX_DBG_ERROR)
+
+__printf(3, 4)
+void _mwifiex_dbg(const struct mwifiex_adapter *adapter, int mask,
+                 const char *fmt, ...);
+#define mwifiex_dbg(adapter, mask, fmt, ...)                           \
+       _mwifiex_dbg(adapter, MWIFIEX_DBG_##mask, fmt, ##__VA_ARGS__)
+
+#define DEBUG_DUMP_DATA_MAX_LEN                128
+#define mwifiex_dbg_dump(adapter, dbg_mask, str, buf, len)     \
+do {                                                           \
+       if ((adapter)->debug_mask & MWIFIEX_DBG_##dbg_mask)     \
+               print_hex_dump(KERN_DEBUG, str,                 \
+                              DUMP_PREFIX_OFFSET, 16, 1,       \
+                              buf, len, false);                \
+} while (0)
+
+struct mwifiex_dbg {
+       u32 num_cmd_host_to_card_failure;
+       u32 num_cmd_sleep_cfm_host_to_card_failure;
+       u32 num_tx_host_to_card_failure;
+       u32 num_event_deauth;
+       u32 num_event_disassoc;
+       u32 num_event_link_lost;
+       u32 num_cmd_deauth;
+       u32 num_cmd_assoc_success;
+       u32 num_cmd_assoc_failure;
+       u32 num_tx_timeout;
+       u16 timeout_cmd_id;
+       u16 timeout_cmd_act;
+       u16 last_cmd_id[DBG_CMD_NUM];
+       u16 last_cmd_act[DBG_CMD_NUM];
+       u16 last_cmd_index;
+       u16 last_cmd_resp_id[DBG_CMD_NUM];
+       u16 last_cmd_resp_index;
+       u16 last_event[DBG_CMD_NUM];
+       u16 last_event_index;
+};
+
+enum MWIFIEX_HARDWARE_STATUS {
+       MWIFIEX_HW_STATUS_READY,
+       MWIFIEX_HW_STATUS_INITIALIZING,
+       MWIFIEX_HW_STATUS_INIT_DONE,
+       MWIFIEX_HW_STATUS_RESET,
+       MWIFIEX_HW_STATUS_CLOSING,
+       MWIFIEX_HW_STATUS_NOT_READY
+};
+
+enum MWIFIEX_802_11_POWER_MODE {
+       MWIFIEX_802_11_POWER_MODE_CAM,
+       MWIFIEX_802_11_POWER_MODE_PSP
+};
+
+struct mwifiex_tx_param {
+       u32 next_pkt_len;
+};
+
+enum MWIFIEX_PS_STATE {
+       PS_STATE_AWAKE,
+       PS_STATE_PRE_SLEEP,
+       PS_STATE_SLEEP_CFM,
+       PS_STATE_SLEEP
+};
+
+enum mwifiex_iface_type {
+       MWIFIEX_SDIO,
+       MWIFIEX_PCIE,
+       MWIFIEX_USB
+};
+
+struct mwifiex_add_ba_param {
+       u32 tx_win_size;
+       u32 rx_win_size;
+       u32 timeout;
+       u8 tx_amsdu;
+       u8 rx_amsdu;
+};
+
+struct mwifiex_tx_aggr {
+       u8 ampdu_user;
+       u8 ampdu_ap;
+       u8 amsdu;
+};
+
+enum mwifiex_ba_status {
+       BA_SETUP_NONE = 0,
+       BA_SETUP_INPROGRESS,
+       BA_SETUP_COMPLETE
+};
+
+struct mwifiex_ra_list_tbl {
+       struct list_head list;
+       struct sk_buff_head skb_head;
+       u8 ra[ETH_ALEN];
+       u32 is_11n_enabled;
+       u16 max_amsdu;
+       u16 ba_pkt_count;
+       u8 ba_packet_thr;
+       enum mwifiex_ba_status ba_status;
+       u8 amsdu_in_ampdu;
+       u16 total_pkt_count;
+       bool tdls_link;
+       bool tx_paused;
+};
+
+struct mwifiex_tid_tbl {
+       struct list_head ra_list;
+};
+
+#define WMM_HIGHEST_PRIORITY           7
+#define HIGH_PRIO_TID                          7
+#define LOW_PRIO_TID                           0
+
+struct mwifiex_wmm_desc {
+       struct mwifiex_tid_tbl tid_tbl_ptr[MAX_NUM_TID];
+       u32 packets_out[MAX_NUM_TID];
+       u32 pkts_paused[MAX_NUM_TID];
+       /* spin lock to protect ra_list */
+       spinlock_t ra_list_spinlock;
+       struct mwifiex_wmm_ac_status ac_status[IEEE80211_NUM_ACS];
+       enum mwifiex_wmm_ac_e ac_down_graded_vals[IEEE80211_NUM_ACS];
+       u32 drv_pkt_delay_max;
+       u8 queue_priority[IEEE80211_NUM_ACS];
+       u32 user_pri_pkt_tx_ctrl[WMM_HIGHEST_PRIORITY + 1];     /* UP: 0 to 7 */
+       /* Number of transmit packets queued */
+       atomic_t tx_pkts_queued;
+       /* Tracks highest priority with a packet queued */
+       atomic_t highest_queued_prio;
+};
+
+struct mwifiex_802_11_security {
+       u8 wpa_enabled;
+       u8 wpa2_enabled;
+       u8 wapi_enabled;
+       u8 wapi_key_on;
+       u8 wep_enabled;
+       u32 authentication_mode;
+       u8 is_authtype_auto;
+       u32 encryption_mode;
+};
+
+struct ieee_types_header {
+       u8 element_id;
+       u8 len;
+} __packed;
+
+struct ieee_types_vendor_specific {
+       struct ieee_types_vendor_header vend_hdr;
+       u8 data[IEEE_MAX_IE_SIZE - sizeof(struct ieee_types_vendor_header)];
+} __packed;
+
+struct ieee_types_generic {
+       struct ieee_types_header ieee_hdr;
+       u8 data[IEEE_MAX_IE_SIZE - sizeof(struct ieee_types_header)];
+} __packed;
+
+struct ieee_types_bss_co_2040 {
+       struct ieee_types_header ieee_hdr;
+       u8 bss_2040co;
+} __packed;
+
+struct ieee_types_extcap {
+       struct ieee_types_header ieee_hdr;
+       u8 ext_capab[8];
+} __packed;
+
+struct ieee_types_vht_cap {
+       struct ieee_types_header ieee_hdr;
+       struct ieee80211_vht_cap vhtcap;
+} __packed;
+
+struct ieee_types_vht_oper {
+       struct ieee_types_header ieee_hdr;
+       struct ieee80211_vht_operation vhtoper;
+} __packed;
+
+struct ieee_types_aid {
+       struct ieee_types_header ieee_hdr;
+       u16 aid;
+} __packed;
+
+struct mwifiex_bssdescriptor {
+       u8 mac_address[ETH_ALEN];
+       struct cfg80211_ssid ssid;
+       u32 privacy;
+       s32 rssi;
+       u32 channel;
+       u32 freq;
+       u16 beacon_period;
+       u8 erp_flags;
+       u32 bss_mode;
+       u8 supported_rates[MWIFIEX_SUPPORTED_RATES];
+       u8 data_rates[MWIFIEX_SUPPORTED_RATES];
+       /* Network band.
+        * BAND_B(0x01): 'b' band
+        * BAND_G(0x02): 'g' band
+        * BAND_A(0X04): 'a' band
+        */
+       u16 bss_band;
+       u64 fw_tsf;
+       u64 timestamp;
+       union ieee_types_phy_param_set phy_param_set;
+       union ieee_types_ss_param_set ss_param_set;
+       u16 cap_info_bitmap;
+       struct ieee_types_wmm_parameter wmm_ie;
+       u8  disable_11n;
+       struct ieee80211_ht_cap *bcn_ht_cap;
+       u16 ht_cap_offset;
+       struct ieee80211_ht_operation *bcn_ht_oper;
+       u16 ht_info_offset;
+       u8 *bcn_bss_co_2040;
+       u16 bss_co_2040_offset;
+       u8 *bcn_ext_cap;
+       u16 ext_cap_offset;
+       struct ieee80211_vht_cap *bcn_vht_cap;
+       u16 vht_cap_offset;
+       struct ieee80211_vht_operation *bcn_vht_oper;
+       u16 vht_info_offset;
+       struct ieee_types_oper_mode_ntf *oper_mode;
+       u16 oper_mode_offset;
+       u8 disable_11ac;
+       struct ieee_types_vendor_specific *bcn_wpa_ie;
+       u16 wpa_offset;
+       struct ieee_types_generic *bcn_rsn_ie;
+       u16 rsn_offset;
+       struct ieee_types_generic *bcn_wapi_ie;
+       u16 wapi_offset;
+       u8 *beacon_buf;
+       u32 beacon_buf_size;
+       u8 sensed_11h;
+       u8 local_constraint;
+       u8 chan_sw_ie_present;
+};
+
+struct mwifiex_current_bss_params {
+       struct mwifiex_bssdescriptor bss_descriptor;
+       u8 wmm_enabled;
+       u8 wmm_uapsd_enabled;
+       u8 band;
+       u32 num_of_rates;
+       u8 data_rates[MWIFIEX_SUPPORTED_RATES];
+};
+
+struct mwifiex_sleep_params {
+       u16 sp_error;
+       u16 sp_offset;
+       u16 sp_stable_time;
+       u8 sp_cal_control;
+       u8 sp_ext_sleep_clk;
+       u16 sp_reserved;
+};
+
+struct mwifiex_sleep_period {
+       u16 period;
+       u16 reserved;
+};
+
+struct mwifiex_wep_key {
+       u32 length;
+       u32 key_index;
+       u32 key_length;
+       u8 key_material[MWIFIEX_KEY_BUFFER_SIZE];
+};
+
+#define MAX_REGION_CHANNEL_NUM  2
+
+struct mwifiex_chan_freq_power {
+       u16 channel;
+       u32 freq;
+       u16 max_tx_power;
+       u8 unsupported;
+};
+
+enum state_11d_t {
+       DISABLE_11D = 0,
+       ENABLE_11D = 1,
+};
+
+#define MWIFIEX_MAX_TRIPLET_802_11D            83
+
+struct mwifiex_802_11d_domain_reg {
+       u8 country_code[IEEE80211_COUNTRY_STRING_LEN];
+       u8 no_of_triplet;
+       struct ieee80211_country_ie_triplet
+               triplet[MWIFIEX_MAX_TRIPLET_802_11D];
+};
+
+struct mwifiex_vendor_spec_cfg_ie {
+       u16 mask;
+       u16 flag;
+       u8 ie[MWIFIEX_MAX_VSIE_LEN];
+};
+
+struct wps {
+       u8 session_enable;
+};
+
+struct mwifiex_roc_cfg {
+       u64 cookie;
+       struct ieee80211_channel chan;
+};
+
+#define MWIFIEX_FW_DUMP_IDX            0xff
+#define MWIFIEX_DRV_INFO_IDX           20
+#define FW_DUMP_MAX_NAME_LEN           8
+#define FW_DUMP_HOST_READY             0xEE
+#define FW_DUMP_DONE                   0xFF
+#define FW_DUMP_READ_DONE              0xFE
+
+struct memory_type_mapping {
+       u8 mem_name[FW_DUMP_MAX_NAME_LEN];
+       u8 *mem_ptr;
+       u32 mem_size;
+       u8 done_flag;
+};
+
+enum rdwr_status {
+       RDWR_STATUS_SUCCESS = 0,
+       RDWR_STATUS_FAILURE = 1,
+       RDWR_STATUS_DONE = 2
+};
+
+enum mwifiex_iface_work_flags {
+       MWIFIEX_IFACE_WORK_DEVICE_DUMP,
+       MWIFIEX_IFACE_WORK_CARD_RESET,
+};
+
+struct mwifiex_private {
+       struct mwifiex_adapter *adapter;
+       u8 bss_type;
+       u8 bss_role;
+       u8 bss_priority;
+       u8 bss_num;
+       u8 bss_started;
+       u8 frame_type;
+       u8 curr_addr[ETH_ALEN];
+       u8 media_connected;
+       u8 port_open;
+       u8 usb_port;
+       u32 num_tx_timeout;
+       /* track consecutive timeout */
+       u8 tx_timeout_cnt;
+       struct net_device *netdev;
+       struct net_device_stats stats;
+       u16 curr_pkt_filter;
+       u32 bss_mode;
+       u32 pkt_tx_ctrl;
+       u16 tx_power_level;
+       u8 max_tx_power_level;
+       u8 min_tx_power_level;
+       u8 tx_rate;
+       u8 tx_htinfo;
+       u8 rxpd_htinfo;
+       u8 rxpd_rate;
+       u16 rate_bitmap;
+       u16 bitmap_rates[MAX_BITMAP_RATES_SIZE];
+       u32 data_rate;
+       u8 is_data_rate_auto;
+       u16 bcn_avg_factor;
+       u16 data_avg_factor;
+       s16 data_rssi_last;
+       s16 data_nf_last;
+       s16 data_rssi_avg;
+       s16 data_nf_avg;
+       s16 bcn_rssi_last;
+       s16 bcn_nf_last;
+       s16 bcn_rssi_avg;
+       s16 bcn_nf_avg;
+       struct mwifiex_bssdescriptor *attempted_bss_desc;
+       struct cfg80211_ssid prev_ssid;
+       u8 prev_bssid[ETH_ALEN];
+       struct mwifiex_current_bss_params curr_bss_params;
+       u16 beacon_period;
+       u8 dtim_period;
+       u16 listen_interval;
+       u16 atim_window;
+       u8 adhoc_channel;
+       u8 adhoc_is_link_sensed;
+       u8 adhoc_state;
+       struct mwifiex_802_11_security sec_info;
+       struct mwifiex_wep_key wep_key[NUM_WEP_KEYS];
+       u16 wep_key_curr_index;
+       u8 wpa_ie[256];
+       u8 wpa_ie_len;
+       u8 wpa_is_gtk_set;
+       struct host_cmd_ds_802_11_key_material aes_key;
+       struct host_cmd_ds_802_11_key_material_v2 aes_key_v2;
+       u8 wapi_ie[256];
+       u8 wapi_ie_len;
+       u8 *wps_ie;
+       u8 wps_ie_len;
+       u8 wmm_required;
+       u8 wmm_enabled;
+       u8 wmm_qosinfo;
+       struct mwifiex_wmm_desc wmm;
+       atomic_t wmm_tx_pending[IEEE80211_NUM_ACS];
+       struct list_head sta_list;
+       /* spin lock for associated station/TDLS peers list */
+       spinlock_t sta_list_spinlock;
+       struct list_head auto_tdls_list;
+       /* spin lock for auto TDLS peer list */
+       spinlock_t auto_tdls_lock;
+       struct list_head tx_ba_stream_tbl_ptr;
+       /* spin lock for tx_ba_stream_tbl_ptr queue */
+       spinlock_t tx_ba_stream_tbl_lock;
+       struct mwifiex_tx_aggr aggr_prio_tbl[MAX_NUM_TID];
+       struct mwifiex_add_ba_param add_ba_param;
+       u16 rx_seq[MAX_NUM_TID];
+       u8 tos_to_tid_inv[MAX_NUM_TID];
+       struct list_head rx_reorder_tbl_ptr;
+       /* spin lock for rx_reorder_tbl_ptr queue */
+       spinlock_t rx_reorder_tbl_lock;
+       /* spin lock for Rx packets */
+       spinlock_t rx_pkt_lock;
+
+#define MWIFIEX_ASSOC_RSP_BUF_SIZE  500
+       u8 assoc_rsp_buf[MWIFIEX_ASSOC_RSP_BUF_SIZE];
+       u32 assoc_rsp_size;
+
+#define MWIFIEX_GENIE_BUF_SIZE      256
+       u8 gen_ie_buf[MWIFIEX_GENIE_BUF_SIZE];
+       u8 gen_ie_buf_len;
+
+       struct mwifiex_vendor_spec_cfg_ie vs_ie[MWIFIEX_MAX_VSIE_NUM];
+
+#define MWIFIEX_ASSOC_TLV_BUF_SIZE  256
+       u8 assoc_tlv_buf[MWIFIEX_ASSOC_TLV_BUF_SIZE];
+       u8 assoc_tlv_buf_len;
+
+       u8 *curr_bcn_buf;
+       u32 curr_bcn_size;
+       /* spin lock for beacon buffer */
+       spinlock_t curr_bcn_buf_lock;
+       struct wireless_dev wdev;
+       struct mwifiex_chan_freq_power cfp;
+       char version_str[128];
+#ifdef CONFIG_DEBUG_FS
+       struct dentry *dfs_dev_dir;
+#endif
+       u16 current_key_index;
+       struct semaphore async_sem;
+       struct cfg80211_scan_request *scan_request;
+       u8 cfg_bssid[6];
+       struct wps wps;
+       u8 scan_block;
+       s32 cqm_rssi_thold;
+       u32 cqm_rssi_hyst;
+       u8 subsc_evt_rssi_state;
+       struct mwifiex_ds_misc_subsc_evt async_subsc_evt_storage;
+       struct mwifiex_ie mgmt_ie[MAX_MGMT_IE_INDEX];
+       u16 beacon_idx;
+       u16 proberesp_idx;
+       u16 assocresp_idx;
+       u16 gen_idx;
+       u8 ap_11n_enabled;
+       u8 ap_11ac_enabled;
+       u32 mgmt_frame_mask;
+       struct mwifiex_roc_cfg roc_cfg;
+       bool scan_aborting;
+       u8 csa_chan;
+       unsigned long csa_expire_time;
+       u8 del_list_idx;
+       bool hs2_enabled;
+       struct mwifiex_uap_bss_param bss_cfg;
+       struct cfg80211_chan_def bss_chandef;
+       struct station_parameters *sta_params;
+       struct sk_buff_head tdls_txq;
+       u8 check_tdls_tx;
+       struct timer_list auto_tdls_timer;
+       bool auto_tdls_timer_active;
+       struct idr ack_status_frames;
+       /* spin lock for ack status */
+       spinlock_t ack_status_lock;
+       /** rx histogram data */
+       struct mwifiex_histogram_data *hist_data;
+       struct cfg80211_chan_def dfs_chandef;
+       struct workqueue_struct *dfs_cac_workqueue;
+       struct delayed_work dfs_cac_work;
+       struct timer_list dfs_chan_switch_timer;
+       struct workqueue_struct *dfs_chan_sw_workqueue;
+       struct delayed_work dfs_chan_sw_work;
+       struct cfg80211_beacon_data beacon_after;
+       struct mwifiex_11h_intf_state state_11h;
+       struct mwifiex_ds_mem_rw mem_rw;
+       struct sk_buff_head bypass_txq;
+       struct mwifiex_user_scan_chan hidden_chan[MWIFIEX_USER_SCAN_CHAN_MAX];
+};
+
+
+struct mwifiex_tx_ba_stream_tbl {
+       struct list_head list;
+       int tid;
+       u8 ra[ETH_ALEN];
+       enum mwifiex_ba_status ba_status;
+       u8 amsdu;
+};
+
+struct mwifiex_rx_reorder_tbl;
+
+struct reorder_tmr_cnxt {
+       struct timer_list timer;
+       struct mwifiex_rx_reorder_tbl *ptr;
+       struct mwifiex_private *priv;
+       u8 timer_is_set;
+};
+
+struct mwifiex_rx_reorder_tbl {
+       struct list_head list;
+       int tid;
+       u8 ta[ETH_ALEN];
+       int init_win;
+       int start_win;
+       int win_size;
+       void **rx_reorder_ptr;
+       struct reorder_tmr_cnxt timer_context;
+       u8 amsdu;
+       u8 flags;
+};
+
+struct mwifiex_bss_prio_node {
+       struct list_head list;
+       struct mwifiex_private *priv;
+};
+
+struct mwifiex_bss_prio_tbl {
+       struct list_head bss_prio_head;
+       /* spin lock for bss priority  */
+       spinlock_t bss_prio_lock;
+       struct mwifiex_bss_prio_node *bss_prio_cur;
+};
+
+struct cmd_ctrl_node {
+       struct list_head list;
+       struct mwifiex_private *priv;
+       u32 cmd_oid;
+       u32 cmd_flag;
+       struct sk_buff *cmd_skb;
+       struct sk_buff *resp_skb;
+       void *data_buf;
+       u32 wait_q_enabled;
+       struct sk_buff *skb;
+       u8 *condition;
+       u8 cmd_wait_q_woken;
+};
+
+struct mwifiex_bss_priv {
+       u8 band;
+       u64 fw_tsf;
+};
+
+struct mwifiex_tdls_capab {
+       __le16 capab;
+       u8 rates[32];
+       u8 rates_len;
+       u8 qos_info;
+       u8 coex_2040;
+       u16 aid;
+       struct ieee80211_ht_cap ht_capb;
+       struct ieee80211_ht_operation ht_oper;
+       struct ieee_types_extcap extcap;
+       struct ieee_types_generic rsn_ie;
+       struct ieee80211_vht_cap vhtcap;
+       struct ieee80211_vht_operation vhtoper;
+};
+
+struct mwifiex_station_stats {
+       u64 last_rx;
+       s8 rssi;
+       u64 rx_bytes;
+       u64 tx_bytes;
+       u32 rx_packets;
+       u32 tx_packets;
+       u32 tx_failed;
+       u8 last_tx_rate;
+       u8 last_tx_htinfo;
+};
+
+/* This is AP/TDLS specific structure which stores information
+ * about associated/peer STA
+ */
+struct mwifiex_sta_node {
+       struct list_head list;
+       u8 mac_addr[ETH_ALEN];
+       u8 is_wmm_enabled;
+       u8 is_11n_enabled;
+       u8 is_11ac_enabled;
+       u8 ampdu_sta[MAX_NUM_TID];
+       u16 rx_seq[MAX_NUM_TID];
+       u16 max_amsdu;
+       u8 tdls_status;
+       struct mwifiex_tdls_capab tdls_cap;
+       struct mwifiex_station_stats stats;
+       u8 tx_pause;
+};
+
+struct mwifiex_auto_tdls_peer {
+       struct list_head list;
+       u8 mac_addr[ETH_ALEN];
+       u8 tdls_status;
+       int rssi;
+       long rssi_jiffies;
+       u8 failure_count;
+       u8 do_discover;
+       u8 do_setup;
+};
+
+struct mwifiex_if_ops {
+       int (*init_if) (struct mwifiex_adapter *);
+       void (*cleanup_if) (struct mwifiex_adapter *);
+       int (*check_fw_status) (struct mwifiex_adapter *, u32);
+       int (*prog_fw) (struct mwifiex_adapter *, struct mwifiex_fw_image *);
+       int (*register_dev) (struct mwifiex_adapter *);
+       void (*unregister_dev) (struct mwifiex_adapter *);
+       int (*enable_int) (struct mwifiex_adapter *);
+       void (*disable_int) (struct mwifiex_adapter *);
+       int (*process_int_status) (struct mwifiex_adapter *);
+       int (*host_to_card) (struct mwifiex_adapter *, u8, struct sk_buff *,
+                            struct mwifiex_tx_param *);
+       int (*wakeup) (struct mwifiex_adapter *);
+       int (*wakeup_complete) (struct mwifiex_adapter *);
+
+       /* Interface specific functions */
+       void (*update_mp_end_port) (struct mwifiex_adapter *, u16);
+       void (*cleanup_mpa_buf) (struct mwifiex_adapter *);
+       int (*cmdrsp_complete) (struct mwifiex_adapter *, struct sk_buff *);
+       int (*event_complete) (struct mwifiex_adapter *, struct sk_buff *);
+       int (*init_fw_port) (struct mwifiex_adapter *);
+       int (*dnld_fw) (struct mwifiex_adapter *, struct mwifiex_fw_image *);
+       void (*card_reset) (struct mwifiex_adapter *);
+       int (*reg_dump)(struct mwifiex_adapter *, char *);
+       void (*device_dump)(struct mwifiex_adapter *);
+       int (*clean_pcie_ring) (struct mwifiex_adapter *adapter);
+       void (*iface_work)(struct work_struct *work);
+       void (*submit_rem_rx_urbs)(struct mwifiex_adapter *adapter);
+       void (*deaggr_pkt)(struct mwifiex_adapter *, struct sk_buff *);
+       void (*multi_port_resync)(struct mwifiex_adapter *);
+       bool (*is_port_ready)(struct mwifiex_private *);
+};
+
+struct mwifiex_adapter {
+       u8 iface_type;
+       unsigned int debug_mask;
+       struct mwifiex_iface_comb iface_limit;
+       struct mwifiex_iface_comb curr_iface_comb;
+       struct mwifiex_private *priv[MWIFIEX_MAX_BSS_NUM];
+       u8 priv_num;
+       const struct firmware *firmware;
+       char fw_name[32];
+       int winner;
+       struct device *dev;
+       struct wiphy *wiphy;
+       u8 perm_addr[ETH_ALEN];
+       bool surprise_removed;
+       u32 fw_release_number;
+       u16 init_wait_q_woken;
+       wait_queue_head_t init_wait_q;
+       void *card;
+       struct mwifiex_if_ops if_ops;
+       atomic_t bypass_tx_pending;
+       atomic_t rx_pending;
+       atomic_t tx_pending;
+       atomic_t cmd_pending;
+       struct workqueue_struct *workqueue;
+       struct work_struct main_work;
+       struct workqueue_struct *rx_workqueue;
+       struct work_struct rx_work;
+       struct workqueue_struct *dfs_workqueue;
+       struct work_struct dfs_work;
+       bool rx_work_enabled;
+       bool rx_processing;
+       bool delay_main_work;
+       bool rx_locked;
+       bool main_locked;
+       struct mwifiex_bss_prio_tbl bss_prio_tbl[MWIFIEX_MAX_BSS_NUM];
+       /* spin lock for init/shutdown */
+       spinlock_t mwifiex_lock;
+       /* spin lock for main process */
+       spinlock_t main_proc_lock;
+       u32 mwifiex_processing;
+       u8 more_task_flag;
+       u16 tx_buf_size;
+       u16 curr_tx_buf_size;
+       /* sdio single port rx aggregation capability */
+       bool host_disable_sdio_rx_aggr;
+       bool sdio_rx_aggr_enable;
+       u16 sdio_rx_block_size;
+       u32 ioport;
+       enum MWIFIEX_HARDWARE_STATUS hw_status;
+       u16 number_of_antenna;
+       u32 fw_cap_info;
+       /* spin lock for interrupt handling */
+       spinlock_t int_lock;
+       u8 int_status;
+       u32 event_cause;
+       struct sk_buff *event_skb;
+       u8 upld_buf[MWIFIEX_UPLD_SIZE];
+       u8 data_sent;
+       u8 cmd_sent;
+       u8 cmd_resp_received;
+       u8 event_received;
+       u8 data_received;
+       u16 seq_num;
+       struct cmd_ctrl_node *cmd_pool;
+       struct cmd_ctrl_node *curr_cmd;
+       /* spin lock for command */
+       spinlock_t mwifiex_cmd_lock;
+       u8 is_cmd_timedout;
+       u16 last_init_cmd;
+       struct timer_list cmd_timer;
+       struct list_head cmd_free_q;
+       /* spin lock for cmd_free_q */
+       spinlock_t cmd_free_q_lock;
+       struct list_head cmd_pending_q;
+       /* spin lock for cmd_pending_q */
+       spinlock_t cmd_pending_q_lock;
+       struct list_head scan_pending_q;
+       /* spin lock for scan_pending_q */
+       spinlock_t scan_pending_q_lock;
+       /* spin lock for RX processing routine */
+       spinlock_t rx_proc_lock;
+       struct sk_buff_head tx_data_q;
+       atomic_t tx_queued;
+       u32 scan_processing;
+       u16 region_code;
+       struct mwifiex_802_11d_domain_reg domain_reg;
+       u16 scan_probes;
+       u32 scan_mode;
+       u16 specific_scan_time;
+       u16 active_scan_time;
+       u16 passive_scan_time;
+       u16 scan_chan_gap_time;
+       u8 fw_bands;
+       u8 adhoc_start_band;
+       u8 config_bands;
+       struct mwifiex_chan_scan_param_set *scan_channels;
+       u8 tx_lock_flag;
+       struct mwifiex_sleep_params sleep_params;
+       struct mwifiex_sleep_period sleep_period;
+       u16 ps_mode;
+       u32 ps_state;
+       u8 need_to_wakeup;
+       u16 multiple_dtim;
+       u16 local_listen_interval;
+       u16 null_pkt_interval;
+       struct sk_buff *sleep_cfm;
+       u16 bcn_miss_time_out;
+       u16 adhoc_awake_period;
+       u8 is_deep_sleep;
+       u8 delay_null_pkt;
+       u16 delay_to_ps;
+       u16 enhanced_ps_mode;
+       u8 pm_wakeup_card_req;
+       u16 gen_null_pkt;
+       u16 pps_uapsd_mode;
+       u32 pm_wakeup_fw_try;
+       struct timer_list wakeup_timer;
+       u8 is_hs_configured;
+       struct mwifiex_hs_config_param hs_cfg;
+       u8 hs_activated;
+       u16 hs_activate_wait_q_woken;
+       wait_queue_head_t hs_activate_wait_q;
+       bool is_suspended;
+       bool hs_enabling;
+       u8 event_body[MAX_EVENT_SIZE];
+       u32 hw_dot_11n_dev_cap;
+       u8 hw_dev_mcs_support;
+       u8 user_dev_mcs_support;
+       u8 adhoc_11n_enabled;
+       u8 sec_chan_offset;
+       struct mwifiex_dbg dbg;
+       u8 arp_filter[ARP_FILTER_MAX_BUF_SIZE];
+       u32 arp_filter_size;
+       struct mwifiex_wait_queue cmd_wait_q;
+       u8 scan_wait_q_woken;
+       spinlock_t queue_lock;          /* lock for tx queues */
+       u8 country_code[IEEE80211_COUNTRY_STRING_LEN];
+       u16 max_mgmt_ie_index;
+       const struct firmware *cal_data;
+       struct device_node *dt_node;
+
+       /* 11AC */
+       u32 is_hw_11ac_capable;
+       u32 hw_dot_11ac_dev_cap;
+       u32 hw_dot_11ac_mcs_support;
+       u32 usr_dot_11ac_dev_cap_bg;
+       u32 usr_dot_11ac_dev_cap_a;
+       u32 usr_dot_11ac_mcs_support;
+
+       atomic_t pending_bridged_pkts;
+       struct semaphore *card_sem;
+       bool ext_scan;
+       u8 fw_api_ver;
+       u8 key_api_major_ver, key_api_minor_ver;
+       struct memory_type_mapping *mem_type_mapping_tbl;
+       u8 num_mem_types;
+       void *drv_info_dump;
+       u32 drv_info_size;
+       bool scan_chan_gap_enabled;
+       struct sk_buff_head rx_data_q;
+       struct mwifiex_chan_stats *chan_stats;
+       u32 num_in_chan_stats;
+       int survey_idx;
+       bool auto_tdls;
+       u8 coex_scan;
+       u8 coex_min_scan_time;
+       u8 coex_max_scan_time;
+       u8 coex_win_size;
+       u8 coex_tx_win_size;
+       u8 coex_rx_win_size;
+       bool drcs_enabled;
+       u8 active_scan_triggered;
+       bool usb_mc_status;
+       bool usb_mc_setup;
+};
+
+void mwifiex_process_tx_queue(struct mwifiex_adapter *adapter);
+
+int mwifiex_init_lock_list(struct mwifiex_adapter *adapter);
+
+void mwifiex_set_trans_start(struct net_device *dev);
+
+void mwifiex_stop_net_dev_queue(struct net_device *netdev,
+               struct mwifiex_adapter *adapter);
+
+void mwifiex_wake_up_net_dev_queue(struct net_device *netdev,
+               struct mwifiex_adapter *adapter);
+
+int mwifiex_init_priv(struct mwifiex_private *priv);
+void mwifiex_free_priv(struct mwifiex_private *priv);
+
+int mwifiex_init_fw(struct mwifiex_adapter *adapter);
+
+int mwifiex_init_fw_complete(struct mwifiex_adapter *adapter);
+
+int mwifiex_shutdown_drv(struct mwifiex_adapter *adapter);
+
+int mwifiex_shutdown_fw_complete(struct mwifiex_adapter *adapter);
+
+int mwifiex_dnld_fw(struct mwifiex_adapter *, struct mwifiex_fw_image *);
+
+int mwifiex_recv_packet(struct mwifiex_private *priv, struct sk_buff *skb);
+
+int mwifiex_process_mgmt_packet(struct mwifiex_private *priv,
+                               struct sk_buff *skb);
+
+int mwifiex_process_event(struct mwifiex_adapter *adapter);
+
+int mwifiex_complete_cmd(struct mwifiex_adapter *adapter,
+                        struct cmd_ctrl_node *cmd_node);
+
+int mwifiex_send_cmd(struct mwifiex_private *priv, u16 cmd_no,
+                    u16 cmd_action, u32 cmd_oid, void *data_buf, bool sync);
+
+void mwifiex_cmd_timeout_func(unsigned long function_context);
+
+int mwifiex_get_debug_info(struct mwifiex_private *,
+                          struct mwifiex_debug_info *);
+
+int mwifiex_alloc_cmd_buffer(struct mwifiex_adapter *adapter);
+int mwifiex_free_cmd_buffer(struct mwifiex_adapter *adapter);
+void mwifiex_cancel_all_pending_cmd(struct mwifiex_adapter *adapter);
+void mwifiex_cancel_pending_ioctl(struct mwifiex_adapter *adapter);
+
+void mwifiex_insert_cmd_to_free_q(struct mwifiex_adapter *adapter,
+                                 struct cmd_ctrl_node *cmd_node);
+void mwifiex_recycle_cmd_node(struct mwifiex_adapter *adapter,
+                             struct cmd_ctrl_node *cmd_node);
+
+void mwifiex_insert_cmd_to_pending_q(struct mwifiex_adapter *adapter,
+                                    struct cmd_ctrl_node *cmd_node,
+                                    u32 addtail);
+
+int mwifiex_exec_next_cmd(struct mwifiex_adapter *adapter);
+int mwifiex_process_cmdresp(struct mwifiex_adapter *adapter);
+int mwifiex_handle_rx_packet(struct mwifiex_adapter *adapter,
+                            struct sk_buff *skb);
+int mwifiex_process_tx(struct mwifiex_private *priv, struct sk_buff *skb,
+                      struct mwifiex_tx_param *tx_param);
+int mwifiex_send_null_packet(struct mwifiex_private *priv, u8 flags);
+int mwifiex_write_data_complete(struct mwifiex_adapter *adapter,
+                               struct sk_buff *skb, int aggr, int status);
+void mwifiex_clean_txrx(struct mwifiex_private *priv);
+u8 mwifiex_check_last_packet_indication(struct mwifiex_private *priv);
+void mwifiex_check_ps_cond(struct mwifiex_adapter *adapter);
+void mwifiex_process_sleep_confirm_resp(struct mwifiex_adapter *, u8 *,
+                                       u32);
+int mwifiex_cmd_enh_power_mode(struct mwifiex_private *priv,
+                              struct host_cmd_ds_command *cmd,
+                              u16 cmd_action, uint16_t ps_bitmap,
+                              struct mwifiex_ds_auto_ds *auto_ds);
+int mwifiex_ret_enh_power_mode(struct mwifiex_private *priv,
+                              struct host_cmd_ds_command *resp,
+                              struct mwifiex_ds_pm_cfg *pm_cfg);
+void mwifiex_process_hs_config(struct mwifiex_adapter *adapter);
+void mwifiex_hs_activated_event(struct mwifiex_private *priv,
+                                       u8 activated);
+int mwifiex_set_hs_params(struct mwifiex_private *priv, u16 action,
+                         int cmd_type, struct mwifiex_ds_hs_cfg *hs_cfg);
+int mwifiex_ret_802_11_hs_cfg(struct mwifiex_private *priv,
+                             struct host_cmd_ds_command *resp);
+int mwifiex_process_rx_packet(struct mwifiex_private *priv,
+                             struct sk_buff *skb);
+int mwifiex_sta_prepare_cmd(struct mwifiex_private *, uint16_t cmd_no,
+                           u16 cmd_action, u32 cmd_oid,
+                           void *data_buf, void *cmd_buf);
+int mwifiex_uap_prepare_cmd(struct mwifiex_private *priv, uint16_t cmd_no,
+                           u16 cmd_action, u32 cmd_oid,
+                           void *data_buf, void *cmd_buf);
+int mwifiex_process_sta_cmdresp(struct mwifiex_private *, u16 cmdresp_no,
+                               struct host_cmd_ds_command *resp);
+int mwifiex_process_sta_rx_packet(struct mwifiex_private *,
+                                 struct sk_buff *skb);
+int mwifiex_process_uap_rx_packet(struct mwifiex_private *priv,
+                                 struct sk_buff *skb);
+int mwifiex_handle_uap_rx_forward(struct mwifiex_private *priv,
+                                 struct sk_buff *skb);
+int mwifiex_process_sta_event(struct mwifiex_private *);
+int mwifiex_process_uap_event(struct mwifiex_private *);
+void mwifiex_delete_all_station_list(struct mwifiex_private *priv);
+void mwifiex_wmm_del_peer_ra_list(struct mwifiex_private *priv,
+                                 const u8 *ra_addr);
+void *mwifiex_process_sta_txpd(struct mwifiex_private *, struct sk_buff *skb);
+void *mwifiex_process_uap_txpd(struct mwifiex_private *, struct sk_buff *skb);
+int mwifiex_sta_init_cmd(struct mwifiex_private *, u8 first_sta, bool init);
+int mwifiex_cmd_802_11_scan(struct host_cmd_ds_command *cmd,
+                           struct mwifiex_scan_cmd_config *scan_cfg);
+void mwifiex_queue_scan_cmd(struct mwifiex_private *priv,
+                           struct cmd_ctrl_node *cmd_node);
+int mwifiex_ret_802_11_scan(struct mwifiex_private *priv,
+                           struct host_cmd_ds_command *resp);
+s32 mwifiex_ssid_cmp(struct cfg80211_ssid *ssid1, struct cfg80211_ssid *ssid2);
+int mwifiex_associate(struct mwifiex_private *priv,
+                     struct mwifiex_bssdescriptor *bss_desc);
+int mwifiex_cmd_802_11_associate(struct mwifiex_private *priv,
+                                struct host_cmd_ds_command *cmd,
+                                struct mwifiex_bssdescriptor *bss_desc);
+int mwifiex_ret_802_11_associate(struct mwifiex_private *priv,
+                                struct host_cmd_ds_command *resp);
+void mwifiex_reset_connect_state(struct mwifiex_private *priv, u16 reason);
+u8 mwifiex_band_to_radio_type(u8 band);
+int mwifiex_deauthenticate(struct mwifiex_private *priv, u8 *mac);
+void mwifiex_deauthenticate_all(struct mwifiex_adapter *adapter);
+int mwifiex_adhoc_start(struct mwifiex_private *priv,
+                       struct cfg80211_ssid *adhoc_ssid);
+int mwifiex_adhoc_join(struct mwifiex_private *priv,
+                      struct mwifiex_bssdescriptor *bss_desc);
+int mwifiex_cmd_802_11_ad_hoc_start(struct mwifiex_private *priv,
+                                   struct host_cmd_ds_command *cmd,
+                                   struct cfg80211_ssid *req_ssid);
+int mwifiex_cmd_802_11_ad_hoc_join(struct mwifiex_private *priv,
+                                  struct host_cmd_ds_command *cmd,
+                                  struct mwifiex_bssdescriptor *bss_desc);
+int mwifiex_ret_802_11_ad_hoc(struct mwifiex_private *priv,
+                             struct host_cmd_ds_command *resp);
+int mwifiex_cmd_802_11_bg_scan_query(struct host_cmd_ds_command *cmd);
+struct mwifiex_chan_freq_power *mwifiex_get_cfp(struct mwifiex_private *priv,
+                                               u8 band, u16 channel, u32 freq);
+u32 mwifiex_index_to_data_rate(struct mwifiex_private *priv,
+                              u8 index, u8 ht_info);
+u32 mwifiex_index_to_acs_data_rate(struct mwifiex_private *priv,
+                                  u8 index, u8 ht_info);
+u32 mwifiex_find_freq_from_band_chan(u8, u8);
+int mwifiex_cmd_append_vsie_tlv(struct mwifiex_private *priv, u16 vsie_mask,
+                               u8 **buffer);
+u32 mwifiex_get_active_data_rates(struct mwifiex_private *priv,
+                                   u8 *rates);
+u32 mwifiex_get_supported_rates(struct mwifiex_private *priv, u8 *rates);
+u32 mwifiex_get_rates_from_cfg80211(struct mwifiex_private *priv,
+                                   u8 *rates, u8 radio_type);
+u8 mwifiex_is_rate_auto(struct mwifiex_private *priv);
+extern u16 region_code_index[MWIFIEX_MAX_REGION_CODE];
+void mwifiex_save_curr_bcn(struct mwifiex_private *priv);
+void mwifiex_free_curr_bcn(struct mwifiex_private *priv);
+int mwifiex_cmd_get_hw_spec(struct mwifiex_private *priv,
+                           struct host_cmd_ds_command *cmd);
+int mwifiex_ret_get_hw_spec(struct mwifiex_private *priv,
+                           struct host_cmd_ds_command *resp);
+int is_command_pending(struct mwifiex_adapter *adapter);
+void mwifiex_init_priv_params(struct mwifiex_private *priv,
+                                               struct net_device *dev);
+int mwifiex_set_secure_params(struct mwifiex_private *priv,
+                             struct mwifiex_uap_bss_param *bss_config,
+                             struct cfg80211_ap_settings *params);
+void mwifiex_set_ht_params(struct mwifiex_private *priv,
+                          struct mwifiex_uap_bss_param *bss_cfg,
+                          struct cfg80211_ap_settings *params);
+void mwifiex_set_vht_params(struct mwifiex_private *priv,
+                           struct mwifiex_uap_bss_param *bss_cfg,
+                           struct cfg80211_ap_settings *params);
+void mwifiex_set_tpc_params(struct mwifiex_private *priv,
+                           struct mwifiex_uap_bss_param *bss_cfg,
+                           struct cfg80211_ap_settings *params);
+void mwifiex_set_uap_rates(struct mwifiex_uap_bss_param *bss_cfg,
+                          struct cfg80211_ap_settings *params);
+void mwifiex_set_vht_width(struct mwifiex_private *priv,
+                          enum nl80211_chan_width width,
+                          bool ap_11ac_disable);
+void
+mwifiex_set_wmm_params(struct mwifiex_private *priv,
+                      struct mwifiex_uap_bss_param *bss_cfg,
+                      struct cfg80211_ap_settings *params);
+void mwifiex_set_ba_params(struct mwifiex_private *priv);
+
+void mwifiex_update_ampdu_txwinsize(struct mwifiex_adapter *pmadapter);
+void mwifiex_bt_coex_wlan_param_update_event(struct mwifiex_private *priv,
+                                            struct sk_buff *event_skb);
+
+void mwifiex_set_11ac_ba_params(struct mwifiex_private *priv);
+int mwifiex_cmd_802_11_scan_ext(struct mwifiex_private *priv,
+                               struct host_cmd_ds_command *cmd,
+                               void *data_buf);
+int mwifiex_ret_802_11_scan_ext(struct mwifiex_private *priv,
+                               struct host_cmd_ds_command *resp);
+int mwifiex_handle_event_ext_scan_report(struct mwifiex_private *priv,
+                                        void *buf);
+
+/*
+ * This function checks if the queuing is RA based or not.
+ */
+static inline u8
+mwifiex_queuing_ra_based(struct mwifiex_private *priv)
+{
+       /*
+        * Currently we assume if we are in Infra, then DA=RA. This might not be
+        * true in the future
+        */
+       if ((priv->bss_mode == NL80211_IFTYPE_STATION) &&
+           (GET_BSS_ROLE(priv) == MWIFIEX_BSS_ROLE_STA))
+               return false;
+
+       return true;
+}
+
+/*
+ * This function copies rates.
+ */
+static inline u32
+mwifiex_copy_rates(u8 *dest, u32 pos, u8 *src, int len)
+{
+       int i;
+
+       for (i = 0; i < len && src[i]; i++, pos++) {
+               if (pos >= MWIFIEX_SUPPORTED_RATES)
+                       break;
+               dest[pos] = src[i];
+       }
+
+       return pos;
+}
+
+/*
+ * This function returns the correct private structure pointer based
+ * upon the BSS type and BSS number.
+ */
+static inline struct mwifiex_private *
+mwifiex_get_priv_by_id(struct mwifiex_adapter *adapter,
+                      u8 bss_num, u8 bss_type)
+{
+       int i;
+
+       for (i = 0; i < adapter->priv_num; i++) {
+               if (adapter->priv[i]) {
+                       if ((adapter->priv[i]->bss_num == bss_num) &&
+                           (adapter->priv[i]->bss_type == bss_type))
+                               break;
+               }
+       }
+       return ((i < adapter->priv_num) ? adapter->priv[i] : NULL);
+}
+
+/*
+ * This function returns the first available private structure pointer
+ * based upon the BSS role.
+ */
+static inline struct mwifiex_private *
+mwifiex_get_priv(struct mwifiex_adapter *adapter,
+                enum mwifiex_bss_role bss_role)
+{
+       int i;
+
+       for (i = 0; i < adapter->priv_num; i++) {
+               if (adapter->priv[i]) {
+                       if (bss_role == MWIFIEX_BSS_ROLE_ANY ||
+                           GET_BSS_ROLE(adapter->priv[i]) == bss_role)
+                               break;
+               }
+       }
+
+       return ((i < adapter->priv_num) ? adapter->priv[i] : NULL);
+}
+
+/*
+ * This function returns the first available unused private structure pointer.
+ */
+static inline struct mwifiex_private *
+mwifiex_get_unused_priv(struct mwifiex_adapter *adapter)
+{
+       int i;
+
+       for (i = 0; i < adapter->priv_num; i++) {
+               if (adapter->priv[i]) {
+                       if (adapter->priv[i]->bss_mode ==
+                           NL80211_IFTYPE_UNSPECIFIED)
+                               break;
+               }
+       }
+
+       return ((i < adapter->priv_num) ? adapter->priv[i] : NULL);
+}
+
+/*
+ * This function returns the driver private structure of a network device.
+ */
+static inline struct mwifiex_private *
+mwifiex_netdev_get_priv(struct net_device *dev)
+{
+       return (struct mwifiex_private *) (*(unsigned long *) netdev_priv(dev));
+}
+
+/*
+ * This function checks if a skb holds a management frame.
+ */
+static inline bool mwifiex_is_skb_mgmt_frame(struct sk_buff *skb)
+{
+       return (le32_to_cpu(*(__le32 *)skb->data) == PKT_TYPE_MGMT);
+}
+
+/* This function retrieves channel closed for operation by Channel
+ * Switch Announcement.
+ */
+static inline u8
+mwifiex_11h_get_csa_closed_channel(struct mwifiex_private *priv)
+{
+       if (!priv->csa_chan)
+               return 0;
+
+       /* Clear csa channel, if DFS channel move time has passed */
+       if (time_after(jiffies, priv->csa_expire_time)) {
+               priv->csa_chan = 0;
+               priv->csa_expire_time = 0;
+       }
+
+       return priv->csa_chan;
+}
+
+static inline u8 mwifiex_is_any_intf_active(struct mwifiex_private *priv)
+{
+       struct mwifiex_private *priv_num;
+       int i;
+
+       for (i = 0; i < priv->adapter->priv_num; i++) {
+               priv_num = priv->adapter->priv[i];
+               if (priv_num) {
+                       if ((GET_BSS_ROLE(priv_num) == MWIFIEX_BSS_ROLE_UAP &&
+                            priv_num->bss_started) ||
+                           (GET_BSS_ROLE(priv_num) == MWIFIEX_BSS_ROLE_STA &&
+                            priv_num->media_connected))
+                               return 1;
+               }
+       }
+
+       return 0;
+}
+
+static inline u8 mwifiex_is_tdls_link_setup(u8 status)
+{
+       switch (status) {
+       case TDLS_SETUP_COMPLETE:
+       case TDLS_CHAN_SWITCHING:
+       case TDLS_IN_BASE_CHAN:
+       case TDLS_IN_OFF_CHAN:
+               return true;
+       default:
+               break;
+       }
+
+       return false;
+}
+
+int mwifiex_init_shutdown_fw(struct mwifiex_private *priv,
+                            u32 func_init_shutdown);
+int mwifiex_add_card(void *, struct semaphore *, struct mwifiex_if_ops *, u8);
+int mwifiex_remove_card(struct mwifiex_adapter *, struct semaphore *);
+
+void mwifiex_get_version(struct mwifiex_adapter *adapter, char *version,
+                        int maxlen);
+int mwifiex_request_set_multicast_list(struct mwifiex_private *priv,
+                       struct mwifiex_multicast_list *mcast_list);
+int mwifiex_copy_mcast_addr(struct mwifiex_multicast_list *mlist,
+                           struct net_device *dev);
+int mwifiex_wait_queue_complete(struct mwifiex_adapter *adapter,
+                               struct cmd_ctrl_node *cmd_queued);
+int mwifiex_bss_start(struct mwifiex_private *priv, struct cfg80211_bss *bss,
+                     struct cfg80211_ssid *req_ssid);
+int mwifiex_cancel_hs(struct mwifiex_private *priv, int cmd_type);
+int mwifiex_enable_hs(struct mwifiex_adapter *adapter);
+int mwifiex_disable_auto_ds(struct mwifiex_private *priv);
+int mwifiex_drv_get_data_rate(struct mwifiex_private *priv, u32 *rate);
+int mwifiex_request_scan(struct mwifiex_private *priv,
+                        struct cfg80211_ssid *req_ssid);
+int mwifiex_scan_networks(struct mwifiex_private *priv,
+                         const struct mwifiex_user_scan_cfg *user_scan_in);
+int mwifiex_set_radio(struct mwifiex_private *priv, u8 option);
+
+int mwifiex_set_encode(struct mwifiex_private *priv, struct key_params *kp,
+                      const u8 *key, int key_len, u8 key_index,
+                      const u8 *mac_addr, int disable);
+
+int mwifiex_set_gen_ie(struct mwifiex_private *priv, const u8 *ie, int ie_len);
+
+int mwifiex_get_ver_ext(struct mwifiex_private *priv);
+
+int mwifiex_remain_on_chan_cfg(struct mwifiex_private *priv, u16 action,
+                              struct ieee80211_channel *chan,
+                              unsigned int duration);
+
+int mwifiex_get_stats_info(struct mwifiex_private *priv,
+                          struct mwifiex_ds_get_stats *log);
+
+int mwifiex_reg_write(struct mwifiex_private *priv, u32 reg_type,
+                     u32 reg_offset, u32 reg_value);
+
+int mwifiex_reg_read(struct mwifiex_private *priv, u32 reg_type,
+                    u32 reg_offset, u32 *value);
+
+int mwifiex_eeprom_read(struct mwifiex_private *priv, u16 offset, u16 bytes,
+                       u8 *value);
+
+int mwifiex_set_11n_httx_cfg(struct mwifiex_private *priv, int data);
+
+int mwifiex_get_11n_httx_cfg(struct mwifiex_private *priv, int *data);
+
+int mwifiex_set_tx_rate_cfg(struct mwifiex_private *priv, int tx_rate_index);
+
+int mwifiex_get_tx_rate_cfg(struct mwifiex_private *priv, int *tx_rate_index);
+
+int mwifiex_drv_set_power(struct mwifiex_private *priv, u32 *ps_mode);
+
+int mwifiex_drv_get_driver_version(struct mwifiex_adapter *adapter,
+                                  char *version, int max_len);
+
+int mwifiex_set_tx_power(struct mwifiex_private *priv,
+                        struct mwifiex_power_cfg *power_cfg);
+
+int mwifiex_main_process(struct mwifiex_adapter *);
+
+int mwifiex_queue_tx_pkt(struct mwifiex_private *priv, struct sk_buff *skb);
+
+int mwifiex_get_bss_info(struct mwifiex_private *,
+                        struct mwifiex_bss_info *);
+int mwifiex_fill_new_bss_desc(struct mwifiex_private *priv,
+                             struct cfg80211_bss *bss,
+                             struct mwifiex_bssdescriptor *bss_desc);
+int mwifiex_update_bss_desc_with_ie(struct mwifiex_adapter *adapter,
+                                   struct mwifiex_bssdescriptor *bss_entry);
+int mwifiex_check_network_compatibility(struct mwifiex_private *priv,
+                                       struct mwifiex_bssdescriptor *bss_desc);
+
+u8 mwifiex_chan_type_to_sec_chan_offset(enum nl80211_channel_type chan_type);
+u8 mwifiex_sec_chan_offset_to_chan_type(u8 second_chan_offset);
+
+struct wireless_dev *mwifiex_add_virtual_intf(struct wiphy *wiphy,
+                                             const char *name,
+                                             unsigned char name_assign_type,
+                                             enum nl80211_iftype type,
+                                             u32 *flags,
+                                             struct vif_params *params);
+int mwifiex_del_virtual_intf(struct wiphy *wiphy, struct wireless_dev *wdev);
+
+void mwifiex_set_sys_config_invalid_data(struct mwifiex_uap_bss_param *config);
+
+int mwifiex_add_wowlan_magic_pkt_filter(struct mwifiex_adapter *adapter);
+
+int mwifiex_set_mgmt_ies(struct mwifiex_private *priv,
+                        struct cfg80211_beacon_data *data);
+int mwifiex_del_mgmt_ies(struct mwifiex_private *priv);
+u8 *mwifiex_11d_code_2_region(u8 code);
+void mwifiex_uap_set_channel(struct mwifiex_private *priv,
+                            struct mwifiex_uap_bss_param *bss_cfg,
+                            struct cfg80211_chan_def chandef);
+int mwifiex_config_start_uap(struct mwifiex_private *priv,
+                            struct mwifiex_uap_bss_param *bss_cfg);
+void mwifiex_uap_del_sta_data(struct mwifiex_private *priv,
+                             struct mwifiex_sta_node *node);
+
+void mwifiex_init_11h_params(struct mwifiex_private *priv);
+int mwifiex_is_11h_active(struct mwifiex_private *priv);
+int mwifiex_11h_activate(struct mwifiex_private *priv, bool flag);
+
+void mwifiex_11h_process_join(struct mwifiex_private *priv, u8 **buffer,
+                             struct mwifiex_bssdescriptor *bss_desc);
+int mwifiex_11h_handle_event_chanswann(struct mwifiex_private *priv);
+int mwifiex_dnld_dt_cfgdata(struct mwifiex_private *priv,
+                           struct device_node *node, const char *prefix);
+void mwifiex_dnld_txpwr_table(struct mwifiex_private *priv);
+
+extern const struct ethtool_ops mwifiex_ethtool_ops;
+
+void mwifiex_del_all_sta_list(struct mwifiex_private *priv);
+void mwifiex_del_sta_entry(struct mwifiex_private *priv, const u8 *mac);
+void
+mwifiex_set_sta_ht_cap(struct mwifiex_private *priv, const u8 *ies,
+                      int ies_len, struct mwifiex_sta_node *node);
+struct mwifiex_sta_node *
+mwifiex_add_sta_entry(struct mwifiex_private *priv, const u8 *mac);
+struct mwifiex_sta_node *
+mwifiex_get_sta_entry(struct mwifiex_private *priv, const u8 *mac);
+u8 mwifiex_is_tdls_chan_switching(struct mwifiex_private *priv);
+u8 mwifiex_is_tdls_off_chan(struct mwifiex_private *priv);
+u8 mwifiex_is_send_cmd_allowed(struct mwifiex_private *priv);
+int mwifiex_send_tdls_data_frame(struct mwifiex_private *priv, const u8 *peer,
+                                u8 action_code, u8 dialog_token,
+                                u16 status_code, const u8 *extra_ies,
+                                size_t extra_ies_len);
+int mwifiex_send_tdls_action_frame(struct mwifiex_private *priv, const u8 *peer,
+                                  u8 action_code, u8 dialog_token,
+                                  u16 status_code, const u8 *extra_ies,
+                                  size_t extra_ies_len);
+void mwifiex_process_tdls_action_frame(struct mwifiex_private *priv,
+                                      u8 *buf, int len);
+int mwifiex_tdls_oper(struct mwifiex_private *priv, const u8 *peer, u8 action);
+int mwifiex_get_tdls_link_status(struct mwifiex_private *priv, const u8 *mac);
+int mwifiex_get_tdls_list(struct mwifiex_private *priv,
+                         struct tdls_peer_info *buf);
+void mwifiex_disable_all_tdls_links(struct mwifiex_private *priv);
+bool mwifiex_is_bss_in_11ac_mode(struct mwifiex_private *priv);
+u8 mwifiex_get_center_freq_index(struct mwifiex_private *priv, u8 band,
+                                u32 pri_chan, u8 chan_bw);
+int mwifiex_init_channel_scan_gap(struct mwifiex_adapter *adapter);
+
+int mwifiex_tdls_check_tx(struct mwifiex_private *priv, struct sk_buff *skb);
+void mwifiex_flush_auto_tdls_list(struct mwifiex_private *priv);
+void mwifiex_auto_tdls_update_peer_status(struct mwifiex_private *priv,
+                                         const u8 *mac, u8 link_status);
+void mwifiex_auto_tdls_update_peer_signal(struct mwifiex_private *priv,
+                                         u8 *mac, s8 snr, s8 nflr);
+void mwifiex_check_auto_tdls(unsigned long context);
+void mwifiex_add_auto_tdls_peer(struct mwifiex_private *priv, const u8 *mac);
+void mwifiex_setup_auto_tdls_timer(struct mwifiex_private *priv);
+void mwifiex_clean_auto_tdls(struct mwifiex_private *priv);
+int mwifiex_config_tdls_enable(struct mwifiex_private *priv);
+int mwifiex_config_tdls_disable(struct mwifiex_private *priv);
+int mwifiex_config_tdls_cs_params(struct mwifiex_private *priv);
+int mwifiex_stop_tdls_cs(struct mwifiex_private *priv, const u8 *peer_mac);
+int mwifiex_start_tdls_cs(struct mwifiex_private *priv, const u8 *peer_mac,
+                         u8 primary_chan, u8 second_chan_offset, u8 band);
+
+int mwifiex_cmd_issue_chan_report_request(struct mwifiex_private *priv,
+                                         struct host_cmd_ds_command *cmd,
+                                         void *data_buf);
+int mwifiex_11h_handle_chanrpt_ready(struct mwifiex_private *priv,
+                                    struct sk_buff *skb);
+
+void mwifiex_parse_tx_status_event(struct mwifiex_private *priv,
+                                  void *event_body);
+
+struct sk_buff *
+mwifiex_clone_skb_for_tx_status(struct mwifiex_private *priv,
+                               struct sk_buff *skb, u8 flag, u64 *cookie);
+void mwifiex_dfs_cac_work_queue(struct work_struct *work);
+void mwifiex_dfs_chan_sw_work_queue(struct work_struct *work);
+void mwifiex_abort_cac(struct mwifiex_private *priv);
+int mwifiex_stop_radar_detection(struct mwifiex_private *priv,
+                                struct cfg80211_chan_def *chandef);
+int mwifiex_11h_handle_radar_detected(struct mwifiex_private *priv,
+                                     struct sk_buff *skb);
+
+void mwifiex_hist_data_set(struct mwifiex_private *priv, u8 rx_rate, s8 snr,
+                          s8 nflr);
+void mwifiex_hist_data_reset(struct mwifiex_private *priv);
+void mwifiex_hist_data_add(struct mwifiex_private *priv,
+                          u8 rx_rate, s8 snr, s8 nflr);
+u8 mwifiex_adjust_data_rate(struct mwifiex_private *priv,
+                           u8 rx_rate, u8 ht_info);
+
+void mwifiex_drv_info_dump(struct mwifiex_adapter *adapter);
+void mwifiex_upload_device_dump(struct mwifiex_adapter *adapter);
+void *mwifiex_alloc_dma_align_buf(int rx_len, gfp_t flags);
+void mwifiex_queue_main_work(struct mwifiex_adapter *adapter);
+void mwifiex_coex_ampdu_rxwinsize(struct mwifiex_adapter *adapter);
+void mwifiex_11n_delba(struct mwifiex_private *priv, int tid);
+int mwifiex_send_domain_info_cmd_fw(struct wiphy *wiphy);
+void mwifiex_process_tx_pause_event(struct mwifiex_private *priv,
+                                   struct sk_buff *event);
+void mwifiex_process_multi_chan_event(struct mwifiex_private *priv,
+                                     struct sk_buff *event_skb);
+void mwifiex_multi_chan_resync(struct mwifiex_adapter *adapter);
+
+#ifdef CONFIG_DEBUG_FS
+void mwifiex_debugfs_init(void);
+void mwifiex_debugfs_remove(void);
+
+void mwifiex_dev_debugfs_init(struct mwifiex_private *priv);
+void mwifiex_dev_debugfs_remove(struct mwifiex_private *priv);
+#endif
+#endif /* !_MWIFIEX_MAIN_H_ */
diff --git a/drivers/net/wireless/marvell/mwifiex/pcie.c b/drivers/net/wireless/marvell/mwifiex/pcie.c
new file mode 100644 (file)
index 0000000..21192b6
--- /dev/null
@@ -0,0 +1,2742 @@
+/*
+ * Marvell Wireless LAN device driver: PCIE specific handling
+ *
+ * Copyright (C) 2011-2014, Marvell International Ltd.
+ *
+ * This software file (the "File") is distributed by Marvell International
+ * Ltd. under the terms of the GNU General Public License Version 2, June 1991
+ * (the "License").  You may use, redistribute and/or modify this File in
+ * accordance with the terms and conditions of the License, a copy of which
+ * is available by writing to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the
+ * worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
+ *
+ * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
+ * ARE EXPRESSLY DISCLAIMED.  The License provides additional details about
+ * this warranty disclaimer.
+ */
+
+#include <linux/firmware.h>
+
+#include "decl.h"
+#include "ioctl.h"
+#include "util.h"
+#include "fw.h"
+#include "main.h"
+#include "wmm.h"
+#include "11n.h"
+#include "pcie.h"
+
+#define PCIE_VERSION   "1.0"
+#define DRV_NAME        "Marvell mwifiex PCIe"
+
+static u8 user_rmmod;
+
+static struct mwifiex_if_ops pcie_ops;
+
+static struct semaphore add_remove_card_sem;
+
+static struct memory_type_mapping mem_type_mapping_tbl[] = {
+       {"ITCM", NULL, 0, 0xF0},
+       {"DTCM", NULL, 0, 0xF1},
+       {"SQRAM", NULL, 0, 0xF2},
+       {"IRAM", NULL, 0, 0xF3},
+       {"APU", NULL, 0, 0xF4},
+       {"CIU", NULL, 0, 0xF5},
+       {"ICU", NULL, 0, 0xF6},
+       {"MAC", NULL, 0, 0xF7},
+};
+
+static int
+mwifiex_map_pci_memory(struct mwifiex_adapter *adapter, struct sk_buff *skb,
+                      size_t size, int flags)
+{
+       struct pcie_service_card *card = adapter->card;
+       struct mwifiex_dma_mapping mapping;
+
+       mapping.addr = pci_map_single(card->dev, skb->data, size, flags);
+       if (pci_dma_mapping_error(card->dev, mapping.addr)) {
+               mwifiex_dbg(adapter, ERROR, "failed to map pci memory!\n");
+               return -1;
+       }
+       mapping.len = size;
+       mwifiex_store_mapping(skb, &mapping);
+       return 0;
+}
+
+static void mwifiex_unmap_pci_memory(struct mwifiex_adapter *adapter,
+                                    struct sk_buff *skb, int flags)
+{
+       struct pcie_service_card *card = adapter->card;
+       struct mwifiex_dma_mapping mapping;
+
+       mwifiex_get_mapping(skb, &mapping);
+       pci_unmap_single(card->dev, mapping.addr, mapping.len, flags);
+}
+
+/*
+ * This function reads sleep cookie and checks if FW is ready
+ */
+static bool mwifiex_pcie_ok_to_access_hw(struct mwifiex_adapter *adapter)
+{
+       u32 *cookie_addr;
+       struct pcie_service_card *card = adapter->card;
+       const struct mwifiex_pcie_card_reg *reg = card->pcie.reg;
+
+       if (!reg->sleep_cookie)
+               return true;
+
+       if (card->sleep_cookie_vbase) {
+               cookie_addr = (u32 *)card->sleep_cookie_vbase;
+               mwifiex_dbg(adapter, INFO,
+                           "info: ACCESS_HW: sleep cookie=0x%x\n",
+                           *cookie_addr);
+               if (*cookie_addr == FW_AWAKE_COOKIE)
+                       return true;
+       }
+
+       return false;
+}
+
+#ifdef CONFIG_PM_SLEEP
+/*
+ * Kernel needs to suspend all functions separately. Therefore all
+ * registered functions must have drivers with suspend and resume
+ * methods. Failing that the kernel simply removes the whole card.
+ *
+ * If already not suspended, this function allocates and sends a host
+ * sleep activate request to the firmware and turns off the traffic.
+ */
+static int mwifiex_pcie_suspend(struct device *dev)
+{
+       struct mwifiex_adapter *adapter;
+       struct pcie_service_card *card;
+       int hs_actived;
+       struct pci_dev *pdev = to_pci_dev(dev);
+
+       if (pdev) {
+               card = pci_get_drvdata(pdev);
+               if (!card || !card->adapter) {
+                       pr_err("Card or adapter structure is not valid\n");
+                       return 0;
+               }
+       } else {
+               pr_err("PCIE device is not specified\n");
+               return 0;
+       }
+
+       adapter = card->adapter;
+
+       hs_actived = mwifiex_enable_hs(adapter);
+
+       /* Indicate device suspended */
+       adapter->is_suspended = true;
+       adapter->hs_enabling = false;
+
+       return 0;
+}
+
+/*
+ * Kernel needs to suspend all functions separately. Therefore all
+ * registered functions must have drivers with suspend and resume
+ * methods. Failing that the kernel simply removes the whole card.
+ *
+ * If already not resumed, this function turns on the traffic and
+ * sends a host sleep cancel request to the firmware.
+ */
+static int mwifiex_pcie_resume(struct device *dev)
+{
+       struct mwifiex_adapter *adapter;
+       struct pcie_service_card *card;
+       struct pci_dev *pdev = to_pci_dev(dev);
+
+       if (pdev) {
+               card = pci_get_drvdata(pdev);
+               if (!card || !card->adapter) {
+                       pr_err("Card or adapter structure is not valid\n");
+                       return 0;
+               }
+       } else {
+               pr_err("PCIE device is not specified\n");
+               return 0;
+       }
+
+       adapter = card->adapter;
+
+       if (!adapter->is_suspended) {
+               mwifiex_dbg(adapter, WARN,
+                           "Device already resumed\n");
+               return 0;
+       }
+
+       adapter->is_suspended = false;
+
+       mwifiex_cancel_hs(mwifiex_get_priv(adapter, MWIFIEX_BSS_ROLE_STA),
+                         MWIFIEX_ASYNC_CMD);
+
+       return 0;
+}
+#endif
+
+/*
+ * This function probes an mwifiex device and registers it. It allocates
+ * the card structure, enables PCIE function number and initiates the
+ * device registration and initialization procedure by adding a logical
+ * interface.
+ */
+static int mwifiex_pcie_probe(struct pci_dev *pdev,
+                                       const struct pci_device_id *ent)
+{
+       struct pcie_service_card *card;
+
+       pr_debug("info: vendor=0x%4.04X device=0x%4.04X rev=%d\n",
+                pdev->vendor, pdev->device, pdev->revision);
+
+       card = kzalloc(sizeof(struct pcie_service_card), GFP_KERNEL);
+       if (!card)
+               return -ENOMEM;
+
+       card->dev = pdev;
+
+       if (ent->driver_data) {
+               struct mwifiex_pcie_device *data = (void *)ent->driver_data;
+               card->pcie.firmware = data->firmware;
+               card->pcie.reg = data->reg;
+               card->pcie.blksz_fw_dl = data->blksz_fw_dl;
+               card->pcie.tx_buf_size = data->tx_buf_size;
+               card->pcie.can_dump_fw = data->can_dump_fw;
+               card->pcie.can_ext_scan = data->can_ext_scan;
+       }
+
+       if (mwifiex_add_card(card, &add_remove_card_sem, &pcie_ops,
+                            MWIFIEX_PCIE)) {
+               pr_err("%s failed\n", __func__);
+               kfree(card);
+               return -1;
+       }
+
+       return 0;
+}
+
+/*
+ * This function removes the interface and frees up the card structure.
+ */
+static void mwifiex_pcie_remove(struct pci_dev *pdev)
+{
+       struct pcie_service_card *card;
+       struct mwifiex_adapter *adapter;
+       struct mwifiex_private *priv;
+
+       card = pci_get_drvdata(pdev);
+       if (!card)
+               return;
+
+       adapter = card->adapter;
+       if (!adapter || !adapter->priv_num)
+               return;
+
+       if (user_rmmod) {
+#ifdef CONFIG_PM_SLEEP
+               if (adapter->is_suspended)
+                       mwifiex_pcie_resume(&pdev->dev);
+#endif
+
+               mwifiex_deauthenticate_all(adapter);
+
+               priv = mwifiex_get_priv(adapter, MWIFIEX_BSS_ROLE_ANY);
+
+               mwifiex_disable_auto_ds(priv);
+
+               mwifiex_init_shutdown_fw(priv, MWIFIEX_FUNC_SHUTDOWN);
+       }
+
+       mwifiex_remove_card(card->adapter, &add_remove_card_sem);
+}
+
+static void mwifiex_pcie_shutdown(struct pci_dev *pdev)
+{
+       user_rmmod = 1;
+       mwifiex_pcie_remove(pdev);
+
+       return;
+}
+
+static const struct pci_device_id mwifiex_ids[] = {
+       {
+               PCIE_VENDOR_ID_MARVELL, PCIE_DEVICE_ID_MARVELL_88W8766P,
+               PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+               .driver_data = (unsigned long)&mwifiex_pcie8766,
+       },
+       {
+               PCIE_VENDOR_ID_MARVELL, PCIE_DEVICE_ID_MARVELL_88W8897,
+               PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+               .driver_data = (unsigned long)&mwifiex_pcie8897,
+       },
+       {
+               PCIE_VENDOR_ID_MARVELL, PCIE_DEVICE_ID_MARVELL_88W8997,
+               PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+               .driver_data = (unsigned long)&mwifiex_pcie8997,
+       },
+       {},
+};
+
+MODULE_DEVICE_TABLE(pci, mwifiex_ids);
+
+#ifdef CONFIG_PM_SLEEP
+/* Power Management Hooks */
+static SIMPLE_DEV_PM_OPS(mwifiex_pcie_pm_ops, mwifiex_pcie_suspend,
+                               mwifiex_pcie_resume);
+#endif
+
+/* PCI Device Driver */
+static struct pci_driver __refdata mwifiex_pcie = {
+       .name     = "mwifiex_pcie",
+       .id_table = mwifiex_ids,
+       .probe    = mwifiex_pcie_probe,
+       .remove   = mwifiex_pcie_remove,
+#ifdef CONFIG_PM_SLEEP
+       .driver   = {
+               .pm = &mwifiex_pcie_pm_ops,
+       },
+#endif
+       .shutdown = mwifiex_pcie_shutdown,
+};
+
+/*
+ * This function writes data into PCIE card register.
+ */
+static int mwifiex_write_reg(struct mwifiex_adapter *adapter, int reg, u32 data)
+{
+       struct pcie_service_card *card = adapter->card;
+
+       iowrite32(data, card->pci_mmap1 + reg);
+
+       return 0;
+}
+
+/*
+ * This function reads data from PCIE card register.
+ */
+static int mwifiex_read_reg(struct mwifiex_adapter *adapter, int reg, u32 *data)
+{
+       struct pcie_service_card *card = adapter->card;
+
+       *data = ioread32(card->pci_mmap1 + reg);
+
+       return 0;
+}
+
+/* This function reads u8 data from PCIE card register. */
+static int mwifiex_read_reg_byte(struct mwifiex_adapter *adapter,
+                                int reg, u8 *data)
+{
+       struct pcie_service_card *card = adapter->card;
+
+       *data = ioread8(card->pci_mmap1 + reg);
+
+       return 0;
+}
+
+/*
+ * This function adds delay loop to ensure FW is awake before proceeding.
+ */
+static void mwifiex_pcie_dev_wakeup_delay(struct mwifiex_adapter *adapter)
+{
+       int i = 0;
+
+       while (mwifiex_pcie_ok_to_access_hw(adapter)) {
+               i++;
+               usleep_range(10, 20);
+               /* 50ms max wait */
+               if (i == 5000)
+                       break;
+       }
+
+       return;
+}
+
+static void mwifiex_delay_for_sleep_cookie(struct mwifiex_adapter *adapter,
+                                          u32 max_delay_loop_cnt)
+{
+       struct pcie_service_card *card = adapter->card;
+       u8 *buffer;
+       u32 sleep_cookie, count;
+
+       for (count = 0; count < max_delay_loop_cnt; count++) {
+               buffer = card->cmdrsp_buf->data - INTF_HEADER_LEN;
+               sleep_cookie = *(u32 *)buffer;
+
+               if (sleep_cookie == MWIFIEX_DEF_SLEEP_COOKIE) {
+                       mwifiex_dbg(adapter, INFO,
+                                   "sleep cookie found at count %d\n", count);
+                       break;
+               }
+               usleep_range(20, 30);
+       }
+
+       if (count >= max_delay_loop_cnt)
+               mwifiex_dbg(adapter, INFO,
+                           "max count reached while accessing sleep cookie\n");
+}
+
+/* This function wakes up the card by reading fw_status register. */
+static int mwifiex_pm_wakeup_card(struct mwifiex_adapter *adapter)
+{
+       u32 fw_status;
+       struct pcie_service_card *card = adapter->card;
+       const struct mwifiex_pcie_card_reg *reg = card->pcie.reg;
+
+       mwifiex_dbg(adapter, EVENT,
+                   "event: Wakeup device...\n");
+
+       if (reg->sleep_cookie)
+               mwifiex_pcie_dev_wakeup_delay(adapter);
+
+       /* Reading fw_status register will wakeup device */
+       if (mwifiex_read_reg(adapter, reg->fw_status, &fw_status)) {
+               mwifiex_dbg(adapter, ERROR,
+                           "Reading fw_status register failed\n");
+               return -1;
+       }
+
+       if (reg->sleep_cookie) {
+               mwifiex_pcie_dev_wakeup_delay(adapter);
+               mwifiex_dbg(adapter, INFO,
+                           "PCIE wakeup: Setting PS_STATE_AWAKE\n");
+               adapter->ps_state = PS_STATE_AWAKE;
+       }
+
+       return 0;
+}
+
+/*
+ * This function is called after the card has woken up.
+ *
+ * The card configuration register is reset.
+ */
+static int mwifiex_pm_wakeup_card_complete(struct mwifiex_adapter *adapter)
+{
+       mwifiex_dbg(adapter, CMD,
+                   "cmd: Wakeup device completed\n");
+
+       return 0;
+}
+
+/*
+ * This function disables the host interrupt.
+ *
+ * The host interrupt mask is read, the disable bit is reset and
+ * written back to the card host interrupt mask register.
+ */
+static int mwifiex_pcie_disable_host_int(struct mwifiex_adapter *adapter)
+{
+       if (mwifiex_pcie_ok_to_access_hw(adapter)) {
+               if (mwifiex_write_reg(adapter, PCIE_HOST_INT_MASK,
+                                     0x00000000)) {
+                       mwifiex_dbg(adapter, ERROR,
+                                   "Disable host interrupt failed\n");
+                       return -1;
+               }
+       }
+
+       return 0;
+}
+
+/*
+ * This function enables the host interrupt.
+ *
+ * The host interrupt enable mask is written to the card
+ * host interrupt mask register.
+ */
+static int mwifiex_pcie_enable_host_int(struct mwifiex_adapter *adapter)
+{
+       if (mwifiex_pcie_ok_to_access_hw(adapter)) {
+               /* Simply write the mask to the register */
+               if (mwifiex_write_reg(adapter, PCIE_HOST_INT_MASK,
+                                     HOST_INTR_MASK)) {
+                       mwifiex_dbg(adapter, ERROR,
+                                   "Enable host interrupt failed\n");
+                       return -1;
+               }
+       }
+
+       return 0;
+}
+
+/*
+ * This function initializes TX buffer ring descriptors
+ */
+static int mwifiex_init_txq_ring(struct mwifiex_adapter *adapter)
+{
+       struct pcie_service_card *card = adapter->card;
+       const struct mwifiex_pcie_card_reg *reg = card->pcie.reg;
+       struct mwifiex_pcie_buf_desc *desc;
+       struct mwifiex_pfu_buf_desc *desc2;
+       int i;
+
+       for (i = 0; i < MWIFIEX_MAX_TXRX_BD; i++) {
+               card->tx_buf_list[i] = NULL;
+               if (reg->pfu_enabled) {
+                       card->txbd_ring[i] = (void *)card->txbd_ring_vbase +
+                                            (sizeof(*desc2) * i);
+                       desc2 = card->txbd_ring[i];
+                       memset(desc2, 0, sizeof(*desc2));
+               } else {
+                       card->txbd_ring[i] = (void *)card->txbd_ring_vbase +
+                                            (sizeof(*desc) * i);
+                       desc = card->txbd_ring[i];
+                       memset(desc, 0, sizeof(*desc));
+               }
+       }
+
+       return 0;
+}
+
+/* This function initializes RX buffer ring descriptors. Each SKB is allocated
+ * here and after mapping PCI memory, its physical address is assigned to
+ * PCIE Rx buffer descriptor's physical address.
+ */
+static int mwifiex_init_rxq_ring(struct mwifiex_adapter *adapter)
+{
+       struct pcie_service_card *card = adapter->card;
+       const struct mwifiex_pcie_card_reg *reg = card->pcie.reg;
+       struct sk_buff *skb;
+       struct mwifiex_pcie_buf_desc *desc;
+       struct mwifiex_pfu_buf_desc *desc2;
+       dma_addr_t buf_pa;
+       int i;
+
+       for (i = 0; i < MWIFIEX_MAX_TXRX_BD; i++) {
+               /* Allocate skb here so that firmware can DMA data from it */
+               skb = mwifiex_alloc_dma_align_buf(MWIFIEX_RX_DATA_BUF_SIZE,
+                                                 GFP_KERNEL | GFP_DMA);
+               if (!skb) {
+                       mwifiex_dbg(adapter, ERROR,
+                                   "Unable to allocate skb for RX ring.\n");
+                       kfree(card->rxbd_ring_vbase);
+                       return -ENOMEM;
+               }
+
+               if (mwifiex_map_pci_memory(adapter, skb,
+                                          MWIFIEX_RX_DATA_BUF_SIZE,
+                                          PCI_DMA_FROMDEVICE))
+                       return -1;
+
+               buf_pa = MWIFIEX_SKB_DMA_ADDR(skb);
+
+               mwifiex_dbg(adapter, INFO,
+                           "info: RX ring: skb=%p len=%d data=%p buf_pa=%#x:%x\n",
+                           skb, skb->len, skb->data, (u32)buf_pa,
+                           (u32)((u64)buf_pa >> 32));
+
+               card->rx_buf_list[i] = skb;
+               if (reg->pfu_enabled) {
+                       card->rxbd_ring[i] = (void *)card->rxbd_ring_vbase +
+                                            (sizeof(*desc2) * i);
+                       desc2 = card->rxbd_ring[i];
+                       desc2->paddr = buf_pa;
+                       desc2->len = (u16)skb->len;
+                       desc2->frag_len = (u16)skb->len;
+                       desc2->flags = reg->ring_flag_eop | reg->ring_flag_sop;
+                       desc2->offset = 0;
+               } else {
+                       card->rxbd_ring[i] = (void *)(card->rxbd_ring_vbase +
+                                            (sizeof(*desc) * i));
+                       desc = card->rxbd_ring[i];
+                       desc->paddr = buf_pa;
+                       desc->len = (u16)skb->len;
+                       desc->flags = 0;
+               }
+       }
+
+       return 0;
+}
+
+/* This function initializes event buffer ring descriptors. Each SKB is
+ * allocated here and after mapping PCI memory, its physical address is assigned
+ * to PCIE Rx buffer descriptor's physical address
+ */
+static int mwifiex_pcie_init_evt_ring(struct mwifiex_adapter *adapter)
+{
+       struct pcie_service_card *card = adapter->card;
+       struct mwifiex_evt_buf_desc *desc;
+       struct sk_buff *skb;
+       dma_addr_t buf_pa;
+       int i;
+
+       for (i = 0; i < MWIFIEX_MAX_EVT_BD; i++) {
+               /* Allocate skb here so that firmware can DMA data from it */
+               skb = dev_alloc_skb(MAX_EVENT_SIZE);
+               if (!skb) {
+                       mwifiex_dbg(adapter, ERROR,
+                                   "Unable to allocate skb for EVENT buf.\n");
+                       kfree(card->evtbd_ring_vbase);
+                       return -ENOMEM;
+               }
+               skb_put(skb, MAX_EVENT_SIZE);
+
+               if (mwifiex_map_pci_memory(adapter, skb, MAX_EVENT_SIZE,
+                                          PCI_DMA_FROMDEVICE))
+                       return -1;
+
+               buf_pa = MWIFIEX_SKB_DMA_ADDR(skb);
+
+               mwifiex_dbg(adapter, EVENT,
+                           "info: EVT ring: skb=%p len=%d data=%p buf_pa=%#x:%x\n",
+                           skb, skb->len, skb->data, (u32)buf_pa,
+                           (u32)((u64)buf_pa >> 32));
+
+               card->evt_buf_list[i] = skb;
+               card->evtbd_ring[i] = (void *)(card->evtbd_ring_vbase +
+                                     (sizeof(*desc) * i));
+               desc = card->evtbd_ring[i];
+               desc->paddr = buf_pa;
+               desc->len = (u16)skb->len;
+               desc->flags = 0;
+       }
+
+       return 0;
+}
+
+/* This function cleans up TX buffer rings. If any of the buffer list has valid
+ * SKB address, associated SKB is freed.
+ */
+static void mwifiex_cleanup_txq_ring(struct mwifiex_adapter *adapter)
+{
+       struct pcie_service_card *card = adapter->card;
+       const struct mwifiex_pcie_card_reg *reg = card->pcie.reg;
+       struct sk_buff *skb;
+       struct mwifiex_pcie_buf_desc *desc;
+       struct mwifiex_pfu_buf_desc *desc2;
+       int i;
+
+       for (i = 0; i < MWIFIEX_MAX_TXRX_BD; i++) {
+               if (reg->pfu_enabled) {
+                       desc2 = card->txbd_ring[i];
+                       if (card->tx_buf_list[i]) {
+                               skb = card->tx_buf_list[i];
+                               mwifiex_unmap_pci_memory(adapter, skb,
+                                                        PCI_DMA_TODEVICE);
+                               dev_kfree_skb_any(skb);
+                       }
+                       memset(desc2, 0, sizeof(*desc2));
+               } else {
+                       desc = card->txbd_ring[i];
+                       if (card->tx_buf_list[i]) {
+                               skb = card->tx_buf_list[i];
+                               mwifiex_unmap_pci_memory(adapter, skb,
+                                                        PCI_DMA_TODEVICE);
+                               dev_kfree_skb_any(skb);
+                       }
+                       memset(desc, 0, sizeof(*desc));
+               }
+               card->tx_buf_list[i] = NULL;
+       }
+
+       return;
+}
+
+/* This function cleans up RX buffer rings. If any of the buffer list has valid
+ * SKB address, associated SKB is freed.
+ */
+static void mwifiex_cleanup_rxq_ring(struct mwifiex_adapter *adapter)
+{
+       struct pcie_service_card *card = adapter->card;
+       const struct mwifiex_pcie_card_reg *reg = card->pcie.reg;
+       struct mwifiex_pcie_buf_desc *desc;
+       struct mwifiex_pfu_buf_desc *desc2;
+       struct sk_buff *skb;
+       int i;
+
+       for (i = 0; i < MWIFIEX_MAX_TXRX_BD; i++) {
+               if (reg->pfu_enabled) {
+                       desc2 = card->rxbd_ring[i];
+                       if (card->rx_buf_list[i]) {
+                               skb = card->rx_buf_list[i];
+                               mwifiex_unmap_pci_memory(adapter, skb,
+                                                        PCI_DMA_FROMDEVICE);
+                               dev_kfree_skb_any(skb);
+                       }
+                       memset(desc2, 0, sizeof(*desc2));
+               } else {
+                       desc = card->rxbd_ring[i];
+                       if (card->rx_buf_list[i]) {
+                               skb = card->rx_buf_list[i];
+                               mwifiex_unmap_pci_memory(adapter, skb,
+                                                        PCI_DMA_FROMDEVICE);
+                               dev_kfree_skb_any(skb);
+                       }
+                       memset(desc, 0, sizeof(*desc));
+               }
+               card->rx_buf_list[i] = NULL;
+       }
+
+       return;
+}
+
+/* This function cleans up event buffer rings. If any of the buffer list has
+ * valid SKB address, associated SKB is freed.
+ */
+static void mwifiex_cleanup_evt_ring(struct mwifiex_adapter *adapter)
+{
+       struct pcie_service_card *card = adapter->card;
+       struct mwifiex_evt_buf_desc *desc;
+       struct sk_buff *skb;
+       int i;
+
+       for (i = 0; i < MWIFIEX_MAX_EVT_BD; i++) {
+               desc = card->evtbd_ring[i];
+               if (card->evt_buf_list[i]) {
+                       skb = card->evt_buf_list[i];
+                       mwifiex_unmap_pci_memory(adapter, skb,
+                                                PCI_DMA_FROMDEVICE);
+                       dev_kfree_skb_any(skb);
+               }
+               card->evt_buf_list[i] = NULL;
+               memset(desc, 0, sizeof(*desc));
+       }
+
+       return;
+}
+
+/* This function creates buffer descriptor ring for TX
+ */
+static int mwifiex_pcie_create_txbd_ring(struct mwifiex_adapter *adapter)
+{
+       struct pcie_service_card *card = adapter->card;
+       const struct mwifiex_pcie_card_reg *reg = card->pcie.reg;
+
+       /*
+        * driver maintaines the write pointer and firmware maintaines the read
+        * pointer. The write pointer starts at 0 (zero) while the read pointer
+        * starts at zero with rollover bit set
+        */
+       card->txbd_wrptr = 0;
+
+       if (reg->pfu_enabled)
+               card->txbd_rdptr = 0;
+       else
+               card->txbd_rdptr |= reg->tx_rollover_ind;
+
+       /* allocate shared memory for the BD ring and divide the same in to
+          several descriptors */
+       if (reg->pfu_enabled)
+               card->txbd_ring_size = sizeof(struct mwifiex_pfu_buf_desc) *
+                                      MWIFIEX_MAX_TXRX_BD;
+       else
+               card->txbd_ring_size = sizeof(struct mwifiex_pcie_buf_desc) *
+                                      MWIFIEX_MAX_TXRX_BD;
+
+       mwifiex_dbg(adapter, INFO,
+                   "info: txbd_ring: Allocating %d bytes\n",
+                   card->txbd_ring_size);
+       card->txbd_ring_vbase = pci_alloc_consistent(card->dev,
+                                                    card->txbd_ring_size,
+                                                    &card->txbd_ring_pbase);
+       if (!card->txbd_ring_vbase) {
+               mwifiex_dbg(adapter, ERROR,
+                           "allocate consistent memory (%d bytes) failed!\n",
+                           card->txbd_ring_size);
+               return -ENOMEM;
+       }
+       mwifiex_dbg(adapter, DATA,
+                   "info: txbd_ring - base: %p, pbase: %#x:%x, len: %x\n",
+                   card->txbd_ring_vbase, (unsigned int)card->txbd_ring_pbase,
+                   (u32)((u64)card->txbd_ring_pbase >> 32),
+                   card->txbd_ring_size);
+
+       return mwifiex_init_txq_ring(adapter);
+}
+
+static int mwifiex_pcie_delete_txbd_ring(struct mwifiex_adapter *adapter)
+{
+       struct pcie_service_card *card = adapter->card;
+       const struct mwifiex_pcie_card_reg *reg = card->pcie.reg;
+
+       mwifiex_cleanup_txq_ring(adapter);
+
+       if (card->txbd_ring_vbase)
+               pci_free_consistent(card->dev, card->txbd_ring_size,
+                                   card->txbd_ring_vbase,
+                                   card->txbd_ring_pbase);
+       card->txbd_ring_size = 0;
+       card->txbd_wrptr = 0;
+       card->txbd_rdptr = 0 | reg->tx_rollover_ind;
+       card->txbd_ring_vbase = NULL;
+       card->txbd_ring_pbase = 0;
+
+       return 0;
+}
+
+/*
+ * This function creates buffer descriptor ring for RX
+ */
+static int mwifiex_pcie_create_rxbd_ring(struct mwifiex_adapter *adapter)
+{
+       struct pcie_service_card *card = adapter->card;
+       const struct mwifiex_pcie_card_reg *reg = card->pcie.reg;
+
+       /*
+        * driver maintaines the read pointer and firmware maintaines the write
+        * pointer. The write pointer starts at 0 (zero) while the read pointer
+        * starts at zero with rollover bit set
+        */
+       card->rxbd_wrptr = 0;
+       card->rxbd_rdptr = reg->rx_rollover_ind;
+
+       if (reg->pfu_enabled)
+               card->rxbd_ring_size = sizeof(struct mwifiex_pfu_buf_desc) *
+                                      MWIFIEX_MAX_TXRX_BD;
+       else
+               card->rxbd_ring_size = sizeof(struct mwifiex_pcie_buf_desc) *
+                                      MWIFIEX_MAX_TXRX_BD;
+
+       mwifiex_dbg(adapter, INFO,
+                   "info: rxbd_ring: Allocating %d bytes\n",
+                   card->rxbd_ring_size);
+       card->rxbd_ring_vbase = pci_alloc_consistent(card->dev,
+                                                    card->rxbd_ring_size,
+                                                    &card->rxbd_ring_pbase);
+       if (!card->rxbd_ring_vbase) {
+               mwifiex_dbg(adapter, ERROR,
+                           "allocate consistent memory (%d bytes) failed!\n",
+                           card->rxbd_ring_size);
+               return -ENOMEM;
+       }
+
+       mwifiex_dbg(adapter, DATA,
+                   "info: rxbd_ring - base: %p, pbase: %#x:%x, len: %#x\n",
+                   card->rxbd_ring_vbase, (u32)card->rxbd_ring_pbase,
+                   (u32)((u64)card->rxbd_ring_pbase >> 32),
+                   card->rxbd_ring_size);
+
+       return mwifiex_init_rxq_ring(adapter);
+}
+
+/*
+ * This function deletes Buffer descriptor ring for RX
+ */
+static int mwifiex_pcie_delete_rxbd_ring(struct mwifiex_adapter *adapter)
+{
+       struct pcie_service_card *card = adapter->card;
+       const struct mwifiex_pcie_card_reg *reg = card->pcie.reg;
+
+       mwifiex_cleanup_rxq_ring(adapter);
+
+       if (card->rxbd_ring_vbase)
+               pci_free_consistent(card->dev, card->rxbd_ring_size,
+                                   card->rxbd_ring_vbase,
+                                   card->rxbd_ring_pbase);
+       card->rxbd_ring_size = 0;
+       card->rxbd_wrptr = 0;
+       card->rxbd_rdptr = 0 | reg->rx_rollover_ind;
+       card->rxbd_ring_vbase = NULL;
+       card->rxbd_ring_pbase = 0;
+
+       return 0;
+}
+
+/*
+ * This function creates buffer descriptor ring for Events
+ */
+static int mwifiex_pcie_create_evtbd_ring(struct mwifiex_adapter *adapter)
+{
+       struct pcie_service_card *card = adapter->card;
+       const struct mwifiex_pcie_card_reg *reg = card->pcie.reg;
+
+       /*
+        * driver maintaines the read pointer and firmware maintaines the write
+        * pointer. The write pointer starts at 0 (zero) while the read pointer
+        * starts at zero with rollover bit set
+        */
+       card->evtbd_wrptr = 0;
+       card->evtbd_rdptr = reg->evt_rollover_ind;
+
+       card->evtbd_ring_size = sizeof(struct mwifiex_evt_buf_desc) *
+                               MWIFIEX_MAX_EVT_BD;
+
+       mwifiex_dbg(adapter, INFO,
+                   "info: evtbd_ring: Allocating %d bytes\n",
+               card->evtbd_ring_size);
+       card->evtbd_ring_vbase = pci_alloc_consistent(card->dev,
+                                                     card->evtbd_ring_size,
+                                                     &card->evtbd_ring_pbase);
+       if (!card->evtbd_ring_vbase) {
+               mwifiex_dbg(adapter, ERROR,
+                           "allocate consistent memory (%d bytes) failed!\n",
+                           card->evtbd_ring_size);
+               return -ENOMEM;
+       }
+
+       mwifiex_dbg(adapter, EVENT,
+                   "info: CMDRSP/EVT bd_ring - base: %p pbase: %#x:%x len: %#x\n",
+                   card->evtbd_ring_vbase, (u32)card->evtbd_ring_pbase,
+                   (u32)((u64)card->evtbd_ring_pbase >> 32),
+                   card->evtbd_ring_size);
+
+       return mwifiex_pcie_init_evt_ring(adapter);
+}
+
+/*
+ * This function deletes Buffer descriptor ring for Events
+ */
+static int mwifiex_pcie_delete_evtbd_ring(struct mwifiex_adapter *adapter)
+{
+       struct pcie_service_card *card = adapter->card;
+       const struct mwifiex_pcie_card_reg *reg = card->pcie.reg;
+
+       mwifiex_cleanup_evt_ring(adapter);
+
+       if (card->evtbd_ring_vbase)
+               pci_free_consistent(card->dev, card->evtbd_ring_size,
+                                   card->evtbd_ring_vbase,
+                                   card->evtbd_ring_pbase);
+       card->evtbd_wrptr = 0;
+       card->evtbd_rdptr = 0 | reg->evt_rollover_ind;
+       card->evtbd_ring_size = 0;
+       card->evtbd_ring_vbase = NULL;
+       card->evtbd_ring_pbase = 0;
+
+       return 0;
+}
+
+/*
+ * This function allocates a buffer for CMDRSP
+ */
+static int mwifiex_pcie_alloc_cmdrsp_buf(struct mwifiex_adapter *adapter)
+{
+       struct pcie_service_card *card = adapter->card;
+       struct sk_buff *skb;
+
+       /* Allocate memory for receiving command response data */
+       skb = dev_alloc_skb(MWIFIEX_UPLD_SIZE);
+       if (!skb) {
+               mwifiex_dbg(adapter, ERROR,
+                           "Unable to allocate skb for command response data.\n");
+               return -ENOMEM;
+       }
+       skb_put(skb, MWIFIEX_UPLD_SIZE);
+       if (mwifiex_map_pci_memory(adapter, skb, MWIFIEX_UPLD_SIZE,
+                                  PCI_DMA_FROMDEVICE))
+               return -1;
+
+       card->cmdrsp_buf = skb;
+
+       return 0;
+}
+
+/*
+ * This function deletes a buffer for CMDRSP
+ */
+static int mwifiex_pcie_delete_cmdrsp_buf(struct mwifiex_adapter *adapter)
+{
+       struct pcie_service_card *card;
+
+       if (!adapter)
+               return 0;
+
+       card = adapter->card;
+
+       if (card && card->cmdrsp_buf) {
+               mwifiex_unmap_pci_memory(adapter, card->cmdrsp_buf,
+                                        PCI_DMA_FROMDEVICE);
+               dev_kfree_skb_any(card->cmdrsp_buf);
+       }
+
+       if (card && card->cmd_buf) {
+               mwifiex_unmap_pci_memory(adapter, card->cmd_buf,
+                                        PCI_DMA_TODEVICE);
+       }
+       return 0;
+}
+
+/*
+ * This function allocates a buffer for sleep cookie
+ */
+static int mwifiex_pcie_alloc_sleep_cookie_buf(struct mwifiex_adapter *adapter)
+{
+       struct pcie_service_card *card = adapter->card;
+
+       card->sleep_cookie_vbase = pci_alloc_consistent(card->dev, sizeof(u32),
+                                                    &card->sleep_cookie_pbase);
+       if (!card->sleep_cookie_vbase) {
+               mwifiex_dbg(adapter, ERROR,
+                           "pci_alloc_consistent failed!\n");
+               return -ENOMEM;
+       }
+       /* Init val of Sleep Cookie */
+       *(u32 *)card->sleep_cookie_vbase = FW_AWAKE_COOKIE;
+
+       mwifiex_dbg(adapter, INFO,
+                   "alloc_scook: sleep cookie=0x%x\n",
+                   *((u32 *)card->sleep_cookie_vbase));
+
+       return 0;
+}
+
+/*
+ * This function deletes buffer for sleep cookie
+ */
+static int mwifiex_pcie_delete_sleep_cookie_buf(struct mwifiex_adapter *adapter)
+{
+       struct pcie_service_card *card;
+
+       if (!adapter)
+               return 0;
+
+       card = adapter->card;
+
+       if (card && card->sleep_cookie_vbase) {
+               pci_free_consistent(card->dev, sizeof(u32),
+                                   card->sleep_cookie_vbase,
+                                   card->sleep_cookie_pbase);
+               card->sleep_cookie_vbase = NULL;
+       }
+
+       return 0;
+}
+
+/* This function flushes the TX buffer descriptor ring
+ * This function defined as handler is also called while cleaning TXRX
+ * during disconnect/ bss stop.
+ */
+static int mwifiex_clean_pcie_ring_buf(struct mwifiex_adapter *adapter)
+{
+       struct pcie_service_card *card = adapter->card;
+
+       if (!mwifiex_pcie_txbd_empty(card, card->txbd_rdptr)) {
+               card->txbd_flush = 1;
+               /* write pointer already set at last send
+                * send dnld-rdy intr again, wait for completion.
+                */
+               if (mwifiex_write_reg(adapter, PCIE_CPU_INT_EVENT,
+                                     CPU_INTR_DNLD_RDY)) {
+                       mwifiex_dbg(adapter, ERROR,
+                                   "failed to assert dnld-rdy interrupt.\n");
+                       return -1;
+               }
+       }
+       return 0;
+}
+
+/*
+ * This function unmaps and frees downloaded data buffer
+ */
+static int mwifiex_pcie_send_data_complete(struct mwifiex_adapter *adapter)
+{
+       struct sk_buff *skb;
+       u32 wrdoneidx, rdptr, num_tx_buffs, unmap_count = 0;
+       struct mwifiex_pcie_buf_desc *desc;
+       struct mwifiex_pfu_buf_desc *desc2;
+       struct pcie_service_card *card = adapter->card;
+       const struct mwifiex_pcie_card_reg *reg = card->pcie.reg;
+
+       if (!mwifiex_pcie_ok_to_access_hw(adapter))
+               mwifiex_pm_wakeup_card(adapter);
+
+       /* Read the TX ring read pointer set by firmware */
+       if (mwifiex_read_reg(adapter, reg->tx_rdptr, &rdptr)) {
+               mwifiex_dbg(adapter, ERROR,
+                           "SEND COMP: failed to read reg->tx_rdptr\n");
+               return -1;
+       }
+
+       mwifiex_dbg(adapter, DATA,
+                   "SEND COMP: rdptr_prev=0x%x, rdptr=0x%x\n",
+                   card->txbd_rdptr, rdptr);
+
+       num_tx_buffs = MWIFIEX_MAX_TXRX_BD << reg->tx_start_ptr;
+       /* free from previous txbd_rdptr to current txbd_rdptr */
+       while (((card->txbd_rdptr & reg->tx_mask) !=
+               (rdptr & reg->tx_mask)) ||
+              ((card->txbd_rdptr & reg->tx_rollover_ind) !=
+               (rdptr & reg->tx_rollover_ind))) {
+               wrdoneidx = (card->txbd_rdptr & reg->tx_mask) >>
+                           reg->tx_start_ptr;
+
+               skb = card->tx_buf_list[wrdoneidx];
+
+               if (skb) {
+                       mwifiex_dbg(adapter, DATA,
+                                   "SEND COMP: Detach skb %p at txbd_rdidx=%d\n",
+                                   skb, wrdoneidx);
+                       mwifiex_unmap_pci_memory(adapter, skb,
+                                                PCI_DMA_TODEVICE);
+
+                       unmap_count++;
+
+                       if (card->txbd_flush)
+                               mwifiex_write_data_complete(adapter, skb, 0,
+                                                           -1);
+                       else
+                               mwifiex_write_data_complete(adapter, skb, 0, 0);
+               }
+
+               card->tx_buf_list[wrdoneidx] = NULL;
+
+               if (reg->pfu_enabled) {
+                       desc2 = card->txbd_ring[wrdoneidx];
+                       memset(desc2, 0, sizeof(*desc2));
+               } else {
+                       desc = card->txbd_ring[wrdoneidx];
+                       memset(desc, 0, sizeof(*desc));
+               }
+               switch (card->dev->device) {
+               case PCIE_DEVICE_ID_MARVELL_88W8766P:
+                       card->txbd_rdptr++;
+                       break;
+               case PCIE_DEVICE_ID_MARVELL_88W8897:
+               case PCIE_DEVICE_ID_MARVELL_88W8997:
+                       card->txbd_rdptr += reg->ring_tx_start_ptr;
+                       break;
+               }
+
+
+               if ((card->txbd_rdptr & reg->tx_mask) == num_tx_buffs)
+                       card->txbd_rdptr = ((card->txbd_rdptr &
+                                            reg->tx_rollover_ind) ^
+                                            reg->tx_rollover_ind);
+       }
+
+       if (unmap_count)
+               adapter->data_sent = false;
+
+       if (card->txbd_flush) {
+               if (mwifiex_pcie_txbd_empty(card, card->txbd_rdptr))
+                       card->txbd_flush = 0;
+               else
+                       mwifiex_clean_pcie_ring_buf(adapter);
+       }
+
+       return 0;
+}
+
+/* This function sends data buffer to device. First 4 bytes of payload
+ * are filled with payload length and payload type. Then this payload
+ * is mapped to PCI device memory. Tx ring pointers are advanced accordingly.
+ * Download ready interrupt to FW is deffered if Tx ring is not full and
+ * additional payload can be accomodated.
+ * Caller must ensure tx_param parameter to this function is not NULL.
+ */
+static int
+mwifiex_pcie_send_data(struct mwifiex_adapter *adapter, struct sk_buff *skb,
+                      struct mwifiex_tx_param *tx_param)
+{
+       struct pcie_service_card *card = adapter->card;
+       const struct mwifiex_pcie_card_reg *reg = card->pcie.reg;
+       u32 wrindx, num_tx_buffs, rx_val;
+       int ret;
+       dma_addr_t buf_pa;
+       struct mwifiex_pcie_buf_desc *desc = NULL;
+       struct mwifiex_pfu_buf_desc *desc2 = NULL;
+       __le16 *tmp;
+
+       if (!(skb->data && skb->len)) {
+               mwifiex_dbg(adapter, ERROR,
+                           "%s(): invalid parameter <%p, %#x>\n",
+                           __func__, skb->data, skb->len);
+               return -1;
+       }
+
+       if (!mwifiex_pcie_ok_to_access_hw(adapter))
+               mwifiex_pm_wakeup_card(adapter);
+
+       num_tx_buffs = MWIFIEX_MAX_TXRX_BD << reg->tx_start_ptr;
+       mwifiex_dbg(adapter, DATA,
+                   "info: SEND DATA: <Rd: %#x, Wr: %#x>\n",
+               card->txbd_rdptr, card->txbd_wrptr);
+       if (mwifiex_pcie_txbd_not_full(card)) {
+               u8 *payload;
+
+               adapter->data_sent = true;
+               payload = skb->data;
+               tmp = (__le16 *)&payload[0];
+               *tmp = cpu_to_le16((u16)skb->len);
+               tmp = (__le16 *)&payload[2];
+               *tmp = cpu_to_le16(MWIFIEX_TYPE_DATA);
+
+               if (mwifiex_map_pci_memory(adapter, skb, skb->len,
+                                          PCI_DMA_TODEVICE))
+                       return -1;
+
+               wrindx = (card->txbd_wrptr & reg->tx_mask) >> reg->tx_start_ptr;
+               buf_pa = MWIFIEX_SKB_DMA_ADDR(skb);
+               card->tx_buf_list[wrindx] = skb;
+
+               if (reg->pfu_enabled) {
+                       desc2 = card->txbd_ring[wrindx];
+                       desc2->paddr = buf_pa;
+                       desc2->len = (u16)skb->len;
+                       desc2->frag_len = (u16)skb->len;
+                       desc2->offset = 0;
+                       desc2->flags = MWIFIEX_BD_FLAG_FIRST_DESC |
+                                        MWIFIEX_BD_FLAG_LAST_DESC;
+               } else {
+                       desc = card->txbd_ring[wrindx];
+                       desc->paddr = buf_pa;
+                       desc->len = (u16)skb->len;
+                       desc->flags = MWIFIEX_BD_FLAG_FIRST_DESC |
+                                     MWIFIEX_BD_FLAG_LAST_DESC;
+               }
+
+               switch (card->dev->device) {
+               case PCIE_DEVICE_ID_MARVELL_88W8766P:
+                       card->txbd_wrptr++;
+                       break;
+               case PCIE_DEVICE_ID_MARVELL_88W8897:
+               case PCIE_DEVICE_ID_MARVELL_88W8997:
+                       card->txbd_wrptr += reg->ring_tx_start_ptr;
+                       break;
+               }
+
+               if ((card->txbd_wrptr & reg->tx_mask) == num_tx_buffs)
+                       card->txbd_wrptr = ((card->txbd_wrptr &
+                                               reg->tx_rollover_ind) ^
+                                               reg->tx_rollover_ind);
+
+               rx_val = card->rxbd_rdptr & reg->rx_wrap_mask;
+               /* Write the TX ring write pointer in to reg->tx_wrptr */
+               if (mwifiex_write_reg(adapter, reg->tx_wrptr,
+                                     card->txbd_wrptr | rx_val)) {
+                       mwifiex_dbg(adapter, ERROR,
+                                   "SEND DATA: failed to write reg->tx_wrptr\n");
+                       ret = -1;
+                       goto done_unmap;
+               }
+               if ((mwifiex_pcie_txbd_not_full(card)) &&
+                   tx_param->next_pkt_len) {
+                       /* have more packets and TxBD still can hold more */
+                       mwifiex_dbg(adapter, DATA,
+                                   "SEND DATA: delay dnld-rdy interrupt.\n");
+                       adapter->data_sent = false;
+               } else {
+                       /* Send the TX ready interrupt */
+                       if (mwifiex_write_reg(adapter, PCIE_CPU_INT_EVENT,
+                                             CPU_INTR_DNLD_RDY)) {
+                               mwifiex_dbg(adapter, ERROR,
+                                           "SEND DATA: failed to assert dnld-rdy interrupt.\n");
+                               ret = -1;
+                               goto done_unmap;
+                       }
+               }
+               mwifiex_dbg(adapter, DATA,
+                           "info: SEND DATA: Updated <Rd: %#x, Wr:\t"
+                           "%#x> and sent packet to firmware successfully\n",
+                           card->txbd_rdptr, card->txbd_wrptr);
+       } else {
+               mwifiex_dbg(adapter, DATA,
+                           "info: TX Ring full, can't send packets to fw\n");
+               adapter->data_sent = true;
+               /* Send the TX ready interrupt */
+               if (mwifiex_write_reg(adapter, PCIE_CPU_INT_EVENT,
+                                     CPU_INTR_DNLD_RDY))
+                       mwifiex_dbg(adapter, ERROR,
+                                   "SEND DATA: failed to assert door-bell intr\n");
+               return -EBUSY;
+       }
+
+       return -EINPROGRESS;
+done_unmap:
+       mwifiex_unmap_pci_memory(adapter, skb, PCI_DMA_TODEVICE);
+       card->tx_buf_list[wrindx] = NULL;
+       if (reg->pfu_enabled)
+               memset(desc2, 0, sizeof(*desc2));
+       else
+               memset(desc, 0, sizeof(*desc));
+
+       return ret;
+}
+
+/*
+ * This function handles received buffer ring and
+ * dispatches packets to upper
+ */
+static int mwifiex_pcie_process_recv_data(struct mwifiex_adapter *adapter)
+{
+       struct pcie_service_card *card = adapter->card;
+       const struct mwifiex_pcie_card_reg *reg = card->pcie.reg;
+       u32 wrptr, rd_index, tx_val;
+       dma_addr_t buf_pa;
+       int ret = 0;
+       struct sk_buff *skb_tmp = NULL;
+       struct mwifiex_pcie_buf_desc *desc;
+       struct mwifiex_pfu_buf_desc *desc2;
+
+       if (!mwifiex_pcie_ok_to_access_hw(adapter))
+               mwifiex_pm_wakeup_card(adapter);
+
+       /* Read the RX ring Write pointer set by firmware */
+       if (mwifiex_read_reg(adapter, reg->rx_wrptr, &wrptr)) {
+               mwifiex_dbg(adapter, ERROR,
+                           "RECV DATA: failed to read reg->rx_wrptr\n");
+               ret = -1;
+               goto done;
+       }
+       card->rxbd_wrptr = wrptr;
+
+       while (((wrptr & reg->rx_mask) !=
+               (card->rxbd_rdptr & reg->rx_mask)) ||
+              ((wrptr & reg->rx_rollover_ind) ==
+               (card->rxbd_rdptr & reg->rx_rollover_ind))) {
+               struct sk_buff *skb_data;
+               u16 rx_len;
+               __le16 pkt_len;
+
+               rd_index = card->rxbd_rdptr & reg->rx_mask;
+               skb_data = card->rx_buf_list[rd_index];
+
+               /* If skb allocation was failed earlier for Rx packet,
+                * rx_buf_list[rd_index] would have been left with a NULL.
+                */
+               if (!skb_data)
+                       return -ENOMEM;
+
+               mwifiex_unmap_pci_memory(adapter, skb_data, PCI_DMA_FROMDEVICE);
+               card->rx_buf_list[rd_index] = NULL;
+
+               /* Get data length from interface header -
+                * first 2 bytes for len, next 2 bytes is for type
+                */
+               pkt_len = *((__le16 *)skb_data->data);
+               rx_len = le16_to_cpu(pkt_len);
+               if (WARN_ON(rx_len <= INTF_HEADER_LEN ||
+                           rx_len > MWIFIEX_RX_DATA_BUF_SIZE)) {
+                       mwifiex_dbg(adapter, ERROR,
+                                   "Invalid RX len %d, Rd=%#x, Wr=%#x\n",
+                                   rx_len, card->rxbd_rdptr, wrptr);
+                       dev_kfree_skb_any(skb_data);
+               } else {
+                       skb_put(skb_data, rx_len);
+                       mwifiex_dbg(adapter, DATA,
+                                   "info: RECV DATA: Rd=%#x, Wr=%#x, Len=%d\n",
+                                   card->rxbd_rdptr, wrptr, rx_len);
+                       skb_pull(skb_data, INTF_HEADER_LEN);
+                       if (adapter->rx_work_enabled) {
+                               skb_queue_tail(&adapter->rx_data_q, skb_data);
+                               adapter->data_received = true;
+                               atomic_inc(&adapter->rx_pending);
+                       } else {
+                               mwifiex_handle_rx_packet(adapter, skb_data);
+                       }
+               }
+
+               skb_tmp = mwifiex_alloc_dma_align_buf(MWIFIEX_RX_DATA_BUF_SIZE,
+                                                     GFP_KERNEL | GFP_DMA);
+               if (!skb_tmp) {
+                       mwifiex_dbg(adapter, ERROR,
+                                   "Unable to allocate skb.\n");
+                       return -ENOMEM;
+               }
+
+               if (mwifiex_map_pci_memory(adapter, skb_tmp,
+                                          MWIFIEX_RX_DATA_BUF_SIZE,
+                                          PCI_DMA_FROMDEVICE))
+                       return -1;
+
+               buf_pa = MWIFIEX_SKB_DMA_ADDR(skb_tmp);
+
+               mwifiex_dbg(adapter, INFO,
+                           "RECV DATA: Attach new sk_buff %p at rxbd_rdidx=%d\n",
+                           skb_tmp, rd_index);
+               card->rx_buf_list[rd_index] = skb_tmp;
+
+               if (reg->pfu_enabled) {
+                       desc2 = card->rxbd_ring[rd_index];
+                       desc2->paddr = buf_pa;
+                       desc2->len = skb_tmp->len;
+                       desc2->frag_len = skb_tmp->len;
+                       desc2->offset = 0;
+                       desc2->flags = reg->ring_flag_sop | reg->ring_flag_eop;
+               } else {
+                       desc = card->rxbd_ring[rd_index];
+                       desc->paddr = buf_pa;
+                       desc->len = skb_tmp->len;
+                       desc->flags = 0;
+               }
+
+               if ((++card->rxbd_rdptr & reg->rx_mask) ==
+                                                       MWIFIEX_MAX_TXRX_BD) {
+                       card->rxbd_rdptr = ((card->rxbd_rdptr &
+                                            reg->rx_rollover_ind) ^
+                                            reg->rx_rollover_ind);
+               }
+               mwifiex_dbg(adapter, DATA,
+                           "info: RECV DATA: <Rd: %#x, Wr: %#x>\n",
+                           card->rxbd_rdptr, wrptr);
+
+               tx_val = card->txbd_wrptr & reg->tx_wrap_mask;
+               /* Write the RX ring read pointer in to reg->rx_rdptr */
+               if (mwifiex_write_reg(adapter, reg->rx_rdptr,
+                                     card->rxbd_rdptr | tx_val)) {
+                       mwifiex_dbg(adapter, DATA,
+                                   "RECV DATA: failed to write reg->rx_rdptr\n");
+                       ret = -1;
+                       goto done;
+               }
+
+               /* Read the RX ring Write pointer set by firmware */
+               if (mwifiex_read_reg(adapter, reg->rx_wrptr, &wrptr)) {
+                       mwifiex_dbg(adapter, ERROR,
+                                   "RECV DATA: failed to read reg->rx_wrptr\n");
+                       ret = -1;
+                       goto done;
+               }
+               mwifiex_dbg(adapter, DATA,
+                           "info: RECV DATA: Rcvd packet from fw successfully\n");
+               card->rxbd_wrptr = wrptr;
+       }
+
+done:
+       return ret;
+}
+
+/*
+ * This function downloads the boot command to device
+ */
+static int
+mwifiex_pcie_send_boot_cmd(struct mwifiex_adapter *adapter, struct sk_buff *skb)
+{
+       dma_addr_t buf_pa;
+       struct pcie_service_card *card = adapter->card;
+       const struct mwifiex_pcie_card_reg *reg = card->pcie.reg;
+
+       if (!(skb->data && skb->len)) {
+               mwifiex_dbg(adapter, ERROR,
+                           "Invalid parameter in %s <%p. len %d>\n",
+                           __func__, skb->data, skb->len);
+               return -1;
+       }
+
+       if (mwifiex_map_pci_memory(adapter, skb, skb->len , PCI_DMA_TODEVICE))
+               return -1;
+
+       buf_pa = MWIFIEX_SKB_DMA_ADDR(skb);
+
+       /* Write the lower 32bits of the physical address to low command
+        * address scratch register
+        */
+       if (mwifiex_write_reg(adapter, reg->cmd_addr_lo, (u32)buf_pa)) {
+               mwifiex_dbg(adapter, ERROR,
+                           "%s: failed to write download command to boot code.\n",
+                           __func__);
+               mwifiex_unmap_pci_memory(adapter, skb, PCI_DMA_TODEVICE);
+               return -1;
+       }
+
+       /* Write the upper 32bits of the physical address to high command
+        * address scratch register
+        */
+       if (mwifiex_write_reg(adapter, reg->cmd_addr_hi,
+                             (u32)((u64)buf_pa >> 32))) {
+               mwifiex_dbg(adapter, ERROR,
+                           "%s: failed to write download command to boot code.\n",
+                           __func__);
+               mwifiex_unmap_pci_memory(adapter, skb, PCI_DMA_TODEVICE);
+               return -1;
+       }
+
+       /* Write the command length to cmd_size scratch register */
+       if (mwifiex_write_reg(adapter, reg->cmd_size, skb->len)) {
+               mwifiex_dbg(adapter, ERROR,
+                           "%s: failed to write command len to cmd_size scratch reg\n",
+                           __func__);
+               mwifiex_unmap_pci_memory(adapter, skb, PCI_DMA_TODEVICE);
+               return -1;
+       }
+
+       /* Ring the door bell */
+       if (mwifiex_write_reg(adapter, PCIE_CPU_INT_EVENT,
+                             CPU_INTR_DOOR_BELL)) {
+               mwifiex_dbg(adapter, ERROR,
+                           "%s: failed to assert door-bell intr\n", __func__);
+               mwifiex_unmap_pci_memory(adapter, skb, PCI_DMA_TODEVICE);
+               return -1;
+       }
+
+       return 0;
+}
+
+/* This function init rx port in firmware which in turn enables to receive data
+ * from device before transmitting any packet.
+ */
+static int mwifiex_pcie_init_fw_port(struct mwifiex_adapter *adapter)
+{
+       struct pcie_service_card *card = adapter->card;
+       const struct mwifiex_pcie_card_reg *reg = card->pcie.reg;
+       int tx_wrap = card->txbd_wrptr & reg->tx_wrap_mask;
+
+       /* Write the RX ring read pointer in to reg->rx_rdptr */
+       if (mwifiex_write_reg(adapter, reg->rx_rdptr, card->rxbd_rdptr |
+                             tx_wrap)) {
+               mwifiex_dbg(adapter, ERROR,
+                           "RECV DATA: failed to write reg->rx_rdptr\n");
+               return -1;
+       }
+       return 0;
+}
+
+/* This function downloads commands to the device
+ */
+static int
+mwifiex_pcie_send_cmd(struct mwifiex_adapter *adapter, struct sk_buff *skb)
+{
+       struct pcie_service_card *card = adapter->card;
+       const struct mwifiex_pcie_card_reg *reg = card->pcie.reg;
+       int ret = 0;
+       dma_addr_t cmd_buf_pa, cmdrsp_buf_pa;
+       u8 *payload = (u8 *)skb->data;
+
+       if (!(skb->data && skb->len)) {
+               mwifiex_dbg(adapter, ERROR,
+                           "Invalid parameter in %s <%p, %#x>\n",
+                           __func__, skb->data, skb->len);
+               return -1;
+       }
+
+       /* Make sure a command response buffer is available */
+       if (!card->cmdrsp_buf) {
+               mwifiex_dbg(adapter, ERROR,
+                           "No response buffer available, send command failed\n");
+               return -EBUSY;
+       }
+
+       if (!mwifiex_pcie_ok_to_access_hw(adapter))
+               mwifiex_pm_wakeup_card(adapter);
+
+       adapter->cmd_sent = true;
+
+       *(__le16 *)&payload[0] = cpu_to_le16((u16)skb->len);
+       *(__le16 *)&payload[2] = cpu_to_le16(MWIFIEX_TYPE_CMD);
+
+       if (mwifiex_map_pci_memory(adapter, skb, skb->len, PCI_DMA_TODEVICE))
+               return -1;
+
+       card->cmd_buf = skb;
+
+       /* To send a command, the driver will:
+               1. Write the 64bit physical address of the data buffer to
+                  cmd response address low  + cmd response address high
+               2. Ring the door bell (i.e. set the door bell interrupt)
+
+               In response to door bell interrupt, the firmware will perform
+               the DMA of the command packet (first header to obtain the total
+               length and then rest of the command).
+       */
+
+       if (card->cmdrsp_buf) {
+               cmdrsp_buf_pa = MWIFIEX_SKB_DMA_ADDR(card->cmdrsp_buf);
+               /* Write the lower 32bits of the cmdrsp buffer physical
+                  address */
+               if (mwifiex_write_reg(adapter, reg->cmdrsp_addr_lo,
+                                     (u32)cmdrsp_buf_pa)) {
+                       mwifiex_dbg(adapter, ERROR,
+                                   "Failed to write download cmd to boot code.\n");
+                       ret = -1;
+                       goto done;
+               }
+               /* Write the upper 32bits of the cmdrsp buffer physical
+                  address */
+               if (mwifiex_write_reg(adapter, reg->cmdrsp_addr_hi,
+                                     (u32)((u64)cmdrsp_buf_pa >> 32))) {
+                       mwifiex_dbg(adapter, ERROR,
+                                   "Failed to write download cmd to boot code.\n");
+                       ret = -1;
+                       goto done;
+               }
+       }
+
+       cmd_buf_pa = MWIFIEX_SKB_DMA_ADDR(card->cmd_buf);
+       /* Write the lower 32bits of the physical address to reg->cmd_addr_lo */
+       if (mwifiex_write_reg(adapter, reg->cmd_addr_lo,
+                             (u32)cmd_buf_pa)) {
+               mwifiex_dbg(adapter, ERROR,
+                           "Failed to write download cmd to boot code.\n");
+               ret = -1;
+               goto done;
+       }
+       /* Write the upper 32bits of the physical address to reg->cmd_addr_hi */
+       if (mwifiex_write_reg(adapter, reg->cmd_addr_hi,
+                             (u32)((u64)cmd_buf_pa >> 32))) {
+               mwifiex_dbg(adapter, ERROR,
+                           "Failed to write download cmd to boot code.\n");
+               ret = -1;
+               goto done;
+       }
+
+       /* Write the command length to reg->cmd_size */
+       if (mwifiex_write_reg(adapter, reg->cmd_size,
+                             card->cmd_buf->len)) {
+               mwifiex_dbg(adapter, ERROR,
+                           "Failed to write cmd len to reg->cmd_size\n");
+               ret = -1;
+               goto done;
+       }
+
+       /* Ring the door bell */
+       if (mwifiex_write_reg(adapter, PCIE_CPU_INT_EVENT,
+                             CPU_INTR_DOOR_BELL)) {
+               mwifiex_dbg(adapter, ERROR,
+                           "Failed to assert door-bell intr\n");
+               ret = -1;
+               goto done;
+       }
+
+done:
+       if (ret)
+               adapter->cmd_sent = false;
+
+       return 0;
+}
+
+/*
+ * This function handles command complete interrupt
+ */
+static int mwifiex_pcie_process_cmd_complete(struct mwifiex_adapter *adapter)
+{
+       struct pcie_service_card *card = adapter->card;
+       const struct mwifiex_pcie_card_reg *reg = card->pcie.reg;
+       struct sk_buff *skb = card->cmdrsp_buf;
+       int count = 0;
+       u16 rx_len;
+       __le16 pkt_len;
+
+       mwifiex_dbg(adapter, CMD,
+                   "info: Rx CMD Response\n");
+
+       mwifiex_unmap_pci_memory(adapter, skb, PCI_DMA_FROMDEVICE);
+
+       /* Unmap the command as a response has been received. */
+       if (card->cmd_buf) {
+               mwifiex_unmap_pci_memory(adapter, card->cmd_buf,
+                                        PCI_DMA_TODEVICE);
+               card->cmd_buf = NULL;
+       }
+
+       pkt_len = *((__le16 *)skb->data);
+       rx_len = le16_to_cpu(pkt_len);
+       skb_trim(skb, rx_len);
+       skb_pull(skb, INTF_HEADER_LEN);
+
+       if (!adapter->curr_cmd) {
+               if (adapter->ps_state == PS_STATE_SLEEP_CFM) {
+                       mwifiex_process_sleep_confirm_resp(adapter, skb->data,
+                                                          skb->len);
+                       mwifiex_pcie_enable_host_int(adapter);
+                       if (mwifiex_write_reg(adapter,
+                                             PCIE_CPU_INT_EVENT,
+                                             CPU_INTR_SLEEP_CFM_DONE)) {
+                               mwifiex_dbg(adapter, ERROR,
+                                           "Write register failed\n");
+                               return -1;
+                       }
+                       mwifiex_delay_for_sleep_cookie(adapter,
+                                                      MWIFIEX_MAX_DELAY_COUNT);
+                       while (reg->sleep_cookie && (count++ < 10) &&
+                              mwifiex_pcie_ok_to_access_hw(adapter))
+                               usleep_range(50, 60);
+               } else {
+                       mwifiex_dbg(adapter, ERROR,
+                                   "There is no command but got cmdrsp\n");
+               }
+               memcpy(adapter->upld_buf, skb->data,
+                      min_t(u32, MWIFIEX_SIZE_OF_CMD_BUFFER, skb->len));
+               skb_push(skb, INTF_HEADER_LEN);
+               if (mwifiex_map_pci_memory(adapter, skb, MWIFIEX_UPLD_SIZE,
+                                          PCI_DMA_FROMDEVICE))
+                       return -1;
+       } else if (mwifiex_pcie_ok_to_access_hw(adapter)) {
+               adapter->curr_cmd->resp_skb = skb;
+               adapter->cmd_resp_received = true;
+               /* Take the pointer and set it to CMD node and will
+                  return in the response complete callback */
+               card->cmdrsp_buf = NULL;
+
+               /* Clear the cmd-rsp buffer address in scratch registers. This
+                  will prevent firmware from writing to the same response
+                  buffer again. */
+               if (mwifiex_write_reg(adapter, reg->cmdrsp_addr_lo, 0)) {
+                       mwifiex_dbg(adapter, ERROR,
+                                   "cmd_done: failed to clear cmd_rsp_addr_lo\n");
+                       return -1;
+               }
+               /* Write the upper 32bits of the cmdrsp buffer physical
+                  address */
+               if (mwifiex_write_reg(adapter, reg->cmdrsp_addr_hi, 0)) {
+                       mwifiex_dbg(adapter, ERROR,
+                                   "cmd_done: failed to clear cmd_rsp_addr_hi\n");
+                       return -1;
+               }
+       }
+
+       return 0;
+}
+
+/*
+ * Command Response processing complete handler
+ */
+static int mwifiex_pcie_cmdrsp_complete(struct mwifiex_adapter *adapter,
+                                       struct sk_buff *skb)
+{
+       struct pcie_service_card *card = adapter->card;
+
+       if (skb) {
+               card->cmdrsp_buf = skb;
+               skb_push(card->cmdrsp_buf, INTF_HEADER_LEN);
+               if (mwifiex_map_pci_memory(adapter, skb, MWIFIEX_UPLD_SIZE,
+                                          PCI_DMA_FROMDEVICE))
+                       return -1;
+       }
+
+       return 0;
+}
+
+/*
+ * This function handles firmware event ready interrupt
+ */
+static int mwifiex_pcie_process_event_ready(struct mwifiex_adapter *adapter)
+{
+       struct pcie_service_card *card = adapter->card;
+       const struct mwifiex_pcie_card_reg *reg = card->pcie.reg;
+       u32 rdptr = card->evtbd_rdptr & MWIFIEX_EVTBD_MASK;
+       u32 wrptr, event;
+       struct mwifiex_evt_buf_desc *desc;
+
+       if (!mwifiex_pcie_ok_to_access_hw(adapter))
+               mwifiex_pm_wakeup_card(adapter);
+
+       if (adapter->event_received) {
+               mwifiex_dbg(adapter, EVENT,
+                           "info: Event being processed,\t"
+                           "do not process this interrupt just yet\n");
+               return 0;
+       }
+
+       if (rdptr >= MWIFIEX_MAX_EVT_BD) {
+               mwifiex_dbg(adapter, ERROR,
+                           "info: Invalid read pointer...\n");
+               return -1;
+       }
+
+       /* Read the event ring write pointer set by firmware */
+       if (mwifiex_read_reg(adapter, reg->evt_wrptr, &wrptr)) {
+               mwifiex_dbg(adapter, ERROR,
+                           "EventReady: failed to read reg->evt_wrptr\n");
+               return -1;
+       }
+
+       mwifiex_dbg(adapter, EVENT,
+                   "info: EventReady: Initial <Rd: 0x%x, Wr: 0x%x>",
+                   card->evtbd_rdptr, wrptr);
+       if (((wrptr & MWIFIEX_EVTBD_MASK) != (card->evtbd_rdptr
+                                             & MWIFIEX_EVTBD_MASK)) ||
+           ((wrptr & reg->evt_rollover_ind) ==
+            (card->evtbd_rdptr & reg->evt_rollover_ind))) {
+               struct sk_buff *skb_cmd;
+               __le16 data_len = 0;
+               u16 evt_len;
+
+               mwifiex_dbg(adapter, INFO,
+                           "info: Read Index: %d\n", rdptr);
+               skb_cmd = card->evt_buf_list[rdptr];
+               mwifiex_unmap_pci_memory(adapter, skb_cmd, PCI_DMA_FROMDEVICE);
+
+               /* Take the pointer and set it to event pointer in adapter
+                  and will return back after event handling callback */
+               card->evt_buf_list[rdptr] = NULL;
+               desc = card->evtbd_ring[rdptr];
+               memset(desc, 0, sizeof(*desc));
+
+               event = *(u32 *) &skb_cmd->data[INTF_HEADER_LEN];
+               adapter->event_cause = event;
+               /* The first 4bytes will be the event transfer header
+                  len is 2 bytes followed by type which is 2 bytes */
+               memcpy(&data_len, skb_cmd->data, sizeof(__le16));
+               evt_len = le16_to_cpu(data_len);
+               skb_trim(skb_cmd, evt_len);
+               skb_pull(skb_cmd, INTF_HEADER_LEN);
+               mwifiex_dbg(adapter, EVENT,
+                           "info: Event length: %d\n", evt_len);
+
+               if ((evt_len > 0) && (evt_len  < MAX_EVENT_SIZE))
+                       memcpy(adapter->event_body, skb_cmd->data +
+                              MWIFIEX_EVENT_HEADER_LEN, evt_len -
+                              MWIFIEX_EVENT_HEADER_LEN);
+
+               adapter->event_received = true;
+               adapter->event_skb = skb_cmd;
+
+               /* Do not update the event read pointer here, wait till the
+                  buffer is released. This is just to make things simpler,
+                  we need to find a better method of managing these buffers.
+               */
+       } else {
+               if (mwifiex_write_reg(adapter, PCIE_CPU_INT_EVENT,
+                                     CPU_INTR_EVENT_DONE)) {
+                       mwifiex_dbg(adapter, ERROR,
+                                   "Write register failed\n");
+                       return -1;
+               }
+       }
+
+       return 0;
+}
+
+/*
+ * Event processing complete handler
+ */
+static int mwifiex_pcie_event_complete(struct mwifiex_adapter *adapter,
+                                      struct sk_buff *skb)
+{
+       struct pcie_service_card *card = adapter->card;
+       const struct mwifiex_pcie_card_reg *reg = card->pcie.reg;
+       int ret = 0;
+       u32 rdptr = card->evtbd_rdptr & MWIFIEX_EVTBD_MASK;
+       u32 wrptr;
+       struct mwifiex_evt_buf_desc *desc;
+
+       if (!skb)
+               return 0;
+
+       if (rdptr >= MWIFIEX_MAX_EVT_BD) {
+               mwifiex_dbg(adapter, ERROR,
+                           "event_complete: Invalid rdptr 0x%x\n",
+                           rdptr);
+               return -EINVAL;
+       }
+
+       /* Read the event ring write pointer set by firmware */
+       if (mwifiex_read_reg(adapter, reg->evt_wrptr, &wrptr)) {
+               mwifiex_dbg(adapter, ERROR,
+                           "event_complete: failed to read reg->evt_wrptr\n");
+               return -1;
+       }
+
+       if (!card->evt_buf_list[rdptr]) {
+               skb_push(skb, INTF_HEADER_LEN);
+               skb_put(skb, MAX_EVENT_SIZE - skb->len);
+               if (mwifiex_map_pci_memory(adapter, skb,
+                                          MAX_EVENT_SIZE,
+                                          PCI_DMA_FROMDEVICE))
+                       return -1;
+               card->evt_buf_list[rdptr] = skb;
+               desc = card->evtbd_ring[rdptr];
+               desc->paddr = MWIFIEX_SKB_DMA_ADDR(skb);
+               desc->len = (u16)skb->len;
+               desc->flags = 0;
+               skb = NULL;
+       } else {
+               mwifiex_dbg(adapter, ERROR,
+                           "info: ERROR: buf still valid at index %d, <%p, %p>\n",
+                           rdptr, card->evt_buf_list[rdptr], skb);
+       }
+
+       if ((++card->evtbd_rdptr & MWIFIEX_EVTBD_MASK) == MWIFIEX_MAX_EVT_BD) {
+               card->evtbd_rdptr = ((card->evtbd_rdptr &
+                                       reg->evt_rollover_ind) ^
+                                       reg->evt_rollover_ind);
+       }
+
+       mwifiex_dbg(adapter, EVENT,
+                   "info: Updated <Rd: 0x%x, Wr: 0x%x>",
+                   card->evtbd_rdptr, wrptr);
+
+       /* Write the event ring read pointer in to reg->evt_rdptr */
+       if (mwifiex_write_reg(adapter, reg->evt_rdptr,
+                             card->evtbd_rdptr)) {
+               mwifiex_dbg(adapter, ERROR,
+                           "event_complete: failed to read reg->evt_rdptr\n");
+               return -1;
+       }
+
+       mwifiex_dbg(adapter, EVENT,
+                   "info: Check Events Again\n");
+       ret = mwifiex_pcie_process_event_ready(adapter);
+
+       return ret;
+}
+
+/*
+ * This function downloads the firmware to the card.
+ *
+ * Firmware is downloaded to the card in blocks. Every block download
+ * is tested for CRC errors, and retried a number of times before
+ * returning failure.
+ */
+static int mwifiex_prog_fw_w_helper(struct mwifiex_adapter *adapter,
+                                   struct mwifiex_fw_image *fw)
+{
+       int ret;
+       u8 *firmware = fw->fw_buf;
+       u32 firmware_len = fw->fw_len;
+       u32 offset = 0;
+       struct sk_buff *skb;
+       u32 txlen, tx_blocks = 0, tries, len;
+       u32 block_retry_cnt = 0;
+       struct pcie_service_card *card = adapter->card;
+       const struct mwifiex_pcie_card_reg *reg = card->pcie.reg;
+
+       if (!firmware || !firmware_len) {
+               mwifiex_dbg(adapter, ERROR,
+                           "No firmware image found! Terminating download\n");
+               return -1;
+       }
+
+       mwifiex_dbg(adapter, INFO,
+                   "info: Downloading FW image (%d bytes)\n",
+                   firmware_len);
+
+       if (mwifiex_pcie_disable_host_int(adapter)) {
+               mwifiex_dbg(adapter, ERROR,
+                           "%s: Disabling interrupts failed.\n", __func__);
+               return -1;
+       }
+
+       skb = dev_alloc_skb(MWIFIEX_UPLD_SIZE);
+       if (!skb) {
+               ret = -ENOMEM;
+               goto done;
+       }
+
+       /* Perform firmware data transfer */
+       do {
+               u32 ireg_intr = 0;
+
+               /* More data? */
+               if (offset >= firmware_len)
+                       break;
+
+               for (tries = 0; tries < MAX_POLL_TRIES; tries++) {
+                       ret = mwifiex_read_reg(adapter, reg->cmd_size,
+                                              &len);
+                       if (ret) {
+                               mwifiex_dbg(adapter, FATAL,
+                                           "Failed reading len from boot code\n");
+                               goto done;
+                       }
+                       if (len)
+                               break;
+                       usleep_range(10, 20);
+               }
+
+               if (!len) {
+                       break;
+               } else if (len > MWIFIEX_UPLD_SIZE) {
+                       mwifiex_dbg(adapter, ERROR,
+                                   "FW download failure @ %d, invalid length %d\n",
+                                   offset, len);
+                       ret = -1;
+                       goto done;
+               }
+
+               txlen = len;
+
+               if (len & BIT(0)) {
+                       block_retry_cnt++;
+                       if (block_retry_cnt > MAX_WRITE_IOMEM_RETRY) {
+                               mwifiex_dbg(adapter, ERROR,
+                                           "FW download failure @ %d, over max\t"
+                                           "retry count\n", offset);
+                               ret = -1;
+                               goto done;
+                       }
+                       mwifiex_dbg(adapter, ERROR,
+                                   "FW CRC error indicated by the\t"
+                                   "helper: len = 0x%04X, txlen = %d\n",
+                                   len, txlen);
+                       len &= ~BIT(0);
+                       /* Setting this to 0 to resend from same offset */
+                       txlen = 0;
+               } else {
+                       block_retry_cnt = 0;
+                       /* Set blocksize to transfer - checking for
+                          last block */
+                       if (firmware_len - offset < txlen)
+                               txlen = firmware_len - offset;
+
+                       mwifiex_dbg(adapter, INFO, ".");
+
+                       tx_blocks = (txlen + card->pcie.blksz_fw_dl - 1) /
+                                   card->pcie.blksz_fw_dl;
+
+                       /* Copy payload to buffer */
+                       memmove(skb->data, &firmware[offset], txlen);
+               }
+
+               skb_put(skb, MWIFIEX_UPLD_SIZE - skb->len);
+               skb_trim(skb, tx_blocks * card->pcie.blksz_fw_dl);
+
+               /* Send the boot command to device */
+               if (mwifiex_pcie_send_boot_cmd(adapter, skb)) {
+                       mwifiex_dbg(adapter, ERROR,
+                                   "Failed to send firmware download command\n");
+                       ret = -1;
+                       goto done;
+               }
+
+               /* Wait for the command done interrupt */
+               do {
+                       if (mwifiex_read_reg(adapter, PCIE_CPU_INT_STATUS,
+                                            &ireg_intr)) {
+                               mwifiex_dbg(adapter, ERROR,
+                                           "%s: Failed to read\t"
+                                           "interrupt status during fw dnld.\n",
+                                           __func__);
+                               mwifiex_unmap_pci_memory(adapter, skb,
+                                                        PCI_DMA_TODEVICE);
+                               ret = -1;
+                               goto done;
+                       }
+               } while ((ireg_intr & CPU_INTR_DOOR_BELL) ==
+                        CPU_INTR_DOOR_BELL);
+
+               mwifiex_unmap_pci_memory(adapter, skb, PCI_DMA_TODEVICE);
+
+               offset += txlen;
+       } while (true);
+
+       mwifiex_dbg(adapter, MSG,
+                   "info: FW download over, size %d bytes\n", offset);
+
+       ret = 0;
+
+done:
+       dev_kfree_skb_any(skb);
+       return ret;
+}
+
+/*
+ * This function checks the firmware status in card.
+ *
+ * The winner interface is also determined by this function.
+ */
+static int
+mwifiex_check_fw_status(struct mwifiex_adapter *adapter, u32 poll_num)
+{
+       int ret = 0;
+       u32 firmware_stat, winner_status;
+       struct pcie_service_card *card = adapter->card;
+       const struct mwifiex_pcie_card_reg *reg = card->pcie.reg;
+       u32 tries;
+
+       /* Mask spurios interrupts */
+       if (mwifiex_write_reg(adapter, PCIE_HOST_INT_STATUS_MASK,
+                             HOST_INTR_MASK)) {
+               mwifiex_dbg(adapter, ERROR,
+                           "Write register failed\n");
+               return -1;
+       }
+
+       mwifiex_dbg(adapter, INFO,
+                   "Setting driver ready signature\n");
+       if (mwifiex_write_reg(adapter, reg->drv_rdy,
+                             FIRMWARE_READY_PCIE)) {
+               mwifiex_dbg(adapter, ERROR,
+                           "Failed to write driver ready signature\n");
+               return -1;
+       }
+
+       /* Wait for firmware initialization event */
+       for (tries = 0; tries < poll_num; tries++) {
+               if (mwifiex_read_reg(adapter, reg->fw_status,
+                                    &firmware_stat))
+                       ret = -1;
+               else
+                       ret = 0;
+               if (ret)
+                       continue;
+               if (firmware_stat == FIRMWARE_READY_PCIE) {
+                       ret = 0;
+                       break;
+               } else {
+                       msleep(100);
+                       ret = -1;
+               }
+       }
+
+       if (ret) {
+               if (mwifiex_read_reg(adapter, reg->fw_status,
+                                    &winner_status))
+                       ret = -1;
+               else if (!winner_status) {
+                       mwifiex_dbg(adapter, INFO,
+                                   "PCI-E is the winner\n");
+                       adapter->winner = 1;
+               } else {
+                       mwifiex_dbg(adapter, ERROR,
+                                   "PCI-E is not the winner <%#x,%d>, exit dnld\n",
+                                   ret, adapter->winner);
+               }
+       }
+
+       return ret;
+}
+
+/*
+ * This function reads the interrupt status from card.
+ */
+static void mwifiex_interrupt_status(struct mwifiex_adapter *adapter)
+{
+       u32 pcie_ireg;
+       unsigned long flags;
+
+       if (!mwifiex_pcie_ok_to_access_hw(adapter))
+               return;
+
+       if (mwifiex_read_reg(adapter, PCIE_HOST_INT_STATUS, &pcie_ireg)) {
+               mwifiex_dbg(adapter, ERROR, "Read register failed\n");
+               return;
+       }
+
+       if ((pcie_ireg != 0xFFFFFFFF) && (pcie_ireg)) {
+
+               mwifiex_pcie_disable_host_int(adapter);
+
+               /* Clear the pending interrupts */
+               if (mwifiex_write_reg(adapter, PCIE_HOST_INT_STATUS,
+                                     ~pcie_ireg)) {
+                       mwifiex_dbg(adapter, ERROR,
+                                   "Write register failed\n");
+                       return;
+               }
+               spin_lock_irqsave(&adapter->int_lock, flags);
+               adapter->int_status |= pcie_ireg;
+               spin_unlock_irqrestore(&adapter->int_lock, flags);
+
+               if (!adapter->pps_uapsd_mode &&
+                   adapter->ps_state == PS_STATE_SLEEP &&
+                   mwifiex_pcie_ok_to_access_hw(adapter)) {
+                               /* Potentially for PCIe we could get other
+                                * interrupts like shared. Don't change power
+                                * state until cookie is set */
+                               adapter->ps_state = PS_STATE_AWAKE;
+                               adapter->pm_wakeup_fw_try = false;
+                               del_timer(&adapter->wakeup_timer);
+               }
+       }
+}
+
+/*
+ * Interrupt handler for PCIe root port
+ *
+ * This function reads the interrupt status from firmware and assigns
+ * the main process in workqueue which will handle the interrupt.
+ */
+static irqreturn_t mwifiex_pcie_interrupt(int irq, void *context)
+{
+       struct pci_dev *pdev = (struct pci_dev *)context;
+       struct pcie_service_card *card;
+       struct mwifiex_adapter *adapter;
+
+       if (!pdev) {
+               pr_debug("info: %s: pdev is NULL\n", (u8 *)pdev);
+               goto exit;
+       }
+
+       card = pci_get_drvdata(pdev);
+       if (!card || !card->adapter) {
+               pr_debug("info: %s: card=%p adapter=%p\n", __func__, card,
+                        card ? card->adapter : NULL);
+               goto exit;
+       }
+       adapter = card->adapter;
+
+       if (adapter->surprise_removed)
+               goto exit;
+
+       mwifiex_interrupt_status(adapter);
+       mwifiex_queue_main_work(adapter);
+
+exit:
+       return IRQ_HANDLED;
+}
+
+/*
+ * This function checks the current interrupt status.
+ *
+ * The following interrupts are checked and handled by this function -
+ *      - Data sent
+ *      - Command sent
+ *      - Command received
+ *      - Packets received
+ *      - Events received
+ *
+ * In case of Rx packets received, the packets are uploaded from card to
+ * host and processed accordingly.
+ */
+static int mwifiex_process_int_status(struct mwifiex_adapter *adapter)
+{
+       int ret;
+       u32 pcie_ireg;
+       unsigned long flags;
+
+       spin_lock_irqsave(&adapter->int_lock, flags);
+       /* Clear out unused interrupts */
+       pcie_ireg = adapter->int_status;
+       adapter->int_status = 0;
+       spin_unlock_irqrestore(&adapter->int_lock, flags);
+
+       while (pcie_ireg & HOST_INTR_MASK) {
+               if (pcie_ireg & HOST_INTR_DNLD_DONE) {
+                       pcie_ireg &= ~HOST_INTR_DNLD_DONE;
+                       mwifiex_dbg(adapter, INTR,
+                                   "info: TX DNLD Done\n");
+                       ret = mwifiex_pcie_send_data_complete(adapter);
+                       if (ret)
+                               return ret;
+               }
+               if (pcie_ireg & HOST_INTR_UPLD_RDY) {
+                       pcie_ireg &= ~HOST_INTR_UPLD_RDY;
+                       mwifiex_dbg(adapter, INTR,
+                                   "info: Rx DATA\n");
+                       ret = mwifiex_pcie_process_recv_data(adapter);
+                       if (ret)
+                               return ret;
+               }
+               if (pcie_ireg & HOST_INTR_EVENT_RDY) {
+                       pcie_ireg &= ~HOST_INTR_EVENT_RDY;
+                       mwifiex_dbg(adapter, INTR,
+                                   "info: Rx EVENT\n");
+                       ret = mwifiex_pcie_process_event_ready(adapter);
+                       if (ret)
+                               return ret;
+               }
+
+               if (pcie_ireg & HOST_INTR_CMD_DONE) {
+                       pcie_ireg &= ~HOST_INTR_CMD_DONE;
+                       if (adapter->cmd_sent) {
+                               mwifiex_dbg(adapter, INTR,
+                                           "info: CMD sent Interrupt\n");
+                               adapter->cmd_sent = false;
+                       }
+                       /* Handle command response */
+                       ret = mwifiex_pcie_process_cmd_complete(adapter);
+                       if (ret)
+                               return ret;
+               }
+
+               if (mwifiex_pcie_ok_to_access_hw(adapter)) {
+                       if (mwifiex_read_reg(adapter, PCIE_HOST_INT_STATUS,
+                                            &pcie_ireg)) {
+                               mwifiex_dbg(adapter, ERROR,
+                                           "Read register failed\n");
+                               return -1;
+                       }
+
+                       if ((pcie_ireg != 0xFFFFFFFF) && (pcie_ireg)) {
+                               if (mwifiex_write_reg(adapter,
+                                                     PCIE_HOST_INT_STATUS,
+                                                     ~pcie_ireg)) {
+                                       mwifiex_dbg(adapter, ERROR,
+                                                   "Write register failed\n");
+                                       return -1;
+                               }
+                       }
+
+               }
+       }
+       mwifiex_dbg(adapter, INTR,
+                   "info: cmd_sent=%d data_sent=%d\n",
+                   adapter->cmd_sent, adapter->data_sent);
+       if (adapter->ps_state != PS_STATE_SLEEP)
+               mwifiex_pcie_enable_host_int(adapter);
+
+       return 0;
+}
+
+/*
+ * This function downloads data from driver to card.
+ *
+ * Both commands and data packets are transferred to the card by this
+ * function.
+ *
+ * This function adds the PCIE specific header to the front of the buffer
+ * before transferring. The header contains the length of the packet and
+ * the type. The firmware handles the packets based upon this set type.
+ */
+static int mwifiex_pcie_host_to_card(struct mwifiex_adapter *adapter, u8 type,
+                                    struct sk_buff *skb,
+                                    struct mwifiex_tx_param *tx_param)
+{
+       if (!skb) {
+               mwifiex_dbg(adapter, ERROR,
+                           "Passed NULL skb to %s\n", __func__);
+               return -1;
+       }
+
+       if (type == MWIFIEX_TYPE_DATA)
+               return mwifiex_pcie_send_data(adapter, skb, tx_param);
+       else if (type == MWIFIEX_TYPE_CMD)
+               return mwifiex_pcie_send_cmd(adapter, skb);
+
+       return 0;
+}
+
+/* This function read/write firmware */
+static enum rdwr_status
+mwifiex_pcie_rdwr_firmware(struct mwifiex_adapter *adapter, u8 doneflag)
+{
+       int ret, tries;
+       u8 ctrl_data;
+       struct pcie_service_card *card = adapter->card;
+       const struct mwifiex_pcie_card_reg *reg = card->pcie.reg;
+
+       ret = mwifiex_write_reg(adapter, reg->fw_dump_ctrl, FW_DUMP_HOST_READY);
+       if (ret) {
+               mwifiex_dbg(adapter, ERROR,
+                           "PCIE write err\n");
+               return RDWR_STATUS_FAILURE;
+       }
+
+       for (tries = 0; tries < MAX_POLL_TRIES; tries++) {
+               mwifiex_read_reg_byte(adapter, reg->fw_dump_ctrl, &ctrl_data);
+               if (ctrl_data == FW_DUMP_DONE)
+                       return RDWR_STATUS_SUCCESS;
+               if (doneflag && ctrl_data == doneflag)
+                       return RDWR_STATUS_DONE;
+               if (ctrl_data != FW_DUMP_HOST_READY) {
+                       mwifiex_dbg(adapter, WARN,
+                                   "The ctrl reg was changed, re-try again!\n");
+                       ret = mwifiex_write_reg(adapter, reg->fw_dump_ctrl,
+                                               FW_DUMP_HOST_READY);
+                       if (ret) {
+                               mwifiex_dbg(adapter, ERROR,
+                                           "PCIE write err\n");
+                               return RDWR_STATUS_FAILURE;
+                       }
+               }
+               usleep_range(100, 200);
+       }
+
+       mwifiex_dbg(adapter, ERROR, "Fail to pull ctrl_data\n");
+       return RDWR_STATUS_FAILURE;
+}
+
+/* This function dump firmware memory to file */
+static void mwifiex_pcie_fw_dump(struct mwifiex_adapter *adapter)
+{
+       struct pcie_service_card *card = adapter->card;
+       const struct mwifiex_pcie_card_reg *creg = card->pcie.reg;
+       unsigned int reg, reg_start, reg_end;
+       u8 *dbg_ptr, *end_ptr, dump_num, idx, i, read_reg, doneflag = 0;
+       enum rdwr_status stat;
+       u32 memory_size;
+       int ret;
+
+       if (!card->pcie.can_dump_fw)
+               return;
+
+       for (idx = 0; idx < ARRAY_SIZE(mem_type_mapping_tbl); idx++) {
+               struct memory_type_mapping *entry = &mem_type_mapping_tbl[idx];
+
+               if (entry->mem_ptr) {
+                       vfree(entry->mem_ptr);
+                       entry->mem_ptr = NULL;
+               }
+               entry->mem_size = 0;
+       }
+
+       mwifiex_dbg(adapter, DUMP, "== mwifiex firmware dump start ==\n");
+
+       /* Read the number of the memories which will dump */
+       stat = mwifiex_pcie_rdwr_firmware(adapter, doneflag);
+       if (stat == RDWR_STATUS_FAILURE)
+               return;
+
+       reg = creg->fw_dump_start;
+       mwifiex_read_reg_byte(adapter, reg, &dump_num);
+
+       /* Read the length of every memory which will dump */
+       for (idx = 0; idx < dump_num; idx++) {
+               struct memory_type_mapping *entry = &mem_type_mapping_tbl[idx];
+
+               stat = mwifiex_pcie_rdwr_firmware(adapter, doneflag);
+               if (stat == RDWR_STATUS_FAILURE)
+                       return;
+
+               memory_size = 0;
+               reg = creg->fw_dump_start;
+               for (i = 0; i < 4; i++) {
+                       mwifiex_read_reg_byte(adapter, reg, &read_reg);
+                       memory_size |= (read_reg << (i * 8));
+                       reg++;
+               }
+
+               if (memory_size == 0) {
+                       mwifiex_dbg(adapter, MSG, "Firmware dump Finished!\n");
+                       ret = mwifiex_write_reg(adapter, creg->fw_dump_ctrl,
+                                               FW_DUMP_READ_DONE);
+                       if (ret) {
+                               mwifiex_dbg(adapter, ERROR, "PCIE write err\n");
+                               return;
+                       }
+                       break;
+               }
+
+               mwifiex_dbg(adapter, DUMP,
+                           "%s_SIZE=0x%x\n", entry->mem_name, memory_size);
+               entry->mem_ptr = vmalloc(memory_size + 1);
+               entry->mem_size = memory_size;
+               if (!entry->mem_ptr) {
+                       mwifiex_dbg(adapter, ERROR,
+                                   "Vmalloc %s failed\n", entry->mem_name);
+                       return;
+               }
+               dbg_ptr = entry->mem_ptr;
+               end_ptr = dbg_ptr + memory_size;
+
+               doneflag = entry->done_flag;
+               mwifiex_dbg(adapter, DUMP, "Start %s output, please wait...\n",
+                           entry->mem_name);
+
+               do {
+                       stat = mwifiex_pcie_rdwr_firmware(adapter, doneflag);
+                       if (RDWR_STATUS_FAILURE == stat)
+                               return;
+
+                       reg_start = creg->fw_dump_start;
+                       reg_end = creg->fw_dump_end;
+                       for (reg = reg_start; reg <= reg_end; reg++) {
+                               mwifiex_read_reg_byte(adapter, reg, dbg_ptr);
+                               if (dbg_ptr < end_ptr) {
+                                       dbg_ptr++;
+                               } else {
+                                       mwifiex_dbg(adapter, ERROR,
+                                                   "Allocated buf not enough\n");
+                                       return;
+                               }
+                       }
+
+                       if (stat != RDWR_STATUS_DONE)
+                               continue;
+
+                       mwifiex_dbg(adapter, DUMP,
+                                   "%s done: size=0x%tx\n",
+                                   entry->mem_name, dbg_ptr - entry->mem_ptr);
+                       break;
+               } while (true);
+       }
+       mwifiex_dbg(adapter, DUMP, "== mwifiex firmware dump end ==\n");
+}
+
+static void mwifiex_pcie_device_dump_work(struct mwifiex_adapter *adapter)
+{
+       mwifiex_drv_info_dump(adapter);
+       mwifiex_pcie_fw_dump(adapter);
+       mwifiex_upload_device_dump(adapter);
+}
+
+static unsigned long iface_work_flags;
+static struct mwifiex_adapter *save_adapter;
+static void mwifiex_pcie_work(struct work_struct *work)
+{
+       if (test_and_clear_bit(MWIFIEX_IFACE_WORK_DEVICE_DUMP,
+                              &iface_work_flags))
+               mwifiex_pcie_device_dump_work(save_adapter);
+}
+
+static DECLARE_WORK(pcie_work, mwifiex_pcie_work);
+/* This function dumps FW information */
+static void mwifiex_pcie_device_dump(struct mwifiex_adapter *adapter)
+{
+       save_adapter = adapter;
+       if (test_bit(MWIFIEX_IFACE_WORK_DEVICE_DUMP, &iface_work_flags))
+               return;
+
+       set_bit(MWIFIEX_IFACE_WORK_DEVICE_DUMP, &iface_work_flags);
+
+       schedule_work(&pcie_work);
+}
+
+/*
+ * This function initializes the PCI-E host memory space, WCB rings, etc.
+ *
+ * The following initializations steps are followed -
+ *      - Allocate TXBD ring buffers
+ *      - Allocate RXBD ring buffers
+ *      - Allocate event BD ring buffers
+ *      - Allocate command response ring buffer
+ *      - Allocate sleep cookie buffer
+ */
+static int mwifiex_pcie_init(struct mwifiex_adapter *adapter)
+{
+       struct pcie_service_card *card = adapter->card;
+       int ret;
+       struct pci_dev *pdev = card->dev;
+       const struct mwifiex_pcie_card_reg *reg = card->pcie.reg;
+
+       pci_set_drvdata(pdev, card);
+
+       ret = pci_enable_device(pdev);
+       if (ret)
+               goto err_enable_dev;
+
+       pci_set_master(pdev);
+
+       mwifiex_dbg(adapter, INFO,
+                   "try set_consistent_dma_mask(32)\n");
+       ret = pci_set_dma_mask(pdev, DMA_BIT_MASK(32));
+       if (ret) {
+               mwifiex_dbg(adapter, ERROR,
+                           "set_dma_mask(32) failed\n");
+               goto err_set_dma_mask;
+       }
+
+       ret = pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(32));
+       if (ret) {
+               mwifiex_dbg(adapter, ERROR,
+                           "set_consistent_dma_mask(64) failed\n");
+               goto err_set_dma_mask;
+       }
+
+       ret = pci_request_region(pdev, 0, DRV_NAME);
+       if (ret) {
+               mwifiex_dbg(adapter, ERROR,
+                           "req_reg(0) error\n");
+               goto err_req_region0;
+       }
+       card->pci_mmap = pci_iomap(pdev, 0, 0);
+       if (!card->pci_mmap) {
+               mwifiex_dbg(adapter, ERROR, "iomap(0) error\n");
+               ret = -EIO;
+               goto err_iomap0;
+       }
+       ret = pci_request_region(pdev, 2, DRV_NAME);
+       if (ret) {
+               mwifiex_dbg(adapter, ERROR, "req_reg(2) error\n");
+               goto err_req_region2;
+       }
+       card->pci_mmap1 = pci_iomap(pdev, 2, 0);
+       if (!card->pci_mmap1) {
+               mwifiex_dbg(adapter, ERROR,
+                           "iomap(2) error\n");
+               ret = -EIO;
+               goto err_iomap2;
+       }
+
+       mwifiex_dbg(adapter, INFO,
+                   "PCI memory map Virt0: %p PCI memory map Virt2: %p\n",
+                   card->pci_mmap, card->pci_mmap1);
+
+       card->cmdrsp_buf = NULL;
+       ret = mwifiex_pcie_create_txbd_ring(adapter);
+       if (ret)
+               goto err_cre_txbd;
+       ret = mwifiex_pcie_create_rxbd_ring(adapter);
+       if (ret)
+               goto err_cre_rxbd;
+       ret = mwifiex_pcie_create_evtbd_ring(adapter);
+       if (ret)
+               goto err_cre_evtbd;
+       ret = mwifiex_pcie_alloc_cmdrsp_buf(adapter);
+       if (ret)
+               goto err_alloc_cmdbuf;
+       if (reg->sleep_cookie) {
+               ret = mwifiex_pcie_alloc_sleep_cookie_buf(adapter);
+               if (ret)
+                       goto err_alloc_cookie;
+       } else {
+               card->sleep_cookie_vbase = NULL;
+       }
+       return ret;
+
+err_alloc_cookie:
+       mwifiex_pcie_delete_cmdrsp_buf(adapter);
+err_alloc_cmdbuf:
+       mwifiex_pcie_delete_evtbd_ring(adapter);
+err_cre_evtbd:
+       mwifiex_pcie_delete_rxbd_ring(adapter);
+err_cre_rxbd:
+       mwifiex_pcie_delete_txbd_ring(adapter);
+err_cre_txbd:
+       pci_iounmap(pdev, card->pci_mmap1);
+err_iomap2:
+       pci_release_region(pdev, 2);
+err_req_region2:
+       pci_iounmap(pdev, card->pci_mmap);
+err_iomap0:
+       pci_release_region(pdev, 0);
+err_req_region0:
+err_set_dma_mask:
+       pci_disable_device(pdev);
+err_enable_dev:
+       pci_set_drvdata(pdev, NULL);
+       return ret;
+}
+
+/*
+ * This function cleans up the allocated card buffers.
+ *
+ * The following are freed by this function -
+ *      - TXBD ring buffers
+ *      - RXBD ring buffers
+ *      - Event BD ring buffers
+ *      - Command response ring buffer
+ *      - Sleep cookie buffer
+ */
+static void mwifiex_pcie_cleanup(struct mwifiex_adapter *adapter)
+{
+       struct pcie_service_card *card = adapter->card;
+       struct pci_dev *pdev = card->dev;
+       const struct mwifiex_pcie_card_reg *reg = card->pcie.reg;
+
+       if (user_rmmod) {
+               mwifiex_dbg(adapter, INFO,
+                           "Clearing driver ready signature\n");
+               if (mwifiex_write_reg(adapter, reg->drv_rdy, 0x00000000))
+                       mwifiex_dbg(adapter, ERROR,
+                                   "Failed to write driver not-ready signature\n");
+       }
+
+       if (pdev) {
+               pci_iounmap(pdev, card->pci_mmap);
+               pci_iounmap(pdev, card->pci_mmap1);
+               pci_disable_device(pdev);
+               pci_release_region(pdev, 2);
+               pci_release_region(pdev, 0);
+               pci_set_drvdata(pdev, NULL);
+       }
+       kfree(card);
+}
+
+/*
+ * This function registers the PCIE device.
+ *
+ * PCIE IRQ is claimed, block size is set and driver data is initialized.
+ */
+static int mwifiex_register_dev(struct mwifiex_adapter *adapter)
+{
+       int ret;
+       struct pcie_service_card *card = adapter->card;
+       struct pci_dev *pdev = card->dev;
+
+       /* save adapter pointer in card */
+       card->adapter = adapter;
+
+       ret = request_irq(pdev->irq, mwifiex_pcie_interrupt, IRQF_SHARED,
+                         "MRVL_PCIE", pdev);
+       if (ret) {
+               mwifiex_dbg(adapter, ERROR,
+                           "request_irq failed: ret=%d\n", ret);
+               adapter->card = NULL;
+               return -1;
+       }
+
+       adapter->dev = &pdev->dev;
+       adapter->tx_buf_size = card->pcie.tx_buf_size;
+       adapter->mem_type_mapping_tbl = mem_type_mapping_tbl;
+       adapter->num_mem_types = ARRAY_SIZE(mem_type_mapping_tbl);
+       strcpy(adapter->fw_name, card->pcie.firmware);
+       adapter->ext_scan = card->pcie.can_ext_scan;
+
+       return 0;
+}
+
+/*
+ * This function unregisters the PCIE device.
+ *
+ * The PCIE IRQ is released, the function is disabled and driver
+ * data is set to null.
+ */
+static void mwifiex_unregister_dev(struct mwifiex_adapter *adapter)
+{
+       struct pcie_service_card *card = adapter->card;
+       const struct mwifiex_pcie_card_reg *reg;
+
+       if (card) {
+               mwifiex_dbg(adapter, INFO,
+                           "%s(): calling free_irq()\n", __func__);
+               free_irq(card->dev->irq, card->dev);
+
+               reg = card->pcie.reg;
+               if (reg->sleep_cookie)
+                       mwifiex_pcie_delete_sleep_cookie_buf(adapter);
+
+               mwifiex_pcie_delete_cmdrsp_buf(adapter);
+               mwifiex_pcie_delete_evtbd_ring(adapter);
+               mwifiex_pcie_delete_rxbd_ring(adapter);
+               mwifiex_pcie_delete_txbd_ring(adapter);
+               card->cmdrsp_buf = NULL;
+       }
+}
+
+static struct mwifiex_if_ops pcie_ops = {
+       .init_if =                      mwifiex_pcie_init,
+       .cleanup_if =                   mwifiex_pcie_cleanup,
+       .check_fw_status =              mwifiex_check_fw_status,
+       .prog_fw =                      mwifiex_prog_fw_w_helper,
+       .register_dev =                 mwifiex_register_dev,
+       .unregister_dev =               mwifiex_unregister_dev,
+       .enable_int =                   mwifiex_pcie_enable_host_int,
+       .process_int_status =           mwifiex_process_int_status,
+       .host_to_card =                 mwifiex_pcie_host_to_card,
+       .wakeup =                       mwifiex_pm_wakeup_card,
+       .wakeup_complete =              mwifiex_pm_wakeup_card_complete,
+
+       /* PCIE specific */
+       .cmdrsp_complete =              mwifiex_pcie_cmdrsp_complete,
+       .event_complete =               mwifiex_pcie_event_complete,
+       .update_mp_end_port =           NULL,
+       .cleanup_mpa_buf =              NULL,
+       .init_fw_port =                 mwifiex_pcie_init_fw_port,
+       .clean_pcie_ring =              mwifiex_clean_pcie_ring_buf,
+       .device_dump =                  mwifiex_pcie_device_dump,
+};
+
+/*
+ * This function initializes the PCIE driver module.
+ *
+ * This initiates the semaphore and registers the device with
+ * PCIE bus.
+ */
+static int mwifiex_pcie_init_module(void)
+{
+       int ret;
+
+       pr_debug("Marvell PCIe Driver\n");
+
+       sema_init(&add_remove_card_sem, 1);
+
+       /* Clear the flag in case user removes the card. */
+       user_rmmod = 0;
+
+       ret = pci_register_driver(&mwifiex_pcie);
+       if (ret)
+               pr_err("Driver register failed!\n");
+       else
+               pr_debug("info: Driver registered successfully!\n");
+
+       return ret;
+}
+
+/*
+ * This function cleans up the PCIE driver.
+ *
+ * The following major steps are followed for cleanup -
+ *      - Resume the device if its suspended
+ *      - Disconnect the device if connected
+ *      - Shutdown the firmware
+ *      - Unregister the device from PCIE bus.
+ */
+static void mwifiex_pcie_cleanup_module(void)
+{
+       if (!down_interruptible(&add_remove_card_sem))
+               up(&add_remove_card_sem);
+
+       /* Set the flag as user is removing this module. */
+       user_rmmod = 1;
+
+       cancel_work_sync(&pcie_work);
+       pci_unregister_driver(&mwifiex_pcie);
+}
+
+module_init(mwifiex_pcie_init_module);
+module_exit(mwifiex_pcie_cleanup_module);
+
+MODULE_AUTHOR("Marvell International Ltd.");
+MODULE_DESCRIPTION("Marvell WiFi-Ex PCI-Express Driver version " PCIE_VERSION);
+MODULE_VERSION(PCIE_VERSION);
+MODULE_LICENSE("GPL v2");
+MODULE_FIRMWARE(PCIE8766_DEFAULT_FW_NAME);
+MODULE_FIRMWARE(PCIE8897_DEFAULT_FW_NAME);
+MODULE_FIRMWARE(PCIE8997_DEFAULT_FW_NAME);
diff --git a/drivers/net/wireless/marvell/mwifiex/pcie.h b/drivers/net/wireless/marvell/mwifiex/pcie.h
new file mode 100644 (file)
index 0000000..48e549c
--- /dev/null
@@ -0,0 +1,382 @@
+/* @file mwifiex_pcie.h
+ *
+ * @brief This file contains definitions for PCI-E interface.
+ * driver.
+ *
+ * Copyright (C) 2011-2014, Marvell International Ltd.
+ *
+ * This software file (the "File") is distributed by Marvell International
+ * Ltd. under the terms of the GNU General Public License Version 2, June 1991
+ * (the "License").  You may use, redistribute and/or modify this File in
+ * accordance with the terms and conditions of the License, a copy of which
+ * is available by writing to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the
+ * worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
+ *
+ * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
+ * ARE EXPRESSLY DISCLAIMED.  The License provides additional details about
+ * this warranty disclaimer.
+ */
+
+#ifndef        _MWIFIEX_PCIE_H
+#define        _MWIFIEX_PCIE_H
+
+#include    <linux/pci.h>
+#include    <linux/pcieport_if.h>
+#include    <linux/interrupt.h>
+
+#include    "main.h"
+
+#define PCIE8766_DEFAULT_FW_NAME "mrvl/pcie8766_uapsta.bin"
+#define PCIE8897_DEFAULT_FW_NAME "mrvl/pcie8897_uapsta.bin"
+#define PCIE8997_DEFAULT_FW_NAME "mrvl/pcie8997_uapsta.bin"
+
+#define PCIE_VENDOR_ID_MARVELL              (0x11ab)
+#define PCIE_DEVICE_ID_MARVELL_88W8766P                (0x2b30)
+#define PCIE_DEVICE_ID_MARVELL_88W8897         (0x2b38)
+#define PCIE_DEVICE_ID_MARVELL_88W8997         (0x2b42)
+
+/* Constants for Buffer Descriptor (BD) rings */
+#define MWIFIEX_MAX_TXRX_BD                    0x20
+#define MWIFIEX_TXBD_MASK                      0x3F
+#define MWIFIEX_RXBD_MASK                      0x3F
+
+#define MWIFIEX_MAX_EVT_BD                     0x08
+#define MWIFIEX_EVTBD_MASK                     0x0f
+
+/* PCIE INTERNAL REGISTERS */
+#define PCIE_SCRATCH_0_REG                             0xC10
+#define PCIE_SCRATCH_1_REG                             0xC14
+#define PCIE_CPU_INT_EVENT                             0xC18
+#define PCIE_CPU_INT_STATUS                            0xC1C
+#define PCIE_HOST_INT_STATUS                           0xC30
+#define PCIE_HOST_INT_MASK                             0xC34
+#define PCIE_HOST_INT_STATUS_MASK                      0xC3C
+#define PCIE_SCRATCH_2_REG                             0xC40
+#define PCIE_SCRATCH_3_REG                             0xC44
+#define PCIE_SCRATCH_4_REG                             0xCD0
+#define PCIE_SCRATCH_5_REG                             0xCD4
+#define PCIE_SCRATCH_6_REG                             0xCD8
+#define PCIE_SCRATCH_7_REG                             0xCDC
+#define PCIE_SCRATCH_8_REG                             0xCE0
+#define PCIE_SCRATCH_9_REG                             0xCE4
+#define PCIE_SCRATCH_10_REG                            0xCE8
+#define PCIE_SCRATCH_11_REG                            0xCEC
+#define PCIE_SCRATCH_12_REG                            0xCF0
+#define PCIE_RD_DATA_PTR_Q0_Q1                          0xC08C
+#define PCIE_WR_DATA_PTR_Q0_Q1                          0xC05C
+
+#define CPU_INTR_DNLD_RDY                              BIT(0)
+#define CPU_INTR_DOOR_BELL                             BIT(1)
+#define CPU_INTR_SLEEP_CFM_DONE                        BIT(2)
+#define CPU_INTR_RESET                                 BIT(3)
+#define CPU_INTR_EVENT_DONE                            BIT(5)
+
+#define HOST_INTR_DNLD_DONE                            BIT(0)
+#define HOST_INTR_UPLD_RDY                             BIT(1)
+#define HOST_INTR_CMD_DONE                             BIT(2)
+#define HOST_INTR_EVENT_RDY                            BIT(3)
+#define HOST_INTR_MASK                                 (HOST_INTR_DNLD_DONE | \
+                                                        HOST_INTR_UPLD_RDY  | \
+                                                        HOST_INTR_CMD_DONE  | \
+                                                        HOST_INTR_EVENT_RDY)
+
+#define MWIFIEX_BD_FLAG_ROLLOVER_IND                   BIT(7)
+#define MWIFIEX_BD_FLAG_FIRST_DESC                     BIT(0)
+#define MWIFIEX_BD_FLAG_LAST_DESC                      BIT(1)
+#define MWIFIEX_BD_FLAG_SOP                            BIT(0)
+#define MWIFIEX_BD_FLAG_EOP                            BIT(1)
+#define MWIFIEX_BD_FLAG_XS_SOP                         BIT(2)
+#define MWIFIEX_BD_FLAG_XS_EOP                         BIT(3)
+#define MWIFIEX_BD_FLAG_EVT_ROLLOVER_IND               BIT(7)
+#define MWIFIEX_BD_FLAG_RX_ROLLOVER_IND                        BIT(10)
+#define MWIFIEX_BD_FLAG_TX_START_PTR                   BIT(16)
+#define MWIFIEX_BD_FLAG_TX_ROLLOVER_IND                        BIT(26)
+
+/* Max retry number of command write */
+#define MAX_WRITE_IOMEM_RETRY                          2
+/* Define PCIE block size for firmware download */
+#define MWIFIEX_PCIE_BLOCK_SIZE_FW_DNLD                256
+/* FW awake cookie after FW ready */
+#define FW_AWAKE_COOKIE                                                (0xAA55AA55)
+#define MWIFIEX_DEF_SLEEP_COOKIE                       0xBEEFBEEF
+#define MWIFIEX_MAX_DELAY_COUNT                                5
+
+struct mwifiex_pcie_card_reg {
+       u16 cmd_addr_lo;
+       u16 cmd_addr_hi;
+       u16 fw_status;
+       u16 cmd_size;
+       u16 cmdrsp_addr_lo;
+       u16 cmdrsp_addr_hi;
+       u16 tx_rdptr;
+       u16 tx_wrptr;
+       u16 rx_rdptr;
+       u16 rx_wrptr;
+       u16 evt_rdptr;
+       u16 evt_wrptr;
+       u16 drv_rdy;
+       u16 tx_start_ptr;
+       u32 tx_mask;
+       u32 tx_wrap_mask;
+       u32 rx_mask;
+       u32 rx_wrap_mask;
+       u32 tx_rollover_ind;
+       u32 rx_rollover_ind;
+       u32 evt_rollover_ind;
+       u8 ring_flag_sop;
+       u8 ring_flag_eop;
+       u8 ring_flag_xs_sop;
+       u8 ring_flag_xs_eop;
+       u32 ring_tx_start_ptr;
+       u8 pfu_enabled;
+       u8 sleep_cookie;
+       u16 fw_dump_ctrl;
+       u16 fw_dump_start;
+       u16 fw_dump_end;
+};
+
+static const struct mwifiex_pcie_card_reg mwifiex_reg_8766 = {
+       .cmd_addr_lo = PCIE_SCRATCH_0_REG,
+       .cmd_addr_hi = PCIE_SCRATCH_1_REG,
+       .cmd_size = PCIE_SCRATCH_2_REG,
+       .fw_status = PCIE_SCRATCH_3_REG,
+       .cmdrsp_addr_lo = PCIE_SCRATCH_4_REG,
+       .cmdrsp_addr_hi = PCIE_SCRATCH_5_REG,
+       .tx_rdptr = PCIE_SCRATCH_6_REG,
+       .tx_wrptr = PCIE_SCRATCH_7_REG,
+       .rx_rdptr = PCIE_SCRATCH_8_REG,
+       .rx_wrptr = PCIE_SCRATCH_9_REG,
+       .evt_rdptr = PCIE_SCRATCH_10_REG,
+       .evt_wrptr = PCIE_SCRATCH_11_REG,
+       .drv_rdy = PCIE_SCRATCH_12_REG,
+       .tx_start_ptr = 0,
+       .tx_mask = MWIFIEX_TXBD_MASK,
+       .tx_wrap_mask = 0,
+       .rx_mask = MWIFIEX_RXBD_MASK,
+       .rx_wrap_mask = 0,
+       .tx_rollover_ind = MWIFIEX_BD_FLAG_ROLLOVER_IND,
+       .rx_rollover_ind = MWIFIEX_BD_FLAG_ROLLOVER_IND,
+       .evt_rollover_ind = MWIFIEX_BD_FLAG_ROLLOVER_IND,
+       .ring_flag_sop = 0,
+       .ring_flag_eop = 0,
+       .ring_flag_xs_sop = 0,
+       .ring_flag_xs_eop = 0,
+       .ring_tx_start_ptr = 0,
+       .pfu_enabled = 0,
+       .sleep_cookie = 1,
+};
+
+static const struct mwifiex_pcie_card_reg mwifiex_reg_8897 = {
+       .cmd_addr_lo = PCIE_SCRATCH_0_REG,
+       .cmd_addr_hi = PCIE_SCRATCH_1_REG,
+       .cmd_size = PCIE_SCRATCH_2_REG,
+       .fw_status = PCIE_SCRATCH_3_REG,
+       .cmdrsp_addr_lo = PCIE_SCRATCH_4_REG,
+       .cmdrsp_addr_hi = PCIE_SCRATCH_5_REG,
+       .tx_rdptr = PCIE_RD_DATA_PTR_Q0_Q1,
+       .tx_wrptr = PCIE_WR_DATA_PTR_Q0_Q1,
+       .rx_rdptr = PCIE_WR_DATA_PTR_Q0_Q1,
+       .rx_wrptr = PCIE_RD_DATA_PTR_Q0_Q1,
+       .evt_rdptr = PCIE_SCRATCH_10_REG,
+       .evt_wrptr = PCIE_SCRATCH_11_REG,
+       .drv_rdy = PCIE_SCRATCH_12_REG,
+       .tx_start_ptr = 16,
+       .tx_mask = 0x03FF0000,
+       .tx_wrap_mask = 0x07FF0000,
+       .rx_mask = 0x000003FF,
+       .rx_wrap_mask = 0x000007FF,
+       .tx_rollover_ind = MWIFIEX_BD_FLAG_TX_ROLLOVER_IND,
+       .rx_rollover_ind = MWIFIEX_BD_FLAG_RX_ROLLOVER_IND,
+       .evt_rollover_ind = MWIFIEX_BD_FLAG_EVT_ROLLOVER_IND,
+       .ring_flag_sop = MWIFIEX_BD_FLAG_SOP,
+       .ring_flag_eop = MWIFIEX_BD_FLAG_EOP,
+       .ring_flag_xs_sop = MWIFIEX_BD_FLAG_XS_SOP,
+       .ring_flag_xs_eop = MWIFIEX_BD_FLAG_XS_EOP,
+       .ring_tx_start_ptr = MWIFIEX_BD_FLAG_TX_START_PTR,
+       .pfu_enabled = 1,
+       .sleep_cookie = 0,
+       .fw_dump_ctrl = 0xcf4,
+       .fw_dump_start = 0xcf8,
+       .fw_dump_end = 0xcff,
+};
+
+static const struct mwifiex_pcie_card_reg mwifiex_reg_8997 = {
+       .cmd_addr_lo = PCIE_SCRATCH_0_REG,
+       .cmd_addr_hi = PCIE_SCRATCH_1_REG,
+       .cmd_size = PCIE_SCRATCH_2_REG,
+       .fw_status = PCIE_SCRATCH_3_REG,
+       .cmdrsp_addr_lo = PCIE_SCRATCH_4_REG,
+       .cmdrsp_addr_hi = PCIE_SCRATCH_5_REG,
+       .tx_rdptr = 0xC1A4,
+       .tx_wrptr = 0xC1A8,
+       .rx_rdptr = 0xC1A8,
+       .rx_wrptr = 0xC1A4,
+       .evt_rdptr = PCIE_SCRATCH_10_REG,
+       .evt_wrptr = PCIE_SCRATCH_11_REG,
+       .drv_rdy = PCIE_SCRATCH_12_REG,
+       .tx_start_ptr = 16,
+       .tx_mask = 0x0FFF0000,
+       .tx_wrap_mask = 0x01FF0000,
+       .rx_mask = 0x00000FFF,
+       .rx_wrap_mask = 0x000001FF,
+       .tx_rollover_ind = BIT(28),
+       .rx_rollover_ind = BIT(12),
+       .evt_rollover_ind = MWIFIEX_BD_FLAG_EVT_ROLLOVER_IND,
+       .ring_flag_sop = MWIFIEX_BD_FLAG_SOP,
+       .ring_flag_eop = MWIFIEX_BD_FLAG_EOP,
+       .ring_flag_xs_sop = MWIFIEX_BD_FLAG_XS_SOP,
+       .ring_flag_xs_eop = MWIFIEX_BD_FLAG_XS_EOP,
+       .ring_tx_start_ptr = MWIFIEX_BD_FLAG_TX_START_PTR,
+       .pfu_enabled = 1,
+       .sleep_cookie = 0,
+};
+
+struct mwifiex_pcie_device {
+       const char *firmware;
+       const struct mwifiex_pcie_card_reg *reg;
+       u16 blksz_fw_dl;
+       u16 tx_buf_size;
+       bool can_dump_fw;
+       bool can_ext_scan;
+};
+
+static const struct mwifiex_pcie_device mwifiex_pcie8766 = {
+       .firmware       = PCIE8766_DEFAULT_FW_NAME,
+       .reg            = &mwifiex_reg_8766,
+       .blksz_fw_dl = MWIFIEX_PCIE_BLOCK_SIZE_FW_DNLD,
+       .tx_buf_size = MWIFIEX_TX_DATA_BUF_SIZE_2K,
+       .can_dump_fw = false,
+       .can_ext_scan = true,
+};
+
+static const struct mwifiex_pcie_device mwifiex_pcie8897 = {
+       .firmware       = PCIE8897_DEFAULT_FW_NAME,
+       .reg            = &mwifiex_reg_8897,
+       .blksz_fw_dl = MWIFIEX_PCIE_BLOCK_SIZE_FW_DNLD,
+       .tx_buf_size = MWIFIEX_TX_DATA_BUF_SIZE_4K,
+       .can_dump_fw = true,
+       .can_ext_scan = true,
+};
+
+static const struct mwifiex_pcie_device mwifiex_pcie8997 = {
+       .firmware       = PCIE8997_DEFAULT_FW_NAME,
+       .reg            = &mwifiex_reg_8997,
+       .blksz_fw_dl = MWIFIEX_PCIE_BLOCK_SIZE_FW_DNLD,
+       .tx_buf_size = MWIFIEX_TX_DATA_BUF_SIZE_4K,
+       .can_dump_fw = false,
+       .can_ext_scan = true,
+};
+
+struct mwifiex_evt_buf_desc {
+       u64 paddr;
+       u16 len;
+       u16 flags;
+} __packed;
+
+struct mwifiex_pcie_buf_desc {
+       u64 paddr;
+       u16 len;
+       u16 flags;
+} __packed;
+
+struct mwifiex_pfu_buf_desc {
+       u16 flags;
+       u16 offset;
+       u16 frag_len;
+       u16 len;
+       u64 paddr;
+       u32 reserved;
+} __packed;
+
+struct pcie_service_card {
+       struct pci_dev *dev;
+       struct mwifiex_adapter *adapter;
+       struct mwifiex_pcie_device pcie;
+
+       u8 txbd_flush;
+       u32 txbd_wrptr;
+       u32 txbd_rdptr;
+       u32 txbd_ring_size;
+       u8 *txbd_ring_vbase;
+       dma_addr_t txbd_ring_pbase;
+       void *txbd_ring[MWIFIEX_MAX_TXRX_BD];
+       struct sk_buff *tx_buf_list[MWIFIEX_MAX_TXRX_BD];
+
+       u32 rxbd_wrptr;
+       u32 rxbd_rdptr;
+       u32 rxbd_ring_size;
+       u8 *rxbd_ring_vbase;
+       dma_addr_t rxbd_ring_pbase;
+       void *rxbd_ring[MWIFIEX_MAX_TXRX_BD];
+       struct sk_buff *rx_buf_list[MWIFIEX_MAX_TXRX_BD];
+
+       u32 evtbd_wrptr;
+       u32 evtbd_rdptr;
+       u32 evtbd_ring_size;
+       u8 *evtbd_ring_vbase;
+       dma_addr_t evtbd_ring_pbase;
+       void *evtbd_ring[MWIFIEX_MAX_EVT_BD];
+       struct sk_buff *evt_buf_list[MWIFIEX_MAX_EVT_BD];
+
+       struct sk_buff *cmd_buf;
+       struct sk_buff *cmdrsp_buf;
+       u8 *sleep_cookie_vbase;
+       dma_addr_t sleep_cookie_pbase;
+       void __iomem *pci_mmap;
+       void __iomem *pci_mmap1;
+};
+
+static inline int
+mwifiex_pcie_txbd_empty(struct pcie_service_card *card, u32 rdptr)
+{
+       const struct mwifiex_pcie_card_reg *reg = card->pcie.reg;
+
+       switch (card->dev->device) {
+       case PCIE_DEVICE_ID_MARVELL_88W8766P:
+               if (((card->txbd_wrptr & reg->tx_mask) ==
+                    (rdptr & reg->tx_mask)) &&
+                   ((card->txbd_wrptr & reg->tx_rollover_ind) !=
+                    (rdptr & reg->tx_rollover_ind)))
+                       return 1;
+               break;
+       case PCIE_DEVICE_ID_MARVELL_88W8897:
+               if (((card->txbd_wrptr & reg->tx_mask) ==
+                    (rdptr & reg->tx_mask)) &&
+                   ((card->txbd_wrptr & reg->tx_rollover_ind) ==
+                       (rdptr & reg->tx_rollover_ind)))
+                       return 1;
+               break;
+       }
+
+       return 0;
+}
+
+static inline int
+mwifiex_pcie_txbd_not_full(struct pcie_service_card *card)
+{
+       const struct mwifiex_pcie_card_reg *reg = card->pcie.reg;
+
+       switch (card->dev->device) {
+       case PCIE_DEVICE_ID_MARVELL_88W8766P:
+               if (((card->txbd_wrptr & reg->tx_mask) !=
+                    (card->txbd_rdptr & reg->tx_mask)) ||
+                   ((card->txbd_wrptr & reg->tx_rollover_ind) !=
+                    (card->txbd_rdptr & reg->tx_rollover_ind)))
+                       return 1;
+               break;
+       case PCIE_DEVICE_ID_MARVELL_88W8897:
+       case PCIE_DEVICE_ID_MARVELL_88W8997:
+               if (((card->txbd_wrptr & reg->tx_mask) !=
+                    (card->txbd_rdptr & reg->tx_mask)) ||
+                   ((card->txbd_wrptr & reg->tx_rollover_ind) ==
+                    (card->txbd_rdptr & reg->tx_rollover_ind)))
+                       return 1;
+               break;
+       }
+
+       return 0;
+}
+
+#endif /* _MWIFIEX_PCIE_H */
diff --git a/drivers/net/wireless/marvell/mwifiex/scan.c b/drivers/net/wireless/marvell/mwifiex/scan.c
new file mode 100644 (file)
index 0000000..c20017c
--- /dev/null
@@ -0,0 +1,2639 @@
+/*
+ * Marvell Wireless LAN device driver: scan ioctl and command handling
+ *
+ * Copyright (C) 2011-2014, Marvell International Ltd.
+ *
+ * This software file (the "File") is distributed by Marvell International
+ * Ltd. under the terms of the GNU General Public License Version 2, June 1991
+ * (the "License").  You may use, redistribute and/or modify this File in
+ * accordance with the terms and conditions of the License, a copy of which
+ * is available by writing to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the
+ * worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
+ *
+ * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
+ * ARE EXPRESSLY DISCLAIMED.  The License provides additional details about
+ * this warranty disclaimer.
+ */
+
+#include "decl.h"
+#include "ioctl.h"
+#include "util.h"
+#include "fw.h"
+#include "main.h"
+#include "11n.h"
+#include "cfg80211.h"
+
+/* The maximum number of channels the firmware can scan per command */
+#define MWIFIEX_MAX_CHANNELS_PER_SPECIFIC_SCAN   14
+
+#define MWIFIEX_DEF_CHANNELS_PER_SCAN_CMD      4
+
+/* Memory needed to store a max sized Channel List TLV for a firmware scan */
+#define CHAN_TLV_MAX_SIZE  (sizeof(struct mwifiex_ie_types_header)         \
+                               + (MWIFIEX_MAX_CHANNELS_PER_SPECIFIC_SCAN     \
+                               *sizeof(struct mwifiex_chan_scan_param_set)))
+
+/* Memory needed to store supported rate */
+#define RATE_TLV_MAX_SIZE   (sizeof(struct mwifiex_ie_types_rates_param_set) \
+                               + HOSTCMD_SUPPORTED_RATES)
+
+/* Memory needed to store a max number/size WildCard SSID TLV for a firmware
+       scan */
+#define WILDCARD_SSID_TLV_MAX_SIZE  \
+       (MWIFIEX_MAX_SSID_LIST_LENGTH *                                 \
+               (sizeof(struct mwifiex_ie_types_wildcard_ssid_params)   \
+                       + IEEE80211_MAX_SSID_LEN))
+
+/* Maximum memory needed for a mwifiex_scan_cmd_config with all TLVs at max */
+#define MAX_SCAN_CFG_ALLOC (sizeof(struct mwifiex_scan_cmd_config)        \
+                               + sizeof(struct mwifiex_ie_types_num_probes)   \
+                               + sizeof(struct mwifiex_ie_types_htcap)       \
+                               + CHAN_TLV_MAX_SIZE                 \
+                               + RATE_TLV_MAX_SIZE                 \
+                               + WILDCARD_SSID_TLV_MAX_SIZE)
+
+
+union mwifiex_scan_cmd_config_tlv {
+       /* Scan configuration (variable length) */
+       struct mwifiex_scan_cmd_config config;
+       /* Max allocated block */
+       u8 config_alloc_buf[MAX_SCAN_CFG_ALLOC];
+};
+
+enum cipher_suite {
+       CIPHER_SUITE_TKIP,
+       CIPHER_SUITE_CCMP,
+       CIPHER_SUITE_MAX
+};
+static u8 mwifiex_wpa_oui[CIPHER_SUITE_MAX][4] = {
+       { 0x00, 0x50, 0xf2, 0x02 },     /* TKIP */
+       { 0x00, 0x50, 0xf2, 0x04 },     /* AES  */
+};
+static u8 mwifiex_rsn_oui[CIPHER_SUITE_MAX][4] = {
+       { 0x00, 0x0f, 0xac, 0x02 },     /* TKIP */
+       { 0x00, 0x0f, 0xac, 0x04 },     /* AES  */
+};
+
+/*
+ * This function parses a given IE for a given OUI.
+ *
+ * This is used to parse a WPA/RSN IE to find if it has
+ * a given oui in PTK.
+ */
+static u8
+mwifiex_search_oui_in_ie(struct ie_body *iebody, u8 *oui)
+{
+       u8 count;
+
+       count = iebody->ptk_cnt[0];
+
+       /* There could be multiple OUIs for PTK hence
+          1) Take the length.
+          2) Check all the OUIs for AES.
+          3) If one of them is AES then pass success. */
+       while (count) {
+               if (!memcmp(iebody->ptk_body, oui, sizeof(iebody->ptk_body)))
+                       return MWIFIEX_OUI_PRESENT;
+
+               --count;
+               if (count)
+                       iebody = (struct ie_body *) ((u8 *) iebody +
+                                               sizeof(iebody->ptk_body));
+       }
+
+       pr_debug("info: %s: OUI is not found in PTK\n", __func__);
+       return MWIFIEX_OUI_NOT_PRESENT;
+}
+
+/*
+ * This function checks if a given OUI is present in a RSN IE.
+ *
+ * The function first checks if a RSN IE is present or not in the
+ * BSS descriptor. It tries to locate the OUI only if such an IE is
+ * present.
+ */
+static u8
+mwifiex_is_rsn_oui_present(struct mwifiex_bssdescriptor *bss_desc, u32 cipher)
+{
+       u8 *oui;
+       struct ie_body *iebody;
+       u8 ret = MWIFIEX_OUI_NOT_PRESENT;
+
+       if (((bss_desc->bcn_rsn_ie) && ((*(bss_desc->bcn_rsn_ie)).
+                                       ieee_hdr.element_id == WLAN_EID_RSN))) {
+               iebody = (struct ie_body *)
+                        (((u8 *) bss_desc->bcn_rsn_ie->data) +
+                         RSN_GTK_OUI_OFFSET);
+               oui = &mwifiex_rsn_oui[cipher][0];
+               ret = mwifiex_search_oui_in_ie(iebody, oui);
+               if (ret)
+                       return ret;
+       }
+       return ret;
+}
+
+/*
+ * This function checks if a given OUI is present in a WPA IE.
+ *
+ * The function first checks if a WPA IE is present or not in the
+ * BSS descriptor. It tries to locate the OUI only if such an IE is
+ * present.
+ */
+static u8
+mwifiex_is_wpa_oui_present(struct mwifiex_bssdescriptor *bss_desc, u32 cipher)
+{
+       u8 *oui;
+       struct ie_body *iebody;
+       u8 ret = MWIFIEX_OUI_NOT_PRESENT;
+
+       if (((bss_desc->bcn_wpa_ie) &&
+            ((*(bss_desc->bcn_wpa_ie)).vend_hdr.element_id ==
+             WLAN_EID_VENDOR_SPECIFIC))) {
+               iebody = (struct ie_body *) bss_desc->bcn_wpa_ie->data;
+               oui = &mwifiex_wpa_oui[cipher][0];
+               ret = mwifiex_search_oui_in_ie(iebody, oui);
+               if (ret)
+                       return ret;
+       }
+       return ret;
+}
+
+/*
+ * This function compares two SSIDs and checks if they match.
+ */
+s32
+mwifiex_ssid_cmp(struct cfg80211_ssid *ssid1, struct cfg80211_ssid *ssid2)
+{
+       if (!ssid1 || !ssid2 || (ssid1->ssid_len != ssid2->ssid_len))
+               return -1;
+       return memcmp(ssid1->ssid, ssid2->ssid, ssid1->ssid_len);
+}
+
+/*
+ * This function checks if wapi is enabled in driver and scanned network is
+ * compatible with it.
+ */
+static bool
+mwifiex_is_bss_wapi(struct mwifiex_private *priv,
+                   struct mwifiex_bssdescriptor *bss_desc)
+{
+       if (priv->sec_info.wapi_enabled &&
+           (bss_desc->bcn_wapi_ie &&
+            ((*(bss_desc->bcn_wapi_ie)).ieee_hdr.element_id ==
+                       WLAN_EID_BSS_AC_ACCESS_DELAY))) {
+               return true;
+       }
+       return false;
+}
+
+/*
+ * This function checks if driver is configured with no security mode and
+ * scanned network is compatible with it.
+ */
+static bool
+mwifiex_is_bss_no_sec(struct mwifiex_private *priv,
+                     struct mwifiex_bssdescriptor *bss_desc)
+{
+       if (!priv->sec_info.wep_enabled && !priv->sec_info.wpa_enabled &&
+           !priv->sec_info.wpa2_enabled && ((!bss_desc->bcn_wpa_ie) ||
+               ((*(bss_desc->bcn_wpa_ie)).vend_hdr.element_id !=
+                WLAN_EID_VENDOR_SPECIFIC)) &&
+           ((!bss_desc->bcn_rsn_ie) ||
+               ((*(bss_desc->bcn_rsn_ie)).ieee_hdr.element_id !=
+                WLAN_EID_RSN)) &&
+           !priv->sec_info.encryption_mode && !bss_desc->privacy) {
+               return true;
+       }
+       return false;
+}
+
+/*
+ * This function checks if static WEP is enabled in driver and scanned network
+ * is compatible with it.
+ */
+static bool
+mwifiex_is_bss_static_wep(struct mwifiex_private *priv,
+                         struct mwifiex_bssdescriptor *bss_desc)
+{
+       if (priv->sec_info.wep_enabled && !priv->sec_info.wpa_enabled &&
+           !priv->sec_info.wpa2_enabled && bss_desc->privacy) {
+               return true;
+       }
+       return false;
+}
+
+/*
+ * This function checks if wpa is enabled in driver and scanned network is
+ * compatible with it.
+ */
+static bool
+mwifiex_is_bss_wpa(struct mwifiex_private *priv,
+                  struct mwifiex_bssdescriptor *bss_desc)
+{
+       if (!priv->sec_info.wep_enabled && priv->sec_info.wpa_enabled &&
+           !priv->sec_info.wpa2_enabled && ((bss_desc->bcn_wpa_ie) &&
+           ((*(bss_desc->bcn_wpa_ie)).
+            vend_hdr.element_id == WLAN_EID_VENDOR_SPECIFIC))
+          /*
+           * Privacy bit may NOT be set in some APs like
+           * LinkSys WRT54G && bss_desc->privacy
+           */
+        ) {
+               mwifiex_dbg(priv->adapter, INFO,
+                           "info: %s: WPA:\t"
+                           "wpa_ie=%#x wpa2_ie=%#x WEP=%s WPA=%s WPA2=%s\t"
+                           "EncMode=%#x privacy=%#x\n", __func__,
+                           (bss_desc->bcn_wpa_ie) ?
+                           (*bss_desc->bcn_wpa_ie).
+                           vend_hdr.element_id : 0,
+                           (bss_desc->bcn_rsn_ie) ?
+                           (*bss_desc->bcn_rsn_ie).
+                           ieee_hdr.element_id : 0,
+                           (priv->sec_info.wep_enabled) ? "e" : "d",
+                           (priv->sec_info.wpa_enabled) ? "e" : "d",
+                           (priv->sec_info.wpa2_enabled) ? "e" : "d",
+                           priv->sec_info.encryption_mode,
+                           bss_desc->privacy);
+               return true;
+       }
+       return false;
+}
+
+/*
+ * This function checks if wpa2 is enabled in driver and scanned network is
+ * compatible with it.
+ */
+static bool
+mwifiex_is_bss_wpa2(struct mwifiex_private *priv,
+                   struct mwifiex_bssdescriptor *bss_desc)
+{
+       if (!priv->sec_info.wep_enabled &&
+           !priv->sec_info.wpa_enabled &&
+           priv->sec_info.wpa2_enabled &&
+           ((bss_desc->bcn_rsn_ie) &&
+            ((*(bss_desc->bcn_rsn_ie)).ieee_hdr.element_id == WLAN_EID_RSN))) {
+               /*
+                * Privacy bit may NOT be set in some APs like
+                * LinkSys WRT54G && bss_desc->privacy
+                */
+               mwifiex_dbg(priv->adapter, INFO,
+                           "info: %s: WPA2:\t"
+                           "wpa_ie=%#x wpa2_ie=%#x WEP=%s WPA=%s WPA2=%s\t"
+                           "EncMode=%#x privacy=%#x\n", __func__,
+                           (bss_desc->bcn_wpa_ie) ?
+                           (*bss_desc->bcn_wpa_ie).
+                           vend_hdr.element_id : 0,
+                           (bss_desc->bcn_rsn_ie) ?
+                           (*bss_desc->bcn_rsn_ie).
+                           ieee_hdr.element_id : 0,
+                           (priv->sec_info.wep_enabled) ? "e" : "d",
+                           (priv->sec_info.wpa_enabled) ? "e" : "d",
+                           (priv->sec_info.wpa2_enabled) ? "e" : "d",
+                           priv->sec_info.encryption_mode,
+                           bss_desc->privacy);
+               return true;
+       }
+       return false;
+}
+
+/*
+ * This function checks if adhoc AES is enabled in driver and scanned network is
+ * compatible with it.
+ */
+static bool
+mwifiex_is_bss_adhoc_aes(struct mwifiex_private *priv,
+                        struct mwifiex_bssdescriptor *bss_desc)
+{
+       if (!priv->sec_info.wep_enabled && !priv->sec_info.wpa_enabled &&
+           !priv->sec_info.wpa2_enabled &&
+           ((!bss_desc->bcn_wpa_ie) ||
+            ((*(bss_desc->bcn_wpa_ie)).
+             vend_hdr.element_id != WLAN_EID_VENDOR_SPECIFIC)) &&
+           ((!bss_desc->bcn_rsn_ie) ||
+            ((*(bss_desc->bcn_rsn_ie)).ieee_hdr.element_id != WLAN_EID_RSN)) &&
+           !priv->sec_info.encryption_mode && bss_desc->privacy) {
+               return true;
+       }
+       return false;
+}
+
+/*
+ * This function checks if dynamic WEP is enabled in driver and scanned network
+ * is compatible with it.
+ */
+static bool
+mwifiex_is_bss_dynamic_wep(struct mwifiex_private *priv,
+                          struct mwifiex_bssdescriptor *bss_desc)
+{
+       if (!priv->sec_info.wep_enabled && !priv->sec_info.wpa_enabled &&
+           !priv->sec_info.wpa2_enabled &&
+           ((!bss_desc->bcn_wpa_ie) ||
+            ((*(bss_desc->bcn_wpa_ie)).
+             vend_hdr.element_id != WLAN_EID_VENDOR_SPECIFIC)) &&
+           ((!bss_desc->bcn_rsn_ie) ||
+            ((*(bss_desc->bcn_rsn_ie)).ieee_hdr.element_id != WLAN_EID_RSN)) &&
+           priv->sec_info.encryption_mode && bss_desc->privacy) {
+               mwifiex_dbg(priv->adapter, INFO,
+                           "info: %s: dynamic\t"
+                           "WEP: wpa_ie=%#x wpa2_ie=%#x\t"
+                           "EncMode=%#x privacy=%#x\n",
+                           __func__,
+                           (bss_desc->bcn_wpa_ie) ?
+                           (*bss_desc->bcn_wpa_ie).
+                           vend_hdr.element_id : 0,
+                           (bss_desc->bcn_rsn_ie) ?
+                           (*bss_desc->bcn_rsn_ie).
+                           ieee_hdr.element_id : 0,
+                           priv->sec_info.encryption_mode,
+                           bss_desc->privacy);
+               return true;
+       }
+       return false;
+}
+
+/*
+ * This function checks if a scanned network is compatible with the driver
+ * settings.
+ *
+ *   WEP     WPA    WPA2   ad-hoc encrypt                  Network
+ * enabled enabled enabled  AES    mode   Privacy WPA WPA2 Compatible
+ *    0       0       0      0     NONE      0     0   0   yes No security
+ *    0       1       0      0      x        1x    1   x   yes WPA (disable
+ *                                                         HT if no AES)
+ *    0       0       1      0      x        1x    x   1   yes WPA2 (disable
+ *                                                         HT if no AES)
+ *    0       0       0      1     NONE      1     0   0   yes Ad-hoc AES
+ *    1       0       0      0     NONE      1     0   0   yes Static WEP
+ *                                                         (disable HT)
+ *    0       0       0      0    !=NONE     1     0   0   yes Dynamic WEP
+ *
+ * Compatibility is not matched while roaming, except for mode.
+ */
+static s32
+mwifiex_is_network_compatible(struct mwifiex_private *priv,
+                             struct mwifiex_bssdescriptor *bss_desc, u32 mode)
+{
+       struct mwifiex_adapter *adapter = priv->adapter;
+
+       bss_desc->disable_11n = false;
+
+       /* Don't check for compatibility if roaming */
+       if (priv->media_connected &&
+           (priv->bss_mode == NL80211_IFTYPE_STATION) &&
+           (bss_desc->bss_mode == NL80211_IFTYPE_STATION))
+               return 0;
+
+       if (priv->wps.session_enable) {
+               mwifiex_dbg(adapter, IOCTL,
+                           "info: return success directly in WPS period\n");
+               return 0;
+       }
+
+       if (bss_desc->chan_sw_ie_present) {
+               mwifiex_dbg(adapter, INFO,
+                           "Don't connect to AP with WLAN_EID_CHANNEL_SWITCH\n");
+               return -1;
+       }
+
+       if (mwifiex_is_bss_wapi(priv, bss_desc)) {
+               mwifiex_dbg(adapter, INFO,
+                           "info: return success for WAPI AP\n");
+               return 0;
+       }
+
+       if (bss_desc->bss_mode == mode) {
+               if (mwifiex_is_bss_no_sec(priv, bss_desc)) {
+                       /* No security */
+                       return 0;
+               } else if (mwifiex_is_bss_static_wep(priv, bss_desc)) {
+                       /* Static WEP enabled */
+                       mwifiex_dbg(adapter, INFO,
+                                   "info: Disable 11n in WEP mode.\n");
+                       bss_desc->disable_11n = true;
+                       return 0;
+               } else if (mwifiex_is_bss_wpa(priv, bss_desc)) {
+                       /* WPA enabled */
+                       if (((priv->adapter->config_bands & BAND_GN ||
+                             priv->adapter->config_bands & BAND_AN) &&
+                            bss_desc->bcn_ht_cap) &&
+                           !mwifiex_is_wpa_oui_present(bss_desc,
+                                                        CIPHER_SUITE_CCMP)) {
+
+                               if (mwifiex_is_wpa_oui_present
+                                               (bss_desc, CIPHER_SUITE_TKIP)) {
+                                       mwifiex_dbg(adapter, INFO,
+                                                   "info: Disable 11n if AES\t"
+                                                   "is not supported by AP\n");
+                                       bss_desc->disable_11n = true;
+                               } else {
+                                       return -1;
+                               }
+                       }
+                       return 0;
+               } else if (mwifiex_is_bss_wpa2(priv, bss_desc)) {
+                       /* WPA2 enabled */
+                       if (((priv->adapter->config_bands & BAND_GN ||
+                             priv->adapter->config_bands & BAND_AN) &&
+                            bss_desc->bcn_ht_cap) &&
+                           !mwifiex_is_rsn_oui_present(bss_desc,
+                                                       CIPHER_SUITE_CCMP)) {
+
+                               if (mwifiex_is_rsn_oui_present
+                                               (bss_desc, CIPHER_SUITE_TKIP)) {
+                                       mwifiex_dbg(adapter, INFO,
+                                                   "info: Disable 11n if AES\t"
+                                                   "is not supported by AP\n");
+                                       bss_desc->disable_11n = true;
+                               } else {
+                                       return -1;
+                               }
+                       }
+                       return 0;
+               } else if (mwifiex_is_bss_adhoc_aes(priv, bss_desc)) {
+                       /* Ad-hoc AES enabled */
+                       return 0;
+               } else if (mwifiex_is_bss_dynamic_wep(priv, bss_desc)) {
+                       /* Dynamic WEP enabled */
+                       return 0;
+               }
+
+               /* Security doesn't match */
+               mwifiex_dbg(adapter, ERROR,
+                           "info: %s: failed: wpa_ie=%#x wpa2_ie=%#x WEP=%s\t"
+                           "WPA=%s WPA2=%s EncMode=%#x privacy=%#x\n",
+                           __func__,
+                           (bss_desc->bcn_wpa_ie) ?
+                           (*bss_desc->bcn_wpa_ie).vend_hdr.element_id : 0,
+                           (bss_desc->bcn_rsn_ie) ?
+                           (*bss_desc->bcn_rsn_ie).ieee_hdr.element_id : 0,
+                           (priv->sec_info.wep_enabled) ? "e" : "d",
+                           (priv->sec_info.wpa_enabled) ? "e" : "d",
+                           (priv->sec_info.wpa2_enabled) ? "e" : "d",
+                           priv->sec_info.encryption_mode, bss_desc->privacy);
+               return -1;
+       }
+
+       /* Mode doesn't match */
+       return -1;
+}
+
+/*
+ * This function creates a channel list for the driver to scan, based
+ * on region/band information.
+ *
+ * This routine is used for any scan that is not provided with a
+ * specific channel list to scan.
+ */
+static int
+mwifiex_scan_create_channel_list(struct mwifiex_private *priv,
+                                const struct mwifiex_user_scan_cfg
+                                                       *user_scan_in,
+                                struct mwifiex_chan_scan_param_set
+                                                       *scan_chan_list,
+                                u8 filtered_scan)
+{
+       enum ieee80211_band band;
+       struct ieee80211_supported_band *sband;
+       struct ieee80211_channel *ch;
+       struct mwifiex_adapter *adapter = priv->adapter;
+       int chan_idx = 0, i;
+
+       for (band = 0; (band < IEEE80211_NUM_BANDS) ; band++) {
+
+               if (!priv->wdev.wiphy->bands[band])
+                       continue;
+
+               sband = priv->wdev.wiphy->bands[band];
+
+               for (i = 0; (i < sband->n_channels) ; i++) {
+                       ch = &sband->channels[i];
+                       if (ch->flags & IEEE80211_CHAN_DISABLED)
+                               continue;
+                       scan_chan_list[chan_idx].radio_type = band;
+
+                       if (user_scan_in &&
+                           user_scan_in->chan_list[0].scan_time)
+                               scan_chan_list[chan_idx].max_scan_time =
+                                       cpu_to_le16((u16) user_scan_in->
+                                       chan_list[0].scan_time);
+                       else if (ch->flags & IEEE80211_CHAN_NO_IR)
+                               scan_chan_list[chan_idx].max_scan_time =
+                                       cpu_to_le16(adapter->passive_scan_time);
+                       else
+                               scan_chan_list[chan_idx].max_scan_time =
+                                       cpu_to_le16(adapter->active_scan_time);
+
+                       if (ch->flags & IEEE80211_CHAN_NO_IR)
+                               scan_chan_list[chan_idx].chan_scan_mode_bitmap
+                                       |= (MWIFIEX_PASSIVE_SCAN |
+                                           MWIFIEX_HIDDEN_SSID_REPORT);
+                       else
+                               scan_chan_list[chan_idx].chan_scan_mode_bitmap
+                                       &= ~MWIFIEX_PASSIVE_SCAN;
+                       scan_chan_list[chan_idx].chan_number =
+                                                       (u32) ch->hw_value;
+                       if (filtered_scan) {
+                               scan_chan_list[chan_idx].max_scan_time =
+                               cpu_to_le16(adapter->specific_scan_time);
+                               scan_chan_list[chan_idx].chan_scan_mode_bitmap
+                                       |= MWIFIEX_DISABLE_CHAN_FILT;
+                       }
+                       chan_idx++;
+               }
+
+       }
+       return chan_idx;
+}
+
+/* This function appends rate TLV to scan config command. */
+static int
+mwifiex_append_rate_tlv(struct mwifiex_private *priv,
+                       struct mwifiex_scan_cmd_config *scan_cfg_out,
+                       u8 radio)
+{
+       struct mwifiex_ie_types_rates_param_set *rates_tlv;
+       u8 rates[MWIFIEX_SUPPORTED_RATES], *tlv_pos;
+       u32 rates_size;
+
+       memset(rates, 0, sizeof(rates));
+
+       tlv_pos = (u8 *)scan_cfg_out->tlv_buf + scan_cfg_out->tlv_buf_len;
+
+       if (priv->scan_request)
+               rates_size = mwifiex_get_rates_from_cfg80211(priv, rates,
+                                                            radio);
+       else
+               rates_size = mwifiex_get_supported_rates(priv, rates);
+
+       mwifiex_dbg(priv->adapter, CMD,
+                   "info: SCAN_CMD: Rates size = %d\n",
+               rates_size);
+       rates_tlv = (struct mwifiex_ie_types_rates_param_set *)tlv_pos;
+       rates_tlv->header.type = cpu_to_le16(WLAN_EID_SUPP_RATES);
+       rates_tlv->header.len = cpu_to_le16((u16) rates_size);
+       memcpy(rates_tlv->rates, rates, rates_size);
+       scan_cfg_out->tlv_buf_len += sizeof(rates_tlv->header) + rates_size;
+
+       return rates_size;
+}
+
+/*
+ * This function constructs and sends multiple scan config commands to
+ * the firmware.
+ *
+ * Previous routines in the code flow have created a scan command configuration
+ * with any requested TLVs.  This function splits the channel TLV into maximum
+ * channels supported per scan lists and sends the portion of the channel TLV,
+ * along with the other TLVs, to the firmware.
+ */
+static int
+mwifiex_scan_channel_list(struct mwifiex_private *priv,
+                         u32 max_chan_per_scan, u8 filtered_scan,
+                         struct mwifiex_scan_cmd_config *scan_cfg_out,
+                         struct mwifiex_ie_types_chan_list_param_set
+                         *chan_tlv_out,
+                         struct mwifiex_chan_scan_param_set *scan_chan_list)
+{
+       struct mwifiex_adapter *adapter = priv->adapter;
+       int ret = 0;
+       struct mwifiex_chan_scan_param_set *tmp_chan_list;
+       struct mwifiex_chan_scan_param_set *start_chan;
+       struct cmd_ctrl_node *cmd_node, *tmp_node;
+       unsigned long flags;
+       u32 tlv_idx, rates_size, cmd_no;
+       u32 total_scan_time;
+       u32 done_early;
+       u8 radio_type;
+
+       if (!scan_cfg_out || !chan_tlv_out || !scan_chan_list) {
+               mwifiex_dbg(priv->adapter, ERROR,
+                           "info: Scan: Null detect: %p, %p, %p\n",
+                           scan_cfg_out, chan_tlv_out, scan_chan_list);
+               return -1;
+       }
+
+       /* Check csa channel expiry before preparing scan list */
+       mwifiex_11h_get_csa_closed_channel(priv);
+
+       chan_tlv_out->header.type = cpu_to_le16(TLV_TYPE_CHANLIST);
+
+       /* Set the temp channel struct pointer to the start of the desired
+          list */
+       tmp_chan_list = scan_chan_list;
+
+       /* Loop through the desired channel list, sending a new firmware scan
+          commands for each max_chan_per_scan channels (or for 1,6,11
+          individually if configured accordingly) */
+       while (tmp_chan_list->chan_number) {
+
+               tlv_idx = 0;
+               total_scan_time = 0;
+               radio_type = 0;
+               chan_tlv_out->header.len = 0;
+               start_chan = tmp_chan_list;
+               done_early = false;
+
+               /*
+                * Construct the Channel TLV for the scan command.  Continue to
+                * insert channel TLVs until:
+                *   - the tlv_idx hits the maximum configured per scan command
+                *   - the next channel to insert is 0 (end of desired channel
+                *     list)
+                *   - done_early is set (controlling individual scanning of
+                *     1,6,11)
+                */
+               while (tlv_idx < max_chan_per_scan &&
+                      tmp_chan_list->chan_number && !done_early) {
+
+                       if (tmp_chan_list->chan_number == priv->csa_chan) {
+                               tmp_chan_list++;
+                               continue;
+                       }
+
+                       radio_type = tmp_chan_list->radio_type;
+                       mwifiex_dbg(priv->adapter, INFO,
+                                   "info: Scan: Chan(%3d), Radio(%d),\t"
+                                   "Mode(%d, %d), Dur(%d)\n",
+                                   tmp_chan_list->chan_number,
+                                   tmp_chan_list->radio_type,
+                                   tmp_chan_list->chan_scan_mode_bitmap
+                                   & MWIFIEX_PASSIVE_SCAN,
+                                   (tmp_chan_list->chan_scan_mode_bitmap
+                                   & MWIFIEX_DISABLE_CHAN_FILT) >> 1,
+                                   le16_to_cpu(tmp_chan_list->max_scan_time));
+
+                       /* Copy the current channel TLV to the command being
+                          prepared */
+                       memcpy(chan_tlv_out->chan_scan_param + tlv_idx,
+                              tmp_chan_list,
+                              sizeof(chan_tlv_out->chan_scan_param));
+
+                       /* Increment the TLV header length by the size
+                          appended */
+                       le16_add_cpu(&chan_tlv_out->header.len,
+                                    sizeof(chan_tlv_out->chan_scan_param));
+
+                       /*
+                        * The tlv buffer length is set to the number of bytes
+                        * of the between the channel tlv pointer and the start
+                        * of the tlv buffer.  This compensates for any TLVs
+                        * that were appended before the channel list.
+                        */
+                       scan_cfg_out->tlv_buf_len = (u32) ((u8 *) chan_tlv_out -
+                                                       scan_cfg_out->tlv_buf);
+
+                       /* Add the size of the channel tlv header and the data
+                          length */
+                       scan_cfg_out->tlv_buf_len +=
+                               (sizeof(chan_tlv_out->header)
+                                + le16_to_cpu(chan_tlv_out->header.len));
+
+                       /* Increment the index to the channel tlv we are
+                          constructing */
+                       tlv_idx++;
+
+                       /* Count the total scan time per command */
+                       total_scan_time +=
+                               le16_to_cpu(tmp_chan_list->max_scan_time);
+
+                       done_early = false;
+
+                       /* Stop the loop if the *current* channel is in the
+                          1,6,11 set and we are not filtering on a BSSID
+                          or SSID. */
+                       if (!filtered_scan &&
+                           (tmp_chan_list->chan_number == 1 ||
+                            tmp_chan_list->chan_number == 6 ||
+                            tmp_chan_list->chan_number == 11))
+                               done_early = true;
+
+                       /* Increment the tmp pointer to the next channel to
+                          be scanned */
+                       tmp_chan_list++;
+
+                       /* Stop the loop if the *next* channel is in the 1,6,11
+                          set.  This will cause it to be the only channel
+                          scanned on the next interation */
+                       if (!filtered_scan &&
+                           (tmp_chan_list->chan_number == 1 ||
+                            tmp_chan_list->chan_number == 6 ||
+                            tmp_chan_list->chan_number == 11))
+                               done_early = true;
+               }
+
+               /* The total scan time should be less than scan command timeout
+                  value */
+               if (total_scan_time > MWIFIEX_MAX_TOTAL_SCAN_TIME) {
+                       mwifiex_dbg(priv->adapter, ERROR,
+                                   "total scan time %dms\t"
+                                   "is over limit (%dms), scan skipped\n",
+                                   total_scan_time,
+                                   MWIFIEX_MAX_TOTAL_SCAN_TIME);
+                       ret = -1;
+                       break;
+               }
+
+               rates_size = mwifiex_append_rate_tlv(priv, scan_cfg_out,
+                                                    radio_type);
+
+               priv->adapter->scan_channels = start_chan;
+
+               /* Send the scan command to the firmware with the specified
+                  cfg */
+               if (priv->adapter->ext_scan)
+                       cmd_no = HostCmd_CMD_802_11_SCAN_EXT;
+               else
+                       cmd_no = HostCmd_CMD_802_11_SCAN;
+
+               ret = mwifiex_send_cmd(priv, cmd_no, HostCmd_ACT_GEN_SET,
+                                      0, scan_cfg_out, false);
+
+               /* rate IE is updated per scan command but same starting
+                * pointer is used each time so that rate IE from earlier
+                * scan_cfg_out->buf is overwritten with new one.
+                */
+               scan_cfg_out->tlv_buf_len -=
+                           sizeof(struct mwifiex_ie_types_header) + rates_size;
+
+               if (ret) {
+                       spin_lock_irqsave(&adapter->scan_pending_q_lock, flags);
+                       list_for_each_entry_safe(cmd_node, tmp_node,
+                                                &adapter->scan_pending_q,
+                                                list) {
+                               list_del(&cmd_node->list);
+                               cmd_node->wait_q_enabled = false;
+                               mwifiex_insert_cmd_to_free_q(adapter, cmd_node);
+                       }
+                       spin_unlock_irqrestore(&adapter->scan_pending_q_lock,
+                                              flags);
+                       break;
+               }
+       }
+
+       if (ret)
+               return -1;
+
+       return 0;
+}
+
+/*
+ * This function constructs a scan command configuration structure to use
+ * in scan commands.
+ *
+ * Application layer or other functions can invoke network scanning
+ * with a scan configuration supplied in a user scan configuration structure.
+ * This structure is used as the basis of one or many scan command configuration
+ * commands that are sent to the command processing module and eventually to the
+ * firmware.
+ *
+ * This function creates a scan command configuration structure  based on the
+ * following user supplied parameters (if present):
+ *      - SSID filter
+ *      - BSSID filter
+ *      - Number of Probes to be sent
+ *      - Channel list
+ *
+ * If the SSID or BSSID filter is not present, the filter is disabled/cleared.
+ * If the number of probes is not set, adapter default setting is used.
+ */
+static void
+mwifiex_config_scan(struct mwifiex_private *priv,
+                   const struct mwifiex_user_scan_cfg *user_scan_in,
+                   struct mwifiex_scan_cmd_config *scan_cfg_out,
+                   struct mwifiex_ie_types_chan_list_param_set **chan_list_out,
+                   struct mwifiex_chan_scan_param_set *scan_chan_list,
+                   u8 *max_chan_per_scan, u8 *filtered_scan,
+                   u8 *scan_current_only)
+{
+       struct mwifiex_adapter *adapter = priv->adapter;
+       struct mwifiex_ie_types_num_probes *num_probes_tlv;
+       struct mwifiex_ie_types_scan_chan_gap *chan_gap_tlv;
+       struct mwifiex_ie_types_wildcard_ssid_params *wildcard_ssid_tlv;
+       struct mwifiex_ie_types_bssid_list *bssid_tlv;
+       u8 *tlv_pos;
+       u32 num_probes;
+       u32 ssid_len;
+       u32 chan_idx;
+       u32 chan_num;
+       u32 scan_type;
+       u16 scan_dur;
+       u8 channel;
+       u8 radio_type;
+       int i;
+       u8 ssid_filter;
+       struct mwifiex_ie_types_htcap *ht_cap;
+       struct mwifiex_ie_types_bss_mode *bss_mode;
+
+       /* The tlv_buf_len is calculated for each scan command.  The TLVs added
+          in this routine will be preserved since the routine that sends the
+          command will append channelTLVs at *chan_list_out.  The difference
+          between the *chan_list_out and the tlv_buf start will be used to
+          calculate the size of anything we add in this routine. */
+       scan_cfg_out->tlv_buf_len = 0;
+
+       /* Running tlv pointer.  Assigned to chan_list_out at end of function
+          so later routines know where channels can be added to the command
+          buf */
+       tlv_pos = scan_cfg_out->tlv_buf;
+
+       /* Initialize the scan as un-filtered; the flag is later set to TRUE
+          below if a SSID or BSSID filter is sent in the command */
+       *filtered_scan = false;
+
+       /* Initialize the scan as not being only on the current channel.  If
+          the channel list is customized, only contains one channel, and is
+          the active channel, this is set true and data flow is not halted. */
+       *scan_current_only = false;
+
+       if (user_scan_in) {
+
+               /* Default the ssid_filter flag to TRUE, set false under
+                  certain wildcard conditions and qualified by the existence
+                  of an SSID list before marking the scan as filtered */
+               ssid_filter = true;
+
+               /* Set the BSS type scan filter, use Adapter setting if
+                  unset */
+               scan_cfg_out->bss_mode =
+                       (user_scan_in->bss_mode ? (u8) user_scan_in->
+                        bss_mode : (u8) adapter->scan_mode);
+
+               /* Set the number of probes to send, use Adapter setting
+                  if unset */
+               num_probes =
+                       (user_scan_in->num_probes ? user_scan_in->
+                        num_probes : adapter->scan_probes);
+
+               /*
+                * Set the BSSID filter to the incoming configuration,
+                * if non-zero.  If not set, it will remain disabled
+                * (all zeros).
+                */
+               memcpy(scan_cfg_out->specific_bssid,
+                      user_scan_in->specific_bssid,
+                      sizeof(scan_cfg_out->specific_bssid));
+
+               if (adapter->ext_scan &&
+                   !is_zero_ether_addr(scan_cfg_out->specific_bssid)) {
+                       bssid_tlv =
+                               (struct mwifiex_ie_types_bssid_list *)tlv_pos;
+                       bssid_tlv->header.type = cpu_to_le16(TLV_TYPE_BSSID);
+                       bssid_tlv->header.len = cpu_to_le16(ETH_ALEN);
+                       memcpy(bssid_tlv->bssid, user_scan_in->specific_bssid,
+                              ETH_ALEN);
+                       tlv_pos += sizeof(struct mwifiex_ie_types_bssid_list);
+               }
+
+               for (i = 0; i < user_scan_in->num_ssids; i++) {
+                       ssid_len = user_scan_in->ssid_list[i].ssid_len;
+
+                       wildcard_ssid_tlv =
+                               (struct mwifiex_ie_types_wildcard_ssid_params *)
+                               tlv_pos;
+                       wildcard_ssid_tlv->header.type =
+                               cpu_to_le16(TLV_TYPE_WILDCARDSSID);
+                       wildcard_ssid_tlv->header.len = cpu_to_le16(
+                               (u16) (ssid_len + sizeof(wildcard_ssid_tlv->
+                                                        max_ssid_length)));
+
+                       /*
+                        * max_ssid_length = 0 tells firmware to perform
+                        * specific scan for the SSID filled, whereas
+                        * max_ssid_length = IEEE80211_MAX_SSID_LEN is for
+                        * wildcard scan.
+                        */
+                       if (ssid_len)
+                               wildcard_ssid_tlv->max_ssid_length = 0;
+                       else
+                               wildcard_ssid_tlv->max_ssid_length =
+                                                       IEEE80211_MAX_SSID_LEN;
+
+                       if (!memcmp(user_scan_in->ssid_list[i].ssid,
+                                   "DIRECT-", 7))
+                               wildcard_ssid_tlv->max_ssid_length = 0xfe;
+
+                       memcpy(wildcard_ssid_tlv->ssid,
+                              user_scan_in->ssid_list[i].ssid, ssid_len);
+
+                       tlv_pos += (sizeof(wildcard_ssid_tlv->header)
+                               + le16_to_cpu(wildcard_ssid_tlv->header.len));
+
+                       mwifiex_dbg(adapter, INFO,
+                                   "info: scan: ssid[%d]: %s, %d\n",
+                                   i, wildcard_ssid_tlv->ssid,
+                                   wildcard_ssid_tlv->max_ssid_length);
+
+                       /* Empty wildcard ssid with a maxlen will match many or
+                          potentially all SSIDs (maxlen == 32), therefore do
+                          not treat the scan as
+                          filtered. */
+                       if (!ssid_len && wildcard_ssid_tlv->max_ssid_length)
+                               ssid_filter = false;
+               }
+
+               /*
+                *  The default number of channels sent in the command is low to
+                *  ensure the response buffer from the firmware does not
+                *  truncate scan results.  That is not an issue with an SSID
+                *  or BSSID filter applied to the scan results in the firmware.
+                */
+               if ((i && ssid_filter) ||
+                   !is_zero_ether_addr(scan_cfg_out->specific_bssid))
+                       *filtered_scan = true;
+
+               if (user_scan_in->scan_chan_gap) {
+                       mwifiex_dbg(adapter, INFO,
+                                   "info: scan: channel gap = %d\n",
+                                   user_scan_in->scan_chan_gap);
+                       *max_chan_per_scan =
+                                       MWIFIEX_MAX_CHANNELS_PER_SPECIFIC_SCAN;
+
+                       chan_gap_tlv = (void *)tlv_pos;
+                       chan_gap_tlv->header.type =
+                                        cpu_to_le16(TLV_TYPE_SCAN_CHANNEL_GAP);
+                       chan_gap_tlv->header.len =
+                                   cpu_to_le16(sizeof(chan_gap_tlv->chan_gap));
+                       chan_gap_tlv->chan_gap =
+                                    cpu_to_le16((user_scan_in->scan_chan_gap));
+                       tlv_pos +=
+                                 sizeof(struct mwifiex_ie_types_scan_chan_gap);
+               }
+       } else {
+               scan_cfg_out->bss_mode = (u8) adapter->scan_mode;
+               num_probes = adapter->scan_probes;
+       }
+
+       /*
+        *  If a specific BSSID or SSID is used, the number of channels in the
+        *  scan command will be increased to the absolute maximum.
+        */
+       if (*filtered_scan)
+               *max_chan_per_scan = MWIFIEX_MAX_CHANNELS_PER_SPECIFIC_SCAN;
+       else
+               *max_chan_per_scan = MWIFIEX_DEF_CHANNELS_PER_SCAN_CMD;
+
+       if (adapter->ext_scan) {
+               bss_mode = (struct mwifiex_ie_types_bss_mode *)tlv_pos;
+               bss_mode->header.type = cpu_to_le16(TLV_TYPE_BSS_MODE);
+               bss_mode->header.len = cpu_to_le16(sizeof(bss_mode->bss_mode));
+               bss_mode->bss_mode = scan_cfg_out->bss_mode;
+               tlv_pos += sizeof(bss_mode->header) +
+                          le16_to_cpu(bss_mode->header.len);
+       }
+
+       /* If the input config or adapter has the number of Probes set,
+          add tlv */
+       if (num_probes) {
+
+               mwifiex_dbg(adapter, INFO,
+                           "info: scan: num_probes = %d\n",
+                           num_probes);
+
+               num_probes_tlv = (struct mwifiex_ie_types_num_probes *) tlv_pos;
+               num_probes_tlv->header.type = cpu_to_le16(TLV_TYPE_NUMPROBES);
+               num_probes_tlv->header.len =
+                       cpu_to_le16(sizeof(num_probes_tlv->num_probes));
+               num_probes_tlv->num_probes = cpu_to_le16((u16) num_probes);
+
+               tlv_pos += sizeof(num_probes_tlv->header) +
+                       le16_to_cpu(num_probes_tlv->header.len);
+
+       }
+
+       if (ISSUPP_11NENABLED(priv->adapter->fw_cap_info) &&
+           (priv->adapter->config_bands & BAND_GN ||
+            priv->adapter->config_bands & BAND_AN)) {
+               ht_cap = (struct mwifiex_ie_types_htcap *) tlv_pos;
+               memset(ht_cap, 0, sizeof(struct mwifiex_ie_types_htcap));
+               ht_cap->header.type = cpu_to_le16(WLAN_EID_HT_CAPABILITY);
+               ht_cap->header.len =
+                               cpu_to_le16(sizeof(struct ieee80211_ht_cap));
+               radio_type =
+                       mwifiex_band_to_radio_type(priv->adapter->config_bands);
+               mwifiex_fill_cap_info(priv, radio_type, &ht_cap->ht_cap);
+               tlv_pos += sizeof(struct mwifiex_ie_types_htcap);
+       }
+
+       /* Append vendor specific IE TLV */
+       mwifiex_cmd_append_vsie_tlv(priv, MWIFIEX_VSIE_MASK_SCAN, &tlv_pos);
+
+       /*
+        * Set the output for the channel TLV to the address in the tlv buffer
+        *   past any TLVs that were added in this function (SSID, num_probes).
+        *   Channel TLVs will be added past this for each scan command,
+        *   preserving the TLVs that were previously added.
+        */
+       *chan_list_out =
+               (struct mwifiex_ie_types_chan_list_param_set *) tlv_pos;
+
+       if (user_scan_in && user_scan_in->chan_list[0].chan_number) {
+
+               mwifiex_dbg(adapter, INFO,
+                           "info: Scan: Using supplied channel list\n");
+
+               for (chan_idx = 0;
+                    chan_idx < MWIFIEX_USER_SCAN_CHAN_MAX &&
+                    user_scan_in->chan_list[chan_idx].chan_number;
+                    chan_idx++) {
+
+                       channel = user_scan_in->chan_list[chan_idx].chan_number;
+                       (scan_chan_list + chan_idx)->chan_number = channel;
+
+                       radio_type =
+                               user_scan_in->chan_list[chan_idx].radio_type;
+                       (scan_chan_list + chan_idx)->radio_type = radio_type;
+
+                       scan_type = user_scan_in->chan_list[chan_idx].scan_type;
+
+                       if (scan_type == MWIFIEX_SCAN_TYPE_PASSIVE)
+                               (scan_chan_list +
+                                chan_idx)->chan_scan_mode_bitmap
+                                       |= (MWIFIEX_PASSIVE_SCAN |
+                                           MWIFIEX_HIDDEN_SSID_REPORT);
+                       else
+                               (scan_chan_list +
+                                chan_idx)->chan_scan_mode_bitmap
+                                       &= ~MWIFIEX_PASSIVE_SCAN;
+
+                       if (*filtered_scan)
+                               (scan_chan_list +
+                                chan_idx)->chan_scan_mode_bitmap
+                                       |= MWIFIEX_DISABLE_CHAN_FILT;
+
+                       if (user_scan_in->chan_list[chan_idx].scan_time) {
+                               scan_dur = (u16) user_scan_in->
+                                       chan_list[chan_idx].scan_time;
+                       } else {
+                               if (scan_type == MWIFIEX_SCAN_TYPE_PASSIVE)
+                                       scan_dur = adapter->passive_scan_time;
+                               else if (*filtered_scan)
+                                       scan_dur = adapter->specific_scan_time;
+                               else
+                                       scan_dur = adapter->active_scan_time;
+                       }
+
+                       (scan_chan_list + chan_idx)->min_scan_time =
+                               cpu_to_le16(scan_dur);
+                       (scan_chan_list + chan_idx)->max_scan_time =
+                               cpu_to_le16(scan_dur);
+               }
+
+               /* Check if we are only scanning the current channel */
+               if ((chan_idx == 1) &&
+                   (user_scan_in->chan_list[0].chan_number ==
+                    priv->curr_bss_params.bss_descriptor.channel)) {
+                       *scan_current_only = true;
+                       mwifiex_dbg(adapter, INFO,
+                                   "info: Scan: Scanning current channel only\n");
+               }
+               chan_num = chan_idx;
+       } else {
+               mwifiex_dbg(adapter, INFO,
+                           "info: Scan: Creating full region channel list\n");
+               chan_num = mwifiex_scan_create_channel_list(priv, user_scan_in,
+                                                           scan_chan_list,
+                                                           *filtered_scan);
+       }
+
+}
+
+/*
+ * This function inspects the scan response buffer for pointers to
+ * expected TLVs.
+ *
+ * TLVs can be included at the end of the scan response BSS information.
+ *
+ * Data in the buffer is parsed pointers to TLVs that can potentially
+ * be passed back in the response.
+ */
+static void
+mwifiex_ret_802_11_scan_get_tlv_ptrs(struct mwifiex_adapter *adapter,
+                                    struct mwifiex_ie_types_data *tlv,
+                                    u32 tlv_buf_size, u32 req_tlv_type,
+                                    struct mwifiex_ie_types_data **tlv_data)
+{
+       struct mwifiex_ie_types_data *current_tlv;
+       u32 tlv_buf_left;
+       u32 tlv_type;
+       u32 tlv_len;
+
+       current_tlv = tlv;
+       tlv_buf_left = tlv_buf_size;
+       *tlv_data = NULL;
+
+       mwifiex_dbg(adapter, INFO,
+                   "info: SCAN_RESP: tlv_buf_size = %d\n",
+                   tlv_buf_size);
+
+       while (tlv_buf_left >= sizeof(struct mwifiex_ie_types_header)) {
+
+               tlv_type = le16_to_cpu(current_tlv->header.type);
+               tlv_len = le16_to_cpu(current_tlv->header.len);
+
+               if (sizeof(tlv->header) + tlv_len > tlv_buf_left) {
+                       mwifiex_dbg(adapter, ERROR,
+                                   "SCAN_RESP: TLV buffer corrupt\n");
+                       break;
+               }
+
+               if (req_tlv_type == tlv_type) {
+                       switch (tlv_type) {
+                       case TLV_TYPE_TSFTIMESTAMP:
+                               mwifiex_dbg(adapter, INFO,
+                                           "info: SCAN_RESP: TSF\t"
+                                           "timestamp TLV, len = %d\n",
+                                           tlv_len);
+                               *tlv_data = current_tlv;
+                               break;
+                       case TLV_TYPE_CHANNELBANDLIST:
+                               mwifiex_dbg(adapter, INFO,
+                                           "info: SCAN_RESP: channel\t"
+                                           "band list TLV, len = %d\n",
+                                           tlv_len);
+                               *tlv_data = current_tlv;
+                               break;
+                       default:
+                               mwifiex_dbg(adapter, ERROR,
+                                           "SCAN_RESP: unhandled TLV = %d\n",
+                                           tlv_type);
+                               /* Give up, this seems corrupted */
+                               return;
+                       }
+               }
+
+               if (*tlv_data)
+                       break;
+
+
+               tlv_buf_left -= (sizeof(tlv->header) + tlv_len);
+               current_tlv =
+                       (struct mwifiex_ie_types_data *) (current_tlv->data +
+                                                         tlv_len);
+
+       }                       /* while */
+}
+
+/*
+ * This function parses provided beacon buffer and updates
+ * respective fields in bss descriptor structure.
+ */
+int mwifiex_update_bss_desc_with_ie(struct mwifiex_adapter *adapter,
+                                   struct mwifiex_bssdescriptor *bss_entry)
+{
+       int ret = 0;
+       u8 element_id;
+       struct ieee_types_fh_param_set *fh_param_set;
+       struct ieee_types_ds_param_set *ds_param_set;
+       struct ieee_types_cf_param_set *cf_param_set;
+       struct ieee_types_ibss_param_set *ibss_param_set;
+       u8 *current_ptr;
+       u8 *rate;
+       u8 element_len;
+       u16 total_ie_len;
+       u8 bytes_to_copy;
+       u8 rate_size;
+       u8 found_data_rate_ie;
+       u32 bytes_left;
+       struct ieee_types_vendor_specific *vendor_ie;
+       const u8 wpa_oui[4] = { 0x00, 0x50, 0xf2, 0x01 };
+       const u8 wmm_oui[4] = { 0x00, 0x50, 0xf2, 0x02 };
+
+       found_data_rate_ie = false;
+       rate_size = 0;
+       current_ptr = bss_entry->beacon_buf;
+       bytes_left = bss_entry->beacon_buf_size;
+
+       /* Process variable IE */
+       while (bytes_left >= 2) {
+               element_id = *current_ptr;
+               element_len = *(current_ptr + 1);
+               total_ie_len = element_len + sizeof(struct ieee_types_header);
+
+               if (bytes_left < total_ie_len) {
+                       mwifiex_dbg(adapter, ERROR,
+                                   "err: InterpretIE: in processing\t"
+                                   "IE, bytes left < IE length\n");
+                       return -1;
+               }
+               switch (element_id) {
+               case WLAN_EID_SSID:
+                       bss_entry->ssid.ssid_len = element_len;
+                       memcpy(bss_entry->ssid.ssid, (current_ptr + 2),
+                              element_len);
+                       mwifiex_dbg(adapter, INFO,
+                                   "info: InterpretIE: ssid: %-32s\n",
+                                   bss_entry->ssid.ssid);
+                       break;
+
+               case WLAN_EID_SUPP_RATES:
+                       memcpy(bss_entry->data_rates, current_ptr + 2,
+                              element_len);
+                       memcpy(bss_entry->supported_rates, current_ptr + 2,
+                              element_len);
+                       rate_size = element_len;
+                       found_data_rate_ie = true;
+                       break;
+
+               case WLAN_EID_FH_PARAMS:
+                       fh_param_set =
+                               (struct ieee_types_fh_param_set *) current_ptr;
+                       memcpy(&bss_entry->phy_param_set.fh_param_set,
+                              fh_param_set,
+                              sizeof(struct ieee_types_fh_param_set));
+                       break;
+
+               case WLAN_EID_DS_PARAMS:
+                       ds_param_set =
+                               (struct ieee_types_ds_param_set *) current_ptr;
+
+                       bss_entry->channel = ds_param_set->current_chan;
+
+                       memcpy(&bss_entry->phy_param_set.ds_param_set,
+                              ds_param_set,
+                              sizeof(struct ieee_types_ds_param_set));
+                       break;
+
+               case WLAN_EID_CF_PARAMS:
+                       cf_param_set =
+                               (struct ieee_types_cf_param_set *) current_ptr;
+                       memcpy(&bss_entry->ss_param_set.cf_param_set,
+                              cf_param_set,
+                              sizeof(struct ieee_types_cf_param_set));
+                       break;
+
+               case WLAN_EID_IBSS_PARAMS:
+                       ibss_param_set =
+                               (struct ieee_types_ibss_param_set *)
+                               current_ptr;
+                       memcpy(&bss_entry->ss_param_set.ibss_param_set,
+                              ibss_param_set,
+                              sizeof(struct ieee_types_ibss_param_set));
+                       break;
+
+               case WLAN_EID_ERP_INFO:
+                       bss_entry->erp_flags = *(current_ptr + 2);
+                       break;
+
+               case WLAN_EID_PWR_CONSTRAINT:
+                       bss_entry->local_constraint = *(current_ptr + 2);
+                       bss_entry->sensed_11h = true;
+                       break;
+
+               case WLAN_EID_CHANNEL_SWITCH:
+                       bss_entry->chan_sw_ie_present = true;
+               case WLAN_EID_PWR_CAPABILITY:
+               case WLAN_EID_TPC_REPORT:
+               case WLAN_EID_QUIET:
+                       bss_entry->sensed_11h = true;
+                   break;
+
+               case WLAN_EID_EXT_SUPP_RATES:
+                       /*
+                        * Only process extended supported rate
+                        * if data rate is already found.
+                        * Data rate IE should come before
+                        * extended supported rate IE
+                        */
+                       if (found_data_rate_ie) {
+                               if ((element_len + rate_size) >
+                                   MWIFIEX_SUPPORTED_RATES)
+                                       bytes_to_copy =
+                                               (MWIFIEX_SUPPORTED_RATES -
+                                                rate_size);
+                               else
+                                       bytes_to_copy = element_len;
+
+                               rate = (u8 *) bss_entry->data_rates;
+                               rate += rate_size;
+                               memcpy(rate, current_ptr + 2, bytes_to_copy);
+
+                               rate = (u8 *) bss_entry->supported_rates;
+                               rate += rate_size;
+                               memcpy(rate, current_ptr + 2, bytes_to_copy);
+                       }
+                       break;
+
+               case WLAN_EID_VENDOR_SPECIFIC:
+                       vendor_ie = (struct ieee_types_vendor_specific *)
+                                       current_ptr;
+
+                       if (!memcmp
+                           (vendor_ie->vend_hdr.oui, wpa_oui,
+                            sizeof(wpa_oui))) {
+                               bss_entry->bcn_wpa_ie =
+                                       (struct ieee_types_vendor_specific *)
+                                       current_ptr;
+                               bss_entry->wpa_offset = (u16)
+                                       (current_ptr - bss_entry->beacon_buf);
+                       } else if (!memcmp(vendor_ie->vend_hdr.oui, wmm_oui,
+                                   sizeof(wmm_oui))) {
+                               if (total_ie_len ==
+                                   sizeof(struct ieee_types_wmm_parameter) ||
+                                   total_ie_len ==
+                                   sizeof(struct ieee_types_wmm_info))
+                                       /*
+                                        * Only accept and copy the WMM IE if
+                                        * it matches the size expected for the
+                                        * WMM Info IE or the WMM Parameter IE.
+                                        */
+                                       memcpy((u8 *) &bss_entry->wmm_ie,
+                                              current_ptr, total_ie_len);
+                       }
+                       break;
+               case WLAN_EID_RSN:
+                       bss_entry->bcn_rsn_ie =
+                               (struct ieee_types_generic *) current_ptr;
+                       bss_entry->rsn_offset = (u16) (current_ptr -
+                                                       bss_entry->beacon_buf);
+                       break;
+               case WLAN_EID_BSS_AC_ACCESS_DELAY:
+                       bss_entry->bcn_wapi_ie =
+                               (struct ieee_types_generic *) current_ptr;
+                       bss_entry->wapi_offset = (u16) (current_ptr -
+                                                       bss_entry->beacon_buf);
+                       break;
+               case WLAN_EID_HT_CAPABILITY:
+                       bss_entry->bcn_ht_cap = (struct ieee80211_ht_cap *)
+                                       (current_ptr +
+                                       sizeof(struct ieee_types_header));
+                       bss_entry->ht_cap_offset = (u16) (current_ptr +
+                                       sizeof(struct ieee_types_header) -
+                                       bss_entry->beacon_buf);
+                       break;
+               case WLAN_EID_HT_OPERATION:
+                       bss_entry->bcn_ht_oper =
+                               (struct ieee80211_ht_operation *)(current_ptr +
+                                       sizeof(struct ieee_types_header));
+                       bss_entry->ht_info_offset = (u16) (current_ptr +
+                                       sizeof(struct ieee_types_header) -
+                                       bss_entry->beacon_buf);
+                       break;
+               case WLAN_EID_VHT_CAPABILITY:
+                       bss_entry->disable_11ac = false;
+                       bss_entry->bcn_vht_cap =
+                               (void *)(current_ptr +
+                                        sizeof(struct ieee_types_header));
+                       bss_entry->vht_cap_offset =
+                                       (u16)((u8 *)bss_entry->bcn_vht_cap -
+                                             bss_entry->beacon_buf);
+                       break;
+               case WLAN_EID_VHT_OPERATION:
+                       bss_entry->bcn_vht_oper =
+                               (void *)(current_ptr +
+                                        sizeof(struct ieee_types_header));
+                       bss_entry->vht_info_offset =
+                                       (u16)((u8 *)bss_entry->bcn_vht_oper -
+                                             bss_entry->beacon_buf);
+                       break;
+               case WLAN_EID_BSS_COEX_2040:
+                       bss_entry->bcn_bss_co_2040 = current_ptr;
+                       bss_entry->bss_co_2040_offset =
+                               (u16) (current_ptr - bss_entry->beacon_buf);
+                       break;
+               case WLAN_EID_EXT_CAPABILITY:
+                       bss_entry->bcn_ext_cap = current_ptr;
+                       bss_entry->ext_cap_offset =
+                               (u16) (current_ptr - bss_entry->beacon_buf);
+                       break;
+               case WLAN_EID_OPMODE_NOTIF:
+                       bss_entry->oper_mode = (void *)current_ptr;
+                       bss_entry->oper_mode_offset =
+                                       (u16)((u8 *)bss_entry->oper_mode -
+                                             bss_entry->beacon_buf);
+                       break;
+               default:
+                       break;
+               }
+
+               current_ptr += element_len + 2;
+
+               /* Need to account for IE ID and IE Len */
+               bytes_left -= (element_len + 2);
+
+       }       /* while (bytes_left > 2) */
+       return ret;
+}
+
+/*
+ * This function converts radio type scan parameter to a band configuration
+ * to be used in join command.
+ */
+static u8
+mwifiex_radio_type_to_band(u8 radio_type)
+{
+       switch (radio_type) {
+       case HostCmd_SCAN_RADIO_TYPE_A:
+               return BAND_A;
+       case HostCmd_SCAN_RADIO_TYPE_BG:
+       default:
+               return BAND_G;
+       }
+}
+
+/*
+ * This is an internal function used to start a scan based on an input
+ * configuration.
+ *
+ * This uses the input user scan configuration information when provided in
+ * order to send the appropriate scan commands to firmware to populate or
+ * update the internal driver scan table.
+ */
+int mwifiex_scan_networks(struct mwifiex_private *priv,
+                         const struct mwifiex_user_scan_cfg *user_scan_in)
+{
+       int ret;
+       struct mwifiex_adapter *adapter = priv->adapter;
+       struct cmd_ctrl_node *cmd_node;
+       union mwifiex_scan_cmd_config_tlv *scan_cfg_out;
+       struct mwifiex_ie_types_chan_list_param_set *chan_list_out;
+       struct mwifiex_chan_scan_param_set *scan_chan_list;
+       u8 filtered_scan;
+       u8 scan_current_chan_only;
+       u8 max_chan_per_scan;
+       unsigned long flags;
+
+       if (adapter->scan_processing) {
+               mwifiex_dbg(adapter, WARN,
+                           "cmd: Scan already in process...\n");
+               return -EBUSY;
+       }
+
+       if (priv->scan_block) {
+               mwifiex_dbg(adapter, WARN,
+                           "cmd: Scan is blocked during association...\n");
+               return -EBUSY;
+       }
+
+       if (adapter->surprise_removed || adapter->is_cmd_timedout) {
+               mwifiex_dbg(adapter, ERROR,
+                           "Ignore scan. Card removed or firmware in bad state\n");
+               return -EFAULT;
+       }
+
+       spin_lock_irqsave(&adapter->mwifiex_cmd_lock, flags);
+       adapter->scan_processing = true;
+       spin_unlock_irqrestore(&adapter->mwifiex_cmd_lock, flags);
+
+       scan_cfg_out = kzalloc(sizeof(union mwifiex_scan_cmd_config_tlv),
+                              GFP_KERNEL);
+       if (!scan_cfg_out) {
+               ret = -ENOMEM;
+               goto done;
+       }
+
+       scan_chan_list = kcalloc(MWIFIEX_USER_SCAN_CHAN_MAX,
+                                sizeof(struct mwifiex_chan_scan_param_set),
+                                GFP_KERNEL);
+       if (!scan_chan_list) {
+               kfree(scan_cfg_out);
+               ret = -ENOMEM;
+               goto done;
+       }
+
+       mwifiex_config_scan(priv, user_scan_in, &scan_cfg_out->config,
+                           &chan_list_out, scan_chan_list, &max_chan_per_scan,
+                           &filtered_scan, &scan_current_chan_only);
+
+       ret = mwifiex_scan_channel_list(priv, max_chan_per_scan, filtered_scan,
+                                       &scan_cfg_out->config, chan_list_out,
+                                       scan_chan_list);
+
+       /* Get scan command from scan_pending_q and put to cmd_pending_q */
+       if (!ret) {
+               spin_lock_irqsave(&adapter->scan_pending_q_lock, flags);
+               if (!list_empty(&adapter->scan_pending_q)) {
+                       cmd_node = list_first_entry(&adapter->scan_pending_q,
+                                                   struct cmd_ctrl_node, list);
+                       list_del(&cmd_node->list);
+                       spin_unlock_irqrestore(&adapter->scan_pending_q_lock,
+                                              flags);
+                       mwifiex_insert_cmd_to_pending_q(adapter, cmd_node,
+                                                       true);
+                       queue_work(adapter->workqueue, &adapter->main_work);
+
+                       /* Perform internal scan synchronously */
+                       if (!priv->scan_request) {
+                               mwifiex_dbg(adapter, INFO,
+                                           "wait internal scan\n");
+                               mwifiex_wait_queue_complete(adapter, cmd_node);
+                       }
+               } else {
+                       spin_unlock_irqrestore(&adapter->scan_pending_q_lock,
+                                              flags);
+               }
+       }
+
+       kfree(scan_cfg_out);
+       kfree(scan_chan_list);
+done:
+       if (ret) {
+               spin_lock_irqsave(&adapter->mwifiex_cmd_lock, flags);
+               adapter->scan_processing = false;
+               spin_unlock_irqrestore(&adapter->mwifiex_cmd_lock, flags);
+       }
+       return ret;
+}
+
+/*
+ * This function prepares a scan command to be sent to the firmware.
+ *
+ * This uses the scan command configuration sent to the command processing
+ * module in command preparation stage to configure a scan command structure
+ * to send to firmware.
+ *
+ * The fixed fields specifying the BSS type and BSSID filters as well as a
+ * variable number/length of TLVs are sent in the command to firmware.
+ *
+ * Preparation also includes -
+ *      - Setting command ID, and proper size
+ *      - Ensuring correct endian-ness
+ */
+int mwifiex_cmd_802_11_scan(struct host_cmd_ds_command *cmd,
+                           struct mwifiex_scan_cmd_config *scan_cfg)
+{
+       struct host_cmd_ds_802_11_scan *scan_cmd = &cmd->params.scan;
+
+       /* Set fixed field variables in scan command */
+       scan_cmd->bss_mode = scan_cfg->bss_mode;
+       memcpy(scan_cmd->bssid, scan_cfg->specific_bssid,
+              sizeof(scan_cmd->bssid));
+       memcpy(scan_cmd->tlv_buffer, scan_cfg->tlv_buf, scan_cfg->tlv_buf_len);
+
+       cmd->command = cpu_to_le16(HostCmd_CMD_802_11_SCAN);
+
+       /* Size is equal to the sizeof(fixed portions) + the TLV len + header */
+       cmd->size = cpu_to_le16((u16) (sizeof(scan_cmd->bss_mode)
+                                         + sizeof(scan_cmd->bssid)
+                                         + scan_cfg->tlv_buf_len + S_DS_GEN));
+
+       return 0;
+}
+
+/*
+ * This function checks compatibility of requested network with current
+ * driver settings.
+ */
+int mwifiex_check_network_compatibility(struct mwifiex_private *priv,
+                                       struct mwifiex_bssdescriptor *bss_desc)
+{
+       int ret = -1;
+
+       if (!bss_desc)
+               return -1;
+
+       if ((mwifiex_get_cfp(priv, (u8) bss_desc->bss_band,
+                            (u16) bss_desc->channel, 0))) {
+               switch (priv->bss_mode) {
+               case NL80211_IFTYPE_STATION:
+               case NL80211_IFTYPE_ADHOC:
+                       ret = mwifiex_is_network_compatible(priv, bss_desc,
+                                                           priv->bss_mode);
+                       if (ret)
+                               mwifiex_dbg(priv->adapter, ERROR,
+                                           "Incompatible network settings\n");
+                       break;
+               default:
+                       ret = 0;
+               }
+       }
+
+       return ret;
+}
+
+/* This function checks if SSID string contains all zeroes or length is zero */
+static bool mwifiex_is_hidden_ssid(struct cfg80211_ssid *ssid)
+{
+       int idx;
+
+       for (idx = 0; idx < ssid->ssid_len; idx++) {
+               if (ssid->ssid[idx])
+                       return false;
+       }
+
+       return true;
+}
+
+/* This function checks if any hidden SSID found in passive scan channels
+ * and save those channels for specific SSID active scan
+ */
+static int mwifiex_save_hidden_ssid_channels(struct mwifiex_private *priv,
+                                            struct cfg80211_bss *bss)
+{
+       struct mwifiex_bssdescriptor *bss_desc;
+       int ret;
+       int chid;
+
+       /* Allocate and fill new bss descriptor */
+       bss_desc = kzalloc(sizeof(*bss_desc), GFP_KERNEL);
+       if (!bss_desc)
+               return -ENOMEM;
+
+       ret = mwifiex_fill_new_bss_desc(priv, bss, bss_desc);
+       if (ret)
+               goto done;
+
+       if (mwifiex_is_hidden_ssid(&bss_desc->ssid)) {
+               mwifiex_dbg(priv->adapter, INFO, "found hidden SSID\n");
+               for (chid = 0 ; chid < MWIFIEX_USER_SCAN_CHAN_MAX; chid++) {
+                       if (priv->hidden_chan[chid].chan_number ==
+                           bss->channel->hw_value)
+                               break;
+
+                       if (!priv->hidden_chan[chid].chan_number) {
+                               priv->hidden_chan[chid].chan_number =
+                                       bss->channel->hw_value;
+                               priv->hidden_chan[chid].radio_type =
+                                       bss->channel->band;
+                               priv->hidden_chan[chid].scan_type =
+                                       MWIFIEX_SCAN_TYPE_ACTIVE;
+                               break;
+                       }
+               }
+       }
+
+done:
+       kfree(bss_desc);
+       return 0;
+}
+
+static int mwifiex_update_curr_bss_params(struct mwifiex_private *priv,
+                                         struct cfg80211_bss *bss)
+{
+       struct mwifiex_bssdescriptor *bss_desc;
+       int ret;
+       unsigned long flags;
+
+       /* Allocate and fill new bss descriptor */
+       bss_desc = kzalloc(sizeof(struct mwifiex_bssdescriptor), GFP_KERNEL);
+       if (!bss_desc)
+               return -ENOMEM;
+
+       ret = mwifiex_fill_new_bss_desc(priv, bss, bss_desc);
+       if (ret)
+               goto done;
+
+       ret = mwifiex_check_network_compatibility(priv, bss_desc);
+       if (ret)
+               goto done;
+
+       spin_lock_irqsave(&priv->curr_bcn_buf_lock, flags);
+       /* Make a copy of current BSSID descriptor */
+       memcpy(&priv->curr_bss_params.bss_descriptor, bss_desc,
+              sizeof(priv->curr_bss_params.bss_descriptor));
+
+       /* The contents of beacon_ie will be copied to its own buffer
+        * in mwifiex_save_curr_bcn()
+        */
+       mwifiex_save_curr_bcn(priv);
+       spin_unlock_irqrestore(&priv->curr_bcn_buf_lock, flags);
+
+done:
+       /* beacon_ie buffer was allocated in function
+        * mwifiex_fill_new_bss_desc(). Free it now.
+        */
+       kfree(bss_desc->beacon_buf);
+       kfree(bss_desc);
+       return 0;
+}
+
+static int
+mwifiex_parse_single_response_buf(struct mwifiex_private *priv, u8 **bss_info,
+                                 u32 *bytes_left, u64 fw_tsf, u8 *radio_type,
+                                 bool ext_scan, s32 rssi_val)
+{
+       struct mwifiex_adapter *adapter = priv->adapter;
+       struct mwifiex_chan_freq_power *cfp;
+       struct cfg80211_bss *bss;
+       u8 bssid[ETH_ALEN];
+       s32 rssi;
+       const u8 *ie_buf;
+       size_t ie_len;
+       u16 channel = 0;
+       u16 beacon_size = 0;
+       u32 curr_bcn_bytes;
+       u32 freq;
+       u16 beacon_period;
+       u16 cap_info_bitmap;
+       u8 *current_ptr;
+       u64 timestamp;
+       struct mwifiex_fixed_bcn_param *bcn_param;
+       struct mwifiex_bss_priv *bss_priv;
+
+       if (*bytes_left >= sizeof(beacon_size)) {
+               /* Extract & convert beacon size from command buffer */
+               beacon_size = le16_to_cpu(*(__le16 *)(*bss_info));
+               *bytes_left -= sizeof(beacon_size);
+               *bss_info += sizeof(beacon_size);
+       }
+
+       if (!beacon_size || beacon_size > *bytes_left) {
+               *bss_info += *bytes_left;
+               *bytes_left = 0;
+               return -EFAULT;
+       }
+
+       /* Initialize the current working beacon pointer for this BSS
+        * iteration
+        */
+       current_ptr = *bss_info;
+
+       /* Advance the return beacon pointer past the current beacon */
+       *bss_info += beacon_size;
+       *bytes_left -= beacon_size;
+
+       curr_bcn_bytes = beacon_size;
+
+       /* First 5 fields are bssid, RSSI(for legacy scan only),
+        * time stamp, beacon interval, and capability information
+        */
+       if (curr_bcn_bytes < ETH_ALEN + sizeof(u8) +
+           sizeof(struct mwifiex_fixed_bcn_param)) {
+               mwifiex_dbg(adapter, ERROR,
+                           "InterpretIE: not enough bytes left\n");
+               return -EFAULT;
+       }
+
+       memcpy(bssid, current_ptr, ETH_ALEN);
+       current_ptr += ETH_ALEN;
+       curr_bcn_bytes -= ETH_ALEN;
+
+       if (!ext_scan) {
+               rssi = (s32) *current_ptr;
+               rssi = (-rssi) * 100;           /* Convert dBm to mBm */
+               current_ptr += sizeof(u8);
+               curr_bcn_bytes -= sizeof(u8);
+               mwifiex_dbg(adapter, INFO,
+                           "info: InterpretIE: RSSI=%d\n", rssi);
+       } else {
+               rssi = rssi_val;
+       }
+
+       bcn_param = (struct mwifiex_fixed_bcn_param *)current_ptr;
+       current_ptr += sizeof(*bcn_param);
+       curr_bcn_bytes -= sizeof(*bcn_param);
+
+       timestamp = le64_to_cpu(bcn_param->timestamp);
+       beacon_period = le16_to_cpu(bcn_param->beacon_period);
+
+       cap_info_bitmap = le16_to_cpu(bcn_param->cap_info_bitmap);
+       mwifiex_dbg(adapter, INFO,
+                   "info: InterpretIE: capabilities=0x%X\n",
+                   cap_info_bitmap);
+
+       /* Rest of the current buffer are IE's */
+       ie_buf = current_ptr;
+       ie_len = curr_bcn_bytes;
+       mwifiex_dbg(adapter, INFO,
+                   "info: InterpretIE: IELength for this AP = %d\n",
+                   curr_bcn_bytes);
+
+       while (curr_bcn_bytes >= sizeof(struct ieee_types_header)) {
+               u8 element_id, element_len;
+
+               element_id = *current_ptr;
+               element_len = *(current_ptr + 1);
+               if (curr_bcn_bytes < element_len +
+                               sizeof(struct ieee_types_header)) {
+                       mwifiex_dbg(adapter, ERROR,
+                                   "%s: bytes left < IE length\n", __func__);
+                       return -EFAULT;
+               }
+               if (element_id == WLAN_EID_DS_PARAMS) {
+                       channel = *(current_ptr +
+                                   sizeof(struct ieee_types_header));
+                       break;
+               }
+
+               current_ptr += element_len + sizeof(struct ieee_types_header);
+               curr_bcn_bytes -= element_len +
+                                       sizeof(struct ieee_types_header);
+       }
+
+       if (channel) {
+               struct ieee80211_channel *chan;
+               u8 band;
+
+               /* Skip entry if on csa closed channel */
+               if (channel == priv->csa_chan) {
+                       mwifiex_dbg(adapter, WARN,
+                                   "Dropping entry on csa closed channel\n");
+                       return 0;
+               }
+
+               band = BAND_G;
+               if (radio_type)
+                       band = mwifiex_radio_type_to_band(*radio_type &
+                                                         (BIT(0) | BIT(1)));
+
+               cfp = mwifiex_get_cfp(priv, band, channel, 0);
+
+               freq = cfp ? cfp->freq : 0;
+
+               chan = ieee80211_get_channel(priv->wdev.wiphy, freq);
+
+               if (chan && !(chan->flags & IEEE80211_CHAN_DISABLED)) {
+                       bss = cfg80211_inform_bss(priv->wdev.wiphy,
+                                           chan, CFG80211_BSS_FTYPE_UNKNOWN,
+                                           bssid, timestamp,
+                                           cap_info_bitmap, beacon_period,
+                                           ie_buf, ie_len, rssi, GFP_KERNEL);
+                       if (bss) {
+                               bss_priv = (struct mwifiex_bss_priv *)bss->priv;
+                               bss_priv->band = band;
+                               bss_priv->fw_tsf = fw_tsf;
+                               if (priv->media_connected &&
+                                   !memcmp(bssid, priv->curr_bss_params.
+                                           bss_descriptor.mac_address,
+                                           ETH_ALEN))
+                                       mwifiex_update_curr_bss_params(priv,
+                                                                      bss);
+                               cfg80211_put_bss(priv->wdev.wiphy, bss);
+                       }
+
+                       if ((chan->flags & IEEE80211_CHAN_RADAR) ||
+                           (chan->flags & IEEE80211_CHAN_NO_IR)) {
+                               mwifiex_dbg(adapter, INFO,
+                                           "radar or passive channel %d\n",
+                                           channel);
+                               mwifiex_save_hidden_ssid_channels(priv, bss);
+                       }
+               }
+       } else {
+               mwifiex_dbg(adapter, WARN, "missing BSS channel IE\n");
+       }
+
+       return 0;
+}
+
+static void mwifiex_complete_scan(struct mwifiex_private *priv)
+{
+       struct mwifiex_adapter *adapter = priv->adapter;
+
+       adapter->survey_idx = 0;
+       if (adapter->curr_cmd->wait_q_enabled) {
+               adapter->cmd_wait_q.status = 0;
+               if (!priv->scan_request) {
+                       mwifiex_dbg(adapter, INFO,
+                                   "complete internal scan\n");
+                       mwifiex_complete_cmd(adapter, adapter->curr_cmd);
+               }
+       }
+}
+
+/* This function checks if any hidden SSID found in passive scan channels
+ * and do specific SSID active scan for those channels
+ */
+static int
+mwifiex_active_scan_req_for_passive_chan(struct mwifiex_private *priv)
+{
+       int ret;
+       struct mwifiex_adapter *adapter = priv->adapter;
+       u8 id = 0;
+       struct mwifiex_user_scan_cfg  *user_scan_cfg;
+
+       if (adapter->active_scan_triggered || !priv->scan_request) {
+               adapter->active_scan_triggered = false;
+               return 0;
+       }
+
+       if (!priv->hidden_chan[0].chan_number) {
+               mwifiex_dbg(adapter, INFO, "No BSS with hidden SSID found on DFS channels\n");
+               return 0;
+       }
+       user_scan_cfg = kzalloc(sizeof(*user_scan_cfg), GFP_KERNEL);
+
+       if (!user_scan_cfg)
+               return -ENOMEM;
+
+       memset(user_scan_cfg, 0, sizeof(*user_scan_cfg));
+
+       for (id = 0; id < MWIFIEX_USER_SCAN_CHAN_MAX; id++) {
+               if (!priv->hidden_chan[id].chan_number)
+                       break;
+               memcpy(&user_scan_cfg->chan_list[id],
+                      &priv->hidden_chan[id],
+                      sizeof(struct mwifiex_user_scan_chan));
+       }
+
+       adapter->active_scan_triggered = true;
+       user_scan_cfg->num_ssids = priv->scan_request->n_ssids;
+       user_scan_cfg->ssid_list = priv->scan_request->ssids;
+
+       ret = mwifiex_scan_networks(priv, user_scan_cfg);
+       kfree(user_scan_cfg);
+
+       memset(&priv->hidden_chan, 0, sizeof(priv->hidden_chan));
+
+       if (ret) {
+               dev_err(priv->adapter->dev, "scan failed: %d\n", ret);
+               return ret;
+       }
+
+       return 0;
+}
+static void mwifiex_check_next_scan_command(struct mwifiex_private *priv)
+{
+       struct mwifiex_adapter *adapter = priv->adapter;
+       struct cmd_ctrl_node *cmd_node, *tmp_node;
+       unsigned long flags;
+
+       spin_lock_irqsave(&adapter->scan_pending_q_lock, flags);
+       if (list_empty(&adapter->scan_pending_q)) {
+               spin_unlock_irqrestore(&adapter->scan_pending_q_lock, flags);
+               spin_lock_irqsave(&adapter->mwifiex_cmd_lock, flags);
+               adapter->scan_processing = false;
+               spin_unlock_irqrestore(&adapter->mwifiex_cmd_lock, flags);
+
+               mwifiex_active_scan_req_for_passive_chan(priv);
+
+               if (!adapter->ext_scan)
+                       mwifiex_complete_scan(priv);
+
+               if (priv->scan_request) {
+                       mwifiex_dbg(adapter, INFO,
+                                   "info: notifying scan done\n");
+                       cfg80211_scan_done(priv->scan_request, 0);
+                       priv->scan_request = NULL;
+               } else {
+                       priv->scan_aborting = false;
+                       mwifiex_dbg(adapter, INFO,
+                                   "info: scan already aborted\n");
+               }
+       } else if ((priv->scan_aborting && !priv->scan_request) ||
+                  priv->scan_block) {
+               list_for_each_entry_safe(cmd_node, tmp_node,
+                                        &adapter->scan_pending_q, list) {
+                       list_del(&cmd_node->list);
+                       mwifiex_insert_cmd_to_free_q(adapter, cmd_node);
+               }
+               spin_unlock_irqrestore(&adapter->scan_pending_q_lock, flags);
+
+               spin_lock_irqsave(&adapter->mwifiex_cmd_lock, flags);
+               adapter->scan_processing = false;
+               spin_unlock_irqrestore(&adapter->mwifiex_cmd_lock, flags);
+
+               if (!adapter->active_scan_triggered) {
+                       if (priv->scan_request) {
+                               mwifiex_dbg(adapter, INFO,
+                                           "info: aborting scan\n");
+                               cfg80211_scan_done(priv->scan_request, 1);
+                               priv->scan_request = NULL;
+                       } else {
+                               priv->scan_aborting = false;
+                               mwifiex_dbg(adapter, INFO,
+                                           "info: scan already aborted\n");
+                       }
+               }
+       } else {
+               /* Get scan command from scan_pending_q and put to
+                * cmd_pending_q
+                */
+               cmd_node = list_first_entry(&adapter->scan_pending_q,
+                                           struct cmd_ctrl_node, list);
+               list_del(&cmd_node->list);
+               spin_unlock_irqrestore(&adapter->scan_pending_q_lock, flags);
+               mwifiex_insert_cmd_to_pending_q(adapter, cmd_node, true);
+       }
+
+       return;
+}
+
+/*
+ * This function handles the command response of scan.
+ *
+ * The response buffer for the scan command has the following
+ * memory layout:
+ *
+ *      .-------------------------------------------------------------.
+ *      |  Header (4 * sizeof(t_u16)):  Standard command response hdr |
+ *      .-------------------------------------------------------------.
+ *      |  BufSize (t_u16) : sizeof the BSS Description data          |
+ *      .-------------------------------------------------------------.
+ *      |  NumOfSet (t_u8) : Number of BSS Descs returned             |
+ *      .-------------------------------------------------------------.
+ *      |  BSSDescription data (variable, size given in BufSize)      |
+ *      .-------------------------------------------------------------.
+ *      |  TLV data (variable, size calculated using Header->Size,    |
+ *      |            BufSize and sizeof the fixed fields above)       |
+ *      .-------------------------------------------------------------.
+ */
+int mwifiex_ret_802_11_scan(struct mwifiex_private *priv,
+                           struct host_cmd_ds_command *resp)
+{
+       int ret = 0;
+       struct mwifiex_adapter *adapter = priv->adapter;
+       struct host_cmd_ds_802_11_scan_rsp *scan_rsp;
+       struct mwifiex_ie_types_data *tlv_data;
+       struct mwifiex_ie_types_tsf_timestamp *tsf_tlv;
+       u8 *bss_info;
+       u32 scan_resp_size;
+       u32 bytes_left;
+       u32 idx;
+       u32 tlv_buf_size;
+       struct mwifiex_ie_types_chan_band_list_param_set *chan_band_tlv;
+       struct chan_band_param_set *chan_band;
+       u8 is_bgscan_resp;
+       __le64 fw_tsf = 0;
+       u8 *radio_type;
+
+       is_bgscan_resp = (le16_to_cpu(resp->command)
+                         == HostCmd_CMD_802_11_BG_SCAN_QUERY);
+       if (is_bgscan_resp)
+               scan_rsp = &resp->params.bg_scan_query_resp.scan_resp;
+       else
+               scan_rsp = &resp->params.scan_resp;
+
+
+       if (scan_rsp->number_of_sets > MWIFIEX_MAX_AP) {
+               mwifiex_dbg(adapter, ERROR,
+                           "SCAN_RESP: too many AP returned (%d)\n",
+                           scan_rsp->number_of_sets);
+               ret = -1;
+               goto check_next_scan;
+       }
+
+       /* Check csa channel expiry before parsing scan response */
+       mwifiex_11h_get_csa_closed_channel(priv);
+
+       bytes_left = le16_to_cpu(scan_rsp->bss_descript_size);
+       mwifiex_dbg(adapter, INFO,
+                   "info: SCAN_RESP: bss_descript_size %d\n",
+                   bytes_left);
+
+       scan_resp_size = le16_to_cpu(resp->size);
+
+       mwifiex_dbg(adapter, INFO,
+                   "info: SCAN_RESP: returned %d APs before parsing\n",
+                   scan_rsp->number_of_sets);
+
+       bss_info = scan_rsp->bss_desc_and_tlv_buffer;
+
+       /*
+        * The size of the TLV buffer is equal to the entire command response
+        *   size (scan_resp_size) minus the fixed fields (sizeof()'s), the
+        *   BSS Descriptions (bss_descript_size as bytesLef) and the command
+        *   response header (S_DS_GEN)
+        */
+       tlv_buf_size = scan_resp_size - (bytes_left
+                                        + sizeof(scan_rsp->bss_descript_size)
+                                        + sizeof(scan_rsp->number_of_sets)
+                                        + S_DS_GEN);
+
+       tlv_data = (struct mwifiex_ie_types_data *) (scan_rsp->
+                                                bss_desc_and_tlv_buffer +
+                                                bytes_left);
+
+       /* Search the TLV buffer space in the scan response for any valid
+          TLVs */
+       mwifiex_ret_802_11_scan_get_tlv_ptrs(adapter, tlv_data, tlv_buf_size,
+                                            TLV_TYPE_TSFTIMESTAMP,
+                                            (struct mwifiex_ie_types_data **)
+                                            &tsf_tlv);
+
+       /* Search the TLV buffer space in the scan response for any valid
+          TLVs */
+       mwifiex_ret_802_11_scan_get_tlv_ptrs(adapter, tlv_data, tlv_buf_size,
+                                            TLV_TYPE_CHANNELBANDLIST,
+                                            (struct mwifiex_ie_types_data **)
+                                            &chan_band_tlv);
+
+       for (idx = 0; idx < scan_rsp->number_of_sets && bytes_left; idx++) {
+               /*
+                * If the TSF TLV was appended to the scan results, save this
+                * entry's TSF value in the fw_tsf field. It is the firmware's
+                * TSF value at the time the beacon or probe response was
+                * received.
+                */
+               if (tsf_tlv)
+                       memcpy(&fw_tsf, &tsf_tlv->tsf_data[idx * TSF_DATA_SIZE],
+                              sizeof(fw_tsf));
+
+               if (chan_band_tlv) {
+                       chan_band = &chan_band_tlv->chan_band_param[idx];
+                       radio_type = &chan_band->radio_type;
+               } else {
+                       radio_type = NULL;
+               }
+
+               ret = mwifiex_parse_single_response_buf(priv, &bss_info,
+                                                       &bytes_left,
+                                                       le64_to_cpu(fw_tsf),
+                                                       radio_type, false, 0);
+               if (ret)
+                       goto check_next_scan;
+       }
+
+check_next_scan:
+       mwifiex_check_next_scan_command(priv);
+       return ret;
+}
+
+/*
+ * This function prepares an extended scan command to be sent to the firmware
+ *
+ * This uses the scan command configuration sent to the command processing
+ * module in command preparation stage to configure a extended scan command
+ * structure to send to firmware.
+ */
+int mwifiex_cmd_802_11_scan_ext(struct mwifiex_private *priv,
+                               struct host_cmd_ds_command *cmd,
+                               void *data_buf)
+{
+       struct host_cmd_ds_802_11_scan_ext *ext_scan = &cmd->params.ext_scan;
+       struct mwifiex_scan_cmd_config *scan_cfg = data_buf;
+
+       memcpy(ext_scan->tlv_buffer, scan_cfg->tlv_buf, scan_cfg->tlv_buf_len);
+
+       cmd->command = cpu_to_le16(HostCmd_CMD_802_11_SCAN_EXT);
+
+       /* Size is equal to the sizeof(fixed portions) + the TLV len + header */
+       cmd->size = cpu_to_le16((u16)(sizeof(ext_scan->reserved)
+                                     + scan_cfg->tlv_buf_len + S_DS_GEN));
+
+       return 0;
+}
+
+static void
+mwifiex_update_chan_statistics(struct mwifiex_private *priv,
+                              struct mwifiex_ietypes_chanstats *tlv_stat)
+{
+       struct mwifiex_adapter *adapter = priv->adapter;
+       u8 i, num_chan;
+       struct mwifiex_fw_chan_stats *fw_chan_stats;
+       struct mwifiex_chan_stats chan_stats;
+
+       fw_chan_stats = (void *)((u8 *)tlv_stat +
+                             sizeof(struct mwifiex_ie_types_header));
+       num_chan = le16_to_cpu(tlv_stat->header.len) /
+                                             sizeof(struct mwifiex_chan_stats);
+
+       for (i = 0 ; i < num_chan; i++) {
+               chan_stats.chan_num = fw_chan_stats->chan_num;
+               chan_stats.bandcfg = fw_chan_stats->bandcfg;
+               chan_stats.flags = fw_chan_stats->flags;
+               chan_stats.noise = fw_chan_stats->noise;
+               chan_stats.total_bss = le16_to_cpu(fw_chan_stats->total_bss);
+               chan_stats.cca_scan_dur =
+                                      le16_to_cpu(fw_chan_stats->cca_scan_dur);
+               chan_stats.cca_busy_dur =
+                                      le16_to_cpu(fw_chan_stats->cca_busy_dur);
+               mwifiex_dbg(adapter, INFO,
+                           "chan=%d, noise=%d, total_network=%d scan_duration=%d, busy_duration=%d\n",
+                           chan_stats.chan_num,
+                           chan_stats.noise,
+                           chan_stats.total_bss,
+                           chan_stats.cca_scan_dur,
+                           chan_stats.cca_busy_dur);
+               memcpy(&adapter->chan_stats[adapter->survey_idx++], &chan_stats,
+                      sizeof(struct mwifiex_chan_stats));
+               fw_chan_stats++;
+       }
+}
+
+/* This function handles the command response of extended scan */
+int mwifiex_ret_802_11_scan_ext(struct mwifiex_private *priv,
+                               struct host_cmd_ds_command *resp)
+{
+       struct mwifiex_adapter *adapter = priv->adapter;
+       struct host_cmd_ds_802_11_scan_ext *ext_scan_resp;
+       struct mwifiex_ie_types_header *tlv;
+       struct mwifiex_ietypes_chanstats *tlv_stat;
+       u16 buf_left, type, len;
+
+       struct host_cmd_ds_command *cmd_ptr;
+       struct cmd_ctrl_node *cmd_node;
+       unsigned long cmd_flags, scan_flags;
+       bool complete_scan = false;
+
+       mwifiex_dbg(adapter, INFO, "info: EXT scan returns successfully\n");
+
+       ext_scan_resp = &resp->params.ext_scan;
+
+       tlv = (void *)ext_scan_resp->tlv_buffer;
+       buf_left = le16_to_cpu(resp->size) - (sizeof(*ext_scan_resp) + S_DS_GEN
+                                             - 1);
+
+       while (buf_left >= sizeof(struct mwifiex_ie_types_header)) {
+               type = le16_to_cpu(tlv->type);
+               len = le16_to_cpu(tlv->len);
+
+               if (buf_left < (sizeof(struct mwifiex_ie_types_header) + len)) {
+                       mwifiex_dbg(adapter, ERROR,
+                                   "error processing scan response TLVs");
+                       break;
+               }
+
+               switch (type) {
+               case TLV_TYPE_CHANNEL_STATS:
+                       tlv_stat = (void *)tlv;
+                       mwifiex_update_chan_statistics(priv, tlv_stat);
+                       break;
+               default:
+                       break;
+               }
+
+               buf_left -= len + sizeof(struct mwifiex_ie_types_header);
+               tlv = (void *)((u8 *)tlv + len +
+                              sizeof(struct mwifiex_ie_types_header));
+       }
+
+       spin_lock_irqsave(&adapter->cmd_pending_q_lock, cmd_flags);
+       spin_lock_irqsave(&adapter->scan_pending_q_lock, scan_flags);
+       if (list_empty(&adapter->scan_pending_q)) {
+               complete_scan = true;
+               list_for_each_entry(cmd_node, &adapter->cmd_pending_q, list) {
+                       cmd_ptr = (void *)cmd_node->cmd_skb->data;
+                       if (le16_to_cpu(cmd_ptr->command) ==
+                           HostCmd_CMD_802_11_SCAN_EXT) {
+                               mwifiex_dbg(adapter, INFO,
+                                           "Scan pending in command pending list");
+                               complete_scan = false;
+                               break;
+                       }
+               }
+       }
+       spin_unlock_irqrestore(&adapter->scan_pending_q_lock, scan_flags);
+       spin_unlock_irqrestore(&adapter->cmd_pending_q_lock, cmd_flags);
+
+       if (complete_scan)
+               mwifiex_complete_scan(priv);
+
+       return 0;
+}
+
+/* This function This function handles the event extended scan report. It
+ * parses extended scan results and informs to cfg80211 stack.
+ */
+int mwifiex_handle_event_ext_scan_report(struct mwifiex_private *priv,
+                                        void *buf)
+{
+       int ret = 0;
+       struct mwifiex_adapter *adapter = priv->adapter;
+       u8 *bss_info;
+       u32 bytes_left, bytes_left_for_tlv, idx;
+       u16 type, len;
+       struct mwifiex_ie_types_data *tlv;
+       struct mwifiex_ie_types_bss_scan_rsp *scan_rsp_tlv;
+       struct mwifiex_ie_types_bss_scan_info *scan_info_tlv;
+       u8 *radio_type;
+       u64 fw_tsf = 0;
+       s32 rssi = 0;
+       struct mwifiex_event_scan_result *event_scan = buf;
+       u8 num_of_set = event_scan->num_of_set;
+       u8 *scan_resp = buf + sizeof(struct mwifiex_event_scan_result);
+       u16 scan_resp_size = le16_to_cpu(event_scan->buf_size);
+
+       if (num_of_set > MWIFIEX_MAX_AP) {
+               mwifiex_dbg(adapter, ERROR,
+                           "EXT_SCAN: Invalid number of AP returned (%d)!!\n",
+                           num_of_set);
+               ret = -1;
+               goto check_next_scan;
+       }
+
+       bytes_left = scan_resp_size;
+       mwifiex_dbg(adapter, INFO,
+                   "EXT_SCAN: size %d, returned %d APs...",
+                   scan_resp_size, num_of_set);
+       mwifiex_dbg_dump(adapter, CMD_D, "EXT_SCAN buffer:", buf,
+                        scan_resp_size +
+                        sizeof(struct mwifiex_event_scan_result));
+
+       tlv = (struct mwifiex_ie_types_data *)scan_resp;
+
+       for (idx = 0; idx < num_of_set && bytes_left; idx++) {
+               type = le16_to_cpu(tlv->header.type);
+               len = le16_to_cpu(tlv->header.len);
+               if (bytes_left < sizeof(struct mwifiex_ie_types_header) + len) {
+                       mwifiex_dbg(adapter, ERROR,
+                                   "EXT_SCAN: Error bytes left < TLV length\n");
+                       break;
+               }
+               scan_rsp_tlv = NULL;
+               scan_info_tlv = NULL;
+               bytes_left_for_tlv = bytes_left;
+
+               /* BSS response TLV with beacon or probe response buffer
+                * at the initial position of each descriptor
+                */
+               if (type != TLV_TYPE_BSS_SCAN_RSP)
+                       break;
+
+               bss_info = (u8 *)tlv;
+               scan_rsp_tlv = (struct mwifiex_ie_types_bss_scan_rsp *)tlv;
+               tlv = (struct mwifiex_ie_types_data *)(tlv->data + len);
+               bytes_left_for_tlv -=
+                               (len + sizeof(struct mwifiex_ie_types_header));
+
+               while (bytes_left_for_tlv >=
+                      sizeof(struct mwifiex_ie_types_header) &&
+                      le16_to_cpu(tlv->header.type) != TLV_TYPE_BSS_SCAN_RSP) {
+                       type = le16_to_cpu(tlv->header.type);
+                       len = le16_to_cpu(tlv->header.len);
+                       if (bytes_left_for_tlv <
+                           sizeof(struct mwifiex_ie_types_header) + len) {
+                               mwifiex_dbg(adapter, ERROR,
+                                           "EXT_SCAN: Error in processing TLV,\t"
+                                           "bytes left < TLV length\n");
+                               scan_rsp_tlv = NULL;
+                               bytes_left_for_tlv = 0;
+                               continue;
+                       }
+                       switch (type) {
+                       case TLV_TYPE_BSS_SCAN_INFO:
+                               scan_info_tlv =
+                                 (struct mwifiex_ie_types_bss_scan_info *)tlv;
+                               if (len !=
+                                sizeof(struct mwifiex_ie_types_bss_scan_info) -
+                                sizeof(struct mwifiex_ie_types_header)) {
+                                       bytes_left_for_tlv = 0;
+                                       continue;
+                               }
+                               break;
+                       default:
+                               break;
+                       }
+                       tlv = (struct mwifiex_ie_types_data *)(tlv->data + len);
+                       bytes_left -=
+                               (len + sizeof(struct mwifiex_ie_types_header));
+                       bytes_left_for_tlv -=
+                               (len + sizeof(struct mwifiex_ie_types_header));
+               }
+
+               if (!scan_rsp_tlv)
+                       break;
+
+               /* Advance pointer to the beacon buffer length and
+                * update the bytes count so that the function
+                * wlan_interpret_bss_desc_with_ie() can handle the
+                * scan buffer withut any change
+                */
+               bss_info += sizeof(u16);
+               bytes_left -= sizeof(u16);
+
+               if (scan_info_tlv) {
+                       rssi = (s32)(s16)(le16_to_cpu(scan_info_tlv->rssi));
+                       rssi *= 100;           /* Convert dBm to mBm */
+                       mwifiex_dbg(adapter, INFO,
+                                   "info: InterpretIE: RSSI=%d\n", rssi);
+                       fw_tsf = le64_to_cpu(scan_info_tlv->tsf);
+                       radio_type = &scan_info_tlv->radio_type;
+               } else {
+                       radio_type = NULL;
+               }
+               ret = mwifiex_parse_single_response_buf(priv, &bss_info,
+                                                       &bytes_left, fw_tsf,
+                                                       radio_type, true, rssi);
+               if (ret)
+                       goto check_next_scan;
+       }
+
+check_next_scan:
+       if (!event_scan->more_event)
+               mwifiex_check_next_scan_command(priv);
+
+       return ret;
+}
+
+/*
+ * This function prepares command for background scan query.
+ *
+ * Preparation includes -
+ *      - Setting command ID and proper size
+ *      - Setting background scan flush parameter
+ *      - Ensuring correct endian-ness
+ */
+int mwifiex_cmd_802_11_bg_scan_query(struct host_cmd_ds_command *cmd)
+{
+       struct host_cmd_ds_802_11_bg_scan_query *bg_query =
+               &cmd->params.bg_scan_query;
+
+       cmd->command = cpu_to_le16(HostCmd_CMD_802_11_BG_SCAN_QUERY);
+       cmd->size = cpu_to_le16(sizeof(struct host_cmd_ds_802_11_bg_scan_query)
+                               + S_DS_GEN);
+
+       bg_query->flush = 1;
+
+       return 0;
+}
+
+/*
+ * This function inserts scan command node to the scan pending queue.
+ */
+void
+mwifiex_queue_scan_cmd(struct mwifiex_private *priv,
+                      struct cmd_ctrl_node *cmd_node)
+{
+       struct mwifiex_adapter *adapter = priv->adapter;
+       unsigned long flags;
+
+       cmd_node->wait_q_enabled = true;
+       cmd_node->condition = &adapter->scan_wait_q_woken;
+       spin_lock_irqsave(&adapter->scan_pending_q_lock, flags);
+       list_add_tail(&cmd_node->list, &adapter->scan_pending_q);
+       spin_unlock_irqrestore(&adapter->scan_pending_q_lock, flags);
+}
+
+/*
+ * This function sends a scan command for all available channels to the
+ * firmware, filtered on a specific SSID.
+ */
+static int mwifiex_scan_specific_ssid(struct mwifiex_private *priv,
+                                     struct cfg80211_ssid *req_ssid)
+{
+       struct mwifiex_adapter *adapter = priv->adapter;
+       int ret;
+       struct mwifiex_user_scan_cfg *scan_cfg;
+
+       if (adapter->scan_processing) {
+               mwifiex_dbg(adapter, WARN,
+                           "cmd: Scan already in process...\n");
+               return -EBUSY;
+       }
+
+       if (priv->scan_block) {
+               mwifiex_dbg(adapter, WARN,
+                           "cmd: Scan is blocked during association...\n");
+               return -EBUSY;
+       }
+
+       scan_cfg = kzalloc(sizeof(struct mwifiex_user_scan_cfg), GFP_KERNEL);
+       if (!scan_cfg)
+               return -ENOMEM;
+
+       scan_cfg->ssid_list = req_ssid;
+       scan_cfg->num_ssids = 1;
+
+       ret = mwifiex_scan_networks(priv, scan_cfg);
+
+       kfree(scan_cfg);
+       return ret;
+}
+
+/*
+ * Sends IOCTL request to start a scan.
+ *
+ * This function allocates the IOCTL request buffer, fills it
+ * with requisite parameters and calls the IOCTL handler.
+ *
+ * Scan command can be issued for both normal scan and specific SSID
+ * scan, depending upon whether an SSID is provided or not.
+ */
+int mwifiex_request_scan(struct mwifiex_private *priv,
+                        struct cfg80211_ssid *req_ssid)
+{
+       int ret;
+
+       if (down_interruptible(&priv->async_sem)) {
+               mwifiex_dbg(priv->adapter, ERROR,
+                           "%s: acquire semaphore fail\n",
+                           __func__);
+               return -1;
+       }
+
+       priv->adapter->scan_wait_q_woken = false;
+
+       if (req_ssid && req_ssid->ssid_len != 0)
+               /* Specific SSID scan */
+               ret = mwifiex_scan_specific_ssid(priv, req_ssid);
+       else
+               /* Normal scan */
+               ret = mwifiex_scan_networks(priv, NULL);
+
+       up(&priv->async_sem);
+
+       return ret;
+}
+
+/*
+ * This function appends the vendor specific IE TLV to a buffer.
+ */
+int
+mwifiex_cmd_append_vsie_tlv(struct mwifiex_private *priv,
+                           u16 vsie_mask, u8 **buffer)
+{
+       int id, ret_len = 0;
+       struct mwifiex_ie_types_vendor_param_set *vs_param_set;
+
+       if (!buffer)
+               return 0;
+       if (!(*buffer))
+               return 0;
+
+       /*
+        * Traverse through the saved vendor specific IE array and append
+        * the selected(scan/assoc/adhoc) IE as TLV to the command
+        */
+       for (id = 0; id < MWIFIEX_MAX_VSIE_NUM; id++) {
+               if (priv->vs_ie[id].mask & vsie_mask) {
+                       vs_param_set =
+                               (struct mwifiex_ie_types_vendor_param_set *)
+                               *buffer;
+                       vs_param_set->header.type =
+                               cpu_to_le16(TLV_TYPE_PASSTHROUGH);
+                       vs_param_set->header.len =
+                               cpu_to_le16((((u16) priv->vs_ie[id].ie[1])
+                               & 0x00FF) + 2);
+                       memcpy(vs_param_set->ie, priv->vs_ie[id].ie,
+                              le16_to_cpu(vs_param_set->header.len));
+                       *buffer += le16_to_cpu(vs_param_set->header.len) +
+                                  sizeof(struct mwifiex_ie_types_header);
+                       ret_len += le16_to_cpu(vs_param_set->header.len) +
+                                  sizeof(struct mwifiex_ie_types_header);
+               }
+       }
+       return ret_len;
+}
+
+/*
+ * This function saves a beacon buffer of the current BSS descriptor.
+ *
+ * The current beacon buffer is saved so that it can be restored in the
+ * following cases that makes the beacon buffer not to contain the current
+ * ssid's beacon buffer.
+ *      - The current ssid was not found somehow in the last scan.
+ *      - The current ssid was the last entry of the scan table and overloaded.
+ */
+void
+mwifiex_save_curr_bcn(struct mwifiex_private *priv)
+{
+       struct mwifiex_bssdescriptor *curr_bss =
+               &priv->curr_bss_params.bss_descriptor;
+
+       if (!curr_bss->beacon_buf_size)
+               return;
+
+       /* allocate beacon buffer at 1st time; or if it's size has changed */
+       if (!priv->curr_bcn_buf ||
+           priv->curr_bcn_size != curr_bss->beacon_buf_size) {
+               priv->curr_bcn_size = curr_bss->beacon_buf_size;
+
+               kfree(priv->curr_bcn_buf);
+               priv->curr_bcn_buf = kmalloc(curr_bss->beacon_buf_size,
+                                            GFP_ATOMIC);
+               if (!priv->curr_bcn_buf)
+                       return;
+       }
+
+       memcpy(priv->curr_bcn_buf, curr_bss->beacon_buf,
+              curr_bss->beacon_buf_size);
+       mwifiex_dbg(priv->adapter, INFO,
+                   "info: current beacon saved %d\n",
+                   priv->curr_bcn_size);
+
+       curr_bss->beacon_buf = priv->curr_bcn_buf;
+
+       /* adjust the pointers in the current BSS descriptor */
+       if (curr_bss->bcn_wpa_ie)
+               curr_bss->bcn_wpa_ie =
+                       (struct ieee_types_vendor_specific *)
+                       (curr_bss->beacon_buf +
+                        curr_bss->wpa_offset);
+
+       if (curr_bss->bcn_rsn_ie)
+               curr_bss->bcn_rsn_ie = (struct ieee_types_generic *)
+                       (curr_bss->beacon_buf +
+                        curr_bss->rsn_offset);
+
+       if (curr_bss->bcn_ht_cap)
+               curr_bss->bcn_ht_cap = (struct ieee80211_ht_cap *)
+                       (curr_bss->beacon_buf +
+                        curr_bss->ht_cap_offset);
+
+       if (curr_bss->bcn_ht_oper)
+               curr_bss->bcn_ht_oper = (struct ieee80211_ht_operation *)
+                       (curr_bss->beacon_buf +
+                        curr_bss->ht_info_offset);
+
+       if (curr_bss->bcn_vht_cap)
+               curr_bss->bcn_vht_cap = (void *)(curr_bss->beacon_buf +
+                                                curr_bss->vht_cap_offset);
+
+       if (curr_bss->bcn_vht_oper)
+               curr_bss->bcn_vht_oper = (void *)(curr_bss->beacon_buf +
+                                                 curr_bss->vht_info_offset);
+
+       if (curr_bss->bcn_bss_co_2040)
+               curr_bss->bcn_bss_co_2040 =
+                       (curr_bss->beacon_buf + curr_bss->bss_co_2040_offset);
+
+       if (curr_bss->bcn_ext_cap)
+               curr_bss->bcn_ext_cap = curr_bss->beacon_buf +
+                       curr_bss->ext_cap_offset;
+
+       if (curr_bss->oper_mode)
+               curr_bss->oper_mode = (void *)(curr_bss->beacon_buf +
+                                              curr_bss->oper_mode_offset);
+}
+
+/*
+ * This function frees the current BSS descriptor beacon buffer.
+ */
+void
+mwifiex_free_curr_bcn(struct mwifiex_private *priv)
+{
+       kfree(priv->curr_bcn_buf);
+       priv->curr_bcn_buf = NULL;
+}
diff --git a/drivers/net/wireless/marvell/mwifiex/sdio.c b/drivers/net/wireless/marvell/mwifiex/sdio.c
new file mode 100644 (file)
index 0000000..78a8474
--- /dev/null
@@ -0,0 +1,2684 @@
+/*
+ * Marvell Wireless LAN device driver: SDIO specific handling
+ *
+ * Copyright (C) 2011-2014, Marvell International Ltd.
+ *
+ * This software file (the "File") is distributed by Marvell International
+ * Ltd. under the terms of the GNU General Public License Version 2, June 1991
+ * (the "License").  You may use, redistribute and/or modify this File in
+ * accordance with the terms and conditions of the License, a copy of which
+ * is available by writing to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the
+ * worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
+ *
+ * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
+ * ARE EXPRESSLY DISCLAIMED.  The License provides additional details about
+ * this warranty disclaimer.
+ */
+
+#include <linux/firmware.h>
+
+#include "decl.h"
+#include "ioctl.h"
+#include "util.h"
+#include "fw.h"
+#include "main.h"
+#include "wmm.h"
+#include "11n.h"
+#include "sdio.h"
+
+
+#define SDIO_VERSION   "1.0"
+
+/* The mwifiex_sdio_remove() callback function is called when
+ * user removes this module from kernel space or ejects
+ * the card from the slot. The driver handles these 2 cases
+ * differently.
+ * If the user is removing the module, the few commands (FUNC_SHUTDOWN,
+ * HS_CANCEL etc.) are sent to the firmware.
+ * If the card is removed, there is no need to send these command.
+ *
+ * The variable 'user_rmmod' is used to distinguish these two
+ * scenarios. This flag is initialized as FALSE in case the card
+ * is removed, and will be set to TRUE for module removal when
+ * module_exit function is called.
+ */
+static u8 user_rmmod;
+
+static struct mwifiex_if_ops sdio_ops;
+static unsigned long iface_work_flags;
+
+static struct semaphore add_remove_card_sem;
+
+static struct memory_type_mapping generic_mem_type_map[] = {
+       {"DUMP", NULL, 0, 0xDD},
+};
+
+static struct memory_type_mapping mem_type_mapping_tbl[] = {
+       {"ITCM", NULL, 0, 0xF0},
+       {"DTCM", NULL, 0, 0xF1},
+       {"SQRAM", NULL, 0, 0xF2},
+       {"APU", NULL, 0, 0xF3},
+       {"CIU", NULL, 0, 0xF4},
+       {"ICU", NULL, 0, 0xF5},
+       {"MAC", NULL, 0, 0xF6},
+       {"EXT7", NULL, 0, 0xF7},
+       {"EXT8", NULL, 0, 0xF8},
+       {"EXT9", NULL, 0, 0xF9},
+       {"EXT10", NULL, 0, 0xFA},
+       {"EXT11", NULL, 0, 0xFB},
+       {"EXT12", NULL, 0, 0xFC},
+       {"EXT13", NULL, 0, 0xFD},
+       {"EXTLAST", NULL, 0, 0xFE},
+};
+
+/*
+ * SDIO probe.
+ *
+ * This function probes an mwifiex device and registers it. It allocates
+ * the card structure, enables SDIO function number and initiates the
+ * device registration and initialization procedure by adding a logical
+ * interface.
+ */
+static int
+mwifiex_sdio_probe(struct sdio_func *func, const struct sdio_device_id *id)
+{
+       int ret;
+       struct sdio_mmc_card *card = NULL;
+
+       pr_debug("info: vendor=0x%4.04X device=0x%4.04X class=%d function=%d\n",
+                func->vendor, func->device, func->class, func->num);
+
+       card = kzalloc(sizeof(struct sdio_mmc_card), GFP_KERNEL);
+       if (!card)
+               return -ENOMEM;
+
+       card->func = func;
+       card->device_id = id;
+
+       func->card->quirks |= MMC_QUIRK_BLKSZ_FOR_BYTE_MODE;
+
+       if (id->driver_data) {
+               struct mwifiex_sdio_device *data = (void *)id->driver_data;
+
+               card->firmware = data->firmware;
+               card->reg = data->reg;
+               card->max_ports = data->max_ports;
+               card->mp_agg_pkt_limit = data->mp_agg_pkt_limit;
+               card->supports_sdio_new_mode = data->supports_sdio_new_mode;
+               card->has_control_mask = data->has_control_mask;
+               card->tx_buf_size = data->tx_buf_size;
+               card->mp_tx_agg_buf_size = data->mp_tx_agg_buf_size;
+               card->mp_rx_agg_buf_size = data->mp_rx_agg_buf_size;
+               card->can_dump_fw = data->can_dump_fw;
+               card->fw_dump_enh = data->fw_dump_enh;
+               card->can_auto_tdls = data->can_auto_tdls;
+               card->can_ext_scan = data->can_ext_scan;
+       }
+
+       sdio_claim_host(func);
+       ret = sdio_enable_func(func);
+       sdio_release_host(func);
+
+       if (ret) {
+               pr_err("%s: failed to enable function\n", __func__);
+               kfree(card);
+               return -EIO;
+       }
+
+       if (mwifiex_add_card(card, &add_remove_card_sem, &sdio_ops,
+                            MWIFIEX_SDIO)) {
+               pr_err("%s: add card failed\n", __func__);
+               kfree(card);
+               sdio_claim_host(func);
+               ret = sdio_disable_func(func);
+               sdio_release_host(func);
+               ret = -1;
+       }
+
+       return ret;
+}
+
+/*
+ * SDIO resume.
+ *
+ * Kernel needs to suspend all functions separately. Therefore all
+ * registered functions must have drivers with suspend and resume
+ * methods. Failing that the kernel simply removes the whole card.
+ *
+ * If already not resumed, this function turns on the traffic and
+ * sends a host sleep cancel request to the firmware.
+ */
+static int mwifiex_sdio_resume(struct device *dev)
+{
+       struct sdio_func *func = dev_to_sdio_func(dev);
+       struct sdio_mmc_card *card;
+       struct mwifiex_adapter *adapter;
+       mmc_pm_flag_t pm_flag = 0;
+
+       if (func) {
+               pm_flag = sdio_get_host_pm_caps(func);
+               card = sdio_get_drvdata(func);
+               if (!card || !card->adapter) {
+                       pr_err("resume: invalid card or adapter\n");
+                       return 0;
+               }
+       } else {
+               pr_err("resume: sdio_func is not specified\n");
+               return 0;
+       }
+
+       adapter = card->adapter;
+
+       if (!adapter->is_suspended) {
+               mwifiex_dbg(adapter, WARN,
+                           "device already resumed\n");
+               return 0;
+       }
+
+       adapter->is_suspended = false;
+
+       /* Disable Host Sleep */
+       mwifiex_cancel_hs(mwifiex_get_priv(adapter, MWIFIEX_BSS_ROLE_STA),
+                         MWIFIEX_ASYNC_CMD);
+
+       return 0;
+}
+
+/*
+ * SDIO remove.
+ *
+ * This function removes the interface and frees up the card structure.
+ */
+static void
+mwifiex_sdio_remove(struct sdio_func *func)
+{
+       struct sdio_mmc_card *card;
+       struct mwifiex_adapter *adapter;
+       struct mwifiex_private *priv;
+
+       card = sdio_get_drvdata(func);
+       if (!card)
+               return;
+
+       adapter = card->adapter;
+       if (!adapter || !adapter->priv_num)
+               return;
+
+       mwifiex_dbg(adapter, INFO, "info: SDIO func num=%d\n", func->num);
+
+       if (user_rmmod) {
+               if (adapter->is_suspended)
+                       mwifiex_sdio_resume(adapter->dev);
+
+               mwifiex_deauthenticate_all(adapter);
+
+               priv = mwifiex_get_priv(adapter, MWIFIEX_BSS_ROLE_ANY);
+               mwifiex_disable_auto_ds(priv);
+               mwifiex_init_shutdown_fw(priv, MWIFIEX_FUNC_SHUTDOWN);
+       }
+
+       mwifiex_remove_card(card->adapter, &add_remove_card_sem);
+}
+
+/*
+ * SDIO suspend.
+ *
+ * Kernel needs to suspend all functions separately. Therefore all
+ * registered functions must have drivers with suspend and resume
+ * methods. Failing that the kernel simply removes the whole card.
+ *
+ * If already not suspended, this function allocates and sends a host
+ * sleep activate request to the firmware and turns off the traffic.
+ */
+static int mwifiex_sdio_suspend(struct device *dev)
+{
+       struct sdio_func *func = dev_to_sdio_func(dev);
+       struct sdio_mmc_card *card;
+       struct mwifiex_adapter *adapter;
+       mmc_pm_flag_t pm_flag = 0;
+       int ret = 0;
+
+       if (func) {
+               pm_flag = sdio_get_host_pm_caps(func);
+               pr_debug("cmd: %s: suspend: PM flag = 0x%x\n",
+                        sdio_func_id(func), pm_flag);
+               if (!(pm_flag & MMC_PM_KEEP_POWER)) {
+                       pr_err("%s: cannot remain alive while host is"
+                               " suspended\n", sdio_func_id(func));
+                       return -ENOSYS;
+               }
+
+               card = sdio_get_drvdata(func);
+               if (!card || !card->adapter) {
+                       pr_err("suspend: invalid card or adapter\n");
+                       return 0;
+               }
+       } else {
+               pr_err("suspend: sdio_func is not specified\n");
+               return 0;
+       }
+
+       adapter = card->adapter;
+
+       /* Enable the Host Sleep */
+       if (!mwifiex_enable_hs(adapter)) {
+               mwifiex_dbg(adapter, ERROR,
+                           "cmd: failed to suspend\n");
+               adapter->hs_enabling = false;
+               return -EFAULT;
+       }
+
+       mwifiex_dbg(adapter, INFO,
+                   "cmd: suspend with MMC_PM_KEEP_POWER\n");
+       ret = sdio_set_host_pm_flags(func, MMC_PM_KEEP_POWER);
+
+       /* Indicate device suspended */
+       adapter->is_suspended = true;
+       adapter->hs_enabling = false;
+
+       return ret;
+}
+
+/* Device ID for SD8786 */
+#define SDIO_DEVICE_ID_MARVELL_8786   (0x9116)
+/* Device ID for SD8787 */
+#define SDIO_DEVICE_ID_MARVELL_8787   (0x9119)
+/* Device ID for SD8797 */
+#define SDIO_DEVICE_ID_MARVELL_8797   (0x9129)
+/* Device ID for SD8897 */
+#define SDIO_DEVICE_ID_MARVELL_8897   (0x912d)
+/* Device ID for SD8887 */
+#define SDIO_DEVICE_ID_MARVELL_8887   (0x9135)
+/* Device ID for SD8801 */
+#define SDIO_DEVICE_ID_MARVELL_8801   (0x9139)
+/* Device ID for SD8997 */
+#define SDIO_DEVICE_ID_MARVELL_8997   (0x9141)
+
+
+/* WLAN IDs */
+static const struct sdio_device_id mwifiex_ids[] = {
+       {SDIO_DEVICE(SDIO_VENDOR_ID_MARVELL, SDIO_DEVICE_ID_MARVELL_8786),
+               .driver_data = (unsigned long) &mwifiex_sdio_sd8786},
+       {SDIO_DEVICE(SDIO_VENDOR_ID_MARVELL, SDIO_DEVICE_ID_MARVELL_8787),
+               .driver_data = (unsigned long) &mwifiex_sdio_sd8787},
+       {SDIO_DEVICE(SDIO_VENDOR_ID_MARVELL, SDIO_DEVICE_ID_MARVELL_8797),
+               .driver_data = (unsigned long) &mwifiex_sdio_sd8797},
+       {SDIO_DEVICE(SDIO_VENDOR_ID_MARVELL, SDIO_DEVICE_ID_MARVELL_8897),
+               .driver_data = (unsigned long) &mwifiex_sdio_sd8897},
+       {SDIO_DEVICE(SDIO_VENDOR_ID_MARVELL, SDIO_DEVICE_ID_MARVELL_8887),
+               .driver_data = (unsigned long)&mwifiex_sdio_sd8887},
+       {SDIO_DEVICE(SDIO_VENDOR_ID_MARVELL, SDIO_DEVICE_ID_MARVELL_8801),
+               .driver_data = (unsigned long)&mwifiex_sdio_sd8801},
+       {SDIO_DEVICE(SDIO_VENDOR_ID_MARVELL, SDIO_DEVICE_ID_MARVELL_8997),
+               .driver_data = (unsigned long)&mwifiex_sdio_sd8997},
+       {},
+};
+
+MODULE_DEVICE_TABLE(sdio, mwifiex_ids);
+
+static const struct dev_pm_ops mwifiex_sdio_pm_ops = {
+       .suspend = mwifiex_sdio_suspend,
+       .resume = mwifiex_sdio_resume,
+};
+
+static struct sdio_driver mwifiex_sdio = {
+       .name = "mwifiex_sdio",
+       .id_table = mwifiex_ids,
+       .probe = mwifiex_sdio_probe,
+       .remove = mwifiex_sdio_remove,
+       .drv = {
+               .owner = THIS_MODULE,
+               .pm = &mwifiex_sdio_pm_ops,
+       }
+};
+
+/* Write data into SDIO card register. Caller claims SDIO device. */
+static int
+mwifiex_write_reg_locked(struct sdio_func *func, u32 reg, u8 data)
+{
+       int ret = -1;
+       sdio_writeb(func, data, reg, &ret);
+       return ret;
+}
+
+/*
+ * This function writes data into SDIO card register.
+ */
+static int
+mwifiex_write_reg(struct mwifiex_adapter *adapter, u32 reg, u8 data)
+{
+       struct sdio_mmc_card *card = adapter->card;
+       int ret;
+
+       sdio_claim_host(card->func);
+       ret = mwifiex_write_reg_locked(card->func, reg, data);
+       sdio_release_host(card->func);
+
+       return ret;
+}
+
+/*
+ * This function reads data from SDIO card register.
+ */
+static int
+mwifiex_read_reg(struct mwifiex_adapter *adapter, u32 reg, u8 *data)
+{
+       struct sdio_mmc_card *card = adapter->card;
+       int ret = -1;
+       u8 val;
+
+       sdio_claim_host(card->func);
+       val = sdio_readb(card->func, reg, &ret);
+       sdio_release_host(card->func);
+
+       *data = val;
+
+       return ret;
+}
+
+/*
+ * This function writes multiple data into SDIO card memory.
+ *
+ * This does not work in suspended mode.
+ */
+static int
+mwifiex_write_data_sync(struct mwifiex_adapter *adapter,
+                       u8 *buffer, u32 pkt_len, u32 port)
+{
+       struct sdio_mmc_card *card = adapter->card;
+       int ret;
+       u8 blk_mode =
+               (port & MWIFIEX_SDIO_BYTE_MODE_MASK) ? BYTE_MODE : BLOCK_MODE;
+       u32 blk_size = (blk_mode == BLOCK_MODE) ? MWIFIEX_SDIO_BLOCK_SIZE : 1;
+       u32 blk_cnt =
+               (blk_mode ==
+                BLOCK_MODE) ? (pkt_len /
+                               MWIFIEX_SDIO_BLOCK_SIZE) : pkt_len;
+       u32 ioport = (port & MWIFIEX_SDIO_IO_PORT_MASK);
+
+       if (adapter->is_suspended) {
+               mwifiex_dbg(adapter, ERROR,
+                           "%s: not allowed while suspended\n", __func__);
+               return -1;
+       }
+
+       sdio_claim_host(card->func);
+
+       ret = sdio_writesb(card->func, ioport, buffer, blk_cnt * blk_size);
+
+       sdio_release_host(card->func);
+
+       return ret;
+}
+
+/*
+ * This function reads multiple data from SDIO card memory.
+ */
+static int mwifiex_read_data_sync(struct mwifiex_adapter *adapter, u8 *buffer,
+                                 u32 len, u32 port, u8 claim)
+{
+       struct sdio_mmc_card *card = adapter->card;
+       int ret;
+       u8 blk_mode = (port & MWIFIEX_SDIO_BYTE_MODE_MASK) ? BYTE_MODE
+                      : BLOCK_MODE;
+       u32 blk_size = (blk_mode == BLOCK_MODE) ? MWIFIEX_SDIO_BLOCK_SIZE : 1;
+       u32 blk_cnt = (blk_mode == BLOCK_MODE) ? (len / MWIFIEX_SDIO_BLOCK_SIZE)
+                       : len;
+       u32 ioport = (port & MWIFIEX_SDIO_IO_PORT_MASK);
+
+       if (claim)
+               sdio_claim_host(card->func);
+
+       ret = sdio_readsb(card->func, buffer, ioport, blk_cnt * blk_size);
+
+       if (claim)
+               sdio_release_host(card->func);
+
+       return ret;
+}
+
+/*
+ * This function wakes up the card.
+ *
+ * A host power up command is written to the card configuration
+ * register to wake up the card.
+ */
+static int mwifiex_pm_wakeup_card(struct mwifiex_adapter *adapter)
+{
+       mwifiex_dbg(adapter, EVENT,
+                   "event: wakeup device...\n");
+
+       return mwifiex_write_reg(adapter, CONFIGURATION_REG, HOST_POWER_UP);
+}
+
+/*
+ * This function is called after the card has woken up.
+ *
+ * The card configuration register is reset.
+ */
+static int mwifiex_pm_wakeup_card_complete(struct mwifiex_adapter *adapter)
+{
+       mwifiex_dbg(adapter, EVENT,
+                   "cmd: wakeup device completed\n");
+
+       return mwifiex_write_reg(adapter, CONFIGURATION_REG, 0);
+}
+
+/*
+ * This function is used to initialize IO ports for the
+ * chipsets supporting SDIO new mode eg SD8897.
+ */
+static int mwifiex_init_sdio_new_mode(struct mwifiex_adapter *adapter)
+{
+       u8 reg;
+       struct sdio_mmc_card *card = adapter->card;
+
+       adapter->ioport = MEM_PORT;
+
+       /* enable sdio new mode */
+       if (mwifiex_read_reg(adapter, card->reg->card_cfg_2_1_reg, &reg))
+               return -1;
+       if (mwifiex_write_reg(adapter, card->reg->card_cfg_2_1_reg,
+                             reg | CMD53_NEW_MODE))
+               return -1;
+
+       /* Configure cmd port and enable reading rx length from the register */
+       if (mwifiex_read_reg(adapter, card->reg->cmd_cfg_0, &reg))
+               return -1;
+       if (mwifiex_write_reg(adapter, card->reg->cmd_cfg_0,
+                             reg | CMD_PORT_RD_LEN_EN))
+               return -1;
+
+       /* Enable Dnld/Upld ready auto reset for cmd port after cmd53 is
+        * completed
+        */
+       if (mwifiex_read_reg(adapter, card->reg->cmd_cfg_1, &reg))
+               return -1;
+       if (mwifiex_write_reg(adapter, card->reg->cmd_cfg_1,
+                             reg | CMD_PORT_AUTO_EN))
+               return -1;
+
+       return 0;
+}
+
+/* This function initializes the IO ports.
+ *
+ * The following operations are performed -
+ *      - Read the IO ports (0, 1 and 2)
+ *      - Set host interrupt Reset-To-Read to clear
+ *      - Set auto re-enable interrupt
+ */
+static int mwifiex_init_sdio_ioport(struct mwifiex_adapter *adapter)
+{
+       u8 reg;
+       struct sdio_mmc_card *card = adapter->card;
+
+       adapter->ioport = 0;
+
+       if (card->supports_sdio_new_mode) {
+               if (mwifiex_init_sdio_new_mode(adapter))
+                       return -1;
+               goto cont;
+       }
+
+       /* Read the IO port */
+       if (!mwifiex_read_reg(adapter, card->reg->io_port_0_reg, &reg))
+               adapter->ioport |= (reg & 0xff);
+       else
+               return -1;
+
+       if (!mwifiex_read_reg(adapter, card->reg->io_port_1_reg, &reg))
+               adapter->ioport |= ((reg & 0xff) << 8);
+       else
+               return -1;
+
+       if (!mwifiex_read_reg(adapter, card->reg->io_port_2_reg, &reg))
+               adapter->ioport |= ((reg & 0xff) << 16);
+       else
+               return -1;
+cont:
+       mwifiex_dbg(adapter, INFO,
+                   "info: SDIO FUNC1 IO port: %#x\n", adapter->ioport);
+
+       /* Set Host interrupt reset to read to clear */
+       if (!mwifiex_read_reg(adapter, card->reg->host_int_rsr_reg, &reg))
+               mwifiex_write_reg(adapter, card->reg->host_int_rsr_reg,
+                                 reg | card->reg->sdio_int_mask);
+       else
+               return -1;
+
+       /* Dnld/Upld ready set to auto reset */
+       if (!mwifiex_read_reg(adapter, card->reg->card_misc_cfg_reg, &reg))
+               mwifiex_write_reg(adapter, card->reg->card_misc_cfg_reg,
+                                 reg | AUTO_RE_ENABLE_INT);
+       else
+               return -1;
+
+       return 0;
+}
+
+/*
+ * This function sends data to the card.
+ */
+static int mwifiex_write_data_to_card(struct mwifiex_adapter *adapter,
+                                     u8 *payload, u32 pkt_len, u32 port)
+{
+       u32 i = 0;
+       int ret;
+
+       do {
+               ret = mwifiex_write_data_sync(adapter, payload, pkt_len, port);
+               if (ret) {
+                       i++;
+                       mwifiex_dbg(adapter, ERROR,
+                                   "host_to_card, write iomem\t"
+                                   "(%d) failed: %d\n", i, ret);
+                       if (mwifiex_write_reg(adapter, CONFIGURATION_REG, 0x04))
+                               mwifiex_dbg(adapter, ERROR,
+                                           "write CFG reg failed\n");
+
+                       ret = -1;
+                       if (i > MAX_WRITE_IOMEM_RETRY)
+                               return ret;
+               }
+       } while (ret == -1);
+
+       return ret;
+}
+
+/*
+ * This function gets the read port.
+ *
+ * If control port bit is set in MP read bitmap, the control port
+ * is returned, otherwise the current read port is returned and
+ * the value is increased (provided it does not reach the maximum
+ * limit, in which case it is reset to 1)
+ */
+static int mwifiex_get_rd_port(struct mwifiex_adapter *adapter, u8 *port)
+{
+       struct sdio_mmc_card *card = adapter->card;
+       const struct mwifiex_sdio_card_reg *reg = card->reg;
+       u32 rd_bitmap = card->mp_rd_bitmap;
+
+       mwifiex_dbg(adapter, DATA,
+                   "data: mp_rd_bitmap=0x%08x\n", rd_bitmap);
+
+       if (card->supports_sdio_new_mode) {
+               if (!(rd_bitmap & reg->data_port_mask))
+                       return -1;
+       } else {
+               if (!(rd_bitmap & (CTRL_PORT_MASK | reg->data_port_mask)))
+                       return -1;
+       }
+
+       if ((card->has_control_mask) &&
+           (card->mp_rd_bitmap & CTRL_PORT_MASK)) {
+               card->mp_rd_bitmap &= (u32) (~CTRL_PORT_MASK);
+               *port = CTRL_PORT;
+               mwifiex_dbg(adapter, DATA,
+                           "data: port=%d mp_rd_bitmap=0x%08x\n",
+                           *port, card->mp_rd_bitmap);
+               return 0;
+       }
+
+       if (!(card->mp_rd_bitmap & (1 << card->curr_rd_port)))
+               return -1;
+
+       /* We are now handling the SDIO data ports */
+       card->mp_rd_bitmap &= (u32)(~(1 << card->curr_rd_port));
+       *port = card->curr_rd_port;
+
+       if (++card->curr_rd_port == card->max_ports)
+               card->curr_rd_port = reg->start_rd_port;
+
+       mwifiex_dbg(adapter, DATA,
+                   "data: port=%d mp_rd_bitmap=0x%08x -> 0x%08x\n",
+                   *port, rd_bitmap, card->mp_rd_bitmap);
+
+       return 0;
+}
+
+/*
+ * This function gets the write port for data.
+ *
+ * The current write port is returned if available and the value is
+ * increased (provided it does not reach the maximum limit, in which
+ * case it is reset to 1)
+ */
+static int mwifiex_get_wr_port_data(struct mwifiex_adapter *adapter, u32 *port)
+{
+       struct sdio_mmc_card *card = adapter->card;
+       const struct mwifiex_sdio_card_reg *reg = card->reg;
+       u32 wr_bitmap = card->mp_wr_bitmap;
+
+       mwifiex_dbg(adapter, DATA,
+                   "data: mp_wr_bitmap=0x%08x\n", wr_bitmap);
+
+       if (!(wr_bitmap & card->mp_data_port_mask)) {
+               adapter->data_sent = true;
+               return -EBUSY;
+       }
+
+       if (card->mp_wr_bitmap & (1 << card->curr_wr_port)) {
+               card->mp_wr_bitmap &= (u32) (~(1 << card->curr_wr_port));
+               *port = card->curr_wr_port;
+               if (++card->curr_wr_port == card->mp_end_port)
+                       card->curr_wr_port = reg->start_wr_port;
+       } else {
+               adapter->data_sent = true;
+               return -EBUSY;
+       }
+
+       if ((card->has_control_mask) && (*port == CTRL_PORT)) {
+               mwifiex_dbg(adapter, ERROR,
+                           "invalid data port=%d cur port=%d mp_wr_bitmap=0x%08x -> 0x%08x\n",
+                           *port, card->curr_wr_port, wr_bitmap,
+                           card->mp_wr_bitmap);
+               return -1;
+       }
+
+       mwifiex_dbg(adapter, DATA,
+                   "data: port=%d mp_wr_bitmap=0x%08x -> 0x%08x\n",
+                   *port, wr_bitmap, card->mp_wr_bitmap);
+
+       return 0;
+}
+
+/*
+ * This function polls the card status.
+ */
+static int
+mwifiex_sdio_poll_card_status(struct mwifiex_adapter *adapter, u8 bits)
+{
+       struct sdio_mmc_card *card = adapter->card;
+       u32 tries;
+       u8 cs;
+
+       for (tries = 0; tries < MAX_POLL_TRIES; tries++) {
+               if (mwifiex_read_reg(adapter, card->reg->poll_reg, &cs))
+                       break;
+               else if ((cs & bits) == bits)
+                       return 0;
+
+               usleep_range(10, 20);
+       }
+
+       mwifiex_dbg(adapter, ERROR,
+                   "poll card status failed, tries = %d\n", tries);
+
+       return -1;
+}
+
+/*
+ * This function reads the firmware status.
+ */
+static int
+mwifiex_sdio_read_fw_status(struct mwifiex_adapter *adapter, u16 *dat)
+{
+       struct sdio_mmc_card *card = adapter->card;
+       const struct mwifiex_sdio_card_reg *reg = card->reg;
+       u8 fws0, fws1;
+
+       if (mwifiex_read_reg(adapter, reg->status_reg_0, &fws0))
+               return -1;
+
+       if (mwifiex_read_reg(adapter, reg->status_reg_1, &fws1))
+               return -1;
+
+       *dat = (u16) ((fws1 << 8) | fws0);
+
+       return 0;
+}
+
+/*
+ * This function disables the host interrupt.
+ *
+ * The host interrupt mask is read, the disable bit is reset and
+ * written back to the card host interrupt mask register.
+ */
+static void mwifiex_sdio_disable_host_int(struct mwifiex_adapter *adapter)
+{
+       struct sdio_mmc_card *card = adapter->card;
+       struct sdio_func *func = card->func;
+
+       sdio_claim_host(func);
+       mwifiex_write_reg_locked(func, card->reg->host_int_mask_reg, 0);
+       sdio_release_irq(func);
+       sdio_release_host(func);
+}
+
+/*
+ * This function reads the interrupt status from card.
+ */
+static void mwifiex_interrupt_status(struct mwifiex_adapter *adapter)
+{
+       struct sdio_mmc_card *card = adapter->card;
+       u8 sdio_ireg;
+       unsigned long flags;
+
+       if (mwifiex_read_data_sync(adapter, card->mp_regs,
+                                  card->reg->max_mp_regs,
+                                  REG_PORT | MWIFIEX_SDIO_BYTE_MODE_MASK, 0)) {
+               mwifiex_dbg(adapter, ERROR, "read mp_regs failed\n");
+               return;
+       }
+
+       sdio_ireg = card->mp_regs[card->reg->host_int_status_reg];
+       if (sdio_ireg) {
+               /*
+                * DN_LD_HOST_INT_STATUS and/or UP_LD_HOST_INT_STATUS
+                * For SDIO new mode CMD port interrupts
+                *      DN_LD_CMD_PORT_HOST_INT_STATUS and/or
+                *      UP_LD_CMD_PORT_HOST_INT_STATUS
+                * Clear the interrupt status register
+                */
+               mwifiex_dbg(adapter, INTR,
+                           "int: sdio_ireg = %#x\n", sdio_ireg);
+               spin_lock_irqsave(&adapter->int_lock, flags);
+               adapter->int_status |= sdio_ireg;
+               spin_unlock_irqrestore(&adapter->int_lock, flags);
+       }
+}
+
+/*
+ * SDIO interrupt handler.
+ *
+ * This function reads the interrupt status from firmware and handles
+ * the interrupt in current thread (ksdioirqd) right away.
+ */
+static void
+mwifiex_sdio_interrupt(struct sdio_func *func)
+{
+       struct mwifiex_adapter *adapter;
+       struct sdio_mmc_card *card;
+
+       card = sdio_get_drvdata(func);
+       if (!card || !card->adapter) {
+               pr_debug("int: func=%p card=%p adapter=%p\n",
+                        func, card, card ? card->adapter : NULL);
+               return;
+       }
+       adapter = card->adapter;
+
+       if (!adapter->pps_uapsd_mode && adapter->ps_state == PS_STATE_SLEEP)
+               adapter->ps_state = PS_STATE_AWAKE;
+
+       mwifiex_interrupt_status(adapter);
+       mwifiex_main_process(adapter);
+}
+
+/*
+ * This function enables the host interrupt.
+ *
+ * The host interrupt enable mask is written to the card
+ * host interrupt mask register.
+ */
+static int mwifiex_sdio_enable_host_int(struct mwifiex_adapter *adapter)
+{
+       struct sdio_mmc_card *card = adapter->card;
+       struct sdio_func *func = card->func;
+       int ret;
+
+       sdio_claim_host(func);
+
+       /* Request the SDIO IRQ */
+       ret = sdio_claim_irq(func, mwifiex_sdio_interrupt);
+       if (ret) {
+               mwifiex_dbg(adapter, ERROR,
+                           "claim irq failed: ret=%d\n", ret);
+               goto out;
+       }
+
+       /* Simply write the mask to the register */
+       ret = mwifiex_write_reg_locked(func, card->reg->host_int_mask_reg,
+                                      card->reg->host_int_enable);
+       if (ret) {
+               mwifiex_dbg(adapter, ERROR,
+                           "enable host interrupt failed\n");
+               sdio_release_irq(func);
+       }
+
+out:
+       sdio_release_host(func);
+       return ret;
+}
+
+/*
+ * This function sends a data buffer to the card.
+ */
+static int mwifiex_sdio_card_to_host(struct mwifiex_adapter *adapter,
+                                    u32 *type, u8 *buffer,
+                                    u32 npayload, u32 ioport)
+{
+       int ret;
+       u32 nb;
+
+       if (!buffer) {
+               mwifiex_dbg(adapter, ERROR,
+                           "%s: buffer is NULL\n", __func__);
+               return -1;
+       }
+
+       ret = mwifiex_read_data_sync(adapter, buffer, npayload, ioport, 1);
+
+       if (ret) {
+               mwifiex_dbg(adapter, ERROR,
+                           "%s: read iomem failed: %d\n", __func__,
+                       ret);
+               return -1;
+       }
+
+       nb = le16_to_cpu(*(__le16 *) (buffer));
+       if (nb > npayload) {
+               mwifiex_dbg(adapter, ERROR,
+                           "%s: invalid packet, nb=%d npayload=%d\n",
+                           __func__, nb, npayload);
+               return -1;
+       }
+
+       *type = le16_to_cpu(*(__le16 *) (buffer + 2));
+
+       return ret;
+}
+
+/*
+ * This function downloads the firmware to the card.
+ *
+ * Firmware is downloaded to the card in blocks. Every block download
+ * is tested for CRC errors, and retried a number of times before
+ * returning failure.
+ */
+static int mwifiex_prog_fw_w_helper(struct mwifiex_adapter *adapter,
+                                   struct mwifiex_fw_image *fw)
+{
+       struct sdio_mmc_card *card = adapter->card;
+       const struct mwifiex_sdio_card_reg *reg = card->reg;
+       int ret;
+       u8 *firmware = fw->fw_buf;
+       u32 firmware_len = fw->fw_len;
+       u32 offset = 0;
+       u8 base0, base1;
+       u8 *fwbuf;
+       u16 len = 0;
+       u32 txlen, tx_blocks = 0, tries;
+       u32 i = 0;
+
+       if (!firmware_len) {
+               mwifiex_dbg(adapter, ERROR,
+                           "firmware image not found! Terminating download\n");
+               return -1;
+       }
+
+       mwifiex_dbg(adapter, INFO,
+                   "info: downloading FW image (%d bytes)\n",
+                   firmware_len);
+
+       /* Assume that the allocated buffer is 8-byte aligned */
+       fwbuf = kzalloc(MWIFIEX_UPLD_SIZE, GFP_KERNEL);
+       if (!fwbuf)
+               return -ENOMEM;
+
+       sdio_claim_host(card->func);
+
+       /* Perform firmware data transfer */
+       do {
+               /* The host polls for the DN_LD_CARD_RDY and CARD_IO_READY
+                  bits */
+               ret = mwifiex_sdio_poll_card_status(adapter, CARD_IO_READY |
+                                                   DN_LD_CARD_RDY);
+               if (ret) {
+                       mwifiex_dbg(adapter, ERROR,
+                                   "FW download with helper:\t"
+                                   "poll status timeout @ %d\n", offset);
+                       goto done;
+               }
+
+               /* More data? */
+               if (offset >= firmware_len)
+                       break;
+
+               for (tries = 0; tries < MAX_POLL_TRIES; tries++) {
+                       ret = mwifiex_read_reg(adapter, reg->base_0_reg,
+                                              &base0);
+                       if (ret) {
+                               mwifiex_dbg(adapter, ERROR,
+                                           "dev BASE0 register read failed:\t"
+                                           "base0=%#04X(%d). Terminating dnld\n",
+                                           base0, base0);
+                               goto done;
+                       }
+                       ret = mwifiex_read_reg(adapter, reg->base_1_reg,
+                                              &base1);
+                       if (ret) {
+                               mwifiex_dbg(adapter, ERROR,
+                                           "dev BASE1 register read failed:\t"
+                                           "base1=%#04X(%d). Terminating dnld\n",
+                                           base1, base1);
+                               goto done;
+                       }
+                       len = (u16) (((base1 & 0xff) << 8) | (base0 & 0xff));
+
+                       if (len)
+                               break;
+
+                       usleep_range(10, 20);
+               }
+
+               if (!len) {
+                       break;
+               } else if (len > MWIFIEX_UPLD_SIZE) {
+                       mwifiex_dbg(adapter, ERROR,
+                                   "FW dnld failed @ %d, invalid length %d\n",
+                                   offset, len);
+                       ret = -1;
+                       goto done;
+               }
+
+               txlen = len;
+
+               if (len & BIT(0)) {
+                       i++;
+                       if (i > MAX_WRITE_IOMEM_RETRY) {
+                               mwifiex_dbg(adapter, ERROR,
+                                           "FW dnld failed @ %d, over max retry\n",
+                                           offset);
+                               ret = -1;
+                               goto done;
+                       }
+                       mwifiex_dbg(adapter, ERROR,
+                                   "CRC indicated by the helper:\t"
+                                   "len = 0x%04X, txlen = %d\n", len, txlen);
+                       len &= ~BIT(0);
+                       /* Setting this to 0 to resend from same offset */
+                       txlen = 0;
+               } else {
+                       i = 0;
+
+                       /* Set blocksize to transfer - checking for last
+                          block */
+                       if (firmware_len - offset < txlen)
+                               txlen = firmware_len - offset;
+
+                       tx_blocks = (txlen + MWIFIEX_SDIO_BLOCK_SIZE - 1)
+                                   / MWIFIEX_SDIO_BLOCK_SIZE;
+
+                       /* Copy payload to buffer */
+                       memmove(fwbuf, &firmware[offset], txlen);
+               }
+
+               ret = mwifiex_write_data_sync(adapter, fwbuf, tx_blocks *
+                                             MWIFIEX_SDIO_BLOCK_SIZE,
+                                             adapter->ioport);
+               if (ret) {
+                       mwifiex_dbg(adapter, ERROR,
+                                   "FW download, write iomem (%d) failed @ %d\n",
+                                   i, offset);
+                       if (mwifiex_write_reg(adapter, CONFIGURATION_REG, 0x04))
+                               mwifiex_dbg(adapter, ERROR,
+                                           "write CFG reg failed\n");
+
+                       ret = -1;
+                       goto done;
+               }
+
+               offset += txlen;
+       } while (true);
+
+       sdio_release_host(card->func);
+
+       mwifiex_dbg(adapter, MSG,
+                   "info: FW download over, size %d bytes\n", offset);
+
+       ret = 0;
+done:
+       kfree(fwbuf);
+       return ret;
+}
+
+/*
+ * This function checks the firmware status in card.
+ *
+ * The winner interface is also determined by this function.
+ */
+static int mwifiex_check_fw_status(struct mwifiex_adapter *adapter,
+                                  u32 poll_num)
+{
+       struct sdio_mmc_card *card = adapter->card;
+       int ret = 0;
+       u16 firmware_stat;
+       u32 tries;
+       u8 winner_status;
+
+       /* Wait for firmware initialization event */
+       for (tries = 0; tries < poll_num; tries++) {
+               ret = mwifiex_sdio_read_fw_status(adapter, &firmware_stat);
+               if (ret)
+                       continue;
+               if (firmware_stat == FIRMWARE_READY_SDIO) {
+                       ret = 0;
+                       break;
+               } else {
+                       msleep(100);
+                       ret = -1;
+               }
+       }
+
+       if (ret) {
+               if (mwifiex_read_reg
+                   (adapter, card->reg->status_reg_0, &winner_status))
+                       winner_status = 0;
+
+               if (winner_status)
+                       adapter->winner = 0;
+               else
+                       adapter->winner = 1;
+       }
+       return ret;
+}
+
+/*
+ * This function decode sdio aggreation pkt.
+ *
+ * Based on the the data block size and pkt_len,
+ * skb data will be decoded to few packets.
+ */
+static void mwifiex_deaggr_sdio_pkt(struct mwifiex_adapter *adapter,
+                                   struct sk_buff *skb)
+{
+       u32 total_pkt_len, pkt_len;
+       struct sk_buff *skb_deaggr;
+       u32 pkt_type;
+       u16 blk_size;
+       u8 blk_num;
+       u8 *data;
+
+       data = skb->data;
+       total_pkt_len = skb->len;
+
+       while (total_pkt_len >= (SDIO_HEADER_OFFSET + INTF_HEADER_LEN)) {
+               if (total_pkt_len < adapter->sdio_rx_block_size)
+                       break;
+               blk_num = *(data + BLOCK_NUMBER_OFFSET);
+               blk_size = adapter->sdio_rx_block_size * blk_num;
+               if (blk_size > total_pkt_len) {
+                       mwifiex_dbg(adapter, ERROR,
+                                   "%s: error in blk_size,\t"
+                                   "blk_num=%d, blk_size=%d, total_pkt_len=%d\n",
+                                   __func__, blk_num, blk_size, total_pkt_len);
+                       break;
+               }
+               pkt_len = le16_to_cpu(*(__le16 *)(data + SDIO_HEADER_OFFSET));
+               pkt_type = le16_to_cpu(*(__le16 *)(data + SDIO_HEADER_OFFSET +
+                                        2));
+               if ((pkt_len + SDIO_HEADER_OFFSET) > blk_size) {
+                       mwifiex_dbg(adapter, ERROR,
+                                   "%s: error in pkt_len,\t"
+                                   "pkt_len=%d, blk_size=%d\n",
+                                   __func__, pkt_len, blk_size);
+                       break;
+               }
+               skb_deaggr = mwifiex_alloc_dma_align_buf(pkt_len,
+                                                        GFP_KERNEL | GFP_DMA);
+               if (!skb_deaggr)
+                       break;
+               skb_put(skb_deaggr, pkt_len);
+               memcpy(skb_deaggr->data, data + SDIO_HEADER_OFFSET, pkt_len);
+               skb_pull(skb_deaggr, INTF_HEADER_LEN);
+
+               mwifiex_handle_rx_packet(adapter, skb_deaggr);
+               data += blk_size;
+               total_pkt_len -= blk_size;
+       }
+}
+
+/*
+ * This function decodes a received packet.
+ *
+ * Based on the type, the packet is treated as either a data, or
+ * a command response, or an event, and the correct handler
+ * function is invoked.
+ */
+static int mwifiex_decode_rx_packet(struct mwifiex_adapter *adapter,
+                                   struct sk_buff *skb, u32 upld_typ)
+{
+       u8 *cmd_buf;
+       __le16 *curr_ptr = (__le16 *)skb->data;
+       u16 pkt_len = le16_to_cpu(*curr_ptr);
+       struct mwifiex_rxinfo *rx_info;
+
+       if (upld_typ != MWIFIEX_TYPE_AGGR_DATA) {
+               skb_trim(skb, pkt_len);
+               skb_pull(skb, INTF_HEADER_LEN);
+       }
+
+       switch (upld_typ) {
+       case MWIFIEX_TYPE_AGGR_DATA:
+               mwifiex_dbg(adapter, INFO,
+                           "info: --- Rx: Aggr Data packet ---\n");
+               rx_info = MWIFIEX_SKB_RXCB(skb);
+               rx_info->buf_type = MWIFIEX_TYPE_AGGR_DATA;
+               if (adapter->rx_work_enabled) {
+                       skb_queue_tail(&adapter->rx_data_q, skb);
+                       atomic_inc(&adapter->rx_pending);
+                       adapter->data_received = true;
+               } else {
+                       mwifiex_deaggr_sdio_pkt(adapter, skb);
+                       dev_kfree_skb_any(skb);
+               }
+               break;
+
+       case MWIFIEX_TYPE_DATA:
+               mwifiex_dbg(adapter, DATA,
+                           "info: --- Rx: Data packet ---\n");
+               if (adapter->rx_work_enabled) {
+                       skb_queue_tail(&adapter->rx_data_q, skb);
+                       adapter->data_received = true;
+                       atomic_inc(&adapter->rx_pending);
+               } else {
+                       mwifiex_handle_rx_packet(adapter, skb);
+               }
+               break;
+
+       case MWIFIEX_TYPE_CMD:
+               mwifiex_dbg(adapter, CMD,
+                           "info: --- Rx: Cmd Response ---\n");
+               /* take care of curr_cmd = NULL case */
+               if (!adapter->curr_cmd) {
+                       cmd_buf = adapter->upld_buf;
+
+                       if (adapter->ps_state == PS_STATE_SLEEP_CFM)
+                               mwifiex_process_sleep_confirm_resp(adapter,
+                                                                  skb->data,
+                                                                  skb->len);
+
+                       memcpy(cmd_buf, skb->data,
+                              min_t(u32, MWIFIEX_SIZE_OF_CMD_BUFFER,
+                                    skb->len));
+
+                       dev_kfree_skb_any(skb);
+               } else {
+                       adapter->cmd_resp_received = true;
+                       adapter->curr_cmd->resp_skb = skb;
+               }
+               break;
+
+       case MWIFIEX_TYPE_EVENT:
+               mwifiex_dbg(adapter, EVENT,
+                           "info: --- Rx: Event ---\n");
+               adapter->event_cause = le32_to_cpu(*(__le32 *) skb->data);
+
+               if ((skb->len > 0) && (skb->len  < MAX_EVENT_SIZE))
+                       memcpy(adapter->event_body,
+                              skb->data + MWIFIEX_EVENT_HEADER_LEN,
+                              skb->len);
+
+               /* event cause has been saved to adapter->event_cause */
+               adapter->event_received = true;
+               adapter->event_skb = skb;
+
+               break;
+
+       default:
+               mwifiex_dbg(adapter, ERROR,
+                           "unknown upload type %#x\n", upld_typ);
+               dev_kfree_skb_any(skb);
+               break;
+       }
+
+       return 0;
+}
+
+/*
+ * This function transfers received packets from card to driver, performing
+ * aggregation if required.
+ *
+ * For data received on control port, or if aggregation is disabled, the
+ * received buffers are uploaded as separate packets. However, if aggregation
+ * is enabled and required, the buffers are copied onto an aggregation buffer,
+ * provided there is space left, processed and finally uploaded.
+ */
+static int mwifiex_sdio_card_to_host_mp_aggr(struct mwifiex_adapter *adapter,
+                                            u16 rx_len, u8 port)
+{
+       struct sdio_mmc_card *card = adapter->card;
+       s32 f_do_rx_aggr = 0;
+       s32 f_do_rx_cur = 0;
+       s32 f_aggr_cur = 0;
+       s32 f_post_aggr_cur = 0;
+       struct sk_buff *skb_deaggr;
+       struct sk_buff *skb = NULL;
+       u32 pkt_len, pkt_type, mport, pind;
+       u8 *curr_ptr;
+
+       if ((card->has_control_mask) && (port == CTRL_PORT)) {
+               /* Read the command Resp without aggr */
+               mwifiex_dbg(adapter, CMD,
+                           "info: %s: no aggregation for cmd\t"
+                           "response\n", __func__);
+
+               f_do_rx_cur = 1;
+               goto rx_curr_single;
+       }
+
+       if (!card->mpa_rx.enabled) {
+               mwifiex_dbg(adapter, WARN,
+                           "info: %s: rx aggregation disabled\n",
+                           __func__);
+
+               f_do_rx_cur = 1;
+               goto rx_curr_single;
+       }
+
+       if ((!card->has_control_mask && (card->mp_rd_bitmap &
+                                        card->reg->data_port_mask)) ||
+           (card->has_control_mask && (card->mp_rd_bitmap &
+                                       (~((u32) CTRL_PORT_MASK))))) {
+               /* Some more data RX pending */
+               mwifiex_dbg(adapter, INFO,
+                           "info: %s: not last packet\n", __func__);
+
+               if (MP_RX_AGGR_IN_PROGRESS(card)) {
+                       if (MP_RX_AGGR_BUF_HAS_ROOM(card, rx_len)) {
+                               f_aggr_cur = 1;
+                       } else {
+                               /* No room in Aggr buf, do rx aggr now */
+                               f_do_rx_aggr = 1;
+                               f_post_aggr_cur = 1;
+                       }
+               } else {
+                       /* Rx aggr not in progress */
+                       f_aggr_cur = 1;
+               }
+
+       } else {
+               /* No more data RX pending */
+               mwifiex_dbg(adapter, INFO,
+                           "info: %s: last packet\n", __func__);
+
+               if (MP_RX_AGGR_IN_PROGRESS(card)) {
+                       f_do_rx_aggr = 1;
+                       if (MP_RX_AGGR_BUF_HAS_ROOM(card, rx_len))
+                               f_aggr_cur = 1;
+                       else
+                               /* No room in Aggr buf, do rx aggr now */
+                               f_do_rx_cur = 1;
+               } else {
+                       f_do_rx_cur = 1;
+               }
+       }
+
+       if (f_aggr_cur) {
+               mwifiex_dbg(adapter, INFO,
+                           "info: current packet aggregation\n");
+               /* Curr pkt can be aggregated */
+               mp_rx_aggr_setup(card, rx_len, port);
+
+               if (MP_RX_AGGR_PKT_LIMIT_REACHED(card) ||
+                   mp_rx_aggr_port_limit_reached(card)) {
+                       mwifiex_dbg(adapter, INFO,
+                                   "info: %s: aggregated packet\t"
+                                   "limit reached\n", __func__);
+                       /* No more pkts allowed in Aggr buf, rx it */
+                       f_do_rx_aggr = 1;
+               }
+       }
+
+       if (f_do_rx_aggr) {
+               /* do aggr RX now */
+               mwifiex_dbg(adapter, DATA,
+                           "info: do_rx_aggr: num of packets: %d\n",
+                           card->mpa_rx.pkt_cnt);
+
+               if (card->supports_sdio_new_mode) {
+                       int i;
+                       u32 port_count;
+
+                       for (i = 0, port_count = 0; i < card->max_ports; i++)
+                               if (card->mpa_rx.ports & BIT(i))
+                                       port_count++;
+
+                       /* Reading data from "start_port + 0" to "start_port +
+                        * port_count -1", so decrease the count by 1
+                        */
+                       port_count--;
+                       mport = (adapter->ioport | SDIO_MPA_ADDR_BASE |
+                                (port_count << 8)) + card->mpa_rx.start_port;
+               } else {
+                       mport = (adapter->ioport | SDIO_MPA_ADDR_BASE |
+                                (card->mpa_rx.ports << 4)) +
+                                card->mpa_rx.start_port;
+               }
+
+               if (mwifiex_read_data_sync(adapter, card->mpa_rx.buf,
+                                          card->mpa_rx.buf_len, mport, 1))
+                       goto error;
+
+               curr_ptr = card->mpa_rx.buf;
+
+               for (pind = 0; pind < card->mpa_rx.pkt_cnt; pind++) {
+                       u32 *len_arr = card->mpa_rx.len_arr;
+
+                       /* get curr PKT len & type */
+                       pkt_len = le16_to_cpu(*(__le16 *) &curr_ptr[0]);
+                       pkt_type = le16_to_cpu(*(__le16 *) &curr_ptr[2]);
+
+                       /* copy pkt to deaggr buf */
+                       skb_deaggr = mwifiex_alloc_dma_align_buf(len_arr[pind],
+                                                                GFP_KERNEL |
+                                                                GFP_DMA);
+                       if (!skb_deaggr) {
+                               mwifiex_dbg(adapter, ERROR, "skb allocation failure\t"
+                                           "drop pkt len=%d type=%d\n",
+                                           pkt_len, pkt_type);
+                               curr_ptr += len_arr[pind];
+                               continue;
+                       }
+
+                       skb_put(skb_deaggr, len_arr[pind]);
+
+                       if ((pkt_type == MWIFIEX_TYPE_DATA ||
+                            (pkt_type == MWIFIEX_TYPE_AGGR_DATA &&
+                             adapter->sdio_rx_aggr_enable)) &&
+                           (pkt_len <= len_arr[pind])) {
+
+                               memcpy(skb_deaggr->data, curr_ptr, pkt_len);
+
+                               skb_trim(skb_deaggr, pkt_len);
+
+                               /* Process de-aggr packet */
+                               mwifiex_decode_rx_packet(adapter, skb_deaggr,
+                                                        pkt_type);
+                       } else {
+                               mwifiex_dbg(adapter, ERROR,
+                                           "drop wrong aggr pkt:\t"
+                                           "sdio_single_port_rx_aggr=%d\t"
+                                           "type=%d len=%d max_len=%d\n",
+                                           adapter->sdio_rx_aggr_enable,
+                                           pkt_type, pkt_len, len_arr[pind]);
+                               dev_kfree_skb_any(skb_deaggr);
+                       }
+                       curr_ptr += len_arr[pind];
+               }
+               MP_RX_AGGR_BUF_RESET(card);
+       }
+
+rx_curr_single:
+       if (f_do_rx_cur) {
+               mwifiex_dbg(adapter, INFO, "info: RX: port: %d, rx_len: %d\n",
+                           port, rx_len);
+
+               skb = mwifiex_alloc_dma_align_buf(rx_len, GFP_KERNEL | GFP_DMA);
+               if (!skb) {
+                       mwifiex_dbg(adapter, ERROR,
+                                   "single skb allocated fail,\t"
+                                   "drop pkt port=%d len=%d\n", port, rx_len);
+                       if (mwifiex_sdio_card_to_host(adapter, &pkt_type,
+                                                     card->mpa_rx.buf, rx_len,
+                                                     adapter->ioport + port))
+                               goto error;
+                       return 0;
+               }
+
+               skb_put(skb, rx_len);
+
+               if (mwifiex_sdio_card_to_host(adapter, &pkt_type,
+                                             skb->data, skb->len,
+                                             adapter->ioport + port))
+                       goto error;
+               if (!adapter->sdio_rx_aggr_enable &&
+                   pkt_type == MWIFIEX_TYPE_AGGR_DATA) {
+                       mwifiex_dbg(adapter, ERROR, "drop wrong pkt type %d\t"
+                                   "current SDIO RX Aggr not enabled\n",
+                                   pkt_type);
+                       dev_kfree_skb_any(skb);
+                       return 0;
+               }
+
+               mwifiex_decode_rx_packet(adapter, skb, pkt_type);
+       }
+       if (f_post_aggr_cur) {
+               mwifiex_dbg(adapter, INFO,
+                           "info: current packet aggregation\n");
+               /* Curr pkt can be aggregated */
+               mp_rx_aggr_setup(card, rx_len, port);
+       }
+
+       return 0;
+error:
+       if (MP_RX_AGGR_IN_PROGRESS(card))
+               MP_RX_AGGR_BUF_RESET(card);
+
+       if (f_do_rx_cur && skb)
+               /* Single transfer pending. Free curr buff also */
+               dev_kfree_skb_any(skb);
+
+       return -1;
+}
+
+/*
+ * This function checks the current interrupt status.
+ *
+ * The following interrupts are checked and handled by this function -
+ *      - Data sent
+ *      - Command sent
+ *      - Packets received
+ *
+ * Since the firmware does not generate download ready interrupt if the
+ * port updated is command port only, command sent interrupt checking
+ * should be done manually, and for every SDIO interrupt.
+ *
+ * In case of Rx packets received, the packets are uploaded from card to
+ * host and processed accordingly.
+ */
+static int mwifiex_process_int_status(struct mwifiex_adapter *adapter)
+{
+       struct sdio_mmc_card *card = adapter->card;
+       const struct mwifiex_sdio_card_reg *reg = card->reg;
+       int ret = 0;
+       u8 sdio_ireg;
+       struct sk_buff *skb;
+       u8 port = CTRL_PORT;
+       u32 len_reg_l, len_reg_u;
+       u32 rx_blocks;
+       u16 rx_len;
+       unsigned long flags;
+       u32 bitmap;
+       u8 cr;
+
+       spin_lock_irqsave(&adapter->int_lock, flags);
+       sdio_ireg = adapter->int_status;
+       adapter->int_status = 0;
+       spin_unlock_irqrestore(&adapter->int_lock, flags);
+
+       if (!sdio_ireg)
+               return ret;
+
+       /* Following interrupt is only for SDIO new mode */
+       if (sdio_ireg & DN_LD_CMD_PORT_HOST_INT_STATUS && adapter->cmd_sent)
+               adapter->cmd_sent = false;
+
+       /* Following interrupt is only for SDIO new mode */
+       if (sdio_ireg & UP_LD_CMD_PORT_HOST_INT_STATUS) {
+               u32 pkt_type;
+
+               /* read the len of control packet */
+               rx_len = card->mp_regs[reg->cmd_rd_len_1] << 8;
+               rx_len |= (u16)card->mp_regs[reg->cmd_rd_len_0];
+               rx_blocks = DIV_ROUND_UP(rx_len, MWIFIEX_SDIO_BLOCK_SIZE);
+               if (rx_len <= INTF_HEADER_LEN ||
+                   (rx_blocks * MWIFIEX_SDIO_BLOCK_SIZE) >
+                    MWIFIEX_RX_DATA_BUF_SIZE)
+                       return -1;
+               rx_len = (u16) (rx_blocks * MWIFIEX_SDIO_BLOCK_SIZE);
+               mwifiex_dbg(adapter, INFO, "info: rx_len = %d\n", rx_len);
+
+               skb = mwifiex_alloc_dma_align_buf(rx_len, GFP_KERNEL | GFP_DMA);
+               if (!skb)
+                       return -1;
+
+               skb_put(skb, rx_len);
+
+               if (mwifiex_sdio_card_to_host(adapter, &pkt_type, skb->data,
+                                             skb->len, adapter->ioport |
+                                                       CMD_PORT_SLCT)) {
+                       mwifiex_dbg(adapter, ERROR,
+                                   "%s: failed to card_to_host", __func__);
+                       dev_kfree_skb_any(skb);
+                       goto term_cmd;
+               }
+
+               if ((pkt_type != MWIFIEX_TYPE_CMD) &&
+                   (pkt_type != MWIFIEX_TYPE_EVENT))
+                       mwifiex_dbg(adapter, ERROR,
+                                   "%s:Received wrong packet on cmd port",
+                                   __func__);
+
+               mwifiex_decode_rx_packet(adapter, skb, pkt_type);
+       }
+
+       if (sdio_ireg & DN_LD_HOST_INT_STATUS) {
+               bitmap = (u32) card->mp_regs[reg->wr_bitmap_l];
+               bitmap |= ((u32) card->mp_regs[reg->wr_bitmap_u]) << 8;
+               if (card->supports_sdio_new_mode) {
+                       bitmap |=
+                               ((u32) card->mp_regs[reg->wr_bitmap_1l]) << 16;
+                       bitmap |=
+                               ((u32) card->mp_regs[reg->wr_bitmap_1u]) << 24;
+               }
+               card->mp_wr_bitmap = bitmap;
+
+               mwifiex_dbg(adapter, INTR,
+                           "int: DNLD: wr_bitmap=0x%x\n",
+                           card->mp_wr_bitmap);
+               if (adapter->data_sent &&
+                   (card->mp_wr_bitmap & card->mp_data_port_mask)) {
+                       mwifiex_dbg(adapter, INTR,
+                                   "info:  <--- Tx DONE Interrupt --->\n");
+                       adapter->data_sent = false;
+               }
+       }
+
+       /* As firmware will not generate download ready interrupt if the port
+          updated is command port only, cmd_sent should be done for any SDIO
+          interrupt. */
+       if (card->has_control_mask && adapter->cmd_sent) {
+               /* Check if firmware has attach buffer at command port and
+                  update just that in wr_bit_map. */
+               card->mp_wr_bitmap |=
+                       (u32) card->mp_regs[reg->wr_bitmap_l] & CTRL_PORT_MASK;
+               if (card->mp_wr_bitmap & CTRL_PORT_MASK)
+                       adapter->cmd_sent = false;
+       }
+
+       mwifiex_dbg(adapter, INTR, "info: cmd_sent=%d data_sent=%d\n",
+                   adapter->cmd_sent, adapter->data_sent);
+       if (sdio_ireg & UP_LD_HOST_INT_STATUS) {
+               bitmap = (u32) card->mp_regs[reg->rd_bitmap_l];
+               bitmap |= ((u32) card->mp_regs[reg->rd_bitmap_u]) << 8;
+               if (card->supports_sdio_new_mode) {
+                       bitmap |=
+                               ((u32) card->mp_regs[reg->rd_bitmap_1l]) << 16;
+                       bitmap |=
+                               ((u32) card->mp_regs[reg->rd_bitmap_1u]) << 24;
+               }
+               card->mp_rd_bitmap = bitmap;
+               mwifiex_dbg(adapter, INTR,
+                           "int: UPLD: rd_bitmap=0x%x\n",
+                           card->mp_rd_bitmap);
+
+               while (true) {
+                       ret = mwifiex_get_rd_port(adapter, &port);
+                       if (ret) {
+                               mwifiex_dbg(adapter, INFO,
+                                           "info: no more rd_port available\n");
+                               break;
+                       }
+                       len_reg_l = reg->rd_len_p0_l + (port << 1);
+                       len_reg_u = reg->rd_len_p0_u + (port << 1);
+                       rx_len = ((u16) card->mp_regs[len_reg_u]) << 8;
+                       rx_len |= (u16) card->mp_regs[len_reg_l];
+                       mwifiex_dbg(adapter, INFO,
+                                   "info: RX: port=%d rx_len=%u\n",
+                                   port, rx_len);
+                       rx_blocks =
+                               (rx_len + MWIFIEX_SDIO_BLOCK_SIZE -
+                                1) / MWIFIEX_SDIO_BLOCK_SIZE;
+                       if (rx_len <= INTF_HEADER_LEN ||
+                           (card->mpa_rx.enabled &&
+                            ((rx_blocks * MWIFIEX_SDIO_BLOCK_SIZE) >
+                             card->mpa_rx.buf_size))) {
+                               mwifiex_dbg(adapter, ERROR,
+                                           "invalid rx_len=%d\n",
+                                           rx_len);
+                               return -1;
+                       }
+
+                       rx_len = (u16) (rx_blocks * MWIFIEX_SDIO_BLOCK_SIZE);
+                       mwifiex_dbg(adapter, INFO, "info: rx_len = %d\n",
+                                   rx_len);
+
+                       if (mwifiex_sdio_card_to_host_mp_aggr(adapter, rx_len,
+                                                             port)) {
+                               mwifiex_dbg(adapter, ERROR,
+                                           "card_to_host_mpa failed: int status=%#x\n",
+                                           sdio_ireg);
+                               goto term_cmd;
+                       }
+               }
+       }
+
+       return 0;
+
+term_cmd:
+       /* terminate cmd */
+       if (mwifiex_read_reg(adapter, CONFIGURATION_REG, &cr))
+               mwifiex_dbg(adapter, ERROR, "read CFG reg failed\n");
+       else
+               mwifiex_dbg(adapter, INFO,
+                           "info: CFG reg val = %d\n", cr);
+
+       if (mwifiex_write_reg(adapter, CONFIGURATION_REG, (cr | 0x04)))
+               mwifiex_dbg(adapter, ERROR,
+                           "write CFG reg failed\n");
+       else
+               mwifiex_dbg(adapter, INFO, "info: write success\n");
+
+       if (mwifiex_read_reg(adapter, CONFIGURATION_REG, &cr))
+               mwifiex_dbg(adapter, ERROR,
+                           "read CFG reg failed\n");
+       else
+               mwifiex_dbg(adapter, INFO,
+                           "info: CFG reg val =%x\n", cr);
+
+       return -1;
+}
+
+/*
+ * This function aggregates transmission buffers in driver and downloads
+ * the aggregated packet to card.
+ *
+ * The individual packets are aggregated by copying into an aggregation
+ * buffer and then downloaded to the card. Previous unsent packets in the
+ * aggregation buffer are pre-copied first before new packets are added.
+ * Aggregation is done till there is space left in the aggregation buffer,
+ * or till new packets are available.
+ *
+ * The function will only download the packet to the card when aggregation
+ * stops, otherwise it will just aggregate the packet in aggregation buffer
+ * and return.
+ */
+static int mwifiex_host_to_card_mp_aggr(struct mwifiex_adapter *adapter,
+                                       u8 *payload, u32 pkt_len, u32 port,
+                                       u32 next_pkt_len)
+{
+       struct sdio_mmc_card *card = adapter->card;
+       int ret = 0;
+       s32 f_send_aggr_buf = 0;
+       s32 f_send_cur_buf = 0;
+       s32 f_precopy_cur_buf = 0;
+       s32 f_postcopy_cur_buf = 0;
+       u32 mport;
+
+       if (!card->mpa_tx.enabled ||
+           (card->has_control_mask && (port == CTRL_PORT)) ||
+           (card->supports_sdio_new_mode && (port == CMD_PORT_SLCT))) {
+               mwifiex_dbg(adapter, WARN,
+                           "info: %s: tx aggregation disabled\n",
+                           __func__);
+
+               f_send_cur_buf = 1;
+               goto tx_curr_single;
+       }
+
+       if (next_pkt_len) {
+               /* More pkt in TX queue */
+               mwifiex_dbg(adapter, INFO,
+                           "info: %s: more packets in queue.\n",
+                           __func__);
+
+               if (MP_TX_AGGR_IN_PROGRESS(card)) {
+                       if (MP_TX_AGGR_BUF_HAS_ROOM(card, pkt_len)) {
+                               f_precopy_cur_buf = 1;
+
+                               if (!(card->mp_wr_bitmap &
+                                     (1 << card->curr_wr_port)) ||
+                                   !MP_TX_AGGR_BUF_HAS_ROOM(
+                                           card, pkt_len + next_pkt_len))
+                                       f_send_aggr_buf = 1;
+                       } else {
+                               /* No room in Aggr buf, send it */
+                               f_send_aggr_buf = 1;
+
+                               if (!(card->mp_wr_bitmap &
+                                     (1 << card->curr_wr_port)))
+                                       f_send_cur_buf = 1;
+                               else
+                                       f_postcopy_cur_buf = 1;
+                       }
+               } else {
+                       if (MP_TX_AGGR_BUF_HAS_ROOM(card, pkt_len) &&
+                           (card->mp_wr_bitmap & (1 << card->curr_wr_port)))
+                               f_precopy_cur_buf = 1;
+                       else
+                               f_send_cur_buf = 1;
+               }
+       } else {
+               /* Last pkt in TX queue */
+               mwifiex_dbg(adapter, INFO,
+                           "info: %s: Last packet in Tx Queue.\n",
+                           __func__);
+
+               if (MP_TX_AGGR_IN_PROGRESS(card)) {
+                       /* some packs in Aggr buf already */
+                       f_send_aggr_buf = 1;
+
+                       if (MP_TX_AGGR_BUF_HAS_ROOM(card, pkt_len))
+                               f_precopy_cur_buf = 1;
+                       else
+                               /* No room in Aggr buf, send it */
+                               f_send_cur_buf = 1;
+               } else {
+                       f_send_cur_buf = 1;
+               }
+       }
+
+       if (f_precopy_cur_buf) {
+               mwifiex_dbg(adapter, DATA,
+                           "data: %s: precopy current buffer\n",
+                           __func__);
+               MP_TX_AGGR_BUF_PUT(card, payload, pkt_len, port);
+
+               if (MP_TX_AGGR_PKT_LIMIT_REACHED(card) ||
+                   mp_tx_aggr_port_limit_reached(card))
+                       /* No more pkts allowed in Aggr buf, send it */
+                       f_send_aggr_buf = 1;
+       }
+
+       if (f_send_aggr_buf) {
+               mwifiex_dbg(adapter, DATA,
+                           "data: %s: send aggr buffer: %d %d\n",
+                           __func__, card->mpa_tx.start_port,
+                           card->mpa_tx.ports);
+               if (card->supports_sdio_new_mode) {
+                       u32 port_count;
+                       int i;
+
+                       for (i = 0, port_count = 0; i < card->max_ports; i++)
+                               if (card->mpa_tx.ports & BIT(i))
+                                       port_count++;
+
+                       /* Writing data from "start_port + 0" to "start_port +
+                        * port_count -1", so decrease the count by 1
+                        */
+                       port_count--;
+                       mport = (adapter->ioport | SDIO_MPA_ADDR_BASE |
+                                (port_count << 8)) + card->mpa_tx.start_port;
+               } else {
+                       mport = (adapter->ioport | SDIO_MPA_ADDR_BASE |
+                                (card->mpa_tx.ports << 4)) +
+                                card->mpa_tx.start_port;
+               }
+
+               ret = mwifiex_write_data_to_card(adapter, card->mpa_tx.buf,
+                                                card->mpa_tx.buf_len, mport);
+
+               MP_TX_AGGR_BUF_RESET(card);
+       }
+
+tx_curr_single:
+       if (f_send_cur_buf) {
+               mwifiex_dbg(adapter, DATA,
+                           "data: %s: send current buffer %d\n",
+                           __func__, port);
+               ret = mwifiex_write_data_to_card(adapter, payload, pkt_len,
+                                                adapter->ioport + port);
+       }
+
+       if (f_postcopy_cur_buf) {
+               mwifiex_dbg(adapter, DATA,
+                           "data: %s: postcopy current buffer\n",
+                           __func__);
+               MP_TX_AGGR_BUF_PUT(card, payload, pkt_len, port);
+       }
+
+       return ret;
+}
+
+/*
+ * This function downloads data from driver to card.
+ *
+ * Both commands and data packets are transferred to the card by this
+ * function.
+ *
+ * This function adds the SDIO specific header to the front of the buffer
+ * before transferring. The header contains the length of the packet and
+ * the type. The firmware handles the packets based upon this set type.
+ */
+static int mwifiex_sdio_host_to_card(struct mwifiex_adapter *adapter,
+                                    u8 type, struct sk_buff *skb,
+                                    struct mwifiex_tx_param *tx_param)
+{
+       struct sdio_mmc_card *card = adapter->card;
+       int ret;
+       u32 buf_block_len;
+       u32 blk_size;
+       u32 port = CTRL_PORT;
+       u8 *payload = (u8 *)skb->data;
+       u32 pkt_len = skb->len;
+
+       /* Allocate buffer and copy payload */
+       blk_size = MWIFIEX_SDIO_BLOCK_SIZE;
+       buf_block_len = (pkt_len + blk_size - 1) / blk_size;
+       *(__le16 *)&payload[0] = cpu_to_le16((u16)pkt_len);
+       *(__le16 *)&payload[2] = cpu_to_le16(type);
+
+       /*
+        * This is SDIO specific header
+        *  u16 length,
+        *  u16 type (MWIFIEX_TYPE_DATA = 0, MWIFIEX_TYPE_CMD = 1,
+        *  MWIFIEX_TYPE_EVENT = 3)
+        */
+       if (type == MWIFIEX_TYPE_DATA) {
+               ret = mwifiex_get_wr_port_data(adapter, &port);
+               if (ret) {
+                       mwifiex_dbg(adapter, ERROR,
+                                   "%s: no wr_port available\n",
+                                   __func__);
+                       return ret;
+               }
+       } else {
+               adapter->cmd_sent = true;
+               /* Type must be MWIFIEX_TYPE_CMD */
+
+               if (pkt_len <= INTF_HEADER_LEN ||
+                   pkt_len > MWIFIEX_UPLD_SIZE)
+                       mwifiex_dbg(adapter, ERROR,
+                                   "%s: payload=%p, nb=%d\n",
+                                   __func__, payload, pkt_len);
+
+               if (card->supports_sdio_new_mode)
+                       port = CMD_PORT_SLCT;
+       }
+
+       /* Transfer data to card */
+       pkt_len = buf_block_len * blk_size;
+
+       if (tx_param)
+               ret = mwifiex_host_to_card_mp_aggr(adapter, payload, pkt_len,
+                                                  port, tx_param->next_pkt_len
+                                                  );
+       else
+               ret = mwifiex_host_to_card_mp_aggr(adapter, payload, pkt_len,
+                                                  port, 0);
+
+       if (ret) {
+               if (type == MWIFIEX_TYPE_CMD)
+                       adapter->cmd_sent = false;
+               if (type == MWIFIEX_TYPE_DATA) {
+                       adapter->data_sent = false;
+                       /* restore curr_wr_port in error cases */
+                       card->curr_wr_port = port;
+                       card->mp_wr_bitmap |= (u32)(1 << card->curr_wr_port);
+               }
+       } else {
+               if (type == MWIFIEX_TYPE_DATA) {
+                       if (!(card->mp_wr_bitmap & (1 << card->curr_wr_port)))
+                               adapter->data_sent = true;
+                       else
+                               adapter->data_sent = false;
+               }
+       }
+
+       return ret;
+}
+
+/*
+ * This function allocates the MPA Tx and Rx buffers.
+ */
+static int mwifiex_alloc_sdio_mpa_buffers(struct mwifiex_adapter *adapter,
+                                  u32 mpa_tx_buf_size, u32 mpa_rx_buf_size)
+{
+       struct sdio_mmc_card *card = adapter->card;
+       u32 rx_buf_size;
+       int ret = 0;
+
+       card->mpa_tx.buf = kzalloc(mpa_tx_buf_size, GFP_KERNEL);
+       if (!card->mpa_tx.buf) {
+               ret = -1;
+               goto error;
+       }
+
+       card->mpa_tx.buf_size = mpa_tx_buf_size;
+
+       rx_buf_size = max_t(u32, mpa_rx_buf_size,
+                           (u32)SDIO_MAX_AGGR_BUF_SIZE);
+       card->mpa_rx.buf = kzalloc(rx_buf_size, GFP_KERNEL);
+       if (!card->mpa_rx.buf) {
+               ret = -1;
+               goto error;
+       }
+
+       card->mpa_rx.buf_size = rx_buf_size;
+
+error:
+       if (ret) {
+               kfree(card->mpa_tx.buf);
+               kfree(card->mpa_rx.buf);
+               card->mpa_tx.buf_size = 0;
+               card->mpa_rx.buf_size = 0;
+       }
+
+       return ret;
+}
+
+/*
+ * This function unregisters the SDIO device.
+ *
+ * The SDIO IRQ is released, the function is disabled and driver
+ * data is set to null.
+ */
+static void
+mwifiex_unregister_dev(struct mwifiex_adapter *adapter)
+{
+       struct sdio_mmc_card *card = adapter->card;
+
+       if (adapter->card) {
+               sdio_claim_host(card->func);
+               sdio_disable_func(card->func);
+               sdio_release_host(card->func);
+       }
+}
+
+/*
+ * This function registers the SDIO device.
+ *
+ * SDIO IRQ is claimed, block size is set and driver data is initialized.
+ */
+static int mwifiex_register_dev(struct mwifiex_adapter *adapter)
+{
+       int ret;
+       struct sdio_mmc_card *card = adapter->card;
+       struct sdio_func *func = card->func;
+
+       /* save adapter pointer in card */
+       card->adapter = adapter;
+       adapter->tx_buf_size = card->tx_buf_size;
+
+       sdio_claim_host(func);
+
+       /* Set block size */
+       ret = sdio_set_block_size(card->func, MWIFIEX_SDIO_BLOCK_SIZE);
+       sdio_release_host(func);
+       if (ret) {
+               mwifiex_dbg(adapter, ERROR,
+                           "cannot set SDIO block size\n");
+               return ret;
+       }
+
+
+       adapter->dev = &func->dev;
+
+       strcpy(adapter->fw_name, card->firmware);
+       if (card->fw_dump_enh) {
+               adapter->mem_type_mapping_tbl = generic_mem_type_map;
+               adapter->num_mem_types = 1;
+       } else {
+               adapter->mem_type_mapping_tbl = mem_type_mapping_tbl;
+               adapter->num_mem_types = ARRAY_SIZE(mem_type_mapping_tbl);
+       }
+
+       return 0;
+}
+
+/*
+ * This function initializes the SDIO driver.
+ *
+ * The following initializations steps are followed -
+ *      - Read the Host interrupt status register to acknowledge
+ *        the first interrupt got from bootloader
+ *      - Disable host interrupt mask register
+ *      - Get SDIO port
+ *      - Initialize SDIO variables in card
+ *      - Allocate MP registers
+ *      - Allocate MPA Tx and Rx buffers
+ */
+static int mwifiex_init_sdio(struct mwifiex_adapter *adapter)
+{
+       struct sdio_mmc_card *card = adapter->card;
+       const struct mwifiex_sdio_card_reg *reg = card->reg;
+       int ret;
+       u8 sdio_ireg;
+
+       sdio_set_drvdata(card->func, card);
+
+       /*
+        * Read the host_int_status_reg for ACK the first interrupt got
+        * from the bootloader. If we don't do this we get a interrupt
+        * as soon as we register the irq.
+        */
+       mwifiex_read_reg(adapter, card->reg->host_int_status_reg, &sdio_ireg);
+
+       /* Get SDIO ioport */
+       mwifiex_init_sdio_ioport(adapter);
+
+       /* Initialize SDIO variables in card */
+       card->mp_rd_bitmap = 0;
+       card->mp_wr_bitmap = 0;
+       card->curr_rd_port = reg->start_rd_port;
+       card->curr_wr_port = reg->start_wr_port;
+
+       card->mp_data_port_mask = reg->data_port_mask;
+
+       card->mpa_tx.buf_len = 0;
+       card->mpa_tx.pkt_cnt = 0;
+       card->mpa_tx.start_port = 0;
+
+       card->mpa_tx.enabled = 1;
+       card->mpa_tx.pkt_aggr_limit = card->mp_agg_pkt_limit;
+
+       card->mpa_rx.buf_len = 0;
+       card->mpa_rx.pkt_cnt = 0;
+       card->mpa_rx.start_port = 0;
+
+       card->mpa_rx.enabled = 1;
+       card->mpa_rx.pkt_aggr_limit = card->mp_agg_pkt_limit;
+
+       /* Allocate buffers for SDIO MP-A */
+       card->mp_regs = kzalloc(reg->max_mp_regs, GFP_KERNEL);
+       if (!card->mp_regs)
+               return -ENOMEM;
+
+       /* Allocate skb pointer buffers */
+       card->mpa_rx.skb_arr = kzalloc((sizeof(void *)) *
+                                      card->mp_agg_pkt_limit, GFP_KERNEL);
+       card->mpa_rx.len_arr = kzalloc(sizeof(*card->mpa_rx.len_arr) *
+                                      card->mp_agg_pkt_limit, GFP_KERNEL);
+       ret = mwifiex_alloc_sdio_mpa_buffers(adapter,
+                                            card->mp_tx_agg_buf_size,
+                                            card->mp_rx_agg_buf_size);
+
+       /* Allocate 32k MPA Tx/Rx buffers if 64k memory allocation fails */
+       if (ret && (card->mp_tx_agg_buf_size == MWIFIEX_MP_AGGR_BUF_SIZE_MAX ||
+                   card->mp_rx_agg_buf_size == MWIFIEX_MP_AGGR_BUF_SIZE_MAX)) {
+               /* Disable rx single port aggregation */
+               adapter->host_disable_sdio_rx_aggr = true;
+
+               ret = mwifiex_alloc_sdio_mpa_buffers
+                       (adapter, MWIFIEX_MP_AGGR_BUF_SIZE_32K,
+                        MWIFIEX_MP_AGGR_BUF_SIZE_32K);
+               if (ret) {
+                       /* Disable multi port aggregation */
+                       card->mpa_tx.enabled = 0;
+                       card->mpa_rx.enabled = 0;
+               }
+       }
+
+       adapter->auto_tdls = card->can_auto_tdls;
+       adapter->ext_scan = card->can_ext_scan;
+       return 0;
+}
+
+/*
+ * This function resets the MPA Tx and Rx buffers.
+ */
+static void mwifiex_cleanup_mpa_buf(struct mwifiex_adapter *adapter)
+{
+       struct sdio_mmc_card *card = adapter->card;
+
+       MP_TX_AGGR_BUF_RESET(card);
+       MP_RX_AGGR_BUF_RESET(card);
+}
+
+/*
+ * This function cleans up the allocated card buffers.
+ *
+ * The following are freed by this function -
+ *      - MP registers
+ *      - MPA Tx buffer
+ *      - MPA Rx buffer
+ */
+static void mwifiex_cleanup_sdio(struct mwifiex_adapter *adapter)
+{
+       struct sdio_mmc_card *card = adapter->card;
+
+       kfree(card->mp_regs);
+       kfree(card->mpa_rx.skb_arr);
+       kfree(card->mpa_rx.len_arr);
+       kfree(card->mpa_tx.buf);
+       kfree(card->mpa_rx.buf);
+       sdio_set_drvdata(card->func, NULL);
+       kfree(card);
+}
+
+/*
+ * This function updates the MP end port in card.
+ */
+static void
+mwifiex_update_mp_end_port(struct mwifiex_adapter *adapter, u16 port)
+{
+       struct sdio_mmc_card *card = adapter->card;
+       const struct mwifiex_sdio_card_reg *reg = card->reg;
+       int i;
+
+       card->mp_end_port = port;
+
+       card->mp_data_port_mask = reg->data_port_mask;
+
+       if (reg->start_wr_port) {
+               for (i = 1; i <= card->max_ports - card->mp_end_port; i++)
+                       card->mp_data_port_mask &=
+                                       ~(1 << (card->max_ports - i));
+       }
+
+       card->curr_wr_port = reg->start_wr_port;
+
+       mwifiex_dbg(adapter, CMD,
+                   "cmd: mp_end_port %d, data port mask 0x%x\n",
+                   port, card->mp_data_port_mask);
+}
+
+static void mwifiex_recreate_adapter(struct sdio_mmc_card *card)
+{
+       struct sdio_func *func = card->func;
+       const struct sdio_device_id *device_id = card->device_id;
+
+       /* TODO mmc_hw_reset does not require destroying and re-probing the
+        * whole adapter. Hence there was no need to for this rube-goldberg
+        * design to reload the fw from an external workqueue. If we don't
+        * destroy the adapter we could reload the fw from
+        * mwifiex_main_work_queue directly.
+        * The real difficulty with fw reset is to restore all the user
+        * settings applied through ioctl. By destroying and recreating the
+        * adapter, we take the easy way out, since we rely on user space to
+        * restore them. We assume that user space will treat the new
+        * incarnation of the adapter(interfaces) as if they had been just
+        * discovered and initializes them from scratch.
+        */
+
+       mwifiex_sdio_remove(func);
+
+       /* power cycle the adapter */
+       sdio_claim_host(func);
+       mmc_hw_reset(func->card->host);
+       sdio_release_host(func);
+
+       mwifiex_sdio_probe(func, device_id);
+}
+
+static struct mwifiex_adapter *save_adapter;
+static void mwifiex_sdio_card_reset_work(struct mwifiex_adapter *adapter)
+{
+       struct sdio_mmc_card *card = adapter->card;
+
+       /* TODO card pointer is unprotected. If the adapter is removed
+        * physically, sdio core might trigger mwifiex_sdio_remove, before this
+        * workqueue is run, which will destroy the adapter struct. When this
+        * workqueue eventually exceutes it will dereference an invalid adapter
+        * pointer
+        */
+       mwifiex_recreate_adapter(card);
+}
+
+/* This function read/write firmware */
+static enum
+rdwr_status mwifiex_sdio_rdwr_firmware(struct mwifiex_adapter *adapter,
+                                      u8 doneflag)
+{
+       struct sdio_mmc_card *card = adapter->card;
+       int ret, tries;
+       u8 ctrl_data = 0;
+
+       sdio_writeb(card->func, card->reg->fw_dump_host_ready,
+                   card->reg->fw_dump_ctrl, &ret);
+       if (ret) {
+               mwifiex_dbg(adapter, ERROR, "SDIO Write ERR\n");
+               return RDWR_STATUS_FAILURE;
+       }
+       for (tries = 0; tries < MAX_POLL_TRIES; tries++) {
+               ctrl_data = sdio_readb(card->func, card->reg->fw_dump_ctrl,
+                                      &ret);
+               if (ret) {
+                       mwifiex_dbg(adapter, ERROR, "SDIO read err\n");
+                       return RDWR_STATUS_FAILURE;
+               }
+               if (ctrl_data == FW_DUMP_DONE)
+                       break;
+               if (doneflag && ctrl_data == doneflag)
+                       return RDWR_STATUS_DONE;
+               if (ctrl_data != card->reg->fw_dump_host_ready) {
+                       mwifiex_dbg(adapter, WARN,
+                                   "The ctrl reg was changed, re-try again\n");
+                       sdio_writeb(card->func, card->reg->fw_dump_host_ready,
+                                   card->reg->fw_dump_ctrl, &ret);
+                       if (ret) {
+                               mwifiex_dbg(adapter, ERROR, "SDIO write err\n");
+                               return RDWR_STATUS_FAILURE;
+                       }
+               }
+               usleep_range(100, 200);
+       }
+       if (ctrl_data == card->reg->fw_dump_host_ready) {
+               mwifiex_dbg(adapter, ERROR,
+                           "Fail to pull ctrl_data\n");
+               return RDWR_STATUS_FAILURE;
+       }
+
+       return RDWR_STATUS_SUCCESS;
+}
+
+/* This function dump firmware memory to file */
+static void mwifiex_sdio_fw_dump(struct mwifiex_adapter *adapter)
+{
+       struct sdio_mmc_card *card = adapter->card;
+       int ret = 0;
+       unsigned int reg, reg_start, reg_end;
+       u8 *dbg_ptr, *end_ptr, dump_num, idx, i, read_reg, doneflag = 0;
+       enum rdwr_status stat;
+       u32 memory_size;
+
+       if (!card->can_dump_fw)
+               return;
+
+       for (idx = 0; idx < ARRAY_SIZE(mem_type_mapping_tbl); idx++) {
+               struct memory_type_mapping *entry = &mem_type_mapping_tbl[idx];
+
+               if (entry->mem_ptr) {
+                       vfree(entry->mem_ptr);
+                       entry->mem_ptr = NULL;
+               }
+               entry->mem_size = 0;
+       }
+
+       mwifiex_pm_wakeup_card(adapter);
+       sdio_claim_host(card->func);
+
+       mwifiex_dbg(adapter, MSG, "== mwifiex firmware dump start ==\n");
+
+       stat = mwifiex_sdio_rdwr_firmware(adapter, doneflag);
+       if (stat == RDWR_STATUS_FAILURE)
+               goto done;
+
+       reg = card->reg->fw_dump_start;
+       /* Read the number of the memories which will dump */
+       dump_num = sdio_readb(card->func, reg, &ret);
+       if (ret) {
+               mwifiex_dbg(adapter, ERROR, "SDIO read memory length err\n");
+               goto done;
+       }
+
+       /* Read the length of every memory which will dump */
+       for (idx = 0; idx < dump_num; idx++) {
+               struct memory_type_mapping *entry = &mem_type_mapping_tbl[idx];
+
+               stat = mwifiex_sdio_rdwr_firmware(adapter, doneflag);
+               if (stat == RDWR_STATUS_FAILURE)
+                       goto done;
+
+               memory_size = 0;
+               reg = card->reg->fw_dump_start;
+               for (i = 0; i < 4; i++) {
+                       read_reg = sdio_readb(card->func, reg, &ret);
+                       if (ret) {
+                               mwifiex_dbg(adapter, ERROR, "SDIO read err\n");
+                               goto done;
+                       }
+                       memory_size |= (read_reg << i*8);
+                       reg++;
+               }
+
+               if (memory_size == 0) {
+                       mwifiex_dbg(adapter, DUMP, "Firmware dump Finished!\n");
+                       ret = mwifiex_write_reg(adapter,
+                                               card->reg->fw_dump_ctrl,
+                                               FW_DUMP_READ_DONE);
+                       if (ret) {
+                               mwifiex_dbg(adapter, ERROR, "SDIO write err\n");
+                               return;
+                       }
+                       break;
+               }
+
+               mwifiex_dbg(adapter, DUMP,
+                           "%s_SIZE=0x%x\n", entry->mem_name, memory_size);
+               entry->mem_ptr = vmalloc(memory_size + 1);
+               entry->mem_size = memory_size;
+               if (!entry->mem_ptr) {
+                       mwifiex_dbg(adapter, ERROR, "Vmalloc %s failed\n",
+                                   entry->mem_name);
+                       goto done;
+               }
+               dbg_ptr = entry->mem_ptr;
+               end_ptr = dbg_ptr + memory_size;
+
+               doneflag = entry->done_flag;
+               mwifiex_dbg(adapter, DUMP,
+                           "Start %s output, please wait...\n",
+                           entry->mem_name);
+
+               do {
+                       stat = mwifiex_sdio_rdwr_firmware(adapter, doneflag);
+                       if (stat == RDWR_STATUS_FAILURE)
+                               goto done;
+
+                       reg_start = card->reg->fw_dump_start;
+                       reg_end = card->reg->fw_dump_end;
+                       for (reg = reg_start; reg <= reg_end; reg++) {
+                               *dbg_ptr = sdio_readb(card->func, reg, &ret);
+                               if (ret) {
+                                       mwifiex_dbg(adapter, ERROR,
+                                                   "SDIO read err\n");
+                                       goto done;
+                               }
+                               if (dbg_ptr < end_ptr)
+                                       dbg_ptr++;
+                               else
+                                       mwifiex_dbg(adapter, ERROR,
+                                                   "Allocated buf not enough\n");
+                       }
+
+                       if (stat != RDWR_STATUS_DONE)
+                               continue;
+
+                       mwifiex_dbg(adapter, DUMP, "%s done: size=0x%tx\n",
+                                   entry->mem_name, dbg_ptr - entry->mem_ptr);
+                       break;
+               } while (1);
+       }
+       mwifiex_dbg(adapter, MSG, "== mwifiex firmware dump end ==\n");
+
+done:
+       sdio_release_host(card->func);
+}
+
+static void mwifiex_sdio_generic_fw_dump(struct mwifiex_adapter *adapter)
+{
+       struct sdio_mmc_card *card = adapter->card;
+       struct memory_type_mapping *entry = &generic_mem_type_map[0];
+       unsigned int reg, reg_start, reg_end;
+       u8 start_flag = 0, done_flag = 0;
+       u8 *dbg_ptr, *end_ptr;
+       enum rdwr_status stat;
+       int ret = -1, tries;
+
+       if (!card->fw_dump_enh)
+               return;
+
+       if (entry->mem_ptr) {
+               vfree(entry->mem_ptr);
+               entry->mem_ptr = NULL;
+       }
+       entry->mem_size = 0;
+
+       mwifiex_pm_wakeup_card(adapter);
+       sdio_claim_host(card->func);
+
+       mwifiex_dbg(adapter, MSG, "== mwifiex firmware dump start ==\n");
+
+       stat = mwifiex_sdio_rdwr_firmware(adapter, done_flag);
+       if (stat == RDWR_STATUS_FAILURE)
+               goto done;
+
+       reg_start = card->reg->fw_dump_start;
+       reg_end = card->reg->fw_dump_end;
+       for (reg = reg_start; reg <= reg_end; reg++) {
+               for (tries = 0; tries < MAX_POLL_TRIES; tries++) {
+                       start_flag = sdio_readb(card->func, reg, &ret);
+                       if (ret) {
+                               mwifiex_dbg(adapter, ERROR,
+                                           "SDIO read err\n");
+                               goto done;
+                       }
+                       if (start_flag == 0)
+                               break;
+                       if (tries == MAX_POLL_TRIES) {
+                               mwifiex_dbg(adapter, ERROR,
+                                           "FW not ready to dump\n");
+                               ret = -1;
+                               goto done;
+                       }
+               }
+               usleep_range(100, 200);
+       }
+
+       entry->mem_ptr = vmalloc(0xf0000 + 1);
+       if (!entry->mem_ptr) {
+               ret = -1;
+               goto done;
+       }
+       dbg_ptr = entry->mem_ptr;
+       entry->mem_size = 0xf0000;
+       end_ptr = dbg_ptr + entry->mem_size;
+
+       done_flag = entry->done_flag;
+       mwifiex_dbg(adapter, DUMP,
+                   "Start %s output, please wait...\n", entry->mem_name);
+
+       while (true) {
+               stat = mwifiex_sdio_rdwr_firmware(adapter, done_flag);
+               if (stat == RDWR_STATUS_FAILURE)
+                       goto done;
+               for (reg = reg_start; reg <= reg_end; reg++) {
+                       *dbg_ptr = sdio_readb(card->func, reg, &ret);
+                       if (ret) {
+                               mwifiex_dbg(adapter, ERROR,
+                                           "SDIO read err\n");
+                               goto done;
+                       }
+                       dbg_ptr++;
+                       if (dbg_ptr >= end_ptr) {
+                               u8 *tmp_ptr;
+
+                               tmp_ptr = vmalloc(entry->mem_size + 0x4000 + 1);
+                               if (!tmp_ptr)
+                                       goto done;
+
+                               memcpy(tmp_ptr, entry->mem_ptr,
+                                      entry->mem_size);
+                               vfree(entry->mem_ptr);
+                               entry->mem_ptr = tmp_ptr;
+                               tmp_ptr = NULL;
+                               dbg_ptr = entry->mem_ptr + entry->mem_size;
+                               entry->mem_size += 0x4000;
+                               end_ptr = entry->mem_ptr + entry->mem_size;
+                       }
+               }
+               if (stat == RDWR_STATUS_DONE) {
+                       entry->mem_size = dbg_ptr - entry->mem_ptr;
+                       mwifiex_dbg(adapter, DUMP, "dump %s done size=0x%x\n",
+                                   entry->mem_name, entry->mem_size);
+                       ret = 0;
+                       break;
+               }
+       }
+       mwifiex_dbg(adapter, MSG, "== mwifiex firmware dump end ==\n");
+
+done:
+       if (ret) {
+               mwifiex_dbg(adapter, ERROR, "firmware dump failed\n");
+               if (entry->mem_ptr) {
+                       vfree(entry->mem_ptr);
+                       entry->mem_ptr = NULL;
+               }
+               entry->mem_size = 0;
+       }
+       sdio_release_host(card->func);
+}
+
+static void mwifiex_sdio_device_dump_work(struct mwifiex_adapter *adapter)
+{
+       struct sdio_mmc_card *card = adapter->card;
+
+       mwifiex_drv_info_dump(adapter);
+       if (card->fw_dump_enh)
+               mwifiex_sdio_generic_fw_dump(adapter);
+       else
+               mwifiex_sdio_fw_dump(adapter);
+       mwifiex_upload_device_dump(adapter);
+}
+
+static void mwifiex_sdio_work(struct work_struct *work)
+{
+       if (test_and_clear_bit(MWIFIEX_IFACE_WORK_DEVICE_DUMP,
+                              &iface_work_flags))
+               mwifiex_sdio_device_dump_work(save_adapter);
+       if (test_and_clear_bit(MWIFIEX_IFACE_WORK_CARD_RESET,
+                              &iface_work_flags))
+               mwifiex_sdio_card_reset_work(save_adapter);
+}
+
+static DECLARE_WORK(sdio_work, mwifiex_sdio_work);
+/* This function resets the card */
+static void mwifiex_sdio_card_reset(struct mwifiex_adapter *adapter)
+{
+       save_adapter = adapter;
+       if (test_bit(MWIFIEX_IFACE_WORK_CARD_RESET, &iface_work_flags))
+               return;
+
+       set_bit(MWIFIEX_IFACE_WORK_CARD_RESET, &iface_work_flags);
+
+       schedule_work(&sdio_work);
+}
+
+/* This function dumps FW information */
+static void mwifiex_sdio_device_dump(struct mwifiex_adapter *adapter)
+{
+       save_adapter = adapter;
+       if (test_bit(MWIFIEX_IFACE_WORK_DEVICE_DUMP, &iface_work_flags))
+               return;
+
+       set_bit(MWIFIEX_IFACE_WORK_DEVICE_DUMP, &iface_work_flags);
+       schedule_work(&sdio_work);
+}
+
+/* Function to dump SDIO function registers and SDIO scratch registers in case
+ * of FW crash
+ */
+static int
+mwifiex_sdio_reg_dump(struct mwifiex_adapter *adapter, char *drv_buf)
+{
+       char *p = drv_buf;
+       struct sdio_mmc_card *cardp = adapter->card;
+       int ret = 0;
+       u8 count, func, data, index = 0, size = 0;
+       u8 reg, reg_start, reg_end;
+       char buf[256], *ptr;
+
+       if (!p)
+               return 0;
+
+       mwifiex_dbg(adapter, MSG, "SDIO register dump start\n");
+
+       mwifiex_pm_wakeup_card(adapter);
+
+       sdio_claim_host(cardp->func);
+
+       for (count = 0; count < 5; count++) {
+               memset(buf, 0, sizeof(buf));
+               ptr = buf;
+
+               switch (count) {
+               case 0:
+                       /* Read the registers of SDIO function0 */
+                       func = count;
+                       reg_start = 0;
+                       reg_end = 9;
+                       break;
+               case 1:
+                       /* Read the registers of SDIO function1 */
+                       func = count;
+                       reg_start = cardp->reg->func1_dump_reg_start;
+                       reg_end = cardp->reg->func1_dump_reg_end;
+                       break;
+               case 2:
+                       index = 0;
+                       func = 1;
+                       reg_start = cardp->reg->func1_spec_reg_table[index++];
+                       size = cardp->reg->func1_spec_reg_num;
+                       reg_end = cardp->reg->func1_spec_reg_table[size-1];
+                       break;
+               default:
+                       /* Read the scratch registers of SDIO function1 */
+                       if (count == 4)
+                               mdelay(100);
+                       func = 1;
+                       reg_start = cardp->reg->func1_scratch_reg;
+                       reg_end = reg_start + MWIFIEX_SDIO_SCRATCH_SIZE;
+               }
+
+               if (count != 2)
+                       ptr += sprintf(ptr, "SDIO Func%d (%#x-%#x): ",
+                                      func, reg_start, reg_end);
+               else
+                       ptr += sprintf(ptr, "SDIO Func%d: ", func);
+
+               for (reg = reg_start; reg <= reg_end;) {
+                       if (func == 0)
+                               data = sdio_f0_readb(cardp->func, reg, &ret);
+                       else
+                               data = sdio_readb(cardp->func, reg, &ret);
+
+                       if (count == 2)
+                               ptr += sprintf(ptr, "(%#x) ", reg);
+                       if (!ret) {
+                               ptr += sprintf(ptr, "%02x ", data);
+                       } else {
+                               ptr += sprintf(ptr, "ERR");
+                               break;
+                       }
+
+                       if (count == 2 && reg < reg_end)
+                               reg = cardp->reg->func1_spec_reg_table[index++];
+                       else
+                               reg++;
+               }
+
+               mwifiex_dbg(adapter, MSG, "%s\n", buf);
+               p += sprintf(p, "%s\n", buf);
+       }
+
+       sdio_release_host(cardp->func);
+
+       mwifiex_dbg(adapter, MSG, "SDIO register dump end\n");
+
+       return p - drv_buf;
+}
+
+static struct mwifiex_if_ops sdio_ops = {
+       .init_if = mwifiex_init_sdio,
+       .cleanup_if = mwifiex_cleanup_sdio,
+       .check_fw_status = mwifiex_check_fw_status,
+       .prog_fw = mwifiex_prog_fw_w_helper,
+       .register_dev = mwifiex_register_dev,
+       .unregister_dev = mwifiex_unregister_dev,
+       .enable_int = mwifiex_sdio_enable_host_int,
+       .disable_int = mwifiex_sdio_disable_host_int,
+       .process_int_status = mwifiex_process_int_status,
+       .host_to_card = mwifiex_sdio_host_to_card,
+       .wakeup = mwifiex_pm_wakeup_card,
+       .wakeup_complete = mwifiex_pm_wakeup_card_complete,
+
+       /* SDIO specific */
+       .update_mp_end_port = mwifiex_update_mp_end_port,
+       .cleanup_mpa_buf = mwifiex_cleanup_mpa_buf,
+       .cmdrsp_complete = mwifiex_sdio_cmdrsp_complete,
+       .event_complete = mwifiex_sdio_event_complete,
+       .card_reset = mwifiex_sdio_card_reset,
+       .reg_dump = mwifiex_sdio_reg_dump,
+       .device_dump = mwifiex_sdio_device_dump,
+       .deaggr_pkt = mwifiex_deaggr_sdio_pkt,
+};
+
+/*
+ * This function initializes the SDIO driver.
+ *
+ * This initiates the semaphore and registers the device with
+ * SDIO bus.
+ */
+static int
+mwifiex_sdio_init_module(void)
+{
+       sema_init(&add_remove_card_sem, 1);
+
+       /* Clear the flag in case user removes the card. */
+       user_rmmod = 0;
+
+       return sdio_register_driver(&mwifiex_sdio);
+}
+
+/*
+ * This function cleans up the SDIO driver.
+ *
+ * The following major steps are followed for cleanup -
+ *      - Resume the device if its suspended
+ *      - Disconnect the device if connected
+ *      - Shutdown the firmware
+ *      - Unregister the device from SDIO bus.
+ */
+static void
+mwifiex_sdio_cleanup_module(void)
+{
+       if (!down_interruptible(&add_remove_card_sem))
+               up(&add_remove_card_sem);
+
+       /* Set the flag as user is removing this module. */
+       user_rmmod = 1;
+       cancel_work_sync(&sdio_work);
+
+       sdio_unregister_driver(&mwifiex_sdio);
+}
+
+module_init(mwifiex_sdio_init_module);
+module_exit(mwifiex_sdio_cleanup_module);
+
+MODULE_AUTHOR("Marvell International Ltd.");
+MODULE_DESCRIPTION("Marvell WiFi-Ex SDIO Driver version " SDIO_VERSION);
+MODULE_VERSION(SDIO_VERSION);
+MODULE_LICENSE("GPL v2");
+MODULE_FIRMWARE(SD8786_DEFAULT_FW_NAME);
+MODULE_FIRMWARE(SD8787_DEFAULT_FW_NAME);
+MODULE_FIRMWARE(SD8797_DEFAULT_FW_NAME);
+MODULE_FIRMWARE(SD8897_DEFAULT_FW_NAME);
+MODULE_FIRMWARE(SD8887_DEFAULT_FW_NAME);
+MODULE_FIRMWARE(SD8997_DEFAULT_FW_NAME);
diff --git a/drivers/net/wireless/marvell/mwifiex/sdio.h b/drivers/net/wireless/marvell/mwifiex/sdio.h
new file mode 100644 (file)
index 0000000..b9fbc5c
--- /dev/null
@@ -0,0 +1,672 @@
+/*
+ * Marvell Wireless LAN device driver: SDIO specific definitions
+ *
+ * Copyright (C) 2011-2014, Marvell International Ltd.
+ *
+ * This software file (the "File") is distributed by Marvell International
+ * Ltd. under the terms of the GNU General Public License Version 2, June 1991
+ * (the "License").  You may use, redistribute and/or modify this File in
+ * accordance with the terms and conditions of the License, a copy of which
+ * is available by writing to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the
+ * worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
+ *
+ * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
+ * ARE EXPRESSLY DISCLAIMED.  The License provides additional details about
+ * this warranty disclaimer.
+ */
+
+#ifndef        _MWIFIEX_SDIO_H
+#define        _MWIFIEX_SDIO_H
+
+
+#include <linux/mmc/sdio.h>
+#include <linux/mmc/sdio_ids.h>
+#include <linux/mmc/sdio_func.h>
+#include <linux/mmc/card.h>
+#include <linux/mmc/host.h>
+
+#include "main.h"
+
+#define SD8786_DEFAULT_FW_NAME "mrvl/sd8786_uapsta.bin"
+#define SD8787_DEFAULT_FW_NAME "mrvl/sd8787_uapsta.bin"
+#define SD8797_DEFAULT_FW_NAME "mrvl/sd8797_uapsta.bin"
+#define SD8897_DEFAULT_FW_NAME "mrvl/sd8897_uapsta.bin"
+#define SD8887_DEFAULT_FW_NAME "mrvl/sd8887_uapsta.bin"
+#define SD8801_DEFAULT_FW_NAME "mrvl/sd8801_uapsta.bin"
+#define SD8997_DEFAULT_FW_NAME "mrvl/sd8997_uapsta.bin"
+
+#define BLOCK_MODE     1
+#define BYTE_MODE      0
+
+#define REG_PORT                       0
+
+#define MWIFIEX_SDIO_IO_PORT_MASK              0xfffff
+
+#define MWIFIEX_SDIO_BYTE_MODE_MASK    0x80000000
+
+#define MWIFIEX_MAX_FUNC2_REG_NUM      13
+#define MWIFIEX_SDIO_SCRATCH_SIZE      10
+
+#define SDIO_MPA_ADDR_BASE             0x1000
+#define CTRL_PORT                      0
+#define CTRL_PORT_MASK                 0x0001
+
+#define CMD_PORT_UPLD_INT_MASK         (0x1U<<6)
+#define CMD_PORT_DNLD_INT_MASK         (0x1U<<7)
+#define HOST_TERM_CMD53                        (0x1U << 2)
+#define REG_PORT                       0
+#define MEM_PORT                       0x10000
+
+#define CMD53_NEW_MODE                 (0x1U << 0)
+#define CMD_PORT_RD_LEN_EN             (0x1U << 2)
+#define CMD_PORT_AUTO_EN               (0x1U << 0)
+#define CMD_PORT_SLCT                  0x8000
+#define UP_LD_CMD_PORT_HOST_INT_STATUS (0x40U)
+#define DN_LD_CMD_PORT_HOST_INT_STATUS (0x80U)
+
+#define MWIFIEX_MP_AGGR_BUF_SIZE_16K   (16384)
+#define MWIFIEX_MP_AGGR_BUF_SIZE_32K   (32768)
+/* we leave one block of 256 bytes for DMA alignment*/
+#define MWIFIEX_MP_AGGR_BUF_SIZE_MAX    (65280)
+
+/* Misc. Config Register : Auto Re-enable interrupts */
+#define AUTO_RE_ENABLE_INT              BIT(4)
+
+/* Host Control Registers : Configuration */
+#define CONFIGURATION_REG              0x00
+/* Host Control Registers : Host power up */
+#define HOST_POWER_UP                  (0x1U << 1)
+
+/* Host Control Registers : Upload host interrupt mask */
+#define UP_LD_HOST_INT_MASK            (0x1U)
+/* Host Control Registers : Download host interrupt mask */
+#define DN_LD_HOST_INT_MASK            (0x2U)
+
+/* Host Control Registers : Upload host interrupt status */
+#define UP_LD_HOST_INT_STATUS          (0x1U)
+/* Host Control Registers : Download host interrupt status */
+#define DN_LD_HOST_INT_STATUS          (0x2U)
+
+/* Host Control Registers : Host interrupt status */
+#define CARD_INT_STATUS_REG            0x28
+
+/* Card Control Registers : Card I/O ready */
+#define CARD_IO_READY                   (0x1U << 3)
+/* Card Control Registers : Download card ready */
+#define DN_LD_CARD_RDY                  (0x1U << 0)
+
+/* Max retry number of CMD53 write */
+#define MAX_WRITE_IOMEM_RETRY          2
+
+/* SDIO Tx aggregation in progress ? */
+#define MP_TX_AGGR_IN_PROGRESS(a) (a->mpa_tx.pkt_cnt > 0)
+
+/* SDIO Tx aggregation buffer room for next packet ? */
+#define MP_TX_AGGR_BUF_HAS_ROOM(a, len) ((a->mpa_tx.buf_len+len)       \
+                                               <= a->mpa_tx.buf_size)
+
+/* Copy current packet (SDIO Tx aggregation buffer) to SDIO buffer */
+#define MP_TX_AGGR_BUF_PUT(a, payload, pkt_len, port) do {             \
+       memmove(&a->mpa_tx.buf[a->mpa_tx.buf_len],                      \
+                       payload, pkt_len);                              \
+       a->mpa_tx.buf_len += pkt_len;                                   \
+       if (!a->mpa_tx.pkt_cnt)                                         \
+               a->mpa_tx.start_port = port;                            \
+       if (a->mpa_tx.start_port <= port)                               \
+               a->mpa_tx.ports |= (1<<(a->mpa_tx.pkt_cnt));            \
+       else                                                            \
+               a->mpa_tx.ports |= (1<<(a->mpa_tx.pkt_cnt+1+            \
+                                               (a->max_ports - \
+                                               a->mp_end_port)));      \
+       a->mpa_tx.pkt_cnt++;                                            \
+} while (0)
+
+/* SDIO Tx aggregation limit ? */
+#define MP_TX_AGGR_PKT_LIMIT_REACHED(a)                                        \
+                       (a->mpa_tx.pkt_cnt == a->mpa_tx.pkt_aggr_limit)
+
+/* Reset SDIO Tx aggregation buffer parameters */
+#define MP_TX_AGGR_BUF_RESET(a) do {                                   \
+       a->mpa_tx.pkt_cnt = 0;                                          \
+       a->mpa_tx.buf_len = 0;                                          \
+       a->mpa_tx.ports = 0;                                            \
+       a->mpa_tx.start_port = 0;                                       \
+} while (0)
+
+/* SDIO Rx aggregation limit ? */
+#define MP_RX_AGGR_PKT_LIMIT_REACHED(a)                                        \
+                       (a->mpa_rx.pkt_cnt == a->mpa_rx.pkt_aggr_limit)
+
+/* SDIO Rx aggregation in progress ? */
+#define MP_RX_AGGR_IN_PROGRESS(a) (a->mpa_rx.pkt_cnt > 0)
+
+/* SDIO Rx aggregation buffer room for next packet ? */
+#define MP_RX_AGGR_BUF_HAS_ROOM(a, rx_len)                             \
+                       ((a->mpa_rx.buf_len+rx_len) <= a->mpa_rx.buf_size)
+
+/* Reset SDIO Rx aggregation buffer parameters */
+#define MP_RX_AGGR_BUF_RESET(a) do {                                   \
+       a->mpa_rx.pkt_cnt = 0;                                          \
+       a->mpa_rx.buf_len = 0;                                          \
+       a->mpa_rx.ports = 0;                                            \
+       a->mpa_rx.start_port = 0;                                       \
+} while (0)
+
+/* data structure for SDIO MPA TX */
+struct mwifiex_sdio_mpa_tx {
+       /* multiport tx aggregation buffer pointer */
+       u8 *buf;
+       u32 buf_len;
+       u32 pkt_cnt;
+       u32 ports;
+       u16 start_port;
+       u8 enabled;
+       u32 buf_size;
+       u32 pkt_aggr_limit;
+};
+
+struct mwifiex_sdio_mpa_rx {
+       u8 *buf;
+       u32 buf_len;
+       u32 pkt_cnt;
+       u32 ports;
+       u16 start_port;
+
+       struct sk_buff **skb_arr;
+       u32 *len_arr;
+
+       u8 enabled;
+       u32 buf_size;
+       u32 pkt_aggr_limit;
+};
+
+int mwifiex_bus_register(void);
+void mwifiex_bus_unregister(void);
+
+struct mwifiex_sdio_card_reg {
+       u8 start_rd_port;
+       u8 start_wr_port;
+       u8 base_0_reg;
+       u8 base_1_reg;
+       u8 poll_reg;
+       u8 host_int_enable;
+       u8 host_int_rsr_reg;
+       u8 host_int_status_reg;
+       u8 host_int_mask_reg;
+       u8 status_reg_0;
+       u8 status_reg_1;
+       u8 sdio_int_mask;
+       u32 data_port_mask;
+       u8 io_port_0_reg;
+       u8 io_port_1_reg;
+       u8 io_port_2_reg;
+       u8 max_mp_regs;
+       u8 rd_bitmap_l;
+       u8 rd_bitmap_u;
+       u8 rd_bitmap_1l;
+       u8 rd_bitmap_1u;
+       u8 wr_bitmap_l;
+       u8 wr_bitmap_u;
+       u8 wr_bitmap_1l;
+       u8 wr_bitmap_1u;
+       u8 rd_len_p0_l;
+       u8 rd_len_p0_u;
+       u8 card_misc_cfg_reg;
+       u8 card_cfg_2_1_reg;
+       u8 cmd_rd_len_0;
+       u8 cmd_rd_len_1;
+       u8 cmd_rd_len_2;
+       u8 cmd_rd_len_3;
+       u8 cmd_cfg_0;
+       u8 cmd_cfg_1;
+       u8 cmd_cfg_2;
+       u8 cmd_cfg_3;
+       u8 fw_dump_host_ready;
+       u8 fw_dump_ctrl;
+       u8 fw_dump_start;
+       u8 fw_dump_end;
+       u8 func1_dump_reg_start;
+       u8 func1_dump_reg_end;
+       u8 func1_scratch_reg;
+       u8 func1_spec_reg_num;
+       u8 func1_spec_reg_table[MWIFIEX_MAX_FUNC2_REG_NUM];
+};
+
+struct sdio_mmc_card {
+       struct sdio_func *func;
+       struct mwifiex_adapter *adapter;
+
+       const char *firmware;
+       const struct mwifiex_sdio_card_reg *reg;
+       u8 max_ports;
+       u8 mp_agg_pkt_limit;
+       u16 tx_buf_size;
+       u32 mp_tx_agg_buf_size;
+       u32 mp_rx_agg_buf_size;
+
+       u32 mp_rd_bitmap;
+       u32 mp_wr_bitmap;
+
+       u16 mp_end_port;
+       u32 mp_data_port_mask;
+
+       u8 curr_rd_port;
+       u8 curr_wr_port;
+
+       u8 *mp_regs;
+       bool supports_sdio_new_mode;
+       bool has_control_mask;
+       bool can_dump_fw;
+       bool fw_dump_enh;
+       bool can_auto_tdls;
+       bool can_ext_scan;
+
+       struct mwifiex_sdio_mpa_tx mpa_tx;
+       struct mwifiex_sdio_mpa_rx mpa_rx;
+
+       /* needed for card reset */
+       const struct sdio_device_id *device_id;
+};
+
+struct mwifiex_sdio_device {
+       const char *firmware;
+       const struct mwifiex_sdio_card_reg *reg;
+       u8 max_ports;
+       u8 mp_agg_pkt_limit;
+       u16 tx_buf_size;
+       u32 mp_tx_agg_buf_size;
+       u32 mp_rx_agg_buf_size;
+       bool supports_sdio_new_mode;
+       bool has_control_mask;
+       bool can_dump_fw;
+       bool fw_dump_enh;
+       bool can_auto_tdls;
+       bool can_ext_scan;
+};
+
+static const struct mwifiex_sdio_card_reg mwifiex_reg_sd87xx = {
+       .start_rd_port = 1,
+       .start_wr_port = 1,
+       .base_0_reg = 0x0040,
+       .base_1_reg = 0x0041,
+       .poll_reg = 0x30,
+       .host_int_enable = UP_LD_HOST_INT_MASK | DN_LD_HOST_INT_MASK,
+       .host_int_rsr_reg = 0x1,
+       .host_int_mask_reg = 0x02,
+       .host_int_status_reg = 0x03,
+       .status_reg_0 = 0x60,
+       .status_reg_1 = 0x61,
+       .sdio_int_mask = 0x3f,
+       .data_port_mask = 0x0000fffe,
+       .io_port_0_reg = 0x78,
+       .io_port_1_reg = 0x79,
+       .io_port_2_reg = 0x7A,
+       .max_mp_regs = 64,
+       .rd_bitmap_l = 0x04,
+       .rd_bitmap_u = 0x05,
+       .wr_bitmap_l = 0x06,
+       .wr_bitmap_u = 0x07,
+       .rd_len_p0_l = 0x08,
+       .rd_len_p0_u = 0x09,
+       .card_misc_cfg_reg = 0x6c,
+       .func1_dump_reg_start = 0x0,
+       .func1_dump_reg_end = 0x9,
+       .func1_scratch_reg = 0x60,
+       .func1_spec_reg_num = 5,
+       .func1_spec_reg_table = {0x28, 0x30, 0x34, 0x38, 0x3c},
+};
+
+static const struct mwifiex_sdio_card_reg mwifiex_reg_sd8897 = {
+       .start_rd_port = 0,
+       .start_wr_port = 0,
+       .base_0_reg = 0x60,
+       .base_1_reg = 0x61,
+       .poll_reg = 0x50,
+       .host_int_enable = UP_LD_HOST_INT_MASK | DN_LD_HOST_INT_MASK |
+                       CMD_PORT_UPLD_INT_MASK | CMD_PORT_DNLD_INT_MASK,
+       .host_int_rsr_reg = 0x1,
+       .host_int_status_reg = 0x03,
+       .host_int_mask_reg = 0x02,
+       .status_reg_0 = 0xc0,
+       .status_reg_1 = 0xc1,
+       .sdio_int_mask = 0xff,
+       .data_port_mask = 0xffffffff,
+       .io_port_0_reg = 0xD8,
+       .io_port_1_reg = 0xD9,
+       .io_port_2_reg = 0xDA,
+       .max_mp_regs = 184,
+       .rd_bitmap_l = 0x04,
+       .rd_bitmap_u = 0x05,
+       .rd_bitmap_1l = 0x06,
+       .rd_bitmap_1u = 0x07,
+       .wr_bitmap_l = 0x08,
+       .wr_bitmap_u = 0x09,
+       .wr_bitmap_1l = 0x0a,
+       .wr_bitmap_1u = 0x0b,
+       .rd_len_p0_l = 0x0c,
+       .rd_len_p0_u = 0x0d,
+       .card_misc_cfg_reg = 0xcc,
+       .card_cfg_2_1_reg = 0xcd,
+       .cmd_rd_len_0 = 0xb4,
+       .cmd_rd_len_1 = 0xb5,
+       .cmd_rd_len_2 = 0xb6,
+       .cmd_rd_len_3 = 0xb7,
+       .cmd_cfg_0 = 0xb8,
+       .cmd_cfg_1 = 0xb9,
+       .cmd_cfg_2 = 0xba,
+       .cmd_cfg_3 = 0xbb,
+       .fw_dump_host_ready = 0xee,
+       .fw_dump_ctrl = 0xe2,
+       .fw_dump_start = 0xe3,
+       .fw_dump_end = 0xea,
+       .func1_dump_reg_start = 0x0,
+       .func1_dump_reg_end = 0xb,
+       .func1_scratch_reg = 0xc0,
+       .func1_spec_reg_num = 8,
+       .func1_spec_reg_table = {0x4C, 0x50, 0x54, 0x55, 0x58,
+                                0x59, 0x5c, 0x5d},
+};
+
+static const struct mwifiex_sdio_card_reg mwifiex_reg_sd8997 = {
+       .start_rd_port = 0,
+       .start_wr_port = 0,
+       .base_0_reg = 0xF8,
+       .base_1_reg = 0xF9,
+       .poll_reg = 0x5C,
+       .host_int_enable = UP_LD_HOST_INT_MASK | DN_LD_HOST_INT_MASK |
+                       CMD_PORT_UPLD_INT_MASK | CMD_PORT_DNLD_INT_MASK,
+       .host_int_rsr_reg = 0x4,
+       .host_int_status_reg = 0x0C,
+       .host_int_mask_reg = 0x08,
+       .status_reg_0 = 0xE8,
+       .status_reg_1 = 0xE9,
+       .sdio_int_mask = 0xff,
+       .data_port_mask = 0xffffffff,
+       .io_port_0_reg = 0xE4,
+       .io_port_1_reg = 0xE5,
+       .io_port_2_reg = 0xE6,
+       .max_mp_regs = 196,
+       .rd_bitmap_l = 0x10,
+       .rd_bitmap_u = 0x11,
+       .rd_bitmap_1l = 0x12,
+       .rd_bitmap_1u = 0x13,
+       .wr_bitmap_l = 0x14,
+       .wr_bitmap_u = 0x15,
+       .wr_bitmap_1l = 0x16,
+       .wr_bitmap_1u = 0x17,
+       .rd_len_p0_l = 0x18,
+       .rd_len_p0_u = 0x19,
+       .card_misc_cfg_reg = 0xd8,
+       .card_cfg_2_1_reg = 0xd9,
+       .cmd_rd_len_0 = 0xc0,
+       .cmd_rd_len_1 = 0xc1,
+       .cmd_rd_len_2 = 0xc2,
+       .cmd_rd_len_3 = 0xc3,
+       .cmd_cfg_0 = 0xc4,
+       .cmd_cfg_1 = 0xc5,
+       .cmd_cfg_2 = 0xc6,
+       .cmd_cfg_3 = 0xc7,
+       .fw_dump_host_ready = 0xcc,
+       .fw_dump_ctrl = 0xf0,
+       .fw_dump_start = 0xf1,
+       .fw_dump_end = 0xf8,
+       .func1_dump_reg_start = 0x10,
+       .func1_dump_reg_end = 0x17,
+       .func1_scratch_reg = 0xe8,
+       .func1_spec_reg_num = 13,
+       .func1_spec_reg_table = {0x08, 0x58, 0x5C, 0x5D,
+                                0x60, 0x61, 0x62, 0x64,
+                                0x65, 0x66, 0x68, 0x69,
+                                0x6a},
+};
+
+static const struct mwifiex_sdio_card_reg mwifiex_reg_sd8887 = {
+       .start_rd_port = 0,
+       .start_wr_port = 0,
+       .base_0_reg = 0x6C,
+       .base_1_reg = 0x6D,
+       .poll_reg = 0x5C,
+       .host_int_enable = UP_LD_HOST_INT_MASK | DN_LD_HOST_INT_MASK |
+                       CMD_PORT_UPLD_INT_MASK | CMD_PORT_DNLD_INT_MASK,
+       .host_int_rsr_reg = 0x4,
+       .host_int_status_reg = 0x0C,
+       .host_int_mask_reg = 0x08,
+       .status_reg_0 = 0x90,
+       .status_reg_1 = 0x91,
+       .sdio_int_mask = 0xff,
+       .data_port_mask = 0xffffffff,
+       .io_port_0_reg = 0xE4,
+       .io_port_1_reg = 0xE5,
+       .io_port_2_reg = 0xE6,
+       .max_mp_regs = 196,
+       .rd_bitmap_l = 0x10,
+       .rd_bitmap_u = 0x11,
+       .rd_bitmap_1l = 0x12,
+       .rd_bitmap_1u = 0x13,
+       .wr_bitmap_l = 0x14,
+       .wr_bitmap_u = 0x15,
+       .wr_bitmap_1l = 0x16,
+       .wr_bitmap_1u = 0x17,
+       .rd_len_p0_l = 0x18,
+       .rd_len_p0_u = 0x19,
+       .card_misc_cfg_reg = 0xd8,
+       .card_cfg_2_1_reg = 0xd9,
+       .cmd_rd_len_0 = 0xc0,
+       .cmd_rd_len_1 = 0xc1,
+       .cmd_rd_len_2 = 0xc2,
+       .cmd_rd_len_3 = 0xc3,
+       .cmd_cfg_0 = 0xc4,
+       .cmd_cfg_1 = 0xc5,
+       .cmd_cfg_2 = 0xc6,
+       .cmd_cfg_3 = 0xc7,
+       .func1_dump_reg_start = 0x10,
+       .func1_dump_reg_end = 0x17,
+       .func1_scratch_reg = 0x90,
+       .func1_spec_reg_num = 13,
+       .func1_spec_reg_table = {0x08, 0x58, 0x5C, 0x5D, 0x60,
+                                0x61, 0x62, 0x64, 0x65, 0x66,
+                                0x68, 0x69, 0x6a},
+};
+
+static const struct mwifiex_sdio_device mwifiex_sdio_sd8786 = {
+       .firmware = SD8786_DEFAULT_FW_NAME,
+       .reg = &mwifiex_reg_sd87xx,
+       .max_ports = 16,
+       .mp_agg_pkt_limit = 8,
+       .tx_buf_size = MWIFIEX_TX_DATA_BUF_SIZE_2K,
+       .mp_tx_agg_buf_size = MWIFIEX_MP_AGGR_BUF_SIZE_16K,
+       .mp_rx_agg_buf_size = MWIFIEX_MP_AGGR_BUF_SIZE_16K,
+       .supports_sdio_new_mode = false,
+       .has_control_mask = true,
+       .can_dump_fw = false,
+       .can_auto_tdls = false,
+       .can_ext_scan = false,
+};
+
+static const struct mwifiex_sdio_device mwifiex_sdio_sd8787 = {
+       .firmware = SD8787_DEFAULT_FW_NAME,
+       .reg = &mwifiex_reg_sd87xx,
+       .max_ports = 16,
+       .mp_agg_pkt_limit = 8,
+       .tx_buf_size = MWIFIEX_TX_DATA_BUF_SIZE_2K,
+       .mp_tx_agg_buf_size = MWIFIEX_MP_AGGR_BUF_SIZE_16K,
+       .mp_rx_agg_buf_size = MWIFIEX_MP_AGGR_BUF_SIZE_16K,
+       .supports_sdio_new_mode = false,
+       .has_control_mask = true,
+       .can_dump_fw = false,
+       .can_auto_tdls = false,
+       .can_ext_scan = true,
+};
+
+static const struct mwifiex_sdio_device mwifiex_sdio_sd8797 = {
+       .firmware = SD8797_DEFAULT_FW_NAME,
+       .reg = &mwifiex_reg_sd87xx,
+       .max_ports = 16,
+       .mp_agg_pkt_limit = 8,
+       .tx_buf_size = MWIFIEX_TX_DATA_BUF_SIZE_2K,
+       .mp_tx_agg_buf_size = MWIFIEX_MP_AGGR_BUF_SIZE_16K,
+       .mp_rx_agg_buf_size = MWIFIEX_MP_AGGR_BUF_SIZE_16K,
+       .supports_sdio_new_mode = false,
+       .has_control_mask = true,
+       .can_dump_fw = false,
+       .can_auto_tdls = false,
+       .can_ext_scan = true,
+};
+
+static const struct mwifiex_sdio_device mwifiex_sdio_sd8897 = {
+       .firmware = SD8897_DEFAULT_FW_NAME,
+       .reg = &mwifiex_reg_sd8897,
+       .max_ports = 32,
+       .mp_agg_pkt_limit = 16,
+       .tx_buf_size = MWIFIEX_TX_DATA_BUF_SIZE_4K,
+       .mp_tx_agg_buf_size = MWIFIEX_MP_AGGR_BUF_SIZE_MAX,
+       .mp_rx_agg_buf_size = MWIFIEX_MP_AGGR_BUF_SIZE_MAX,
+       .supports_sdio_new_mode = true,
+       .has_control_mask = false,
+       .can_dump_fw = true,
+       .can_auto_tdls = false,
+       .can_ext_scan = true,
+};
+
+static const struct mwifiex_sdio_device mwifiex_sdio_sd8997 = {
+       .firmware = SD8997_DEFAULT_FW_NAME,
+       .reg = &mwifiex_reg_sd8997,
+       .max_ports = 32,
+       .mp_agg_pkt_limit = 16,
+       .tx_buf_size = MWIFIEX_TX_DATA_BUF_SIZE_4K,
+       .mp_tx_agg_buf_size = MWIFIEX_MP_AGGR_BUF_SIZE_MAX,
+       .mp_rx_agg_buf_size = MWIFIEX_MP_AGGR_BUF_SIZE_MAX,
+       .supports_sdio_new_mode = true,
+       .has_control_mask = false,
+       .can_dump_fw = true,
+       .fw_dump_enh = true,
+       .can_auto_tdls = false,
+       .can_ext_scan = true,
+};
+
+static const struct mwifiex_sdio_device mwifiex_sdio_sd8887 = {
+       .firmware = SD8887_DEFAULT_FW_NAME,
+       .reg = &mwifiex_reg_sd8887,
+       .max_ports = 32,
+       .mp_agg_pkt_limit = 16,
+       .tx_buf_size = MWIFIEX_TX_DATA_BUF_SIZE_2K,
+       .mp_tx_agg_buf_size = MWIFIEX_MP_AGGR_BUF_SIZE_32K,
+       .mp_rx_agg_buf_size = MWIFIEX_MP_AGGR_BUF_SIZE_32K,
+       .supports_sdio_new_mode = true,
+       .has_control_mask = false,
+       .can_dump_fw = false,
+       .can_auto_tdls = true,
+       .can_ext_scan = true,
+};
+
+static const struct mwifiex_sdio_device mwifiex_sdio_sd8801 = {
+       .firmware = SD8801_DEFAULT_FW_NAME,
+       .reg = &mwifiex_reg_sd87xx,
+       .max_ports = 16,
+       .mp_agg_pkt_limit = 8,
+       .supports_sdio_new_mode = false,
+       .has_control_mask = true,
+       .tx_buf_size = MWIFIEX_TX_DATA_BUF_SIZE_2K,
+       .mp_tx_agg_buf_size = MWIFIEX_MP_AGGR_BUF_SIZE_16K,
+       .mp_rx_agg_buf_size = MWIFIEX_MP_AGGR_BUF_SIZE_16K,
+       .can_dump_fw = false,
+       .can_auto_tdls = false,
+       .can_ext_scan = true,
+};
+
+/*
+ * .cmdrsp_complete handler
+ */
+static inline int mwifiex_sdio_cmdrsp_complete(struct mwifiex_adapter *adapter,
+                                              struct sk_buff *skb)
+{
+       dev_kfree_skb_any(skb);
+       return 0;
+}
+
+/*
+ * .event_complete handler
+ */
+static inline int mwifiex_sdio_event_complete(struct mwifiex_adapter *adapter,
+                                             struct sk_buff *skb)
+{
+       dev_kfree_skb_any(skb);
+       return 0;
+}
+
+static inline bool
+mp_rx_aggr_port_limit_reached(struct sdio_mmc_card *card)
+{
+       u8 tmp;
+
+       if (card->curr_rd_port < card->mpa_rx.start_port) {
+               if (card->supports_sdio_new_mode)
+                       tmp = card->mp_end_port >> 1;
+               else
+                       tmp = card->mp_agg_pkt_limit;
+
+               if (((card->max_ports - card->mpa_rx.start_port) +
+                   card->curr_rd_port) >= tmp)
+                       return true;
+       }
+
+       if (!card->supports_sdio_new_mode)
+               return false;
+
+       if ((card->curr_rd_port - card->mpa_rx.start_port) >=
+           (card->mp_end_port >> 1))
+               return true;
+
+       return false;
+}
+
+static inline bool
+mp_tx_aggr_port_limit_reached(struct sdio_mmc_card *card)
+{
+       u16 tmp;
+
+       if (card->curr_wr_port < card->mpa_tx.start_port) {
+               if (card->supports_sdio_new_mode)
+                       tmp = card->mp_end_port >> 1;
+               else
+                       tmp = card->mp_agg_pkt_limit;
+
+               if (((card->max_ports - card->mpa_tx.start_port) +
+                   card->curr_wr_port) >= tmp)
+                       return true;
+       }
+
+       if (!card->supports_sdio_new_mode)
+               return false;
+
+       if ((card->curr_wr_port - card->mpa_tx.start_port) >=
+           (card->mp_end_port >> 1))
+               return true;
+
+       return false;
+}
+
+/* Prepare to copy current packet from card to SDIO Rx aggregation buffer */
+static inline void mp_rx_aggr_setup(struct sdio_mmc_card *card,
+                                   u16 rx_len, u8 port)
+{
+       card->mpa_rx.buf_len += rx_len;
+
+       if (!card->mpa_rx.pkt_cnt)
+               card->mpa_rx.start_port = port;
+
+       if (card->supports_sdio_new_mode) {
+               card->mpa_rx.ports |= (1 << port);
+       } else {
+               if (card->mpa_rx.start_port <= port)
+                       card->mpa_rx.ports |= 1 << (card->mpa_rx.pkt_cnt);
+               else
+                       card->mpa_rx.ports |= 1 << (card->mpa_rx.pkt_cnt + 1);
+       }
+       card->mpa_rx.skb_arr[card->mpa_rx.pkt_cnt] = NULL;
+       card->mpa_rx.len_arr[card->mpa_rx.pkt_cnt] = rx_len;
+       card->mpa_rx.pkt_cnt++;
+}
+#endif /* _MWIFIEX_SDIO_H */
diff --git a/drivers/net/wireless/marvell/mwifiex/sta_cmd.c b/drivers/net/wireless/marvell/mwifiex/sta_cmd.c
new file mode 100644 (file)
index 0000000..e486867
--- /dev/null
@@ -0,0 +1,2282 @@
+/*
+ * Marvell Wireless LAN device driver: station command handling
+ *
+ * Copyright (C) 2011-2014, Marvell International Ltd.
+ *
+ * This software file (the "File") is distributed by Marvell International
+ * Ltd. under the terms of the GNU General Public License Version 2, June 1991
+ * (the "License").  You may use, redistribute and/or modify this File in
+ * accordance with the terms and conditions of the License, a copy of which
+ * is available by writing to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the
+ * worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
+ *
+ * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
+ * ARE EXPRESSLY DISCLAIMED.  The License provides additional details about
+ * this warranty disclaimer.
+ */
+
+#include "decl.h"
+#include "ioctl.h"
+#include "util.h"
+#include "fw.h"
+#include "main.h"
+#include "wmm.h"
+#include "11n.h"
+#include "11ac.h"
+
+static bool drcs;
+module_param(drcs, bool, 0644);
+MODULE_PARM_DESC(drcs, "multi-channel operation:1, single-channel operation:0");
+
+static bool disable_auto_ds;
+module_param(disable_auto_ds, bool, 0);
+MODULE_PARM_DESC(disable_auto_ds,
+                "deepsleep enabled=0(default), deepsleep disabled=1");
+/*
+ * This function prepares command to set/get RSSI information.
+ *
+ * Preparation includes -
+ *      - Setting command ID, action and proper size
+ *      - Setting data/beacon average factors
+ *      - Resetting SNR/NF/RSSI values in private structure
+ *      - Ensuring correct endian-ness
+ */
+static int
+mwifiex_cmd_802_11_rssi_info(struct mwifiex_private *priv,
+                            struct host_cmd_ds_command *cmd, u16 cmd_action)
+{
+       cmd->command = cpu_to_le16(HostCmd_CMD_RSSI_INFO);
+       cmd->size = cpu_to_le16(sizeof(struct host_cmd_ds_802_11_rssi_info) +
+                               S_DS_GEN);
+       cmd->params.rssi_info.action = cpu_to_le16(cmd_action);
+       cmd->params.rssi_info.ndata = cpu_to_le16(priv->data_avg_factor);
+       cmd->params.rssi_info.nbcn = cpu_to_le16(priv->bcn_avg_factor);
+
+       /* Reset SNR/NF/RSSI values in private structure */
+       priv->data_rssi_last = 0;
+       priv->data_nf_last = 0;
+       priv->data_rssi_avg = 0;
+       priv->data_nf_avg = 0;
+       priv->bcn_rssi_last = 0;
+       priv->bcn_nf_last = 0;
+       priv->bcn_rssi_avg = 0;
+       priv->bcn_nf_avg = 0;
+
+       return 0;
+}
+
+/*
+ * This function prepares command to set MAC control.
+ *
+ * Preparation includes -
+ *      - Setting command ID, action and proper size
+ *      - Ensuring correct endian-ness
+ */
+static int mwifiex_cmd_mac_control(struct mwifiex_private *priv,
+                                  struct host_cmd_ds_command *cmd,
+                                  u16 cmd_action, u16 *action)
+{
+       struct host_cmd_ds_mac_control *mac_ctrl = &cmd->params.mac_ctrl;
+
+       if (cmd_action != HostCmd_ACT_GEN_SET) {
+               mwifiex_dbg(priv->adapter, ERROR,
+                           "mac_control: only support set cmd\n");
+               return -1;
+       }
+
+       cmd->command = cpu_to_le16(HostCmd_CMD_MAC_CONTROL);
+       cmd->size =
+               cpu_to_le16(sizeof(struct host_cmd_ds_mac_control) + S_DS_GEN);
+       mac_ctrl->action = cpu_to_le16(*action);
+
+       return 0;
+}
+
+/*
+ * This function prepares command to set/get SNMP MIB.
+ *
+ * Preparation includes -
+ *      - Setting command ID, action and proper size
+ *      - Setting SNMP MIB OID number and value
+ *        (as required)
+ *      - Ensuring correct endian-ness
+ *
+ * The following SNMP MIB OIDs are supported -
+ *      - FRAG_THRESH_I     : Fragmentation threshold
+ *      - RTS_THRESH_I      : RTS threshold
+ *      - SHORT_RETRY_LIM_I : Short retry limit
+ *      - DOT11D_I          : 11d support
+ */
+static int mwifiex_cmd_802_11_snmp_mib(struct mwifiex_private *priv,
+                                      struct host_cmd_ds_command *cmd,
+                                      u16 cmd_action, u32 cmd_oid,
+                                      u16 *ul_temp)
+{
+       struct host_cmd_ds_802_11_snmp_mib *snmp_mib = &cmd->params.smib;
+
+       mwifiex_dbg(priv->adapter, CMD,
+                   "cmd: SNMP_CMD: cmd_oid = 0x%x\n", cmd_oid);
+       cmd->command = cpu_to_le16(HostCmd_CMD_802_11_SNMP_MIB);
+       cmd->size = cpu_to_le16(sizeof(struct host_cmd_ds_802_11_snmp_mib)
+                               - 1 + S_DS_GEN);
+
+       snmp_mib->oid = cpu_to_le16((u16)cmd_oid);
+       if (cmd_action == HostCmd_ACT_GEN_GET) {
+               snmp_mib->query_type = cpu_to_le16(HostCmd_ACT_GEN_GET);
+               snmp_mib->buf_size = cpu_to_le16(MAX_SNMP_BUF_SIZE);
+               le16_add_cpu(&cmd->size, MAX_SNMP_BUF_SIZE);
+       } else if (cmd_action == HostCmd_ACT_GEN_SET) {
+               snmp_mib->query_type = cpu_to_le16(HostCmd_ACT_GEN_SET);
+               snmp_mib->buf_size = cpu_to_le16(sizeof(u16));
+               *((__le16 *) (snmp_mib->value)) = cpu_to_le16(*ul_temp);
+               le16_add_cpu(&cmd->size, sizeof(u16));
+       }
+
+       mwifiex_dbg(priv->adapter, CMD,
+                   "cmd: SNMP_CMD: Action=0x%x, OID=0x%x,\t"
+                   "OIDSize=0x%x, Value=0x%x\n",
+                   cmd_action, cmd_oid, le16_to_cpu(snmp_mib->buf_size),
+                   le16_to_cpu(*(__le16 *)snmp_mib->value));
+       return 0;
+}
+
+/*
+ * This function prepares command to get log.
+ *
+ * Preparation includes -
+ *      - Setting command ID and proper size
+ *      - Ensuring correct endian-ness
+ */
+static int
+mwifiex_cmd_802_11_get_log(struct host_cmd_ds_command *cmd)
+{
+       cmd->command = cpu_to_le16(HostCmd_CMD_802_11_GET_LOG);
+       cmd->size = cpu_to_le16(sizeof(struct host_cmd_ds_802_11_get_log) +
+                               S_DS_GEN);
+       return 0;
+}
+
+/*
+ * This function prepares command to set/get Tx data rate configuration.
+ *
+ * Preparation includes -
+ *      - Setting command ID, action and proper size
+ *      - Setting configuration index, rate scope and rate drop pattern
+ *        parameters (as required)
+ *      - Ensuring correct endian-ness
+ */
+static int mwifiex_cmd_tx_rate_cfg(struct mwifiex_private *priv,
+                                  struct host_cmd_ds_command *cmd,
+                                  u16 cmd_action, u16 *pbitmap_rates)
+{
+       struct host_cmd_ds_tx_rate_cfg *rate_cfg = &cmd->params.tx_rate_cfg;
+       struct mwifiex_rate_scope *rate_scope;
+       struct mwifiex_rate_drop_pattern *rate_drop;
+       u32 i;
+
+       cmd->command = cpu_to_le16(HostCmd_CMD_TX_RATE_CFG);
+
+       rate_cfg->action = cpu_to_le16(cmd_action);
+       rate_cfg->cfg_index = 0;
+
+       rate_scope = (struct mwifiex_rate_scope *) ((u8 *) rate_cfg +
+                     sizeof(struct host_cmd_ds_tx_rate_cfg));
+       rate_scope->type = cpu_to_le16(TLV_TYPE_RATE_SCOPE);
+       rate_scope->length = cpu_to_le16
+               (sizeof(*rate_scope) - sizeof(struct mwifiex_ie_types_header));
+       if (pbitmap_rates != NULL) {
+               rate_scope->hr_dsss_rate_bitmap = cpu_to_le16(pbitmap_rates[0]);
+               rate_scope->ofdm_rate_bitmap = cpu_to_le16(pbitmap_rates[1]);
+               for (i = 0;
+                    i < sizeof(rate_scope->ht_mcs_rate_bitmap) / sizeof(u16);
+                    i++)
+                       rate_scope->ht_mcs_rate_bitmap[i] =
+                               cpu_to_le16(pbitmap_rates[2 + i]);
+               if (priv->adapter->fw_api_ver == MWIFIEX_FW_V15) {
+                       for (i = 0;
+                            i < ARRAY_SIZE(rate_scope->vht_mcs_rate_bitmap);
+                            i++)
+                               rate_scope->vht_mcs_rate_bitmap[i] =
+                                       cpu_to_le16(pbitmap_rates[10 + i]);
+               }
+       } else {
+               rate_scope->hr_dsss_rate_bitmap =
+                       cpu_to_le16(priv->bitmap_rates[0]);
+               rate_scope->ofdm_rate_bitmap =
+                       cpu_to_le16(priv->bitmap_rates[1]);
+               for (i = 0;
+                    i < sizeof(rate_scope->ht_mcs_rate_bitmap) / sizeof(u16);
+                    i++)
+                       rate_scope->ht_mcs_rate_bitmap[i] =
+                               cpu_to_le16(priv->bitmap_rates[2 + i]);
+               if (priv->adapter->fw_api_ver == MWIFIEX_FW_V15) {
+                       for (i = 0;
+                            i < ARRAY_SIZE(rate_scope->vht_mcs_rate_bitmap);
+                            i++)
+                               rate_scope->vht_mcs_rate_bitmap[i] =
+                                       cpu_to_le16(priv->bitmap_rates[10 + i]);
+               }
+       }
+
+       rate_drop = (struct mwifiex_rate_drop_pattern *) ((u8 *) rate_scope +
+                                            sizeof(struct mwifiex_rate_scope));
+       rate_drop->type = cpu_to_le16(TLV_TYPE_RATE_DROP_CONTROL);
+       rate_drop->length = cpu_to_le16(sizeof(rate_drop->rate_drop_mode));
+       rate_drop->rate_drop_mode = 0;
+
+       cmd->size =
+               cpu_to_le16(S_DS_GEN + sizeof(struct host_cmd_ds_tx_rate_cfg) +
+                           sizeof(struct mwifiex_rate_scope) +
+                           sizeof(struct mwifiex_rate_drop_pattern));
+
+       return 0;
+}
+
+/*
+ * This function prepares command to set/get Tx power configuration.
+ *
+ * Preparation includes -
+ *      - Setting command ID, action and proper size
+ *      - Setting Tx power mode, power group TLV
+ *        (as required)
+ *      - Ensuring correct endian-ness
+ */
+static int mwifiex_cmd_tx_power_cfg(struct host_cmd_ds_command *cmd,
+                                   u16 cmd_action,
+                                   struct host_cmd_ds_txpwr_cfg *txp)
+{
+       struct mwifiex_types_power_group *pg_tlv;
+       struct host_cmd_ds_txpwr_cfg *cmd_txp_cfg = &cmd->params.txp_cfg;
+
+       cmd->command = cpu_to_le16(HostCmd_CMD_TXPWR_CFG);
+       cmd->size =
+               cpu_to_le16(S_DS_GEN + sizeof(struct host_cmd_ds_txpwr_cfg));
+       switch (cmd_action) {
+       case HostCmd_ACT_GEN_SET:
+               if (txp->mode) {
+                       pg_tlv = (struct mwifiex_types_power_group
+                                 *) ((unsigned long) txp +
+                                    sizeof(struct host_cmd_ds_txpwr_cfg));
+                       memmove(cmd_txp_cfg, txp,
+                               sizeof(struct host_cmd_ds_txpwr_cfg) +
+                               sizeof(struct mwifiex_types_power_group) +
+                               le16_to_cpu(pg_tlv->length));
+
+                       pg_tlv = (struct mwifiex_types_power_group *) ((u8 *)
+                                 cmd_txp_cfg +
+                                 sizeof(struct host_cmd_ds_txpwr_cfg));
+                       cmd->size = cpu_to_le16(le16_to_cpu(cmd->size) +
+                                 sizeof(struct mwifiex_types_power_group) +
+                                 le16_to_cpu(pg_tlv->length));
+               } else {
+                       memmove(cmd_txp_cfg, txp, sizeof(*txp));
+               }
+               cmd_txp_cfg->action = cpu_to_le16(cmd_action);
+               break;
+       case HostCmd_ACT_GEN_GET:
+               cmd_txp_cfg->action = cpu_to_le16(cmd_action);
+               break;
+       }
+
+       return 0;
+}
+
+/*
+ * This function prepares command to get RF Tx power.
+ */
+static int mwifiex_cmd_rf_tx_power(struct mwifiex_private *priv,
+                                  struct host_cmd_ds_command *cmd,
+                                  u16 cmd_action, void *data_buf)
+{
+       struct host_cmd_ds_rf_tx_pwr *txp = &cmd->params.txp;
+
+       cmd->size = cpu_to_le16(sizeof(struct host_cmd_ds_rf_tx_pwr)
+                               + S_DS_GEN);
+       cmd->command = cpu_to_le16(HostCmd_CMD_RF_TX_PWR);
+       txp->action = cpu_to_le16(cmd_action);
+
+       return 0;
+}
+
+/*
+ * This function prepares command to set rf antenna.
+ */
+static int mwifiex_cmd_rf_antenna(struct mwifiex_private *priv,
+                                 struct host_cmd_ds_command *cmd,
+                                 u16 cmd_action,
+                                 struct mwifiex_ds_ant_cfg *ant_cfg)
+{
+       struct host_cmd_ds_rf_ant_mimo *ant_mimo = &cmd->params.ant_mimo;
+       struct host_cmd_ds_rf_ant_siso *ant_siso = &cmd->params.ant_siso;
+
+       cmd->command = cpu_to_le16(HostCmd_CMD_RF_ANTENNA);
+
+       if (cmd_action != HostCmd_ACT_GEN_SET)
+               return 0;
+
+       if (priv->adapter->hw_dev_mcs_support == HT_STREAM_2X2) {
+               cmd->size = cpu_to_le16(sizeof(struct host_cmd_ds_rf_ant_mimo) +
+                                       S_DS_GEN);
+               ant_mimo->action_tx = cpu_to_le16(HostCmd_ACT_SET_TX);
+               ant_mimo->tx_ant_mode = cpu_to_le16((u16)ant_cfg->tx_ant);
+               ant_mimo->action_rx = cpu_to_le16(HostCmd_ACT_SET_RX);
+               ant_mimo->rx_ant_mode = cpu_to_le16((u16)ant_cfg->rx_ant);
+       } else {
+               cmd->size = cpu_to_le16(sizeof(struct host_cmd_ds_rf_ant_siso) +
+                                       S_DS_GEN);
+               ant_siso->action = cpu_to_le16(HostCmd_ACT_SET_BOTH);
+               ant_siso->ant_mode = cpu_to_le16((u16)ant_cfg->tx_ant);
+       }
+
+       return 0;
+}
+
+/*
+ * This function prepares command to set Host Sleep configuration.
+ *
+ * Preparation includes -
+ *      - Setting command ID and proper size
+ *      - Setting Host Sleep action, conditions, ARP filters
+ *        (as required)
+ *      - Ensuring correct endian-ness
+ */
+static int
+mwifiex_cmd_802_11_hs_cfg(struct mwifiex_private *priv,
+                         struct host_cmd_ds_command *cmd,
+                         u16 cmd_action,
+                         struct mwifiex_hs_config_param *hscfg_param)
+{
+       struct mwifiex_adapter *adapter = priv->adapter;
+       struct host_cmd_ds_802_11_hs_cfg_enh *hs_cfg = &cmd->params.opt_hs_cfg;
+       bool hs_activate = false;
+
+       if (!hscfg_param)
+               /* New Activate command */
+               hs_activate = true;
+       cmd->command = cpu_to_le16(HostCmd_CMD_802_11_HS_CFG_ENH);
+
+       if (!hs_activate &&
+           (hscfg_param->conditions != cpu_to_le32(HS_CFG_CANCEL)) &&
+           ((adapter->arp_filter_size > 0) &&
+            (adapter->arp_filter_size <= ARP_FILTER_MAX_BUF_SIZE))) {
+               mwifiex_dbg(adapter, CMD,
+                           "cmd: Attach %d bytes ArpFilter to HSCfg cmd\n",
+                           adapter->arp_filter_size);
+               memcpy(((u8 *) hs_cfg) +
+                      sizeof(struct host_cmd_ds_802_11_hs_cfg_enh),
+                      adapter->arp_filter, adapter->arp_filter_size);
+               cmd->size = cpu_to_le16
+                               (adapter->arp_filter_size +
+                                sizeof(struct host_cmd_ds_802_11_hs_cfg_enh)
+                               + S_DS_GEN);
+       } else {
+               cmd->size = cpu_to_le16(S_DS_GEN + sizeof(struct
+                                               host_cmd_ds_802_11_hs_cfg_enh));
+       }
+       if (hs_activate) {
+               hs_cfg->action = cpu_to_le16(HS_ACTIVATE);
+               hs_cfg->params.hs_activate.resp_ctrl = cpu_to_le16(RESP_NEEDED);
+       } else {
+               hs_cfg->action = cpu_to_le16(HS_CONFIGURE);
+               hs_cfg->params.hs_config.conditions = hscfg_param->conditions;
+               hs_cfg->params.hs_config.gpio = hscfg_param->gpio;
+               hs_cfg->params.hs_config.gap = hscfg_param->gap;
+               mwifiex_dbg(adapter, CMD,
+                           "cmd: HS_CFG_CMD: condition:0x%x gpio:0x%x gap:0x%x\n",
+                           hs_cfg->params.hs_config.conditions,
+                           hs_cfg->params.hs_config.gpio,
+                           hs_cfg->params.hs_config.gap);
+       }
+
+       return 0;
+}
+
+/*
+ * This function prepares command to set/get MAC address.
+ *
+ * Preparation includes -
+ *      - Setting command ID, action and proper size
+ *      - Setting MAC address (for SET only)
+ *      - Ensuring correct endian-ness
+ */
+static int mwifiex_cmd_802_11_mac_address(struct mwifiex_private *priv,
+                                         struct host_cmd_ds_command *cmd,
+                                         u16 cmd_action)
+{
+       cmd->command = cpu_to_le16(HostCmd_CMD_802_11_MAC_ADDRESS);
+       cmd->size = cpu_to_le16(sizeof(struct host_cmd_ds_802_11_mac_address) +
+                               S_DS_GEN);
+       cmd->result = 0;
+
+       cmd->params.mac_addr.action = cpu_to_le16(cmd_action);
+
+       if (cmd_action == HostCmd_ACT_GEN_SET)
+               memcpy(cmd->params.mac_addr.mac_addr, priv->curr_addr,
+                      ETH_ALEN);
+       return 0;
+}
+
+/*
+ * This function prepares command to set MAC multicast address.
+ *
+ * Preparation includes -
+ *      - Setting command ID, action and proper size
+ *      - Setting MAC multicast address
+ *      - Ensuring correct endian-ness
+ */
+static int
+mwifiex_cmd_mac_multicast_adr(struct host_cmd_ds_command *cmd,
+                             u16 cmd_action,
+                             struct mwifiex_multicast_list *mcast_list)
+{
+       struct host_cmd_ds_mac_multicast_adr *mcast_addr = &cmd->params.mc_addr;
+
+       cmd->size = cpu_to_le16(sizeof(struct host_cmd_ds_mac_multicast_adr) +
+                               S_DS_GEN);
+       cmd->command = cpu_to_le16(HostCmd_CMD_MAC_MULTICAST_ADR);
+
+       mcast_addr->action = cpu_to_le16(cmd_action);
+       mcast_addr->num_of_adrs =
+               cpu_to_le16((u16) mcast_list->num_multicast_addr);
+       memcpy(mcast_addr->mac_list, mcast_list->mac_list,
+              mcast_list->num_multicast_addr * ETH_ALEN);
+
+       return 0;
+}
+
+/*
+ * This function prepares command to deauthenticate.
+ *
+ * Preparation includes -
+ *      - Setting command ID and proper size
+ *      - Setting AP MAC address and reason code
+ *      - Ensuring correct endian-ness
+ */
+static int mwifiex_cmd_802_11_deauthenticate(struct mwifiex_private *priv,
+                                            struct host_cmd_ds_command *cmd,
+                                            u8 *mac)
+{
+       struct host_cmd_ds_802_11_deauthenticate *deauth = &cmd->params.deauth;
+
+       cmd->command = cpu_to_le16(HostCmd_CMD_802_11_DEAUTHENTICATE);
+       cmd->size = cpu_to_le16(sizeof(struct host_cmd_ds_802_11_deauthenticate)
+                               + S_DS_GEN);
+
+       /* Set AP MAC address */
+       memcpy(deauth->mac_addr, mac, ETH_ALEN);
+
+       mwifiex_dbg(priv->adapter, CMD, "cmd: Deauth: %pM\n", deauth->mac_addr);
+
+       deauth->reason_code = cpu_to_le16(WLAN_REASON_DEAUTH_LEAVING);
+
+       return 0;
+}
+
+/*
+ * This function prepares command to stop Ad-Hoc network.
+ *
+ * Preparation includes -
+ *      - Setting command ID and proper size
+ *      - Ensuring correct endian-ness
+ */
+static int mwifiex_cmd_802_11_ad_hoc_stop(struct host_cmd_ds_command *cmd)
+{
+       cmd->command = cpu_to_le16(HostCmd_CMD_802_11_AD_HOC_STOP);
+       cmd->size = cpu_to_le16(S_DS_GEN);
+       return 0;
+}
+
+/*
+ * This function sets WEP key(s) to key parameter TLV(s).
+ *
+ * Multi-key parameter TLVs are supported, so we can send multiple
+ * WEP keys in a single buffer.
+ */
+static int
+mwifiex_set_keyparamset_wep(struct mwifiex_private *priv,
+                           struct mwifiex_ie_type_key_param_set *key_param_set,
+                           u16 *key_param_len)
+{
+       int cur_key_param_len;
+       u8 i;
+
+       /* Multi-key_param_set TLV is supported */
+       for (i = 0; i < NUM_WEP_KEYS; i++) {
+               if ((priv->wep_key[i].key_length == WLAN_KEY_LEN_WEP40) ||
+                   (priv->wep_key[i].key_length == WLAN_KEY_LEN_WEP104)) {
+                       key_param_set->type =
+                               cpu_to_le16(TLV_TYPE_KEY_MATERIAL);
+/* Key_param_set WEP fixed length */
+#define KEYPARAMSET_WEP_FIXED_LEN 8
+                       key_param_set->length = cpu_to_le16((u16)
+                                       (priv->wep_key[i].
+                                        key_length +
+                                        KEYPARAMSET_WEP_FIXED_LEN));
+                       key_param_set->key_type_id =
+                               cpu_to_le16(KEY_TYPE_ID_WEP);
+                       key_param_set->key_info =
+                               cpu_to_le16(KEY_ENABLED | KEY_UNICAST |
+                                           KEY_MCAST);
+                       key_param_set->key_len =
+                               cpu_to_le16(priv->wep_key[i].key_length);
+                       /* Set WEP key index */
+                       key_param_set->key[0] = i;
+                       /* Set default Tx key flag */
+                       if (i ==
+                           (priv->
+                            wep_key_curr_index & HostCmd_WEP_KEY_INDEX_MASK))
+                               key_param_set->key[1] = 1;
+                       else
+                               key_param_set->key[1] = 0;
+                       memmove(&key_param_set->key[2],
+                               priv->wep_key[i].key_material,
+                               priv->wep_key[i].key_length);
+
+                       cur_key_param_len = priv->wep_key[i].key_length +
+                               KEYPARAMSET_WEP_FIXED_LEN +
+                               sizeof(struct mwifiex_ie_types_header);
+                       *key_param_len += (u16) cur_key_param_len;
+                       key_param_set =
+                               (struct mwifiex_ie_type_key_param_set *)
+                                               ((u8 *)key_param_set +
+                                                cur_key_param_len);
+               } else if (!priv->wep_key[i].key_length) {
+                       continue;
+               } else {
+                       mwifiex_dbg(priv->adapter, ERROR,
+                                   "key%d Length = %d is incorrect\n",
+                                   (i + 1), priv->wep_key[i].key_length);
+                       return -1;
+               }
+       }
+
+       return 0;
+}
+
+/* This function populates key material v2 command
+ * to set network key for AES & CMAC AES.
+ */
+static int mwifiex_set_aes_key_v2(struct mwifiex_private *priv,
+                                 struct host_cmd_ds_command *cmd,
+                                 struct mwifiex_ds_encrypt_key *enc_key,
+                                 struct host_cmd_ds_802_11_key_material_v2 *km)
+{
+       struct mwifiex_adapter *adapter = priv->adapter;
+       u16 size, len = KEY_PARAMS_FIXED_LEN;
+
+       if (enc_key->is_igtk_key) {
+               mwifiex_dbg(adapter, INFO,
+                           "%s: Set CMAC AES Key\n", __func__);
+               if (enc_key->is_rx_seq_valid)
+                       memcpy(km->key_param_set.key_params.cmac_aes.ipn,
+                              enc_key->pn, enc_key->pn_len);
+               km->key_param_set.key_info &= cpu_to_le16(~KEY_MCAST);
+               km->key_param_set.key_info |= cpu_to_le16(KEY_IGTK);
+               km->key_param_set.key_type = KEY_TYPE_ID_AES_CMAC;
+               km->key_param_set.key_params.cmac_aes.key_len =
+                                         cpu_to_le16(enc_key->key_len);
+               memcpy(km->key_param_set.key_params.cmac_aes.key,
+                      enc_key->key_material, enc_key->key_len);
+               len += sizeof(struct mwifiex_cmac_aes_param);
+       } else {
+               mwifiex_dbg(adapter, INFO,
+                           "%s: Set AES Key\n", __func__);
+               if (enc_key->is_rx_seq_valid)
+                       memcpy(km->key_param_set.key_params.aes.pn,
+                              enc_key->pn, enc_key->pn_len);
+               km->key_param_set.key_type = KEY_TYPE_ID_AES;
+               km->key_param_set.key_params.aes.key_len =
+                                         cpu_to_le16(enc_key->key_len);
+               memcpy(km->key_param_set.key_params.aes.key,
+                      enc_key->key_material, enc_key->key_len);
+               len += sizeof(struct mwifiex_aes_param);
+       }
+
+       km->key_param_set.len = cpu_to_le16(len);
+       size = len + sizeof(struct mwifiex_ie_types_header) +
+              sizeof(km->action) + S_DS_GEN;
+       cmd->size = cpu_to_le16(size);
+
+       return 0;
+}
+
+/* This function prepares command to set/get/reset network key(s).
+ * This function prepares key material command for V2 format.
+ * Preparation includes -
+ *      - Setting command ID, action and proper size
+ *      - Setting WEP keys, WAPI keys or WPA keys along with required
+ *        encryption (TKIP, AES) (as required)
+ *      - Ensuring correct endian-ness
+ */
+static int
+mwifiex_cmd_802_11_key_material_v2(struct mwifiex_private *priv,
+                                  struct host_cmd_ds_command *cmd,
+                                  u16 cmd_action, u32 cmd_oid,
+                                  struct mwifiex_ds_encrypt_key *enc_key)
+{
+       struct mwifiex_adapter *adapter = priv->adapter;
+       u8 *mac = enc_key->mac_addr;
+       u16 key_info, len = KEY_PARAMS_FIXED_LEN;
+       struct host_cmd_ds_802_11_key_material_v2 *km =
+                                               &cmd->params.key_material_v2;
+
+       cmd->command = cpu_to_le16(HostCmd_CMD_802_11_KEY_MATERIAL);
+       km->action = cpu_to_le16(cmd_action);
+
+       if (cmd_action == HostCmd_ACT_GEN_GET) {
+               mwifiex_dbg(adapter, INFO, "%s: Get key\n", __func__);
+               km->key_param_set.key_idx =
+                                       enc_key->key_index & KEY_INDEX_MASK;
+               km->key_param_set.type = cpu_to_le16(TLV_TYPE_KEY_PARAM_V2);
+               km->key_param_set.len = cpu_to_le16(KEY_PARAMS_FIXED_LEN);
+               memcpy(km->key_param_set.mac_addr, mac, ETH_ALEN);
+
+               if (enc_key->key_index & MWIFIEX_KEY_INDEX_UNICAST)
+                       key_info = KEY_UNICAST;
+               else
+                       key_info = KEY_MCAST;
+
+               if (enc_key->is_igtk_key)
+                       key_info |= KEY_IGTK;
+
+               km->key_param_set.key_info = cpu_to_le16(key_info);
+
+               cmd->size = cpu_to_le16(sizeof(struct mwifiex_ie_types_header) +
+                                       S_DS_GEN + KEY_PARAMS_FIXED_LEN +
+                                       sizeof(km->action));
+               return 0;
+       }
+
+       memset(&km->key_param_set, 0,
+              sizeof(struct mwifiex_ie_type_key_param_set_v2));
+
+       if (enc_key->key_disable) {
+               mwifiex_dbg(adapter, INFO, "%s: Remove key\n", __func__);
+               km->action = cpu_to_le16(HostCmd_ACT_GEN_REMOVE);
+               km->key_param_set.type = cpu_to_le16(TLV_TYPE_KEY_PARAM_V2);
+               km->key_param_set.len = cpu_to_le16(KEY_PARAMS_FIXED_LEN);
+               km->key_param_set.key_idx = enc_key->key_index & KEY_INDEX_MASK;
+               key_info = KEY_MCAST | KEY_UNICAST;
+               km->key_param_set.key_info = cpu_to_le16(key_info);
+               memcpy(km->key_param_set.mac_addr, mac, ETH_ALEN);
+               cmd->size = cpu_to_le16(sizeof(struct mwifiex_ie_types_header) +
+                                       S_DS_GEN + KEY_PARAMS_FIXED_LEN +
+                                       sizeof(km->action));
+               return 0;
+       }
+
+       km->action = cpu_to_le16(HostCmd_ACT_GEN_SET);
+       km->key_param_set.key_idx = enc_key->key_index & KEY_INDEX_MASK;
+       km->key_param_set.type = cpu_to_le16(TLV_TYPE_KEY_PARAM_V2);
+       key_info = KEY_ENABLED;
+       memcpy(km->key_param_set.mac_addr, mac, ETH_ALEN);
+
+       if (enc_key->key_len <= WLAN_KEY_LEN_WEP104) {
+               mwifiex_dbg(adapter, INFO, "%s: Set WEP Key\n", __func__);
+               len += sizeof(struct mwifiex_wep_param);
+               km->key_param_set.len = cpu_to_le16(len);
+               km->key_param_set.key_type = KEY_TYPE_ID_WEP;
+
+               if (GET_BSS_ROLE(priv) == MWIFIEX_BSS_ROLE_UAP) {
+                               key_info |= KEY_MCAST | KEY_UNICAST;
+               } else {
+                       if (enc_key->is_current_wep_key) {
+                               key_info |= KEY_MCAST | KEY_UNICAST;
+                               if (km->key_param_set.key_idx ==
+                                   (priv->wep_key_curr_index & KEY_INDEX_MASK))
+                                       key_info |= KEY_DEFAULT;
+                       } else {
+                               if (mac) {
+                                       if (is_broadcast_ether_addr(mac))
+                                               key_info |= KEY_MCAST;
+                                       else
+                                               key_info |= KEY_UNICAST |
+                                                           KEY_DEFAULT;
+                               } else {
+                                       key_info |= KEY_MCAST;
+                               }
+                       }
+               }
+               km->key_param_set.key_info = cpu_to_le16(key_info);
+
+               km->key_param_set.key_params.wep.key_len =
+                                                 cpu_to_le16(enc_key->key_len);
+               memcpy(km->key_param_set.key_params.wep.key,
+                      enc_key->key_material, enc_key->key_len);
+
+               cmd->size = cpu_to_le16(sizeof(struct mwifiex_ie_types_header) +
+                                       len + sizeof(km->action) + S_DS_GEN);
+               return 0;
+       }
+
+       if (is_broadcast_ether_addr(mac))
+               key_info |= KEY_MCAST | KEY_RX_KEY;
+       else
+               key_info |= KEY_UNICAST | KEY_TX_KEY | KEY_RX_KEY;
+
+       if (enc_key->is_wapi_key) {
+               mwifiex_dbg(adapter, INFO, "%s: Set WAPI Key\n", __func__);
+               km->key_param_set.key_type = KEY_TYPE_ID_WAPI;
+               memcpy(km->key_param_set.key_params.wapi.pn, enc_key->pn,
+                      PN_LEN);
+               km->key_param_set.key_params.wapi.key_len =
+                                               cpu_to_le16(enc_key->key_len);
+               memcpy(km->key_param_set.key_params.wapi.key,
+                      enc_key->key_material, enc_key->key_len);
+               if (is_broadcast_ether_addr(mac))
+                       priv->sec_info.wapi_key_on = true;
+
+               if (!priv->sec_info.wapi_key_on)
+                       key_info |= KEY_DEFAULT;
+               km->key_param_set.key_info = cpu_to_le16(key_info);
+
+               len += sizeof(struct mwifiex_wapi_param);
+               km->key_param_set.len = cpu_to_le16(len);
+               cmd->size = cpu_to_le16(sizeof(struct mwifiex_ie_types_header) +
+                                       len + sizeof(km->action) + S_DS_GEN);
+               return 0;
+       }
+
+       if (priv->bss_mode == NL80211_IFTYPE_ADHOC) {
+               key_info |= KEY_DEFAULT;
+               /* Enable unicast bit for WPA-NONE/ADHOC_AES */
+               if (!priv->sec_info.wpa2_enabled &&
+                   !is_broadcast_ether_addr(mac))
+                       key_info |= KEY_UNICAST;
+       } else {
+               /* Enable default key for WPA/WPA2 */
+               if (!priv->wpa_is_gtk_set)
+                       key_info |= KEY_DEFAULT;
+       }
+
+       km->key_param_set.key_info = cpu_to_le16(key_info);
+
+       if (enc_key->key_len == WLAN_KEY_LEN_CCMP)
+               return mwifiex_set_aes_key_v2(priv, cmd, enc_key, km);
+
+       if (enc_key->key_len == WLAN_KEY_LEN_TKIP) {
+               mwifiex_dbg(adapter, INFO,
+                           "%s: Set TKIP Key\n", __func__);
+               if (enc_key->is_rx_seq_valid)
+                       memcpy(km->key_param_set.key_params.tkip.pn,
+                              enc_key->pn, enc_key->pn_len);
+               km->key_param_set.key_type = KEY_TYPE_ID_TKIP;
+               km->key_param_set.key_params.tkip.key_len =
+                                               cpu_to_le16(enc_key->key_len);
+               memcpy(km->key_param_set.key_params.tkip.key,
+                      enc_key->key_material, enc_key->key_len);
+
+               len += sizeof(struct mwifiex_tkip_param);
+               km->key_param_set.len = cpu_to_le16(len);
+               cmd->size = cpu_to_le16(sizeof(struct mwifiex_ie_types_header) +
+                                       len + sizeof(km->action) + S_DS_GEN);
+       }
+
+       return 0;
+}
+
+/*
+ * This function prepares command to set/get/reset network key(s).
+ * This function prepares key material command for V1 format.
+ *
+ * Preparation includes -
+ *      - Setting command ID, action and proper size
+ *      - Setting WEP keys, WAPI keys or WPA keys along with required
+ *        encryption (TKIP, AES) (as required)
+ *      - Ensuring correct endian-ness
+ */
+static int
+mwifiex_cmd_802_11_key_material_v1(struct mwifiex_private *priv,
+                                  struct host_cmd_ds_command *cmd,
+                                  u16 cmd_action, u32 cmd_oid,
+                                  struct mwifiex_ds_encrypt_key *enc_key)
+{
+       struct host_cmd_ds_802_11_key_material *key_material =
+               &cmd->params.key_material;
+       struct host_cmd_tlv_mac_addr *tlv_mac;
+       u16 key_param_len = 0, cmd_size;
+       int ret = 0;
+
+       cmd->command = cpu_to_le16(HostCmd_CMD_802_11_KEY_MATERIAL);
+       key_material->action = cpu_to_le16(cmd_action);
+
+       if (cmd_action == HostCmd_ACT_GEN_GET) {
+               cmd->size =
+                       cpu_to_le16(sizeof(key_material->action) + S_DS_GEN);
+               return ret;
+       }
+
+       if (!enc_key) {
+               memset(&key_material->key_param_set, 0,
+                      (NUM_WEP_KEYS *
+                       sizeof(struct mwifiex_ie_type_key_param_set)));
+               ret = mwifiex_set_keyparamset_wep(priv,
+                                                 &key_material->key_param_set,
+                                                 &key_param_len);
+               cmd->size = cpu_to_le16(key_param_len +
+                                   sizeof(key_material->action) + S_DS_GEN);
+               return ret;
+       } else
+               memset(&key_material->key_param_set, 0,
+                      sizeof(struct mwifiex_ie_type_key_param_set));
+       if (enc_key->is_wapi_key) {
+               mwifiex_dbg(priv->adapter, INFO, "info: Set WAPI Key\n");
+               key_material->key_param_set.key_type_id =
+                                               cpu_to_le16(KEY_TYPE_ID_WAPI);
+               if (cmd_oid == KEY_INFO_ENABLED)
+                       key_material->key_param_set.key_info =
+                                               cpu_to_le16(KEY_ENABLED);
+               else
+                       key_material->key_param_set.key_info =
+                                               cpu_to_le16(!KEY_ENABLED);
+
+               key_material->key_param_set.key[0] = enc_key->key_index;
+               if (!priv->sec_info.wapi_key_on)
+                       key_material->key_param_set.key[1] = 1;
+               else
+                       /* set 0 when re-key */
+                       key_material->key_param_set.key[1] = 0;
+
+               if (!is_broadcast_ether_addr(enc_key->mac_addr)) {
+                       /* WAPI pairwise key: unicast */
+                       key_material->key_param_set.key_info |=
+                               cpu_to_le16(KEY_UNICAST);
+               } else {        /* WAPI group key: multicast */
+                       key_material->key_param_set.key_info |=
+                               cpu_to_le16(KEY_MCAST);
+                       priv->sec_info.wapi_key_on = true;
+               }
+
+               key_material->key_param_set.type =
+                                       cpu_to_le16(TLV_TYPE_KEY_MATERIAL);
+               key_material->key_param_set.key_len =
+                                               cpu_to_le16(WAPI_KEY_LEN);
+               memcpy(&key_material->key_param_set.key[2],
+                      enc_key->key_material, enc_key->key_len);
+               memcpy(&key_material->key_param_set.key[2 + enc_key->key_len],
+                      enc_key->pn, PN_LEN);
+               key_material->key_param_set.length =
+                       cpu_to_le16(WAPI_KEY_LEN + KEYPARAMSET_FIXED_LEN);
+
+               key_param_len = (WAPI_KEY_LEN + KEYPARAMSET_FIXED_LEN) +
+                                sizeof(struct mwifiex_ie_types_header);
+               cmd->size = cpu_to_le16(sizeof(key_material->action)
+                                       + S_DS_GEN +  key_param_len);
+               return ret;
+       }
+       if (enc_key->key_len == WLAN_KEY_LEN_CCMP) {
+               if (enc_key->is_igtk_key) {
+                       mwifiex_dbg(priv->adapter, CMD, "cmd: CMAC_AES\n");
+                       key_material->key_param_set.key_type_id =
+                                       cpu_to_le16(KEY_TYPE_ID_AES_CMAC);
+                       if (cmd_oid == KEY_INFO_ENABLED)
+                               key_material->key_param_set.key_info =
+                                               cpu_to_le16(KEY_ENABLED);
+                       else
+                               key_material->key_param_set.key_info =
+                                               cpu_to_le16(!KEY_ENABLED);
+
+                       key_material->key_param_set.key_info |=
+                                                       cpu_to_le16(KEY_IGTK);
+               } else {
+                       mwifiex_dbg(priv->adapter, CMD, "cmd: WPA_AES\n");
+                       key_material->key_param_set.key_type_id =
+                                               cpu_to_le16(KEY_TYPE_ID_AES);
+                       if (cmd_oid == KEY_INFO_ENABLED)
+                               key_material->key_param_set.key_info =
+                                               cpu_to_le16(KEY_ENABLED);
+                       else
+                               key_material->key_param_set.key_info =
+                                               cpu_to_le16(!KEY_ENABLED);
+
+                       if (enc_key->key_index & MWIFIEX_KEY_INDEX_UNICAST)
+                               /* AES pairwise key: unicast */
+                               key_material->key_param_set.key_info |=
+                                               cpu_to_le16(KEY_UNICAST);
+                       else    /* AES group key: multicast */
+                               key_material->key_param_set.key_info |=
+                                                       cpu_to_le16(KEY_MCAST);
+               }
+       } else if (enc_key->key_len == WLAN_KEY_LEN_TKIP) {
+               mwifiex_dbg(priv->adapter, CMD, "cmd: WPA_TKIP\n");
+               key_material->key_param_set.key_type_id =
+                                               cpu_to_le16(KEY_TYPE_ID_TKIP);
+               key_material->key_param_set.key_info =
+                                               cpu_to_le16(KEY_ENABLED);
+
+               if (enc_key->key_index & MWIFIEX_KEY_INDEX_UNICAST)
+                               /* TKIP pairwise key: unicast */
+                       key_material->key_param_set.key_info |=
+                                               cpu_to_le16(KEY_UNICAST);
+               else            /* TKIP group key: multicast */
+                       key_material->key_param_set.key_info |=
+                                                       cpu_to_le16(KEY_MCAST);
+       }
+
+       if (key_material->key_param_set.key_type_id) {
+               key_material->key_param_set.type =
+                                       cpu_to_le16(TLV_TYPE_KEY_MATERIAL);
+               key_material->key_param_set.key_len =
+                                       cpu_to_le16((u16) enc_key->key_len);
+               memcpy(key_material->key_param_set.key, enc_key->key_material,
+                      enc_key->key_len);
+               key_material->key_param_set.length =
+                       cpu_to_le16((u16) enc_key->key_len +
+                                   KEYPARAMSET_FIXED_LEN);
+
+               key_param_len = (u16)(enc_key->key_len + KEYPARAMSET_FIXED_LEN)
+                               + sizeof(struct mwifiex_ie_types_header);
+
+               if (le16_to_cpu(key_material->key_param_set.key_type_id) ==
+                                                       KEY_TYPE_ID_AES_CMAC) {
+                       struct mwifiex_cmac_param *param =
+                                       (void *)key_material->key_param_set.key;
+
+                       memcpy(param->ipn, enc_key->pn, IGTK_PN_LEN);
+                       memcpy(param->key, enc_key->key_material,
+                              WLAN_KEY_LEN_AES_CMAC);
+
+                       key_param_len = sizeof(struct mwifiex_cmac_param);
+                       key_material->key_param_set.key_len =
+                                               cpu_to_le16(key_param_len);
+                       key_param_len += KEYPARAMSET_FIXED_LEN;
+                       key_material->key_param_set.length =
+                                               cpu_to_le16(key_param_len);
+                       key_param_len += sizeof(struct mwifiex_ie_types_header);
+               }
+
+               cmd->size = cpu_to_le16(sizeof(key_material->action) + S_DS_GEN
+                                       + key_param_len);
+
+               if (GET_BSS_ROLE(priv) == MWIFIEX_BSS_ROLE_UAP) {
+                       tlv_mac = (void *)((u8 *)&key_material->key_param_set +
+                                          key_param_len);
+                       tlv_mac->header.type =
+                                       cpu_to_le16(TLV_TYPE_STA_MAC_ADDR);
+                       tlv_mac->header.len = cpu_to_le16(ETH_ALEN);
+                       memcpy(tlv_mac->mac_addr, enc_key->mac_addr, ETH_ALEN);
+                       cmd_size = key_param_len + S_DS_GEN +
+                                  sizeof(key_material->action) +
+                                  sizeof(struct host_cmd_tlv_mac_addr);
+               } else {
+                       cmd_size = key_param_len + S_DS_GEN +
+                                  sizeof(key_material->action);
+               }
+               cmd->size = cpu_to_le16(cmd_size);
+       }
+
+       return ret;
+}
+
+/* Wrapper function for setting network key depending upon FW KEY API version */
+static int
+mwifiex_cmd_802_11_key_material(struct mwifiex_private *priv,
+                               struct host_cmd_ds_command *cmd,
+                               u16 cmd_action, u32 cmd_oid,
+                               struct mwifiex_ds_encrypt_key *enc_key)
+{
+       if (priv->adapter->key_api_major_ver == KEY_API_VER_MAJOR_V2)
+               return mwifiex_cmd_802_11_key_material_v2(priv, cmd,
+                                                         cmd_action, cmd_oid,
+                                                         enc_key);
+
+       else
+               return mwifiex_cmd_802_11_key_material_v1(priv, cmd,
+                                                         cmd_action, cmd_oid,
+                                                         enc_key);
+}
+
+/*
+ * This function prepares command to set/get 11d domain information.
+ *
+ * Preparation includes -
+ *      - Setting command ID, action and proper size
+ *      - Setting domain information fields (for SET only)
+ *      - Ensuring correct endian-ness
+ */
+static int mwifiex_cmd_802_11d_domain_info(struct mwifiex_private *priv,
+                                          struct host_cmd_ds_command *cmd,
+                                          u16 cmd_action)
+{
+       struct mwifiex_adapter *adapter = priv->adapter;
+       struct host_cmd_ds_802_11d_domain_info *domain_info =
+               &cmd->params.domain_info;
+       struct mwifiex_ietypes_domain_param_set *domain =
+               &domain_info->domain;
+       u8 no_of_triplet = adapter->domain_reg.no_of_triplet;
+
+       mwifiex_dbg(adapter, INFO,
+                   "info: 11D: no_of_triplet=0x%x\n", no_of_triplet);
+
+       cmd->command = cpu_to_le16(HostCmd_CMD_802_11D_DOMAIN_INFO);
+       domain_info->action = cpu_to_le16(cmd_action);
+       if (cmd_action == HostCmd_ACT_GEN_GET) {
+               cmd->size = cpu_to_le16(sizeof(domain_info->action) + S_DS_GEN);
+               return 0;
+       }
+
+       /* Set domain info fields */
+       domain->header.type = cpu_to_le16(WLAN_EID_COUNTRY);
+       memcpy(domain->country_code, adapter->domain_reg.country_code,
+              sizeof(domain->country_code));
+
+       domain->header.len =
+               cpu_to_le16((no_of_triplet *
+                            sizeof(struct ieee80211_country_ie_triplet))
+                           + sizeof(domain->country_code));
+
+       if (no_of_triplet) {
+               memcpy(domain->triplet, adapter->domain_reg.triplet,
+                      no_of_triplet * sizeof(struct
+                                             ieee80211_country_ie_triplet));
+
+               cmd->size = cpu_to_le16(sizeof(domain_info->action) +
+                                       le16_to_cpu(domain->header.len) +
+                                       sizeof(struct mwifiex_ie_types_header)
+                                       + S_DS_GEN);
+       } else {
+               cmd->size = cpu_to_le16(sizeof(domain_info->action) + S_DS_GEN);
+       }
+
+       return 0;
+}
+
+/*
+ * This function prepares command to set/get IBSS coalescing status.
+ *
+ * Preparation includes -
+ *      - Setting command ID, action and proper size
+ *      - Setting status to enable or disable (for SET only)
+ *      - Ensuring correct endian-ness
+ */
+static int mwifiex_cmd_ibss_coalescing_status(struct host_cmd_ds_command *cmd,
+                                             u16 cmd_action, u16 *enable)
+{
+       struct host_cmd_ds_802_11_ibss_status *ibss_coal =
+               &(cmd->params.ibss_coalescing);
+
+       cmd->command = cpu_to_le16(HostCmd_CMD_802_11_IBSS_COALESCING_STATUS);
+       cmd->size = cpu_to_le16(sizeof(struct host_cmd_ds_802_11_ibss_status) +
+                               S_DS_GEN);
+       cmd->result = 0;
+       ibss_coal->action = cpu_to_le16(cmd_action);
+
+       switch (cmd_action) {
+       case HostCmd_ACT_GEN_SET:
+               if (enable)
+                       ibss_coal->enable = cpu_to_le16(*enable);
+               else
+                       ibss_coal->enable = 0;
+               break;
+
+               /* In other case.. Nothing to do */
+       case HostCmd_ACT_GEN_GET:
+       default:
+               break;
+       }
+
+       return 0;
+}
+
+/* This function prepares command buffer to get/set memory location value.
+ */
+static int
+mwifiex_cmd_mem_access(struct host_cmd_ds_command *cmd, u16 cmd_action,
+                      void *pdata_buf)
+{
+       struct mwifiex_ds_mem_rw *mem_rw = (void *)pdata_buf;
+       struct host_cmd_ds_mem_access *mem_access = (void *)&cmd->params.mem;
+
+       cmd->command = cpu_to_le16(HostCmd_CMD_MEM_ACCESS);
+       cmd->size = cpu_to_le16(sizeof(struct host_cmd_ds_mem_access) +
+                               S_DS_GEN);
+
+       mem_access->action = cpu_to_le16(cmd_action);
+       mem_access->addr = cpu_to_le32(mem_rw->addr);
+       mem_access->value = cpu_to_le32(mem_rw->value);
+
+       return 0;
+}
+
+/*
+ * This function prepares command to set/get register value.
+ *
+ * Preparation includes -
+ *      - Setting command ID, action and proper size
+ *      - Setting register offset (for both GET and SET) and
+ *        register value (for SET only)
+ *      - Ensuring correct endian-ness
+ *
+ * The following type of registers can be accessed with this function -
+ *      - MAC register
+ *      - BBP register
+ *      - RF register
+ *      - PMIC register
+ *      - CAU register
+ *      - EEPROM
+ */
+static int mwifiex_cmd_reg_access(struct host_cmd_ds_command *cmd,
+                                 u16 cmd_action, void *data_buf)
+{
+       struct mwifiex_ds_reg_rw *reg_rw = data_buf;
+
+       switch (le16_to_cpu(cmd->command)) {
+       case HostCmd_CMD_MAC_REG_ACCESS:
+       {
+               struct host_cmd_ds_mac_reg_access *mac_reg;
+
+               cmd->size = cpu_to_le16(sizeof(*mac_reg) + S_DS_GEN);
+               mac_reg = &cmd->params.mac_reg;
+               mac_reg->action = cpu_to_le16(cmd_action);
+               mac_reg->offset =
+                       cpu_to_le16((u16) le32_to_cpu(reg_rw->offset));
+               mac_reg->value = reg_rw->value;
+               break;
+       }
+       case HostCmd_CMD_BBP_REG_ACCESS:
+       {
+               struct host_cmd_ds_bbp_reg_access *bbp_reg;
+
+               cmd->size = cpu_to_le16(sizeof(*bbp_reg) + S_DS_GEN);
+               bbp_reg = &cmd->params.bbp_reg;
+               bbp_reg->action = cpu_to_le16(cmd_action);
+               bbp_reg->offset =
+                       cpu_to_le16((u16) le32_to_cpu(reg_rw->offset));
+               bbp_reg->value = (u8) le32_to_cpu(reg_rw->value);
+               break;
+       }
+       case HostCmd_CMD_RF_REG_ACCESS:
+       {
+               struct host_cmd_ds_rf_reg_access *rf_reg;
+
+               cmd->size = cpu_to_le16(sizeof(*rf_reg) + S_DS_GEN);
+               rf_reg = &cmd->params.rf_reg;
+               rf_reg->action = cpu_to_le16(cmd_action);
+               rf_reg->offset = cpu_to_le16((u16) le32_to_cpu(reg_rw->offset));
+               rf_reg->value = (u8) le32_to_cpu(reg_rw->value);
+               break;
+       }
+       case HostCmd_CMD_PMIC_REG_ACCESS:
+       {
+               struct host_cmd_ds_pmic_reg_access *pmic_reg;
+
+               cmd->size = cpu_to_le16(sizeof(*pmic_reg) + S_DS_GEN);
+               pmic_reg = &cmd->params.pmic_reg;
+               pmic_reg->action = cpu_to_le16(cmd_action);
+               pmic_reg->offset =
+                               cpu_to_le16((u16) le32_to_cpu(reg_rw->offset));
+               pmic_reg->value = (u8) le32_to_cpu(reg_rw->value);
+               break;
+       }
+       case HostCmd_CMD_CAU_REG_ACCESS:
+       {
+               struct host_cmd_ds_rf_reg_access *cau_reg;
+
+               cmd->size = cpu_to_le16(sizeof(*cau_reg) + S_DS_GEN);
+               cau_reg = &cmd->params.rf_reg;
+               cau_reg->action = cpu_to_le16(cmd_action);
+               cau_reg->offset =
+                               cpu_to_le16((u16) le32_to_cpu(reg_rw->offset));
+               cau_reg->value = (u8) le32_to_cpu(reg_rw->value);
+               break;
+       }
+       case HostCmd_CMD_802_11_EEPROM_ACCESS:
+       {
+               struct mwifiex_ds_read_eeprom *rd_eeprom = data_buf;
+               struct host_cmd_ds_802_11_eeprom_access *cmd_eeprom =
+                       &cmd->params.eeprom;
+
+               cmd->size = cpu_to_le16(sizeof(*cmd_eeprom) + S_DS_GEN);
+               cmd_eeprom->action = cpu_to_le16(cmd_action);
+               cmd_eeprom->offset = rd_eeprom->offset;
+               cmd_eeprom->byte_count = rd_eeprom->byte_count;
+               cmd_eeprom->value = 0;
+               break;
+       }
+       default:
+               return -1;
+       }
+
+       return 0;
+}
+
+/*
+ * This function prepares command to set PCI-Express
+ * host buffer configuration
+ *
+ * Preparation includes -
+ *      - Setting command ID, action and proper size
+ *      - Setting host buffer configuration
+ *      - Ensuring correct endian-ness
+ */
+static int
+mwifiex_cmd_pcie_host_spec(struct mwifiex_private *priv,
+                          struct host_cmd_ds_command *cmd, u16 action)
+{
+       struct host_cmd_ds_pcie_details *host_spec =
+                                       &cmd->params.pcie_host_spec;
+       struct pcie_service_card *card = priv->adapter->card;
+
+       cmd->command = cpu_to_le16(HostCmd_CMD_PCIE_DESC_DETAILS);
+       cmd->size = cpu_to_le16(sizeof(struct
+                                       host_cmd_ds_pcie_details) + S_DS_GEN);
+       cmd->result = 0;
+
+       memset(host_spec, 0, sizeof(struct host_cmd_ds_pcie_details));
+
+       if (action != HostCmd_ACT_GEN_SET)
+               return 0;
+
+       /* Send the ring base addresses and count to firmware */
+       host_spec->txbd_addr_lo = (u32)(card->txbd_ring_pbase);
+       host_spec->txbd_addr_hi = (u32)(((u64)card->txbd_ring_pbase)>>32);
+       host_spec->txbd_count = MWIFIEX_MAX_TXRX_BD;
+       host_spec->rxbd_addr_lo = (u32)(card->rxbd_ring_pbase);
+       host_spec->rxbd_addr_hi = (u32)(((u64)card->rxbd_ring_pbase)>>32);
+       host_spec->rxbd_count = MWIFIEX_MAX_TXRX_BD;
+       host_spec->evtbd_addr_lo = (u32)(card->evtbd_ring_pbase);
+       host_spec->evtbd_addr_hi = (u32)(((u64)card->evtbd_ring_pbase)>>32);
+       host_spec->evtbd_count = MWIFIEX_MAX_EVT_BD;
+       if (card->sleep_cookie_vbase) {
+               host_spec->sleep_cookie_addr_lo =
+                                               (u32)(card->sleep_cookie_pbase);
+               host_spec->sleep_cookie_addr_hi =
+                                (u32)(((u64)(card->sleep_cookie_pbase)) >> 32);
+               mwifiex_dbg(priv->adapter, INFO,
+                           "sleep_cook_lo phy addr: 0x%x\n",
+                           host_spec->sleep_cookie_addr_lo);
+       }
+
+       return 0;
+}
+
+/*
+ * This function prepares command for event subscription, configuration
+ * and query. Events can be subscribed or unsubscribed. Current subscribed
+ * events can be queried. Also, current subscribed events are reported in
+ * every FW response.
+ */
+static int
+mwifiex_cmd_802_11_subsc_evt(struct mwifiex_private *priv,
+                            struct host_cmd_ds_command *cmd,
+                            struct mwifiex_ds_misc_subsc_evt *subsc_evt_cfg)
+{
+       struct host_cmd_ds_802_11_subsc_evt *subsc_evt = &cmd->params.subsc_evt;
+       struct mwifiex_ie_types_rssi_threshold *rssi_tlv;
+       u16 event_bitmap;
+       u8 *pos;
+
+       cmd->command = cpu_to_le16(HostCmd_CMD_802_11_SUBSCRIBE_EVENT);
+       cmd->size = cpu_to_le16(sizeof(struct host_cmd_ds_802_11_subsc_evt) +
+                               S_DS_GEN);
+
+       subsc_evt->action = cpu_to_le16(subsc_evt_cfg->action);
+       mwifiex_dbg(priv->adapter, CMD,
+                   "cmd: action: %d\n", subsc_evt_cfg->action);
+
+       /*For query requests, no configuration TLV structures are to be added.*/
+       if (subsc_evt_cfg->action == HostCmd_ACT_GEN_GET)
+               return 0;
+
+       subsc_evt->events = cpu_to_le16(subsc_evt_cfg->events);
+
+       event_bitmap = subsc_evt_cfg->events;
+       mwifiex_dbg(priv->adapter, CMD, "cmd: event bitmap : %16x\n",
+                   event_bitmap);
+
+       if (((subsc_evt_cfg->action == HostCmd_ACT_BITWISE_CLR) ||
+            (subsc_evt_cfg->action == HostCmd_ACT_BITWISE_SET)) &&
+           (event_bitmap == 0)) {
+               mwifiex_dbg(priv->adapter, ERROR,
+                           "Error: No event specified\t"
+                           "for bitwise action type\n");
+               return -EINVAL;
+       }
+
+       /*
+        * Append TLV structures for each of the specified events for
+        * subscribing or re-configuring. This is not required for
+        * bitwise unsubscribing request.
+        */
+       if (subsc_evt_cfg->action == HostCmd_ACT_BITWISE_CLR)
+               return 0;
+
+       pos = ((u8 *)subsc_evt) +
+                       sizeof(struct host_cmd_ds_802_11_subsc_evt);
+
+       if (event_bitmap & BITMASK_BCN_RSSI_LOW) {
+               rssi_tlv = (struct mwifiex_ie_types_rssi_threshold *) pos;
+
+               rssi_tlv->header.type = cpu_to_le16(TLV_TYPE_RSSI_LOW);
+               rssi_tlv->header.len =
+                   cpu_to_le16(sizeof(struct mwifiex_ie_types_rssi_threshold) -
+                               sizeof(struct mwifiex_ie_types_header));
+               rssi_tlv->abs_value = subsc_evt_cfg->bcn_l_rssi_cfg.abs_value;
+               rssi_tlv->evt_freq = subsc_evt_cfg->bcn_l_rssi_cfg.evt_freq;
+
+               mwifiex_dbg(priv->adapter, EVENT,
+                           "Cfg Beacon Low Rssi event,\t"
+                           "RSSI:-%d dBm, Freq:%d\n",
+                           subsc_evt_cfg->bcn_l_rssi_cfg.abs_value,
+                           subsc_evt_cfg->bcn_l_rssi_cfg.evt_freq);
+
+               pos += sizeof(struct mwifiex_ie_types_rssi_threshold);
+               le16_add_cpu(&cmd->size,
+                            sizeof(struct mwifiex_ie_types_rssi_threshold));
+       }
+
+       if (event_bitmap & BITMASK_BCN_RSSI_HIGH) {
+               rssi_tlv = (struct mwifiex_ie_types_rssi_threshold *) pos;
+
+               rssi_tlv->header.type = cpu_to_le16(TLV_TYPE_RSSI_HIGH);
+               rssi_tlv->header.len =
+                   cpu_to_le16(sizeof(struct mwifiex_ie_types_rssi_threshold) -
+                               sizeof(struct mwifiex_ie_types_header));
+               rssi_tlv->abs_value = subsc_evt_cfg->bcn_h_rssi_cfg.abs_value;
+               rssi_tlv->evt_freq = subsc_evt_cfg->bcn_h_rssi_cfg.evt_freq;
+
+               mwifiex_dbg(priv->adapter, EVENT,
+                           "Cfg Beacon High Rssi event,\t"
+                           "RSSI:-%d dBm, Freq:%d\n",
+                           subsc_evt_cfg->bcn_h_rssi_cfg.abs_value,
+                           subsc_evt_cfg->bcn_h_rssi_cfg.evt_freq);
+
+               pos += sizeof(struct mwifiex_ie_types_rssi_threshold);
+               le16_add_cpu(&cmd->size,
+                            sizeof(struct mwifiex_ie_types_rssi_threshold));
+       }
+
+       return 0;
+}
+
+static int
+mwifiex_cmd_append_rpn_expression(struct mwifiex_private *priv,
+                                 struct mwifiex_mef_entry *mef_entry,
+                                 u8 **buffer)
+{
+       struct mwifiex_mef_filter *filter = mef_entry->filter;
+       int i, byte_len;
+       u8 *stack_ptr = *buffer;
+
+       for (i = 0; i < MWIFIEX_MEF_MAX_FILTERS; i++) {
+               filter = &mef_entry->filter[i];
+               if (!filter->filt_type)
+                       break;
+               *(__le32 *)stack_ptr = cpu_to_le32((u32)filter->repeat);
+               stack_ptr += 4;
+               *stack_ptr = TYPE_DNUM;
+               stack_ptr += 1;
+
+               byte_len = filter->byte_seq[MWIFIEX_MEF_MAX_BYTESEQ];
+               memcpy(stack_ptr, filter->byte_seq, byte_len);
+               stack_ptr += byte_len;
+               *stack_ptr = byte_len;
+               stack_ptr += 1;
+               *stack_ptr = TYPE_BYTESEQ;
+               stack_ptr += 1;
+
+               *(__le32 *)stack_ptr = cpu_to_le32((u32)filter->offset);
+               stack_ptr += 4;
+               *stack_ptr = TYPE_DNUM;
+               stack_ptr += 1;
+
+               *stack_ptr = filter->filt_type;
+               stack_ptr += 1;
+
+               if (filter->filt_action) {
+                       *stack_ptr = filter->filt_action;
+                       stack_ptr += 1;
+               }
+
+               if (stack_ptr - *buffer > STACK_NBYTES)
+                       return -1;
+       }
+
+       *buffer = stack_ptr;
+       return 0;
+}
+
+static int
+mwifiex_cmd_mef_cfg(struct mwifiex_private *priv,
+                   struct host_cmd_ds_command *cmd,
+                   struct mwifiex_ds_mef_cfg *mef)
+{
+       struct host_cmd_ds_mef_cfg *mef_cfg = &cmd->params.mef_cfg;
+       struct mwifiex_fw_mef_entry *mef_entry = NULL;
+       u8 *pos = (u8 *)mef_cfg;
+       u16 i;
+
+       cmd->command = cpu_to_le16(HostCmd_CMD_MEF_CFG);
+
+       mef_cfg->criteria = cpu_to_le32(mef->criteria);
+       mef_cfg->num_entries = cpu_to_le16(mef->num_entries);
+       pos += sizeof(*mef_cfg);
+
+       for (i = 0; i < mef->num_entries; i++) {
+               mef_entry = (struct mwifiex_fw_mef_entry *)pos;
+               mef_entry->mode = mef->mef_entry[i].mode;
+               mef_entry->action = mef->mef_entry[i].action;
+               pos += sizeof(*mef_cfg->mef_entry);
+
+               if (mwifiex_cmd_append_rpn_expression(priv,
+                                                     &mef->mef_entry[i], &pos))
+                       return -1;
+
+               mef_entry->exprsize =
+                       cpu_to_le16(pos - mef_entry->expr);
+       }
+       cmd->size = cpu_to_le16((u16) (pos - (u8 *)mef_cfg) + S_DS_GEN);
+
+       return 0;
+}
+
+/* This function parse cal data from ASCII to hex */
+static u32 mwifiex_parse_cal_cfg(u8 *src, size_t len, u8 *dst)
+{
+       u8 *s = src, *d = dst;
+
+       while (s - src < len) {
+               if (*s && (isspace(*s) || *s == '\t')) {
+                       s++;
+                       continue;
+               }
+               if (isxdigit(*s)) {
+                       *d++ = simple_strtol(s, NULL, 16);
+                       s += 2;
+               } else {
+                       s++;
+               }
+       }
+
+       return d - dst;
+}
+
+int mwifiex_dnld_dt_cfgdata(struct mwifiex_private *priv,
+                           struct device_node *node, const char *prefix)
+{
+#ifdef CONFIG_OF
+       struct property *prop;
+       size_t len = strlen(prefix);
+       int ret;
+
+       /* look for all matching property names */
+       for_each_property_of_node(node, prop) {
+               if (len > strlen(prop->name) ||
+                   strncmp(prop->name, prefix, len))
+                       continue;
+
+               /* property header is 6 bytes, data must fit in cmd buffer */
+               if (prop && prop->value && prop->length > 6 &&
+                   prop->length <= MWIFIEX_SIZE_OF_CMD_BUFFER - S_DS_GEN) {
+                       ret = mwifiex_send_cmd(priv, HostCmd_CMD_CFG_DATA,
+                                              HostCmd_ACT_GEN_SET, 0,
+                                              prop, true);
+                       if (ret)
+                               return ret;
+               }
+       }
+#endif
+       return 0;
+}
+
+/* This function prepares command of set_cfg_data. */
+static int mwifiex_cmd_cfg_data(struct mwifiex_private *priv,
+                               struct host_cmd_ds_command *cmd, void *data_buf)
+{
+       struct mwifiex_adapter *adapter = priv->adapter;
+       struct property *prop = data_buf;
+       u32 len;
+       u8 *data = (u8 *)cmd + S_DS_GEN;
+       int ret;
+
+       if (prop) {
+               len = prop->length;
+               ret = of_property_read_u8_array(adapter->dt_node, prop->name,
+                                               data, len);
+               if (ret)
+                       return ret;
+               mwifiex_dbg(adapter, INFO,
+                           "download cfg_data from device tree: %s\n",
+                           prop->name);
+       } else if (adapter->cal_data->data && adapter->cal_data->size > 0) {
+               len = mwifiex_parse_cal_cfg((u8 *)adapter->cal_data->data,
+                                           adapter->cal_data->size, data);
+               mwifiex_dbg(adapter, INFO,
+                           "download cfg_data from config file\n");
+       } else {
+               return -1;
+       }
+
+       cmd->command = cpu_to_le16(HostCmd_CMD_CFG_DATA);
+       cmd->size = cpu_to_le16(S_DS_GEN + len);
+
+       return 0;
+}
+
+static int
+mwifiex_cmd_set_mc_policy(struct mwifiex_private *priv,
+                         struct host_cmd_ds_command *cmd,
+                         u16 cmd_action, void *data_buf)
+{
+       struct host_cmd_ds_multi_chan_policy *mc_pol = &cmd->params.mc_policy;
+       const u16 *drcs_info = data_buf;
+
+       mc_pol->action = cpu_to_le16(cmd_action);
+       mc_pol->policy = cpu_to_le16(*drcs_info);
+       cmd->command = cpu_to_le16(HostCmd_CMD_MC_POLICY);
+       cmd->size = cpu_to_le16(sizeof(struct host_cmd_ds_multi_chan_policy) +
+                               S_DS_GEN);
+       return 0;
+}
+
+static int mwifiex_cmd_robust_coex(struct mwifiex_private *priv,
+                                  struct host_cmd_ds_command *cmd,
+                                  u16 cmd_action, bool *is_timeshare)
+{
+       struct host_cmd_ds_robust_coex *coex = &cmd->params.coex;
+       struct mwifiex_ie_types_robust_coex *coex_tlv;
+
+       cmd->command = cpu_to_le16(HostCmd_CMD_ROBUST_COEX);
+       cmd->size = cpu_to_le16(sizeof(*coex) + sizeof(*coex_tlv) + S_DS_GEN);
+
+       coex->action = cpu_to_le16(cmd_action);
+       coex_tlv = (struct mwifiex_ie_types_robust_coex *)
+                               ((u8 *)coex + sizeof(*coex));
+       coex_tlv->header.type = cpu_to_le16(TLV_TYPE_ROBUST_COEX);
+       coex_tlv->header.len = cpu_to_le16(sizeof(coex_tlv->mode));
+
+       if (coex->action == HostCmd_ACT_GEN_GET)
+               return 0;
+
+       if (*is_timeshare)
+               coex_tlv->mode = cpu_to_le32(MWIFIEX_COEX_MODE_TIMESHARE);
+       else
+               coex_tlv->mode = cpu_to_le32(MWIFIEX_COEX_MODE_SPATIAL);
+
+       return 0;
+}
+
+static int
+mwifiex_cmd_coalesce_cfg(struct mwifiex_private *priv,
+                        struct host_cmd_ds_command *cmd,
+                        u16 cmd_action, void *data_buf)
+{
+       struct host_cmd_ds_coalesce_cfg *coalesce_cfg =
+                                               &cmd->params.coalesce_cfg;
+       struct mwifiex_ds_coalesce_cfg *cfg = data_buf;
+       struct coalesce_filt_field_param *param;
+       u16 cnt, idx, length;
+       struct coalesce_receive_filt_rule *rule;
+
+       cmd->command = cpu_to_le16(HostCmd_CMD_COALESCE_CFG);
+       cmd->size = cpu_to_le16(S_DS_GEN);
+
+       coalesce_cfg->action = cpu_to_le16(cmd_action);
+       coalesce_cfg->num_of_rules = cpu_to_le16(cfg->num_of_rules);
+       rule = coalesce_cfg->rule;
+
+       for (cnt = 0; cnt < cfg->num_of_rules; cnt++) {
+               rule->header.type = cpu_to_le16(TLV_TYPE_COALESCE_RULE);
+               rule->max_coalescing_delay =
+                       cpu_to_le16(cfg->rule[cnt].max_coalescing_delay);
+               rule->pkt_type = cfg->rule[cnt].pkt_type;
+               rule->num_of_fields = cfg->rule[cnt].num_of_fields;
+
+               length = 0;
+
+               param = rule->params;
+               for (idx = 0; idx < cfg->rule[cnt].num_of_fields; idx++) {
+                       param->operation = cfg->rule[cnt].params[idx].operation;
+                       param->operand_len =
+                                       cfg->rule[cnt].params[idx].operand_len;
+                       param->offset =
+                               cpu_to_le16(cfg->rule[cnt].params[idx].offset);
+                       memcpy(param->operand_byte_stream,
+                              cfg->rule[cnt].params[idx].operand_byte_stream,
+                              param->operand_len);
+
+                       length += sizeof(struct coalesce_filt_field_param);
+
+                       param++;
+               }
+
+               /* Total rule length is sizeof max_coalescing_delay(u16),
+                * num_of_fields(u8), pkt_type(u8) and total length of the all
+                * params
+                */
+               rule->header.len = cpu_to_le16(length + sizeof(u16) +
+                                              sizeof(u8) + sizeof(u8));
+
+               /* Add the rule length to the command size*/
+               le16_add_cpu(&cmd->size, le16_to_cpu(rule->header.len) +
+                            sizeof(struct mwifiex_ie_types_header));
+
+               rule = (void *)((u8 *)rule->params + length);
+       }
+
+       /* Add sizeof action, num_of_rules to total command length */
+       le16_add_cpu(&cmd->size, sizeof(u16) + sizeof(u16));
+
+       return 0;
+}
+
+static int
+mwifiex_cmd_tdls_config(struct mwifiex_private *priv,
+                       struct host_cmd_ds_command *cmd,
+                       u16 cmd_action, void *data_buf)
+{
+       struct host_cmd_ds_tdls_config *tdls_config = &cmd->params.tdls_config;
+       struct mwifiex_tdls_init_cs_params *config;
+       struct mwifiex_tdls_config *init_config;
+       u16 len;
+
+       cmd->command = cpu_to_le16(HostCmd_CMD_TDLS_CONFIG);
+       cmd->size = cpu_to_le16(S_DS_GEN);
+       tdls_config->tdls_action = cpu_to_le16(cmd_action);
+       le16_add_cpu(&cmd->size, sizeof(tdls_config->tdls_action));
+
+       switch (cmd_action) {
+       case ACT_TDLS_CS_ENABLE_CONFIG:
+               init_config = data_buf;
+               len = sizeof(*init_config);
+               memcpy(tdls_config->tdls_data, init_config, len);
+               break;
+       case ACT_TDLS_CS_INIT:
+               config = data_buf;
+               len = sizeof(*config);
+               memcpy(tdls_config->tdls_data, config, len);
+               break;
+       case ACT_TDLS_CS_STOP:
+               len = sizeof(struct mwifiex_tdls_stop_cs_params);
+               memcpy(tdls_config->tdls_data, data_buf, len);
+               break;
+       case ACT_TDLS_CS_PARAMS:
+               len = sizeof(struct mwifiex_tdls_config_cs_params);
+               memcpy(tdls_config->tdls_data, data_buf, len);
+               break;
+       default:
+               mwifiex_dbg(priv->adapter, ERROR,
+                           "Unknown TDLS configuration\n");
+               return -ENOTSUPP;
+       }
+
+       le16_add_cpu(&cmd->size, len);
+       return 0;
+}
+
+static int
+mwifiex_cmd_tdls_oper(struct mwifiex_private *priv,
+                     struct host_cmd_ds_command *cmd,
+                     void *data_buf)
+{
+       struct host_cmd_ds_tdls_oper *tdls_oper = &cmd->params.tdls_oper;
+       struct mwifiex_ds_tdls_oper *oper = data_buf;
+       struct mwifiex_sta_node *sta_ptr;
+       struct host_cmd_tlv_rates *tlv_rates;
+       struct mwifiex_ie_types_htcap *ht_capab;
+       struct mwifiex_ie_types_qos_info *wmm_qos_info;
+       struct mwifiex_ie_types_extcap *extcap;
+       struct mwifiex_ie_types_vhtcap *vht_capab;
+       struct mwifiex_ie_types_aid *aid;
+       struct mwifiex_ie_types_tdls_idle_timeout *timeout;
+       u8 *pos, qos_info;
+       u16 config_len = 0;
+       struct station_parameters *params = priv->sta_params;
+
+       cmd->command = cpu_to_le16(HostCmd_CMD_TDLS_OPER);
+       cmd->size = cpu_to_le16(S_DS_GEN);
+       le16_add_cpu(&cmd->size, sizeof(struct host_cmd_ds_tdls_oper));
+
+       tdls_oper->reason = 0;
+       memcpy(tdls_oper->peer_mac, oper->peer_mac, ETH_ALEN);
+       sta_ptr = mwifiex_get_sta_entry(priv, oper->peer_mac);
+
+       pos = (u8 *)tdls_oper + sizeof(struct host_cmd_ds_tdls_oper);
+
+       switch (oper->tdls_action) {
+       case MWIFIEX_TDLS_DISABLE_LINK:
+               tdls_oper->tdls_action = cpu_to_le16(ACT_TDLS_DELETE);
+               break;
+       case MWIFIEX_TDLS_CREATE_LINK:
+               tdls_oper->tdls_action = cpu_to_le16(ACT_TDLS_CREATE);
+               break;
+       case MWIFIEX_TDLS_CONFIG_LINK:
+               tdls_oper->tdls_action = cpu_to_le16(ACT_TDLS_CONFIG);
+
+               if (!params) {
+                       mwifiex_dbg(priv->adapter, ERROR,
+                                   "TDLS config params not available for %pM\n",
+                                   oper->peer_mac);
+                       return -ENODATA;
+               }
+
+               *(__le16 *)pos = cpu_to_le16(params->capability);
+               config_len += sizeof(params->capability);
+
+               qos_info = params->uapsd_queues | (params->max_sp << 5);
+               wmm_qos_info = (struct mwifiex_ie_types_qos_info *)(pos +
+                                                                   config_len);
+               wmm_qos_info->header.type = cpu_to_le16(WLAN_EID_QOS_CAPA);
+               wmm_qos_info->header.len = cpu_to_le16(sizeof(qos_info));
+               wmm_qos_info->qos_info = qos_info;
+               config_len += sizeof(struct mwifiex_ie_types_qos_info);
+
+               if (params->ht_capa) {
+                       ht_capab = (struct mwifiex_ie_types_htcap *)(pos +
+                                                                   config_len);
+                       ht_capab->header.type =
+                                           cpu_to_le16(WLAN_EID_HT_CAPABILITY);
+                       ht_capab->header.len =
+                                  cpu_to_le16(sizeof(struct ieee80211_ht_cap));
+                       memcpy(&ht_capab->ht_cap, params->ht_capa,
+                              sizeof(struct ieee80211_ht_cap));
+                       config_len += sizeof(struct mwifiex_ie_types_htcap);
+               }
+
+               if (params->supported_rates && params->supported_rates_len) {
+                       tlv_rates = (struct host_cmd_tlv_rates *)(pos +
+                                                                 config_len);
+                       tlv_rates->header.type =
+                                              cpu_to_le16(WLAN_EID_SUPP_RATES);
+                       tlv_rates->header.len =
+                                      cpu_to_le16(params->supported_rates_len);
+                       memcpy(tlv_rates->rates, params->supported_rates,
+                              params->supported_rates_len);
+                       config_len += sizeof(struct host_cmd_tlv_rates) +
+                                     params->supported_rates_len;
+               }
+
+               if (params->ext_capab && params->ext_capab_len) {
+                       extcap = (struct mwifiex_ie_types_extcap *)(pos +
+                                                                   config_len);
+                       extcap->header.type =
+                                          cpu_to_le16(WLAN_EID_EXT_CAPABILITY);
+                       extcap->header.len = cpu_to_le16(params->ext_capab_len);
+                       memcpy(extcap->ext_capab, params->ext_capab,
+                              params->ext_capab_len);
+                       config_len += sizeof(struct mwifiex_ie_types_extcap) +
+                                     params->ext_capab_len;
+               }
+               if (params->vht_capa) {
+                       vht_capab = (struct mwifiex_ie_types_vhtcap *)(pos +
+                                                                   config_len);
+                       vht_capab->header.type =
+                                          cpu_to_le16(WLAN_EID_VHT_CAPABILITY);
+                       vht_capab->header.len =
+                                 cpu_to_le16(sizeof(struct ieee80211_vht_cap));
+                       memcpy(&vht_capab->vht_cap, params->vht_capa,
+                              sizeof(struct ieee80211_vht_cap));
+                       config_len += sizeof(struct mwifiex_ie_types_vhtcap);
+               }
+               if (params->aid) {
+                       aid = (struct mwifiex_ie_types_aid *)(pos + config_len);
+                       aid->header.type = cpu_to_le16(WLAN_EID_AID);
+                       aid->header.len = cpu_to_le16(sizeof(params->aid));
+                       aid->aid = cpu_to_le16(params->aid);
+                       config_len += sizeof(struct mwifiex_ie_types_aid);
+               }
+
+               timeout = (void *)(pos + config_len);
+               timeout->header.type = cpu_to_le16(TLV_TYPE_TDLS_IDLE_TIMEOUT);
+               timeout->header.len = cpu_to_le16(sizeof(timeout->value));
+               timeout->value = cpu_to_le16(MWIFIEX_TDLS_IDLE_TIMEOUT_IN_SEC);
+               config_len += sizeof(struct mwifiex_ie_types_tdls_idle_timeout);
+
+               break;
+       default:
+               mwifiex_dbg(priv->adapter, ERROR, "Unknown TDLS operation\n");
+               return -ENOTSUPP;
+       }
+
+       le16_add_cpu(&cmd->size, config_len);
+
+       return 0;
+}
+
+/* This function prepares command of sdio rx aggr info. */
+static int mwifiex_cmd_sdio_rx_aggr_cfg(struct host_cmd_ds_command *cmd,
+                                       u16 cmd_action, void *data_buf)
+{
+       struct host_cmd_sdio_sp_rx_aggr_cfg *cfg =
+                                       &cmd->params.sdio_rx_aggr_cfg;
+
+       cmd->command = cpu_to_le16(HostCmd_CMD_SDIO_SP_RX_AGGR_CFG);
+       cmd->size =
+               cpu_to_le16(sizeof(struct host_cmd_sdio_sp_rx_aggr_cfg) +
+                           S_DS_GEN);
+       cfg->action = cmd_action;
+       if (cmd_action == HostCmd_ACT_GEN_SET)
+               cfg->enable = *(u8 *)data_buf;
+
+       return 0;
+}
+
+/*
+ * This function prepares the commands before sending them to the firmware.
+ *
+ * This is a generic function which calls specific command preparation
+ * routines based upon the command number.
+ */
+int mwifiex_sta_prepare_cmd(struct mwifiex_private *priv, uint16_t cmd_no,
+                           u16 cmd_action, u32 cmd_oid,
+                           void *data_buf, void *cmd_buf)
+{
+       struct host_cmd_ds_command *cmd_ptr = cmd_buf;
+       int ret = 0;
+
+       /* Prepare command */
+       switch (cmd_no) {
+       case HostCmd_CMD_GET_HW_SPEC:
+               ret = mwifiex_cmd_get_hw_spec(priv, cmd_ptr);
+               break;
+       case HostCmd_CMD_CFG_DATA:
+               ret = mwifiex_cmd_cfg_data(priv, cmd_ptr, data_buf);
+               break;
+       case HostCmd_CMD_MAC_CONTROL:
+               ret = mwifiex_cmd_mac_control(priv, cmd_ptr, cmd_action,
+                                             data_buf);
+               break;
+       case HostCmd_CMD_802_11_MAC_ADDRESS:
+               ret = mwifiex_cmd_802_11_mac_address(priv, cmd_ptr,
+                                                    cmd_action);
+               break;
+       case HostCmd_CMD_MAC_MULTICAST_ADR:
+               ret = mwifiex_cmd_mac_multicast_adr(cmd_ptr, cmd_action,
+                                                   data_buf);
+               break;
+       case HostCmd_CMD_TX_RATE_CFG:
+               ret = mwifiex_cmd_tx_rate_cfg(priv, cmd_ptr, cmd_action,
+                                             data_buf);
+               break;
+       case HostCmd_CMD_TXPWR_CFG:
+               ret = mwifiex_cmd_tx_power_cfg(cmd_ptr, cmd_action,
+                                              data_buf);
+               break;
+       case HostCmd_CMD_RF_TX_PWR:
+               ret = mwifiex_cmd_rf_tx_power(priv, cmd_ptr, cmd_action,
+                                             data_buf);
+               break;
+       case HostCmd_CMD_RF_ANTENNA:
+               ret = mwifiex_cmd_rf_antenna(priv, cmd_ptr, cmd_action,
+                                            data_buf);
+               break;
+       case HostCmd_CMD_802_11_PS_MODE_ENH:
+               ret = mwifiex_cmd_enh_power_mode(priv, cmd_ptr, cmd_action,
+                                                (uint16_t)cmd_oid, data_buf);
+               break;
+       case HostCmd_CMD_802_11_HS_CFG_ENH:
+               ret = mwifiex_cmd_802_11_hs_cfg(priv, cmd_ptr, cmd_action,
+                               (struct mwifiex_hs_config_param *) data_buf);
+               break;
+       case HostCmd_CMD_802_11_SCAN:
+               ret = mwifiex_cmd_802_11_scan(cmd_ptr, data_buf);
+               break;
+       case HostCmd_CMD_802_11_BG_SCAN_QUERY:
+               ret = mwifiex_cmd_802_11_bg_scan_query(cmd_ptr);
+               break;
+       case HostCmd_CMD_802_11_ASSOCIATE:
+               ret = mwifiex_cmd_802_11_associate(priv, cmd_ptr, data_buf);
+               break;
+       case HostCmd_CMD_802_11_DEAUTHENTICATE:
+               ret = mwifiex_cmd_802_11_deauthenticate(priv, cmd_ptr,
+                                                       data_buf);
+               break;
+       case HostCmd_CMD_802_11_AD_HOC_START:
+               ret = mwifiex_cmd_802_11_ad_hoc_start(priv, cmd_ptr,
+                                                     data_buf);
+               break;
+       case HostCmd_CMD_802_11_GET_LOG:
+               ret = mwifiex_cmd_802_11_get_log(cmd_ptr);
+               break;
+       case HostCmd_CMD_802_11_AD_HOC_JOIN:
+               ret = mwifiex_cmd_802_11_ad_hoc_join(priv, cmd_ptr,
+                                                    data_buf);
+               break;
+       case HostCmd_CMD_802_11_AD_HOC_STOP:
+               ret = mwifiex_cmd_802_11_ad_hoc_stop(cmd_ptr);
+               break;
+       case HostCmd_CMD_RSSI_INFO:
+               ret = mwifiex_cmd_802_11_rssi_info(priv, cmd_ptr, cmd_action);
+               break;
+       case HostCmd_CMD_802_11_SNMP_MIB:
+               ret = mwifiex_cmd_802_11_snmp_mib(priv, cmd_ptr, cmd_action,
+                                                 cmd_oid, data_buf);
+               break;
+       case HostCmd_CMD_802_11_TX_RATE_QUERY:
+               cmd_ptr->command =
+                       cpu_to_le16(HostCmd_CMD_802_11_TX_RATE_QUERY);
+               cmd_ptr->size =
+                       cpu_to_le16(sizeof(struct host_cmd_ds_tx_rate_query) +
+                                   S_DS_GEN);
+               priv->tx_rate = 0;
+               ret = 0;
+               break;
+       case HostCmd_CMD_VERSION_EXT:
+               cmd_ptr->command = cpu_to_le16(cmd_no);
+               cmd_ptr->params.verext.version_str_sel =
+                       (u8) (*((u32 *) data_buf));
+               memcpy(&cmd_ptr->params, data_buf,
+                      sizeof(struct host_cmd_ds_version_ext));
+               cmd_ptr->size =
+                       cpu_to_le16(sizeof(struct host_cmd_ds_version_ext) +
+                                   S_DS_GEN);
+               ret = 0;
+               break;
+       case HostCmd_CMD_MGMT_FRAME_REG:
+               cmd_ptr->command = cpu_to_le16(cmd_no);
+               cmd_ptr->params.reg_mask.action = cpu_to_le16(cmd_action);
+               cmd_ptr->params.reg_mask.mask = cpu_to_le32(*(u32 *)data_buf);
+               cmd_ptr->size =
+                       cpu_to_le16(sizeof(struct host_cmd_ds_mgmt_frame_reg) +
+                                   S_DS_GEN);
+               ret = 0;
+               break;
+       case HostCmd_CMD_REMAIN_ON_CHAN:
+               cmd_ptr->command = cpu_to_le16(cmd_no);
+               memcpy(&cmd_ptr->params, data_buf,
+                      sizeof(struct host_cmd_ds_remain_on_chan));
+               cmd_ptr->size =
+                     cpu_to_le16(sizeof(struct host_cmd_ds_remain_on_chan) +
+                                 S_DS_GEN);
+               break;
+       case HostCmd_CMD_11AC_CFG:
+               ret = mwifiex_cmd_11ac_cfg(priv, cmd_ptr, cmd_action, data_buf);
+               break;
+       case HostCmd_CMD_P2P_MODE_CFG:
+               cmd_ptr->command = cpu_to_le16(cmd_no);
+               cmd_ptr->params.mode_cfg.action = cpu_to_le16(cmd_action);
+               cmd_ptr->params.mode_cfg.mode = cpu_to_le16(*(u16 *)data_buf);
+               cmd_ptr->size =
+                       cpu_to_le16(sizeof(struct host_cmd_ds_p2p_mode_cfg) +
+                                   S_DS_GEN);
+               break;
+       case HostCmd_CMD_FUNC_INIT:
+               if (priv->adapter->hw_status == MWIFIEX_HW_STATUS_RESET)
+                       priv->adapter->hw_status = MWIFIEX_HW_STATUS_READY;
+               cmd_ptr->command = cpu_to_le16(cmd_no);
+               cmd_ptr->size = cpu_to_le16(S_DS_GEN);
+               break;
+       case HostCmd_CMD_FUNC_SHUTDOWN:
+               priv->adapter->hw_status = MWIFIEX_HW_STATUS_RESET;
+               cmd_ptr->command = cpu_to_le16(cmd_no);
+               cmd_ptr->size = cpu_to_le16(S_DS_GEN);
+               break;
+       case HostCmd_CMD_11N_ADDBA_REQ:
+               ret = mwifiex_cmd_11n_addba_req(cmd_ptr, data_buf);
+               break;
+       case HostCmd_CMD_11N_DELBA:
+               ret = mwifiex_cmd_11n_delba(cmd_ptr, data_buf);
+               break;
+       case HostCmd_CMD_11N_ADDBA_RSP:
+               ret = mwifiex_cmd_11n_addba_rsp_gen(priv, cmd_ptr, data_buf);
+               break;
+       case HostCmd_CMD_802_11_KEY_MATERIAL:
+               ret = mwifiex_cmd_802_11_key_material(priv, cmd_ptr,
+                                                     cmd_action, cmd_oid,
+                                                     data_buf);
+               break;
+       case HostCmd_CMD_802_11D_DOMAIN_INFO:
+               ret = mwifiex_cmd_802_11d_domain_info(priv, cmd_ptr,
+                                                     cmd_action);
+               break;
+       case HostCmd_CMD_RECONFIGURE_TX_BUFF:
+               ret = mwifiex_cmd_recfg_tx_buf(priv, cmd_ptr, cmd_action,
+                                              data_buf);
+               break;
+       case HostCmd_CMD_AMSDU_AGGR_CTRL:
+               ret = mwifiex_cmd_amsdu_aggr_ctrl(cmd_ptr, cmd_action,
+                                                 data_buf);
+               break;
+       case HostCmd_CMD_11N_CFG:
+               ret = mwifiex_cmd_11n_cfg(priv, cmd_ptr, cmd_action, data_buf);
+               break;
+       case HostCmd_CMD_WMM_GET_STATUS:
+               mwifiex_dbg(priv->adapter, CMD,
+                           "cmd: WMM: WMM_GET_STATUS cmd sent\n");
+               cmd_ptr->command = cpu_to_le16(HostCmd_CMD_WMM_GET_STATUS);
+               cmd_ptr->size =
+                       cpu_to_le16(sizeof(struct host_cmd_ds_wmm_get_status) +
+                                   S_DS_GEN);
+               ret = 0;
+               break;
+       case HostCmd_CMD_802_11_IBSS_COALESCING_STATUS:
+               ret = mwifiex_cmd_ibss_coalescing_status(cmd_ptr, cmd_action,
+                                                        data_buf);
+               break;
+       case HostCmd_CMD_802_11_SCAN_EXT:
+               ret = mwifiex_cmd_802_11_scan_ext(priv, cmd_ptr, data_buf);
+               break;
+       case HostCmd_CMD_MEM_ACCESS:
+               ret = mwifiex_cmd_mem_access(cmd_ptr, cmd_action, data_buf);
+               break;
+       case HostCmd_CMD_MAC_REG_ACCESS:
+       case HostCmd_CMD_BBP_REG_ACCESS:
+       case HostCmd_CMD_RF_REG_ACCESS:
+       case HostCmd_CMD_PMIC_REG_ACCESS:
+       case HostCmd_CMD_CAU_REG_ACCESS:
+       case HostCmd_CMD_802_11_EEPROM_ACCESS:
+               ret = mwifiex_cmd_reg_access(cmd_ptr, cmd_action, data_buf);
+               break;
+       case HostCmd_CMD_SET_BSS_MODE:
+               cmd_ptr->command = cpu_to_le16(cmd_no);
+               if (priv->bss_mode == NL80211_IFTYPE_ADHOC)
+                       cmd_ptr->params.bss_mode.con_type =
+                               CONNECTION_TYPE_ADHOC;
+               else if (priv->bss_mode == NL80211_IFTYPE_STATION ||
+                        priv->bss_mode == NL80211_IFTYPE_P2P_CLIENT)
+                       cmd_ptr->params.bss_mode.con_type =
+                               CONNECTION_TYPE_INFRA;
+               else if (priv->bss_mode == NL80211_IFTYPE_AP ||
+                        priv->bss_mode == NL80211_IFTYPE_P2P_GO)
+                       cmd_ptr->params.bss_mode.con_type = CONNECTION_TYPE_AP;
+               cmd_ptr->size = cpu_to_le16(sizeof(struct
+                               host_cmd_ds_set_bss_mode) + S_DS_GEN);
+               ret = 0;
+               break;
+       case HostCmd_CMD_PCIE_DESC_DETAILS:
+               ret = mwifiex_cmd_pcie_host_spec(priv, cmd_ptr, cmd_action);
+               break;
+       case HostCmd_CMD_802_11_SUBSCRIBE_EVENT:
+               ret = mwifiex_cmd_802_11_subsc_evt(priv, cmd_ptr, data_buf);
+               break;
+       case HostCmd_CMD_MEF_CFG:
+               ret = mwifiex_cmd_mef_cfg(priv, cmd_ptr, data_buf);
+               break;
+       case HostCmd_CMD_COALESCE_CFG:
+               ret = mwifiex_cmd_coalesce_cfg(priv, cmd_ptr, cmd_action,
+                                              data_buf);
+               break;
+       case HostCmd_CMD_TDLS_OPER:
+               ret = mwifiex_cmd_tdls_oper(priv, cmd_ptr, data_buf);
+               break;
+       case HostCmd_CMD_TDLS_CONFIG:
+               ret = mwifiex_cmd_tdls_config(priv, cmd_ptr, cmd_action,
+                                             data_buf);
+               break;
+       case HostCmd_CMD_CHAN_REPORT_REQUEST:
+               ret = mwifiex_cmd_issue_chan_report_request(priv, cmd_ptr,
+                                                           data_buf);
+               break;
+       case HostCmd_CMD_SDIO_SP_RX_AGGR_CFG:
+               ret = mwifiex_cmd_sdio_rx_aggr_cfg(cmd_ptr, cmd_action,
+                                                  data_buf);
+               break;
+       case HostCmd_CMD_MC_POLICY:
+               ret = mwifiex_cmd_set_mc_policy(priv, cmd_ptr, cmd_action,
+                                               data_buf);
+               break;
+       case HostCmd_CMD_ROBUST_COEX:
+               ret = mwifiex_cmd_robust_coex(priv, cmd_ptr, cmd_action,
+                                             data_buf);
+               break;
+       default:
+               mwifiex_dbg(priv->adapter, ERROR,
+                           "PREP_CMD: unknown cmd- %#x\n", cmd_no);
+               ret = -1;
+               break;
+       }
+       return ret;
+}
+
+/*
+ * This function issues commands to initialize firmware.
+ *
+ * This is called after firmware download to bring the card to
+ * working state.
+ * Function is also called during reinitialization of virtual
+ * interfaces.
+ *
+ * The following commands are issued sequentially -
+ *      - Set PCI-Express host buffer configuration (PCIE only)
+ *      - Function init (for first interface only)
+ *      - Read MAC address (for first interface only)
+ *      - Reconfigure Tx buffer size (for first interface only)
+ *      - Enable auto deep sleep (for first interface only)
+ *      - Get Tx rate
+ *      - Get Tx power
+ *      - Set IBSS coalescing status
+ *      - Set AMSDU aggregation control
+ *      - Set 11d control
+ *      - Set MAC control (this must be the last command to initialize firmware)
+ */
+int mwifiex_sta_init_cmd(struct mwifiex_private *priv, u8 first_sta, bool init)
+{
+       struct mwifiex_adapter *adapter = priv->adapter;
+       int ret;
+       u16 enable = true;
+       struct mwifiex_ds_11n_amsdu_aggr_ctrl amsdu_aggr_ctrl;
+       struct mwifiex_ds_auto_ds auto_ds;
+       enum state_11d_t state_11d;
+       struct mwifiex_ds_11n_tx_cfg tx_cfg;
+       u8 sdio_sp_rx_aggr_enable;
+
+       if (first_sta) {
+               if (priv->adapter->iface_type == MWIFIEX_PCIE) {
+                       ret = mwifiex_send_cmd(priv,
+                                              HostCmd_CMD_PCIE_DESC_DETAILS,
+                                              HostCmd_ACT_GEN_SET, 0, NULL,
+                                              true);
+                       if (ret)
+                               return -1;
+               }
+
+               ret = mwifiex_send_cmd(priv, HostCmd_CMD_FUNC_INIT,
+                                      HostCmd_ACT_GEN_SET, 0, NULL, true);
+               if (ret)
+                       return -1;
+
+               /* Download calibration data to firmware.
+                * The cal-data can be read from device tree and/or
+                * a configuration file and downloaded to firmware.
+                */
+               adapter->dt_node =
+                               of_find_node_by_name(NULL, "marvell_cfgdata");
+               if (adapter->dt_node) {
+                       ret = mwifiex_dnld_dt_cfgdata(priv, adapter->dt_node,
+                                                     "marvell,caldata");
+                       if (ret)
+                               return -1;
+               }
+
+               if (adapter->cal_data) {
+                       ret = mwifiex_send_cmd(priv, HostCmd_CMD_CFG_DATA,
+                                              HostCmd_ACT_GEN_SET, 0, NULL,
+                                              true);
+                       if (ret)
+                               return -1;
+               }
+
+               /* Read MAC address from HW */
+               ret = mwifiex_send_cmd(priv, HostCmd_CMD_GET_HW_SPEC,
+                                      HostCmd_ACT_GEN_GET, 0, NULL, true);
+               if (ret)
+                       return -1;
+
+               /** Set SDIO Single Port RX Aggr Info */
+               if (priv->adapter->iface_type == MWIFIEX_SDIO &&
+                   ISSUPP_SDIO_SPA_ENABLED(priv->adapter->fw_cap_info) &&
+                   !priv->adapter->host_disable_sdio_rx_aggr) {
+                       sdio_sp_rx_aggr_enable = true;
+                       ret = mwifiex_send_cmd(priv,
+                                              HostCmd_CMD_SDIO_SP_RX_AGGR_CFG,
+                                              HostCmd_ACT_GEN_SET, 0,
+                                              &sdio_sp_rx_aggr_enable,
+                                              true);
+                       if (ret) {
+                               mwifiex_dbg(priv->adapter, ERROR,
+                                           "error while enabling SP aggregation..disable it");
+                               adapter->sdio_rx_aggr_enable = false;
+                       }
+               }
+
+               /* Reconfigure tx buf size */
+               ret = mwifiex_send_cmd(priv, HostCmd_CMD_RECONFIGURE_TX_BUFF,
+                                      HostCmd_ACT_GEN_SET, 0,
+                                      &priv->adapter->tx_buf_size, true);
+               if (ret)
+                       return -1;
+
+               if (priv->bss_type != MWIFIEX_BSS_TYPE_UAP) {
+                       /* Enable IEEE PS by default */
+                       priv->adapter->ps_mode = MWIFIEX_802_11_POWER_MODE_PSP;
+                       ret = mwifiex_send_cmd(priv,
+                                              HostCmd_CMD_802_11_PS_MODE_ENH,
+                                              EN_AUTO_PS, BITMAP_STA_PS, NULL,
+                                              true);
+                       if (ret)
+                               return -1;
+               }
+
+               if (drcs) {
+                       adapter->drcs_enabled = true;
+                       if (ISSUPP_DRCS_ENABLED(adapter->fw_cap_info))
+                               ret = mwifiex_send_cmd(priv,
+                                                      HostCmd_CMD_MC_POLICY,
+                                                      HostCmd_ACT_GEN_SET, 0,
+                                                      &adapter->drcs_enabled,
+                                                      true);
+                       if (ret)
+                               return -1;
+               }
+       }
+
+       /* get tx rate */
+       ret = mwifiex_send_cmd(priv, HostCmd_CMD_TX_RATE_CFG,
+                              HostCmd_ACT_GEN_GET, 0, NULL, true);
+       if (ret)
+               return -1;
+       priv->data_rate = 0;
+
+       /* get tx power */
+       ret = mwifiex_send_cmd(priv, HostCmd_CMD_RF_TX_PWR,
+                              HostCmd_ACT_GEN_GET, 0, NULL, true);
+       if (ret)
+               return -1;
+
+       if (priv->bss_type == MWIFIEX_BSS_TYPE_STA) {
+               /* set ibss coalescing_status */
+               ret = mwifiex_send_cmd(
+                               priv,
+                               HostCmd_CMD_802_11_IBSS_COALESCING_STATUS,
+                               HostCmd_ACT_GEN_SET, 0, &enable, true);
+               if (ret)
+                       return -1;
+       }
+
+       memset(&amsdu_aggr_ctrl, 0, sizeof(amsdu_aggr_ctrl));
+       amsdu_aggr_ctrl.enable = true;
+       /* Send request to firmware */
+       ret = mwifiex_send_cmd(priv, HostCmd_CMD_AMSDU_AGGR_CTRL,
+                              HostCmd_ACT_GEN_SET, 0,
+                              &amsdu_aggr_ctrl, true);
+       if (ret)
+               return -1;
+       /* MAC Control must be the last command in init_fw */
+       /* set MAC Control */
+       ret = mwifiex_send_cmd(priv, HostCmd_CMD_MAC_CONTROL,
+                              HostCmd_ACT_GEN_SET, 0,
+                              &priv->curr_pkt_filter, true);
+       if (ret)
+               return -1;
+
+       if (!disable_auto_ds &&
+           first_sta && priv->adapter->iface_type != MWIFIEX_USB &&
+           priv->bss_type != MWIFIEX_BSS_TYPE_UAP) {
+               /* Enable auto deep sleep */
+               auto_ds.auto_ds = DEEP_SLEEP_ON;
+               auto_ds.idle_time = DEEP_SLEEP_IDLE_TIME;
+               ret = mwifiex_send_cmd(priv, HostCmd_CMD_802_11_PS_MODE_ENH,
+                                      EN_AUTO_PS, BITMAP_AUTO_DS,
+                                      &auto_ds, true);
+               if (ret)
+                       return -1;
+       }
+
+       if (priv->bss_type != MWIFIEX_BSS_TYPE_UAP) {
+               /* Send cmd to FW to enable/disable 11D function */
+               state_11d = ENABLE_11D;
+               ret = mwifiex_send_cmd(priv, HostCmd_CMD_802_11_SNMP_MIB,
+                                      HostCmd_ACT_GEN_SET, DOT11D_I,
+                                      &state_11d, true);
+               if (ret)
+                       mwifiex_dbg(priv->adapter, ERROR,
+                                   "11D: failed to enable 11D\n");
+       }
+
+       /* Send cmd to FW to configure 11n specific configuration
+        * (Short GI, Channel BW, Green field support etc.) for transmit
+        */
+       tx_cfg.tx_htcap = MWIFIEX_FW_DEF_HTTXCFG;
+       ret = mwifiex_send_cmd(priv, HostCmd_CMD_11N_CFG,
+                              HostCmd_ACT_GEN_SET, 0, &tx_cfg, true);
+
+       if (init) {
+               /* set last_init_cmd before sending the command */
+               priv->adapter->last_init_cmd = HostCmd_CMD_11N_CFG;
+               ret = -EINPROGRESS;
+       }
+
+       return ret;
+}
diff --git a/drivers/net/wireless/marvell/mwifiex/sta_cmdresp.c b/drivers/net/wireless/marvell/mwifiex/sta_cmdresp.c
new file mode 100644 (file)
index 0000000..9ac7aa2
--- /dev/null
@@ -0,0 +1,1249 @@
+/*
+ * Marvell Wireless LAN device driver: station command response handling
+ *
+ * Copyright (C) 2011-2014, Marvell International Ltd.
+ *
+ * This software file (the "File") is distributed by Marvell International
+ * Ltd. under the terms of the GNU General Public License Version 2, June 1991
+ * (the "License").  You may use, redistribute and/or modify this File in
+ * accordance with the terms and conditions of the License, a copy of which
+ * is available by writing to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the
+ * worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
+ *
+ * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
+ * ARE EXPRESSLY DISCLAIMED.  The License provides additional details about
+ * this warranty disclaimer.
+ */
+
+#include "decl.h"
+#include "ioctl.h"
+#include "util.h"
+#include "fw.h"
+#include "main.h"
+#include "wmm.h"
+#include "11n.h"
+#include "11ac.h"
+
+
+/*
+ * This function handles the command response error case.
+ *
+ * For scan response error, the function cancels all the pending
+ * scan commands and generates an event to inform the applications
+ * of the scan completion.
+ *
+ * For Power Save command failure, we do not retry enter PS
+ * command in case of Ad-hoc mode.
+ *
+ * For all other response errors, the current command buffer is freed
+ * and returned to the free command queue.
+ */
+static void
+mwifiex_process_cmdresp_error(struct mwifiex_private *priv,
+                             struct host_cmd_ds_command *resp)
+{
+       struct cmd_ctrl_node *cmd_node = NULL, *tmp_node;
+       struct mwifiex_adapter *adapter = priv->adapter;
+       struct host_cmd_ds_802_11_ps_mode_enh *pm;
+       unsigned long flags;
+
+       mwifiex_dbg(adapter, ERROR,
+                   "CMD_RESP: cmd %#x error, result=%#x\n",
+                   resp->command, resp->result);
+
+       if (adapter->curr_cmd->wait_q_enabled)
+               adapter->cmd_wait_q.status = -1;
+
+       switch (le16_to_cpu(resp->command)) {
+       case HostCmd_CMD_802_11_PS_MODE_ENH:
+               pm = &resp->params.psmode_enh;
+               mwifiex_dbg(adapter, ERROR,
+                           "PS_MODE_ENH cmd failed: result=0x%x action=0x%X\n",
+                           resp->result, le16_to_cpu(pm->action));
+               /* We do not re-try enter-ps command in ad-hoc mode. */
+               if (le16_to_cpu(pm->action) == EN_AUTO_PS &&
+                   (le16_to_cpu(pm->params.ps_bitmap) & BITMAP_STA_PS) &&
+                   priv->bss_mode == NL80211_IFTYPE_ADHOC)
+                       adapter->ps_mode = MWIFIEX_802_11_POWER_MODE_CAM;
+
+               break;
+       case HostCmd_CMD_802_11_SCAN:
+       case HostCmd_CMD_802_11_SCAN_EXT:
+               /* Cancel all pending scan command */
+               spin_lock_irqsave(&adapter->scan_pending_q_lock, flags);
+               list_for_each_entry_safe(cmd_node, tmp_node,
+                                        &adapter->scan_pending_q, list) {
+                       list_del(&cmd_node->list);
+                       spin_unlock_irqrestore(&adapter->scan_pending_q_lock,
+                                              flags);
+                       mwifiex_insert_cmd_to_free_q(adapter, cmd_node);
+                       spin_lock_irqsave(&adapter->scan_pending_q_lock, flags);
+               }
+               spin_unlock_irqrestore(&adapter->scan_pending_q_lock, flags);
+
+               spin_lock_irqsave(&adapter->mwifiex_cmd_lock, flags);
+               adapter->scan_processing = false;
+               spin_unlock_irqrestore(&adapter->mwifiex_cmd_lock, flags);
+               break;
+
+       case HostCmd_CMD_MAC_CONTROL:
+               break;
+
+       case HostCmd_CMD_SDIO_SP_RX_AGGR_CFG:
+               mwifiex_dbg(adapter, MSG,
+                           "SDIO RX single-port aggregation Not support\n");
+               break;
+
+       default:
+               break;
+       }
+       /* Handling errors here */
+       mwifiex_recycle_cmd_node(adapter, adapter->curr_cmd);
+
+       spin_lock_irqsave(&adapter->mwifiex_cmd_lock, flags);
+       adapter->curr_cmd = NULL;
+       spin_unlock_irqrestore(&adapter->mwifiex_cmd_lock, flags);
+}
+
+/*
+ * This function handles the command response of get RSSI info.
+ *
+ * Handling includes changing the header fields into CPU format
+ * and saving the following parameters in driver -
+ *      - Last data and beacon RSSI value
+ *      - Average data and beacon RSSI value
+ *      - Last data and beacon NF value
+ *      - Average data and beacon NF value
+ *
+ * The parameters are send to the application as well, along with
+ * calculated SNR values.
+ */
+static int mwifiex_ret_802_11_rssi_info(struct mwifiex_private *priv,
+                                       struct host_cmd_ds_command *resp)
+{
+       struct host_cmd_ds_802_11_rssi_info_rsp *rssi_info_rsp =
+                                               &resp->params.rssi_info_rsp;
+       struct mwifiex_ds_misc_subsc_evt *subsc_evt =
+                                               &priv->async_subsc_evt_storage;
+
+       priv->data_rssi_last = le16_to_cpu(rssi_info_rsp->data_rssi_last);
+       priv->data_nf_last = le16_to_cpu(rssi_info_rsp->data_nf_last);
+
+       priv->data_rssi_avg = le16_to_cpu(rssi_info_rsp->data_rssi_avg);
+       priv->data_nf_avg = le16_to_cpu(rssi_info_rsp->data_nf_avg);
+
+       priv->bcn_rssi_last = le16_to_cpu(rssi_info_rsp->bcn_rssi_last);
+       priv->bcn_nf_last = le16_to_cpu(rssi_info_rsp->bcn_nf_last);
+
+       priv->bcn_rssi_avg = le16_to_cpu(rssi_info_rsp->bcn_rssi_avg);
+       priv->bcn_nf_avg = le16_to_cpu(rssi_info_rsp->bcn_nf_avg);
+
+       if (priv->subsc_evt_rssi_state == EVENT_HANDLED)
+               return 0;
+
+       memset(subsc_evt, 0x00, sizeof(struct mwifiex_ds_misc_subsc_evt));
+
+       /* Resubscribe low and high rssi events with new thresholds */
+       subsc_evt->events = BITMASK_BCN_RSSI_LOW | BITMASK_BCN_RSSI_HIGH;
+       subsc_evt->action = HostCmd_ACT_BITWISE_SET;
+       if (priv->subsc_evt_rssi_state == RSSI_LOW_RECVD) {
+               subsc_evt->bcn_l_rssi_cfg.abs_value = abs(priv->bcn_rssi_avg -
+                               priv->cqm_rssi_hyst);
+               subsc_evt->bcn_h_rssi_cfg.abs_value = abs(priv->cqm_rssi_thold);
+       } else if (priv->subsc_evt_rssi_state == RSSI_HIGH_RECVD) {
+               subsc_evt->bcn_l_rssi_cfg.abs_value = abs(priv->cqm_rssi_thold);
+               subsc_evt->bcn_h_rssi_cfg.abs_value = abs(priv->bcn_rssi_avg +
+                               priv->cqm_rssi_hyst);
+       }
+       subsc_evt->bcn_l_rssi_cfg.evt_freq = 1;
+       subsc_evt->bcn_h_rssi_cfg.evt_freq = 1;
+
+       priv->subsc_evt_rssi_state = EVENT_HANDLED;
+
+       mwifiex_send_cmd(priv, HostCmd_CMD_802_11_SUBSCRIBE_EVENT,
+                        0, 0, subsc_evt, false);
+
+       return 0;
+}
+
+/*
+ * This function handles the command response of set/get SNMP
+ * MIB parameters.
+ *
+ * Handling includes changing the header fields into CPU format
+ * and saving the parameter in driver.
+ *
+ * The following parameters are supported -
+ *      - Fragmentation threshold
+ *      - RTS threshold
+ *      - Short retry limit
+ */
+static int mwifiex_ret_802_11_snmp_mib(struct mwifiex_private *priv,
+                                      struct host_cmd_ds_command *resp,
+                                      u32 *data_buf)
+{
+       struct host_cmd_ds_802_11_snmp_mib *smib = &resp->params.smib;
+       u16 oid = le16_to_cpu(smib->oid);
+       u16 query_type = le16_to_cpu(smib->query_type);
+       u32 ul_temp;
+
+       mwifiex_dbg(priv->adapter, INFO,
+                   "info: SNMP_RESP: oid value = %#x,\t"
+                   "query_type = %#x, buf size = %#x\n",
+                   oid, query_type, le16_to_cpu(smib->buf_size));
+       if (query_type == HostCmd_ACT_GEN_GET) {
+               ul_temp = le16_to_cpu(*((__le16 *) (smib->value)));
+               if (data_buf)
+                       *data_buf = ul_temp;
+               switch (oid) {
+               case FRAG_THRESH_I:
+                       mwifiex_dbg(priv->adapter, INFO,
+                                   "info: SNMP_RESP: FragThsd =%u\n",
+                                   ul_temp);
+                       break;
+               case RTS_THRESH_I:
+                       mwifiex_dbg(priv->adapter, INFO,
+                                   "info: SNMP_RESP: RTSThsd =%u\n",
+                                   ul_temp);
+                       break;
+               case SHORT_RETRY_LIM_I:
+                       mwifiex_dbg(priv->adapter, INFO,
+                                   "info: SNMP_RESP: TxRetryCount=%u\n",
+                                   ul_temp);
+                       break;
+               case DTIM_PERIOD_I:
+                       mwifiex_dbg(priv->adapter, INFO,
+                                   "info: SNMP_RESP: DTIM period=%u\n",
+                                   ul_temp);
+               default:
+                       break;
+               }
+       }
+
+       return 0;
+}
+
+/*
+ * This function handles the command response of get log request
+ *
+ * Handling includes changing the header fields into CPU format
+ * and sending the received parameters to application.
+ */
+static int mwifiex_ret_get_log(struct mwifiex_private *priv,
+                              struct host_cmd_ds_command *resp,
+                              struct mwifiex_ds_get_stats *stats)
+{
+       struct host_cmd_ds_802_11_get_log *get_log =
+               &resp->params.get_log;
+
+       if (stats) {
+               stats->mcast_tx_frame = le32_to_cpu(get_log->mcast_tx_frame);
+               stats->failed = le32_to_cpu(get_log->failed);
+               stats->retry = le32_to_cpu(get_log->retry);
+               stats->multi_retry = le32_to_cpu(get_log->multi_retry);
+               stats->frame_dup = le32_to_cpu(get_log->frame_dup);
+               stats->rts_success = le32_to_cpu(get_log->rts_success);
+               stats->rts_failure = le32_to_cpu(get_log->rts_failure);
+               stats->ack_failure = le32_to_cpu(get_log->ack_failure);
+               stats->rx_frag = le32_to_cpu(get_log->rx_frag);
+               stats->mcast_rx_frame = le32_to_cpu(get_log->mcast_rx_frame);
+               stats->fcs_error = le32_to_cpu(get_log->fcs_error);
+               stats->tx_frame = le32_to_cpu(get_log->tx_frame);
+               stats->wep_icv_error[0] =
+                       le32_to_cpu(get_log->wep_icv_err_cnt[0]);
+               stats->wep_icv_error[1] =
+                       le32_to_cpu(get_log->wep_icv_err_cnt[1]);
+               stats->wep_icv_error[2] =
+                       le32_to_cpu(get_log->wep_icv_err_cnt[2]);
+               stats->wep_icv_error[3] =
+                       le32_to_cpu(get_log->wep_icv_err_cnt[3]);
+               stats->bcn_rcv_cnt = le32_to_cpu(get_log->bcn_rcv_cnt);
+               stats->bcn_miss_cnt = le32_to_cpu(get_log->bcn_miss_cnt);
+       }
+
+       return 0;
+}
+
+/*
+ * This function handles the command response of set/get Tx rate
+ * configurations.
+ *
+ * Handling includes changing the header fields into CPU format
+ * and saving the following parameters in driver -
+ *      - DSSS rate bitmap
+ *      - OFDM rate bitmap
+ *      - HT MCS rate bitmaps
+ *
+ * Based on the new rate bitmaps, the function re-evaluates if
+ * auto data rate has been activated. If not, it sends another
+ * query to the firmware to get the current Tx data rate.
+ */
+static int mwifiex_ret_tx_rate_cfg(struct mwifiex_private *priv,
+                                  struct host_cmd_ds_command *resp)
+{
+       struct host_cmd_ds_tx_rate_cfg *rate_cfg = &resp->params.tx_rate_cfg;
+       struct mwifiex_rate_scope *rate_scope;
+       struct mwifiex_ie_types_header *head;
+       u16 tlv, tlv_buf_len, tlv_buf_left;
+       u8 *tlv_buf;
+       u32 i;
+
+       tlv_buf = ((u8 *)rate_cfg) + sizeof(struct host_cmd_ds_tx_rate_cfg);
+       tlv_buf_left = le16_to_cpu(resp->size) - S_DS_GEN - sizeof(*rate_cfg);
+
+       while (tlv_buf_left >= sizeof(*head)) {
+               head = (struct mwifiex_ie_types_header *)tlv_buf;
+               tlv = le16_to_cpu(head->type);
+               tlv_buf_len = le16_to_cpu(head->len);
+
+               if (tlv_buf_left < (sizeof(*head) + tlv_buf_len))
+                       break;
+
+               switch (tlv) {
+               case TLV_TYPE_RATE_SCOPE:
+                       rate_scope = (struct mwifiex_rate_scope *) tlv_buf;
+                       priv->bitmap_rates[0] =
+                               le16_to_cpu(rate_scope->hr_dsss_rate_bitmap);
+                       priv->bitmap_rates[1] =
+                               le16_to_cpu(rate_scope->ofdm_rate_bitmap);
+                       for (i = 0;
+                            i <
+                            sizeof(rate_scope->ht_mcs_rate_bitmap) /
+                            sizeof(u16); i++)
+                               priv->bitmap_rates[2 + i] =
+                                       le16_to_cpu(rate_scope->
+                                                   ht_mcs_rate_bitmap[i]);
+
+                       if (priv->adapter->fw_api_ver == MWIFIEX_FW_V15) {
+                               for (i = 0; i < ARRAY_SIZE(rate_scope->
+                                                          vht_mcs_rate_bitmap);
+                                    i++)
+                                       priv->bitmap_rates[10 + i] =
+                                           le16_to_cpu(rate_scope->
+                                                       vht_mcs_rate_bitmap[i]);
+                       }
+                       break;
+                       /* Add RATE_DROP tlv here */
+               }
+
+               tlv_buf += (sizeof(*head) + tlv_buf_len);
+               tlv_buf_left -= (sizeof(*head) + tlv_buf_len);
+       }
+
+       priv->is_data_rate_auto = mwifiex_is_rate_auto(priv);
+
+       if (priv->is_data_rate_auto)
+               priv->data_rate = 0;
+       else
+               return mwifiex_send_cmd(priv, HostCmd_CMD_802_11_TX_RATE_QUERY,
+                                       HostCmd_ACT_GEN_GET, 0, NULL, false);
+
+       return 0;
+}
+
+/*
+ * This function handles the command response of get Tx power level.
+ *
+ * Handling includes saving the maximum and minimum Tx power levels
+ * in driver, as well as sending the values to user.
+ */
+static int mwifiex_get_power_level(struct mwifiex_private *priv, void *data_buf)
+{
+       int length, max_power = -1, min_power = -1;
+       struct mwifiex_types_power_group *pg_tlv_hdr;
+       struct mwifiex_power_group *pg;
+
+       if (!data_buf)
+               return -1;
+
+       pg_tlv_hdr = (struct mwifiex_types_power_group *)((u8 *)data_buf);
+       pg = (struct mwifiex_power_group *)
+               ((u8 *) pg_tlv_hdr + sizeof(struct mwifiex_types_power_group));
+       length = le16_to_cpu(pg_tlv_hdr->length);
+
+       /* At least one structure required to update power */
+       if (length < sizeof(struct mwifiex_power_group))
+               return 0;
+
+       max_power = pg->power_max;
+       min_power = pg->power_min;
+       length -= sizeof(struct mwifiex_power_group);
+
+       while (length >= sizeof(struct mwifiex_power_group)) {
+               pg++;
+               if (max_power < pg->power_max)
+                       max_power = pg->power_max;
+
+               if (min_power > pg->power_min)
+                       min_power = pg->power_min;
+
+               length -= sizeof(struct mwifiex_power_group);
+       }
+       priv->min_tx_power_level = (u8) min_power;
+       priv->max_tx_power_level = (u8) max_power;
+
+       return 0;
+}
+
+/*
+ * This function handles the command response of set/get Tx power
+ * configurations.
+ *
+ * Handling includes changing the header fields into CPU format
+ * and saving the current Tx power level in driver.
+ */
+static int mwifiex_ret_tx_power_cfg(struct mwifiex_private *priv,
+                                   struct host_cmd_ds_command *resp)
+{
+       struct mwifiex_adapter *adapter = priv->adapter;
+       struct host_cmd_ds_txpwr_cfg *txp_cfg = &resp->params.txp_cfg;
+       struct mwifiex_types_power_group *pg_tlv_hdr;
+       struct mwifiex_power_group *pg;
+       u16 action = le16_to_cpu(txp_cfg->action);
+       u16 tlv_buf_left;
+
+       pg_tlv_hdr = (struct mwifiex_types_power_group *)
+               ((u8 *)txp_cfg +
+                sizeof(struct host_cmd_ds_txpwr_cfg));
+
+       pg = (struct mwifiex_power_group *)
+               ((u8 *)pg_tlv_hdr +
+                sizeof(struct mwifiex_types_power_group));
+
+       tlv_buf_left = le16_to_cpu(resp->size) - S_DS_GEN - sizeof(*txp_cfg);
+       if (tlv_buf_left <
+                       le16_to_cpu(pg_tlv_hdr->length) + sizeof(*pg_tlv_hdr))
+               return 0;
+
+       switch (action) {
+       case HostCmd_ACT_GEN_GET:
+               if (adapter->hw_status == MWIFIEX_HW_STATUS_INITIALIZING)
+                       mwifiex_get_power_level(priv, pg_tlv_hdr);
+
+               priv->tx_power_level = (u16) pg->power_min;
+               break;
+
+       case HostCmd_ACT_GEN_SET:
+               if (!le32_to_cpu(txp_cfg->mode))
+                       break;
+
+               if (pg->power_max == pg->power_min)
+                       priv->tx_power_level = (u16) pg->power_min;
+               break;
+       default:
+               mwifiex_dbg(adapter, ERROR,
+                           "CMD_RESP: unknown cmd action %d\n",
+                           action);
+               return 0;
+       }
+       mwifiex_dbg(adapter, INFO,
+                   "info: Current TxPower Level = %d, Max Power=%d, Min Power=%d\n",
+                   priv->tx_power_level, priv->max_tx_power_level,
+                   priv->min_tx_power_level);
+
+       return 0;
+}
+
+/*
+ * This function handles the command response of get RF Tx power.
+ */
+static int mwifiex_ret_rf_tx_power(struct mwifiex_private *priv,
+                                  struct host_cmd_ds_command *resp)
+{
+       struct host_cmd_ds_rf_tx_pwr *txp = &resp->params.txp;
+       u16 action = le16_to_cpu(txp->action);
+
+       priv->tx_power_level = le16_to_cpu(txp->cur_level);
+
+       if (action == HostCmd_ACT_GEN_GET) {
+               priv->max_tx_power_level = txp->max_power;
+               priv->min_tx_power_level = txp->min_power;
+       }
+
+       mwifiex_dbg(priv->adapter, INFO,
+                   "Current TxPower Level=%d, Max Power=%d, Min Power=%d\n",
+                   priv->tx_power_level, priv->max_tx_power_level,
+                   priv->min_tx_power_level);
+
+       return 0;
+}
+
+/*
+ * This function handles the command response of set rf antenna
+ */
+static int mwifiex_ret_rf_antenna(struct mwifiex_private *priv,
+                                 struct host_cmd_ds_command *resp)
+{
+       struct host_cmd_ds_rf_ant_mimo *ant_mimo = &resp->params.ant_mimo;
+       struct host_cmd_ds_rf_ant_siso *ant_siso = &resp->params.ant_siso;
+       struct mwifiex_adapter *adapter = priv->adapter;
+
+       if (adapter->hw_dev_mcs_support == HT_STREAM_2X2)
+               mwifiex_dbg(adapter, INFO,
+                           "RF_ANT_RESP: Tx action = 0x%x, Tx Mode = 0x%04x\t"
+                           "Rx action = 0x%x, Rx Mode = 0x%04x\n",
+                           le16_to_cpu(ant_mimo->action_tx),
+                           le16_to_cpu(ant_mimo->tx_ant_mode),
+                           le16_to_cpu(ant_mimo->action_rx),
+                           le16_to_cpu(ant_mimo->rx_ant_mode));
+       else
+               mwifiex_dbg(adapter, INFO,
+                           "RF_ANT_RESP: action = 0x%x, Mode = 0x%04x\n",
+                           le16_to_cpu(ant_siso->action),
+                           le16_to_cpu(ant_siso->ant_mode));
+
+       return 0;
+}
+
+/*
+ * This function handles the command response of set/get MAC address.
+ *
+ * Handling includes saving the MAC address in driver.
+ */
+static int mwifiex_ret_802_11_mac_address(struct mwifiex_private *priv,
+                                         struct host_cmd_ds_command *resp)
+{
+       struct host_cmd_ds_802_11_mac_address *cmd_mac_addr =
+                                                       &resp->params.mac_addr;
+
+       memcpy(priv->curr_addr, cmd_mac_addr->mac_addr, ETH_ALEN);
+
+       mwifiex_dbg(priv->adapter, INFO,
+                   "info: set mac address: %pM\n", priv->curr_addr);
+
+       return 0;
+}
+
+/*
+ * This function handles the command response of set/get MAC multicast
+ * address.
+ */
+static int mwifiex_ret_mac_multicast_adr(struct mwifiex_private *priv,
+                                        struct host_cmd_ds_command *resp)
+{
+       return 0;
+}
+
+/*
+ * This function handles the command response of get Tx rate query.
+ *
+ * Handling includes changing the header fields into CPU format
+ * and saving the Tx rate and HT information parameters in driver.
+ *
+ * Both rate configuration and current data rate can be retrieved
+ * with this request.
+ */
+static int mwifiex_ret_802_11_tx_rate_query(struct mwifiex_private *priv,
+                                           struct host_cmd_ds_command *resp)
+{
+       priv->tx_rate = resp->params.tx_rate.tx_rate;
+       priv->tx_htinfo = resp->params.tx_rate.ht_info;
+       if (!priv->is_data_rate_auto)
+               priv->data_rate =
+                       mwifiex_index_to_data_rate(priv, priv->tx_rate,
+                                                  priv->tx_htinfo);
+
+       return 0;
+}
+
+/*
+ * This function handles the command response of a deauthenticate
+ * command.
+ *
+ * If the deauthenticated MAC matches the current BSS MAC, the connection
+ * state is reset.
+ */
+static int mwifiex_ret_802_11_deauthenticate(struct mwifiex_private *priv,
+                                            struct host_cmd_ds_command *resp)
+{
+       struct mwifiex_adapter *adapter = priv->adapter;
+
+       adapter->dbg.num_cmd_deauth++;
+       if (!memcmp(resp->params.deauth.mac_addr,
+                   &priv->curr_bss_params.bss_descriptor.mac_address,
+                   sizeof(resp->params.deauth.mac_addr)))
+               mwifiex_reset_connect_state(priv, WLAN_REASON_DEAUTH_LEAVING);
+
+       return 0;
+}
+
+/*
+ * This function handles the command response of ad-hoc stop.
+ *
+ * The function resets the connection state in driver.
+ */
+static int mwifiex_ret_802_11_ad_hoc_stop(struct mwifiex_private *priv,
+                                         struct host_cmd_ds_command *resp)
+{
+       mwifiex_reset_connect_state(priv, WLAN_REASON_DEAUTH_LEAVING);
+       return 0;
+}
+
+/*
+ * This function handles the command response of set/get v1 key material.
+ *
+ * Handling includes updating the driver parameters to reflect the
+ * changes.
+ */
+static int mwifiex_ret_802_11_key_material_v1(struct mwifiex_private *priv,
+                                             struct host_cmd_ds_command *resp)
+{
+       struct host_cmd_ds_802_11_key_material *key =
+                                               &resp->params.key_material;
+
+       if (le16_to_cpu(key->action) == HostCmd_ACT_GEN_SET) {
+               if ((le16_to_cpu(key->key_param_set.key_info) & KEY_MCAST)) {
+                       mwifiex_dbg(priv->adapter, INFO,
+                                   "info: key: GTK is set\n");
+                       priv->wpa_is_gtk_set = true;
+                       priv->scan_block = false;
+                       priv->port_open = true;
+               }
+       }
+
+       memset(priv->aes_key.key_param_set.key, 0,
+              sizeof(key->key_param_set.key));
+       priv->aes_key.key_param_set.key_len = key->key_param_set.key_len;
+       memcpy(priv->aes_key.key_param_set.key, key->key_param_set.key,
+              le16_to_cpu(priv->aes_key.key_param_set.key_len));
+
+       return 0;
+}
+
+/*
+ * This function handles the command response of set/get v2 key material.
+ *
+ * Handling includes updating the driver parameters to reflect the
+ * changes.
+ */
+static int mwifiex_ret_802_11_key_material_v2(struct mwifiex_private *priv,
+                                             struct host_cmd_ds_command *resp)
+{
+       struct host_cmd_ds_802_11_key_material_v2 *key_v2;
+       __le16 len;
+
+       key_v2 = &resp->params.key_material_v2;
+       if (le16_to_cpu(key_v2->action) == HostCmd_ACT_GEN_SET) {
+               if ((le16_to_cpu(key_v2->key_param_set.key_info) & KEY_MCAST)) {
+                       mwifiex_dbg(priv->adapter, INFO, "info: key: GTK is set\n");
+                       priv->wpa_is_gtk_set = true;
+                       priv->scan_block = false;
+                       priv->port_open = true;
+               }
+       }
+
+       if (key_v2->key_param_set.key_type != KEY_TYPE_ID_AES)
+               return 0;
+
+       memset(priv->aes_key_v2.key_param_set.key_params.aes.key, 0,
+              WLAN_KEY_LEN_CCMP);
+       priv->aes_key_v2.key_param_set.key_params.aes.key_len =
+                               key_v2->key_param_set.key_params.aes.key_len;
+       len = priv->aes_key_v2.key_param_set.key_params.aes.key_len;
+       memcpy(priv->aes_key_v2.key_param_set.key_params.aes.key,
+              key_v2->key_param_set.key_params.aes.key, le16_to_cpu(len));
+
+       return 0;
+}
+
+/* Wrapper function for processing response of key material command */
+static int mwifiex_ret_802_11_key_material(struct mwifiex_private *priv,
+                                          struct host_cmd_ds_command *resp)
+{
+       if (priv->adapter->key_api_major_ver == KEY_API_VER_MAJOR_V2)
+               return mwifiex_ret_802_11_key_material_v2(priv, resp);
+       else
+               return mwifiex_ret_802_11_key_material_v1(priv, resp);
+}
+
+/*
+ * This function handles the command response of get 11d domain information.
+ */
+static int mwifiex_ret_802_11d_domain_info(struct mwifiex_private *priv,
+                                          struct host_cmd_ds_command *resp)
+{
+       struct host_cmd_ds_802_11d_domain_info_rsp *domain_info =
+               &resp->params.domain_info_resp;
+       struct mwifiex_ietypes_domain_param_set *domain = &domain_info->domain;
+       u16 action = le16_to_cpu(domain_info->action);
+       u8 no_of_triplet;
+
+       no_of_triplet = (u8) ((le16_to_cpu(domain->header.len)
+                               - IEEE80211_COUNTRY_STRING_LEN)
+                             / sizeof(struct ieee80211_country_ie_triplet));
+
+       mwifiex_dbg(priv->adapter, INFO,
+                   "info: 11D Domain Info Resp: no_of_triplet=%d\n",
+                   no_of_triplet);
+
+       if (no_of_triplet > MWIFIEX_MAX_TRIPLET_802_11D) {
+               mwifiex_dbg(priv->adapter, FATAL,
+                           "11D: invalid number of triplets %d returned\n",
+                           no_of_triplet);
+               return -1;
+       }
+
+       switch (action) {
+       case HostCmd_ACT_GEN_SET:  /* Proc Set Action */
+               break;
+       case HostCmd_ACT_GEN_GET:
+               break;
+       default:
+               mwifiex_dbg(priv->adapter, ERROR,
+                           "11D: invalid action:%d\n", domain_info->action);
+               return -1;
+       }
+
+       return 0;
+}
+
+/*
+ * This function handles the command response of get extended version.
+ *
+ * Handling includes forming the extended version string and sending it
+ * to application.
+ */
+static int mwifiex_ret_ver_ext(struct mwifiex_private *priv,
+                              struct host_cmd_ds_command *resp,
+                              struct host_cmd_ds_version_ext *version_ext)
+{
+       struct host_cmd_ds_version_ext *ver_ext = &resp->params.verext;
+
+       if (version_ext) {
+               version_ext->version_str_sel = ver_ext->version_str_sel;
+               memcpy(version_ext->version_str, ver_ext->version_str,
+                      sizeof(char) * 128);
+               memcpy(priv->version_str, ver_ext->version_str, 128);
+       }
+       return 0;
+}
+
+/*
+ * This function handles the command response of remain on channel.
+ */
+static int
+mwifiex_ret_remain_on_chan(struct mwifiex_private *priv,
+                          struct host_cmd_ds_command *resp,
+                          struct host_cmd_ds_remain_on_chan *roc_cfg)
+{
+       struct host_cmd_ds_remain_on_chan *resp_cfg = &resp->params.roc_cfg;
+
+       if (roc_cfg)
+               memcpy(roc_cfg, resp_cfg, sizeof(*roc_cfg));
+
+       return 0;
+}
+
+/*
+ * This function handles the command response of P2P mode cfg.
+ */
+static int
+mwifiex_ret_p2p_mode_cfg(struct mwifiex_private *priv,
+                        struct host_cmd_ds_command *resp,
+                        void *data_buf)
+{
+       struct host_cmd_ds_p2p_mode_cfg *mode_cfg = &resp->params.mode_cfg;
+
+       if (data_buf)
+               *((u16 *)data_buf) = le16_to_cpu(mode_cfg->mode);
+
+       return 0;
+}
+
+/* This function handles the command response of mem_access command
+ */
+static int
+mwifiex_ret_mem_access(struct mwifiex_private *priv,
+                      struct host_cmd_ds_command *resp, void *pioctl_buf)
+{
+       struct host_cmd_ds_mem_access *mem = (void *)&resp->params.mem;
+
+       priv->mem_rw.addr = le32_to_cpu(mem->addr);
+       priv->mem_rw.value = le32_to_cpu(mem->value);
+
+       return 0;
+}
+/*
+ * This function handles the command response of register access.
+ *
+ * The register value and offset are returned to the user. For EEPROM
+ * access, the byte count is also returned.
+ */
+static int mwifiex_ret_reg_access(u16 type, struct host_cmd_ds_command *resp,
+                                 void *data_buf)
+{
+       struct mwifiex_ds_reg_rw *reg_rw;
+       struct mwifiex_ds_read_eeprom *eeprom;
+       union reg {
+               struct host_cmd_ds_mac_reg_access *mac;
+               struct host_cmd_ds_bbp_reg_access *bbp;
+               struct host_cmd_ds_rf_reg_access *rf;
+               struct host_cmd_ds_pmic_reg_access *pmic;
+               struct host_cmd_ds_802_11_eeprom_access *eeprom;
+       } r;
+
+       if (!data_buf)
+               return 0;
+
+       reg_rw = data_buf;
+       eeprom = data_buf;
+       switch (type) {
+       case HostCmd_CMD_MAC_REG_ACCESS:
+               r.mac = &resp->params.mac_reg;
+               reg_rw->offset = cpu_to_le32((u32) le16_to_cpu(r.mac->offset));
+               reg_rw->value = r.mac->value;
+               break;
+       case HostCmd_CMD_BBP_REG_ACCESS:
+               r.bbp = &resp->params.bbp_reg;
+               reg_rw->offset = cpu_to_le32((u32) le16_to_cpu(r.bbp->offset));
+               reg_rw->value = cpu_to_le32((u32) r.bbp->value);
+               break;
+
+       case HostCmd_CMD_RF_REG_ACCESS:
+               r.rf = &resp->params.rf_reg;
+               reg_rw->offset = cpu_to_le32((u32) le16_to_cpu(r.rf->offset));
+               reg_rw->value = cpu_to_le32((u32) r.bbp->value);
+               break;
+       case HostCmd_CMD_PMIC_REG_ACCESS:
+               r.pmic = &resp->params.pmic_reg;
+               reg_rw->offset = cpu_to_le32((u32) le16_to_cpu(r.pmic->offset));
+               reg_rw->value = cpu_to_le32((u32) r.pmic->value);
+               break;
+       case HostCmd_CMD_CAU_REG_ACCESS:
+               r.rf = &resp->params.rf_reg;
+               reg_rw->offset = cpu_to_le32((u32) le16_to_cpu(r.rf->offset));
+               reg_rw->value = cpu_to_le32((u32) r.rf->value);
+               break;
+       case HostCmd_CMD_802_11_EEPROM_ACCESS:
+               r.eeprom = &resp->params.eeprom;
+               pr_debug("info: EEPROM read len=%x\n", r.eeprom->byte_count);
+               if (le16_to_cpu(eeprom->byte_count) <
+                   le16_to_cpu(r.eeprom->byte_count)) {
+                       eeprom->byte_count = cpu_to_le16(0);
+                       pr_debug("info: EEPROM read length is too big\n");
+                       return -1;
+               }
+               eeprom->offset = r.eeprom->offset;
+               eeprom->byte_count = r.eeprom->byte_count;
+               if (le16_to_cpu(eeprom->byte_count) > 0)
+                       memcpy(&eeprom->value, &r.eeprom->value,
+                              le16_to_cpu(r.eeprom->byte_count));
+
+               break;
+       default:
+               return -1;
+       }
+       return 0;
+}
+
+/*
+ * This function handles the command response of get IBSS coalescing status.
+ *
+ * If the received BSSID is different than the current one, the current BSSID,
+ * beacon interval, ATIM window and ERP information are updated, along with
+ * changing the ad-hoc state accordingly.
+ */
+static int mwifiex_ret_ibss_coalescing_status(struct mwifiex_private *priv,
+                                             struct host_cmd_ds_command *resp)
+{
+       struct host_cmd_ds_802_11_ibss_status *ibss_coal_resp =
+                                       &(resp->params.ibss_coalescing);
+
+       if (le16_to_cpu(ibss_coal_resp->action) == HostCmd_ACT_GEN_SET)
+               return 0;
+
+       mwifiex_dbg(priv->adapter, INFO,
+                   "info: new BSSID %pM\n", ibss_coal_resp->bssid);
+
+       /* If rsp has NULL BSSID, Just return..... No Action */
+       if (is_zero_ether_addr(ibss_coal_resp->bssid)) {
+               mwifiex_dbg(priv->adapter, FATAL, "new BSSID is NULL\n");
+               return 0;
+       }
+
+       /* If BSSID is diff, modify current BSS parameters */
+       if (!ether_addr_equal(priv->curr_bss_params.bss_descriptor.mac_address, ibss_coal_resp->bssid)) {
+               /* BSSID */
+               memcpy(priv->curr_bss_params.bss_descriptor.mac_address,
+                      ibss_coal_resp->bssid, ETH_ALEN);
+
+               /* Beacon Interval */
+               priv->curr_bss_params.bss_descriptor.beacon_period
+                       = le16_to_cpu(ibss_coal_resp->beacon_interval);
+
+               /* ERP Information */
+               priv->curr_bss_params.bss_descriptor.erp_flags =
+                       (u8) le16_to_cpu(ibss_coal_resp->use_g_rate_protect);
+
+               priv->adhoc_state = ADHOC_COALESCED;
+       }
+
+       return 0;
+}
+static int mwifiex_ret_tdls_oper(struct mwifiex_private *priv,
+                                struct host_cmd_ds_command *resp)
+{
+       struct host_cmd_ds_tdls_oper *cmd_tdls_oper = &resp->params.tdls_oper;
+       u16 reason = le16_to_cpu(cmd_tdls_oper->reason);
+       u16 action = le16_to_cpu(cmd_tdls_oper->tdls_action);
+       struct mwifiex_sta_node *node =
+                          mwifiex_get_sta_entry(priv, cmd_tdls_oper->peer_mac);
+
+       switch (action) {
+       case ACT_TDLS_DELETE:
+               if (reason) {
+                       if (!node || reason == TDLS_ERR_LINK_NONEXISTENT)
+                               mwifiex_dbg(priv->adapter, MSG,
+                                           "TDLS link delete for %pM failed: reason %d\n",
+                                           cmd_tdls_oper->peer_mac, reason);
+                       else
+                               mwifiex_dbg(priv->adapter, ERROR,
+                                           "TDLS link delete for %pM failed: reason %d\n",
+                                           cmd_tdls_oper->peer_mac, reason);
+               } else {
+                       mwifiex_dbg(priv->adapter, MSG,
+                                   "TDLS link delete for %pM successful\n",
+                                   cmd_tdls_oper->peer_mac);
+               }
+               break;
+       case ACT_TDLS_CREATE:
+               if (reason) {
+                       mwifiex_dbg(priv->adapter, ERROR,
+                                   "TDLS link creation for %pM failed: reason %d",
+                                   cmd_tdls_oper->peer_mac, reason);
+                       if (node && reason != TDLS_ERR_LINK_EXISTS)
+                               node->tdls_status = TDLS_SETUP_FAILURE;
+               } else {
+                       mwifiex_dbg(priv->adapter, MSG,
+                                   "TDLS link creation for %pM successful",
+                                   cmd_tdls_oper->peer_mac);
+               }
+               break;
+       case ACT_TDLS_CONFIG:
+               if (reason) {
+                       mwifiex_dbg(priv->adapter, ERROR,
+                                   "TDLS link config for %pM failed, reason %d\n",
+                                   cmd_tdls_oper->peer_mac, reason);
+                       if (node)
+                               node->tdls_status = TDLS_SETUP_FAILURE;
+               } else {
+                       mwifiex_dbg(priv->adapter, MSG,
+                                   "TDLS link config for %pM successful\n",
+                                   cmd_tdls_oper->peer_mac);
+               }
+               break;
+       default:
+               mwifiex_dbg(priv->adapter, ERROR,
+                           "Unknown TDLS command action response %d", action);
+               return -1;
+       }
+
+       return 0;
+}
+/*
+ * This function handles the command response for subscribe event command.
+ */
+static int mwifiex_ret_subsc_evt(struct mwifiex_private *priv,
+                                struct host_cmd_ds_command *resp)
+{
+       struct host_cmd_ds_802_11_subsc_evt *cmd_sub_event =
+               &resp->params.subsc_evt;
+
+       /* For every subscribe event command (Get/Set/Clear), FW reports the
+        * current set of subscribed events*/
+       mwifiex_dbg(priv->adapter, EVENT,
+                   "Bitmap of currently subscribed events: %16x\n",
+                   le16_to_cpu(cmd_sub_event->events));
+
+       return 0;
+}
+
+static int mwifiex_ret_uap_sta_list(struct mwifiex_private *priv,
+                                   struct host_cmd_ds_command *resp)
+{
+       struct host_cmd_ds_sta_list *sta_list =
+               &resp->params.sta_list;
+       struct mwifiex_ie_types_sta_info *sta_info = (void *)&sta_list->tlv;
+       int i;
+       struct mwifiex_sta_node *sta_node;
+
+       for (i = 0; i < sta_list->sta_count; i++) {
+               sta_node = mwifiex_get_sta_entry(priv, sta_info->mac);
+               if (unlikely(!sta_node))
+                       continue;
+
+               sta_node->stats.rssi = sta_info->rssi;
+               sta_info++;
+       }
+
+       return 0;
+}
+
+/* This function handles the command response of set_cfg_data */
+static int mwifiex_ret_cfg_data(struct mwifiex_private *priv,
+                               struct host_cmd_ds_command *resp)
+{
+       if (resp->result != HostCmd_RESULT_OK) {
+               mwifiex_dbg(priv->adapter, ERROR, "Cal data cmd resp failed\n");
+               return -1;
+       }
+
+       return 0;
+}
+
+/** This Function handles the command response of sdio rx aggr */
+static int mwifiex_ret_sdio_rx_aggr_cfg(struct mwifiex_private *priv,
+                                       struct host_cmd_ds_command *resp)
+{
+       struct mwifiex_adapter *adapter = priv->adapter;
+       struct host_cmd_sdio_sp_rx_aggr_cfg *cfg =
+                               &resp->params.sdio_rx_aggr_cfg;
+
+       adapter->sdio_rx_aggr_enable = cfg->enable;
+       adapter->sdio_rx_block_size = le16_to_cpu(cfg->block_size);
+
+       return 0;
+}
+
+static int mwifiex_ret_robust_coex(struct mwifiex_private *priv,
+                                  struct host_cmd_ds_command *resp,
+                                  bool *is_timeshare)
+{
+       struct host_cmd_ds_robust_coex *coex = &resp->params.coex;
+       struct mwifiex_ie_types_robust_coex *coex_tlv;
+       u16 action = le16_to_cpu(coex->action);
+       u32 mode;
+
+       coex_tlv = (struct mwifiex_ie_types_robust_coex
+                   *)((u8 *)coex + sizeof(struct host_cmd_ds_robust_coex));
+       if (action == HostCmd_ACT_GEN_GET) {
+               mode = le32_to_cpu(coex_tlv->mode);
+               if (mode == MWIFIEX_COEX_MODE_TIMESHARE)
+                       *is_timeshare = true;
+               else
+                       *is_timeshare = false;
+       }
+
+       return 0;
+}
+
+/*
+ * This function handles the command responses.
+ *
+ * This is a generic function, which calls command specific
+ * response handlers based on the command ID.
+ */
+int mwifiex_process_sta_cmdresp(struct mwifiex_private *priv, u16 cmdresp_no,
+                               struct host_cmd_ds_command *resp)
+{
+       int ret = 0;
+       struct mwifiex_adapter *adapter = priv->adapter;
+       void *data_buf = adapter->curr_cmd->data_buf;
+
+       /* If the command is not successful, cleanup and return failure */
+       if (resp->result != HostCmd_RESULT_OK) {
+               mwifiex_process_cmdresp_error(priv, resp);
+               return -1;
+       }
+       /* Command successful, handle response */
+       switch (cmdresp_no) {
+       case HostCmd_CMD_GET_HW_SPEC:
+               ret = mwifiex_ret_get_hw_spec(priv, resp);
+               break;
+       case HostCmd_CMD_CFG_DATA:
+               ret = mwifiex_ret_cfg_data(priv, resp);
+               break;
+       case HostCmd_CMD_MAC_CONTROL:
+               break;
+       case HostCmd_CMD_802_11_MAC_ADDRESS:
+               ret = mwifiex_ret_802_11_mac_address(priv, resp);
+               break;
+       case HostCmd_CMD_MAC_MULTICAST_ADR:
+               ret = mwifiex_ret_mac_multicast_adr(priv, resp);
+               break;
+       case HostCmd_CMD_TX_RATE_CFG:
+               ret = mwifiex_ret_tx_rate_cfg(priv, resp);
+               break;
+       case HostCmd_CMD_802_11_SCAN:
+               ret = mwifiex_ret_802_11_scan(priv, resp);
+               adapter->curr_cmd->wait_q_enabled = false;
+               break;
+       case HostCmd_CMD_802_11_SCAN_EXT:
+               ret = mwifiex_ret_802_11_scan_ext(priv, resp);
+               adapter->curr_cmd->wait_q_enabled = false;
+               break;
+       case HostCmd_CMD_802_11_BG_SCAN_QUERY:
+               ret = mwifiex_ret_802_11_scan(priv, resp);
+               mwifiex_dbg(adapter, CMD,
+                           "info: CMD_RESP: BG_SCAN result is ready!\n");
+               break;
+       case HostCmd_CMD_TXPWR_CFG:
+               ret = mwifiex_ret_tx_power_cfg(priv, resp);
+               break;
+       case HostCmd_CMD_RF_TX_PWR:
+               ret = mwifiex_ret_rf_tx_power(priv, resp);
+               break;
+       case HostCmd_CMD_RF_ANTENNA:
+               ret = mwifiex_ret_rf_antenna(priv, resp);
+               break;
+       case HostCmd_CMD_802_11_PS_MODE_ENH:
+               ret = mwifiex_ret_enh_power_mode(priv, resp, data_buf);
+               break;
+       case HostCmd_CMD_802_11_HS_CFG_ENH:
+               ret = mwifiex_ret_802_11_hs_cfg(priv, resp);
+               break;
+       case HostCmd_CMD_802_11_ASSOCIATE:
+               ret = mwifiex_ret_802_11_associate(priv, resp);
+               break;
+       case HostCmd_CMD_802_11_DEAUTHENTICATE:
+               ret = mwifiex_ret_802_11_deauthenticate(priv, resp);
+               break;
+       case HostCmd_CMD_802_11_AD_HOC_START:
+       case HostCmd_CMD_802_11_AD_HOC_JOIN:
+               ret = mwifiex_ret_802_11_ad_hoc(priv, resp);
+               break;
+       case HostCmd_CMD_802_11_AD_HOC_STOP:
+               ret = mwifiex_ret_802_11_ad_hoc_stop(priv, resp);
+               break;
+       case HostCmd_CMD_802_11_GET_LOG:
+               ret = mwifiex_ret_get_log(priv, resp, data_buf);
+               break;
+       case HostCmd_CMD_RSSI_INFO:
+               ret = mwifiex_ret_802_11_rssi_info(priv, resp);
+               break;
+       case HostCmd_CMD_802_11_SNMP_MIB:
+               ret = mwifiex_ret_802_11_snmp_mib(priv, resp, data_buf);
+               break;
+       case HostCmd_CMD_802_11_TX_RATE_QUERY:
+               ret = mwifiex_ret_802_11_tx_rate_query(priv, resp);
+               break;
+       case HostCmd_CMD_VERSION_EXT:
+               ret = mwifiex_ret_ver_ext(priv, resp, data_buf);
+               break;
+       case HostCmd_CMD_REMAIN_ON_CHAN:
+               ret = mwifiex_ret_remain_on_chan(priv, resp, data_buf);
+               break;
+       case HostCmd_CMD_11AC_CFG:
+               break;
+       case HostCmd_CMD_P2P_MODE_CFG:
+               ret = mwifiex_ret_p2p_mode_cfg(priv, resp, data_buf);
+               break;
+       case HostCmd_CMD_MGMT_FRAME_REG:
+       case HostCmd_CMD_FUNC_INIT:
+       case HostCmd_CMD_FUNC_SHUTDOWN:
+               break;
+       case HostCmd_CMD_802_11_KEY_MATERIAL:
+               ret = mwifiex_ret_802_11_key_material(priv, resp);
+               break;
+       case HostCmd_CMD_802_11D_DOMAIN_INFO:
+               ret = mwifiex_ret_802_11d_domain_info(priv, resp);
+               break;
+       case HostCmd_CMD_11N_ADDBA_REQ:
+               ret = mwifiex_ret_11n_addba_req(priv, resp);
+               break;
+       case HostCmd_CMD_11N_DELBA:
+               ret = mwifiex_ret_11n_delba(priv, resp);
+               break;
+       case HostCmd_CMD_11N_ADDBA_RSP:
+               ret = mwifiex_ret_11n_addba_resp(priv, resp);
+               break;
+       case HostCmd_CMD_RECONFIGURE_TX_BUFF:
+               if (0xffff == (u16)le16_to_cpu(resp->params.tx_buf.buff_size)) {
+                       if (adapter->iface_type == MWIFIEX_USB &&
+                           adapter->usb_mc_setup) {
+                               if (adapter->if_ops.multi_port_resync)
+                                       adapter->if_ops.
+                                               multi_port_resync(adapter);
+                               adapter->usb_mc_setup = false;
+                               adapter->tx_lock_flag = false;
+                       }
+                       break;
+               }
+               adapter->tx_buf_size = (u16) le16_to_cpu(resp->params.
+                                                            tx_buf.buff_size);
+               adapter->tx_buf_size = (adapter->tx_buf_size
+                                       / MWIFIEX_SDIO_BLOCK_SIZE)
+                                      * MWIFIEX_SDIO_BLOCK_SIZE;
+               adapter->curr_tx_buf_size = adapter->tx_buf_size;
+               mwifiex_dbg(adapter, CMD, "cmd: curr_tx_buf_size=%d\n",
+                           adapter->curr_tx_buf_size);
+
+               if (adapter->if_ops.update_mp_end_port)
+                       adapter->if_ops.update_mp_end_port(adapter,
+                               le16_to_cpu(resp->params.tx_buf.mp_end_port));
+               break;
+       case HostCmd_CMD_AMSDU_AGGR_CTRL:
+               break;
+       case HostCmd_CMD_WMM_GET_STATUS:
+               ret = mwifiex_ret_wmm_get_status(priv, resp);
+               break;
+       case HostCmd_CMD_802_11_IBSS_COALESCING_STATUS:
+               ret = mwifiex_ret_ibss_coalescing_status(priv, resp);
+               break;
+       case HostCmd_CMD_MEM_ACCESS:
+               ret = mwifiex_ret_mem_access(priv, resp, data_buf);
+               break;
+       case HostCmd_CMD_MAC_REG_ACCESS:
+       case HostCmd_CMD_BBP_REG_ACCESS:
+       case HostCmd_CMD_RF_REG_ACCESS:
+       case HostCmd_CMD_PMIC_REG_ACCESS:
+       case HostCmd_CMD_CAU_REG_ACCESS:
+       case HostCmd_CMD_802_11_EEPROM_ACCESS:
+               ret = mwifiex_ret_reg_access(cmdresp_no, resp, data_buf);
+               break;
+       case HostCmd_CMD_SET_BSS_MODE:
+               break;
+       case HostCmd_CMD_11N_CFG:
+               break;
+       case HostCmd_CMD_PCIE_DESC_DETAILS:
+               break;
+       case HostCmd_CMD_802_11_SUBSCRIBE_EVENT:
+               ret = mwifiex_ret_subsc_evt(priv, resp);
+               break;
+       case HostCmd_CMD_UAP_SYS_CONFIG:
+               break;
+       case HOST_CMD_APCMD_STA_LIST:
+               ret = mwifiex_ret_uap_sta_list(priv, resp);
+               break;
+       case HostCmd_CMD_UAP_BSS_START:
+               adapter->tx_lock_flag = false;
+               adapter->pps_uapsd_mode = false;
+               adapter->delay_null_pkt = false;
+               priv->bss_started = 1;
+               break;
+       case HostCmd_CMD_UAP_BSS_STOP:
+               priv->bss_started = 0;
+               break;
+       case HostCmd_CMD_UAP_STA_DEAUTH:
+               break;
+       case HOST_CMD_APCMD_SYS_RESET:
+               break;
+       case HostCmd_CMD_MEF_CFG:
+               break;
+       case HostCmd_CMD_COALESCE_CFG:
+               break;
+       case HostCmd_CMD_TDLS_OPER:
+               ret = mwifiex_ret_tdls_oper(priv, resp);
+       case HostCmd_CMD_MC_POLICY:
+               break;
+       case HostCmd_CMD_CHAN_REPORT_REQUEST:
+               break;
+       case HostCmd_CMD_SDIO_SP_RX_AGGR_CFG:
+               ret = mwifiex_ret_sdio_rx_aggr_cfg(priv, resp);
+               break;
+       case HostCmd_CMD_TDLS_CONFIG:
+               break;
+       case HostCmd_CMD_ROBUST_COEX:
+               ret = mwifiex_ret_robust_coex(priv, resp, data_buf);
+               break;
+       default:
+               mwifiex_dbg(adapter, ERROR,
+                           "CMD_RESP: unknown cmd response %#x\n",
+                           resp->command);
+               break;
+       }
+
+       return ret;
+}
diff --git a/drivers/net/wireless/marvell/mwifiex/sta_event.c b/drivers/net/wireless/marvell/mwifiex/sta_event.c
new file mode 100644 (file)
index 0000000..ff3ee9d
--- /dev/null
@@ -0,0 +1,864 @@
+/*
+ * Marvell Wireless LAN device driver: station event handling
+ *
+ * Copyright (C) 2011-2014, Marvell International Ltd.
+ *
+ * This software file (the "File") is distributed by Marvell International
+ * Ltd. under the terms of the GNU General Public License Version 2, June 1991
+ * (the "License").  You may use, redistribute and/or modify this File in
+ * accordance with the terms and conditions of the License, a copy of which
+ * is available by writing to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the
+ * worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
+ *
+ * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
+ * ARE EXPRESSLY DISCLAIMED.  The License provides additional details about
+ * this warranty disclaimer.
+ */
+
+#include "decl.h"
+#include "ioctl.h"
+#include "util.h"
+#include "fw.h"
+#include "main.h"
+#include "wmm.h"
+#include "11n.h"
+
+/*
+ * This function resets the connection state.
+ *
+ * The function is invoked after receiving a disconnect event from firmware,
+ * and performs the following actions -
+ *      - Set media status to disconnected
+ *      - Clean up Tx and Rx packets
+ *      - Resets SNR/NF/RSSI value in driver
+ *      - Resets security configurations in driver
+ *      - Enables auto data rate
+ *      - Saves the previous SSID and BSSID so that they can
+ *        be used for re-association, if required
+ *      - Erases current SSID and BSSID information
+ *      - Sends a disconnect event to upper layers/applications.
+ */
+void
+mwifiex_reset_connect_state(struct mwifiex_private *priv, u16 reason_code)
+{
+       struct mwifiex_adapter *adapter = priv->adapter;
+
+       if (!priv->media_connected)
+               return;
+
+       mwifiex_dbg(adapter, INFO,
+                   "info: handles disconnect event\n");
+
+       priv->media_connected = false;
+
+       priv->scan_block = false;
+       priv->port_open = false;
+
+       if ((GET_BSS_ROLE(priv) == MWIFIEX_BSS_ROLE_STA) &&
+           ISSUPP_TDLS_ENABLED(priv->adapter->fw_cap_info)) {
+               mwifiex_disable_all_tdls_links(priv);
+
+               if (priv->adapter->auto_tdls)
+                       mwifiex_clean_auto_tdls(priv);
+       }
+
+       /* Free Tx and Rx packets, report disconnect to upper layer */
+       mwifiex_clean_txrx(priv);
+
+       /* Reset SNR/NF/RSSI values */
+       priv->data_rssi_last = 0;
+       priv->data_nf_last = 0;
+       priv->data_rssi_avg = 0;
+       priv->data_nf_avg = 0;
+       priv->bcn_rssi_last = 0;
+       priv->bcn_nf_last = 0;
+       priv->bcn_rssi_avg = 0;
+       priv->bcn_nf_avg = 0;
+       priv->rxpd_rate = 0;
+       priv->rxpd_htinfo = 0;
+       priv->sec_info.wpa_enabled = false;
+       priv->sec_info.wpa2_enabled = false;
+       priv->wpa_ie_len = 0;
+
+       priv->sec_info.wapi_enabled = false;
+       priv->wapi_ie_len = 0;
+       priv->sec_info.wapi_key_on = false;
+
+       priv->sec_info.encryption_mode = 0;
+
+       /* Enable auto data rate */
+       priv->is_data_rate_auto = true;
+       priv->data_rate = 0;
+
+       if ((GET_BSS_ROLE(priv) == MWIFIEX_BSS_ROLE_STA ||
+            GET_BSS_ROLE(priv) == MWIFIEX_BSS_ROLE_UAP) && priv->hist_data)
+               mwifiex_hist_data_reset(priv);
+
+       if (priv->bss_mode == NL80211_IFTYPE_ADHOC) {
+               priv->adhoc_state = ADHOC_IDLE;
+               priv->adhoc_is_link_sensed = false;
+       }
+
+       /*
+        * Memorize the previous SSID and BSSID so
+        * it could be used for re-assoc
+        */
+
+       mwifiex_dbg(adapter, INFO,
+                   "info: previous SSID=%s, SSID len=%u\n",
+                   priv->prev_ssid.ssid, priv->prev_ssid.ssid_len);
+
+       mwifiex_dbg(adapter, INFO,
+                   "info: current SSID=%s, SSID len=%u\n",
+                   priv->curr_bss_params.bss_descriptor.ssid.ssid,
+                   priv->curr_bss_params.bss_descriptor.ssid.ssid_len);
+
+       memcpy(&priv->prev_ssid,
+              &priv->curr_bss_params.bss_descriptor.ssid,
+              sizeof(struct cfg80211_ssid));
+
+       memcpy(priv->prev_bssid,
+              priv->curr_bss_params.bss_descriptor.mac_address, ETH_ALEN);
+
+       /* Need to erase the current SSID and BSSID info */
+       memset(&priv->curr_bss_params, 0x00, sizeof(priv->curr_bss_params));
+
+       adapter->tx_lock_flag = false;
+       adapter->pps_uapsd_mode = false;
+
+       if (adapter->is_cmd_timedout && adapter->curr_cmd)
+               return;
+       priv->media_connected = false;
+       mwifiex_dbg(adapter, MSG,
+                   "info: successfully disconnected from %pM: reason code %d\n",
+                   priv->cfg_bssid, reason_code);
+       if (priv->bss_mode == NL80211_IFTYPE_STATION ||
+           priv->bss_mode == NL80211_IFTYPE_P2P_CLIENT) {
+               cfg80211_disconnected(priv->netdev, reason_code, NULL, 0,
+                                     false, GFP_KERNEL);
+       }
+       eth_zero_addr(priv->cfg_bssid);
+
+       mwifiex_stop_net_dev_queue(priv->netdev, adapter);
+       if (netif_carrier_ok(priv->netdev))
+               netif_carrier_off(priv->netdev);
+}
+
+static int mwifiex_parse_tdls_event(struct mwifiex_private *priv,
+                                   struct sk_buff *event_skb)
+{
+       int ret = 0;
+       struct mwifiex_adapter *adapter = priv->adapter;
+       struct mwifiex_sta_node *sta_ptr;
+       struct mwifiex_tdls_generic_event *tdls_evt =
+                       (void *)event_skb->data + sizeof(adapter->event_cause);
+       u8 *mac = tdls_evt->peer_mac;
+
+       /* reserved 2 bytes are not mandatory in tdls event */
+       if (event_skb->len < (sizeof(struct mwifiex_tdls_generic_event) -
+                             sizeof(u16) - sizeof(adapter->event_cause))) {
+               mwifiex_dbg(adapter, ERROR, "Invalid event length!\n");
+               return -1;
+       }
+
+       sta_ptr = mwifiex_get_sta_entry(priv, tdls_evt->peer_mac);
+       if (!sta_ptr) {
+               mwifiex_dbg(adapter, ERROR, "cannot get sta entry!\n");
+               return -1;
+       }
+
+       switch (le16_to_cpu(tdls_evt->type)) {
+       case TDLS_EVENT_LINK_TEAR_DOWN:
+               cfg80211_tdls_oper_request(priv->netdev,
+                                          tdls_evt->peer_mac,
+                                          NL80211_TDLS_TEARDOWN,
+                                          le16_to_cpu(tdls_evt->u.reason_code),
+                                          GFP_KERNEL);
+               break;
+       case TDLS_EVENT_CHAN_SWITCH_RESULT:
+               mwifiex_dbg(adapter, EVENT, "tdls channel switch result :\n");
+               mwifiex_dbg(adapter, EVENT,
+                           "status=0x%x, reason=0x%x cur_chan=%d\n",
+                           tdls_evt->u.switch_result.status,
+                           tdls_evt->u.switch_result.reason,
+                           tdls_evt->u.switch_result.cur_chan);
+
+               /* tdls channel switch failed */
+               if (tdls_evt->u.switch_result.status != 0) {
+                       switch (tdls_evt->u.switch_result.cur_chan) {
+                       case TDLS_BASE_CHANNEL:
+                               sta_ptr->tdls_status = TDLS_IN_BASE_CHAN;
+                               break;
+                       case TDLS_OFF_CHANNEL:
+                               sta_ptr->tdls_status = TDLS_IN_OFF_CHAN;
+                               break;
+                       default:
+                               break;
+                       }
+                       return ret;
+               }
+
+               /* tdls channel switch success */
+               switch (tdls_evt->u.switch_result.cur_chan) {
+               case TDLS_BASE_CHANNEL:
+                       if (sta_ptr->tdls_status == TDLS_IN_BASE_CHAN)
+                               break;
+                       mwifiex_update_ralist_tx_pause_in_tdls_cs(priv, mac,
+                                                                 false);
+                       sta_ptr->tdls_status = TDLS_IN_BASE_CHAN;
+                       break;
+               case TDLS_OFF_CHANNEL:
+                       if (sta_ptr->tdls_status == TDLS_IN_OFF_CHAN)
+                               break;
+                       mwifiex_update_ralist_tx_pause_in_tdls_cs(priv, mac,
+                                                                 true);
+                       sta_ptr->tdls_status = TDLS_IN_OFF_CHAN;
+                       break;
+               default:
+                       break;
+               }
+
+               break;
+       case TDLS_EVENT_START_CHAN_SWITCH:
+               mwifiex_dbg(adapter, EVENT, "tdls start channel switch...\n");
+               sta_ptr->tdls_status = TDLS_CHAN_SWITCHING;
+               break;
+       case TDLS_EVENT_CHAN_SWITCH_STOPPED:
+               mwifiex_dbg(adapter, EVENT,
+                           "tdls chan switch stopped, reason=%d\n",
+                           tdls_evt->u.cs_stop_reason);
+               break;
+       default:
+               break;
+       }
+
+       return ret;
+}
+
+static void mwifiex_process_uap_tx_pause(struct mwifiex_private *priv,
+                                        struct mwifiex_ie_types_header *tlv)
+{
+       struct mwifiex_tx_pause_tlv *tp;
+       struct mwifiex_sta_node *sta_ptr;
+       unsigned long flags;
+
+       tp = (void *)tlv;
+       mwifiex_dbg(priv->adapter, EVENT,
+                   "uap tx_pause: %pM pause=%d, pkts=%d\n",
+                   tp->peermac, tp->tx_pause,
+                   tp->pkt_cnt);
+
+       if (ether_addr_equal(tp->peermac, priv->netdev->dev_addr)) {
+               if (tp->tx_pause)
+                       priv->port_open = false;
+               else
+                       priv->port_open = true;
+       } else if (is_multicast_ether_addr(tp->peermac)) {
+               mwifiex_update_ralist_tx_pause(priv, tp->peermac, tp->tx_pause);
+       } else {
+               spin_lock_irqsave(&priv->sta_list_spinlock, flags);
+               sta_ptr = mwifiex_get_sta_entry(priv, tp->peermac);
+               spin_unlock_irqrestore(&priv->sta_list_spinlock, flags);
+
+               if (sta_ptr && sta_ptr->tx_pause != tp->tx_pause) {
+                       sta_ptr->tx_pause = tp->tx_pause;
+                       mwifiex_update_ralist_tx_pause(priv, tp->peermac,
+                                                      tp->tx_pause);
+               }
+       }
+}
+
+static void mwifiex_process_sta_tx_pause(struct mwifiex_private *priv,
+                                        struct mwifiex_ie_types_header *tlv)
+{
+       struct mwifiex_tx_pause_tlv *tp;
+       struct mwifiex_sta_node *sta_ptr;
+       int status;
+       unsigned long flags;
+
+       tp = (void *)tlv;
+       mwifiex_dbg(priv->adapter, EVENT,
+                   "sta tx_pause: %pM pause=%d, pkts=%d\n",
+                   tp->peermac, tp->tx_pause,
+                   tp->pkt_cnt);
+
+       if (ether_addr_equal(tp->peermac, priv->cfg_bssid)) {
+               if (tp->tx_pause)
+                       priv->port_open = false;
+               else
+                       priv->port_open = true;
+       } else {
+               if (!ISSUPP_TDLS_ENABLED(priv->adapter->fw_cap_info))
+                       return;
+
+               status = mwifiex_get_tdls_link_status(priv, tp->peermac);
+               if (mwifiex_is_tdls_link_setup(status)) {
+                       spin_lock_irqsave(&priv->sta_list_spinlock, flags);
+                       sta_ptr = mwifiex_get_sta_entry(priv, tp->peermac);
+                       spin_unlock_irqrestore(&priv->sta_list_spinlock, flags);
+
+                       if (sta_ptr && sta_ptr->tx_pause != tp->tx_pause) {
+                               sta_ptr->tx_pause = tp->tx_pause;
+                               mwifiex_update_ralist_tx_pause(priv,
+                                                              tp->peermac,
+                                                              tp->tx_pause);
+                       }
+               }
+       }
+}
+
+void mwifiex_process_multi_chan_event(struct mwifiex_private *priv,
+                                     struct sk_buff *event_skb)
+{
+       struct mwifiex_ie_types_multi_chan_info *chan_info;
+       struct mwifiex_ie_types_mc_group_info *grp_info;
+       struct mwifiex_adapter *adapter = priv->adapter;
+       struct mwifiex_ie_types_header *tlv;
+       u16 tlv_buf_left, tlv_type, tlv_len;
+       int intf_num, bss_type, bss_num, i;
+       struct mwifiex_private *intf_priv;
+
+       tlv_buf_left = event_skb->len - sizeof(u32);
+       chan_info = (void *)event_skb->data + sizeof(u32);
+
+       if (le16_to_cpu(chan_info->header.type) != TLV_TYPE_MULTI_CHAN_INFO ||
+           tlv_buf_left < sizeof(struct mwifiex_ie_types_multi_chan_info)) {
+               mwifiex_dbg(adapter, ERROR,
+                           "unknown TLV in chan_info event\n");
+               return;
+       }
+
+       adapter->usb_mc_status = le16_to_cpu(chan_info->status);
+       mwifiex_dbg(adapter, EVENT, "multi chan operation %s\n",
+                   adapter->usb_mc_status ? "started" : "over");
+
+       tlv_buf_left -= sizeof(struct mwifiex_ie_types_multi_chan_info);
+       tlv = (struct mwifiex_ie_types_header *)chan_info->tlv_buffer;
+
+       while (tlv_buf_left >= (int)sizeof(struct mwifiex_ie_types_header)) {
+               tlv_type = le16_to_cpu(tlv->type);
+               tlv_len  = le16_to_cpu(tlv->len);
+               if ((sizeof(struct mwifiex_ie_types_header) + tlv_len) >
+                   tlv_buf_left) {
+                       mwifiex_dbg(adapter, ERROR, "wrong tlv: tlvLen=%d,\t"
+                                   "tlvBufLeft=%d\n", tlv_len, tlv_buf_left);
+                       break;
+               }
+               if (tlv_type != TLV_TYPE_MC_GROUP_INFO) {
+                       mwifiex_dbg(adapter, ERROR, "wrong tlv type: 0x%x\n",
+                                   tlv_type);
+                       break;
+               }
+
+               grp_info = (struct mwifiex_ie_types_mc_group_info *)tlv;
+               intf_num = grp_info->intf_num;
+               for (i = 0; i < intf_num; i++) {
+                       bss_type = grp_info->bss_type_numlist[i] >> 4;
+                       bss_num = grp_info->bss_type_numlist[i] & BSS_NUM_MASK;
+                       intf_priv = mwifiex_get_priv_by_id(adapter, bss_num,
+                                                          bss_type);
+                       if (!intf_priv) {
+                               mwifiex_dbg(adapter, ERROR,
+                                           "Invalid bss_type bss_num\t"
+                                           "in multi channel event\n");
+                               continue;
+                       }
+                       if (adapter->iface_type == MWIFIEX_USB) {
+                               u8 ep;
+
+                               ep = grp_info->hid_num.usb_ep_num;
+                               if (ep == MWIFIEX_USB_EP_DATA ||
+                                   ep == MWIFIEX_USB_EP_DATA_CH2)
+                                       intf_priv->usb_port = ep;
+                       }
+               }
+
+               tlv_buf_left -= sizeof(struct mwifiex_ie_types_header) +
+                               tlv_len;
+               tlv = (void *)((u8 *)tlv + tlv_len +
+                              sizeof(struct mwifiex_ie_types_header));
+       }
+
+       if (adapter->iface_type == MWIFIEX_USB) {
+               adapter->tx_lock_flag = true;
+               adapter->usb_mc_setup = true;
+               mwifiex_multi_chan_resync(adapter);
+       }
+}
+
+void mwifiex_process_tx_pause_event(struct mwifiex_private *priv,
+                                   struct sk_buff *event_skb)
+{
+       struct mwifiex_ie_types_header *tlv;
+       u16 tlv_type, tlv_len;
+       int tlv_buf_left;
+
+       if (!priv->media_connected) {
+               mwifiex_dbg(priv->adapter, ERROR,
+                           "tx_pause event while disconnected; bss_role=%d\n",
+                           priv->bss_role);
+               return;
+       }
+
+       tlv_buf_left = event_skb->len - sizeof(u32);
+       tlv = (void *)event_skb->data + sizeof(u32);
+
+       while (tlv_buf_left >= (int)sizeof(struct mwifiex_ie_types_header)) {
+               tlv_type = le16_to_cpu(tlv->type);
+               tlv_len  = le16_to_cpu(tlv->len);
+               if ((sizeof(struct mwifiex_ie_types_header) + tlv_len) >
+                   tlv_buf_left) {
+                       mwifiex_dbg(priv->adapter, ERROR,
+                                   "wrong tlv: tlvLen=%d, tlvBufLeft=%d\n",
+                                   tlv_len, tlv_buf_left);
+                       break;
+               }
+               if (tlv_type == TLV_TYPE_TX_PAUSE) {
+                       if (GET_BSS_ROLE(priv) == MWIFIEX_BSS_ROLE_STA)
+                               mwifiex_process_sta_tx_pause(priv, tlv);
+                       else
+                               mwifiex_process_uap_tx_pause(priv, tlv);
+               }
+
+               tlv_buf_left -= sizeof(struct mwifiex_ie_types_header) +
+                               tlv_len;
+               tlv = (void *)((u8 *)tlv + tlv_len +
+                              sizeof(struct mwifiex_ie_types_header));
+       }
+
+}
+
+/*
+* This function handles coex events generated by firmware
+*/
+void mwifiex_bt_coex_wlan_param_update_event(struct mwifiex_private *priv,
+                                            struct sk_buff *event_skb)
+{
+       struct mwifiex_adapter *adapter = priv->adapter;
+       struct mwifiex_ie_types_header *tlv;
+       struct mwifiex_ie_types_btcoex_aggr_win_size *winsizetlv;
+       struct mwifiex_ie_types_btcoex_scan_time *scantlv;
+       s32 len = event_skb->len - sizeof(u32);
+       u8 *cur_ptr = event_skb->data + sizeof(u32);
+       u16 tlv_type, tlv_len;
+
+       while (len >= sizeof(struct mwifiex_ie_types_header)) {
+               tlv = (struct mwifiex_ie_types_header *)cur_ptr;
+               tlv_len = le16_to_cpu(tlv->len);
+               tlv_type = le16_to_cpu(tlv->type);
+
+               if ((tlv_len + sizeof(struct mwifiex_ie_types_header)) > len)
+                       break;
+               switch (tlv_type) {
+               case TLV_BTCOEX_WL_AGGR_WINSIZE:
+                       winsizetlv =
+                           (struct mwifiex_ie_types_btcoex_aggr_win_size *)tlv;
+                       adapter->coex_win_size = winsizetlv->coex_win_size;
+                       adapter->coex_tx_win_size =
+                               winsizetlv->tx_win_size;
+                       adapter->coex_rx_win_size =
+                               winsizetlv->rx_win_size;
+                       mwifiex_coex_ampdu_rxwinsize(adapter);
+                       mwifiex_update_ampdu_txwinsize(adapter);
+                       break;
+
+               case TLV_BTCOEX_WL_SCANTIME:
+                       scantlv =
+                           (struct mwifiex_ie_types_btcoex_scan_time *)tlv;
+                       adapter->coex_scan = scantlv->coex_scan;
+                       adapter->coex_min_scan_time = scantlv->min_scan_time;
+                       adapter->coex_max_scan_time = scantlv->max_scan_time;
+                       break;
+
+               default:
+                       break;
+               }
+
+               len -= tlv_len + sizeof(struct mwifiex_ie_types_header);
+               cur_ptr += tlv_len +
+                       sizeof(struct mwifiex_ie_types_header);
+       }
+
+       dev_dbg(adapter->dev, "coex_scan=%d min_scan=%d coex_win=%d, tx_win=%d rx_win=%d\n",
+               adapter->coex_scan, adapter->coex_min_scan_time,
+               adapter->coex_win_size, adapter->coex_tx_win_size,
+               adapter->coex_rx_win_size);
+}
+
+/*
+ * This function handles events generated by firmware.
+ *
+ * This is a generic function and handles all events.
+ *
+ * Event specific routines are called by this function based
+ * upon the generated event cause.
+ *
+ * For the following events, the function just forwards them to upper
+ * layers, optionally recording the change -
+ *      - EVENT_LINK_SENSED
+ *      - EVENT_MIC_ERR_UNICAST
+ *      - EVENT_MIC_ERR_MULTICAST
+ *      - EVENT_PORT_RELEASE
+ *      - EVENT_RSSI_LOW
+ *      - EVENT_SNR_LOW
+ *      - EVENT_MAX_FAIL
+ *      - EVENT_RSSI_HIGH
+ *      - EVENT_SNR_HIGH
+ *      - EVENT_DATA_RSSI_LOW
+ *      - EVENT_DATA_SNR_LOW
+ *      - EVENT_DATA_RSSI_HIGH
+ *      - EVENT_DATA_SNR_HIGH
+ *      - EVENT_LINK_QUALITY
+ *      - EVENT_PRE_BEACON_LOST
+ *      - EVENT_IBSS_COALESCED
+ *      - EVENT_WEP_ICV_ERR
+ *      - EVENT_BW_CHANGE
+ *      - EVENT_HOSTWAKE_STAIE
+  *
+ * For the following events, no action is taken -
+ *      - EVENT_MIB_CHANGED
+ *      - EVENT_INIT_DONE
+ *      - EVENT_DUMMY_HOST_WAKEUP_SIGNAL
+ *
+ * Rest of the supported events requires driver handling -
+ *      - EVENT_DEAUTHENTICATED
+ *      - EVENT_DISASSOCIATED
+ *      - EVENT_LINK_LOST
+ *      - EVENT_PS_SLEEP
+ *      - EVENT_PS_AWAKE
+ *      - EVENT_DEEP_SLEEP_AWAKE
+ *      - EVENT_HS_ACT_REQ
+ *      - EVENT_ADHOC_BCN_LOST
+ *      - EVENT_BG_SCAN_REPORT
+ *      - EVENT_WMM_STATUS_CHANGE
+ *      - EVENT_ADDBA
+ *      - EVENT_DELBA
+ *      - EVENT_BA_STREAM_TIEMOUT
+ *      - EVENT_AMSDU_AGGR_CTRL
+ */
+int mwifiex_process_sta_event(struct mwifiex_private *priv)
+{
+       struct mwifiex_adapter *adapter = priv->adapter;
+       int ret = 0;
+       u32 eventcause = adapter->event_cause;
+       u16 ctrl, reason_code;
+
+       switch (eventcause) {
+       case EVENT_DUMMY_HOST_WAKEUP_SIGNAL:
+               mwifiex_dbg(adapter, ERROR,
+                           "invalid EVENT: DUMMY_HOST_WAKEUP_SIGNAL, ignore it\n");
+               break;
+       case EVENT_LINK_SENSED:
+               mwifiex_dbg(adapter, EVENT, "event: LINK_SENSED\n");
+               if (!netif_carrier_ok(priv->netdev))
+                       netif_carrier_on(priv->netdev);
+               mwifiex_wake_up_net_dev_queue(priv->netdev, adapter);
+               break;
+
+       case EVENT_DEAUTHENTICATED:
+               mwifiex_dbg(adapter, EVENT, "event: Deauthenticated\n");
+               if (priv->wps.session_enable) {
+                       mwifiex_dbg(adapter, INFO,
+                                   "info: receive deauth event in wps session\n");
+                       break;
+               }
+               adapter->dbg.num_event_deauth++;
+               if (priv->media_connected) {
+                       reason_code =
+                               le16_to_cpu(*(__le16 *)adapter->event_body);
+                       mwifiex_reset_connect_state(priv, reason_code);
+               }
+               break;
+
+       case EVENT_DISASSOCIATED:
+               mwifiex_dbg(adapter, EVENT, "event: Disassociated\n");
+               if (priv->wps.session_enable) {
+                       mwifiex_dbg(adapter, INFO,
+                                   "info: receive disassoc event in wps session\n");
+                       break;
+               }
+               adapter->dbg.num_event_disassoc++;
+               if (priv->media_connected) {
+                       reason_code =
+                               le16_to_cpu(*(__le16 *)adapter->event_body);
+                       mwifiex_reset_connect_state(priv, reason_code);
+               }
+               break;
+
+       case EVENT_LINK_LOST:
+               mwifiex_dbg(adapter, EVENT, "event: Link lost\n");
+               adapter->dbg.num_event_link_lost++;
+               if (priv->media_connected) {
+                       reason_code =
+                               le16_to_cpu(*(__le16 *)adapter->event_body);
+                       mwifiex_reset_connect_state(priv, reason_code);
+               }
+               break;
+
+       case EVENT_PS_SLEEP:
+               mwifiex_dbg(adapter, EVENT, "info: EVENT: SLEEP\n");
+
+               adapter->ps_state = PS_STATE_PRE_SLEEP;
+
+               mwifiex_check_ps_cond(adapter);
+               break;
+
+       case EVENT_PS_AWAKE:
+               mwifiex_dbg(adapter, EVENT, "info: EVENT: AWAKE\n");
+               if (!adapter->pps_uapsd_mode && priv->port_open &&
+                   priv->media_connected && adapter->sleep_period.period) {
+                               adapter->pps_uapsd_mode = true;
+                               mwifiex_dbg(adapter, EVENT,
+                                           "event: PPS/UAPSD mode activated\n");
+               }
+               adapter->tx_lock_flag = false;
+               if (adapter->pps_uapsd_mode && adapter->gen_null_pkt) {
+                       if (mwifiex_check_last_packet_indication(priv)) {
+                               if (adapter->data_sent ||
+                                   (adapter->if_ops.is_port_ready &&
+                                    !adapter->if_ops.is_port_ready(priv))) {
+                                       adapter->ps_state = PS_STATE_AWAKE;
+                                       adapter->pm_wakeup_card_req = false;
+                                       adapter->pm_wakeup_fw_try = false;
+                                       del_timer(&adapter->wakeup_timer);
+                                       break;
+                               }
+                               if (!mwifiex_send_null_packet
+                                       (priv,
+                                        MWIFIEX_TxPD_POWER_MGMT_NULL_PACKET |
+                                        MWIFIEX_TxPD_POWER_MGMT_LAST_PACKET))
+                                               adapter->ps_state =
+                                                       PS_STATE_SLEEP;
+                                       return 0;
+                       }
+               }
+               adapter->ps_state = PS_STATE_AWAKE;
+               adapter->pm_wakeup_card_req = false;
+               adapter->pm_wakeup_fw_try = false;
+               del_timer(&adapter->wakeup_timer);
+
+               break;
+
+       case EVENT_DEEP_SLEEP_AWAKE:
+               adapter->if_ops.wakeup_complete(adapter);
+               mwifiex_dbg(adapter, EVENT, "event: DS_AWAKE\n");
+               if (adapter->is_deep_sleep)
+                       adapter->is_deep_sleep = false;
+               break;
+
+       case EVENT_HS_ACT_REQ:
+               mwifiex_dbg(adapter, EVENT, "event: HS_ACT_REQ\n");
+               ret = mwifiex_send_cmd(priv, HostCmd_CMD_802_11_HS_CFG_ENH,
+                                      0, 0, NULL, false);
+               break;
+
+       case EVENT_MIC_ERR_UNICAST:
+               mwifiex_dbg(adapter, EVENT, "event: UNICAST MIC ERROR\n");
+               cfg80211_michael_mic_failure(priv->netdev, priv->cfg_bssid,
+                                            NL80211_KEYTYPE_PAIRWISE,
+                                            -1, NULL, GFP_KERNEL);
+               break;
+
+       case EVENT_MIC_ERR_MULTICAST:
+               mwifiex_dbg(adapter, EVENT, "event: MULTICAST MIC ERROR\n");
+               cfg80211_michael_mic_failure(priv->netdev, priv->cfg_bssid,
+                                            NL80211_KEYTYPE_GROUP,
+                                            -1, NULL, GFP_KERNEL);
+               break;
+       case EVENT_MIB_CHANGED:
+       case EVENT_INIT_DONE:
+               break;
+
+       case EVENT_ADHOC_BCN_LOST:
+               mwifiex_dbg(adapter, EVENT, "event: ADHOC_BCN_LOST\n");
+               priv->adhoc_is_link_sensed = false;
+               mwifiex_clean_txrx(priv);
+               mwifiex_stop_net_dev_queue(priv->netdev, adapter);
+               if (netif_carrier_ok(priv->netdev))
+                       netif_carrier_off(priv->netdev);
+               break;
+
+       case EVENT_BG_SCAN_REPORT:
+               mwifiex_dbg(adapter, EVENT, "event: BGS_REPORT\n");
+               ret = mwifiex_send_cmd(priv, HostCmd_CMD_802_11_BG_SCAN_QUERY,
+                                      HostCmd_ACT_GEN_GET, 0, NULL, false);
+               break;
+
+       case EVENT_PORT_RELEASE:
+               mwifiex_dbg(adapter, EVENT, "event: PORT RELEASE\n");
+               priv->port_open = true;
+               break;
+
+       case EVENT_EXT_SCAN_REPORT:
+               mwifiex_dbg(adapter, EVENT, "event: EXT_SCAN Report\n");
+               if (adapter->ext_scan)
+                       ret = mwifiex_handle_event_ext_scan_report(priv,
+                                               adapter->event_skb->data);
+
+               break;
+
+       case EVENT_WMM_STATUS_CHANGE:
+               mwifiex_dbg(adapter, EVENT, "event: WMM status changed\n");
+               ret = mwifiex_send_cmd(priv, HostCmd_CMD_WMM_GET_STATUS,
+                                      0, 0, NULL, false);
+               break;
+
+       case EVENT_RSSI_LOW:
+               cfg80211_cqm_rssi_notify(priv->netdev,
+                                        NL80211_CQM_RSSI_THRESHOLD_EVENT_LOW,
+                                        GFP_KERNEL);
+               mwifiex_send_cmd(priv, HostCmd_CMD_RSSI_INFO,
+                                HostCmd_ACT_GEN_GET, 0, NULL, false);
+               priv->subsc_evt_rssi_state = RSSI_LOW_RECVD;
+               mwifiex_dbg(adapter, EVENT, "event: Beacon RSSI_LOW\n");
+               break;
+       case EVENT_SNR_LOW:
+               mwifiex_dbg(adapter, EVENT, "event: Beacon SNR_LOW\n");
+               break;
+       case EVENT_MAX_FAIL:
+               mwifiex_dbg(adapter, EVENT, "event: MAX_FAIL\n");
+               break;
+       case EVENT_RSSI_HIGH:
+               cfg80211_cqm_rssi_notify(priv->netdev,
+                                        NL80211_CQM_RSSI_THRESHOLD_EVENT_HIGH,
+                                        GFP_KERNEL);
+               mwifiex_send_cmd(priv, HostCmd_CMD_RSSI_INFO,
+                                HostCmd_ACT_GEN_GET, 0, NULL, false);
+               priv->subsc_evt_rssi_state = RSSI_HIGH_RECVD;
+               mwifiex_dbg(adapter, EVENT, "event: Beacon RSSI_HIGH\n");
+               break;
+       case EVENT_SNR_HIGH:
+               mwifiex_dbg(adapter, EVENT, "event: Beacon SNR_HIGH\n");
+               break;
+       case EVENT_DATA_RSSI_LOW:
+               mwifiex_dbg(adapter, EVENT, "event: Data RSSI_LOW\n");
+               break;
+       case EVENT_DATA_SNR_LOW:
+               mwifiex_dbg(adapter, EVENT, "event: Data SNR_LOW\n");
+               break;
+       case EVENT_DATA_RSSI_HIGH:
+               mwifiex_dbg(adapter, EVENT, "event: Data RSSI_HIGH\n");
+               break;
+       case EVENT_DATA_SNR_HIGH:
+               mwifiex_dbg(adapter, EVENT, "event: Data SNR_HIGH\n");
+               break;
+       case EVENT_LINK_QUALITY:
+               mwifiex_dbg(adapter, EVENT, "event: Link Quality\n");
+               break;
+       case EVENT_PRE_BEACON_LOST:
+               mwifiex_dbg(adapter, EVENT, "event: Pre-Beacon Lost\n");
+               break;
+       case EVENT_IBSS_COALESCED:
+               mwifiex_dbg(adapter, EVENT, "event: IBSS_COALESCED\n");
+               ret = mwifiex_send_cmd(priv,
+                               HostCmd_CMD_802_11_IBSS_COALESCING_STATUS,
+                               HostCmd_ACT_GEN_GET, 0, NULL, false);
+               break;
+       case EVENT_ADDBA:
+               mwifiex_dbg(adapter, EVENT, "event: ADDBA Request\n");
+               mwifiex_send_cmd(priv, HostCmd_CMD_11N_ADDBA_RSP,
+                                HostCmd_ACT_GEN_SET, 0,
+                                adapter->event_body, false);
+               break;
+       case EVENT_DELBA:
+               mwifiex_dbg(adapter, EVENT, "event: DELBA Request\n");
+               mwifiex_11n_delete_ba_stream(priv, adapter->event_body);
+               break;
+       case EVENT_BA_STREAM_TIEMOUT:
+               mwifiex_dbg(adapter, EVENT, "event:  BA Stream timeout\n");
+               mwifiex_11n_ba_stream_timeout(priv,
+                                             (struct host_cmd_ds_11n_batimeout
+                                              *)
+                                             adapter->event_body);
+               break;
+       case EVENT_AMSDU_AGGR_CTRL:
+               ctrl = le16_to_cpu(*(__le16 *)adapter->event_body);
+               mwifiex_dbg(adapter, EVENT,
+                           "event: AMSDU_AGGR_CTRL %d\n", ctrl);
+
+               adapter->tx_buf_size =
+                               min_t(u16, adapter->curr_tx_buf_size, ctrl);
+               mwifiex_dbg(adapter, EVENT, "event: tx_buf_size %d\n",
+                           adapter->tx_buf_size);
+               break;
+
+       case EVENT_WEP_ICV_ERR:
+               mwifiex_dbg(adapter, EVENT, "event: WEP ICV error\n");
+               break;
+
+       case EVENT_BW_CHANGE:
+               mwifiex_dbg(adapter, EVENT, "event: BW Change\n");
+               break;
+
+       case EVENT_HOSTWAKE_STAIE:
+               mwifiex_dbg(adapter, EVENT,
+                           "event: HOSTWAKE_STAIE %d\n", eventcause);
+               break;
+
+       case EVENT_REMAIN_ON_CHAN_EXPIRED:
+               mwifiex_dbg(adapter, EVENT,
+                           "event: Remain on channel expired\n");
+               cfg80211_remain_on_channel_expired(&priv->wdev,
+                                                  priv->roc_cfg.cookie,
+                                                  &priv->roc_cfg.chan,
+                                                  GFP_ATOMIC);
+
+               memset(&priv->roc_cfg, 0x00, sizeof(struct mwifiex_roc_cfg));
+
+               break;
+
+       case EVENT_CHANNEL_SWITCH_ANN:
+               mwifiex_dbg(adapter, EVENT, "event: Channel Switch Announcement\n");
+               priv->csa_expire_time =
+                               jiffies + msecs_to_jiffies(DFS_CHAN_MOVE_TIME);
+               priv->csa_chan = priv->curr_bss_params.bss_descriptor.channel;
+               ret = mwifiex_send_cmd(priv, HostCmd_CMD_802_11_DEAUTHENTICATE,
+                       HostCmd_ACT_GEN_SET, 0,
+                       priv->curr_bss_params.bss_descriptor.mac_address,
+                       false);
+               break;
+
+       case EVENT_TDLS_GENERIC_EVENT:
+               ret = mwifiex_parse_tdls_event(priv, adapter->event_skb);
+               break;
+
+       case EVENT_TX_DATA_PAUSE:
+               mwifiex_dbg(adapter, EVENT, "event: TX DATA PAUSE\n");
+               mwifiex_process_tx_pause_event(priv, adapter->event_skb);
+               break;
+
+       case EVENT_MULTI_CHAN_INFO:
+               mwifiex_dbg(adapter, EVENT, "event: multi-chan info\n");
+               mwifiex_process_multi_chan_event(priv, adapter->event_skb);
+               break;
+
+       case EVENT_TX_STATUS_REPORT:
+               mwifiex_dbg(adapter, EVENT, "event: TX_STATUS Report\n");
+               mwifiex_parse_tx_status_event(priv, adapter->event_body);
+               break;
+
+       case EVENT_CHANNEL_REPORT_RDY:
+               mwifiex_dbg(adapter, EVENT, "event: Channel Report\n");
+               ret = mwifiex_11h_handle_chanrpt_ready(priv,
+                                                      adapter->event_skb);
+               break;
+       case EVENT_RADAR_DETECTED:
+               mwifiex_dbg(adapter, EVENT, "event: Radar detected\n");
+               ret = mwifiex_11h_handle_radar_detected(priv,
+                                                       adapter->event_skb);
+               break;
+       case EVENT_BT_COEX_WLAN_PARA_CHANGE:
+               dev_dbg(adapter->dev, "EVENT: BT coex wlan param update\n");
+               mwifiex_bt_coex_wlan_param_update_event(priv,
+                                                       adapter->event_skb);
+               break;
+       default:
+               mwifiex_dbg(adapter, ERROR, "event: unknown event id: %#x\n",
+                           eventcause);
+               break;
+       }
+
+       return ret;
+}
diff --git a/drivers/net/wireless/marvell/mwifiex/sta_ioctl.c b/drivers/net/wireless/marvell/mwifiex/sta_ioctl.c
new file mode 100644 (file)
index 0000000..a6c8a4f
--- /dev/null
@@ -0,0 +1,1421 @@
+/*
+ * Marvell Wireless LAN device driver: functions for station ioctl
+ *
+ * Copyright (C) 2011-2014, Marvell International Ltd.
+ *
+ * This software file (the "File") is distributed by Marvell International
+ * Ltd. under the terms of the GNU General Public License Version 2, June 1991
+ * (the "License").  You may use, redistribute and/or modify this File in
+ * accordance with the terms and conditions of the License, a copy of which
+ * is available by writing to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the
+ * worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
+ *
+ * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
+ * ARE EXPRESSLY DISCLAIMED.  The License provides additional details about
+ * this warranty disclaimer.
+ */
+
+#include "decl.h"
+#include "ioctl.h"
+#include "util.h"
+#include "fw.h"
+#include "main.h"
+#include "wmm.h"
+#include "11n.h"
+#include "cfg80211.h"
+
+static int disconnect_on_suspend;
+module_param(disconnect_on_suspend, int, 0644);
+
+/*
+ * Copies the multicast address list from device to driver.
+ *
+ * This function does not validate the destination memory for
+ * size, and the calling function must ensure enough memory is
+ * available.
+ */
+int mwifiex_copy_mcast_addr(struct mwifiex_multicast_list *mlist,
+                           struct net_device *dev)
+{
+       int i = 0;
+       struct netdev_hw_addr *ha;
+
+       netdev_for_each_mc_addr(ha, dev)
+               memcpy(&mlist->mac_list[i++], ha->addr, ETH_ALEN);
+
+       return i;
+}
+
+/*
+ * Wait queue completion handler.
+ *
+ * This function waits on a cmd wait queue. It also cancels the pending
+ * request after waking up, in case of errors.
+ */
+int mwifiex_wait_queue_complete(struct mwifiex_adapter *adapter,
+                               struct cmd_ctrl_node *cmd_queued)
+{
+       int status;
+
+       /* Wait for completion */
+       status = wait_event_interruptible_timeout(adapter->cmd_wait_q.wait,
+                                                 *(cmd_queued->condition),
+                                                 (12 * HZ));
+       if (status <= 0) {
+               if (status == 0)
+                       status = -ETIMEDOUT;
+               mwifiex_dbg(adapter, ERROR, "cmd_wait_q terminated: %d\n",
+                           status);
+               mwifiex_cancel_all_pending_cmd(adapter);
+               return status;
+       }
+
+       status = adapter->cmd_wait_q.status;
+       adapter->cmd_wait_q.status = 0;
+
+       return status;
+}
+
+/*
+ * This function prepares the correct firmware command and
+ * issues it to set the multicast list.
+ *
+ * This function can be used to enable promiscuous mode, or enable all
+ * multicast packets, or to enable selective multicast.
+ */
+int mwifiex_request_set_multicast_list(struct mwifiex_private *priv,
+                               struct mwifiex_multicast_list *mcast_list)
+{
+       int ret = 0;
+       u16 old_pkt_filter;
+
+       old_pkt_filter = priv->curr_pkt_filter;
+
+       if (mcast_list->mode == MWIFIEX_PROMISC_MODE) {
+               mwifiex_dbg(priv->adapter, INFO,
+                           "info: Enable Promiscuous mode\n");
+               priv->curr_pkt_filter |= HostCmd_ACT_MAC_PROMISCUOUS_ENABLE;
+               priv->curr_pkt_filter &=
+                       ~HostCmd_ACT_MAC_ALL_MULTICAST_ENABLE;
+       } else {
+               /* Multicast */
+               priv->curr_pkt_filter &= ~HostCmd_ACT_MAC_PROMISCUOUS_ENABLE;
+               if (mcast_list->mode == MWIFIEX_ALL_MULTI_MODE) {
+                       mwifiex_dbg(priv->adapter, INFO,
+                                   "info: Enabling All Multicast!\n");
+                       priv->curr_pkt_filter |=
+                               HostCmd_ACT_MAC_ALL_MULTICAST_ENABLE;
+               } else {
+                       priv->curr_pkt_filter &=
+                               ~HostCmd_ACT_MAC_ALL_MULTICAST_ENABLE;
+                       mwifiex_dbg(priv->adapter, INFO,
+                                   "info: Set multicast list=%d\n",
+                                   mcast_list->num_multicast_addr);
+                       /* Send multicast addresses to firmware */
+                       ret = mwifiex_send_cmd(priv,
+                                              HostCmd_CMD_MAC_MULTICAST_ADR,
+                                              HostCmd_ACT_GEN_SET, 0,
+                                              mcast_list, false);
+               }
+       }
+       mwifiex_dbg(priv->adapter, INFO,
+                   "info: old_pkt_filter=%#x, curr_pkt_filter=%#x\n",
+                   old_pkt_filter, priv->curr_pkt_filter);
+       if (old_pkt_filter != priv->curr_pkt_filter) {
+               ret = mwifiex_send_cmd(priv, HostCmd_CMD_MAC_CONTROL,
+                                      HostCmd_ACT_GEN_SET,
+                                      0, &priv->curr_pkt_filter, false);
+       }
+
+       return ret;
+}
+
+/*
+ * This function fills bss descriptor structure using provided
+ * information.
+ * beacon_ie buffer is allocated in this function. It is caller's
+ * responsibility to free the memory.
+ */
+int mwifiex_fill_new_bss_desc(struct mwifiex_private *priv,
+                             struct cfg80211_bss *bss,
+                             struct mwifiex_bssdescriptor *bss_desc)
+{
+       u8 *beacon_ie;
+       size_t beacon_ie_len;
+       struct mwifiex_bss_priv *bss_priv = (void *)bss->priv;
+       const struct cfg80211_bss_ies *ies;
+
+       rcu_read_lock();
+       ies = rcu_dereference(bss->ies);
+       beacon_ie = kmemdup(ies->data, ies->len, GFP_ATOMIC);
+       beacon_ie_len = ies->len;
+       bss_desc->timestamp = ies->tsf;
+       rcu_read_unlock();
+
+       if (!beacon_ie) {
+               mwifiex_dbg(priv->adapter, ERROR,
+                           " failed to alloc beacon_ie\n");
+               return -ENOMEM;
+       }
+
+       memcpy(bss_desc->mac_address, bss->bssid, ETH_ALEN);
+       bss_desc->rssi = bss->signal;
+       /* The caller of this function will free beacon_ie */
+       bss_desc->beacon_buf = beacon_ie;
+       bss_desc->beacon_buf_size = beacon_ie_len;
+       bss_desc->beacon_period = bss->beacon_interval;
+       bss_desc->cap_info_bitmap = bss->capability;
+       bss_desc->bss_band = bss_priv->band;
+       bss_desc->fw_tsf = bss_priv->fw_tsf;
+       if (bss_desc->cap_info_bitmap & WLAN_CAPABILITY_PRIVACY) {
+               mwifiex_dbg(priv->adapter, INFO,
+                           "info: InterpretIE: AP WEP enabled\n");
+               bss_desc->privacy = MWIFIEX_802_11_PRIV_FILTER_8021X_WEP;
+       } else {
+               bss_desc->privacy = MWIFIEX_802_11_PRIV_FILTER_ACCEPT_ALL;
+       }
+       if (bss_desc->cap_info_bitmap & WLAN_CAPABILITY_IBSS)
+               bss_desc->bss_mode = NL80211_IFTYPE_ADHOC;
+       else
+               bss_desc->bss_mode = NL80211_IFTYPE_STATION;
+
+       /* Disable 11ac by default. Enable it only where there
+        * exist VHT_CAP IE in AP beacon
+        */
+       bss_desc->disable_11ac = true;
+
+       if (bss_desc->cap_info_bitmap & WLAN_CAPABILITY_SPECTRUM_MGMT)
+               bss_desc->sensed_11h = true;
+
+       return mwifiex_update_bss_desc_with_ie(priv->adapter, bss_desc);
+}
+
+void mwifiex_dnld_txpwr_table(struct mwifiex_private *priv)
+{
+       if (priv->adapter->dt_node) {
+               char txpwr[] = {"marvell,00_txpwrlimit"};
+
+               memcpy(&txpwr[8], priv->adapter->country_code, 2);
+               mwifiex_dnld_dt_cfgdata(priv, priv->adapter->dt_node, txpwr);
+       }
+}
+
+static int mwifiex_process_country_ie(struct mwifiex_private *priv,
+                                     struct cfg80211_bss *bss)
+{
+       const u8 *country_ie;
+       u8 country_ie_len;
+       struct mwifiex_802_11d_domain_reg *domain_info =
+                                       &priv->adapter->domain_reg;
+
+       rcu_read_lock();
+       country_ie = ieee80211_bss_get_ie(bss, WLAN_EID_COUNTRY);
+       if (!country_ie) {
+               rcu_read_unlock();
+               return 0;
+       }
+
+       country_ie_len = country_ie[1];
+       if (country_ie_len < IEEE80211_COUNTRY_IE_MIN_LEN) {
+               rcu_read_unlock();
+               return 0;
+       }
+
+       if (!strncmp(priv->adapter->country_code, &country_ie[2], 2)) {
+               rcu_read_unlock();
+               mwifiex_dbg(priv->adapter, INFO,
+                           "11D: skip setting domain info in FW\n");
+               return 0;
+       }
+       memcpy(priv->adapter->country_code, &country_ie[2], 2);
+
+       domain_info->country_code[0] = country_ie[2];
+       domain_info->country_code[1] = country_ie[3];
+       domain_info->country_code[2] = ' ';
+
+       country_ie_len -= IEEE80211_COUNTRY_STRING_LEN;
+
+       domain_info->no_of_triplet =
+               country_ie_len / sizeof(struct ieee80211_country_ie_triplet);
+
+       memcpy((u8 *)domain_info->triplet,
+              &country_ie[2] + IEEE80211_COUNTRY_STRING_LEN, country_ie_len);
+
+       rcu_read_unlock();
+
+       if (mwifiex_send_cmd(priv, HostCmd_CMD_802_11D_DOMAIN_INFO,
+                            HostCmd_ACT_GEN_SET, 0, NULL, false)) {
+               mwifiex_dbg(priv->adapter, ERROR,
+                           "11D: setting domain info in FW fail\n");
+               return -1;
+       }
+
+       mwifiex_dnld_txpwr_table(priv);
+
+       return 0;
+}
+
+/*
+ * In Ad-Hoc mode, the IBSS is created if not found in scan list.
+ * In both Ad-Hoc and infra mode, an deauthentication is performed
+ * first.
+ */
+int mwifiex_bss_start(struct mwifiex_private *priv, struct cfg80211_bss *bss,
+                     struct cfg80211_ssid *req_ssid)
+{
+       int ret;
+       struct mwifiex_adapter *adapter = priv->adapter;
+       struct mwifiex_bssdescriptor *bss_desc = NULL;
+
+       priv->scan_block = false;
+
+       if (bss) {
+               mwifiex_process_country_ie(priv, bss);
+
+               /* Allocate and fill new bss descriptor */
+               bss_desc = kzalloc(sizeof(struct mwifiex_bssdescriptor),
+                                  GFP_KERNEL);
+               if (!bss_desc)
+                       return -ENOMEM;
+
+               ret = mwifiex_fill_new_bss_desc(priv, bss, bss_desc);
+               if (ret)
+                       goto done;
+       }
+
+       if (priv->bss_mode == NL80211_IFTYPE_STATION ||
+           priv->bss_mode == NL80211_IFTYPE_P2P_CLIENT) {
+               u8 config_bands;
+
+               if (!bss_desc)
+                       return -1;
+
+               if (mwifiex_band_to_radio_type(bss_desc->bss_band) ==
+                                               HostCmd_SCAN_RADIO_TYPE_BG) {
+                       config_bands = BAND_B | BAND_G | BAND_GN;
+               } else {
+                       config_bands = BAND_A | BAND_AN;
+                       if (adapter->fw_bands & BAND_AAC)
+                               config_bands |= BAND_AAC;
+               }
+
+               if (!((config_bands | adapter->fw_bands) & ~adapter->fw_bands))
+                       adapter->config_bands = config_bands;
+
+               ret = mwifiex_check_network_compatibility(priv, bss_desc);
+               if (ret)
+                       goto done;
+
+               if (mwifiex_11h_get_csa_closed_channel(priv) ==
+                                                       (u8)bss_desc->channel) {
+                       mwifiex_dbg(adapter, ERROR,
+                                   "Attempt to reconnect on csa closed chan(%d)\n",
+                                   bss_desc->channel);
+                       goto done;
+               }
+
+               mwifiex_dbg(adapter, INFO,
+                           "info: SSID found in scan list ...\t"
+                           "associating...\n");
+
+               mwifiex_stop_net_dev_queue(priv->netdev, adapter);
+               if (netif_carrier_ok(priv->netdev))
+                       netif_carrier_off(priv->netdev);
+
+               /* Clear any past association response stored for
+                * application retrieval */
+               priv->assoc_rsp_size = 0;
+               ret = mwifiex_associate(priv, bss_desc);
+
+               /* If auth type is auto and association fails using open mode,
+                * try to connect using shared mode */
+               if (ret == WLAN_STATUS_NOT_SUPPORTED_AUTH_ALG &&
+                   priv->sec_info.is_authtype_auto &&
+                   priv->sec_info.wep_enabled) {
+                       priv->sec_info.authentication_mode =
+                                               NL80211_AUTHTYPE_SHARED_KEY;
+                       ret = mwifiex_associate(priv, bss_desc);
+               }
+
+               if (bss)
+                       cfg80211_put_bss(priv->adapter->wiphy, bss);
+       } else {
+               /* Adhoc mode */
+               /* If the requested SSID matches current SSID, return */
+               if (bss_desc && bss_desc->ssid.ssid_len &&
+                   (!mwifiex_ssid_cmp(&priv->curr_bss_params.bss_descriptor.
+                                      ssid, &bss_desc->ssid))) {
+                       ret = 0;
+                       goto done;
+               }
+
+               priv->adhoc_is_link_sensed = false;
+
+               ret = mwifiex_check_network_compatibility(priv, bss_desc);
+
+               mwifiex_stop_net_dev_queue(priv->netdev, adapter);
+               if (netif_carrier_ok(priv->netdev))
+                       netif_carrier_off(priv->netdev);
+
+               if (!ret) {
+                       mwifiex_dbg(adapter, INFO,
+                                   "info: network found in scan\t"
+                                   " list. Joining...\n");
+                       ret = mwifiex_adhoc_join(priv, bss_desc);
+                       if (bss)
+                               cfg80211_put_bss(priv->adapter->wiphy, bss);
+               } else {
+                       mwifiex_dbg(adapter, INFO,
+                                   "info: Network not found in\t"
+                                   "the list, creating adhoc with ssid = %s\n",
+                                   req_ssid->ssid);
+                       ret = mwifiex_adhoc_start(priv, req_ssid);
+               }
+       }
+
+done:
+       /* beacon_ie buffer was allocated in function
+        * mwifiex_fill_new_bss_desc(). Free it now.
+        */
+       if (bss_desc)
+               kfree(bss_desc->beacon_buf);
+       kfree(bss_desc);
+       return ret;
+}
+
+/*
+ * IOCTL request handler to set host sleep configuration.
+ *
+ * This function prepares the correct firmware command and
+ * issues it.
+ */
+int mwifiex_set_hs_params(struct mwifiex_private *priv, u16 action,
+                         int cmd_type, struct mwifiex_ds_hs_cfg *hs_cfg)
+
+{
+       struct mwifiex_adapter *adapter = priv->adapter;
+       int status = 0;
+       u32 prev_cond = 0;
+
+       if (!hs_cfg)
+               return -ENOMEM;
+
+       switch (action) {
+       case HostCmd_ACT_GEN_SET:
+               if (adapter->pps_uapsd_mode) {
+                       mwifiex_dbg(adapter, INFO,
+                                   "info: Host Sleep IOCTL\t"
+                                   "is blocked in UAPSD/PPS mode\n");
+                       status = -1;
+                       break;
+               }
+               if (hs_cfg->is_invoke_hostcmd) {
+                       if (hs_cfg->conditions == HS_CFG_CANCEL) {
+                               if (!adapter->is_hs_configured)
+                                       /* Already cancelled */
+                                       break;
+                               /* Save previous condition */
+                               prev_cond = le32_to_cpu(adapter->hs_cfg
+                                                       .conditions);
+                               adapter->hs_cfg.conditions =
+                                               cpu_to_le32(hs_cfg->conditions);
+                       } else if (hs_cfg->conditions) {
+                               adapter->hs_cfg.conditions =
+                                               cpu_to_le32(hs_cfg->conditions);
+                               adapter->hs_cfg.gpio = (u8)hs_cfg->gpio;
+                               if (hs_cfg->gap)
+                                       adapter->hs_cfg.gap = (u8)hs_cfg->gap;
+                       } else if (adapter->hs_cfg.conditions ==
+                                  cpu_to_le32(HS_CFG_CANCEL)) {
+                               /* Return failure if no parameters for HS
+                                  enable */
+                               status = -1;
+                               break;
+                       }
+
+                       status = mwifiex_send_cmd(priv,
+                                                 HostCmd_CMD_802_11_HS_CFG_ENH,
+                                                 HostCmd_ACT_GEN_SET, 0,
+                                                 &adapter->hs_cfg,
+                                                 cmd_type == MWIFIEX_SYNC_CMD);
+
+                       if (hs_cfg->conditions == HS_CFG_CANCEL)
+                               /* Restore previous condition */
+                               adapter->hs_cfg.conditions =
+                                               cpu_to_le32(prev_cond);
+               } else {
+                       adapter->hs_cfg.conditions =
+                                               cpu_to_le32(hs_cfg->conditions);
+                       adapter->hs_cfg.gpio = (u8)hs_cfg->gpio;
+                       adapter->hs_cfg.gap = (u8)hs_cfg->gap;
+               }
+               break;
+       case HostCmd_ACT_GEN_GET:
+               hs_cfg->conditions = le32_to_cpu(adapter->hs_cfg.conditions);
+               hs_cfg->gpio = adapter->hs_cfg.gpio;
+               hs_cfg->gap = adapter->hs_cfg.gap;
+               break;
+       default:
+               status = -1;
+               break;
+       }
+
+       return status;
+}
+
+/*
+ * Sends IOCTL request to cancel the existing Host Sleep configuration.
+ *
+ * This function allocates the IOCTL request buffer, fills it
+ * with requisite parameters and calls the IOCTL handler.
+ */
+int mwifiex_cancel_hs(struct mwifiex_private *priv, int cmd_type)
+{
+       struct mwifiex_ds_hs_cfg hscfg;
+
+       hscfg.conditions = HS_CFG_CANCEL;
+       hscfg.is_invoke_hostcmd = true;
+
+       return mwifiex_set_hs_params(priv, HostCmd_ACT_GEN_SET,
+                                   cmd_type, &hscfg);
+}
+EXPORT_SYMBOL_GPL(mwifiex_cancel_hs);
+
+/*
+ * Sends IOCTL request to cancel the existing Host Sleep configuration.
+ *
+ * This function allocates the IOCTL request buffer, fills it
+ * with requisite parameters and calls the IOCTL handler.
+ */
+int mwifiex_enable_hs(struct mwifiex_adapter *adapter)
+{
+       struct mwifiex_ds_hs_cfg hscfg;
+       struct mwifiex_private *priv;
+       int i;
+
+       if (disconnect_on_suspend) {
+               for (i = 0; i < adapter->priv_num; i++) {
+                       priv = adapter->priv[i];
+                       if (priv)
+                               mwifiex_deauthenticate(priv, NULL);
+               }
+       }
+
+       if (adapter->hs_activated) {
+               mwifiex_dbg(adapter, CMD,
+                           "cmd: HS Already activated\n");
+               return true;
+       }
+
+       adapter->hs_activate_wait_q_woken = false;
+
+       memset(&hscfg, 0, sizeof(struct mwifiex_ds_hs_cfg));
+       hscfg.is_invoke_hostcmd = true;
+
+       adapter->hs_enabling = true;
+       mwifiex_cancel_all_pending_cmd(adapter);
+
+       if (mwifiex_set_hs_params(mwifiex_get_priv(adapter,
+                                                  MWIFIEX_BSS_ROLE_STA),
+                                 HostCmd_ACT_GEN_SET, MWIFIEX_SYNC_CMD,
+                                 &hscfg)) {
+               mwifiex_dbg(adapter, ERROR,
+                           "IOCTL request HS enable failed\n");
+               return false;
+       }
+
+       if (wait_event_interruptible_timeout(adapter->hs_activate_wait_q,
+                                            adapter->hs_activate_wait_q_woken,
+                                            (10 * HZ)) <= 0) {
+               mwifiex_dbg(adapter, ERROR,
+                           "hs_activate_wait_q terminated\n");
+               return false;
+       }
+
+       return true;
+}
+EXPORT_SYMBOL_GPL(mwifiex_enable_hs);
+
+/*
+ * IOCTL request handler to get BSS information.
+ *
+ * This function collates the information from different driver structures
+ * to send to the user.
+ */
+int mwifiex_get_bss_info(struct mwifiex_private *priv,
+                        struct mwifiex_bss_info *info)
+{
+       struct mwifiex_adapter *adapter = priv->adapter;
+       struct mwifiex_bssdescriptor *bss_desc;
+
+       if (!info)
+               return -1;
+
+       bss_desc = &priv->curr_bss_params.bss_descriptor;
+
+       info->bss_mode = priv->bss_mode;
+
+       memcpy(&info->ssid, &bss_desc->ssid, sizeof(struct cfg80211_ssid));
+
+       memcpy(&info->bssid, &bss_desc->mac_address, ETH_ALEN);
+
+       info->bss_chan = bss_desc->channel;
+
+       memcpy(info->country_code, adapter->country_code,
+              IEEE80211_COUNTRY_STRING_LEN);
+
+       info->media_connected = priv->media_connected;
+
+       info->max_power_level = priv->max_tx_power_level;
+       info->min_power_level = priv->min_tx_power_level;
+
+       info->adhoc_state = priv->adhoc_state;
+
+       info->bcn_nf_last = priv->bcn_nf_last;
+
+       if (priv->sec_info.wep_enabled)
+               info->wep_status = true;
+       else
+               info->wep_status = false;
+
+       info->is_hs_configured = adapter->is_hs_configured;
+       info->is_deep_sleep = adapter->is_deep_sleep;
+
+       return 0;
+}
+
+/*
+ * The function disables auto deep sleep mode.
+ */
+int mwifiex_disable_auto_ds(struct mwifiex_private *priv)
+{
+       struct mwifiex_ds_auto_ds auto_ds;
+
+       auto_ds.auto_ds = DEEP_SLEEP_OFF;
+
+       return mwifiex_send_cmd(priv, HostCmd_CMD_802_11_PS_MODE_ENH,
+                               DIS_AUTO_PS, BITMAP_AUTO_DS, &auto_ds, true);
+}
+EXPORT_SYMBOL_GPL(mwifiex_disable_auto_ds);
+
+/*
+ * Sends IOCTL request to get the data rate.
+ *
+ * This function allocates the IOCTL request buffer, fills it
+ * with requisite parameters and calls the IOCTL handler.
+ */
+int mwifiex_drv_get_data_rate(struct mwifiex_private *priv, u32 *rate)
+{
+       int ret;
+
+       ret = mwifiex_send_cmd(priv, HostCmd_CMD_802_11_TX_RATE_QUERY,
+                              HostCmd_ACT_GEN_GET, 0, NULL, true);
+
+       if (!ret) {
+               if (priv->is_data_rate_auto)
+                       *rate = mwifiex_index_to_data_rate(priv, priv->tx_rate,
+                                                          priv->tx_htinfo);
+               else
+                       *rate = priv->data_rate;
+       }
+
+       return ret;
+}
+
+/*
+ * IOCTL request handler to set tx power configuration.
+ *
+ * This function prepares the correct firmware command and
+ * issues it.
+ *
+ * For non-auto power mode, all the following power groups are set -
+ *      - Modulation class HR/DSSS
+ *      - Modulation class OFDM
+ *      - Modulation class HTBW20
+ *      - Modulation class HTBW40
+ */
+int mwifiex_set_tx_power(struct mwifiex_private *priv,
+                        struct mwifiex_power_cfg *power_cfg)
+{
+       int ret;
+       struct host_cmd_ds_txpwr_cfg *txp_cfg;
+       struct mwifiex_types_power_group *pg_tlv;
+       struct mwifiex_power_group *pg;
+       u8 *buf;
+       u16 dbm = 0;
+
+       if (!power_cfg->is_power_auto) {
+               dbm = (u16) power_cfg->power_level;
+               if ((dbm < priv->min_tx_power_level) ||
+                   (dbm > priv->max_tx_power_level)) {
+                       mwifiex_dbg(priv->adapter, ERROR,
+                                   "txpower value %d dBm\t"
+                                   "is out of range (%d dBm-%d dBm)\n",
+                                   dbm, priv->min_tx_power_level,
+                                   priv->max_tx_power_level);
+                       return -1;
+               }
+       }
+       buf = kzalloc(MWIFIEX_SIZE_OF_CMD_BUFFER, GFP_KERNEL);
+       if (!buf)
+               return -ENOMEM;
+
+       txp_cfg = (struct host_cmd_ds_txpwr_cfg *) buf;
+       txp_cfg->action = cpu_to_le16(HostCmd_ACT_GEN_SET);
+       if (!power_cfg->is_power_auto) {
+               txp_cfg->mode = cpu_to_le32(1);
+               pg_tlv = (struct mwifiex_types_power_group *)
+                        (buf + sizeof(struct host_cmd_ds_txpwr_cfg));
+               pg_tlv->type = cpu_to_le16(TLV_TYPE_POWER_GROUP);
+               pg_tlv->length =
+                       cpu_to_le16(4 * sizeof(struct mwifiex_power_group));
+               pg = (struct mwifiex_power_group *)
+                    (buf + sizeof(struct host_cmd_ds_txpwr_cfg)
+                     + sizeof(struct mwifiex_types_power_group));
+               /* Power group for modulation class HR/DSSS */
+               pg->first_rate_code = 0x00;
+               pg->last_rate_code = 0x03;
+               pg->modulation_class = MOD_CLASS_HR_DSSS;
+               pg->power_step = 0;
+               pg->power_min = (s8) dbm;
+               pg->power_max = (s8) dbm;
+               pg++;
+               /* Power group for modulation class OFDM */
+               pg->first_rate_code = 0x00;
+               pg->last_rate_code = 0x07;
+               pg->modulation_class = MOD_CLASS_OFDM;
+               pg->power_step = 0;
+               pg->power_min = (s8) dbm;
+               pg->power_max = (s8) dbm;
+               pg++;
+               /* Power group for modulation class HTBW20 */
+               pg->first_rate_code = 0x00;
+               pg->last_rate_code = 0x20;
+               pg->modulation_class = MOD_CLASS_HT;
+               pg->power_step = 0;
+               pg->power_min = (s8) dbm;
+               pg->power_max = (s8) dbm;
+               pg->ht_bandwidth = HT_BW_20;
+               pg++;
+               /* Power group for modulation class HTBW40 */
+               pg->first_rate_code = 0x00;
+               pg->last_rate_code = 0x20;
+               pg->modulation_class = MOD_CLASS_HT;
+               pg->power_step = 0;
+               pg->power_min = (s8) dbm;
+               pg->power_max = (s8) dbm;
+               pg->ht_bandwidth = HT_BW_40;
+       }
+       ret = mwifiex_send_cmd(priv, HostCmd_CMD_TXPWR_CFG,
+                              HostCmd_ACT_GEN_SET, 0, buf, true);
+
+       kfree(buf);
+       return ret;
+}
+
+/*
+ * IOCTL request handler to get power save mode.
+ *
+ * This function prepares the correct firmware command and
+ * issues it.
+ */
+int mwifiex_drv_set_power(struct mwifiex_private *priv, u32 *ps_mode)
+{
+       int ret;
+       struct mwifiex_adapter *adapter = priv->adapter;
+       u16 sub_cmd;
+
+       if (*ps_mode)
+               adapter->ps_mode = MWIFIEX_802_11_POWER_MODE_PSP;
+       else
+               adapter->ps_mode = MWIFIEX_802_11_POWER_MODE_CAM;
+       sub_cmd = (*ps_mode) ? EN_AUTO_PS : DIS_AUTO_PS;
+       ret = mwifiex_send_cmd(priv, HostCmd_CMD_802_11_PS_MODE_ENH,
+                              sub_cmd, BITMAP_STA_PS, NULL, true);
+       if ((!ret) && (sub_cmd == DIS_AUTO_PS))
+               ret = mwifiex_send_cmd(priv, HostCmd_CMD_802_11_PS_MODE_ENH,
+                                      GET_PS, 0, NULL, false);
+
+       return ret;
+}
+
+/*
+ * IOCTL request handler to set/reset WPA IE.
+ *
+ * The supplied WPA IE is treated as a opaque buffer. Only the first field
+ * is checked to determine WPA version. If buffer length is zero, the existing
+ * WPA IE is reset.
+ */
+static int mwifiex_set_wpa_ie_helper(struct mwifiex_private *priv,
+                                    u8 *ie_data_ptr, u16 ie_len)
+{
+       if (ie_len) {
+               if (ie_len > sizeof(priv->wpa_ie)) {
+                       mwifiex_dbg(priv->adapter, ERROR,
+                                   "failed to copy WPA IE, too big\n");
+                       return -1;
+               }
+               memcpy(priv->wpa_ie, ie_data_ptr, ie_len);
+               priv->wpa_ie_len = (u8) ie_len;
+               mwifiex_dbg(priv->adapter, CMD,
+                           "cmd: Set Wpa_ie_len=%d IE=%#x\n",
+                           priv->wpa_ie_len, priv->wpa_ie[0]);
+
+               if (priv->wpa_ie[0] == WLAN_EID_VENDOR_SPECIFIC) {
+                       priv->sec_info.wpa_enabled = true;
+               } else if (priv->wpa_ie[0] == WLAN_EID_RSN) {
+                       priv->sec_info.wpa2_enabled = true;
+               } else {
+                       priv->sec_info.wpa_enabled = false;
+                       priv->sec_info.wpa2_enabled = false;
+               }
+       } else {
+               memset(priv->wpa_ie, 0, sizeof(priv->wpa_ie));
+               priv->wpa_ie_len = 0;
+               mwifiex_dbg(priv->adapter, INFO,
+                           "info: reset wpa_ie_len=%d IE=%#x\n",
+                           priv->wpa_ie_len, priv->wpa_ie[0]);
+               priv->sec_info.wpa_enabled = false;
+               priv->sec_info.wpa2_enabled = false;
+       }
+
+       return 0;
+}
+
+/*
+ * IOCTL request handler to set/reset WAPI IE.
+ *
+ * The supplied WAPI IE is treated as a opaque buffer. Only the first field
+ * is checked to internally enable WAPI. If buffer length is zero, the existing
+ * WAPI IE is reset.
+ */
+static int mwifiex_set_wapi_ie(struct mwifiex_private *priv,
+                              u8 *ie_data_ptr, u16 ie_len)
+{
+       if (ie_len) {
+               if (ie_len > sizeof(priv->wapi_ie)) {
+                       mwifiex_dbg(priv->adapter, ERROR,
+                                   "info: failed to copy WAPI IE, too big\n");
+                       return -1;
+               }
+               memcpy(priv->wapi_ie, ie_data_ptr, ie_len);
+               priv->wapi_ie_len = ie_len;
+               mwifiex_dbg(priv->adapter, CMD,
+                           "cmd: Set wapi_ie_len=%d IE=%#x\n",
+                           priv->wapi_ie_len, priv->wapi_ie[0]);
+
+               if (priv->wapi_ie[0] == WLAN_EID_BSS_AC_ACCESS_DELAY)
+                       priv->sec_info.wapi_enabled = true;
+       } else {
+               memset(priv->wapi_ie, 0, sizeof(priv->wapi_ie));
+               priv->wapi_ie_len = ie_len;
+               mwifiex_dbg(priv->adapter, INFO,
+                           "info: Reset wapi_ie_len=%d IE=%#x\n",
+                           priv->wapi_ie_len, priv->wapi_ie[0]);
+               priv->sec_info.wapi_enabled = false;
+       }
+       return 0;
+}
+
+/*
+ * IOCTL request handler to set/reset WPS IE.
+ *
+ * The supplied WPS IE is treated as a opaque buffer. Only the first field
+ * is checked to internally enable WPS. If buffer length is zero, the existing
+ * WPS IE is reset.
+ */
+static int mwifiex_set_wps_ie(struct mwifiex_private *priv,
+                              u8 *ie_data_ptr, u16 ie_len)
+{
+       if (ie_len) {
+               if (ie_len > MWIFIEX_MAX_VSIE_LEN) {
+                       mwifiex_dbg(priv->adapter, ERROR,
+                                   "info: failed to copy WPS IE, too big\n");
+                       return -1;
+               }
+
+               priv->wps_ie = kzalloc(MWIFIEX_MAX_VSIE_LEN, GFP_KERNEL);
+               if (!priv->wps_ie)
+                       return -ENOMEM;
+
+               memcpy(priv->wps_ie, ie_data_ptr, ie_len);
+               priv->wps_ie_len = ie_len;
+               mwifiex_dbg(priv->adapter, CMD,
+                           "cmd: Set wps_ie_len=%d IE=%#x\n",
+                           priv->wps_ie_len, priv->wps_ie[0]);
+       } else {
+               kfree(priv->wps_ie);
+               priv->wps_ie_len = ie_len;
+               mwifiex_dbg(priv->adapter, INFO,
+                           "info: Reset wps_ie_len=%d\n", priv->wps_ie_len);
+       }
+       return 0;
+}
+
+/*
+ * IOCTL request handler to set WAPI key.
+ *
+ * This function prepares the correct firmware command and
+ * issues it.
+ */
+static int mwifiex_sec_ioctl_set_wapi_key(struct mwifiex_private *priv,
+                              struct mwifiex_ds_encrypt_key *encrypt_key)
+{
+
+       return mwifiex_send_cmd(priv, HostCmd_CMD_802_11_KEY_MATERIAL,
+                               HostCmd_ACT_GEN_SET, KEY_INFO_ENABLED,
+                               encrypt_key, true);
+}
+
+/*
+ * IOCTL request handler to set WEP network key.
+ *
+ * This function prepares the correct firmware command and
+ * issues it, after validation checks.
+ */
+static int mwifiex_sec_ioctl_set_wep_key(struct mwifiex_private *priv,
+                             struct mwifiex_ds_encrypt_key *encrypt_key)
+{
+       struct mwifiex_adapter *adapter = priv->adapter;
+       int ret;
+       struct mwifiex_wep_key *wep_key;
+       int index;
+
+       if (priv->wep_key_curr_index >= NUM_WEP_KEYS)
+               priv->wep_key_curr_index = 0;
+       wep_key = &priv->wep_key[priv->wep_key_curr_index];
+       index = encrypt_key->key_index;
+       if (encrypt_key->key_disable) {
+               priv->sec_info.wep_enabled = 0;
+       } else if (!encrypt_key->key_len) {
+               /* Copy the required key as the current key */
+               wep_key = &priv->wep_key[index];
+               if (!wep_key->key_length) {
+                       mwifiex_dbg(adapter, ERROR,
+                                   "key not set, so cannot enable it\n");
+                       return -1;
+               }
+
+               if (adapter->key_api_major_ver == KEY_API_VER_MAJOR_V2) {
+                       memcpy(encrypt_key->key_material,
+                              wep_key->key_material, wep_key->key_length);
+                       encrypt_key->key_len = wep_key->key_length;
+               }
+
+               priv->wep_key_curr_index = (u16) index;
+               priv->sec_info.wep_enabled = 1;
+       } else {
+               wep_key = &priv->wep_key[index];
+               memset(wep_key, 0, sizeof(struct mwifiex_wep_key));
+               /* Copy the key in the driver */
+               memcpy(wep_key->key_material,
+                      encrypt_key->key_material,
+                      encrypt_key->key_len);
+               wep_key->key_index = index;
+               wep_key->key_length = encrypt_key->key_len;
+               priv->sec_info.wep_enabled = 1;
+       }
+       if (wep_key->key_length) {
+               void *enc_key;
+
+               if (encrypt_key->key_disable) {
+                       memset(&priv->wep_key[index], 0,
+                              sizeof(struct mwifiex_wep_key));
+                       if (wep_key->key_length)
+                               goto done;
+                       }
+
+               if (adapter->key_api_major_ver == KEY_API_VER_MAJOR_V2)
+                       enc_key = encrypt_key;
+               else
+                       enc_key = NULL;
+
+               /* Send request to firmware */
+               ret = mwifiex_send_cmd(priv, HostCmd_CMD_802_11_KEY_MATERIAL,
+                                      HostCmd_ACT_GEN_SET, 0, enc_key, false);
+               if (ret)
+                       return ret;
+       }
+
+done:
+       if (priv->sec_info.wep_enabled)
+               priv->curr_pkt_filter |= HostCmd_ACT_MAC_WEP_ENABLE;
+       else
+               priv->curr_pkt_filter &= ~HostCmd_ACT_MAC_WEP_ENABLE;
+
+       ret = mwifiex_send_cmd(priv, HostCmd_CMD_MAC_CONTROL,
+                              HostCmd_ACT_GEN_SET, 0,
+                              &priv->curr_pkt_filter, true);
+
+       return ret;
+}
+
+/*
+ * IOCTL request handler to set WPA key.
+ *
+ * This function prepares the correct firmware command and
+ * issues it, after validation checks.
+ *
+ * Current driver only supports key length of up to 32 bytes.
+ *
+ * This function can also be used to disable a currently set key.
+ */
+static int mwifiex_sec_ioctl_set_wpa_key(struct mwifiex_private *priv,
+                             struct mwifiex_ds_encrypt_key *encrypt_key)
+{
+       int ret;
+       u8 remove_key = false;
+       struct host_cmd_ds_802_11_key_material *ibss_key;
+
+       /* Current driver only supports key length of up to 32 bytes */
+       if (encrypt_key->key_len > WLAN_MAX_KEY_LEN) {
+               mwifiex_dbg(priv->adapter, ERROR,
+                           "key length too long\n");
+               return -1;
+       }
+
+       if (priv->bss_mode == NL80211_IFTYPE_ADHOC) {
+               /*
+                * IBSS/WPA-None uses only one key (Group) for both receiving
+                * and sending unicast and multicast packets.
+                */
+               /* Send the key as PTK to firmware */
+               encrypt_key->key_index = MWIFIEX_KEY_INDEX_UNICAST;
+               ret = mwifiex_send_cmd(priv, HostCmd_CMD_802_11_KEY_MATERIAL,
+                                      HostCmd_ACT_GEN_SET,
+                                      KEY_INFO_ENABLED, encrypt_key, false);
+               if (ret)
+                       return ret;
+
+               ibss_key = &priv->aes_key;
+               memset(ibss_key, 0,
+                      sizeof(struct host_cmd_ds_802_11_key_material));
+               /* Copy the key in the driver */
+               memcpy(ibss_key->key_param_set.key, encrypt_key->key_material,
+                      encrypt_key->key_len);
+               memcpy(&ibss_key->key_param_set.key_len, &encrypt_key->key_len,
+                      sizeof(ibss_key->key_param_set.key_len));
+               ibss_key->key_param_set.key_type_id
+                       = cpu_to_le16(KEY_TYPE_ID_TKIP);
+               ibss_key->key_param_set.key_info = cpu_to_le16(KEY_ENABLED);
+
+               /* Send the key as GTK to firmware */
+               encrypt_key->key_index = ~MWIFIEX_KEY_INDEX_UNICAST;
+       }
+
+       if (!encrypt_key->key_index)
+               encrypt_key->key_index = MWIFIEX_KEY_INDEX_UNICAST;
+
+       if (remove_key)
+               ret = mwifiex_send_cmd(priv, HostCmd_CMD_802_11_KEY_MATERIAL,
+                                      HostCmd_ACT_GEN_SET,
+                                      !KEY_INFO_ENABLED, encrypt_key, true);
+       else
+               ret = mwifiex_send_cmd(priv, HostCmd_CMD_802_11_KEY_MATERIAL,
+                                      HostCmd_ACT_GEN_SET,
+                                      KEY_INFO_ENABLED, encrypt_key, true);
+
+       return ret;
+}
+
+/*
+ * IOCTL request handler to set/get network keys.
+ *
+ * This is a generic key handling function which supports WEP, WPA
+ * and WAPI.
+ */
+static int
+mwifiex_sec_ioctl_encrypt_key(struct mwifiex_private *priv,
+                             struct mwifiex_ds_encrypt_key *encrypt_key)
+{
+       int status;
+
+       if (encrypt_key->is_wapi_key)
+               status = mwifiex_sec_ioctl_set_wapi_key(priv, encrypt_key);
+       else if (encrypt_key->key_len > WLAN_KEY_LEN_WEP104)
+               status = mwifiex_sec_ioctl_set_wpa_key(priv, encrypt_key);
+       else
+               status = mwifiex_sec_ioctl_set_wep_key(priv, encrypt_key);
+       return status;
+}
+
+/*
+ * This function returns the driver version.
+ */
+int
+mwifiex_drv_get_driver_version(struct mwifiex_adapter *adapter, char *version,
+                              int max_len)
+{
+       union {
+               __le32 l;
+               u8 c[4];
+       } ver;
+       char fw_ver[32];
+
+       ver.l = cpu_to_le32(adapter->fw_release_number);
+       sprintf(fw_ver, "%u.%u.%u.p%u", ver.c[2], ver.c[1], ver.c[0], ver.c[3]);
+
+       snprintf(version, max_len, driver_version, fw_ver);
+
+       mwifiex_dbg(adapter, MSG, "info: MWIFIEX VERSION: %s\n", version);
+
+       return 0;
+}
+
+/*
+ * Sends IOCTL request to set encoding parameters.
+ *
+ * This function allocates the IOCTL request buffer, fills it
+ * with requisite parameters and calls the IOCTL handler.
+ */
+int mwifiex_set_encode(struct mwifiex_private *priv, struct key_params *kp,
+                      const u8 *key, int key_len, u8 key_index,
+                      const u8 *mac_addr, int disable)
+{
+       struct mwifiex_ds_encrypt_key encrypt_key;
+
+       memset(&encrypt_key, 0, sizeof(struct mwifiex_ds_encrypt_key));
+       encrypt_key.key_len = key_len;
+       encrypt_key.key_index = key_index;
+
+       if (kp && kp->cipher == WLAN_CIPHER_SUITE_AES_CMAC)
+               encrypt_key.is_igtk_key = true;
+
+       if (!disable) {
+               if (key_len)
+                       memcpy(encrypt_key.key_material, key, key_len);
+               else
+                       encrypt_key.is_current_wep_key = true;
+
+               if (mac_addr)
+                       memcpy(encrypt_key.mac_addr, mac_addr, ETH_ALEN);
+               if (kp && kp->seq && kp->seq_len) {
+                       memcpy(encrypt_key.pn, kp->seq, kp->seq_len);
+                       encrypt_key.pn_len = kp->seq_len;
+                       encrypt_key.is_rx_seq_valid = true;
+               }
+       } else {
+               if (GET_BSS_ROLE(priv) == MWIFIEX_BSS_ROLE_UAP)
+                       return 0;
+               encrypt_key.key_disable = true;
+               if (mac_addr)
+                       memcpy(encrypt_key.mac_addr, mac_addr, ETH_ALEN);
+       }
+
+       return mwifiex_sec_ioctl_encrypt_key(priv, &encrypt_key);
+}
+
+/*
+ * Sends IOCTL request to get extended version.
+ *
+ * This function allocates the IOCTL request buffer, fills it
+ * with requisite parameters and calls the IOCTL handler.
+ */
+int
+mwifiex_get_ver_ext(struct mwifiex_private *priv)
+{
+       struct mwifiex_ver_ext ver_ext;
+
+       memset(&ver_ext, 0, sizeof(struct host_cmd_ds_version_ext));
+       if (mwifiex_send_cmd(priv, HostCmd_CMD_VERSION_EXT,
+                            HostCmd_ACT_GEN_GET, 0, &ver_ext, true))
+               return -1;
+
+       return 0;
+}
+
+int
+mwifiex_remain_on_chan_cfg(struct mwifiex_private *priv, u16 action,
+                          struct ieee80211_channel *chan,
+                          unsigned int duration)
+{
+       struct host_cmd_ds_remain_on_chan roc_cfg;
+       u8 sc;
+
+       memset(&roc_cfg, 0, sizeof(roc_cfg));
+       roc_cfg.action = cpu_to_le16(action);
+       if (action == HostCmd_ACT_GEN_SET) {
+               roc_cfg.band_cfg = chan->band;
+               sc = mwifiex_chan_type_to_sec_chan_offset(NL80211_CHAN_NO_HT);
+               roc_cfg.band_cfg |= (sc << 2);
+
+               roc_cfg.channel =
+                       ieee80211_frequency_to_channel(chan->center_freq);
+               roc_cfg.duration = cpu_to_le32(duration);
+       }
+       if (mwifiex_send_cmd(priv, HostCmd_CMD_REMAIN_ON_CHAN,
+                            action, 0, &roc_cfg, true)) {
+               mwifiex_dbg(priv->adapter, ERROR,
+                           "failed to remain on channel\n");
+               return -1;
+       }
+
+       return roc_cfg.status;
+}
+
+/*
+ * Sends IOCTL request to get statistics information.
+ *
+ * This function allocates the IOCTL request buffer, fills it
+ * with requisite parameters and calls the IOCTL handler.
+ */
+int
+mwifiex_get_stats_info(struct mwifiex_private *priv,
+                      struct mwifiex_ds_get_stats *log)
+{
+       return mwifiex_send_cmd(priv, HostCmd_CMD_802_11_GET_LOG,
+                               HostCmd_ACT_GEN_GET, 0, log, true);
+}
+
+/*
+ * IOCTL request handler to read/write register.
+ *
+ * This function prepares the correct firmware command and
+ * issues it.
+ *
+ * Access to the following registers are supported -
+ *      - MAC
+ *      - BBP
+ *      - RF
+ *      - PMIC
+ *      - CAU
+ */
+static int mwifiex_reg_mem_ioctl_reg_rw(struct mwifiex_private *priv,
+                                       struct mwifiex_ds_reg_rw *reg_rw,
+                                       u16 action)
+{
+       u16 cmd_no;
+
+       switch (le32_to_cpu(reg_rw->type)) {
+       case MWIFIEX_REG_MAC:
+               cmd_no = HostCmd_CMD_MAC_REG_ACCESS;
+               break;
+       case MWIFIEX_REG_BBP:
+               cmd_no = HostCmd_CMD_BBP_REG_ACCESS;
+               break;
+       case MWIFIEX_REG_RF:
+               cmd_no = HostCmd_CMD_RF_REG_ACCESS;
+               break;
+       case MWIFIEX_REG_PMIC:
+               cmd_no = HostCmd_CMD_PMIC_REG_ACCESS;
+               break;
+       case MWIFIEX_REG_CAU:
+               cmd_no = HostCmd_CMD_CAU_REG_ACCESS;
+               break;
+       default:
+               return -1;
+       }
+
+       return mwifiex_send_cmd(priv, cmd_no, action, 0, reg_rw, true);
+}
+
+/*
+ * Sends IOCTL request to write to a register.
+ *
+ * This function allocates the IOCTL request buffer, fills it
+ * with requisite parameters and calls the IOCTL handler.
+ */
+int
+mwifiex_reg_write(struct mwifiex_private *priv, u32 reg_type,
+                 u32 reg_offset, u32 reg_value)
+{
+       struct mwifiex_ds_reg_rw reg_rw;
+
+       reg_rw.type = cpu_to_le32(reg_type);
+       reg_rw.offset = cpu_to_le32(reg_offset);
+       reg_rw.value = cpu_to_le32(reg_value);
+
+       return mwifiex_reg_mem_ioctl_reg_rw(priv, &reg_rw, HostCmd_ACT_GEN_SET);
+}
+
+/*
+ * Sends IOCTL request to read from a register.
+ *
+ * This function allocates the IOCTL request buffer, fills it
+ * with requisite parameters and calls the IOCTL handler.
+ */
+int
+mwifiex_reg_read(struct mwifiex_private *priv, u32 reg_type,
+                u32 reg_offset, u32 *value)
+{
+       int ret;
+       struct mwifiex_ds_reg_rw reg_rw;
+
+       reg_rw.type = cpu_to_le32(reg_type);
+       reg_rw.offset = cpu_to_le32(reg_offset);
+       ret = mwifiex_reg_mem_ioctl_reg_rw(priv, &reg_rw, HostCmd_ACT_GEN_GET);
+
+       if (ret)
+               goto done;
+
+       *value = le32_to_cpu(reg_rw.value);
+
+done:
+       return ret;
+}
+
+/*
+ * Sends IOCTL request to read from EEPROM.
+ *
+ * This function allocates the IOCTL request buffer, fills it
+ * with requisite parameters and calls the IOCTL handler.
+ */
+int
+mwifiex_eeprom_read(struct mwifiex_private *priv, u16 offset, u16 bytes,
+                   u8 *value)
+{
+       int ret;
+       struct mwifiex_ds_read_eeprom rd_eeprom;
+
+       rd_eeprom.offset = cpu_to_le16((u16) offset);
+       rd_eeprom.byte_count = cpu_to_le16((u16) bytes);
+
+       /* Send request to firmware */
+       ret = mwifiex_send_cmd(priv, HostCmd_CMD_802_11_EEPROM_ACCESS,
+                              HostCmd_ACT_GEN_GET, 0, &rd_eeprom, true);
+
+       if (!ret)
+               memcpy(value, rd_eeprom.value, MAX_EEPROM_DATA);
+       return ret;
+}
+
+/*
+ * This function sets a generic IE. In addition to generic IE, it can
+ * also handle WPA, WPA2 and WAPI IEs.
+ */
+static int
+mwifiex_set_gen_ie_helper(struct mwifiex_private *priv, u8 *ie_data_ptr,
+                         u16 ie_len)
+{
+       int ret = 0;
+       struct ieee_types_vendor_header *pvendor_ie;
+       const u8 wpa_oui[] = { 0x00, 0x50, 0xf2, 0x01 };
+       const u8 wps_oui[] = { 0x00, 0x50, 0xf2, 0x04 };
+
+       /* If the passed length is zero, reset the buffer */
+       if (!ie_len) {
+               priv->gen_ie_buf_len = 0;
+               priv->wps.session_enable = false;
+
+               return 0;
+       } else if (!ie_data_ptr) {
+               return -1;
+       }
+       pvendor_ie = (struct ieee_types_vendor_header *) ie_data_ptr;
+       /* Test to see if it is a WPA IE, if not, then it is a gen IE */
+       if (((pvendor_ie->element_id == WLAN_EID_VENDOR_SPECIFIC) &&
+            (!memcmp(pvendor_ie->oui, wpa_oui, sizeof(wpa_oui)))) ||
+           (pvendor_ie->element_id == WLAN_EID_RSN)) {
+
+               /* IE is a WPA/WPA2 IE so call set_wpa function */
+               ret = mwifiex_set_wpa_ie_helper(priv, ie_data_ptr, ie_len);
+               priv->wps.session_enable = false;
+
+               return ret;
+       } else if (pvendor_ie->element_id == WLAN_EID_BSS_AC_ACCESS_DELAY) {
+               /* IE is a WAPI IE so call set_wapi function */
+               ret = mwifiex_set_wapi_ie(priv, ie_data_ptr, ie_len);
+
+               return ret;
+       }
+       /*
+        * Verify that the passed length is not larger than the
+        * available space remaining in the buffer
+        */
+       if (ie_len < (sizeof(priv->gen_ie_buf) - priv->gen_ie_buf_len)) {
+
+               /* Test to see if it is a WPS IE, if so, enable
+                * wps session flag
+                */
+               pvendor_ie = (struct ieee_types_vendor_header *) ie_data_ptr;
+               if ((pvendor_ie->element_id == WLAN_EID_VENDOR_SPECIFIC) &&
+                   (!memcmp(pvendor_ie->oui, wps_oui, sizeof(wps_oui)))) {
+                       priv->wps.session_enable = true;
+                       mwifiex_dbg(priv->adapter, INFO,
+                                   "info: WPS Session Enabled.\n");
+                       ret = mwifiex_set_wps_ie(priv, ie_data_ptr, ie_len);
+               }
+
+               /* Append the passed data to the end of the
+                  genIeBuffer */
+               memcpy(priv->gen_ie_buf + priv->gen_ie_buf_len, ie_data_ptr,
+                      ie_len);
+               /* Increment the stored buffer length by the
+                  size passed */
+               priv->gen_ie_buf_len += ie_len;
+       } else {
+               /* Passed data does not fit in the remaining
+                  buffer space */
+               ret = -1;
+       }
+
+       /* Return 0, or -1 for error case */
+       return ret;
+}
+
+/*
+ * IOCTL request handler to set/get generic IE.
+ *
+ * In addition to various generic IEs, this function can also be
+ * used to set the ARP filter.
+ */
+static int mwifiex_misc_ioctl_gen_ie(struct mwifiex_private *priv,
+                                    struct mwifiex_ds_misc_gen_ie *gen_ie,
+                                    u16 action)
+{
+       struct mwifiex_adapter *adapter = priv->adapter;
+
+       switch (gen_ie->type) {
+       case MWIFIEX_IE_TYPE_GEN_IE:
+               if (action == HostCmd_ACT_GEN_GET) {
+                       gen_ie->len = priv->wpa_ie_len;
+                       memcpy(gen_ie->ie_data, priv->wpa_ie, gen_ie->len);
+               } else {
+                       mwifiex_set_gen_ie_helper(priv, gen_ie->ie_data,
+                                                 (u16) gen_ie->len);
+               }
+               break;
+       case MWIFIEX_IE_TYPE_ARP_FILTER:
+               memset(adapter->arp_filter, 0, sizeof(adapter->arp_filter));
+               if (gen_ie->len > ARP_FILTER_MAX_BUF_SIZE) {
+                       adapter->arp_filter_size = 0;
+                       mwifiex_dbg(adapter, ERROR,
+                                   "invalid ARP filter size\n");
+                       return -1;
+               } else {
+                       memcpy(adapter->arp_filter, gen_ie->ie_data,
+                              gen_ie->len);
+                       adapter->arp_filter_size = gen_ie->len;
+               }
+               break;
+       default:
+               mwifiex_dbg(adapter, ERROR, "invalid IE type\n");
+               return -1;
+       }
+       return 0;
+}
+
+/*
+ * Sends IOCTL request to set a generic IE.
+ *
+ * This function allocates the IOCTL request buffer, fills it
+ * with requisite parameters and calls the IOCTL handler.
+ */
+int
+mwifiex_set_gen_ie(struct mwifiex_private *priv, const u8 *ie, int ie_len)
+{
+       struct mwifiex_ds_misc_gen_ie gen_ie;
+
+       if (ie_len > IEEE_MAX_IE_SIZE)
+               return -EFAULT;
+
+       gen_ie.type = MWIFIEX_IE_TYPE_GEN_IE;
+       gen_ie.len = ie_len;
+       memcpy(gen_ie.ie_data, ie, ie_len);
+       if (mwifiex_misc_ioctl_gen_ie(priv, &gen_ie, HostCmd_ACT_GEN_SET))
+               return -EFAULT;
+
+       return 0;
+}
diff --git a/drivers/net/wireless/marvell/mwifiex/sta_rx.c b/drivers/net/wireless/marvell/mwifiex/sta_rx.c
new file mode 100644 (file)
index 0000000..d4d4cb1
--- /dev/null
@@ -0,0 +1,267 @@
+/*
+ * Marvell Wireless LAN device driver: station RX data handling
+ *
+ * Copyright (C) 2011-2014, Marvell International Ltd.
+ *
+ * This software file (the "File") is distributed by Marvell International
+ * Ltd. under the terms of the GNU General Public License Version 2, June 1991
+ * (the "License").  You may use, redistribute and/or modify this File in
+ * accordance with the terms and conditions of the License, a copy of which
+ * is available by writing to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the
+ * worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
+ *
+ * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
+ * ARE EXPRESSLY DISCLAIMED.  The License provides additional details about
+ * this warranty disclaimer.
+ */
+
+#include <uapi/linux/ipv6.h>
+#include <net/ndisc.h>
+#include "decl.h"
+#include "ioctl.h"
+#include "util.h"
+#include "fw.h"
+#include "main.h"
+#include "11n_aggr.h"
+#include "11n_rxreorder.h"
+
+/* This function checks if a frame is IPv4 ARP or IPv6 Neighbour advertisement
+ * frame. If frame has both source and destination mac address as same, this
+ * function drops such gratuitous frames.
+ */
+static bool
+mwifiex_discard_gratuitous_arp(struct mwifiex_private *priv,
+                              struct sk_buff *skb)
+{
+       const struct mwifiex_arp_eth_header *arp;
+       struct ethhdr *eth;
+       struct ipv6hdr *ipv6;
+       struct icmp6hdr *icmpv6;
+
+       eth = (struct ethhdr *)skb->data;
+       switch (ntohs(eth->h_proto)) {
+       case ETH_P_ARP:
+               arp = (void *)(skb->data + sizeof(struct ethhdr));
+               if (arp->hdr.ar_op == htons(ARPOP_REPLY) ||
+                   arp->hdr.ar_op == htons(ARPOP_REQUEST)) {
+                       if (!memcmp(arp->ar_sip, arp->ar_tip, 4))
+                               return true;
+               }
+               break;
+       case ETH_P_IPV6:
+               ipv6 = (void *)(skb->data + sizeof(struct ethhdr));
+               icmpv6 = (void *)(skb->data + sizeof(struct ethhdr) +
+                                 sizeof(struct ipv6hdr));
+               if (NDISC_NEIGHBOUR_ADVERTISEMENT == icmpv6->icmp6_type) {
+                       if (!memcmp(&ipv6->saddr, &ipv6->daddr,
+                                   sizeof(struct in6_addr)))
+                               return true;
+               }
+               break;
+       default:
+               break;
+       }
+
+       return false;
+}
+
+/*
+ * This function processes the received packet and forwards it
+ * to kernel/upper layer.
+ *
+ * This function parses through the received packet and determines
+ * if it is a debug packet or normal packet.
+ *
+ * For non-debug packets, the function chops off unnecessary leading
+ * header bytes, reconstructs the packet as an ethernet frame or
+ * 802.2/llc/snap frame as required, and sends it to kernel/upper layer.
+ *
+ * The completion callback is called after processing in complete.
+ */
+int mwifiex_process_rx_packet(struct mwifiex_private *priv,
+                             struct sk_buff *skb)
+{
+       int ret;
+       struct rx_packet_hdr *rx_pkt_hdr;
+       struct rxpd *local_rx_pd;
+       int hdr_chop;
+       struct ethhdr *eth;
+       u16 rx_pkt_off, rx_pkt_len;
+       u8 *offset;
+       u8 adj_rx_rate = 0;
+
+       local_rx_pd = (struct rxpd *) (skb->data);
+
+       rx_pkt_off = le16_to_cpu(local_rx_pd->rx_pkt_offset);
+       rx_pkt_len = le16_to_cpu(local_rx_pd->rx_pkt_length);
+       rx_pkt_hdr = (void *)local_rx_pd + rx_pkt_off;
+
+       if ((!memcmp(&rx_pkt_hdr->rfc1042_hdr, bridge_tunnel_header,
+                    sizeof(bridge_tunnel_header))) ||
+           (!memcmp(&rx_pkt_hdr->rfc1042_hdr, rfc1042_header,
+                    sizeof(rfc1042_header)) &&
+            ntohs(rx_pkt_hdr->rfc1042_hdr.snap_type) != ETH_P_AARP &&
+            ntohs(rx_pkt_hdr->rfc1042_hdr.snap_type) != ETH_P_IPX)) {
+               /*
+                *  Replace the 803 header and rfc1042 header (llc/snap) with an
+                *    EthernetII header, keep the src/dst and snap_type
+                *    (ethertype).
+                *  The firmware only passes up SNAP frames converting
+                *    all RX Data from 802.11 to 802.2/LLC/SNAP frames.
+                *  To create the Ethernet II, just move the src, dst address
+                *    right before the snap_type.
+                */
+               eth = (struct ethhdr *)
+                       ((u8 *) &rx_pkt_hdr->eth803_hdr
+                        + sizeof(rx_pkt_hdr->eth803_hdr) +
+                        sizeof(rx_pkt_hdr->rfc1042_hdr)
+                        - sizeof(rx_pkt_hdr->eth803_hdr.h_dest)
+                        - sizeof(rx_pkt_hdr->eth803_hdr.h_source)
+                        - sizeof(rx_pkt_hdr->rfc1042_hdr.snap_type));
+
+               memcpy(eth->h_source, rx_pkt_hdr->eth803_hdr.h_source,
+                      sizeof(eth->h_source));
+               memcpy(eth->h_dest, rx_pkt_hdr->eth803_hdr.h_dest,
+                      sizeof(eth->h_dest));
+
+               /* Chop off the rxpd + the excess memory from the 802.2/llc/snap
+                  header that was removed. */
+               hdr_chop = (u8 *) eth - (u8 *) local_rx_pd;
+       } else {
+               /* Chop off the rxpd */
+               hdr_chop = (u8 *) &rx_pkt_hdr->eth803_hdr -
+                       (u8 *) local_rx_pd;
+       }
+
+       /* Chop off the leading header bytes so the it points to the start of
+          either the reconstructed EthII frame or the 802.2/llc/snap frame */
+       skb_pull(skb, hdr_chop);
+
+       if (priv->hs2_enabled &&
+           mwifiex_discard_gratuitous_arp(priv, skb)) {
+               mwifiex_dbg(priv->adapter, INFO, "Bypassed Gratuitous ARP\n");
+               dev_kfree_skb_any(skb);
+               return 0;
+       }
+
+       if (ISSUPP_TDLS_ENABLED(priv->adapter->fw_cap_info) &&
+           ntohs(rx_pkt_hdr->eth803_hdr.h_proto) == ETH_P_TDLS) {
+               offset = (u8 *)local_rx_pd + rx_pkt_off;
+               mwifiex_process_tdls_action_frame(priv, offset, rx_pkt_len);
+       }
+
+       priv->rxpd_rate = local_rx_pd->rx_rate;
+
+       priv->rxpd_htinfo = local_rx_pd->ht_info;
+
+       if (GET_BSS_ROLE(priv) == MWIFIEX_BSS_ROLE_STA ||
+           GET_BSS_ROLE(priv) == MWIFIEX_BSS_ROLE_UAP) {
+               adj_rx_rate = mwifiex_adjust_data_rate(priv, priv->rxpd_rate,
+                                                      priv->rxpd_htinfo);
+               mwifiex_hist_data_add(priv, adj_rx_rate, local_rx_pd->snr,
+                                     local_rx_pd->nf);
+       }
+
+       ret = mwifiex_recv_packet(priv, skb);
+       if (ret == -1)
+               mwifiex_dbg(priv->adapter, ERROR,
+                           "recv packet failed\n");
+
+       return ret;
+}
+
+/*
+ * This function processes the received buffer.
+ *
+ * The function looks into the RxPD and performs sanity tests on the
+ * received buffer to ensure its a valid packet, before processing it
+ * further. If the packet is determined to be aggregated, it is
+ * de-aggregated accordingly. Non-unicast packets are sent directly to
+ * the kernel/upper layers. Unicast packets are handed over to the
+ * Rx reordering routine if 11n is enabled.
+ *
+ * The completion callback is called after processing in complete.
+ */
+int mwifiex_process_sta_rx_packet(struct mwifiex_private *priv,
+                                 struct sk_buff *skb)
+{
+       struct mwifiex_adapter *adapter = priv->adapter;
+       int ret = 0;
+       struct rxpd *local_rx_pd;
+       struct rx_packet_hdr *rx_pkt_hdr;
+       u8 ta[ETH_ALEN];
+       u16 rx_pkt_type, rx_pkt_offset, rx_pkt_length, seq_num;
+       struct mwifiex_sta_node *sta_ptr;
+
+       local_rx_pd = (struct rxpd *) (skb->data);
+       rx_pkt_type = le16_to_cpu(local_rx_pd->rx_pkt_type);
+       rx_pkt_offset = le16_to_cpu(local_rx_pd->rx_pkt_offset);
+       rx_pkt_length = le16_to_cpu(local_rx_pd->rx_pkt_length);
+       seq_num = le16_to_cpu(local_rx_pd->seq_num);
+
+       rx_pkt_hdr = (void *)local_rx_pd + rx_pkt_offset;
+
+       if ((rx_pkt_offset + rx_pkt_length) > (u16) skb->len) {
+               mwifiex_dbg(adapter, ERROR,
+                           "wrong rx packet: len=%d, rx_pkt_offset=%d, rx_pkt_length=%d\n",
+                           skb->len, rx_pkt_offset, rx_pkt_length);
+               priv->stats.rx_dropped++;
+               dev_kfree_skb_any(skb);
+               return ret;
+       }
+
+       if (rx_pkt_type == PKT_TYPE_MGMT) {
+               ret = mwifiex_process_mgmt_packet(priv, skb);
+               if (ret)
+                       mwifiex_dbg(adapter, ERROR, "Rx of mgmt packet failed");
+               dev_kfree_skb_any(skb);
+               return ret;
+       }
+
+       /*
+        * If the packet is not an unicast packet then send the packet
+        * directly to os. Don't pass thru rx reordering
+        */
+       if ((!IS_11N_ENABLED(priv) &&
+            !(ISSUPP_TDLS_ENABLED(priv->adapter->fw_cap_info) &&
+              !(local_rx_pd->flags & MWIFIEX_RXPD_FLAGS_TDLS_PACKET))) ||
+           !ether_addr_equal_unaligned(priv->curr_addr, rx_pkt_hdr->eth803_hdr.h_dest)) {
+               mwifiex_process_rx_packet(priv, skb);
+               return ret;
+       }
+
+       if (mwifiex_queuing_ra_based(priv) ||
+           (ISSUPP_TDLS_ENABLED(priv->adapter->fw_cap_info) &&
+            local_rx_pd->flags & MWIFIEX_RXPD_FLAGS_TDLS_PACKET)) {
+               memcpy(ta, rx_pkt_hdr->eth803_hdr.h_source, ETH_ALEN);
+               if (local_rx_pd->flags & MWIFIEX_RXPD_FLAGS_TDLS_PACKET &&
+                   local_rx_pd->priority < MAX_NUM_TID) {
+                       sta_ptr = mwifiex_get_sta_entry(priv, ta);
+                       if (sta_ptr)
+                               sta_ptr->rx_seq[local_rx_pd->priority] =
+                                             le16_to_cpu(local_rx_pd->seq_num);
+                       mwifiex_auto_tdls_update_peer_signal(priv, ta,
+                                                            local_rx_pd->snr,
+                                                            local_rx_pd->nf);
+               }
+       } else {
+               if (rx_pkt_type != PKT_TYPE_BAR)
+                       priv->rx_seq[local_rx_pd->priority] = seq_num;
+               memcpy(ta, priv->curr_bss_params.bss_descriptor.mac_address,
+                      ETH_ALEN);
+       }
+
+       /* Reorder and send to OS */
+       ret = mwifiex_11n_rx_reorder_pkt(priv, seq_num, local_rx_pd->priority,
+                                        ta, (u8) rx_pkt_type, skb);
+
+       if (ret || (rx_pkt_type == PKT_TYPE_BAR))
+               dev_kfree_skb_any(skb);
+
+       if (ret)
+               priv->stats.rx_dropped++;
+
+       return ret;
+}
diff --git a/drivers/net/wireless/marvell/mwifiex/sta_tx.c b/drivers/net/wireless/marvell/mwifiex/sta_tx.c
new file mode 100644 (file)
index 0000000..f6683ea
--- /dev/null
@@ -0,0 +1,244 @@
+/*
+ * Marvell Wireless LAN device driver: station TX data handling
+ *
+ * Copyright (C) 2011-2014, Marvell International Ltd.
+ *
+ * This software file (the "File") is distributed by Marvell International
+ * Ltd. under the terms of the GNU General Public License Version 2, June 1991
+ * (the "License").  You may use, redistribute and/or modify this File in
+ * accordance with the terms and conditions of the License, a copy of which
+ * is available by writing to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the
+ * worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
+ *
+ * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
+ * ARE EXPRESSLY DISCLAIMED.  The License provides additional details about
+ * this warranty disclaimer.
+ */
+
+#include "decl.h"
+#include "ioctl.h"
+#include "util.h"
+#include "fw.h"
+#include "main.h"
+#include "wmm.h"
+
+/*
+ * This function fills the TxPD for tx packets.
+ *
+ * The Tx buffer received by this function should already have the
+ * header space allocated for TxPD.
+ *
+ * This function inserts the TxPD in between interface header and actual
+ * data and adjusts the buffer pointers accordingly.
+ *
+ * The following TxPD fields are set by this function, as required -
+ *      - BSS number
+ *      - Tx packet length and offset
+ *      - Priority
+ *      - Packet delay
+ *      - Priority specific Tx control
+ *      - Flags
+ */
+void *mwifiex_process_sta_txpd(struct mwifiex_private *priv,
+                               struct sk_buff *skb)
+{
+       struct mwifiex_adapter *adapter = priv->adapter;
+       struct txpd *local_tx_pd;
+       struct mwifiex_txinfo *tx_info = MWIFIEX_SKB_TXCB(skb);
+       unsigned int pad;
+       u16 pkt_type, pkt_offset;
+       int hroom = (priv->adapter->iface_type == MWIFIEX_USB) ? 0 :
+                      INTF_HEADER_LEN;
+
+       if (!skb->len) {
+               mwifiex_dbg(adapter, ERROR,
+                           "Tx: bad packet length: %d\n", skb->len);
+               tx_info->status_code = -1;
+               return skb->data;
+       }
+
+       BUG_ON(skb_headroom(skb) < MWIFIEX_MIN_DATA_HEADER_LEN);
+
+       pkt_type = mwifiex_is_skb_mgmt_frame(skb) ? PKT_TYPE_MGMT : 0;
+
+       pad = ((void *)skb->data - (sizeof(*local_tx_pd) + hroom)-
+                        NULL) & (MWIFIEX_DMA_ALIGN_SZ - 1);
+       skb_push(skb, sizeof(*local_tx_pd) + pad);
+
+       local_tx_pd = (struct txpd *) skb->data;
+       memset(local_tx_pd, 0, sizeof(struct txpd));
+       local_tx_pd->bss_num = priv->bss_num;
+       local_tx_pd->bss_type = priv->bss_type;
+       local_tx_pd->tx_pkt_length = cpu_to_le16((u16)(skb->len -
+                                                      (sizeof(struct txpd) +
+                                                       pad)));
+
+       local_tx_pd->priority = (u8) skb->priority;
+       local_tx_pd->pkt_delay_2ms =
+                               mwifiex_wmm_compute_drv_pkt_delay(priv, skb);
+
+       if (tx_info->flags & MWIFIEX_BUF_FLAG_EAPOL_TX_STATUS ||
+           tx_info->flags & MWIFIEX_BUF_FLAG_ACTION_TX_STATUS) {
+               local_tx_pd->tx_token_id = tx_info->ack_frame_id;
+               local_tx_pd->flags |= MWIFIEX_TXPD_FLAGS_REQ_TX_STATUS;
+       }
+
+       if (local_tx_pd->priority <
+           ARRAY_SIZE(priv->wmm.user_pri_pkt_tx_ctrl))
+               /*
+                * Set the priority specific tx_control field, setting of 0 will
+                *   cause the default value to be used later in this function
+                */
+               local_tx_pd->tx_control =
+                       cpu_to_le32(priv->wmm.user_pri_pkt_tx_ctrl[local_tx_pd->
+                                                                  priority]);
+
+       if (adapter->pps_uapsd_mode) {
+               if (mwifiex_check_last_packet_indication(priv)) {
+                       adapter->tx_lock_flag = true;
+                       local_tx_pd->flags =
+                               MWIFIEX_TxPD_POWER_MGMT_LAST_PACKET;
+               }
+       }
+
+       if (tx_info->flags & MWIFIEX_BUF_FLAG_TDLS_PKT)
+               local_tx_pd->flags |= MWIFIEX_TXPD_FLAGS_TDLS_PACKET;
+
+       /* Offset of actual data */
+       pkt_offset = sizeof(struct txpd) + pad;
+       if (pkt_type == PKT_TYPE_MGMT) {
+               /* Set the packet type and add header for management frame */
+               local_tx_pd->tx_pkt_type = cpu_to_le16(pkt_type);
+               pkt_offset += MWIFIEX_MGMT_FRAME_HEADER_SIZE;
+       }
+
+       local_tx_pd->tx_pkt_offset = cpu_to_le16(pkt_offset);
+
+       /* make space for INTF_HEADER_LEN */
+       skb_push(skb, hroom);
+
+       if (!local_tx_pd->tx_control)
+               /* TxCtrl set by user or default */
+               local_tx_pd->tx_control = cpu_to_le32(priv->pkt_tx_ctrl);
+
+       return skb->data;
+}
+
+/*
+ * This function tells firmware to send a NULL data packet.
+ *
+ * The function creates a NULL data packet with TxPD and sends to the
+ * firmware for transmission, with highest priority setting.
+ */
+int mwifiex_send_null_packet(struct mwifiex_private *priv, u8 flags)
+{
+       struct mwifiex_adapter *adapter = priv->adapter;
+       struct txpd *local_tx_pd;
+       struct mwifiex_tx_param tx_param;
+/* sizeof(struct txpd) + Interface specific header */
+#define NULL_PACKET_HDR 64
+       u32 data_len = NULL_PACKET_HDR;
+       struct sk_buff *skb;
+       int ret;
+       struct mwifiex_txinfo *tx_info = NULL;
+
+       if (adapter->surprise_removed)
+               return -1;
+
+       if (!priv->media_connected)
+               return -1;
+
+       if (adapter->data_sent)
+               return -1;
+
+       if (adapter->if_ops.is_port_ready &&
+           !adapter->if_ops.is_port_ready(priv))
+               return -1;
+
+       skb = dev_alloc_skb(data_len);
+       if (!skb)
+               return -1;
+
+       tx_info = MWIFIEX_SKB_TXCB(skb);
+       memset(tx_info, 0, sizeof(*tx_info));
+       tx_info->bss_num = priv->bss_num;
+       tx_info->bss_type = priv->bss_type;
+       tx_info->pkt_len = data_len - (sizeof(struct txpd) + INTF_HEADER_LEN);
+       skb_reserve(skb, sizeof(struct txpd) + INTF_HEADER_LEN);
+       skb_push(skb, sizeof(struct txpd));
+
+       local_tx_pd = (struct txpd *) skb->data;
+       local_tx_pd->tx_control = cpu_to_le32(priv->pkt_tx_ctrl);
+       local_tx_pd->flags = flags;
+       local_tx_pd->priority = WMM_HIGHEST_PRIORITY;
+       local_tx_pd->tx_pkt_offset = cpu_to_le16(sizeof(struct txpd));
+       local_tx_pd->bss_num = priv->bss_num;
+       local_tx_pd->bss_type = priv->bss_type;
+
+       if (adapter->iface_type == MWIFIEX_USB) {
+               ret = adapter->if_ops.host_to_card(adapter, priv->usb_port,
+                                                  skb, NULL);
+       } else {
+               skb_push(skb, INTF_HEADER_LEN);
+               tx_param.next_pkt_len = 0;
+               ret = adapter->if_ops.host_to_card(adapter, MWIFIEX_TYPE_DATA,
+                                                  skb, &tx_param);
+       }
+       switch (ret) {
+       case -EBUSY:
+               dev_kfree_skb_any(skb);
+               mwifiex_dbg(adapter, ERROR,
+                           "%s: host_to_card failed: ret=%d\n",
+                           __func__, ret);
+               adapter->dbg.num_tx_host_to_card_failure++;
+               break;
+       case -1:
+               dev_kfree_skb_any(skb);
+               mwifiex_dbg(adapter, ERROR,
+                           "%s: host_to_card failed: ret=%d\n",
+                           __func__, ret);
+               adapter->dbg.num_tx_host_to_card_failure++;
+               break;
+       case 0:
+               dev_kfree_skb_any(skb);
+               mwifiex_dbg(adapter, DATA,
+                           "data: %s: host_to_card succeeded\n",
+                           __func__);
+               adapter->tx_lock_flag = true;
+               break;
+       case -EINPROGRESS:
+               adapter->tx_lock_flag = true;
+               break;
+       default:
+               break;
+       }
+
+       return ret;
+}
+
+/*
+ * This function checks if we need to send last packet indication.
+ */
+u8
+mwifiex_check_last_packet_indication(struct mwifiex_private *priv)
+{
+       struct mwifiex_adapter *adapter = priv->adapter;
+       u8 ret = false;
+
+       if (!adapter->sleep_period.period)
+               return ret;
+       if (mwifiex_wmm_lists_empty(adapter))
+                       ret = true;
+
+       if (ret && !adapter->cmd_sent && !adapter->curr_cmd &&
+           !is_command_pending(adapter)) {
+               adapter->delay_null_pkt = false;
+               ret = true;
+       } else {
+               ret = false;
+               adapter->delay_null_pkt = true;
+       }
+       return ret;
+}
diff --git a/drivers/net/wireless/marvell/mwifiex/tdls.c b/drivers/net/wireless/marvell/mwifiex/tdls.c
new file mode 100644 (file)
index 0000000..9275f9c
--- /dev/null
@@ -0,0 +1,1500 @@
+/* Marvell Wireless LAN device driver: TDLS handling
+ *
+ * Copyright (C) 2014, Marvell International Ltd.
+ *
+ * This software file (the "File") is distributed by Marvell International
+ * Ltd. under the terms of the GNU General Public License Version 2, June 1991
+ * (the "License").  You may use, redistribute and/or modify this File in
+ * accordance with the terms and conditions of the License, a copy of which
+ * is available on the worldwide web at
+ * http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
+ *
+ * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
+ * ARE EXPRESSLY DISCLAIMED.  The License provides additional details about
+ * this warranty disclaimer.
+ */
+
+#include "main.h"
+#include "wmm.h"
+#include "11n.h"
+#include "11n_rxreorder.h"
+#include "11ac.h"
+
+#define TDLS_REQ_FIX_LEN      6
+#define TDLS_RESP_FIX_LEN     8
+#define TDLS_CONFIRM_FIX_LEN  6
+#define MWIFIEX_TDLS_WMM_INFO_SIZE 7
+
+static void mwifiex_restore_tdls_packets(struct mwifiex_private *priv,
+                                        const u8 *mac, u8 status)
+{
+       struct mwifiex_ra_list_tbl *ra_list;
+       struct list_head *tid_list;
+       struct sk_buff *skb, *tmp;
+       struct mwifiex_txinfo *tx_info;
+       unsigned long flags;
+       u32 tid;
+       u8 tid_down;
+
+       mwifiex_dbg(priv->adapter, DATA, "%s: %pM\n", __func__, mac);
+       spin_lock_irqsave(&priv->wmm.ra_list_spinlock, flags);
+
+       skb_queue_walk_safe(&priv->tdls_txq, skb, tmp) {
+               if (!ether_addr_equal(mac, skb->data))
+                       continue;
+
+               __skb_unlink(skb, &priv->tdls_txq);
+               tx_info = MWIFIEX_SKB_TXCB(skb);
+               tid = skb->priority;
+               tid_down = mwifiex_wmm_downgrade_tid(priv, tid);
+
+               if (mwifiex_is_tdls_link_setup(status)) {
+                       ra_list = mwifiex_wmm_get_queue_raptr(priv, tid, mac);
+                       ra_list->tdls_link = true;
+                       tx_info->flags |= MWIFIEX_BUF_FLAG_TDLS_PKT;
+               } else {
+                       tid_list = &priv->wmm.tid_tbl_ptr[tid_down].ra_list;
+                       if (!list_empty(tid_list))
+                               ra_list = list_first_entry(tid_list,
+                                             struct mwifiex_ra_list_tbl, list);
+                       else
+                               ra_list = NULL;
+                       tx_info->flags &= ~MWIFIEX_BUF_FLAG_TDLS_PKT;
+               }
+
+               if (!ra_list) {
+                       mwifiex_write_data_complete(priv->adapter, skb, 0, -1);
+                       continue;
+               }
+
+               skb_queue_tail(&ra_list->skb_head, skb);
+
+               ra_list->ba_pkt_count++;
+               ra_list->total_pkt_count++;
+
+               if (atomic_read(&priv->wmm.highest_queued_prio) <
+                                                      tos_to_tid_inv[tid_down])
+                       atomic_set(&priv->wmm.highest_queued_prio,
+                                  tos_to_tid_inv[tid_down]);
+
+               atomic_inc(&priv->wmm.tx_pkts_queued);
+       }
+
+       spin_unlock_irqrestore(&priv->wmm.ra_list_spinlock, flags);
+       return;
+}
+
+static void mwifiex_hold_tdls_packets(struct mwifiex_private *priv,
+                                     const u8 *mac)
+{
+       struct mwifiex_ra_list_tbl *ra_list;
+       struct list_head *ra_list_head;
+       struct sk_buff *skb, *tmp;
+       unsigned long flags;
+       int i;
+
+       mwifiex_dbg(priv->adapter, DATA, "%s: %pM\n", __func__, mac);
+       spin_lock_irqsave(&priv->wmm.ra_list_spinlock, flags);
+
+       for (i = 0; i < MAX_NUM_TID; i++) {
+               if (!list_empty(&priv->wmm.tid_tbl_ptr[i].ra_list)) {
+                       ra_list_head = &priv->wmm.tid_tbl_ptr[i].ra_list;
+                       list_for_each_entry(ra_list, ra_list_head, list) {
+                               skb_queue_walk_safe(&ra_list->skb_head, skb,
+                                                   tmp) {
+                                       if (!ether_addr_equal(mac, skb->data))
+                                               continue;
+                                       __skb_unlink(skb, &ra_list->skb_head);
+                                       atomic_dec(&priv->wmm.tx_pkts_queued);
+                                       ra_list->total_pkt_count--;
+                                       skb_queue_tail(&priv->tdls_txq, skb);
+                               }
+                       }
+               }
+       }
+
+       spin_unlock_irqrestore(&priv->wmm.ra_list_spinlock, flags);
+       return;
+}
+
+/* This function appends rate TLV to scan config command. */
+static int
+mwifiex_tdls_append_rates_ie(struct mwifiex_private *priv,
+                            struct sk_buff *skb)
+{
+       u8 rates[MWIFIEX_SUPPORTED_RATES], *pos;
+       u16 rates_size, supp_rates_size, ext_rates_size;
+
+       memset(rates, 0, sizeof(rates));
+       rates_size = mwifiex_get_supported_rates(priv, rates);
+
+       supp_rates_size = min_t(u16, rates_size, MWIFIEX_TDLS_SUPPORTED_RATES);
+
+       if (skb_tailroom(skb) < rates_size + 4) {
+               mwifiex_dbg(priv->adapter, ERROR,
+                           "Insuffient space while adding rates\n");
+               return -ENOMEM;
+       }
+
+       pos = skb_put(skb, supp_rates_size + 2);
+       *pos++ = WLAN_EID_SUPP_RATES;
+       *pos++ = supp_rates_size;
+       memcpy(pos, rates, supp_rates_size);
+
+       if (rates_size > MWIFIEX_TDLS_SUPPORTED_RATES) {
+               ext_rates_size = rates_size - MWIFIEX_TDLS_SUPPORTED_RATES;
+               pos = skb_put(skb, ext_rates_size + 2);
+               *pos++ = WLAN_EID_EXT_SUPP_RATES;
+               *pos++ = ext_rates_size;
+               memcpy(pos, rates + MWIFIEX_TDLS_SUPPORTED_RATES,
+                      ext_rates_size);
+       }
+
+       return 0;
+}
+
+static void mwifiex_tdls_add_aid(struct mwifiex_private *priv,
+                               struct sk_buff *skb)
+{
+       struct ieee_types_assoc_rsp *assoc_rsp;
+       u8 *pos;
+
+       assoc_rsp = (struct ieee_types_assoc_rsp *)&priv->assoc_rsp_buf;
+       pos = (void *)skb_put(skb, 4);
+       *pos++ = WLAN_EID_AID;
+       *pos++ = 2;
+       memcpy(pos, &assoc_rsp->a_id, sizeof(assoc_rsp->a_id));
+
+       return;
+}
+
+static int mwifiex_tdls_add_vht_capab(struct mwifiex_private *priv,
+                                     struct sk_buff *skb)
+{
+       struct ieee80211_vht_cap vht_cap;
+       u8 *pos;
+
+       pos = (void *)skb_put(skb, sizeof(struct ieee80211_vht_cap) + 2);
+       *pos++ = WLAN_EID_VHT_CAPABILITY;
+       *pos++ = sizeof(struct ieee80211_vht_cap);
+
+       memset(&vht_cap, 0, sizeof(struct ieee80211_vht_cap));
+
+       mwifiex_fill_vht_cap_tlv(priv, &vht_cap, priv->curr_bss_params.band);
+       memcpy(pos, &vht_cap, sizeof(vht_cap));
+
+       return 0;
+}
+
+static int
+mwifiex_tdls_add_ht_oper(struct mwifiex_private *priv, const u8 *mac,
+                        u8 vht_enabled, struct sk_buff *skb)
+{
+       struct ieee80211_ht_operation *ht_oper;
+       struct mwifiex_sta_node *sta_ptr;
+       struct mwifiex_bssdescriptor *bss_desc =
+                                       &priv->curr_bss_params.bss_descriptor;
+       u8 *pos;
+
+       sta_ptr = mwifiex_get_sta_entry(priv, mac);
+       if (unlikely(!sta_ptr)) {
+               mwifiex_dbg(priv->adapter, ERROR,
+                           "TDLS peer station not found in list\n");
+               return -1;
+       }
+
+       if (!(le16_to_cpu(sta_ptr->tdls_cap.ht_capb.cap_info))) {
+               mwifiex_dbg(priv->adapter, WARN,
+                           "TDLS peer doesn't support ht capabilities\n");
+               return 0;
+       }
+
+       pos = (void *)skb_put(skb, sizeof(struct ieee80211_ht_operation) + 2);
+       *pos++ = WLAN_EID_HT_OPERATION;
+       *pos++ = sizeof(struct ieee80211_ht_operation);
+       ht_oper = (void *)pos;
+
+       ht_oper->primary_chan = bss_desc->channel;
+
+       /* follow AP's channel bandwidth */
+       if (ISSUPP_CHANWIDTH40(priv->adapter->hw_dot_11n_dev_cap) &&
+           bss_desc->bcn_ht_cap &&
+           ISALLOWED_CHANWIDTH40(bss_desc->bcn_ht_oper->ht_param))
+               ht_oper->ht_param = bss_desc->bcn_ht_oper->ht_param;
+
+       if (vht_enabled) {
+               ht_oper->ht_param =
+                         mwifiex_get_sec_chan_offset(bss_desc->channel);
+               ht_oper->ht_param |= BIT(2);
+       }
+
+       memcpy(&sta_ptr->tdls_cap.ht_oper, ht_oper,
+              sizeof(struct ieee80211_ht_operation));
+
+       return 0;
+}
+
+static int mwifiex_tdls_add_vht_oper(struct mwifiex_private *priv,
+                                    const u8 *mac, struct sk_buff *skb)
+{
+       struct mwifiex_bssdescriptor *bss_desc;
+       struct ieee80211_vht_operation *vht_oper;
+       struct ieee80211_vht_cap *vht_cap, *ap_vht_cap = NULL;
+       struct mwifiex_sta_node *sta_ptr;
+       struct mwifiex_adapter *adapter = priv->adapter;
+       u8 supp_chwd_set, peer_supp_chwd_set;
+       u8 *pos, ap_supp_chwd_set, chan_bw;
+       u16 mcs_map_user, mcs_map_resp, mcs_map_result;
+       u16 mcs_user, mcs_resp, nss;
+       u32 usr_vht_cap_info;
+
+       bss_desc = &priv->curr_bss_params.bss_descriptor;
+
+       sta_ptr = mwifiex_get_sta_entry(priv, mac);
+       if (unlikely(!sta_ptr)) {
+               mwifiex_dbg(adapter, ERROR,
+                           "TDLS peer station not found in list\n");
+               return -1;
+       }
+
+       if (!(le32_to_cpu(sta_ptr->tdls_cap.vhtcap.vht_cap_info))) {
+               mwifiex_dbg(adapter, WARN,
+                           "TDLS peer doesn't support vht capabilities\n");
+               return 0;
+       }
+
+       if (!mwifiex_is_bss_in_11ac_mode(priv)) {
+               if (sta_ptr->tdls_cap.extcap.ext_capab[7] &
+                  WLAN_EXT_CAPA8_TDLS_WIDE_BW_ENABLED) {
+                       mwifiex_dbg(adapter, WARN,
+                                   "TDLS peer doesn't support wider bandwidth\n");
+                       return 0;
+               }
+       } else {
+               ap_vht_cap = bss_desc->bcn_vht_cap;
+       }
+
+       pos = (void *)skb_put(skb, sizeof(struct ieee80211_vht_operation) + 2);
+       *pos++ = WLAN_EID_VHT_OPERATION;
+       *pos++ = sizeof(struct ieee80211_vht_operation);
+       vht_oper = (struct ieee80211_vht_operation *)pos;
+
+       if (bss_desc->bss_band & BAND_A)
+               usr_vht_cap_info = adapter->usr_dot_11ac_dev_cap_a;
+       else
+               usr_vht_cap_info = adapter->usr_dot_11ac_dev_cap_bg;
+
+       /* find the minmum bandwith between AP/TDLS peers */
+       vht_cap = &sta_ptr->tdls_cap.vhtcap;
+       supp_chwd_set = GET_VHTCAP_CHWDSET(usr_vht_cap_info);
+       peer_supp_chwd_set =
+                        GET_VHTCAP_CHWDSET(le32_to_cpu(vht_cap->vht_cap_info));
+       supp_chwd_set = min_t(u8, supp_chwd_set, peer_supp_chwd_set);
+
+       /* We need check AP's bandwidth when TDLS_WIDER_BANDWIDTH is off */
+
+       if (ap_vht_cap && sta_ptr->tdls_cap.extcap.ext_capab[7] &
+           WLAN_EXT_CAPA8_TDLS_WIDE_BW_ENABLED) {
+               ap_supp_chwd_set =
+                     GET_VHTCAP_CHWDSET(le32_to_cpu(ap_vht_cap->vht_cap_info));
+               supp_chwd_set = min_t(u8, supp_chwd_set, ap_supp_chwd_set);
+       }
+
+       switch (supp_chwd_set) {
+       case IEEE80211_VHT_CHANWIDTH_80MHZ:
+               vht_oper->chan_width = IEEE80211_VHT_CHANWIDTH_80MHZ;
+               break;
+       case IEEE80211_VHT_CHANWIDTH_160MHZ:
+               vht_oper->chan_width = IEEE80211_VHT_CHANWIDTH_160MHZ;
+               break;
+       case IEEE80211_VHT_CHANWIDTH_80P80MHZ:
+               vht_oper->chan_width = IEEE80211_VHT_CHANWIDTH_80P80MHZ;
+               break;
+       default:
+               vht_oper->chan_width = IEEE80211_VHT_CHANWIDTH_USE_HT;
+               break;
+       }
+
+       mcs_map_user = GET_DEVRXMCSMAP(adapter->usr_dot_11ac_mcs_support);
+       mcs_map_resp = le16_to_cpu(vht_cap->supp_mcs.rx_mcs_map);
+       mcs_map_result = 0;
+
+       for (nss = 1; nss <= 8; nss++) {
+               mcs_user = GET_VHTNSSMCS(mcs_map_user, nss);
+               mcs_resp = GET_VHTNSSMCS(mcs_map_resp, nss);
+
+               if ((mcs_user == IEEE80211_VHT_MCS_NOT_SUPPORTED) ||
+                   (mcs_resp == IEEE80211_VHT_MCS_NOT_SUPPORTED))
+                       SET_VHTNSSMCS(mcs_map_result, nss,
+                                     IEEE80211_VHT_MCS_NOT_SUPPORTED);
+               else
+                       SET_VHTNSSMCS(mcs_map_result, nss,
+                                     min_t(u16, mcs_user, mcs_resp));
+       }
+
+       vht_oper->basic_mcs_set = cpu_to_le16(mcs_map_result);
+
+       switch (vht_oper->chan_width) {
+       case IEEE80211_VHT_CHANWIDTH_80MHZ:
+               chan_bw = IEEE80211_VHT_CHANWIDTH_80MHZ;
+               break;
+       case IEEE80211_VHT_CHANWIDTH_160MHZ:
+               chan_bw = IEEE80211_VHT_CHANWIDTH_160MHZ;
+               break;
+       case IEEE80211_VHT_CHANWIDTH_80P80MHZ:
+               chan_bw = IEEE80211_VHT_CHANWIDTH_80MHZ;
+               break;
+       default:
+               chan_bw = IEEE80211_VHT_CHANWIDTH_USE_HT;
+               break;
+       }
+       vht_oper->center_freq_seg1_idx =
+                       mwifiex_get_center_freq_index(priv, BAND_AAC,
+                                                     bss_desc->channel,
+                                                     chan_bw);
+
+       return 0;
+}
+
+static void mwifiex_tdls_add_ext_capab(struct mwifiex_private *priv,
+                                      struct sk_buff *skb)
+{
+       struct ieee_types_extcap *extcap;
+
+       extcap = (void *)skb_put(skb, sizeof(struct ieee_types_extcap));
+       extcap->ieee_hdr.element_id = WLAN_EID_EXT_CAPABILITY;
+       extcap->ieee_hdr.len = 8;
+       memset(extcap->ext_capab, 0, 8);
+       extcap->ext_capab[4] |= WLAN_EXT_CAPA5_TDLS_ENABLED;
+       extcap->ext_capab[3] |= WLAN_EXT_CAPA4_TDLS_CHAN_SWITCH;
+
+       if (priv->adapter->is_hw_11ac_capable)
+               extcap->ext_capab[7] |= WLAN_EXT_CAPA8_TDLS_WIDE_BW_ENABLED;
+}
+
+static void mwifiex_tdls_add_qos_capab(struct sk_buff *skb)
+{
+       u8 *pos = (void *)skb_put(skb, 3);
+
+       *pos++ = WLAN_EID_QOS_CAPA;
+       *pos++ = 1;
+       *pos++ = MWIFIEX_TDLS_DEF_QOS_CAPAB;
+}
+
+static void
+mwifiex_tdls_add_wmm_param_ie(struct mwifiex_private *priv, struct sk_buff *skb)
+{
+       struct ieee80211_wmm_param_ie *wmm;
+       u8 ac_vi[] = {0x42, 0x43, 0x5e, 0x00};
+       u8 ac_vo[] = {0x62, 0x32, 0x2f, 0x00};
+       u8 ac_be[] = {0x03, 0xa4, 0x00, 0x00};
+       u8 ac_bk[] = {0x27, 0xa4, 0x00, 0x00};
+
+       wmm = (void *)skb_put(skb, sizeof(*wmm));
+       memset(wmm, 0, sizeof(*wmm));
+
+       wmm->element_id = WLAN_EID_VENDOR_SPECIFIC;
+       wmm->len = sizeof(*wmm) - 2;
+       wmm->oui[0] = 0x00; /* Microsoft OUI 00:50:F2 */
+       wmm->oui[1] = 0x50;
+       wmm->oui[2] = 0xf2;
+       wmm->oui_type = 2; /* WME */
+       wmm->oui_subtype = 1; /* WME param */
+       wmm->version = 1; /* WME ver */
+       wmm->qos_info = 0; /* U-APSD not in use */
+
+       /* use default WMM AC parameters for TDLS link*/
+       memcpy(&wmm->ac[0], ac_be, sizeof(ac_be));
+       memcpy(&wmm->ac[1], ac_bk, sizeof(ac_bk));
+       memcpy(&wmm->ac[2], ac_vi, sizeof(ac_vi));
+       memcpy(&wmm->ac[3], ac_vo, sizeof(ac_vo));
+}
+
+static void
+mwifiex_add_wmm_info_ie(struct mwifiex_private *priv, struct sk_buff *skb,
+                       u8 qosinfo)
+{
+       u8 *buf;
+
+       buf = (void *)skb_put(skb, MWIFIEX_TDLS_WMM_INFO_SIZE +
+                             sizeof(struct ieee_types_header));
+
+       *buf++ = WLAN_EID_VENDOR_SPECIFIC;
+       *buf++ = 7; /* len */
+       *buf++ = 0x00; /* Microsoft OUI 00:50:F2 */
+       *buf++ = 0x50;
+       *buf++ = 0xf2;
+       *buf++ = 2; /* WME */
+       *buf++ = 0; /* WME info */
+       *buf++ = 1; /* WME ver */
+       *buf++ = qosinfo; /* U-APSD no in use */
+}
+
+static int mwifiex_prep_tdls_encap_data(struct mwifiex_private *priv,
+                                       const u8 *peer, u8 action_code,
+                                       u8 dialog_token,
+                                       u16 status_code, struct sk_buff *skb)
+{
+       struct ieee80211_tdls_data *tf;
+       int ret;
+       u16 capab;
+       struct ieee80211_ht_cap *ht_cap;
+       u8 radio, *pos;
+
+       capab = priv->curr_bss_params.bss_descriptor.cap_info_bitmap;
+
+       tf = (void *)skb_put(skb, offsetof(struct ieee80211_tdls_data, u));
+       memcpy(tf->da, peer, ETH_ALEN);
+       memcpy(tf->sa, priv->curr_addr, ETH_ALEN);
+       tf->ether_type = cpu_to_be16(ETH_P_TDLS);
+       tf->payload_type = WLAN_TDLS_SNAP_RFTYPE;
+
+       switch (action_code) {
+       case WLAN_TDLS_SETUP_REQUEST:
+               tf->category = WLAN_CATEGORY_TDLS;
+               tf->action_code = WLAN_TDLS_SETUP_REQUEST;
+               skb_put(skb, sizeof(tf->u.setup_req));
+               tf->u.setup_req.dialog_token = dialog_token;
+               tf->u.setup_req.capability = cpu_to_le16(capab);
+               ret = mwifiex_tdls_append_rates_ie(priv, skb);
+               if (ret) {
+                       dev_kfree_skb_any(skb);
+                       return ret;
+               }
+
+               pos = (void *)skb_put(skb, sizeof(struct ieee80211_ht_cap) + 2);
+               *pos++ = WLAN_EID_HT_CAPABILITY;
+               *pos++ = sizeof(struct ieee80211_ht_cap);
+               ht_cap = (void *)pos;
+               radio = mwifiex_band_to_radio_type(priv->curr_bss_params.band);
+               ret = mwifiex_fill_cap_info(priv, radio, ht_cap);
+               if (ret) {
+                       dev_kfree_skb_any(skb);
+                       return ret;
+               }
+
+               if (priv->adapter->is_hw_11ac_capable) {
+                       ret = mwifiex_tdls_add_vht_capab(priv, skb);
+                       if (ret) {
+                               dev_kfree_skb_any(skb);
+                               return ret;
+                       }
+                       mwifiex_tdls_add_aid(priv, skb);
+               }
+
+               mwifiex_tdls_add_ext_capab(priv, skb);
+               mwifiex_tdls_add_qos_capab(skb);
+               mwifiex_add_wmm_info_ie(priv, skb, 0);
+               break;
+
+       case WLAN_TDLS_SETUP_RESPONSE:
+               tf->category = WLAN_CATEGORY_TDLS;
+               tf->action_code = WLAN_TDLS_SETUP_RESPONSE;
+               skb_put(skb, sizeof(tf->u.setup_resp));
+               tf->u.setup_resp.status_code = cpu_to_le16(status_code);
+               tf->u.setup_resp.dialog_token = dialog_token;
+               tf->u.setup_resp.capability = cpu_to_le16(capab);
+               ret = mwifiex_tdls_append_rates_ie(priv, skb);
+               if (ret) {
+                       dev_kfree_skb_any(skb);
+                       return ret;
+               }
+
+               pos = (void *)skb_put(skb, sizeof(struct ieee80211_ht_cap) + 2);
+               *pos++ = WLAN_EID_HT_CAPABILITY;
+               *pos++ = sizeof(struct ieee80211_ht_cap);
+               ht_cap = (void *)pos;
+               radio = mwifiex_band_to_radio_type(priv->curr_bss_params.band);
+               ret = mwifiex_fill_cap_info(priv, radio, ht_cap);
+               if (ret) {
+                       dev_kfree_skb_any(skb);
+                       return ret;
+               }
+
+               if (priv->adapter->is_hw_11ac_capable) {
+                       ret = mwifiex_tdls_add_vht_capab(priv, skb);
+                       if (ret) {
+                               dev_kfree_skb_any(skb);
+                               return ret;
+                       }
+                       mwifiex_tdls_add_aid(priv, skb);
+               }
+
+               mwifiex_tdls_add_ext_capab(priv, skb);
+               mwifiex_tdls_add_qos_capab(skb);
+               mwifiex_add_wmm_info_ie(priv, skb, 0);
+               break;
+
+       case WLAN_TDLS_SETUP_CONFIRM:
+               tf->category = WLAN_CATEGORY_TDLS;
+               tf->action_code = WLAN_TDLS_SETUP_CONFIRM;
+               skb_put(skb, sizeof(tf->u.setup_cfm));
+               tf->u.setup_cfm.status_code = cpu_to_le16(status_code);
+               tf->u.setup_cfm.dialog_token = dialog_token;
+
+               mwifiex_tdls_add_wmm_param_ie(priv, skb);
+               if (priv->adapter->is_hw_11ac_capable) {
+                       ret = mwifiex_tdls_add_vht_oper(priv, peer, skb);
+                       if (ret) {
+                               dev_kfree_skb_any(skb);
+                               return ret;
+                       }
+                       ret = mwifiex_tdls_add_ht_oper(priv, peer, 1, skb);
+                       if (ret) {
+                               dev_kfree_skb_any(skb);
+                               return ret;
+                       }
+               } else {
+                       ret = mwifiex_tdls_add_ht_oper(priv, peer, 0, skb);
+                       if (ret) {
+                               dev_kfree_skb_any(skb);
+                               return ret;
+                       }
+               }
+               break;
+
+       case WLAN_TDLS_TEARDOWN:
+               tf->category = WLAN_CATEGORY_TDLS;
+               tf->action_code = WLAN_TDLS_TEARDOWN;
+               skb_put(skb, sizeof(tf->u.teardown));
+               tf->u.teardown.reason_code = cpu_to_le16(status_code);
+               break;
+
+       case WLAN_TDLS_DISCOVERY_REQUEST:
+               tf->category = WLAN_CATEGORY_TDLS;
+               tf->action_code = WLAN_TDLS_DISCOVERY_REQUEST;
+               skb_put(skb, sizeof(tf->u.discover_req));
+               tf->u.discover_req.dialog_token = dialog_token;
+               break;
+       default:
+               mwifiex_dbg(priv->adapter, ERROR, "Unknown TDLS frame type.\n");
+               return -EINVAL;
+       }
+
+       return 0;
+}
+
+static void
+mwifiex_tdls_add_link_ie(struct sk_buff *skb, const u8 *src_addr,
+                        const u8 *peer, const u8 *bssid)
+{
+       struct ieee80211_tdls_lnkie *lnkid;
+
+       lnkid = (void *)skb_put(skb, sizeof(struct ieee80211_tdls_lnkie));
+       lnkid->ie_type = WLAN_EID_LINK_ID;
+       lnkid->ie_len = sizeof(struct ieee80211_tdls_lnkie) -
+                       sizeof(struct ieee_types_header);
+
+       memcpy(lnkid->bssid, bssid, ETH_ALEN);
+       memcpy(lnkid->init_sta, src_addr, ETH_ALEN);
+       memcpy(lnkid->resp_sta, peer, ETH_ALEN);
+}
+
+int mwifiex_send_tdls_data_frame(struct mwifiex_private *priv, const u8 *peer,
+                                u8 action_code, u8 dialog_token,
+                                u16 status_code, const u8 *extra_ies,
+                                size_t extra_ies_len)
+{
+       struct sk_buff *skb;
+       struct mwifiex_txinfo *tx_info;
+       int ret;
+       u16 skb_len;
+
+       skb_len = MWIFIEX_MIN_DATA_HEADER_LEN +
+                 max(sizeof(struct ieee80211_mgmt),
+                     sizeof(struct ieee80211_tdls_data)) +
+                 MWIFIEX_MGMT_FRAME_HEADER_SIZE +
+                 MWIFIEX_SUPPORTED_RATES +
+                 3 + /* Qos Info */
+                 sizeof(struct ieee_types_extcap) +
+                 sizeof(struct ieee80211_ht_cap) +
+                 sizeof(struct ieee_types_bss_co_2040) +
+                 sizeof(struct ieee80211_ht_operation) +
+                 sizeof(struct ieee80211_tdls_lnkie) +
+                 sizeof(struct ieee80211_wmm_param_ie) +
+                 extra_ies_len;
+
+       if (priv->adapter->is_hw_11ac_capable)
+               skb_len += sizeof(struct ieee_types_vht_cap) +
+                          sizeof(struct ieee_types_vht_oper) +
+                          sizeof(struct ieee_types_aid);
+
+       skb = dev_alloc_skb(skb_len);
+       if (!skb) {
+               mwifiex_dbg(priv->adapter, ERROR,
+                           "allocate skb failed for management frame\n");
+               return -ENOMEM;
+       }
+       skb_reserve(skb, MWIFIEX_MIN_DATA_HEADER_LEN);
+
+       switch (action_code) {
+       case WLAN_TDLS_SETUP_REQUEST:
+       case WLAN_TDLS_SETUP_CONFIRM:
+       case WLAN_TDLS_TEARDOWN:
+       case WLAN_TDLS_DISCOVERY_REQUEST:
+               ret = mwifiex_prep_tdls_encap_data(priv, peer, action_code,
+                                                  dialog_token, status_code,
+                                                  skb);
+               if (ret) {
+                       dev_kfree_skb_any(skb);
+                       return ret;
+               }
+               if (extra_ies_len)
+                       memcpy(skb_put(skb, extra_ies_len), extra_ies,
+                              extra_ies_len);
+               mwifiex_tdls_add_link_ie(skb, priv->curr_addr, peer,
+                                        priv->cfg_bssid);
+               break;
+       case WLAN_TDLS_SETUP_RESPONSE:
+               ret = mwifiex_prep_tdls_encap_data(priv, peer, action_code,
+                                                  dialog_token, status_code,
+                                                  skb);
+               if (ret) {
+                       dev_kfree_skb_any(skb);
+                       return ret;
+               }
+               if (extra_ies_len)
+                       memcpy(skb_put(skb, extra_ies_len), extra_ies,
+                              extra_ies_len);
+               mwifiex_tdls_add_link_ie(skb, peer, priv->curr_addr,
+                                        priv->cfg_bssid);
+               break;
+       }
+
+       switch (action_code) {
+       case WLAN_TDLS_SETUP_REQUEST:
+       case WLAN_TDLS_SETUP_RESPONSE:
+               skb->priority = MWIFIEX_PRIO_BK;
+               break;
+       default:
+               skb->priority = MWIFIEX_PRIO_VI;
+               break;
+       }
+
+       tx_info = MWIFIEX_SKB_TXCB(skb);
+       memset(tx_info, 0, sizeof(*tx_info));
+       tx_info->bss_num = priv->bss_num;
+       tx_info->bss_type = priv->bss_type;
+
+       __net_timestamp(skb);
+       mwifiex_queue_tx_pkt(priv, skb);
+
+       return 0;
+}
+
+static int
+mwifiex_construct_tdls_action_frame(struct mwifiex_private *priv,
+                                   const u8 *peer,
+                                   u8 action_code, u8 dialog_token,
+                                   u16 status_code, struct sk_buff *skb)
+{
+       struct ieee80211_mgmt *mgmt;
+       u8 bc_addr[] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
+       int ret;
+       u16 capab;
+       struct ieee80211_ht_cap *ht_cap;
+       u8 radio, *pos;
+
+       capab = priv->curr_bss_params.bss_descriptor.cap_info_bitmap;
+
+       mgmt = (void *)skb_put(skb, offsetof(struct ieee80211_mgmt, u));
+
+       memset(mgmt, 0, 24);
+       memcpy(mgmt->da, peer, ETH_ALEN);
+       memcpy(mgmt->sa, priv->curr_addr, ETH_ALEN);
+       memcpy(mgmt->bssid, priv->cfg_bssid, ETH_ALEN);
+       mgmt->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT |
+                                         IEEE80211_STYPE_ACTION);
+
+       /* add address 4 */
+       pos = skb_put(skb, ETH_ALEN);
+
+       switch (action_code) {
+       case WLAN_PUB_ACTION_TDLS_DISCOVER_RES:
+               skb_put(skb, sizeof(mgmt->u.action.u.tdls_discover_resp) + 1);
+               mgmt->u.action.category = WLAN_CATEGORY_PUBLIC;
+               mgmt->u.action.u.tdls_discover_resp.action_code =
+                                             WLAN_PUB_ACTION_TDLS_DISCOVER_RES;
+               mgmt->u.action.u.tdls_discover_resp.dialog_token =
+                                                                  dialog_token;
+               mgmt->u.action.u.tdls_discover_resp.capability =
+                                                            cpu_to_le16(capab);
+               /* move back for addr4 */
+               memmove(pos + ETH_ALEN, &mgmt->u.action.category,
+                       sizeof(mgmt->u.action.u.tdls_discover_resp));
+               /* init address 4 */
+               memcpy(pos, bc_addr, ETH_ALEN);
+
+               ret = mwifiex_tdls_append_rates_ie(priv, skb);
+               if (ret) {
+                       dev_kfree_skb_any(skb);
+                       return ret;
+               }
+
+               pos = (void *)skb_put(skb, sizeof(struct ieee80211_ht_cap) + 2);
+               *pos++ = WLAN_EID_HT_CAPABILITY;
+               *pos++ = sizeof(struct ieee80211_ht_cap);
+               ht_cap = (void *)pos;
+               radio = mwifiex_band_to_radio_type(priv->curr_bss_params.band);
+               ret = mwifiex_fill_cap_info(priv, radio, ht_cap);
+               if (ret) {
+                       dev_kfree_skb_any(skb);
+                       return ret;
+               }
+
+               if (priv->adapter->is_hw_11ac_capable) {
+                       ret = mwifiex_tdls_add_vht_capab(priv, skb);
+                       if (ret) {
+                               dev_kfree_skb_any(skb);
+                               return ret;
+                       }
+                       mwifiex_tdls_add_aid(priv, skb);
+               }
+
+               mwifiex_tdls_add_ext_capab(priv, skb);
+               mwifiex_tdls_add_qos_capab(skb);
+               break;
+       default:
+               mwifiex_dbg(priv->adapter, ERROR, "Unknown TDLS action frame type\n");
+               return -EINVAL;
+       }
+
+       return 0;
+}
+
+int mwifiex_send_tdls_action_frame(struct mwifiex_private *priv, const u8 *peer,
+                                  u8 action_code, u8 dialog_token,
+                                  u16 status_code, const u8 *extra_ies,
+                                  size_t extra_ies_len)
+{
+       struct sk_buff *skb;
+       struct mwifiex_txinfo *tx_info;
+       u8 *pos;
+       u32 pkt_type, tx_control;
+       u16 pkt_len, skb_len;
+
+       skb_len = MWIFIEX_MIN_DATA_HEADER_LEN +
+                 max(sizeof(struct ieee80211_mgmt),
+                     sizeof(struct ieee80211_tdls_data)) +
+                 MWIFIEX_MGMT_FRAME_HEADER_SIZE +
+                 MWIFIEX_SUPPORTED_RATES +
+                 sizeof(struct ieee_types_extcap) +
+                 sizeof(struct ieee80211_ht_cap) +
+                 sizeof(struct ieee_types_bss_co_2040) +
+                 sizeof(struct ieee80211_ht_operation) +
+                 sizeof(struct ieee80211_tdls_lnkie) +
+                 extra_ies_len +
+                 3 + /* Qos Info */
+                 ETH_ALEN; /* Address4 */
+
+       if (priv->adapter->is_hw_11ac_capable)
+               skb_len += sizeof(struct ieee_types_vht_cap) +
+                          sizeof(struct ieee_types_vht_oper) +
+                          sizeof(struct ieee_types_aid);
+
+       skb = dev_alloc_skb(skb_len);
+       if (!skb) {
+               mwifiex_dbg(priv->adapter, ERROR,
+                           "allocate skb failed for management frame\n");
+               return -ENOMEM;
+       }
+
+       skb_reserve(skb, MWIFIEX_MIN_DATA_HEADER_LEN);
+
+       pkt_type = PKT_TYPE_MGMT;
+       tx_control = 0;
+       pos = skb_put(skb, MWIFIEX_MGMT_FRAME_HEADER_SIZE + sizeof(pkt_len));
+       memset(pos, 0, MWIFIEX_MGMT_FRAME_HEADER_SIZE + sizeof(pkt_len));
+       memcpy(pos, &pkt_type, sizeof(pkt_type));
+       memcpy(pos + sizeof(pkt_type), &tx_control, sizeof(tx_control));
+
+       if (mwifiex_construct_tdls_action_frame(priv, peer, action_code,
+                                               dialog_token, status_code,
+                                               skb)) {
+               dev_kfree_skb_any(skb);
+               return -EINVAL;
+       }
+
+       if (extra_ies_len)
+               memcpy(skb_put(skb, extra_ies_len), extra_ies, extra_ies_len);
+
+       /* the TDLS link IE is always added last we are the responder */
+
+       mwifiex_tdls_add_link_ie(skb, peer, priv->curr_addr,
+                                priv->cfg_bssid);
+
+       skb->priority = MWIFIEX_PRIO_VI;
+
+       tx_info = MWIFIEX_SKB_TXCB(skb);
+       memset(tx_info, 0, sizeof(*tx_info));
+       tx_info->bss_num = priv->bss_num;
+       tx_info->bss_type = priv->bss_type;
+       tx_info->flags |= MWIFIEX_BUF_FLAG_TDLS_PKT;
+
+       pkt_len = skb->len - MWIFIEX_MGMT_FRAME_HEADER_SIZE - sizeof(pkt_len);
+       memcpy(skb->data + MWIFIEX_MGMT_FRAME_HEADER_SIZE, &pkt_len,
+              sizeof(pkt_len));
+       __net_timestamp(skb);
+       mwifiex_queue_tx_pkt(priv, skb);
+
+       return 0;
+}
+
+/* This function process tdls action frame from peer.
+ * Peer capabilities are stored into station node structure.
+ */
+void mwifiex_process_tdls_action_frame(struct mwifiex_private *priv,
+                                      u8 *buf, int len)
+{
+       struct mwifiex_sta_node *sta_ptr;
+       u8 *peer, *pos, *end;
+       u8 i, action, basic;
+       __le16 cap = 0;
+       int ie_len = 0;
+
+       if (len < (sizeof(struct ethhdr) + 3))
+               return;
+       if (*(buf + sizeof(struct ethhdr)) != WLAN_TDLS_SNAP_RFTYPE)
+               return;
+       if (*(buf + sizeof(struct ethhdr) + 1) != WLAN_CATEGORY_TDLS)
+               return;
+
+       peer = buf + ETH_ALEN;
+       action = *(buf + sizeof(struct ethhdr) + 2);
+       mwifiex_dbg(priv->adapter, DATA,
+                   "rx:tdls action: peer=%pM, action=%d\n", peer, action);
+
+       switch (action) {
+       case WLAN_TDLS_SETUP_REQUEST:
+               if (len < (sizeof(struct ethhdr) + TDLS_REQ_FIX_LEN))
+                       return;
+
+               pos = buf + sizeof(struct ethhdr) + 4;
+               /* payload 1+ category 1 + action 1 + dialog 1 */
+               cap = cpu_to_le16(*(u16 *)pos);
+               ie_len = len - sizeof(struct ethhdr) - TDLS_REQ_FIX_LEN;
+               pos += 2;
+               break;
+
+       case WLAN_TDLS_SETUP_RESPONSE:
+               if (len < (sizeof(struct ethhdr) + TDLS_RESP_FIX_LEN))
+                       return;
+               /* payload 1+ category 1 + action 1 + dialog 1 + status code 2*/
+               pos = buf + sizeof(struct ethhdr) + 6;
+               cap = cpu_to_le16(*(u16 *)pos);
+               ie_len = len - sizeof(struct ethhdr) - TDLS_RESP_FIX_LEN;
+               pos += 2;
+               break;
+
+       case WLAN_TDLS_SETUP_CONFIRM:
+               if (len < (sizeof(struct ethhdr) + TDLS_CONFIRM_FIX_LEN))
+                       return;
+               pos = buf + sizeof(struct ethhdr) + TDLS_CONFIRM_FIX_LEN;
+               ie_len = len - sizeof(struct ethhdr) - TDLS_CONFIRM_FIX_LEN;
+               break;
+       default:
+               mwifiex_dbg(priv->adapter, ERROR, "Unknown TDLS frame type.\n");
+               return;
+       }
+
+       sta_ptr = mwifiex_add_sta_entry(priv, peer);
+       if (!sta_ptr)
+               return;
+
+       sta_ptr->tdls_cap.capab = cap;
+
+       for (end = pos + ie_len; pos + 1 < end; pos += 2 + pos[1]) {
+               if (pos + 2 + pos[1] > end)
+                       break;
+
+               switch (*pos) {
+               case WLAN_EID_SUPP_RATES:
+                       sta_ptr->tdls_cap.rates_len = pos[1];
+                       for (i = 0; i < pos[1]; i++)
+                               sta_ptr->tdls_cap.rates[i] = pos[i + 2];
+                       break;
+
+               case WLAN_EID_EXT_SUPP_RATES:
+                       basic = sta_ptr->tdls_cap.rates_len;
+                       for (i = 0; i < pos[1]; i++)
+                               sta_ptr->tdls_cap.rates[basic + i] = pos[i + 2];
+                       sta_ptr->tdls_cap.rates_len += pos[1];
+                       break;
+               case WLAN_EID_HT_CAPABILITY:
+                       memcpy((u8 *)&sta_ptr->tdls_cap.ht_capb, pos,
+                              sizeof(struct ieee80211_ht_cap));
+                       sta_ptr->is_11n_enabled = 1;
+                       break;
+               case WLAN_EID_HT_OPERATION:
+                       memcpy(&sta_ptr->tdls_cap.ht_oper, pos,
+                              sizeof(struct ieee80211_ht_operation));
+                       break;
+               case WLAN_EID_BSS_COEX_2040:
+                       sta_ptr->tdls_cap.coex_2040 = pos[2];
+                       break;
+               case WLAN_EID_EXT_CAPABILITY:
+                       memcpy((u8 *)&sta_ptr->tdls_cap.extcap, pos,
+                              sizeof(struct ieee_types_header) +
+                              min_t(u8, pos[1], 8));
+                       break;
+               case WLAN_EID_RSN:
+                       memcpy((u8 *)&sta_ptr->tdls_cap.rsn_ie, pos,
+                              sizeof(struct ieee_types_header) +
+                              min_t(u8, pos[1], IEEE_MAX_IE_SIZE -
+                                    sizeof(struct ieee_types_header)));
+                       break;
+               case WLAN_EID_QOS_CAPA:
+                       sta_ptr->tdls_cap.qos_info = pos[2];
+                       break;
+               case WLAN_EID_VHT_OPERATION:
+                       if (priv->adapter->is_hw_11ac_capable)
+                               memcpy(&sta_ptr->tdls_cap.vhtoper, pos,
+                                      sizeof(struct ieee80211_vht_operation));
+                       break;
+               case WLAN_EID_VHT_CAPABILITY:
+                       if (priv->adapter->is_hw_11ac_capable) {
+                               memcpy((u8 *)&sta_ptr->tdls_cap.vhtcap, pos,
+                                      sizeof(struct ieee80211_vht_cap));
+                               sta_ptr->is_11ac_enabled = 1;
+                       }
+                       break;
+               case WLAN_EID_AID:
+                       if (priv->adapter->is_hw_11ac_capable)
+                               sta_ptr->tdls_cap.aid =
+                                             le16_to_cpu(*(__le16 *)(pos + 2));
+               default:
+                       break;
+               }
+       }
+
+       return;
+}
+
+static int
+mwifiex_tdls_process_config_link(struct mwifiex_private *priv, const u8 *peer)
+{
+       struct mwifiex_sta_node *sta_ptr;
+       struct mwifiex_ds_tdls_oper tdls_oper;
+
+       memset(&tdls_oper, 0, sizeof(struct mwifiex_ds_tdls_oper));
+       sta_ptr = mwifiex_get_sta_entry(priv, peer);
+
+       if (!sta_ptr || sta_ptr->tdls_status == TDLS_SETUP_FAILURE) {
+               mwifiex_dbg(priv->adapter, ERROR,
+                           "link absent for peer %pM; cannot config\n", peer);
+               return -EINVAL;
+       }
+
+       memcpy(&tdls_oper.peer_mac, peer, ETH_ALEN);
+       tdls_oper.tdls_action = MWIFIEX_TDLS_CONFIG_LINK;
+       return mwifiex_send_cmd(priv, HostCmd_CMD_TDLS_OPER,
+                               HostCmd_ACT_GEN_SET, 0, &tdls_oper, true);
+}
+
+static int
+mwifiex_tdls_process_create_link(struct mwifiex_private *priv, const u8 *peer)
+{
+       struct mwifiex_sta_node *sta_ptr;
+       struct mwifiex_ds_tdls_oper tdls_oper;
+
+       memset(&tdls_oper, 0, sizeof(struct mwifiex_ds_tdls_oper));
+       sta_ptr = mwifiex_get_sta_entry(priv, peer);
+
+       if (sta_ptr && sta_ptr->tdls_status == TDLS_SETUP_INPROGRESS) {
+               mwifiex_dbg(priv->adapter, WARN,
+                           "Setup already in progress for peer %pM\n", peer);
+               return 0;
+       }
+
+       sta_ptr = mwifiex_add_sta_entry(priv, peer);
+       if (!sta_ptr)
+               return -ENOMEM;
+
+       sta_ptr->tdls_status = TDLS_SETUP_INPROGRESS;
+       mwifiex_hold_tdls_packets(priv, peer);
+       memcpy(&tdls_oper.peer_mac, peer, ETH_ALEN);
+       tdls_oper.tdls_action = MWIFIEX_TDLS_CREATE_LINK;
+       return mwifiex_send_cmd(priv, HostCmd_CMD_TDLS_OPER,
+                               HostCmd_ACT_GEN_SET, 0, &tdls_oper, true);
+}
+
+static int
+mwifiex_tdls_process_disable_link(struct mwifiex_private *priv, const u8 *peer)
+{
+       struct mwifiex_sta_node *sta_ptr;
+       struct mwifiex_ds_tdls_oper tdls_oper;
+       unsigned long flags;
+
+       memset(&tdls_oper, 0, sizeof(struct mwifiex_ds_tdls_oper));
+       sta_ptr = mwifiex_get_sta_entry(priv, peer);
+
+       if (sta_ptr) {
+               if (sta_ptr->is_11n_enabled) {
+                       mwifiex_11n_cleanup_reorder_tbl(priv);
+                       spin_lock_irqsave(&priv->wmm.ra_list_spinlock,
+                                         flags);
+                       mwifiex_11n_delete_all_tx_ba_stream_tbl(priv);
+                       spin_unlock_irqrestore(&priv->wmm.ra_list_spinlock,
+                                              flags);
+               }
+               mwifiex_del_sta_entry(priv, peer);
+       }
+
+       mwifiex_restore_tdls_packets(priv, peer, TDLS_LINK_TEARDOWN);
+       mwifiex_auto_tdls_update_peer_status(priv, peer, TDLS_NOT_SETUP);
+       memcpy(&tdls_oper.peer_mac, peer, ETH_ALEN);
+       tdls_oper.tdls_action = MWIFIEX_TDLS_DISABLE_LINK;
+       return mwifiex_send_cmd(priv, HostCmd_CMD_TDLS_OPER,
+                               HostCmd_ACT_GEN_SET, 0, &tdls_oper, true);
+}
+
+static int
+mwifiex_tdls_process_enable_link(struct mwifiex_private *priv, const u8 *peer)
+{
+       struct mwifiex_sta_node *sta_ptr;
+       struct ieee80211_mcs_info mcs;
+       unsigned long flags;
+       int i;
+
+       sta_ptr = mwifiex_get_sta_entry(priv, peer);
+
+       if (sta_ptr && (sta_ptr->tdls_status != TDLS_SETUP_FAILURE)) {
+               mwifiex_dbg(priv->adapter, MSG,
+                           "tdls: enable link %pM success\n", peer);
+
+               sta_ptr->tdls_status = TDLS_SETUP_COMPLETE;
+
+               mcs = sta_ptr->tdls_cap.ht_capb.mcs;
+               if (mcs.rx_mask[0] != 0xff)
+                       sta_ptr->is_11n_enabled = true;
+               if (sta_ptr->is_11n_enabled) {
+                       if (le16_to_cpu(sta_ptr->tdls_cap.ht_capb.cap_info) &
+                           IEEE80211_HT_CAP_MAX_AMSDU)
+                               sta_ptr->max_amsdu =
+                                       MWIFIEX_TX_DATA_BUF_SIZE_8K;
+                       else
+                               sta_ptr->max_amsdu =
+                                       MWIFIEX_TX_DATA_BUF_SIZE_4K;
+
+                       for (i = 0; i < MAX_NUM_TID; i++)
+                               sta_ptr->ampdu_sta[i] =
+                                             priv->aggr_prio_tbl[i].ampdu_user;
+               } else {
+                       for (i = 0; i < MAX_NUM_TID; i++)
+                               sta_ptr->ampdu_sta[i] = BA_STREAM_NOT_ALLOWED;
+               }
+               if (sta_ptr->tdls_cap.extcap.ext_capab[3] &
+                   WLAN_EXT_CAPA4_TDLS_CHAN_SWITCH) {
+                       mwifiex_config_tdls_enable(priv);
+                       mwifiex_config_tdls_cs_params(priv);
+               }
+
+               memset(sta_ptr->rx_seq, 0xff, sizeof(sta_ptr->rx_seq));
+               mwifiex_restore_tdls_packets(priv, peer, TDLS_SETUP_COMPLETE);
+               mwifiex_auto_tdls_update_peer_status(priv, peer,
+                                                    TDLS_SETUP_COMPLETE);
+       } else {
+               mwifiex_dbg(priv->adapter, ERROR,
+                           "tdls: enable link %pM failed\n", peer);
+               if (sta_ptr) {
+                       mwifiex_11n_cleanup_reorder_tbl(priv);
+                       spin_lock_irqsave(&priv->wmm.ra_list_spinlock,
+                                         flags);
+                       mwifiex_11n_delete_all_tx_ba_stream_tbl(priv);
+                       spin_unlock_irqrestore(&priv->wmm.ra_list_spinlock,
+                                              flags);
+                       mwifiex_del_sta_entry(priv, peer);
+               }
+               mwifiex_restore_tdls_packets(priv, peer, TDLS_LINK_TEARDOWN);
+               mwifiex_auto_tdls_update_peer_status(priv, peer,
+                                                    TDLS_NOT_SETUP);
+
+               return -1;
+       }
+
+       return 0;
+}
+
+int mwifiex_tdls_oper(struct mwifiex_private *priv, const u8 *peer, u8 action)
+{
+       switch (action) {
+       case MWIFIEX_TDLS_ENABLE_LINK:
+               return mwifiex_tdls_process_enable_link(priv, peer);
+       case MWIFIEX_TDLS_DISABLE_LINK:
+               return mwifiex_tdls_process_disable_link(priv, peer);
+       case MWIFIEX_TDLS_CREATE_LINK:
+               return mwifiex_tdls_process_create_link(priv, peer);
+       case MWIFIEX_TDLS_CONFIG_LINK:
+               return mwifiex_tdls_process_config_link(priv, peer);
+       }
+       return 0;
+}
+
+int mwifiex_get_tdls_link_status(struct mwifiex_private *priv, const u8 *mac)
+{
+       struct mwifiex_sta_node *sta_ptr;
+
+       sta_ptr = mwifiex_get_sta_entry(priv, mac);
+       if (sta_ptr)
+               return sta_ptr->tdls_status;
+
+       return TDLS_NOT_SETUP;
+}
+
+int mwifiex_get_tdls_list(struct mwifiex_private *priv,
+                         struct tdls_peer_info *buf)
+{
+       struct mwifiex_sta_node *sta_ptr;
+       struct tdls_peer_info *peer = buf;
+       int count = 0;
+       unsigned long flags;
+
+       if (!ISSUPP_TDLS_ENABLED(priv->adapter->fw_cap_info))
+               return 0;
+
+       /* make sure we are in station mode and connected */
+       if (!(priv->bss_type == MWIFIEX_BSS_TYPE_STA && priv->media_connected))
+               return 0;
+
+       spin_lock_irqsave(&priv->sta_list_spinlock, flags);
+       list_for_each_entry(sta_ptr, &priv->sta_list, list) {
+               if (mwifiex_is_tdls_link_setup(sta_ptr->tdls_status)) {
+                       ether_addr_copy(peer->peer_addr, sta_ptr->mac_addr);
+                       peer++;
+                       count++;
+                       if (count >= MWIFIEX_MAX_TDLS_PEER_SUPPORTED)
+                               break;
+               }
+       }
+       spin_unlock_irqrestore(&priv->sta_list_spinlock, flags);
+
+       return count;
+}
+
+void mwifiex_disable_all_tdls_links(struct mwifiex_private *priv)
+{
+       struct mwifiex_sta_node *sta_ptr;
+       struct mwifiex_ds_tdls_oper tdls_oper;
+       unsigned long flags;
+
+       if (list_empty(&priv->sta_list))
+               return;
+
+       list_for_each_entry(sta_ptr, &priv->sta_list, list) {
+               memset(&tdls_oper, 0, sizeof(struct mwifiex_ds_tdls_oper));
+
+               if (sta_ptr->is_11n_enabled) {
+                       mwifiex_11n_cleanup_reorder_tbl(priv);
+                       spin_lock_irqsave(&priv->wmm.ra_list_spinlock,
+                                         flags);
+                       mwifiex_11n_delete_all_tx_ba_stream_tbl(priv);
+                       spin_unlock_irqrestore(&priv->wmm.ra_list_spinlock,
+                                              flags);
+               }
+
+               mwifiex_restore_tdls_packets(priv, sta_ptr->mac_addr,
+                                            TDLS_LINK_TEARDOWN);
+               memcpy(&tdls_oper.peer_mac, sta_ptr->mac_addr, ETH_ALEN);
+               tdls_oper.tdls_action = MWIFIEX_TDLS_DISABLE_LINK;
+               if (mwifiex_send_cmd(priv, HostCmd_CMD_TDLS_OPER,
+                                    HostCmd_ACT_GEN_SET, 0, &tdls_oper, false))
+                       mwifiex_dbg(priv->adapter, ERROR,
+                                   "Disable link failed for TDLS peer %pM",
+                                   sta_ptr->mac_addr);
+       }
+
+       mwifiex_del_all_sta_list(priv);
+}
+
+int mwifiex_tdls_check_tx(struct mwifiex_private *priv, struct sk_buff *skb)
+{
+       struct mwifiex_auto_tdls_peer *peer;
+       unsigned long flags;
+       u8 mac[ETH_ALEN];
+
+       ether_addr_copy(mac, skb->data);
+
+       spin_lock_irqsave(&priv->auto_tdls_lock, flags);
+       list_for_each_entry(peer, &priv->auto_tdls_list, list) {
+               if (!memcmp(mac, peer->mac_addr, ETH_ALEN)) {
+                       if (peer->rssi <= MWIFIEX_TDLS_RSSI_HIGH &&
+                           peer->tdls_status == TDLS_NOT_SETUP &&
+                           (peer->failure_count <
+                            MWIFIEX_TDLS_MAX_FAIL_COUNT)) {
+                               peer->tdls_status = TDLS_SETUP_INPROGRESS;
+                               mwifiex_dbg(priv->adapter, INFO,
+                                           "setup TDLS link, peer=%pM rssi=%d\n",
+                                           peer->mac_addr, peer->rssi);
+
+                               cfg80211_tdls_oper_request(priv->netdev,
+                                                          peer->mac_addr,
+                                                          NL80211_TDLS_SETUP,
+                                                          0, GFP_ATOMIC);
+                               peer->do_setup = false;
+                               priv->check_tdls_tx = false;
+                       } else if (peer->failure_count <
+                                  MWIFIEX_TDLS_MAX_FAIL_COUNT &&
+                                  peer->do_discover) {
+                               mwifiex_send_tdls_data_frame(priv,
+                                                            peer->mac_addr,
+                                                   WLAN_TDLS_DISCOVERY_REQUEST,
+                                                            1, 0, NULL, 0);
+                               peer->do_discover = false;
+                       }
+               }
+       }
+       spin_unlock_irqrestore(&priv->auto_tdls_lock, flags);
+
+       return 0;
+}
+
+void mwifiex_flush_auto_tdls_list(struct mwifiex_private *priv)
+{
+       struct mwifiex_auto_tdls_peer *peer, *tmp_node;
+       unsigned long flags;
+
+       spin_lock_irqsave(&priv->auto_tdls_lock, flags);
+       list_for_each_entry_safe(peer, tmp_node, &priv->auto_tdls_list, list) {
+               list_del(&peer->list);
+               kfree(peer);
+       }
+
+       INIT_LIST_HEAD(&priv->auto_tdls_list);
+       spin_unlock_irqrestore(&priv->auto_tdls_lock, flags);
+       priv->check_tdls_tx = false;
+}
+
+void mwifiex_add_auto_tdls_peer(struct mwifiex_private *priv, const u8 *mac)
+{
+       struct mwifiex_auto_tdls_peer *tdls_peer;
+       unsigned long flags;
+
+       if (!priv->adapter->auto_tdls)
+               return;
+
+       spin_lock_irqsave(&priv->auto_tdls_lock, flags);
+       list_for_each_entry(tdls_peer, &priv->auto_tdls_list, list) {
+               if (!memcmp(tdls_peer->mac_addr, mac, ETH_ALEN)) {
+                       tdls_peer->tdls_status = TDLS_SETUP_INPROGRESS;
+                       tdls_peer->rssi_jiffies = jiffies;
+                       spin_unlock_irqrestore(&priv->auto_tdls_lock, flags);
+                       return;
+               }
+       }
+
+       /* create new TDLS peer */
+       tdls_peer = kzalloc(sizeof(*tdls_peer), GFP_ATOMIC);
+       if (tdls_peer) {
+               ether_addr_copy(tdls_peer->mac_addr, mac);
+               tdls_peer->tdls_status = TDLS_SETUP_INPROGRESS;
+               tdls_peer->rssi_jiffies = jiffies;
+               INIT_LIST_HEAD(&tdls_peer->list);
+               list_add_tail(&tdls_peer->list, &priv->auto_tdls_list);
+               mwifiex_dbg(priv->adapter, INFO,
+                           "Add auto TDLS peer= %pM to list\n", mac);
+       }
+
+       spin_unlock_irqrestore(&priv->auto_tdls_lock, flags);
+}
+
+void mwifiex_auto_tdls_update_peer_status(struct mwifiex_private *priv,
+                                         const u8 *mac, u8 link_status)
+{
+       struct mwifiex_auto_tdls_peer *peer;
+       unsigned long flags;
+
+       if (!priv->adapter->auto_tdls)
+               return;
+
+       spin_lock_irqsave(&priv->auto_tdls_lock, flags);
+       list_for_each_entry(peer, &priv->auto_tdls_list, list) {
+               if (!memcmp(peer->mac_addr, mac, ETH_ALEN)) {
+                       if ((link_status == TDLS_NOT_SETUP) &&
+                           (peer->tdls_status == TDLS_SETUP_INPROGRESS))
+                               peer->failure_count++;
+                       else if (mwifiex_is_tdls_link_setup(link_status))
+                               peer->failure_count = 0;
+
+                       peer->tdls_status = link_status;
+                       break;
+               }
+       }
+       spin_unlock_irqrestore(&priv->auto_tdls_lock, flags);
+}
+
+void mwifiex_auto_tdls_update_peer_signal(struct mwifiex_private *priv,
+                                         u8 *mac, s8 snr, s8 nflr)
+{
+       struct mwifiex_auto_tdls_peer *peer;
+       unsigned long flags;
+
+       if (!priv->adapter->auto_tdls)
+               return;
+
+       spin_lock_irqsave(&priv->auto_tdls_lock, flags);
+       list_for_each_entry(peer, &priv->auto_tdls_list, list) {
+               if (!memcmp(peer->mac_addr, mac, ETH_ALEN)) {
+                       peer->rssi = nflr - snr;
+                       peer->rssi_jiffies = jiffies;
+                       break;
+               }
+       }
+       spin_unlock_irqrestore(&priv->auto_tdls_lock, flags);
+}
+
+void mwifiex_check_auto_tdls(unsigned long context)
+{
+       struct mwifiex_private *priv = (struct mwifiex_private *)context;
+       struct mwifiex_auto_tdls_peer *tdls_peer;
+       unsigned long flags;
+       u16 reason = WLAN_REASON_TDLS_TEARDOWN_UNSPECIFIED;
+
+       if (WARN_ON_ONCE(!priv || !priv->adapter)) {
+               pr_err("mwifiex: %s: adapter or private structure is NULL\n",
+                      __func__);
+               return;
+       }
+
+       if (unlikely(!priv->adapter->auto_tdls))
+               return;
+
+       if (!priv->auto_tdls_timer_active) {
+               mwifiex_dbg(priv->adapter, INFO,
+                           "auto TDLS timer inactive; return");
+               return;
+       }
+
+       priv->check_tdls_tx = false;
+
+       if (list_empty(&priv->auto_tdls_list)) {
+               mod_timer(&priv->auto_tdls_timer,
+                         jiffies +
+                         msecs_to_jiffies(MWIFIEX_TIMER_10S));
+               return;
+       }
+
+       spin_lock_irqsave(&priv->auto_tdls_lock, flags);
+       list_for_each_entry(tdls_peer, &priv->auto_tdls_list, list) {
+               if ((jiffies - tdls_peer->rssi_jiffies) >
+                   (MWIFIEX_AUTO_TDLS_IDLE_TIME * HZ)) {
+                       tdls_peer->rssi = 0;
+                       tdls_peer->do_discover = true;
+                       priv->check_tdls_tx = true;
+               }
+
+               if (((tdls_peer->rssi >= MWIFIEX_TDLS_RSSI_LOW) ||
+                    !tdls_peer->rssi) &&
+                   mwifiex_is_tdls_link_setup(tdls_peer->tdls_status)) {
+                       tdls_peer->tdls_status = TDLS_LINK_TEARDOWN;
+                       mwifiex_dbg(priv->adapter, MSG,
+                                   "teardown TDLS link,peer=%pM rssi=%d\n",
+                                   tdls_peer->mac_addr, -tdls_peer->rssi);
+                       tdls_peer->do_discover = true;
+                       priv->check_tdls_tx = true;
+                       cfg80211_tdls_oper_request(priv->netdev,
+                                                  tdls_peer->mac_addr,
+                                                  NL80211_TDLS_TEARDOWN,
+                                                  reason, GFP_ATOMIC);
+               } else if (tdls_peer->rssi &&
+                          tdls_peer->rssi <= MWIFIEX_TDLS_RSSI_HIGH &&
+                          tdls_peer->tdls_status == TDLS_NOT_SETUP &&
+                          tdls_peer->failure_count <
+                          MWIFIEX_TDLS_MAX_FAIL_COUNT) {
+                               priv->check_tdls_tx = true;
+                               tdls_peer->do_setup = true;
+                               mwifiex_dbg(priv->adapter, INFO,
+                                           "check TDLS with peer=%pM\t"
+                                           "rssi=%d\n", tdls_peer->mac_addr,
+                                           tdls_peer->rssi);
+               }
+       }
+       spin_unlock_irqrestore(&priv->auto_tdls_lock, flags);
+
+       mod_timer(&priv->auto_tdls_timer,
+                 jiffies + msecs_to_jiffies(MWIFIEX_TIMER_10S));
+}
+
+void mwifiex_setup_auto_tdls_timer(struct mwifiex_private *priv)
+{
+       setup_timer(&priv->auto_tdls_timer, mwifiex_check_auto_tdls,
+                   (unsigned long)priv);
+       priv->auto_tdls_timer_active = true;
+       mod_timer(&priv->auto_tdls_timer,
+                 jiffies + msecs_to_jiffies(MWIFIEX_TIMER_10S));
+}
+
+void mwifiex_clean_auto_tdls(struct mwifiex_private *priv)
+{
+       if (ISSUPP_TDLS_ENABLED(priv->adapter->fw_cap_info) &&
+           priv->adapter->auto_tdls &&
+           priv->bss_type == MWIFIEX_BSS_TYPE_STA) {
+               priv->auto_tdls_timer_active = false;
+               del_timer(&priv->auto_tdls_timer);
+               mwifiex_flush_auto_tdls_list(priv);
+       }
+}
+
+static int mwifiex_config_tdls(struct mwifiex_private *priv, u8 enable)
+{
+       struct mwifiex_tdls_config config;
+
+       config.enable = cpu_to_le16(enable);
+       return mwifiex_send_cmd(priv, HostCmd_CMD_TDLS_CONFIG,
+                               ACT_TDLS_CS_ENABLE_CONFIG, 0, &config, true);
+}
+
+int mwifiex_config_tdls_enable(struct mwifiex_private *priv)
+{
+       return mwifiex_config_tdls(priv, true);
+}
+
+int mwifiex_config_tdls_disable(struct mwifiex_private *priv)
+{
+       return mwifiex_config_tdls(priv, false);
+}
+
+int mwifiex_config_tdls_cs_params(struct mwifiex_private *priv)
+{
+       struct mwifiex_tdls_config_cs_params config_tdls_cs_params;
+
+       config_tdls_cs_params.unit_time = MWIFIEX_DEF_CS_UNIT_TIME;
+       config_tdls_cs_params.thr_otherlink = MWIFIEX_DEF_CS_THR_OTHERLINK;
+       config_tdls_cs_params.thr_directlink = MWIFIEX_DEF_THR_DIRECTLINK;
+
+       return mwifiex_send_cmd(priv, HostCmd_CMD_TDLS_CONFIG,
+                               ACT_TDLS_CS_PARAMS, 0,
+                               &config_tdls_cs_params, true);
+}
+
+int mwifiex_stop_tdls_cs(struct mwifiex_private *priv, const u8 *peer_mac)
+{
+       struct mwifiex_tdls_stop_cs_params stop_tdls_cs_params;
+
+       ether_addr_copy(stop_tdls_cs_params.peer_mac, peer_mac);
+
+       return mwifiex_send_cmd(priv, HostCmd_CMD_TDLS_CONFIG,
+                               ACT_TDLS_CS_STOP, 0,
+                               &stop_tdls_cs_params, true);
+}
+
+int mwifiex_start_tdls_cs(struct mwifiex_private *priv, const u8 *peer_mac,
+                         u8 primary_chan, u8 second_chan_offset, u8 band)
+{
+       struct mwifiex_tdls_init_cs_params start_tdls_cs_params;
+
+       ether_addr_copy(start_tdls_cs_params.peer_mac, peer_mac);
+       start_tdls_cs_params.primary_chan = primary_chan;
+       start_tdls_cs_params.second_chan_offset = second_chan_offset;
+       start_tdls_cs_params.band = band;
+
+       start_tdls_cs_params.switch_time = cpu_to_le16(MWIFIEX_DEF_CS_TIME);
+       start_tdls_cs_params.switch_timeout =
+                                       cpu_to_le16(MWIFIEX_DEF_CS_TIMEOUT);
+       start_tdls_cs_params.reg_class = MWIFIEX_DEF_CS_REG_CLASS;
+       start_tdls_cs_params.periodicity = MWIFIEX_DEF_CS_PERIODICITY;
+
+       return mwifiex_send_cmd(priv, HostCmd_CMD_TDLS_CONFIG,
+                               ACT_TDLS_CS_INIT, 0,
+                               &start_tdls_cs_params, true);
+}
diff --git a/drivers/net/wireless/marvell/mwifiex/txrx.c b/drivers/net/wireless/marvell/mwifiex/txrx.c
new file mode 100644 (file)
index 0000000..bf6182b
--- /dev/null
@@ -0,0 +1,386 @@
+/*
+ * Marvell Wireless LAN device driver: generic TX/RX data handling
+ *
+ * Copyright (C) 2011-2014, Marvell International Ltd.
+ *
+ * This software file (the "File") is distributed by Marvell International
+ * Ltd. under the terms of the GNU General Public License Version 2, June 1991
+ * (the "License").  You may use, redistribute and/or modify this File in
+ * accordance with the terms and conditions of the License, a copy of which
+ * is available by writing to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the
+ * worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
+ *
+ * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
+ * ARE EXPRESSLY DISCLAIMED.  The License provides additional details about
+ * this warranty disclaimer.
+ */
+
+#include "decl.h"
+#include "ioctl.h"
+#include "util.h"
+#include "fw.h"
+#include "main.h"
+#include "wmm.h"
+
+/*
+ * This function processes the received buffer.
+ *
+ * Main responsibility of this function is to parse the RxPD to
+ * identify the correct interface this packet is headed for and
+ * forwarding it to the associated handling function, where the
+ * packet will be further processed and sent to kernel/upper layer
+ * if required.
+ */
+int mwifiex_handle_rx_packet(struct mwifiex_adapter *adapter,
+                            struct sk_buff *skb)
+{
+       struct mwifiex_private *priv =
+               mwifiex_get_priv(adapter, MWIFIEX_BSS_ROLE_ANY);
+       struct rxpd *local_rx_pd;
+       struct mwifiex_rxinfo *rx_info = MWIFIEX_SKB_RXCB(skb);
+       int ret;
+
+       local_rx_pd = (struct rxpd *) (skb->data);
+       /* Get the BSS number from rxpd, get corresponding priv */
+       priv = mwifiex_get_priv_by_id(adapter, local_rx_pd->bss_num &
+                                     BSS_NUM_MASK, local_rx_pd->bss_type);
+       if (!priv)
+               priv = mwifiex_get_priv(adapter, MWIFIEX_BSS_ROLE_ANY);
+
+       if (!priv) {
+               mwifiex_dbg(adapter, ERROR,
+                           "data: priv not found. Drop RX packet\n");
+               dev_kfree_skb_any(skb);
+               return -1;
+       }
+
+       mwifiex_dbg_dump(adapter, DAT_D, "rx pkt:", skb->data,
+                        min_t(size_t, skb->len, DEBUG_DUMP_DATA_MAX_LEN));
+
+       memset(rx_info, 0, sizeof(*rx_info));
+       rx_info->bss_num = priv->bss_num;
+       rx_info->bss_type = priv->bss_type;
+
+       if (priv->bss_role == MWIFIEX_BSS_ROLE_UAP)
+               ret = mwifiex_process_uap_rx_packet(priv, skb);
+       else
+               ret = mwifiex_process_sta_rx_packet(priv, skb);
+
+       return ret;
+}
+EXPORT_SYMBOL_GPL(mwifiex_handle_rx_packet);
+
+/*
+ * This function sends a packet to device.
+ *
+ * It processes the packet to add the TxPD, checks condition and
+ * sends the processed packet to firmware for transmission.
+ *
+ * On successful completion, the function calls the completion callback
+ * and logs the time.
+ */
+int mwifiex_process_tx(struct mwifiex_private *priv, struct sk_buff *skb,
+                      struct mwifiex_tx_param *tx_param)
+{
+       int hroom, ret = -1;
+       struct mwifiex_adapter *adapter = priv->adapter;
+       u8 *head_ptr;
+       struct txpd *local_tx_pd = NULL;
+       struct mwifiex_sta_node *dest_node;
+       struct ethhdr *hdr = (void *)skb->data;
+
+       hroom = (adapter->iface_type == MWIFIEX_USB) ? 0 : INTF_HEADER_LEN;
+
+       if (priv->bss_role == MWIFIEX_BSS_ROLE_UAP) {
+               dest_node = mwifiex_get_sta_entry(priv, hdr->h_dest);
+               if (dest_node) {
+                       dest_node->stats.tx_bytes += skb->len;
+                       dest_node->stats.tx_packets++;
+               }
+
+               head_ptr = mwifiex_process_uap_txpd(priv, skb);
+       } else {
+               head_ptr = mwifiex_process_sta_txpd(priv, skb);
+       }
+
+       if ((adapter->data_sent || adapter->tx_lock_flag) && head_ptr) {
+               skb_queue_tail(&adapter->tx_data_q, skb);
+               atomic_inc(&adapter->tx_queued);
+               return 0;
+       }
+
+       if (head_ptr) {
+               if (GET_BSS_ROLE(priv) == MWIFIEX_BSS_ROLE_STA)
+                       local_tx_pd = (struct txpd *)(head_ptr + hroom);
+               if (adapter->iface_type == MWIFIEX_USB) {
+                       ret = adapter->if_ops.host_to_card(adapter,
+                                                          priv->usb_port,
+                                                          skb, NULL);
+               } else {
+                       ret = adapter->if_ops.host_to_card(adapter,
+                                                          MWIFIEX_TYPE_DATA,
+                                                          skb, tx_param);
+               }
+       }
+       mwifiex_dbg_dump(adapter, DAT_D, "tx pkt:", skb->data,
+                        min_t(size_t, skb->len, DEBUG_DUMP_DATA_MAX_LEN));
+
+       switch (ret) {
+       case -ENOSR:
+               mwifiex_dbg(adapter, DATA, "data: -ENOSR is returned\n");
+               break;
+       case -EBUSY:
+               if ((GET_BSS_ROLE(priv) == MWIFIEX_BSS_ROLE_STA) &&
+                   (adapter->pps_uapsd_mode) && (adapter->tx_lock_flag)) {
+                               priv->adapter->tx_lock_flag = false;
+                               if (local_tx_pd)
+                                       local_tx_pd->flags = 0;
+               }
+               mwifiex_dbg(adapter, ERROR, "data: -EBUSY is returned\n");
+               break;
+       case -1:
+               mwifiex_dbg(adapter, ERROR,
+                           "mwifiex_write_data_async failed: 0x%X\n",
+                           ret);
+               adapter->dbg.num_tx_host_to_card_failure++;
+               mwifiex_write_data_complete(adapter, skb, 0, ret);
+               break;
+       case -EINPROGRESS:
+               break;
+       case 0:
+               mwifiex_write_data_complete(adapter, skb, 0, ret);
+               break;
+       default:
+               break;
+       }
+
+       return ret;
+}
+
+static int mwifiex_host_to_card(struct mwifiex_adapter *adapter,
+                               struct sk_buff *skb,
+                               struct mwifiex_tx_param *tx_param)
+{
+       struct txpd *local_tx_pd = NULL;
+       u8 *head_ptr = skb->data;
+       int ret = 0;
+       struct mwifiex_private *priv;
+       struct mwifiex_txinfo *tx_info;
+
+       tx_info = MWIFIEX_SKB_TXCB(skb);
+       priv = mwifiex_get_priv_by_id(adapter, tx_info->bss_num,
+                                     tx_info->bss_type);
+       if (!priv) {
+               mwifiex_dbg(adapter, ERROR,
+                           "data: priv not found. Drop TX packet\n");
+               adapter->dbg.num_tx_host_to_card_failure++;
+               mwifiex_write_data_complete(adapter, skb, 0, 0);
+               return ret;
+       }
+       if (GET_BSS_ROLE(priv) == MWIFIEX_BSS_ROLE_STA) {
+               if (adapter->iface_type == MWIFIEX_USB)
+                       local_tx_pd = (struct txpd *)head_ptr;
+               else
+                       local_tx_pd = (struct txpd *) (head_ptr +
+                               INTF_HEADER_LEN);
+       }
+
+       if (adapter->iface_type == MWIFIEX_USB) {
+               ret = adapter->if_ops.host_to_card(adapter,
+                                                  priv->usb_port,
+                                                  skb, NULL);
+       } else {
+               ret = adapter->if_ops.host_to_card(adapter,
+                                                  MWIFIEX_TYPE_DATA,
+                                                  skb, tx_param);
+       }
+       switch (ret) {
+       case -ENOSR:
+               mwifiex_dbg(adapter, ERROR, "data: -ENOSR is returned\n");
+               break;
+       case -EBUSY:
+               if ((GET_BSS_ROLE(priv) == MWIFIEX_BSS_ROLE_STA) &&
+                   (adapter->pps_uapsd_mode) &&
+                   (adapter->tx_lock_flag)) {
+                       priv->adapter->tx_lock_flag = false;
+                       if (local_tx_pd)
+                               local_tx_pd->flags = 0;
+               }
+               skb_queue_head(&adapter->tx_data_q, skb);
+               if (tx_info->flags & MWIFIEX_BUF_FLAG_AGGR_PKT)
+                       atomic_add(tx_info->aggr_num, &adapter->tx_queued);
+               else
+                       atomic_inc(&adapter->tx_queued);
+               mwifiex_dbg(adapter, ERROR, "data: -EBUSY is returned\n");
+               break;
+       case -1:
+               mwifiex_dbg(adapter, ERROR,
+                           "mwifiex_write_data_async failed: 0x%X\n", ret);
+               adapter->dbg.num_tx_host_to_card_failure++;
+               mwifiex_write_data_complete(adapter, skb, 0, ret);
+               break;
+       case -EINPROGRESS:
+               break;
+       case 0:
+               mwifiex_write_data_complete(adapter, skb, 0, ret);
+               break;
+       default:
+               break;
+       }
+       return ret;
+}
+
+static int
+mwifiex_dequeue_tx_queue(struct mwifiex_adapter *adapter)
+{
+       struct sk_buff *skb, *skb_next;
+       struct mwifiex_txinfo *tx_info;
+       struct mwifiex_tx_param tx_param;
+
+       skb = skb_dequeue(&adapter->tx_data_q);
+       if (!skb)
+               return -1;
+
+       tx_info = MWIFIEX_SKB_TXCB(skb);
+       if (tx_info->flags & MWIFIEX_BUF_FLAG_AGGR_PKT)
+               atomic_sub(tx_info->aggr_num, &adapter->tx_queued);
+       else
+               atomic_dec(&adapter->tx_queued);
+
+       if (!skb_queue_empty(&adapter->tx_data_q))
+               skb_next = skb_peek(&adapter->tx_data_q);
+       else
+               skb_next = NULL;
+       tx_param.next_pkt_len = ((skb_next) ? skb_next->len : 0);
+       if (!tx_param.next_pkt_len) {
+               if (!mwifiex_wmm_lists_empty(adapter))
+                       tx_param.next_pkt_len = 1;
+       }
+       return mwifiex_host_to_card(adapter, skb, &tx_param);
+}
+
+void
+mwifiex_process_tx_queue(struct mwifiex_adapter *adapter)
+{
+       do {
+               if (adapter->data_sent || adapter->tx_lock_flag)
+                       break;
+               if (mwifiex_dequeue_tx_queue(adapter))
+                       break;
+       } while (!skb_queue_empty(&adapter->tx_data_q));
+}
+
+/*
+ * Packet send completion callback handler.
+ *
+ * It either frees the buffer directly or forwards it to another
+ * completion callback which checks conditions, updates statistics,
+ * wakes up stalled traffic queue if required, and then frees the buffer.
+ */
+int mwifiex_write_data_complete(struct mwifiex_adapter *adapter,
+                               struct sk_buff *skb, int aggr, int status)
+{
+       struct mwifiex_private *priv;
+       struct mwifiex_txinfo *tx_info;
+       struct netdev_queue *txq;
+       int index;
+
+       if (!skb)
+               return 0;
+
+       tx_info = MWIFIEX_SKB_TXCB(skb);
+       priv = mwifiex_get_priv_by_id(adapter, tx_info->bss_num,
+                                     tx_info->bss_type);
+       if (!priv)
+               goto done;
+
+       mwifiex_set_trans_start(priv->netdev);
+       if (!status) {
+               priv->stats.tx_packets++;
+               priv->stats.tx_bytes += tx_info->pkt_len;
+               if (priv->tx_timeout_cnt)
+                       priv->tx_timeout_cnt = 0;
+       } else {
+               priv->stats.tx_errors++;
+       }
+
+       if (tx_info->flags & MWIFIEX_BUF_FLAG_BRIDGED_PKT)
+               atomic_dec_return(&adapter->pending_bridged_pkts);
+
+       if (tx_info->flags & MWIFIEX_BUF_FLAG_AGGR_PKT)
+               goto done;
+
+       if (aggr)
+               /* For skb_aggr, do not wake up tx queue */
+               goto done;
+
+       atomic_dec(&adapter->tx_pending);
+
+       index = mwifiex_1d_to_wmm_queue[skb->priority];
+       if (atomic_dec_return(&priv->wmm_tx_pending[index]) < LOW_TX_PENDING) {
+               txq = netdev_get_tx_queue(priv->netdev, index);
+               if (netif_tx_queue_stopped(txq)) {
+                       netif_tx_wake_queue(txq);
+                       mwifiex_dbg(adapter, DATA, "wake queue: %d\n", index);
+               }
+       }
+done:
+       dev_kfree_skb_any(skb);
+
+       return 0;
+}
+EXPORT_SYMBOL_GPL(mwifiex_write_data_complete);
+
+void mwifiex_parse_tx_status_event(struct mwifiex_private *priv,
+                                  void *event_body)
+{
+       struct tx_status_event *tx_status = (void *)priv->adapter->event_body;
+       struct sk_buff *ack_skb;
+       unsigned long flags;
+       struct mwifiex_txinfo *tx_info;
+
+       if (!tx_status->tx_token_id)
+               return;
+
+       spin_lock_irqsave(&priv->ack_status_lock, flags);
+       ack_skb = idr_find(&priv->ack_status_frames, tx_status->tx_token_id);
+       if (ack_skb)
+               idr_remove(&priv->ack_status_frames, tx_status->tx_token_id);
+       spin_unlock_irqrestore(&priv->ack_status_lock, flags);
+
+       if (ack_skb) {
+               tx_info = MWIFIEX_SKB_TXCB(ack_skb);
+
+               if (tx_info->flags & MWIFIEX_BUF_FLAG_EAPOL_TX_STATUS) {
+                       /* consumes ack_skb */
+                       skb_complete_wifi_ack(ack_skb, !tx_status->status);
+               } else {
+                       /* Remove broadcast address which was added by driver */
+                       memmove(ack_skb->data +
+                               sizeof(struct ieee80211_hdr_3addr) +
+                               MWIFIEX_MGMT_FRAME_HEADER_SIZE + sizeof(u16),
+                               ack_skb->data +
+                               sizeof(struct ieee80211_hdr_3addr) +
+                               MWIFIEX_MGMT_FRAME_HEADER_SIZE + sizeof(u16) +
+                               ETH_ALEN, ack_skb->len -
+                               (sizeof(struct ieee80211_hdr_3addr) +
+                               MWIFIEX_MGMT_FRAME_HEADER_SIZE + sizeof(u16) +
+                               ETH_ALEN));
+                       ack_skb->len = ack_skb->len - ETH_ALEN;
+                       /* Remove driver's proprietary header including 2 bytes
+                        * of packet length and pass actual management frame buffer
+                        * to cfg80211.
+                        */
+                       cfg80211_mgmt_tx_status(&priv->wdev, tx_info->cookie,
+                                               ack_skb->data +
+                                               MWIFIEX_MGMT_FRAME_HEADER_SIZE +
+                                               sizeof(u16), ack_skb->len -
+                                               (MWIFIEX_MGMT_FRAME_HEADER_SIZE
+                                                + sizeof(u16)),
+                                               !tx_status->status, GFP_ATOMIC);
+                       dev_kfree_skb_any(ack_skb);
+               }
+       }
+}
diff --git a/drivers/net/wireless/marvell/mwifiex/uap_cmd.c b/drivers/net/wireless/marvell/mwifiex/uap_cmd.c
new file mode 100644 (file)
index 0000000..759a6ad
--- /dev/null
@@ -0,0 +1,885 @@
+/*
+ * Marvell Wireless LAN device driver: AP specific command handling
+ *
+ * Copyright (C) 2012-2014, Marvell International Ltd.
+ *
+ * This software file (the "File") is distributed by Marvell International
+ * Ltd. under the terms of the GNU General Public License Version 2, June 1991
+ * (the "License").  You may use, redistribute and/or modify this File in
+ * accordance with the terms and conditions of the License, a copy of which
+ * is available by writing to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the
+ * worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
+ *
+ * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
+ * ARE EXPRESSLY DISCLAIMED.  The License provides additional details about
+ * this warranty disclaimer.
+ */
+
+#include "main.h"
+#include "11ac.h"
+
+/* This function parses security related parameters from cfg80211_ap_settings
+ * and sets into FW understandable bss_config structure.
+ */
+int mwifiex_set_secure_params(struct mwifiex_private *priv,
+                             struct mwifiex_uap_bss_param *bss_config,
+                             struct cfg80211_ap_settings *params) {
+       int i;
+       struct mwifiex_wep_key wep_key;
+
+       if (!params->privacy) {
+               bss_config->protocol = PROTOCOL_NO_SECURITY;
+               bss_config->key_mgmt = KEY_MGMT_NONE;
+               bss_config->wpa_cfg.length = 0;
+               priv->sec_info.wep_enabled = 0;
+               priv->sec_info.wpa_enabled = 0;
+               priv->sec_info.wpa2_enabled = 0;
+
+               return 0;
+       }
+
+       switch (params->auth_type) {
+       case NL80211_AUTHTYPE_OPEN_SYSTEM:
+               bss_config->auth_mode = WLAN_AUTH_OPEN;
+               break;
+       case NL80211_AUTHTYPE_SHARED_KEY:
+               bss_config->auth_mode = WLAN_AUTH_SHARED_KEY;
+               break;
+       case NL80211_AUTHTYPE_NETWORK_EAP:
+               bss_config->auth_mode = WLAN_AUTH_LEAP;
+               break;
+       default:
+               bss_config->auth_mode = MWIFIEX_AUTH_MODE_AUTO;
+               break;
+       }
+
+       bss_config->key_mgmt_operation |= KEY_MGMT_ON_HOST;
+
+       for (i = 0; i < params->crypto.n_akm_suites; i++) {
+               switch (params->crypto.akm_suites[i]) {
+               case WLAN_AKM_SUITE_8021X:
+                       if (params->crypto.wpa_versions &
+                           NL80211_WPA_VERSION_1) {
+                               bss_config->protocol = PROTOCOL_WPA;
+                               bss_config->key_mgmt = KEY_MGMT_EAP;
+                       }
+                       if (params->crypto.wpa_versions &
+                           NL80211_WPA_VERSION_2) {
+                               bss_config->protocol |= PROTOCOL_WPA2;
+                               bss_config->key_mgmt = KEY_MGMT_EAP;
+                       }
+                       break;
+               case WLAN_AKM_SUITE_PSK:
+                       if (params->crypto.wpa_versions &
+                           NL80211_WPA_VERSION_1) {
+                               bss_config->protocol = PROTOCOL_WPA;
+                               bss_config->key_mgmt = KEY_MGMT_PSK;
+                       }
+                       if (params->crypto.wpa_versions &
+                           NL80211_WPA_VERSION_2) {
+                               bss_config->protocol |= PROTOCOL_WPA2;
+                               bss_config->key_mgmt = KEY_MGMT_PSK;
+                       }
+                       break;
+               default:
+                       break;
+               }
+       }
+       for (i = 0; i < params->crypto.n_ciphers_pairwise; i++) {
+               switch (params->crypto.ciphers_pairwise[i]) {
+               case WLAN_CIPHER_SUITE_WEP40:
+               case WLAN_CIPHER_SUITE_WEP104:
+                       break;
+               case WLAN_CIPHER_SUITE_TKIP:
+                       if (params->crypto.wpa_versions & NL80211_WPA_VERSION_1)
+                               bss_config->wpa_cfg.pairwise_cipher_wpa |=
+                                                               CIPHER_TKIP;
+                       if (params->crypto.wpa_versions & NL80211_WPA_VERSION_2)
+                               bss_config->wpa_cfg.pairwise_cipher_wpa2 |=
+                                                               CIPHER_TKIP;
+                       break;
+               case WLAN_CIPHER_SUITE_CCMP:
+                       if (params->crypto.wpa_versions & NL80211_WPA_VERSION_1)
+                               bss_config->wpa_cfg.pairwise_cipher_wpa |=
+                                                               CIPHER_AES_CCMP;
+                       if (params->crypto.wpa_versions & NL80211_WPA_VERSION_2)
+                               bss_config->wpa_cfg.pairwise_cipher_wpa2 |=
+                                                               CIPHER_AES_CCMP;
+               default:
+                       break;
+               }
+       }
+
+       switch (params->crypto.cipher_group) {
+       case WLAN_CIPHER_SUITE_WEP40:
+       case WLAN_CIPHER_SUITE_WEP104:
+               if (priv->sec_info.wep_enabled) {
+                       bss_config->protocol = PROTOCOL_STATIC_WEP;
+                       bss_config->key_mgmt = KEY_MGMT_NONE;
+                       bss_config->wpa_cfg.length = 0;
+
+                       for (i = 0; i < NUM_WEP_KEYS; i++) {
+                               wep_key = priv->wep_key[i];
+                               bss_config->wep_cfg[i].key_index = i;
+
+                               if (priv->wep_key_curr_index == i)
+                                       bss_config->wep_cfg[i].is_default = 1;
+                               else
+                                       bss_config->wep_cfg[i].is_default = 0;
+
+                               bss_config->wep_cfg[i].length =
+                                                            wep_key.key_length;
+                               memcpy(&bss_config->wep_cfg[i].key,
+                                      &wep_key.key_material,
+                                      wep_key.key_length);
+                       }
+               }
+               break;
+       case WLAN_CIPHER_SUITE_TKIP:
+               bss_config->wpa_cfg.group_cipher = CIPHER_TKIP;
+               break;
+       case WLAN_CIPHER_SUITE_CCMP:
+               bss_config->wpa_cfg.group_cipher = CIPHER_AES_CCMP;
+               break;
+       default:
+               break;
+       }
+
+       return 0;
+}
+
+/* This function updates 11n related parameters from IE and sets them into
+ * bss_config structure.
+ */
+void
+mwifiex_set_ht_params(struct mwifiex_private *priv,
+                     struct mwifiex_uap_bss_param *bss_cfg,
+                     struct cfg80211_ap_settings *params)
+{
+       const u8 *ht_ie;
+       u16 cap_info;
+
+       if (!ISSUPP_11NENABLED(priv->adapter->fw_cap_info))
+               return;
+
+       ht_ie = cfg80211_find_ie(WLAN_EID_HT_CAPABILITY, params->beacon.tail,
+                                params->beacon.tail_len);
+       if (ht_ie) {
+               memcpy(&bss_cfg->ht_cap, ht_ie + 2,
+                      sizeof(struct ieee80211_ht_cap));
+               cap_info = le16_to_cpu(bss_cfg->ht_cap.cap_info);
+               memset(&bss_cfg->ht_cap.mcs, 0,
+                      priv->adapter->number_of_antenna);
+               switch (GET_RXSTBC(cap_info)) {
+               case MWIFIEX_RX_STBC1:
+                       /* HT_CAP 1X1 mode */
+                       bss_cfg->ht_cap.mcs.rx_mask[0] = 0xff;
+                       break;
+               case MWIFIEX_RX_STBC12: /* fall through */
+               case MWIFIEX_RX_STBC123:
+                       /* HT_CAP 2X2 mode */
+                       bss_cfg->ht_cap.mcs.rx_mask[0] = 0xff;
+                       bss_cfg->ht_cap.mcs.rx_mask[1] = 0xff;
+                       break;
+               default:
+                       mwifiex_dbg(priv->adapter, WARN,
+                                   "Unsupported RX-STBC, default to 2x2\n");
+                       bss_cfg->ht_cap.mcs.rx_mask[0] = 0xff;
+                       bss_cfg->ht_cap.mcs.rx_mask[1] = 0xff;
+                       break;
+               }
+               priv->ap_11n_enabled = 1;
+       } else {
+               memset(&bss_cfg->ht_cap , 0, sizeof(struct ieee80211_ht_cap));
+               bss_cfg->ht_cap.cap_info = cpu_to_le16(MWIFIEX_DEF_HT_CAP);
+               bss_cfg->ht_cap.ampdu_params_info = MWIFIEX_DEF_AMPDU;
+       }
+
+       return;
+}
+
+/* This function updates 11ac related parameters from IE
+ * and sets them into bss_config structure.
+ */
+void mwifiex_set_vht_params(struct mwifiex_private *priv,
+                           struct mwifiex_uap_bss_param *bss_cfg,
+                           struct cfg80211_ap_settings *params)
+{
+       const u8 *vht_ie;
+
+       vht_ie = cfg80211_find_ie(WLAN_EID_VHT_CAPABILITY, params->beacon.tail,
+                                 params->beacon.tail_len);
+       if (vht_ie) {
+               memcpy(&bss_cfg->vht_cap, vht_ie + 2,
+                      sizeof(struct ieee80211_vht_cap));
+               priv->ap_11ac_enabled = 1;
+       } else {
+               priv->ap_11ac_enabled = 0;
+       }
+
+       return;
+}
+
+/* This function updates 11ac related parameters from IE
+ * and sets them into bss_config structure.
+ */
+void mwifiex_set_tpc_params(struct mwifiex_private *priv,
+                           struct mwifiex_uap_bss_param *bss_cfg,
+                           struct cfg80211_ap_settings *params)
+{
+       const u8 *tpc_ie;
+
+       tpc_ie = cfg80211_find_ie(WLAN_EID_TPC_REQUEST, params->beacon.tail,
+                                 params->beacon.tail_len);
+       if (tpc_ie)
+               bss_cfg->power_constraint = *(tpc_ie + 2);
+       else
+               bss_cfg->power_constraint = 0;
+}
+
+/* Enable VHT only when cfg80211_ap_settings has VHT IE.
+ * Otherwise disable VHT.
+ */
+void mwifiex_set_vht_width(struct mwifiex_private *priv,
+                          enum nl80211_chan_width width,
+                          bool ap_11ac_enable)
+{
+       struct mwifiex_adapter *adapter = priv->adapter;
+       struct mwifiex_11ac_vht_cfg vht_cfg;
+
+       vht_cfg.band_config = VHT_CFG_5GHZ;
+       vht_cfg.cap_info = adapter->hw_dot_11ac_dev_cap;
+
+       if (!ap_11ac_enable) {
+               vht_cfg.mcs_tx_set = DISABLE_VHT_MCS_SET;
+               vht_cfg.mcs_rx_set = DISABLE_VHT_MCS_SET;
+       } else {
+               vht_cfg.mcs_tx_set = DEFAULT_VHT_MCS_SET;
+               vht_cfg.mcs_rx_set = DEFAULT_VHT_MCS_SET;
+       }
+
+       vht_cfg.misc_config  = VHT_CAP_UAP_ONLY;
+
+       if (ap_11ac_enable && width >= NL80211_CHAN_WIDTH_80)
+               vht_cfg.misc_config |= VHT_BW_80_160_80P80;
+
+       mwifiex_send_cmd(priv, HostCmd_CMD_11AC_CFG,
+                        HostCmd_ACT_GEN_SET, 0, &vht_cfg, true);
+
+       return;
+}
+
+/* This function finds supported rates IE from beacon parameter and sets
+ * these rates into bss_config structure.
+ */
+void
+mwifiex_set_uap_rates(struct mwifiex_uap_bss_param *bss_cfg,
+                     struct cfg80211_ap_settings *params)
+{
+       struct ieee_types_header *rate_ie;
+       int var_offset = offsetof(struct ieee80211_mgmt, u.beacon.variable);
+       const u8 *var_pos = params->beacon.head + var_offset;
+       int len = params->beacon.head_len - var_offset;
+       u8 rate_len = 0;
+
+       rate_ie = (void *)cfg80211_find_ie(WLAN_EID_SUPP_RATES, var_pos, len);
+       if (rate_ie) {
+               memcpy(bss_cfg->rates, rate_ie + 1, rate_ie->len);
+               rate_len = rate_ie->len;
+       }
+
+       rate_ie = (void *)cfg80211_find_ie(WLAN_EID_EXT_SUPP_RATES,
+                                          params->beacon.tail,
+                                          params->beacon.tail_len);
+       if (rate_ie)
+               memcpy(bss_cfg->rates + rate_len, rate_ie + 1, rate_ie->len);
+
+       return;
+}
+
+/* This function initializes some of mwifiex_uap_bss_param variables.
+ * This helps FW in ignoring invalid values. These values may or may not
+ * be get updated to valid ones at later stage.
+ */
+void mwifiex_set_sys_config_invalid_data(struct mwifiex_uap_bss_param *config)
+{
+       config->bcast_ssid_ctl = 0x7F;
+       config->radio_ctl = 0x7F;
+       config->dtim_period = 0x7F;
+       config->beacon_period = 0x7FFF;
+       config->auth_mode = 0x7F;
+       config->rts_threshold = 0x7FFF;
+       config->frag_threshold = 0x7FFF;
+       config->retry_limit = 0x7F;
+       config->qos_info = 0xFF;
+}
+
+/* This function parses BSS related parameters from structure
+ * and prepares TLVs specific to WPA/WPA2 security.
+ * These TLVs are appended to command buffer.
+ */
+static void
+mwifiex_uap_bss_wpa(u8 **tlv_buf, void *cmd_buf, u16 *param_size)
+{
+       struct host_cmd_tlv_pwk_cipher *pwk_cipher;
+       struct host_cmd_tlv_gwk_cipher *gwk_cipher;
+       struct host_cmd_tlv_passphrase *passphrase;
+       struct host_cmd_tlv_akmp *tlv_akmp;
+       struct mwifiex_uap_bss_param *bss_cfg = cmd_buf;
+       u16 cmd_size = *param_size;
+       u8 *tlv = *tlv_buf;
+
+       tlv_akmp = (struct host_cmd_tlv_akmp *)tlv;
+       tlv_akmp->header.type = cpu_to_le16(TLV_TYPE_UAP_AKMP);
+       tlv_akmp->header.len = cpu_to_le16(sizeof(struct host_cmd_tlv_akmp) -
+                                       sizeof(struct mwifiex_ie_types_header));
+       tlv_akmp->key_mgmt_operation = cpu_to_le16(bss_cfg->key_mgmt_operation);
+       tlv_akmp->key_mgmt = cpu_to_le16(bss_cfg->key_mgmt);
+       cmd_size += sizeof(struct host_cmd_tlv_akmp);
+       tlv += sizeof(struct host_cmd_tlv_akmp);
+
+       if (bss_cfg->wpa_cfg.pairwise_cipher_wpa & VALID_CIPHER_BITMAP) {
+               pwk_cipher = (struct host_cmd_tlv_pwk_cipher *)tlv;
+               pwk_cipher->header.type = cpu_to_le16(TLV_TYPE_PWK_CIPHER);
+               pwk_cipher->header.len =
+                       cpu_to_le16(sizeof(struct host_cmd_tlv_pwk_cipher) -
+                                   sizeof(struct mwifiex_ie_types_header));
+               pwk_cipher->proto = cpu_to_le16(PROTOCOL_WPA);
+               pwk_cipher->cipher = bss_cfg->wpa_cfg.pairwise_cipher_wpa;
+               cmd_size += sizeof(struct host_cmd_tlv_pwk_cipher);
+               tlv += sizeof(struct host_cmd_tlv_pwk_cipher);
+       }
+
+       if (bss_cfg->wpa_cfg.pairwise_cipher_wpa2 & VALID_CIPHER_BITMAP) {
+               pwk_cipher = (struct host_cmd_tlv_pwk_cipher *)tlv;
+               pwk_cipher->header.type = cpu_to_le16(TLV_TYPE_PWK_CIPHER);
+               pwk_cipher->header.len =
+                       cpu_to_le16(sizeof(struct host_cmd_tlv_pwk_cipher) -
+                                   sizeof(struct mwifiex_ie_types_header));
+               pwk_cipher->proto = cpu_to_le16(PROTOCOL_WPA2);
+               pwk_cipher->cipher = bss_cfg->wpa_cfg.pairwise_cipher_wpa2;
+               cmd_size += sizeof(struct host_cmd_tlv_pwk_cipher);
+               tlv += sizeof(struct host_cmd_tlv_pwk_cipher);
+       }
+
+       if (bss_cfg->wpa_cfg.group_cipher & VALID_CIPHER_BITMAP) {
+               gwk_cipher = (struct host_cmd_tlv_gwk_cipher *)tlv;
+               gwk_cipher->header.type = cpu_to_le16(TLV_TYPE_GWK_CIPHER);
+               gwk_cipher->header.len =
+                       cpu_to_le16(sizeof(struct host_cmd_tlv_gwk_cipher) -
+                                   sizeof(struct mwifiex_ie_types_header));
+               gwk_cipher->cipher = bss_cfg->wpa_cfg.group_cipher;
+               cmd_size += sizeof(struct host_cmd_tlv_gwk_cipher);
+               tlv += sizeof(struct host_cmd_tlv_gwk_cipher);
+       }
+
+       if (bss_cfg->wpa_cfg.length) {
+               passphrase = (struct host_cmd_tlv_passphrase *)tlv;
+               passphrase->header.type =
+                               cpu_to_le16(TLV_TYPE_UAP_WPA_PASSPHRASE);
+               passphrase->header.len = cpu_to_le16(bss_cfg->wpa_cfg.length);
+               memcpy(passphrase->passphrase, bss_cfg->wpa_cfg.passphrase,
+                      bss_cfg->wpa_cfg.length);
+               cmd_size += sizeof(struct mwifiex_ie_types_header) +
+                           bss_cfg->wpa_cfg.length;
+               tlv += sizeof(struct mwifiex_ie_types_header) +
+                               bss_cfg->wpa_cfg.length;
+       }
+
+       *param_size = cmd_size;
+       *tlv_buf = tlv;
+
+       return;
+}
+
+/* This function parses WMM related parameters from cfg80211_ap_settings
+ * structure and updates bss_config structure.
+ */
+void
+mwifiex_set_wmm_params(struct mwifiex_private *priv,
+                      struct mwifiex_uap_bss_param *bss_cfg,
+                      struct cfg80211_ap_settings *params)
+{
+       const u8 *vendor_ie;
+       struct ieee_types_header *wmm_ie;
+       u8 wmm_oui[] = {0x00, 0x50, 0xf2, 0x02};
+
+       vendor_ie = cfg80211_find_vendor_ie(WLAN_OUI_MICROSOFT,
+                                           WLAN_OUI_TYPE_MICROSOFT_WMM,
+                                           params->beacon.tail,
+                                           params->beacon.tail_len);
+       if (vendor_ie) {
+               wmm_ie = (struct ieee_types_header *)vendor_ie;
+               memcpy(&bss_cfg->wmm_info, wmm_ie + 1,
+                      sizeof(bss_cfg->wmm_info));
+               priv->wmm_enabled = 1;
+       } else {
+               memset(&bss_cfg->wmm_info, 0, sizeof(bss_cfg->wmm_info));
+               memcpy(&bss_cfg->wmm_info.oui, wmm_oui, sizeof(wmm_oui));
+               bss_cfg->wmm_info.subtype = MWIFIEX_WMM_SUBTYPE;
+               bss_cfg->wmm_info.version = MWIFIEX_WMM_VERSION;
+               priv->wmm_enabled = 0;
+       }
+
+       bss_cfg->qos_info = 0x00;
+       return;
+}
+/* This function parses BSS related parameters from structure
+ * and prepares TLVs specific to WEP encryption.
+ * These TLVs are appended to command buffer.
+ */
+static void
+mwifiex_uap_bss_wep(u8 **tlv_buf, void *cmd_buf, u16 *param_size)
+{
+       struct host_cmd_tlv_wep_key *wep_key;
+       u16 cmd_size = *param_size;
+       int i;
+       u8 *tlv = *tlv_buf;
+       struct mwifiex_uap_bss_param *bss_cfg = cmd_buf;
+
+       for (i = 0; i < NUM_WEP_KEYS; i++) {
+               if (bss_cfg->wep_cfg[i].length &&
+                   (bss_cfg->wep_cfg[i].length == WLAN_KEY_LEN_WEP40 ||
+                    bss_cfg->wep_cfg[i].length == WLAN_KEY_LEN_WEP104)) {
+                       wep_key = (struct host_cmd_tlv_wep_key *)tlv;
+                       wep_key->header.type =
+                               cpu_to_le16(TLV_TYPE_UAP_WEP_KEY);
+                       wep_key->header.len =
+                               cpu_to_le16(bss_cfg->wep_cfg[i].length + 2);
+                       wep_key->key_index = bss_cfg->wep_cfg[i].key_index;
+                       wep_key->is_default = bss_cfg->wep_cfg[i].is_default;
+                       memcpy(wep_key->key, bss_cfg->wep_cfg[i].key,
+                              bss_cfg->wep_cfg[i].length);
+                       cmd_size += sizeof(struct mwifiex_ie_types_header) + 2 +
+                                   bss_cfg->wep_cfg[i].length;
+                       tlv += sizeof(struct mwifiex_ie_types_header) + 2 +
+                                   bss_cfg->wep_cfg[i].length;
+               }
+       }
+
+       *param_size = cmd_size;
+       *tlv_buf = tlv;
+
+       return;
+}
+
+/* This function parses BSS related parameters from structure
+ * and prepares TLVs. These TLVs are appended to command buffer.
+*/
+static int
+mwifiex_uap_bss_param_prepare(u8 *tlv, void *cmd_buf, u16 *param_size)
+{
+       struct host_cmd_tlv_dtim_period *dtim_period;
+       struct host_cmd_tlv_beacon_period *beacon_period;
+       struct host_cmd_tlv_ssid *ssid;
+       struct host_cmd_tlv_bcast_ssid *bcast_ssid;
+       struct host_cmd_tlv_channel_band *chan_band;
+       struct host_cmd_tlv_frag_threshold *frag_threshold;
+       struct host_cmd_tlv_rts_threshold *rts_threshold;
+       struct host_cmd_tlv_retry_limit *retry_limit;
+       struct host_cmd_tlv_encrypt_protocol *encrypt_protocol;
+       struct host_cmd_tlv_auth_type *auth_type;
+       struct host_cmd_tlv_rates *tlv_rates;
+       struct host_cmd_tlv_ageout_timer *ao_timer, *ps_ao_timer;
+       struct host_cmd_tlv_power_constraint *pwr_ct;
+       struct mwifiex_ie_types_htcap *htcap;
+       struct mwifiex_ie_types_wmmcap *wmm_cap;
+       struct mwifiex_uap_bss_param *bss_cfg = cmd_buf;
+       int i;
+       u16 cmd_size = *param_size;
+
+       if (bss_cfg->ssid.ssid_len) {
+               ssid = (struct host_cmd_tlv_ssid *)tlv;
+               ssid->header.type = cpu_to_le16(TLV_TYPE_UAP_SSID);
+               ssid->header.len = cpu_to_le16((u16)bss_cfg->ssid.ssid_len);
+               memcpy(ssid->ssid, bss_cfg->ssid.ssid, bss_cfg->ssid.ssid_len);
+               cmd_size += sizeof(struct mwifiex_ie_types_header) +
+                           bss_cfg->ssid.ssid_len;
+               tlv += sizeof(struct mwifiex_ie_types_header) +
+                               bss_cfg->ssid.ssid_len;
+
+               bcast_ssid = (struct host_cmd_tlv_bcast_ssid *)tlv;
+               bcast_ssid->header.type = cpu_to_le16(TLV_TYPE_UAP_BCAST_SSID);
+               bcast_ssid->header.len =
+                               cpu_to_le16(sizeof(bcast_ssid->bcast_ctl));
+               bcast_ssid->bcast_ctl = bss_cfg->bcast_ssid_ctl;
+               cmd_size += sizeof(struct host_cmd_tlv_bcast_ssid);
+               tlv += sizeof(struct host_cmd_tlv_bcast_ssid);
+       }
+       if (bss_cfg->rates[0]) {
+               tlv_rates = (struct host_cmd_tlv_rates *)tlv;
+               tlv_rates->header.type = cpu_to_le16(TLV_TYPE_UAP_RATES);
+
+               for (i = 0; i < MWIFIEX_SUPPORTED_RATES && bss_cfg->rates[i];
+                    i++)
+                       tlv_rates->rates[i] = bss_cfg->rates[i];
+
+               tlv_rates->header.len = cpu_to_le16(i);
+               cmd_size += sizeof(struct host_cmd_tlv_rates) + i;
+               tlv += sizeof(struct host_cmd_tlv_rates) + i;
+       }
+       if (bss_cfg->channel &&
+           ((bss_cfg->band_cfg == BAND_CONFIG_BG &&
+             bss_cfg->channel <= MAX_CHANNEL_BAND_BG) ||
+           (bss_cfg->band_cfg == BAND_CONFIG_A &&
+            bss_cfg->channel <= MAX_CHANNEL_BAND_A))) {
+               chan_band = (struct host_cmd_tlv_channel_band *)tlv;
+               chan_band->header.type = cpu_to_le16(TLV_TYPE_CHANNELBANDLIST);
+               chan_band->header.len =
+                       cpu_to_le16(sizeof(struct host_cmd_tlv_channel_band) -
+                                   sizeof(struct mwifiex_ie_types_header));
+               chan_band->band_config = bss_cfg->band_cfg;
+               chan_band->channel = bss_cfg->channel;
+               cmd_size += sizeof(struct host_cmd_tlv_channel_band);
+               tlv += sizeof(struct host_cmd_tlv_channel_band);
+       }
+       if (bss_cfg->beacon_period >= MIN_BEACON_PERIOD &&
+           bss_cfg->beacon_period <= MAX_BEACON_PERIOD) {
+               beacon_period = (struct host_cmd_tlv_beacon_period *)tlv;
+               beacon_period->header.type =
+                                       cpu_to_le16(TLV_TYPE_UAP_BEACON_PERIOD);
+               beacon_period->header.len =
+                       cpu_to_le16(sizeof(struct host_cmd_tlv_beacon_period) -
+                                   sizeof(struct mwifiex_ie_types_header));
+               beacon_period->period = cpu_to_le16(bss_cfg->beacon_period);
+               cmd_size += sizeof(struct host_cmd_tlv_beacon_period);
+               tlv += sizeof(struct host_cmd_tlv_beacon_period);
+       }
+       if (bss_cfg->dtim_period >= MIN_DTIM_PERIOD &&
+           bss_cfg->dtim_period <= MAX_DTIM_PERIOD) {
+               dtim_period = (struct host_cmd_tlv_dtim_period *)tlv;
+               dtim_period->header.type =
+                       cpu_to_le16(TLV_TYPE_UAP_DTIM_PERIOD);
+               dtim_period->header.len =
+                       cpu_to_le16(sizeof(struct host_cmd_tlv_dtim_period) -
+                                   sizeof(struct mwifiex_ie_types_header));
+               dtim_period->period = bss_cfg->dtim_period;
+               cmd_size += sizeof(struct host_cmd_tlv_dtim_period);
+               tlv += sizeof(struct host_cmd_tlv_dtim_period);
+       }
+       if (bss_cfg->rts_threshold <= MWIFIEX_RTS_MAX_VALUE) {
+               rts_threshold = (struct host_cmd_tlv_rts_threshold *)tlv;
+               rts_threshold->header.type =
+                                       cpu_to_le16(TLV_TYPE_UAP_RTS_THRESHOLD);
+               rts_threshold->header.len =
+                       cpu_to_le16(sizeof(struct host_cmd_tlv_rts_threshold) -
+                                   sizeof(struct mwifiex_ie_types_header));
+               rts_threshold->rts_thr = cpu_to_le16(bss_cfg->rts_threshold);
+               cmd_size += sizeof(struct host_cmd_tlv_frag_threshold);
+               tlv += sizeof(struct host_cmd_tlv_frag_threshold);
+       }
+       if ((bss_cfg->frag_threshold >= MWIFIEX_FRAG_MIN_VALUE) &&
+           (bss_cfg->frag_threshold <= MWIFIEX_FRAG_MAX_VALUE)) {
+               frag_threshold = (struct host_cmd_tlv_frag_threshold *)tlv;
+               frag_threshold->header.type =
+                               cpu_to_le16(TLV_TYPE_UAP_FRAG_THRESHOLD);
+               frag_threshold->header.len =
+                       cpu_to_le16(sizeof(struct host_cmd_tlv_frag_threshold) -
+                                   sizeof(struct mwifiex_ie_types_header));
+               frag_threshold->frag_thr = cpu_to_le16(bss_cfg->frag_threshold);
+               cmd_size += sizeof(struct host_cmd_tlv_frag_threshold);
+               tlv += sizeof(struct host_cmd_tlv_frag_threshold);
+       }
+       if (bss_cfg->retry_limit <= MWIFIEX_RETRY_LIMIT) {
+               retry_limit = (struct host_cmd_tlv_retry_limit *)tlv;
+               retry_limit->header.type =
+                       cpu_to_le16(TLV_TYPE_UAP_RETRY_LIMIT);
+               retry_limit->header.len =
+                       cpu_to_le16(sizeof(struct host_cmd_tlv_retry_limit) -
+                                   sizeof(struct mwifiex_ie_types_header));
+               retry_limit->limit = (u8)bss_cfg->retry_limit;
+               cmd_size += sizeof(struct host_cmd_tlv_retry_limit);
+               tlv += sizeof(struct host_cmd_tlv_retry_limit);
+       }
+       if ((bss_cfg->protocol & PROTOCOL_WPA) ||
+           (bss_cfg->protocol & PROTOCOL_WPA2) ||
+           (bss_cfg->protocol & PROTOCOL_EAP))
+               mwifiex_uap_bss_wpa(&tlv, cmd_buf, &cmd_size);
+       else
+               mwifiex_uap_bss_wep(&tlv, cmd_buf, &cmd_size);
+
+       if ((bss_cfg->auth_mode <= WLAN_AUTH_SHARED_KEY) ||
+           (bss_cfg->auth_mode == MWIFIEX_AUTH_MODE_AUTO)) {
+               auth_type = (struct host_cmd_tlv_auth_type *)tlv;
+               auth_type->header.type = cpu_to_le16(TLV_TYPE_AUTH_TYPE);
+               auth_type->header.len =
+                       cpu_to_le16(sizeof(struct host_cmd_tlv_auth_type) -
+                       sizeof(struct mwifiex_ie_types_header));
+               auth_type->auth_type = (u8)bss_cfg->auth_mode;
+               cmd_size += sizeof(struct host_cmd_tlv_auth_type);
+               tlv += sizeof(struct host_cmd_tlv_auth_type);
+       }
+       if (bss_cfg->protocol) {
+               encrypt_protocol = (struct host_cmd_tlv_encrypt_protocol *)tlv;
+               encrypt_protocol->header.type =
+                       cpu_to_le16(TLV_TYPE_UAP_ENCRY_PROTOCOL);
+               encrypt_protocol->header.len =
+                       cpu_to_le16(sizeof(struct host_cmd_tlv_encrypt_protocol)
+                       - sizeof(struct mwifiex_ie_types_header));
+               encrypt_protocol->proto = cpu_to_le16(bss_cfg->protocol);
+               cmd_size += sizeof(struct host_cmd_tlv_encrypt_protocol);
+               tlv += sizeof(struct host_cmd_tlv_encrypt_protocol);
+       }
+
+       if (bss_cfg->ht_cap.cap_info) {
+               htcap = (struct mwifiex_ie_types_htcap *)tlv;
+               htcap->header.type = cpu_to_le16(WLAN_EID_HT_CAPABILITY);
+               htcap->header.len =
+                               cpu_to_le16(sizeof(struct ieee80211_ht_cap));
+               htcap->ht_cap.cap_info = bss_cfg->ht_cap.cap_info;
+               htcap->ht_cap.ampdu_params_info =
+                                            bss_cfg->ht_cap.ampdu_params_info;
+               memcpy(&htcap->ht_cap.mcs, &bss_cfg->ht_cap.mcs,
+                      sizeof(struct ieee80211_mcs_info));
+               htcap->ht_cap.extended_ht_cap_info =
+                                       bss_cfg->ht_cap.extended_ht_cap_info;
+               htcap->ht_cap.tx_BF_cap_info = bss_cfg->ht_cap.tx_BF_cap_info;
+               htcap->ht_cap.antenna_selection_info =
+                                       bss_cfg->ht_cap.antenna_selection_info;
+               cmd_size += sizeof(struct mwifiex_ie_types_htcap);
+               tlv += sizeof(struct mwifiex_ie_types_htcap);
+       }
+
+       if (bss_cfg->wmm_info.qos_info != 0xFF) {
+               wmm_cap = (struct mwifiex_ie_types_wmmcap *)tlv;
+               wmm_cap->header.type = cpu_to_le16(WLAN_EID_VENDOR_SPECIFIC);
+               wmm_cap->header.len = cpu_to_le16(sizeof(wmm_cap->wmm_info));
+               memcpy(&wmm_cap->wmm_info, &bss_cfg->wmm_info,
+                      sizeof(wmm_cap->wmm_info));
+               cmd_size += sizeof(struct mwifiex_ie_types_wmmcap);
+               tlv += sizeof(struct mwifiex_ie_types_wmmcap);
+       }
+
+       if (bss_cfg->sta_ao_timer) {
+               ao_timer = (struct host_cmd_tlv_ageout_timer *)tlv;
+               ao_timer->header.type = cpu_to_le16(TLV_TYPE_UAP_AO_TIMER);
+               ao_timer->header.len = cpu_to_le16(sizeof(*ao_timer) -
+                                       sizeof(struct mwifiex_ie_types_header));
+               ao_timer->sta_ao_timer = cpu_to_le32(bss_cfg->sta_ao_timer);
+               cmd_size += sizeof(*ao_timer);
+               tlv += sizeof(*ao_timer);
+       }
+
+       if (bss_cfg->power_constraint) {
+               pwr_ct = (void *)tlv;
+               pwr_ct->header.type = cpu_to_le16(TLV_TYPE_PWR_CONSTRAINT);
+               pwr_ct->header.len = cpu_to_le16(sizeof(u8));
+               pwr_ct->constraint = bss_cfg->power_constraint;
+               cmd_size += sizeof(*pwr_ct);
+               tlv += sizeof(*pwr_ct);
+       }
+
+       if (bss_cfg->ps_sta_ao_timer) {
+               ps_ao_timer = (struct host_cmd_tlv_ageout_timer *)tlv;
+               ps_ao_timer->header.type =
+                               cpu_to_le16(TLV_TYPE_UAP_PS_AO_TIMER);
+               ps_ao_timer->header.len = cpu_to_le16(sizeof(*ps_ao_timer) -
+                               sizeof(struct mwifiex_ie_types_header));
+               ps_ao_timer->sta_ao_timer =
+                                       cpu_to_le32(bss_cfg->ps_sta_ao_timer);
+               cmd_size += sizeof(*ps_ao_timer);
+               tlv += sizeof(*ps_ao_timer);
+       }
+
+       *param_size = cmd_size;
+
+       return 0;
+}
+
+/* This function parses custom IEs from IE list and prepares command buffer */
+static int mwifiex_uap_custom_ie_prepare(u8 *tlv, void *cmd_buf, u16 *ie_size)
+{
+       struct mwifiex_ie_list *ap_ie = cmd_buf;
+       struct mwifiex_ie_types_header *tlv_ie = (void *)tlv;
+
+       if (!ap_ie || !ap_ie->len || !ap_ie->ie_list)
+               return -1;
+
+       *ie_size += le16_to_cpu(ap_ie->len) +
+                       sizeof(struct mwifiex_ie_types_header);
+
+       tlv_ie->type = cpu_to_le16(TLV_TYPE_MGMT_IE);
+       tlv_ie->len = ap_ie->len;
+       tlv += sizeof(struct mwifiex_ie_types_header);
+
+       memcpy(tlv, ap_ie->ie_list, le16_to_cpu(ap_ie->len));
+
+       return 0;
+}
+
+/* Parse AP config structure and prepare TLV based command structure
+ * to be sent to FW for uAP configuration
+ */
+static int
+mwifiex_cmd_uap_sys_config(struct host_cmd_ds_command *cmd, u16 cmd_action,
+                          u32 type, void *cmd_buf)
+{
+       u8 *tlv;
+       u16 cmd_size, param_size, ie_size;
+       struct host_cmd_ds_sys_config *sys_cfg;
+
+       cmd->command = cpu_to_le16(HostCmd_CMD_UAP_SYS_CONFIG);
+       cmd_size = (u16)(sizeof(struct host_cmd_ds_sys_config) + S_DS_GEN);
+       sys_cfg = (struct host_cmd_ds_sys_config *)&cmd->params.uap_sys_config;
+       sys_cfg->action = cpu_to_le16(cmd_action);
+       tlv = sys_cfg->tlv;
+
+       switch (type) {
+       case UAP_BSS_PARAMS_I:
+               param_size = cmd_size;
+               if (mwifiex_uap_bss_param_prepare(tlv, cmd_buf, &param_size))
+                       return -1;
+               cmd->size = cpu_to_le16(param_size);
+               break;
+       case UAP_CUSTOM_IE_I:
+               ie_size = cmd_size;
+               if (mwifiex_uap_custom_ie_prepare(tlv, cmd_buf, &ie_size))
+                       return -1;
+               cmd->size = cpu_to_le16(ie_size);
+               break;
+       default:
+               return -1;
+       }
+
+       return 0;
+}
+
+/* This function prepares AP specific deauth command with mac supplied in
+ * function parameter.
+ */
+static int mwifiex_cmd_uap_sta_deauth(struct mwifiex_private *priv,
+                                     struct host_cmd_ds_command *cmd, u8 *mac)
+{
+       struct host_cmd_ds_sta_deauth *sta_deauth = &cmd->params.sta_deauth;
+
+       cmd->command = cpu_to_le16(HostCmd_CMD_UAP_STA_DEAUTH);
+       memcpy(sta_deauth->mac, mac, ETH_ALEN);
+       sta_deauth->reason = cpu_to_le16(WLAN_REASON_DEAUTH_LEAVING);
+
+       cmd->size = cpu_to_le16(sizeof(struct host_cmd_ds_sta_deauth) +
+                               S_DS_GEN);
+       return 0;
+}
+
+/* This function prepares the AP specific commands before sending them
+ * to the firmware.
+ * This is a generic function which calls specific command preparation
+ * routines based upon the command number.
+ */
+int mwifiex_uap_prepare_cmd(struct mwifiex_private *priv, u16 cmd_no,
+                           u16 cmd_action, u32 type,
+                           void *data_buf, void *cmd_buf)
+{
+       struct host_cmd_ds_command *cmd = cmd_buf;
+
+       switch (cmd_no) {
+       case HostCmd_CMD_UAP_SYS_CONFIG:
+               if (mwifiex_cmd_uap_sys_config(cmd, cmd_action, type, data_buf))
+                       return -1;
+               break;
+       case HostCmd_CMD_UAP_BSS_START:
+       case HostCmd_CMD_UAP_BSS_STOP:
+       case HOST_CMD_APCMD_SYS_RESET:
+       case HOST_CMD_APCMD_STA_LIST:
+               cmd->command = cpu_to_le16(cmd_no);
+               cmd->size = cpu_to_le16(S_DS_GEN);
+               break;
+       case HostCmd_CMD_UAP_STA_DEAUTH:
+               if (mwifiex_cmd_uap_sta_deauth(priv, cmd, data_buf))
+                       return -1;
+               break;
+       case HostCmd_CMD_CHAN_REPORT_REQUEST:
+               if (mwifiex_cmd_issue_chan_report_request(priv, cmd_buf,
+                                                         data_buf))
+                       return -1;
+               break;
+       default:
+               mwifiex_dbg(priv->adapter, ERROR,
+                           "PREP_CMD: unknown cmd %#x\n", cmd_no);
+               return -1;
+       }
+
+       return 0;
+}
+
+void mwifiex_uap_set_channel(struct mwifiex_private *priv,
+                            struct mwifiex_uap_bss_param *bss_cfg,
+                            struct cfg80211_chan_def chandef)
+{
+       u8 config_bands = 0, old_bands = priv->adapter->config_bands;
+
+       priv->bss_chandef = chandef;
+
+       bss_cfg->channel = ieee80211_frequency_to_channel(
+                                                    chandef.chan->center_freq);
+
+       /* Set appropriate bands */
+       if (chandef.chan->band == IEEE80211_BAND_2GHZ) {
+               bss_cfg->band_cfg = BAND_CONFIG_BG;
+               config_bands = BAND_B | BAND_G;
+
+               if (chandef.width > NL80211_CHAN_WIDTH_20_NOHT)
+                       config_bands |= BAND_GN;
+       } else {
+               bss_cfg->band_cfg = BAND_CONFIG_A;
+               config_bands = BAND_A;
+
+               if (chandef.width > NL80211_CHAN_WIDTH_20_NOHT)
+                       config_bands |= BAND_AN;
+
+               if (chandef.width > NL80211_CHAN_WIDTH_40)
+                       config_bands |= BAND_AAC;
+       }
+
+       priv->adapter->config_bands = config_bands;
+
+       if (old_bands != config_bands) {
+               mwifiex_send_domain_info_cmd_fw(priv->adapter->wiphy);
+               mwifiex_dnld_txpwr_table(priv);
+       }
+}
+
+int mwifiex_config_start_uap(struct mwifiex_private *priv,
+                            struct mwifiex_uap_bss_param *bss_cfg)
+{
+       enum state_11d_t state_11d;
+
+       if (mwifiex_send_cmd(priv, HostCmd_CMD_UAP_SYS_CONFIG,
+                            HostCmd_ACT_GEN_SET,
+                            UAP_BSS_PARAMS_I, bss_cfg, false)) {
+               mwifiex_dbg(priv->adapter, ERROR,
+                           "Failed to set the SSID\n");
+               return -1;
+       }
+
+       /* Send cmd to FW to enable 11D function */
+       state_11d = ENABLE_11D;
+       if (mwifiex_send_cmd(priv, HostCmd_CMD_802_11_SNMP_MIB,
+                            HostCmd_ACT_GEN_SET, DOT11D_I,
+                            &state_11d, true)) {
+               mwifiex_dbg(priv->adapter, ERROR,
+                           "11D: failed to enable 11D\n");
+               return -1;
+       }
+
+       if (mwifiex_send_cmd(priv, HostCmd_CMD_UAP_BSS_START,
+                            HostCmd_ACT_GEN_SET, 0, NULL, false)) {
+               mwifiex_dbg(priv->adapter, ERROR,
+                           "Failed to start the BSS\n");
+               return -1;
+       }
+
+       if (priv->sec_info.wep_enabled)
+               priv->curr_pkt_filter |= HostCmd_ACT_MAC_WEP_ENABLE;
+       else
+               priv->curr_pkt_filter &= ~HostCmd_ACT_MAC_WEP_ENABLE;
+
+       if (mwifiex_send_cmd(priv, HostCmd_CMD_MAC_CONTROL,
+                            HostCmd_ACT_GEN_SET, 0,
+                            &priv->curr_pkt_filter, true))
+               return -1;
+
+       return 0;
+}
diff --git a/drivers/net/wireless/marvell/mwifiex/uap_event.c b/drivers/net/wireless/marvell/mwifiex/uap_event.c
new file mode 100644 (file)
index 0000000..86ff542
--- /dev/null
@@ -0,0 +1,333 @@
+/*
+ * Marvell Wireless LAN device driver: AP event handling
+ *
+ * Copyright (C) 2012-2014, Marvell International Ltd.
+ *
+ * This software file (the "File") is distributed by Marvell International
+ * Ltd. under the terms of the GNU General Public License Version 2, June 1991
+ * (the "License").  You may use, redistribute and/or modify this File in
+ * accordance with the terms and conditions of the License, a copy of which
+ * is available by writing to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the
+ * worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
+ *
+ * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
+ * ARE EXPRESSLY DISCLAIMED.  The License provides additional details about
+ * this warranty disclaimer.
+ */
+
+#include "decl.h"
+#include "main.h"
+#include "11n.h"
+
+#define MWIFIEX_BSS_START_EVT_FIX_SIZE    12
+
+static int mwifiex_check_uap_capabilties(struct mwifiex_private *priv,
+                                        struct sk_buff *event)
+{
+       int evt_len;
+       u8 *curr;
+       u16 tlv_len;
+       struct mwifiex_ie_types_data *tlv_hdr;
+       struct ieee_types_wmm_parameter *wmm_param_ie = NULL;
+       int mask = IEEE80211_WMM_IE_AP_QOSINFO_PARAM_SET_CNT_MASK;
+
+       priv->wmm_enabled = false;
+       skb_pull(event, MWIFIEX_BSS_START_EVT_FIX_SIZE);
+       evt_len = event->len;
+       curr = event->data;
+
+       mwifiex_dbg_dump(priv->adapter, EVT_D, "uap capabilties:",
+                        event->data, event->len);
+
+       skb_push(event, MWIFIEX_BSS_START_EVT_FIX_SIZE);
+
+       while ((evt_len >= sizeof(tlv_hdr->header))) {
+               tlv_hdr = (struct mwifiex_ie_types_data *)curr;
+               tlv_len = le16_to_cpu(tlv_hdr->header.len);
+
+               if (evt_len < tlv_len + sizeof(tlv_hdr->header))
+                       break;
+
+               switch (le16_to_cpu(tlv_hdr->header.type)) {
+               case WLAN_EID_HT_CAPABILITY:
+                       priv->ap_11n_enabled = true;
+                       break;
+
+               case WLAN_EID_VHT_CAPABILITY:
+                       priv->ap_11ac_enabled = true;
+                       break;
+
+               case WLAN_EID_VENDOR_SPECIFIC:
+                       /* Point the regular IEEE IE 2 bytes into the Marvell IE
+                        * and setup the IEEE IE type and length byte fields
+                        */
+                       wmm_param_ie = (void *)(curr + 2);
+                       wmm_param_ie->vend_hdr.len = (u8)tlv_len;
+                       wmm_param_ie->vend_hdr.element_id =
+                                               WLAN_EID_VENDOR_SPECIFIC;
+                       mwifiex_dbg(priv->adapter, EVENT,
+                                   "info: check uap capabilities:\t"
+                                   "wmm parameter set count: %d\n",
+                                   wmm_param_ie->qos_info_bitmap & mask);
+
+                       mwifiex_wmm_setup_ac_downgrade(priv);
+                       priv->wmm_enabled = true;
+                       mwifiex_wmm_setup_queue_priorities(priv, wmm_param_ie);
+                       break;
+
+               default:
+                       break;
+               }
+
+               curr += (tlv_len + sizeof(tlv_hdr->header));
+               evt_len -= (tlv_len + sizeof(tlv_hdr->header));
+       }
+
+       return 0;
+}
+
+/*
+ * This function handles AP interface specific events generated by firmware.
+ *
+ * Event specific routines are called by this function based
+ * upon the generated event cause.
+ *
+ *
+ * Events supported for AP -
+ *      - EVENT_UAP_STA_ASSOC
+ *      - EVENT_UAP_STA_DEAUTH
+ *      - EVENT_UAP_BSS_ACTIVE
+ *      - EVENT_UAP_BSS_START
+ *      - EVENT_UAP_BSS_IDLE
+ *      - EVENT_UAP_MIC_COUNTERMEASURES:
+ */
+int mwifiex_process_uap_event(struct mwifiex_private *priv)
+{
+       struct mwifiex_adapter *adapter = priv->adapter;
+       int len, i;
+       u32 eventcause = adapter->event_cause;
+       struct station_info sinfo;
+       struct mwifiex_assoc_event *event;
+       struct mwifiex_sta_node *node;
+       u8 *deauth_mac;
+       struct host_cmd_ds_11n_batimeout *ba_timeout;
+       u16 ctrl;
+
+       switch (eventcause) {
+       case EVENT_UAP_STA_ASSOC:
+               memset(&sinfo, 0, sizeof(sinfo));
+               event = (struct mwifiex_assoc_event *)
+                       (adapter->event_body + MWIFIEX_UAP_EVENT_EXTRA_HEADER);
+               if (le16_to_cpu(event->type) == TLV_TYPE_UAP_MGMT_FRAME) {
+                       len = -1;
+
+                       if (ieee80211_is_assoc_req(event->frame_control))
+                               len = 0;
+                       else if (ieee80211_is_reassoc_req(event->frame_control))
+                               /* There will be ETH_ALEN bytes of
+                                * current_ap_addr before the re-assoc ies.
+                                */
+                               len = ETH_ALEN;
+
+                       if (len != -1) {
+                               sinfo.assoc_req_ies = &event->data[len];
+                               len = (u8 *)sinfo.assoc_req_ies -
+                                     (u8 *)&event->frame_control;
+                               sinfo.assoc_req_ies_len =
+                                       le16_to_cpu(event->len) - (u16)len;
+                       }
+               }
+               cfg80211_new_sta(priv->netdev, event->sta_addr, &sinfo,
+                                GFP_KERNEL);
+
+               node = mwifiex_add_sta_entry(priv, event->sta_addr);
+               if (!node) {
+                       mwifiex_dbg(adapter, ERROR,
+                                   "could not create station entry!\n");
+                       return -1;
+               }
+
+               if (!priv->ap_11n_enabled)
+                       break;
+
+               mwifiex_set_sta_ht_cap(priv, sinfo.assoc_req_ies,
+                                      sinfo.assoc_req_ies_len, node);
+
+               for (i = 0; i < MAX_NUM_TID; i++) {
+                       if (node->is_11n_enabled)
+                               node->ampdu_sta[i] =
+                                             priv->aggr_prio_tbl[i].ampdu_user;
+                       else
+                               node->ampdu_sta[i] = BA_STREAM_NOT_ALLOWED;
+               }
+               memset(node->rx_seq, 0xff, sizeof(node->rx_seq));
+               break;
+       case EVENT_UAP_STA_DEAUTH:
+               deauth_mac = adapter->event_body +
+                            MWIFIEX_UAP_EVENT_EXTRA_HEADER;
+               cfg80211_del_sta(priv->netdev, deauth_mac, GFP_KERNEL);
+
+               if (priv->ap_11n_enabled) {
+                       mwifiex_11n_del_rx_reorder_tbl_by_ta(priv, deauth_mac);
+                       mwifiex_del_tx_ba_stream_tbl_by_ra(priv, deauth_mac);
+               }
+               mwifiex_wmm_del_peer_ra_list(priv, deauth_mac);
+               mwifiex_del_sta_entry(priv, deauth_mac);
+               break;
+       case EVENT_UAP_BSS_IDLE:
+               priv->media_connected = false;
+               priv->port_open = false;
+               mwifiex_clean_txrx(priv);
+               mwifiex_del_all_sta_list(priv);
+               break;
+       case EVENT_UAP_BSS_ACTIVE:
+               priv->media_connected = true;
+               priv->port_open = true;
+               break;
+       case EVENT_UAP_BSS_START:
+               mwifiex_dbg(adapter, EVENT,
+                           "AP EVENT: event id: %#x\n", eventcause);
+               priv->port_open = false;
+               memcpy(priv->netdev->dev_addr, adapter->event_body + 2,
+                      ETH_ALEN);
+               if (priv->hist_data)
+                       mwifiex_hist_data_reset(priv);
+               mwifiex_check_uap_capabilties(priv, adapter->event_skb);
+               break;
+       case EVENT_UAP_MIC_COUNTERMEASURES:
+               /* For future development */
+               mwifiex_dbg(adapter, EVENT,
+                           "AP EVENT: event id: %#x\n", eventcause);
+               break;
+       case EVENT_AMSDU_AGGR_CTRL:
+               ctrl = le16_to_cpu(*(__le16 *)adapter->event_body);
+               mwifiex_dbg(adapter, EVENT,
+                           "event: AMSDU_AGGR_CTRL %d\n", ctrl);
+
+               if (priv->media_connected) {
+                       adapter->tx_buf_size =
+                               min_t(u16, adapter->curr_tx_buf_size, ctrl);
+                       mwifiex_dbg(adapter, EVENT,
+                                   "event: tx_buf_size %d\n",
+                                   adapter->tx_buf_size);
+               }
+               break;
+       case EVENT_ADDBA:
+               mwifiex_dbg(adapter, EVENT, "event: ADDBA Request\n");
+               if (priv->media_connected)
+                       mwifiex_send_cmd(priv, HostCmd_CMD_11N_ADDBA_RSP,
+                                        HostCmd_ACT_GEN_SET, 0,
+                                        adapter->event_body, false);
+               break;
+       case EVENT_DELBA:
+               mwifiex_dbg(adapter, EVENT, "event: DELBA Request\n");
+               if (priv->media_connected)
+                       mwifiex_11n_delete_ba_stream(priv, adapter->event_body);
+               break;
+       case EVENT_BA_STREAM_TIEMOUT:
+               mwifiex_dbg(adapter, EVENT, "event:  BA Stream timeout\n");
+               if (priv->media_connected) {
+                       ba_timeout = (void *)adapter->event_body;
+                       mwifiex_11n_ba_stream_timeout(priv, ba_timeout);
+               }
+               break;
+       case EVENT_EXT_SCAN_REPORT:
+               mwifiex_dbg(adapter, EVENT, "event: EXT_SCAN Report\n");
+               if (adapter->ext_scan)
+                       return mwifiex_handle_event_ext_scan_report(priv,
+                                               adapter->event_skb->data);
+               break;
+       case EVENT_TX_STATUS_REPORT:
+               mwifiex_dbg(adapter, EVENT, "event: TX_STATUS Report\n");
+               mwifiex_parse_tx_status_event(priv, adapter->event_body);
+               break;
+       case EVENT_PS_SLEEP:
+               mwifiex_dbg(adapter, EVENT, "info: EVENT: SLEEP\n");
+
+               adapter->ps_state = PS_STATE_PRE_SLEEP;
+
+               mwifiex_check_ps_cond(adapter);
+               break;
+
+       case EVENT_PS_AWAKE:
+               mwifiex_dbg(adapter, EVENT, "info: EVENT: AWAKE\n");
+               if (!adapter->pps_uapsd_mode &&
+                   priv->media_connected && adapter->sleep_period.period) {
+                               adapter->pps_uapsd_mode = true;
+                               mwifiex_dbg(adapter, EVENT,
+                                           "event: PPS/UAPSD mode activated\n");
+               }
+               adapter->tx_lock_flag = false;
+               if (adapter->pps_uapsd_mode && adapter->gen_null_pkt) {
+                       if (mwifiex_check_last_packet_indication(priv)) {
+                               if (adapter->data_sent ||
+                                   (adapter->if_ops.is_port_ready &&
+                                    !adapter->if_ops.is_port_ready(priv))) {
+                                       adapter->ps_state = PS_STATE_AWAKE;
+                                       adapter->pm_wakeup_card_req = false;
+                                       adapter->pm_wakeup_fw_try = false;
+                                       break;
+                               }
+                               if (!mwifiex_send_null_packet
+                                       (priv,
+                                        MWIFIEX_TxPD_POWER_MGMT_NULL_PACKET |
+                                        MWIFIEX_TxPD_POWER_MGMT_LAST_PACKET))
+                                               adapter->ps_state =
+                                                       PS_STATE_SLEEP;
+                                       return 0;
+                       }
+               }
+               adapter->ps_state = PS_STATE_AWAKE;
+               adapter->pm_wakeup_card_req = false;
+               adapter->pm_wakeup_fw_try = false;
+               break;
+
+       case EVENT_CHANNEL_REPORT_RDY:
+               mwifiex_dbg(adapter, EVENT, "event: Channel Report\n");
+               mwifiex_11h_handle_chanrpt_ready(priv, adapter->event_skb);
+               break;
+       case EVENT_RADAR_DETECTED:
+               mwifiex_dbg(adapter, EVENT, "event: Radar detected\n");
+               mwifiex_11h_handle_radar_detected(priv, adapter->event_skb);
+               break;
+       case EVENT_BT_COEX_WLAN_PARA_CHANGE:
+               dev_err(adapter->dev, "EVENT: BT coex wlan param update\n");
+               mwifiex_bt_coex_wlan_param_update_event(priv,
+                                                       adapter->event_skb);
+               break;
+       case EVENT_TX_DATA_PAUSE:
+               mwifiex_dbg(adapter, EVENT, "event: TX DATA PAUSE\n");
+               mwifiex_process_tx_pause_event(priv, adapter->event_skb);
+               break;
+
+       case EVENT_MULTI_CHAN_INFO:
+               mwifiex_dbg(adapter, EVENT, "event: multi-chan info\n");
+               mwifiex_process_multi_chan_event(priv, adapter->event_skb);
+               break;
+
+       default:
+               mwifiex_dbg(adapter, EVENT,
+                           "event: unknown event id: %#x\n", eventcause);
+               break;
+       }
+
+       return 0;
+}
+
+/* This function deletes station entry from associated station list.
+ * Also if both AP and STA are 11n enabled, RxReorder tables and TxBA stream
+ * tables created for this station are deleted.
+ */
+void mwifiex_uap_del_sta_data(struct mwifiex_private *priv,
+                             struct mwifiex_sta_node *node)
+{
+       if (priv->ap_11n_enabled && node->is_11n_enabled) {
+               mwifiex_11n_del_rx_reorder_tbl_by_ta(priv, node->mac_addr);
+               mwifiex_del_tx_ba_stream_tbl_by_ra(priv, node->mac_addr);
+       }
+       mwifiex_del_sta_entry(priv, node->mac_addr);
+
+       return;
+}
diff --git a/drivers/net/wireless/marvell/mwifiex/uap_txrx.c b/drivers/net/wireless/marvell/mwifiex/uap_txrx.c
new file mode 100644 (file)
index 0000000..74d5d72
--- /dev/null
@@ -0,0 +1,437 @@
+/*
+ * Marvell Wireless LAN device driver: AP TX and RX data handling
+ *
+ * Copyright (C) 2012-2014, Marvell International Ltd.
+ *
+ * This software file (the "File") is distributed by Marvell International
+ * Ltd. under the terms of the GNU General Public License Version 2, June 1991
+ * (the "License").  You may use, redistribute and/or modify this File in
+ * accordance with the terms and conditions of the License, a copy of which
+ * is available by writing to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the
+ * worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
+ *
+ * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
+ * ARE EXPRESSLY DISCLAIMED.  The License provides additional details about
+ * this warranty disclaimer.
+ */
+
+#include "decl.h"
+#include "ioctl.h"
+#include "main.h"
+#include "wmm.h"
+#include "11n_aggr.h"
+#include "11n_rxreorder.h"
+
+/* This function checks if particular RA list has packets more than low bridge
+ * packet threshold and then deletes packet from this RA list.
+ * Function deletes packets from such RA list and returns true. If no such list
+ * is found, false is returned.
+ */
+static bool
+mwifiex_uap_del_tx_pkts_in_ralist(struct mwifiex_private *priv,
+                                 struct list_head *ra_list_head,
+                                 int tid)
+{
+       struct mwifiex_ra_list_tbl *ra_list;
+       struct sk_buff *skb, *tmp;
+       bool pkt_deleted = false;
+       struct mwifiex_txinfo *tx_info;
+       struct mwifiex_adapter *adapter = priv->adapter;
+
+       list_for_each_entry(ra_list, ra_list_head, list) {
+               if (skb_queue_empty(&ra_list->skb_head))
+                       continue;
+
+               skb_queue_walk_safe(&ra_list->skb_head, skb, tmp) {
+                       tx_info = MWIFIEX_SKB_TXCB(skb);
+                       if (tx_info->flags & MWIFIEX_BUF_FLAG_BRIDGED_PKT) {
+                               __skb_unlink(skb, &ra_list->skb_head);
+                               mwifiex_write_data_complete(adapter, skb, 0,
+                                                           -1);
+                               if (ra_list->tx_paused)
+                                       priv->wmm.pkts_paused[tid]--;
+                               else
+                                       atomic_dec(&priv->wmm.tx_pkts_queued);
+                               pkt_deleted = true;
+                       }
+                       if ((atomic_read(&adapter->pending_bridged_pkts) <=
+                                            MWIFIEX_BRIDGED_PKTS_THR_LOW))
+                               break;
+               }
+       }
+
+       return pkt_deleted;
+}
+
+/* This function deletes packets from particular RA List. RA list index
+ * from which packets are deleted is preserved so that packets from next RA
+ * list are deleted upon subsequent call thus maintaining fairness.
+ */
+static void mwifiex_uap_cleanup_tx_queues(struct mwifiex_private *priv)
+{
+       unsigned long flags;
+       struct list_head *ra_list;
+       int i;
+
+       spin_lock_irqsave(&priv->wmm.ra_list_spinlock, flags);
+
+       for (i = 0; i < MAX_NUM_TID; i++, priv->del_list_idx++) {
+               if (priv->del_list_idx == MAX_NUM_TID)
+                       priv->del_list_idx = 0;
+               ra_list = &priv->wmm.tid_tbl_ptr[priv->del_list_idx].ra_list;
+               if (mwifiex_uap_del_tx_pkts_in_ralist(priv, ra_list, i)) {
+                       priv->del_list_idx++;
+                       break;
+               }
+       }
+
+       spin_unlock_irqrestore(&priv->wmm.ra_list_spinlock, flags);
+}
+
+
+static void mwifiex_uap_queue_bridged_pkt(struct mwifiex_private *priv,
+                                        struct sk_buff *skb)
+{
+       struct mwifiex_adapter *adapter = priv->adapter;
+       struct uap_rxpd *uap_rx_pd;
+       struct rx_packet_hdr *rx_pkt_hdr;
+       struct sk_buff *new_skb;
+       struct mwifiex_txinfo *tx_info;
+       int hdr_chop;
+       struct ethhdr *p_ethhdr;
+       struct mwifiex_sta_node *src_node;
+
+       uap_rx_pd = (struct uap_rxpd *)(skb->data);
+       rx_pkt_hdr = (void *)uap_rx_pd + le16_to_cpu(uap_rx_pd->rx_pkt_offset);
+
+       if ((atomic_read(&adapter->pending_bridged_pkts) >=
+                                            MWIFIEX_BRIDGED_PKTS_THR_HIGH)) {
+               mwifiex_dbg(priv->adapter, ERROR,
+                           "Tx: Bridge packet limit reached. Drop packet!\n");
+               kfree_skb(skb);
+               mwifiex_uap_cleanup_tx_queues(priv);
+               return;
+       }
+
+       if ((!memcmp(&rx_pkt_hdr->rfc1042_hdr, bridge_tunnel_header,
+                    sizeof(bridge_tunnel_header))) ||
+           (!memcmp(&rx_pkt_hdr->rfc1042_hdr, rfc1042_header,
+                    sizeof(rfc1042_header)) &&
+            ntohs(rx_pkt_hdr->rfc1042_hdr.snap_type) != ETH_P_AARP &&
+            ntohs(rx_pkt_hdr->rfc1042_hdr.snap_type) != ETH_P_IPX)) {
+               /* Replace the 803 header and rfc1042 header (llc/snap) with
+                * an Ethernet II header, keep the src/dst and snap_type
+                * (ethertype).
+                *
+                * The firmware only passes up SNAP frames converting all RX
+                * data from 802.11 to 802.2/LLC/SNAP frames.
+                *
+                * To create the Ethernet II, just move the src, dst address
+                * right before the snap_type.
+                */
+               p_ethhdr = (struct ethhdr *)
+                       ((u8 *)(&rx_pkt_hdr->eth803_hdr)
+                        + sizeof(rx_pkt_hdr->eth803_hdr)
+                        + sizeof(rx_pkt_hdr->rfc1042_hdr)
+                        - sizeof(rx_pkt_hdr->eth803_hdr.h_dest)
+                        - sizeof(rx_pkt_hdr->eth803_hdr.h_source)
+                        - sizeof(rx_pkt_hdr->rfc1042_hdr.snap_type));
+               memcpy(p_ethhdr->h_source, rx_pkt_hdr->eth803_hdr.h_source,
+                      sizeof(p_ethhdr->h_source));
+               memcpy(p_ethhdr->h_dest, rx_pkt_hdr->eth803_hdr.h_dest,
+                      sizeof(p_ethhdr->h_dest));
+               /* Chop off the rxpd + the excess memory from
+                * 802.2/llc/snap header that was removed.
+                */
+               hdr_chop = (u8 *)p_ethhdr - (u8 *)uap_rx_pd;
+       } else {
+               /* Chop off the rxpd */
+               hdr_chop = (u8 *)&rx_pkt_hdr->eth803_hdr - (u8 *)uap_rx_pd;
+       }
+
+       /* Chop off the leading header bytes so that it points
+        * to the start of either the reconstructed EthII frame
+        * or the 802.2/llc/snap frame.
+        */
+       skb_pull(skb, hdr_chop);
+
+       if (skb_headroom(skb) < MWIFIEX_MIN_DATA_HEADER_LEN) {
+               mwifiex_dbg(priv->adapter, ERROR,
+                           "data: Tx: insufficient skb headroom %d\n",
+                           skb_headroom(skb));
+               /* Insufficient skb headroom - allocate a new skb */
+               new_skb =
+                       skb_realloc_headroom(skb, MWIFIEX_MIN_DATA_HEADER_LEN);
+               if (unlikely(!new_skb)) {
+                       mwifiex_dbg(priv->adapter, ERROR,
+                                   "Tx: cannot allocate new_skb\n");
+                       kfree_skb(skb);
+                       priv->stats.tx_dropped++;
+                       return;
+               }
+
+               kfree_skb(skb);
+               skb = new_skb;
+               mwifiex_dbg(priv->adapter, INFO,
+                           "info: new skb headroom %d\n",
+                           skb_headroom(skb));
+       }
+
+       tx_info = MWIFIEX_SKB_TXCB(skb);
+       memset(tx_info, 0, sizeof(*tx_info));
+       tx_info->bss_num = priv->bss_num;
+       tx_info->bss_type = priv->bss_type;
+       tx_info->flags |= MWIFIEX_BUF_FLAG_BRIDGED_PKT;
+
+       src_node = mwifiex_get_sta_entry(priv, rx_pkt_hdr->eth803_hdr.h_source);
+       if (src_node) {
+               src_node->stats.last_rx = jiffies;
+               src_node->stats.rx_bytes += skb->len;
+               src_node->stats.rx_packets++;
+               src_node->stats.last_tx_rate = uap_rx_pd->rx_rate;
+               src_node->stats.last_tx_htinfo = uap_rx_pd->ht_info;
+       }
+
+       if (is_unicast_ether_addr(rx_pkt_hdr->eth803_hdr.h_dest)) {
+               /* Update bridge packet statistics as the
+                * packet is not going to kernel/upper layer.
+                */
+               priv->stats.rx_bytes += skb->len;
+               priv->stats.rx_packets++;
+
+               /* Sending bridge packet to TX queue, so save the packet
+                * length in TXCB to update statistics in TX complete.
+                */
+               tx_info->pkt_len = skb->len;
+       }
+
+       __net_timestamp(skb);
+       mwifiex_wmm_add_buf_txqueue(priv, skb);
+       atomic_inc(&adapter->tx_pending);
+       atomic_inc(&adapter->pending_bridged_pkts);
+
+       return;
+}
+
+/*
+ * This function contains logic for AP packet forwarding.
+ *
+ * If a packet is multicast/broadcast, it is sent to kernel/upper layer
+ * as well as queued back to AP TX queue so that it can be sent to other
+ * associated stations.
+ * If a packet is unicast and RA is present in associated station list,
+ * it is again requeued into AP TX queue.
+ * If a packet is unicast and RA is not in associated station list,
+ * packet is forwarded to kernel to handle routing logic.
+ */
+int mwifiex_handle_uap_rx_forward(struct mwifiex_private *priv,
+                                 struct sk_buff *skb)
+{
+       struct mwifiex_adapter *adapter = priv->adapter;
+       struct uap_rxpd *uap_rx_pd;
+       struct rx_packet_hdr *rx_pkt_hdr;
+       u8 ra[ETH_ALEN];
+       struct sk_buff *skb_uap;
+
+       uap_rx_pd = (struct uap_rxpd *)(skb->data);
+       rx_pkt_hdr = (void *)uap_rx_pd + le16_to_cpu(uap_rx_pd->rx_pkt_offset);
+
+       /* don't do packet forwarding in disconnected state */
+       if (!priv->media_connected) {
+               mwifiex_dbg(adapter, ERROR,
+                           "drop packet in disconnected state.\n");
+               dev_kfree_skb_any(skb);
+               return 0;
+       }
+
+       memcpy(ra, rx_pkt_hdr->eth803_hdr.h_dest, ETH_ALEN);
+
+       if (is_multicast_ether_addr(ra)) {
+               skb_uap = skb_copy(skb, GFP_ATOMIC);
+               mwifiex_uap_queue_bridged_pkt(priv, skb_uap);
+       } else {
+               if (mwifiex_get_sta_entry(priv, ra)) {
+                       /* Requeue Intra-BSS packet */
+                       mwifiex_uap_queue_bridged_pkt(priv, skb);
+                       return 0;
+               }
+       }
+
+       /* Forward unicat/Inter-BSS packets to kernel. */
+       return mwifiex_process_rx_packet(priv, skb);
+}
+
+/*
+ * This function processes the packet received on AP interface.
+ *
+ * The function looks into the RxPD and performs sanity tests on the
+ * received buffer to ensure its a valid packet before processing it
+ * further. If the packet is determined to be aggregated, it is
+ * de-aggregated accordingly. Then skb is passed to AP packet forwarding logic.
+ *
+ * The completion callback is called after processing is complete.
+ */
+int mwifiex_process_uap_rx_packet(struct mwifiex_private *priv,
+                                 struct sk_buff *skb)
+{
+       struct mwifiex_adapter *adapter = priv->adapter;
+       int ret;
+       struct uap_rxpd *uap_rx_pd;
+       struct rx_packet_hdr *rx_pkt_hdr;
+       u16 rx_pkt_type;
+       u8 ta[ETH_ALEN], pkt_type;
+       unsigned long flags;
+       struct mwifiex_sta_node *node;
+
+       uap_rx_pd = (struct uap_rxpd *)(skb->data);
+       rx_pkt_type = le16_to_cpu(uap_rx_pd->rx_pkt_type);
+       rx_pkt_hdr = (void *)uap_rx_pd + le16_to_cpu(uap_rx_pd->rx_pkt_offset);
+
+       ether_addr_copy(ta, rx_pkt_hdr->eth803_hdr.h_source);
+
+       if ((le16_to_cpu(uap_rx_pd->rx_pkt_offset) +
+            le16_to_cpu(uap_rx_pd->rx_pkt_length)) > (u16) skb->len) {
+               mwifiex_dbg(adapter, ERROR,
+                           "wrong rx packet: len=%d, offset=%d, length=%d\n",
+                           skb->len, le16_to_cpu(uap_rx_pd->rx_pkt_offset),
+                           le16_to_cpu(uap_rx_pd->rx_pkt_length));
+               priv->stats.rx_dropped++;
+
+               node = mwifiex_get_sta_entry(priv, ta);
+               if (node)
+                       node->stats.tx_failed++;
+
+               dev_kfree_skb_any(skb);
+               return 0;
+       }
+
+       if (rx_pkt_type == PKT_TYPE_MGMT) {
+               ret = mwifiex_process_mgmt_packet(priv, skb);
+               if (ret)
+                       mwifiex_dbg(adapter, ERROR,
+                                   "Rx of mgmt packet failed");
+               dev_kfree_skb_any(skb);
+               return ret;
+       }
+
+
+       if (rx_pkt_type != PKT_TYPE_BAR && uap_rx_pd->priority < MAX_NUM_TID) {
+               spin_lock_irqsave(&priv->sta_list_spinlock, flags);
+               node = mwifiex_get_sta_entry(priv, ta);
+               if (node)
+                       node->rx_seq[uap_rx_pd->priority] =
+                                               le16_to_cpu(uap_rx_pd->seq_num);
+               spin_unlock_irqrestore(&priv->sta_list_spinlock, flags);
+       }
+
+       if (!priv->ap_11n_enabled ||
+           (!mwifiex_11n_get_rx_reorder_tbl(priv, uap_rx_pd->priority, ta) &&
+           (le16_to_cpu(uap_rx_pd->rx_pkt_type) != PKT_TYPE_AMSDU))) {
+               ret = mwifiex_handle_uap_rx_forward(priv, skb);
+               return ret;
+       }
+
+       /* Reorder and send to kernel */
+       pkt_type = (u8)le16_to_cpu(uap_rx_pd->rx_pkt_type);
+       ret = mwifiex_11n_rx_reorder_pkt(priv, le16_to_cpu(uap_rx_pd->seq_num),
+                                        uap_rx_pd->priority, ta, pkt_type,
+                                        skb);
+
+       if (ret || (rx_pkt_type == PKT_TYPE_BAR))
+               dev_kfree_skb_any(skb);
+
+       if (ret)
+               priv->stats.rx_dropped++;
+
+       return ret;
+}
+
+/*
+ * This function fills the TxPD for AP tx packets.
+ *
+ * The Tx buffer received by this function should already have the
+ * header space allocated for TxPD.
+ *
+ * This function inserts the TxPD in between interface header and actual
+ * data and adjusts the buffer pointers accordingly.
+ *
+ * The following TxPD fields are set by this function, as required -
+ *      - BSS number
+ *      - Tx packet length and offset
+ *      - Priority
+ *      - Packet delay
+ *      - Priority specific Tx control
+ *      - Flags
+ */
+void *mwifiex_process_uap_txpd(struct mwifiex_private *priv,
+                              struct sk_buff *skb)
+{
+       struct mwifiex_adapter *adapter = priv->adapter;
+       struct uap_txpd *txpd;
+       struct mwifiex_txinfo *tx_info = MWIFIEX_SKB_TXCB(skb);
+       int pad;
+       u16 pkt_type, pkt_offset;
+       int hroom = (priv->adapter->iface_type == MWIFIEX_USB) ? 0 :
+                      INTF_HEADER_LEN;
+
+       if (!skb->len) {
+               mwifiex_dbg(adapter, ERROR,
+                           "Tx: bad packet length: %d\n", skb->len);
+               tx_info->status_code = -1;
+               return skb->data;
+       }
+
+       BUG_ON(skb_headroom(skb) < MWIFIEX_MIN_DATA_HEADER_LEN);
+
+       pkt_type = mwifiex_is_skb_mgmt_frame(skb) ? PKT_TYPE_MGMT : 0;
+
+       pad = ((void *)skb->data - (sizeof(*txpd) + hroom) - NULL) &
+                       (MWIFIEX_DMA_ALIGN_SZ - 1);
+
+       skb_push(skb, sizeof(*txpd) + pad);
+
+       txpd = (struct uap_txpd *)skb->data;
+       memset(txpd, 0, sizeof(*txpd));
+       txpd->bss_num = priv->bss_num;
+       txpd->bss_type = priv->bss_type;
+       txpd->tx_pkt_length = cpu_to_le16((u16)(skb->len - (sizeof(*txpd) +
+                                               pad)));
+       txpd->priority = (u8)skb->priority;
+
+       txpd->pkt_delay_2ms = mwifiex_wmm_compute_drv_pkt_delay(priv, skb);
+
+       if (tx_info->flags & MWIFIEX_BUF_FLAG_EAPOL_TX_STATUS ||
+           tx_info->flags & MWIFIEX_BUF_FLAG_ACTION_TX_STATUS) {
+               txpd->tx_token_id = tx_info->ack_frame_id;
+               txpd->flags |= MWIFIEX_TXPD_FLAGS_REQ_TX_STATUS;
+       }
+
+       if (txpd->priority < ARRAY_SIZE(priv->wmm.user_pri_pkt_tx_ctrl))
+               /*
+                * Set the priority specific tx_control field, setting of 0 will
+                * cause the default value to be used later in this function.
+                */
+               txpd->tx_control =
+                   cpu_to_le32(priv->wmm.user_pri_pkt_tx_ctrl[txpd->priority]);
+
+       /* Offset of actual data */
+       pkt_offset = sizeof(*txpd) + pad;
+       if (pkt_type == PKT_TYPE_MGMT) {
+               /* Set the packet type and add header for management frame */
+               txpd->tx_pkt_type = cpu_to_le16(pkt_type);
+               pkt_offset += MWIFIEX_MGMT_FRAME_HEADER_SIZE;
+       }
+
+       txpd->tx_pkt_offset = cpu_to_le16(pkt_offset);
+
+       /* make space for INTF_HEADER_LEN */
+       skb_push(skb, hroom);
+
+       if (!txpd->tx_control)
+               /* TxCtrl set by user or default */
+               txpd->tx_control = cpu_to_le32(priv->pkt_tx_ctrl);
+
+       return skb->data;
+}
diff --git a/drivers/net/wireless/marvell/mwifiex/usb.c b/drivers/net/wireless/marvell/mwifiex/usb.c
new file mode 100644 (file)
index 0000000..e43aff9
--- /dev/null
@@ -0,0 +1,1267 @@
+/*
+ * Marvell Wireless LAN device driver: USB specific handling
+ *
+ * Copyright (C) 2012-2014, Marvell International Ltd.
+ *
+ * This software file (the "File") is distributed by Marvell International
+ * Ltd. under the terms of the GNU General Public License Version 2, June 1991
+ * (the "License").  You may use, redistribute and/or modify this File in
+ * accordance with the terms and conditions of the License, a copy of which
+ * is available by writing to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the
+ * worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
+ *
+ * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
+ * ARE EXPRESSLY DISCLAIMED.  The License provides additional details about
+ * this warranty disclaimer.
+ */
+
+#include "main.h"
+#include "usb.h"
+
+#define USB_VERSION    "1.0"
+
+static u8 user_rmmod;
+static struct mwifiex_if_ops usb_ops;
+static struct semaphore add_remove_card_sem;
+
+static struct usb_device_id mwifiex_usb_table[] = {
+       /* 8766 */
+       {USB_DEVICE(USB8XXX_VID, USB8766_PID_1)},
+       {USB_DEVICE_AND_INTERFACE_INFO(USB8XXX_VID, USB8766_PID_2,
+                                      USB_CLASS_VENDOR_SPEC,
+                                      USB_SUBCLASS_VENDOR_SPEC, 0xff)},
+       /* 8797 */
+       {USB_DEVICE(USB8XXX_VID, USB8797_PID_1)},
+       {USB_DEVICE_AND_INTERFACE_INFO(USB8XXX_VID, USB8797_PID_2,
+                                      USB_CLASS_VENDOR_SPEC,
+                                      USB_SUBCLASS_VENDOR_SPEC, 0xff)},
+       /* 8801 */
+       {USB_DEVICE(USB8XXX_VID, USB8801_PID_1)},
+       {USB_DEVICE_AND_INTERFACE_INFO(USB8XXX_VID, USB8801_PID_2,
+                                      USB_CLASS_VENDOR_SPEC,
+                                      USB_SUBCLASS_VENDOR_SPEC, 0xff)},
+       /* 8997 */
+       {USB_DEVICE(USB8XXX_VID, USB8997_PID_1)},
+       {USB_DEVICE_AND_INTERFACE_INFO(USB8XXX_VID, USB8997_PID_2,
+                                      USB_CLASS_VENDOR_SPEC,
+                                      USB_SUBCLASS_VENDOR_SPEC, 0xff)},
+       { }     /* Terminating entry */
+};
+
+MODULE_DEVICE_TABLE(usb, mwifiex_usb_table);
+
+static int mwifiex_usb_submit_rx_urb(struct urb_context *ctx, int size);
+
+/* This function handles received packet. Necessary action is taken based on
+ * cmd/event/data.
+ */
+static int mwifiex_usb_recv(struct mwifiex_adapter *adapter,
+                           struct sk_buff *skb, u8 ep)
+{
+       u32 recv_type;
+       __le32 tmp;
+       int ret;
+
+       if (adapter->hs_activated)
+               mwifiex_process_hs_config(adapter);
+
+       if (skb->len < INTF_HEADER_LEN) {
+               mwifiex_dbg(adapter, ERROR,
+                           "%s: invalid skb->len\n", __func__);
+               return -1;
+       }
+
+       switch (ep) {
+       case MWIFIEX_USB_EP_CMD_EVENT:
+               mwifiex_dbg(adapter, EVENT,
+                           "%s: EP_CMD_EVENT\n", __func__);
+               skb_copy_from_linear_data(skb, &tmp, INTF_HEADER_LEN);
+               recv_type = le32_to_cpu(tmp);
+               skb_pull(skb, INTF_HEADER_LEN);
+
+               switch (recv_type) {
+               case MWIFIEX_USB_TYPE_CMD:
+                       if (skb->len > MWIFIEX_SIZE_OF_CMD_BUFFER) {
+                               mwifiex_dbg(adapter, ERROR,
+                                           "CMD: skb->len too large\n");
+                               ret = -1;
+                               goto exit_restore_skb;
+                       } else if (!adapter->curr_cmd) {
+                               mwifiex_dbg(adapter, WARN, "CMD: no curr_cmd\n");
+                               if (adapter->ps_state == PS_STATE_SLEEP_CFM) {
+                                       mwifiex_process_sleep_confirm_resp(
+                                                       adapter, skb->data,
+                                                       skb->len);
+                                       ret = 0;
+                                       goto exit_restore_skb;
+                               }
+                               ret = -1;
+                               goto exit_restore_skb;
+                       }
+
+                       adapter->curr_cmd->resp_skb = skb;
+                       adapter->cmd_resp_received = true;
+                       break;
+               case MWIFIEX_USB_TYPE_EVENT:
+                       if (skb->len < sizeof(u32)) {
+                               mwifiex_dbg(adapter, ERROR,
+                                           "EVENT: skb->len too small\n");
+                               ret = -1;
+                               goto exit_restore_skb;
+                       }
+                       skb_copy_from_linear_data(skb, &tmp, sizeof(u32));
+                       adapter->event_cause = le32_to_cpu(tmp);
+                       mwifiex_dbg(adapter, EVENT,
+                                   "event_cause %#x\n", adapter->event_cause);
+
+                       if (skb->len > MAX_EVENT_SIZE) {
+                               mwifiex_dbg(adapter, ERROR,
+                                           "EVENT: event body too large\n");
+                               ret = -1;
+                               goto exit_restore_skb;
+                       }
+
+                       memcpy(adapter->event_body, skb->data +
+                              MWIFIEX_EVENT_HEADER_LEN, skb->len);
+
+                       adapter->event_received = true;
+                       adapter->event_skb = skb;
+                       break;
+               default:
+                       mwifiex_dbg(adapter, ERROR,
+                                   "unknown recv_type %#x\n", recv_type);
+                       return -1;
+               }
+               break;
+       case MWIFIEX_USB_EP_DATA:
+               mwifiex_dbg(adapter, DATA, "%s: EP_DATA\n", __func__);
+               if (skb->len > MWIFIEX_RX_DATA_BUF_SIZE) {
+                       mwifiex_dbg(adapter, ERROR,
+                                   "DATA: skb->len too large\n");
+                       return -1;
+               }
+
+               skb_queue_tail(&adapter->rx_data_q, skb);
+               adapter->data_received = true;
+               atomic_inc(&adapter->rx_pending);
+               break;
+       default:
+               mwifiex_dbg(adapter, ERROR,
+                           "%s: unknown endport %#x\n", __func__, ep);
+               return -1;
+       }
+
+       return -EINPROGRESS;
+
+exit_restore_skb:
+       /* The buffer will be reused for further cmds/events */
+       skb_push(skb, INTF_HEADER_LEN);
+
+       return ret;
+}
+
+static void mwifiex_usb_rx_complete(struct urb *urb)
+{
+       struct urb_context *context = (struct urb_context *)urb->context;
+       struct mwifiex_adapter *adapter = context->adapter;
+       struct sk_buff *skb = context->skb;
+       struct usb_card_rec *card;
+       int recv_length = urb->actual_length;
+       int size, status;
+
+       if (!adapter || !adapter->card) {
+               pr_err("mwifiex adapter or card structure is not valid\n");
+               return;
+       }
+
+       card = (struct usb_card_rec *)adapter->card;
+       if (card->rx_cmd_ep == context->ep)
+               atomic_dec(&card->rx_cmd_urb_pending);
+       else
+               atomic_dec(&card->rx_data_urb_pending);
+
+       if (recv_length) {
+               if (urb->status || (adapter->surprise_removed)) {
+                       mwifiex_dbg(adapter, ERROR,
+                                   "URB status is failed: %d\n", urb->status);
+                       /* Do not free skb in case of command ep */
+                       if (card->rx_cmd_ep != context->ep)
+                               dev_kfree_skb_any(skb);
+                       goto setup_for_next;
+               }
+               if (skb->len > recv_length)
+                       skb_trim(skb, recv_length);
+               else
+                       skb_put(skb, recv_length - skb->len);
+
+               status = mwifiex_usb_recv(adapter, skb, context->ep);
+
+               mwifiex_dbg(adapter, INFO,
+                           "info: recv_length=%d, status=%d\n",
+                           recv_length, status);
+               if (status == -EINPROGRESS) {
+                       mwifiex_queue_main_work(adapter);
+
+                       /* urb for data_ep is re-submitted now;
+                        * urb for cmd_ep will be re-submitted in callback
+                        * mwifiex_usb_recv_complete
+                        */
+                       if (card->rx_cmd_ep == context->ep)
+                               return;
+               } else {
+                       if (status == -1)
+                               mwifiex_dbg(adapter, ERROR,
+                                           "received data processing failed!\n");
+
+                       /* Do not free skb in case of command ep */
+                       if (card->rx_cmd_ep != context->ep)
+                               dev_kfree_skb_any(skb);
+               }
+       } else if (urb->status) {
+               if (!adapter->is_suspended) {
+                       mwifiex_dbg(adapter, FATAL,
+                                   "Card is removed: %d\n", urb->status);
+                       adapter->surprise_removed = true;
+               }
+               dev_kfree_skb_any(skb);
+               return;
+       } else {
+               /* Do not free skb in case of command ep */
+               if (card->rx_cmd_ep != context->ep)
+                       dev_kfree_skb_any(skb);
+
+               /* fall through setup_for_next */
+       }
+
+setup_for_next:
+       if (card->rx_cmd_ep == context->ep)
+               size = MWIFIEX_RX_CMD_BUF_SIZE;
+       else
+               size = MWIFIEX_RX_DATA_BUF_SIZE;
+
+       if (card->rx_cmd_ep == context->ep) {
+               mwifiex_usb_submit_rx_urb(context, size);
+       } else {
+               if (atomic_read(&adapter->rx_pending) <= HIGH_RX_PENDING){
+                       mwifiex_usb_submit_rx_urb(context, size);
+               }else{
+                       context->skb = NULL;
+               }
+       }
+
+       return;
+}
+
+static void mwifiex_usb_tx_complete(struct urb *urb)
+{
+       struct urb_context *context = (struct urb_context *)(urb->context);
+       struct mwifiex_adapter *adapter = context->adapter;
+       struct usb_card_rec *card = adapter->card;
+       struct usb_tx_data_port *port;
+       int i;
+
+       mwifiex_dbg(adapter, INFO,
+                   "%s: status: %d\n", __func__, urb->status);
+
+       if (context->ep == card->tx_cmd_ep) {
+               mwifiex_dbg(adapter, CMD,
+                           "%s: CMD\n", __func__);
+               atomic_dec(&card->tx_cmd_urb_pending);
+               adapter->cmd_sent = false;
+       } else {
+               mwifiex_dbg(adapter, DATA,
+                           "%s: DATA\n", __func__);
+               for (i = 0; i < MWIFIEX_TX_DATA_PORT; i++) {
+                       port = &card->port[i];
+                       if (context->ep == port->tx_data_ep) {
+                               atomic_dec(&port->tx_data_urb_pending);
+                               port->block_status = false;
+                               break;
+                       }
+               }
+               adapter->data_sent = false;
+               mwifiex_write_data_complete(adapter, context->skb, 0,
+                                           urb->status ? -1 : 0);
+       }
+
+       if (card->mc_resync_flag)
+               mwifiex_multi_chan_resync(adapter);
+
+       mwifiex_queue_main_work(adapter);
+
+       return;
+}
+
+static int mwifiex_usb_submit_rx_urb(struct urb_context *ctx, int size)
+{
+       struct mwifiex_adapter *adapter = ctx->adapter;
+       struct usb_card_rec *card = (struct usb_card_rec *)adapter->card;
+
+       if (card->rx_cmd_ep != ctx->ep) {
+               ctx->skb = dev_alloc_skb(size);
+               if (!ctx->skb) {
+                       mwifiex_dbg(adapter, ERROR,
+                                   "%s: dev_alloc_skb failed\n", __func__);
+                       return -ENOMEM;
+               }
+       }
+
+       usb_fill_bulk_urb(ctx->urb, card->udev,
+                         usb_rcvbulkpipe(card->udev, ctx->ep), ctx->skb->data,
+                         size, mwifiex_usb_rx_complete, (void *)ctx);
+
+       if (card->rx_cmd_ep == ctx->ep)
+               atomic_inc(&card->rx_cmd_urb_pending);
+       else
+               atomic_inc(&card->rx_data_urb_pending);
+
+       if (usb_submit_urb(ctx->urb, GFP_ATOMIC)) {
+               mwifiex_dbg(adapter, ERROR, "usb_submit_urb failed\n");
+               dev_kfree_skb_any(ctx->skb);
+               ctx->skb = NULL;
+
+               if (card->rx_cmd_ep == ctx->ep)
+                       atomic_dec(&card->rx_cmd_urb_pending);
+               else
+                       atomic_dec(&card->rx_data_urb_pending);
+
+               return -1;
+       }
+
+       return 0;
+}
+
+static void mwifiex_usb_free(struct usb_card_rec *card)
+{
+       struct usb_tx_data_port *port;
+       int i, j;
+
+       if (atomic_read(&card->rx_cmd_urb_pending) && card->rx_cmd.urb)
+               usb_kill_urb(card->rx_cmd.urb);
+
+       usb_free_urb(card->rx_cmd.urb);
+       card->rx_cmd.urb = NULL;
+
+       if (atomic_read(&card->rx_data_urb_pending))
+               for (i = 0; i < MWIFIEX_RX_DATA_URB; i++)
+                       if (card->rx_data_list[i].urb)
+                               usb_kill_urb(card->rx_data_list[i].urb);
+
+       for (i = 0; i < MWIFIEX_RX_DATA_URB; i++) {
+               usb_free_urb(card->rx_data_list[i].urb);
+               card->rx_data_list[i].urb = NULL;
+       }
+
+       for (i = 0; i < MWIFIEX_TX_DATA_PORT; i++) {
+               port = &card->port[i];
+               for (j = 0; j < MWIFIEX_TX_DATA_URB; j++) {
+                       usb_free_urb(port->tx_data_list[j].urb);
+                       port->tx_data_list[j].urb = NULL;
+               }
+       }
+
+       usb_free_urb(card->tx_cmd.urb);
+       card->tx_cmd.urb = NULL;
+
+       return;
+}
+
+/* This function probes an mwifiex device and registers it. It allocates
+ * the card structure, initiates the device registration and initialization
+ * procedure by adding a logical interface.
+ */
+static int mwifiex_usb_probe(struct usb_interface *intf,
+                            const struct usb_device_id *id)
+{
+       struct usb_device *udev = interface_to_usbdev(intf);
+       struct usb_host_interface *iface_desc = intf->cur_altsetting;
+       struct usb_endpoint_descriptor *epd;
+       int ret, i;
+       struct usb_card_rec *card;
+       u16 id_vendor, id_product, bcd_device, bcd_usb;
+
+       card = kzalloc(sizeof(struct usb_card_rec), GFP_KERNEL);
+       if (!card)
+               return -ENOMEM;
+
+       id_vendor = le16_to_cpu(udev->descriptor.idVendor);
+       id_product = le16_to_cpu(udev->descriptor.idProduct);
+       bcd_device = le16_to_cpu(udev->descriptor.bcdDevice);
+       bcd_usb = le16_to_cpu(udev->descriptor.bcdUSB);
+       pr_debug("info: VID/PID = %X/%X, Boot2 version = %X\n",
+                id_vendor, id_product, bcd_device);
+
+       /* PID_1 is used for firmware downloading only */
+       switch (id_product) {
+       case USB8766_PID_1:
+       case USB8797_PID_1:
+       case USB8801_PID_1:
+       case USB8997_PID_1:
+               card->usb_boot_state = USB8XXX_FW_DNLD;
+               break;
+       case USB8766_PID_2:
+       case USB8797_PID_2:
+       case USB8801_PID_2:
+       case USB8997_PID_2:
+               card->usb_boot_state = USB8XXX_FW_READY;
+               break;
+       default:
+               pr_warn("unknown id_product %#x\n", id_product);
+               card->usb_boot_state = USB8XXX_FW_DNLD;
+               break;
+       }
+
+       card->udev = udev;
+       card->intf = intf;
+
+       pr_debug("info: bcdUSB=%#x Device Class=%#x SubClass=%#x Protocol=%#x\n",
+                udev->descriptor.bcdUSB, udev->descriptor.bDeviceClass,
+                udev->descriptor.bDeviceSubClass,
+                udev->descriptor.bDeviceProtocol);
+
+       for (i = 0; i < iface_desc->desc.bNumEndpoints; ++i) {
+               epd = &iface_desc->endpoint[i].desc;
+               if (usb_endpoint_dir_in(epd) &&
+                   usb_endpoint_num(epd) == MWIFIEX_USB_EP_CMD_EVENT &&
+                   usb_endpoint_xfer_bulk(epd)) {
+                       pr_debug("info: bulk IN: max pkt size: %d, addr: %d\n",
+                                le16_to_cpu(epd->wMaxPacketSize),
+                                epd->bEndpointAddress);
+                       card->rx_cmd_ep = usb_endpoint_num(epd);
+                       atomic_set(&card->rx_cmd_urb_pending, 0);
+               }
+               if (usb_endpoint_dir_in(epd) &&
+                   usb_endpoint_num(epd) == MWIFIEX_USB_EP_DATA &&
+                   usb_endpoint_xfer_bulk(epd)) {
+                       pr_debug("info: bulk IN: max pkt size: %d, addr: %d\n",
+                                le16_to_cpu(epd->wMaxPacketSize),
+                                epd->bEndpointAddress);
+                       card->rx_data_ep = usb_endpoint_num(epd);
+                       atomic_set(&card->rx_data_urb_pending, 0);
+               }
+               if (usb_endpoint_dir_out(epd) &&
+                   usb_endpoint_num(epd) == MWIFIEX_USB_EP_DATA &&
+                   usb_endpoint_xfer_bulk(epd)) {
+                       pr_debug("info: bulk OUT: max pkt size: %d, addr: %d\n",
+                                le16_to_cpu(epd->wMaxPacketSize),
+                                epd->bEndpointAddress);
+                       card->port[0].tx_data_ep = usb_endpoint_num(epd);
+                       atomic_set(&card->port[0].tx_data_urb_pending, 0);
+               }
+               if (usb_endpoint_dir_out(epd) &&
+                   usb_endpoint_num(epd) == MWIFIEX_USB_EP_DATA_CH2 &&
+                   usb_endpoint_xfer_bulk(epd)) {
+                       pr_debug("info: bulk OUT chan2:\t"
+                                "max pkt size: %d, addr: %d\n",
+                                le16_to_cpu(epd->wMaxPacketSize),
+                                epd->bEndpointAddress);
+                       card->port[1].tx_data_ep = usb_endpoint_num(epd);
+                       atomic_set(&card->port[1].tx_data_urb_pending, 0);
+               }
+               if (usb_endpoint_dir_out(epd) &&
+                   usb_endpoint_num(epd) == MWIFIEX_USB_EP_CMD_EVENT &&
+                   usb_endpoint_xfer_bulk(epd)) {
+                       pr_debug("info: bulk OUT: max pkt size: %d, addr: %d\n",
+                                le16_to_cpu(epd->wMaxPacketSize),
+                                epd->bEndpointAddress);
+                       card->tx_cmd_ep = usb_endpoint_num(epd);
+                       atomic_set(&card->tx_cmd_urb_pending, 0);
+                       card->bulk_out_maxpktsize =
+                                       le16_to_cpu(epd->wMaxPacketSize);
+               }
+       }
+
+       usb_set_intfdata(intf, card);
+
+       ret = mwifiex_add_card(card, &add_remove_card_sem, &usb_ops,
+                              MWIFIEX_USB);
+       if (ret) {
+               pr_err("%s: mwifiex_add_card failed: %d\n", __func__, ret);
+               usb_reset_device(udev);
+               kfree(card);
+               return ret;
+       }
+
+       usb_get_dev(udev);
+
+       return 0;
+}
+
+/* Kernel needs to suspend all functions separately. Therefore all
+ * registered functions must have drivers with suspend and resume
+ * methods. Failing that the kernel simply removes the whole card.
+ *
+ * If already not suspended, this function allocates and sends a
+ * 'host sleep activate' request to the firmware and turns off the traffic.
+ */
+static int mwifiex_usb_suspend(struct usb_interface *intf, pm_message_t message)
+{
+       struct usb_card_rec *card = usb_get_intfdata(intf);
+       struct mwifiex_adapter *adapter;
+       struct usb_tx_data_port *port;
+       int i, j;
+
+       if (!card || !card->adapter) {
+               pr_err("%s: card or card->adapter is NULL\n", __func__);
+               return 0;
+       }
+       adapter = card->adapter;
+
+       if (unlikely(adapter->is_suspended))
+               mwifiex_dbg(adapter, WARN,
+                           "Device already suspended\n");
+
+       mwifiex_enable_hs(adapter);
+
+       /* 'is_suspended' flag indicates device is suspended.
+        * It must be set here before the usb_kill_urb() calls. Reason
+        * is in the complete handlers, urb->status(= -ENOENT) and
+        * this flag is used in combination to distinguish between a
+        * 'suspended' state and a 'disconnect' one.
+        */
+       adapter->is_suspended = true;
+       adapter->hs_enabling = false;
+
+       if (atomic_read(&card->rx_cmd_urb_pending) && card->rx_cmd.urb)
+               usb_kill_urb(card->rx_cmd.urb);
+
+       if (atomic_read(&card->rx_data_urb_pending))
+               for (i = 0; i < MWIFIEX_RX_DATA_URB; i++)
+                       if (card->rx_data_list[i].urb)
+                               usb_kill_urb(card->rx_data_list[i].urb);
+
+       for (i = 0; i < MWIFIEX_TX_DATA_PORT; i++) {
+               port = &card->port[i];
+               for (j = 0; j < MWIFIEX_TX_DATA_URB; j++) {
+                       if (port->tx_data_list[j].urb)
+                               usb_kill_urb(port->tx_data_list[j].urb);
+               }
+       }
+
+       if (card->tx_cmd.urb)
+               usb_kill_urb(card->tx_cmd.urb);
+
+       return 0;
+}
+
+/* Kernel needs to suspend all functions separately. Therefore all
+ * registered functions must have drivers with suspend and resume
+ * methods. Failing that the kernel simply removes the whole card.
+ *
+ * If already not resumed, this function turns on the traffic and
+ * sends a 'host sleep cancel' request to the firmware.
+ */
+static int mwifiex_usb_resume(struct usb_interface *intf)
+{
+       struct usb_card_rec *card = usb_get_intfdata(intf);
+       struct mwifiex_adapter *adapter;
+       int i;
+
+       if (!card || !card->adapter) {
+               pr_err("%s: card or card->adapter is NULL\n", __func__);
+               return 0;
+       }
+       adapter = card->adapter;
+
+       if (unlikely(!adapter->is_suspended)) {
+               mwifiex_dbg(adapter, WARN,
+                           "Device already resumed\n");
+               return 0;
+       }
+
+       /* Indicate device resumed. The netdev queue will be resumed only
+        * after the urbs have been re-submitted
+        */
+       adapter->is_suspended = false;
+
+       if (!atomic_read(&card->rx_data_urb_pending))
+               for (i = 0; i < MWIFIEX_RX_DATA_URB; i++)
+                       mwifiex_usb_submit_rx_urb(&card->rx_data_list[i],
+                                                 MWIFIEX_RX_DATA_BUF_SIZE);
+
+       if (!atomic_read(&card->rx_cmd_urb_pending)) {
+               card->rx_cmd.skb = dev_alloc_skb(MWIFIEX_RX_CMD_BUF_SIZE);
+               if (card->rx_cmd.skb)
+                       mwifiex_usb_submit_rx_urb(&card->rx_cmd,
+                                                 MWIFIEX_RX_CMD_BUF_SIZE);
+       }
+
+       /* Disable Host Sleep */
+       if (adapter->hs_activated)
+               mwifiex_cancel_hs(mwifiex_get_priv(adapter,
+                                                  MWIFIEX_BSS_ROLE_ANY),
+                                 MWIFIEX_ASYNC_CMD);
+
+       return 0;
+}
+
+static void mwifiex_usb_disconnect(struct usb_interface *intf)
+{
+       struct usb_card_rec *card = usb_get_intfdata(intf);
+       struct mwifiex_adapter *adapter;
+
+       if (!card || !card->adapter) {
+               pr_err("%s: card or card->adapter is NULL\n", __func__);
+               return;
+       }
+
+       adapter = card->adapter;
+       if (!adapter->priv_num)
+               return;
+
+       if (user_rmmod) {
+#ifdef CONFIG_PM
+               if (adapter->is_suspended)
+                       mwifiex_usb_resume(intf);
+#endif
+
+               mwifiex_deauthenticate_all(adapter);
+
+               mwifiex_init_shutdown_fw(mwifiex_get_priv(adapter,
+                                                         MWIFIEX_BSS_ROLE_ANY),
+                                        MWIFIEX_FUNC_SHUTDOWN);
+       }
+
+       mwifiex_usb_free(card);
+
+       mwifiex_dbg(adapter, FATAL,
+                   "%s: removing card\n", __func__);
+       mwifiex_remove_card(adapter, &add_remove_card_sem);
+
+       usb_set_intfdata(intf, NULL);
+       usb_put_dev(interface_to_usbdev(intf));
+       kfree(card);
+
+       return;
+}
+
+static struct usb_driver mwifiex_usb_driver = {
+       .name = "mwifiex_usb",
+       .probe = mwifiex_usb_probe,
+       .disconnect = mwifiex_usb_disconnect,
+       .id_table = mwifiex_usb_table,
+       .suspend = mwifiex_usb_suspend,
+       .resume = mwifiex_usb_resume,
+       .soft_unbind = 1,
+};
+
+static int mwifiex_usb_tx_init(struct mwifiex_adapter *adapter)
+{
+       struct usb_card_rec *card = (struct usb_card_rec *)adapter->card;
+       struct usb_tx_data_port *port;
+       int i, j;
+
+       card->tx_cmd.adapter = adapter;
+       card->tx_cmd.ep = card->tx_cmd_ep;
+
+       card->tx_cmd.urb = usb_alloc_urb(0, GFP_KERNEL);
+       if (!card->tx_cmd.urb) {
+               mwifiex_dbg(adapter, ERROR,
+                           "tx_cmd.urb allocation failed\n");
+               return -ENOMEM;
+       }
+
+       for (i = 0; i < MWIFIEX_TX_DATA_PORT; i++) {
+               port = &card->port[i];
+               if (!port->tx_data_ep)
+                       continue;
+               port->tx_data_ix = 0;
+               if (port->tx_data_ep == MWIFIEX_USB_EP_DATA)
+                       port->block_status = false;
+               else
+                       port->block_status = true;
+               for (j = 0; j < MWIFIEX_TX_DATA_URB; j++) {
+                       port->tx_data_list[j].adapter = adapter;
+                       port->tx_data_list[j].ep = port->tx_data_ep;
+                       port->tx_data_list[j].urb =
+                                       usb_alloc_urb(0, GFP_KERNEL);
+                       if (!port->tx_data_list[j].urb) {
+                               mwifiex_dbg(adapter, ERROR,
+                                           "urb allocation failed\n");
+                               return -ENOMEM;
+                       }
+               }
+       }
+
+       return 0;
+}
+
+static int mwifiex_usb_rx_init(struct mwifiex_adapter *adapter)
+{
+       struct usb_card_rec *card = (struct usb_card_rec *)adapter->card;
+       int i;
+
+       card->rx_cmd.adapter = adapter;
+       card->rx_cmd.ep = card->rx_cmd_ep;
+
+       card->rx_cmd.urb = usb_alloc_urb(0, GFP_KERNEL);
+       if (!card->rx_cmd.urb) {
+               mwifiex_dbg(adapter, ERROR, "rx_cmd.urb allocation failed\n");
+               return -ENOMEM;
+       }
+
+       card->rx_cmd.skb = dev_alloc_skb(MWIFIEX_RX_CMD_BUF_SIZE);
+       if (!card->rx_cmd.skb)
+               return -ENOMEM;
+
+       if (mwifiex_usb_submit_rx_urb(&card->rx_cmd, MWIFIEX_RX_CMD_BUF_SIZE))
+               return -1;
+
+       for (i = 0; i < MWIFIEX_RX_DATA_URB; i++) {
+               card->rx_data_list[i].adapter = adapter;
+               card->rx_data_list[i].ep = card->rx_data_ep;
+
+               card->rx_data_list[i].urb = usb_alloc_urb(0, GFP_KERNEL);
+               if (!card->rx_data_list[i].urb) {
+                       mwifiex_dbg(adapter, ERROR,
+                                   "rx_data_list[] urb allocation failed\n");
+                       return -1;
+               }
+               if (mwifiex_usb_submit_rx_urb(&card->rx_data_list[i],
+                                             MWIFIEX_RX_DATA_BUF_SIZE))
+                       return -1;
+       }
+
+       return 0;
+}
+
+static int mwifiex_write_data_sync(struct mwifiex_adapter *adapter, u8 *pbuf,
+                                  u32 *len, u8 ep, u32 timeout)
+{
+       struct usb_card_rec *card = adapter->card;
+       int actual_length, ret;
+
+       if (!(*len % card->bulk_out_maxpktsize))
+               (*len)++;
+
+       /* Send the data block */
+       ret = usb_bulk_msg(card->udev, usb_sndbulkpipe(card->udev, ep), pbuf,
+                          *len, &actual_length, timeout);
+       if (ret) {
+               mwifiex_dbg(adapter, ERROR,
+                           "usb_bulk_msg for tx failed: %d\n", ret);
+               return ret;
+       }
+
+       *len = actual_length;
+
+       return ret;
+}
+
+static int mwifiex_read_data_sync(struct mwifiex_adapter *adapter, u8 *pbuf,
+                                 u32 *len, u8 ep, u32 timeout)
+{
+       struct usb_card_rec *card = adapter->card;
+       int actual_length, ret;
+
+       /* Receive the data response */
+       ret = usb_bulk_msg(card->udev, usb_rcvbulkpipe(card->udev, ep), pbuf,
+                          *len, &actual_length, timeout);
+       if (ret) {
+               mwifiex_dbg(adapter, ERROR,
+                           "usb_bulk_msg for rx failed: %d\n", ret);
+               return ret;
+       }
+
+       *len = actual_length;
+
+       return ret;
+}
+
+static void mwifiex_usb_port_resync(struct mwifiex_adapter *adapter)
+{
+       struct usb_card_rec *card = adapter->card;
+       u8 active_port = MWIFIEX_USB_EP_DATA;
+       struct mwifiex_private *priv = NULL;
+       int i;
+
+       if (adapter->usb_mc_status) {
+               for (i = 0; i < adapter->priv_num; i++) {
+                       priv = adapter->priv[i];
+                       if (!priv)
+                               continue;
+                       if ((priv->bss_role == MWIFIEX_BSS_ROLE_UAP &&
+                            !priv->bss_started) ||
+                           (priv->bss_role == MWIFIEX_BSS_ROLE_STA &&
+                            !priv->media_connected))
+                               priv->usb_port = MWIFIEX_USB_EP_DATA;
+               }
+               for (i = 0; i < MWIFIEX_TX_DATA_PORT; i++)
+                       card->port[i].block_status = false;
+       } else {
+               for (i = 0; i < adapter->priv_num; i++) {
+                       priv = adapter->priv[i];
+                       if (!priv)
+                               continue;
+                       if ((priv->bss_role == MWIFIEX_BSS_ROLE_UAP &&
+                            priv->bss_started) ||
+                           (priv->bss_role == MWIFIEX_BSS_ROLE_STA &&
+                            priv->media_connected)) {
+                               active_port = priv->usb_port;
+                               break;
+                       }
+               }
+               for (i = 0; i < adapter->priv_num; i++) {
+                       priv = adapter->priv[i];
+                       if (priv)
+                               priv->usb_port = active_port;
+               }
+               for (i = 0; i < MWIFIEX_TX_DATA_PORT; i++) {
+                       if (active_port == card->port[i].tx_data_ep)
+                               card->port[i].block_status = false;
+                       else
+                               card->port[i].block_status = true;
+               }
+       }
+}
+
+static bool mwifiex_usb_is_port_ready(struct mwifiex_private *priv)
+{
+       struct usb_card_rec *card = priv->adapter->card;
+       int idx;
+
+       for (idx = 0; idx < MWIFIEX_TX_DATA_PORT; idx++) {
+               if (priv->usb_port == card->port[idx].tx_data_ep)
+                       return !card->port[idx].block_status;
+       }
+
+       return false;
+}
+
+static inline u8 mwifiex_usb_data_sent(struct mwifiex_adapter *adapter)
+{
+       struct usb_card_rec *card = adapter->card;
+       int i;
+
+       for (i = 0; i < MWIFIEX_TX_DATA_PORT; i++)
+               if (!card->port[i].block_status)
+                       return false;
+
+       return true;
+}
+
+/* This function write a command/data packet to card. */
+static int mwifiex_usb_host_to_card(struct mwifiex_adapter *adapter, u8 ep,
+                                   struct sk_buff *skb,
+                                   struct mwifiex_tx_param *tx_param)
+{
+       struct usb_card_rec *card = adapter->card;
+       struct urb_context *context = NULL;
+       struct usb_tx_data_port *port = NULL;
+       u8 *data = (u8 *)skb->data;
+       struct urb *tx_urb;
+       int idx, ret;
+
+       if (adapter->is_suspended) {
+               mwifiex_dbg(adapter, ERROR,
+                           "%s: not allowed while suspended\n", __func__);
+               return -1;
+       }
+
+       if (adapter->surprise_removed) {
+               mwifiex_dbg(adapter, ERROR, "%s: device removed\n", __func__);
+               return -1;
+       }
+
+       mwifiex_dbg(adapter, INFO, "%s: ep=%d\n", __func__, ep);
+
+       if (ep == card->tx_cmd_ep) {
+               context = &card->tx_cmd;
+       } else {
+               for (idx = 0; idx < MWIFIEX_TX_DATA_PORT; idx++) {
+                       if (ep == card->port[idx].tx_data_ep) {
+                               port = &card->port[idx];
+                               if (atomic_read(&port->tx_data_urb_pending)
+                                   >= MWIFIEX_TX_DATA_URB) {
+                                       port->block_status = true;
+                                       ret = -EBUSY;
+                                       goto done;
+                               }
+                               if (port->tx_data_ix >= MWIFIEX_TX_DATA_URB)
+                                       port->tx_data_ix = 0;
+                               context =
+                                       &port->tx_data_list[port->tx_data_ix++];
+                               break;
+                       }
+               }
+               if (!port) {
+                       mwifiex_dbg(adapter, ERROR, "Wrong usb tx data port\n");
+                       return -1;
+               }
+       }
+
+       context->adapter = adapter;
+       context->ep = ep;
+       context->skb = skb;
+       tx_urb = context->urb;
+
+       usb_fill_bulk_urb(tx_urb, card->udev, usb_sndbulkpipe(card->udev, ep),
+                         data, skb->len, mwifiex_usb_tx_complete,
+                         (void *)context);
+
+       tx_urb->transfer_flags |= URB_ZERO_PACKET;
+
+       if (ep == card->tx_cmd_ep)
+               atomic_inc(&card->tx_cmd_urb_pending);
+       else
+               atomic_inc(&port->tx_data_urb_pending);
+
+       if (usb_submit_urb(tx_urb, GFP_ATOMIC)) {
+               mwifiex_dbg(adapter, ERROR,
+                           "%s: usb_submit_urb failed\n", __func__);
+               if (ep == card->tx_cmd_ep) {
+                       atomic_dec(&card->tx_cmd_urb_pending);
+               } else {
+                       atomic_dec(&port->tx_data_urb_pending);
+                       port->block_status = false;
+                       if (port->tx_data_ix)
+                               port->tx_data_ix--;
+                       else
+                               port->tx_data_ix = MWIFIEX_TX_DATA_URB;
+               }
+
+               return -1;
+       } else {
+               if (ep != card->tx_cmd_ep &&
+                   atomic_read(&port->tx_data_urb_pending) ==
+                                                       MWIFIEX_TX_DATA_URB) {
+                       port->block_status = true;
+                       ret = -ENOSR;
+                       goto done;
+               }
+       }
+
+       return -EINPROGRESS;
+
+done:
+       if (ep != card->tx_cmd_ep)
+               adapter->data_sent = mwifiex_usb_data_sent(adapter);
+
+       return ret;
+}
+
+/* This function register usb device and initialize parameter. */
+static int mwifiex_register_dev(struct mwifiex_adapter *adapter)
+{
+       struct usb_card_rec *card = (struct usb_card_rec *)adapter->card;
+
+       card->adapter = adapter;
+       adapter->dev = &card->udev->dev;
+
+       switch (le16_to_cpu(card->udev->descriptor.idProduct)) {
+       case USB8997_PID_1:
+       case USB8997_PID_2:
+               adapter->tx_buf_size = MWIFIEX_TX_DATA_BUF_SIZE_4K;
+               strcpy(adapter->fw_name, USB8997_DEFAULT_FW_NAME);
+               adapter->ext_scan = true;
+               break;
+       case USB8766_PID_1:
+       case USB8766_PID_2:
+               adapter->tx_buf_size = MWIFIEX_TX_DATA_BUF_SIZE_2K;
+               strcpy(adapter->fw_name, USB8766_DEFAULT_FW_NAME);
+               adapter->ext_scan = true;
+               break;
+       case USB8801_PID_1:
+       case USB8801_PID_2:
+               adapter->tx_buf_size = MWIFIEX_TX_DATA_BUF_SIZE_2K;
+               strcpy(adapter->fw_name, USB8801_DEFAULT_FW_NAME);
+               adapter->ext_scan = false;
+               break;
+       case USB8797_PID_1:
+       case USB8797_PID_2:
+       default:
+               adapter->tx_buf_size = MWIFIEX_TX_DATA_BUF_SIZE_2K;
+               strcpy(adapter->fw_name, USB8797_DEFAULT_FW_NAME);
+               break;
+       }
+
+       adapter->usb_mc_status = false;
+       adapter->usb_mc_setup = false;
+
+       return 0;
+}
+
+static void mwifiex_unregister_dev(struct mwifiex_adapter *adapter)
+{
+       struct usb_card_rec *card = (struct usb_card_rec *)adapter->card;
+
+       card->adapter = NULL;
+}
+
+static int mwifiex_prog_fw_w_helper(struct mwifiex_adapter *adapter,
+                                   struct mwifiex_fw_image *fw)
+{
+       int ret = 0;
+       u8 *firmware = fw->fw_buf, *recv_buff;
+       u32 retries = USB8XXX_FW_MAX_RETRY, dlen;
+       u32 fw_seqnum = 0, tlen = 0, dnld_cmd = 0;
+       struct fw_data *fwdata;
+       struct fw_sync_header sync_fw;
+       u8 check_winner = 1;
+
+       if (!firmware) {
+               mwifiex_dbg(adapter, ERROR,
+                           "No firmware image found! Terminating download\n");
+               ret = -1;
+               goto fw_exit;
+       }
+
+       /* Allocate memory for transmit */
+       fwdata = kzalloc(FW_DNLD_TX_BUF_SIZE, GFP_KERNEL);
+       if (!fwdata) {
+               ret = -ENOMEM;
+               goto fw_exit;
+       }
+
+       /* Allocate memory for receive */
+       recv_buff = kzalloc(FW_DNLD_RX_BUF_SIZE, GFP_KERNEL);
+       if (!recv_buff)
+               goto cleanup;
+
+       do {
+               /* Send pseudo data to check winner status first */
+               if (check_winner) {
+                       memset(&fwdata->fw_hdr, 0, sizeof(struct fw_header));
+                       dlen = 0;
+               } else {
+                       /* copy the header of the fw_data to get the length */
+                       memcpy(&fwdata->fw_hdr, &firmware[tlen],
+                              sizeof(struct fw_header));
+
+                       dlen = le32_to_cpu(fwdata->fw_hdr.data_len);
+                       dnld_cmd = le32_to_cpu(fwdata->fw_hdr.dnld_cmd);
+                       tlen += sizeof(struct fw_header);
+
+                       memcpy(fwdata->data, &firmware[tlen], dlen);
+
+                       fwdata->seq_num = cpu_to_le32(fw_seqnum);
+                       tlen += dlen;
+               }
+
+               /* If the send/receive fails or CRC occurs then retry */
+               while (retries--) {
+                       u8 *buf = (u8 *)fwdata;
+                       u32 len = FW_DATA_XMIT_SIZE;
+
+                       /* send the firmware block */
+                       ret = mwifiex_write_data_sync(adapter, buf, &len,
+                                               MWIFIEX_USB_EP_CMD_EVENT,
+                                               MWIFIEX_USB_TIMEOUT);
+                       if (ret) {
+                               mwifiex_dbg(adapter, ERROR,
+                                           "write_data_sync: failed: %d\n",
+                                           ret);
+                               continue;
+                       }
+
+                       buf = recv_buff;
+                       len = FW_DNLD_RX_BUF_SIZE;
+
+                       /* Receive the firmware block response */
+                       ret = mwifiex_read_data_sync(adapter, buf, &len,
+                                               MWIFIEX_USB_EP_CMD_EVENT,
+                                               MWIFIEX_USB_TIMEOUT);
+                       if (ret) {
+                               mwifiex_dbg(adapter, ERROR,
+                                           "read_data_sync: failed: %d\n",
+                                           ret);
+                               continue;
+                       }
+
+                       memcpy(&sync_fw, recv_buff,
+                              sizeof(struct fw_sync_header));
+
+                       /* check 1st firmware block resp for highest bit set */
+                       if (check_winner) {
+                               if (le32_to_cpu(sync_fw.cmd) & 0x80000000) {
+                                       mwifiex_dbg(adapter, WARN,
+                                                   "USB is not the winner %#x\n",
+                                                   sync_fw.cmd);
+
+                                       /* returning success */
+                                       ret = 0;
+                                       goto cleanup;
+                               }
+
+                               mwifiex_dbg(adapter, MSG,
+                                           "start to download FW...\n");
+
+                               check_winner = 0;
+                               break;
+                       }
+
+                       /* check the firmware block response for CRC errors */
+                       if (sync_fw.cmd) {
+                               mwifiex_dbg(adapter, ERROR,
+                                           "FW received block with CRC %#x\n",
+                                           sync_fw.cmd);
+                               ret = -1;
+                               continue;
+                       }
+
+                       retries = USB8XXX_FW_MAX_RETRY;
+                       break;
+               }
+               fw_seqnum++;
+       } while ((dnld_cmd != FW_HAS_LAST_BLOCK) && retries);
+
+cleanup:
+       mwifiex_dbg(adapter, MSG,
+                   "info: FW download over, size %d bytes\n", tlen);
+
+       kfree(recv_buff);
+       kfree(fwdata);
+
+       if (retries)
+               ret = 0;
+fw_exit:
+       return ret;
+}
+
+static int mwifiex_usb_dnld_fw(struct mwifiex_adapter *adapter,
+                       struct mwifiex_fw_image *fw)
+{
+       int ret;
+       struct usb_card_rec *card = (struct usb_card_rec *)adapter->card;
+
+       if (card->usb_boot_state == USB8XXX_FW_DNLD) {
+               ret = mwifiex_prog_fw_w_helper(adapter, fw);
+               if (ret)
+                       return -1;
+
+               /* Boot state changes after successful firmware download */
+               if (card->usb_boot_state == USB8XXX_FW_DNLD)
+                       return -1;
+       }
+
+       ret = mwifiex_usb_rx_init(adapter);
+       if (!ret)
+               ret = mwifiex_usb_tx_init(adapter);
+
+       return ret;
+}
+
+static void mwifiex_submit_rx_urb(struct mwifiex_adapter *adapter, u8 ep)
+{
+       struct usb_card_rec *card = (struct usb_card_rec *)adapter->card;
+
+       skb_push(card->rx_cmd.skb, INTF_HEADER_LEN);
+       if ((ep == card->rx_cmd_ep) &&
+           (!atomic_read(&card->rx_cmd_urb_pending)))
+               mwifiex_usb_submit_rx_urb(&card->rx_cmd,
+                                         MWIFIEX_RX_CMD_BUF_SIZE);
+
+       return;
+}
+
+static int mwifiex_usb_cmd_event_complete(struct mwifiex_adapter *adapter,
+                                      struct sk_buff *skb)
+{
+       mwifiex_submit_rx_urb(adapter, MWIFIEX_USB_EP_CMD_EVENT);
+
+       return 0;
+}
+
+/* This function wakes up the card. */
+static int mwifiex_pm_wakeup_card(struct mwifiex_adapter *adapter)
+{
+       /* Simulation of HS_AWAKE event */
+       adapter->pm_wakeup_fw_try = false;
+       del_timer(&adapter->wakeup_timer);
+       adapter->pm_wakeup_card_req = false;
+       adapter->ps_state = PS_STATE_AWAKE;
+
+       return 0;
+}
+
+static void mwifiex_usb_submit_rem_rx_urbs(struct mwifiex_adapter *adapter)
+{
+       struct usb_card_rec *card = (struct usb_card_rec *)adapter->card;
+       int i;
+       struct urb_context *ctx;
+
+       for (i = 0; i < MWIFIEX_RX_DATA_URB; i++) {
+               if (card->rx_data_list[i].skb)
+                       continue;
+               ctx = &card->rx_data_list[i];
+               mwifiex_usb_submit_rx_urb(ctx, MWIFIEX_RX_DATA_BUF_SIZE);
+       }
+}
+
+/* This function is called after the card has woken up. */
+static inline int
+mwifiex_pm_wakeup_card_complete(struct mwifiex_adapter *adapter)
+{
+       return 0;
+}
+
+static struct mwifiex_if_ops usb_ops = {
+       .register_dev =         mwifiex_register_dev,
+       .unregister_dev =       mwifiex_unregister_dev,
+       .wakeup =               mwifiex_pm_wakeup_card,
+       .wakeup_complete =      mwifiex_pm_wakeup_card_complete,
+
+       /* USB specific */
+       .dnld_fw =              mwifiex_usb_dnld_fw,
+       .cmdrsp_complete =      mwifiex_usb_cmd_event_complete,
+       .event_complete =       mwifiex_usb_cmd_event_complete,
+       .host_to_card =         mwifiex_usb_host_to_card,
+       .submit_rem_rx_urbs =   mwifiex_usb_submit_rem_rx_urbs,
+       .multi_port_resync =    mwifiex_usb_port_resync,
+       .is_port_ready =        mwifiex_usb_is_port_ready,
+};
+
+/* This function initializes the USB driver module.
+ *
+ * This initiates the semaphore and registers the device with
+ * USB bus.
+ */
+static int mwifiex_usb_init_module(void)
+{
+       int ret;
+
+       pr_debug("Marvell USB8797 Driver\n");
+
+       sema_init(&add_remove_card_sem, 1);
+
+       ret = usb_register(&mwifiex_usb_driver);
+       if (ret)
+               pr_err("Driver register failed!\n");
+       else
+               pr_debug("info: Driver registered successfully!\n");
+
+       return ret;
+}
+
+/* This function cleans up the USB driver.
+ *
+ * The following major steps are followed in .disconnect for cleanup:
+ *      - Resume the device if its suspended
+ *      - Disconnect the device if connected
+ *      - Shutdown the firmware
+ *      - Unregister the device from USB bus.
+ */
+static void mwifiex_usb_cleanup_module(void)
+{
+       if (!down_interruptible(&add_remove_card_sem))
+               up(&add_remove_card_sem);
+
+       /* set the flag as user is removing this module */
+       user_rmmod = 1;
+
+       usb_deregister(&mwifiex_usb_driver);
+}
+
+module_init(mwifiex_usb_init_module);
+module_exit(mwifiex_usb_cleanup_module);
+
+MODULE_AUTHOR("Marvell International Ltd.");
+MODULE_DESCRIPTION("Marvell WiFi-Ex USB Driver version" USB_VERSION);
+MODULE_VERSION(USB_VERSION);
+MODULE_LICENSE("GPL v2");
+MODULE_FIRMWARE(USB8766_DEFAULT_FW_NAME);
+MODULE_FIRMWARE(USB8797_DEFAULT_FW_NAME);
+MODULE_FIRMWARE(USB8801_DEFAULT_FW_NAME);
+MODULE_FIRMWARE(USB8997_DEFAULT_FW_NAME);
diff --git a/drivers/net/wireless/marvell/mwifiex/usb.h b/drivers/net/wireless/marvell/mwifiex/usb.h
new file mode 100644 (file)
index 0000000..b4e9246
--- /dev/null
@@ -0,0 +1,110 @@
+/*
+ * This file contains definitions for mwifiex USB interface driver.
+ *
+ * Copyright (C) 2012-2014, Marvell International Ltd.
+ *
+ * This software file (the "File") is distributed by Marvell International
+ * Ltd. under the terms of the GNU General Public License Version 2, June 1991
+ * (the "License").  You may use, redistribute and/or modify this File in
+ * accordance with the terms and conditions of the License, a copy of which
+ * is available by writing to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the
+ * worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
+ *
+ * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
+ * ARE EXPRESSLY DISCLAIMED.  The License provides additional details about
+ * this warranty disclaimer.
+ */
+
+#ifndef _MWIFIEX_USB_H
+#define _MWIFIEX_USB_H
+
+#include <linux/usb.h>
+
+#define USB8XXX_VID            0x1286
+
+#define USB8766_PID_1          0x2041
+#define USB8766_PID_2          0x2042
+#define USB8797_PID_1          0x2043
+#define USB8797_PID_2          0x2044
+#define USB8801_PID_1          0x2049
+#define USB8801_PID_2          0x204a
+#define USB8997_PID_1          0x2052
+#define USB8997_PID_2          0x204e
+
+
+#define USB8XXX_FW_DNLD                1
+#define USB8XXX_FW_READY       2
+#define USB8XXX_FW_MAX_RETRY   3
+
+#define MWIFIEX_TX_DATA_PORT   2
+#define MWIFIEX_TX_DATA_URB    6
+#define MWIFIEX_RX_DATA_URB    6
+#define MWIFIEX_USB_TIMEOUT    100
+
+#define USB8766_DEFAULT_FW_NAME        "mrvl/usb8766_uapsta.bin"
+#define USB8797_DEFAULT_FW_NAME        "mrvl/usb8797_uapsta.bin"
+#define USB8801_DEFAULT_FW_NAME        "mrvl/usb8801_uapsta.bin"
+#define USB8997_DEFAULT_FW_NAME        "mrvl/usb8997_uapsta.bin"
+
+#define FW_DNLD_TX_BUF_SIZE    620
+#define FW_DNLD_RX_BUF_SIZE    2048
+#define FW_HAS_LAST_BLOCK      0x00000004
+
+#define FW_DATA_XMIT_SIZE \
+       (sizeof(struct fw_header) + dlen + sizeof(u32))
+
+struct urb_context {
+       struct mwifiex_adapter *adapter;
+       struct sk_buff *skb;
+       struct urb *urb;
+       u8 ep;
+};
+
+struct usb_tx_data_port {
+       u8 tx_data_ep;
+       u8 block_status;
+       atomic_t tx_data_urb_pending;
+       int tx_data_ix;
+       struct urb_context tx_data_list[MWIFIEX_TX_DATA_URB];
+};
+
+struct usb_card_rec {
+       struct mwifiex_adapter *adapter;
+       struct usb_device *udev;
+       struct usb_interface *intf;
+       u8 rx_cmd_ep;
+       struct urb_context rx_cmd;
+       atomic_t rx_cmd_urb_pending;
+       struct urb_context rx_data_list[MWIFIEX_RX_DATA_URB];
+       u8 usb_boot_state;
+       u8 rx_data_ep;
+       atomic_t rx_data_urb_pending;
+       u8 tx_cmd_ep;
+       atomic_t tx_cmd_urb_pending;
+       int bulk_out_maxpktsize;
+       struct urb_context tx_cmd;
+       u8 mc_resync_flag;
+       struct usb_tx_data_port port[MWIFIEX_TX_DATA_PORT];
+};
+
+struct fw_header {
+       __le32 dnld_cmd;
+       __le32 base_addr;
+       __le32 data_len;
+       __le32 crc;
+};
+
+struct fw_sync_header {
+       __le32 cmd;
+       __le32 seq_num;
+};
+
+struct fw_data {
+       struct fw_header fw_hdr;
+       __le32 seq_num;
+       u8 data[1];
+};
+
+#endif /*_MWIFIEX_USB_H */
diff --git a/drivers/net/wireless/marvell/mwifiex/util.c b/drivers/net/wireless/marvell/mwifiex/util.c
new file mode 100644 (file)
index 0000000..0cec8a6
--- /dev/null
@@ -0,0 +1,751 @@
+/*
+ * Marvell Wireless LAN device driver: utility functions
+ *
+ * Copyright (C) 2011-2014, Marvell International Ltd.
+ *
+ * This software file (the "File") is distributed by Marvell International
+ * Ltd. under the terms of the GNU General Public License Version 2, June 1991
+ * (the "License").  You may use, redistribute and/or modify this File in
+ * accordance with the terms and conditions of the License, a copy of which
+ * is available by writing to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the
+ * worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
+ *
+ * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
+ * ARE EXPRESSLY DISCLAIMED.  The License provides additional details about
+ * this warranty disclaimer.
+ */
+
+#include "decl.h"
+#include "ioctl.h"
+#include "util.h"
+#include "fw.h"
+#include "main.h"
+#include "wmm.h"
+#include "11n.h"
+
+static struct mwifiex_debug_data items[] = {
+       {"debug_mask", item_size(debug_mask),
+        item_addr(debug_mask), 1},
+       {"int_counter", item_size(int_counter),
+        item_addr(int_counter), 1},
+       {"wmm_ac_vo", item_size(packets_out[WMM_AC_VO]),
+        item_addr(packets_out[WMM_AC_VO]), 1},
+       {"wmm_ac_vi", item_size(packets_out[WMM_AC_VI]),
+        item_addr(packets_out[WMM_AC_VI]), 1},
+       {"wmm_ac_be", item_size(packets_out[WMM_AC_BE]),
+        item_addr(packets_out[WMM_AC_BE]), 1},
+       {"wmm_ac_bk", item_size(packets_out[WMM_AC_BK]),
+        item_addr(packets_out[WMM_AC_BK]), 1},
+       {"tx_buf_size", item_size(tx_buf_size),
+        item_addr(tx_buf_size), 1},
+       {"curr_tx_buf_size", item_size(curr_tx_buf_size),
+        item_addr(curr_tx_buf_size), 1},
+       {"ps_mode", item_size(ps_mode),
+        item_addr(ps_mode), 1},
+       {"ps_state", item_size(ps_state),
+        item_addr(ps_state), 1},
+       {"is_deep_sleep", item_size(is_deep_sleep),
+        item_addr(is_deep_sleep), 1},
+       {"wakeup_dev_req", item_size(pm_wakeup_card_req),
+        item_addr(pm_wakeup_card_req), 1},
+       {"wakeup_tries", item_size(pm_wakeup_fw_try),
+        item_addr(pm_wakeup_fw_try), 1},
+       {"hs_configured", item_size(is_hs_configured),
+        item_addr(is_hs_configured), 1},
+       {"hs_activated", item_size(hs_activated),
+        item_addr(hs_activated), 1},
+       {"num_tx_timeout", item_size(num_tx_timeout),
+        item_addr(num_tx_timeout), 1},
+       {"is_cmd_timedout", item_size(is_cmd_timedout),
+        item_addr(is_cmd_timedout), 1},
+       {"timeout_cmd_id", item_size(timeout_cmd_id),
+        item_addr(timeout_cmd_id), 1},
+       {"timeout_cmd_act", item_size(timeout_cmd_act),
+        item_addr(timeout_cmd_act), 1},
+       {"last_cmd_id", item_size(last_cmd_id),
+        item_addr(last_cmd_id), DBG_CMD_NUM},
+       {"last_cmd_act", item_size(last_cmd_act),
+        item_addr(last_cmd_act), DBG_CMD_NUM},
+       {"last_cmd_index", item_size(last_cmd_index),
+        item_addr(last_cmd_index), 1},
+       {"last_cmd_resp_id", item_size(last_cmd_resp_id),
+        item_addr(last_cmd_resp_id), DBG_CMD_NUM},
+       {"last_cmd_resp_index", item_size(last_cmd_resp_index),
+        item_addr(last_cmd_resp_index), 1},
+       {"last_event", item_size(last_event),
+        item_addr(last_event), DBG_CMD_NUM},
+       {"last_event_index", item_size(last_event_index),
+        item_addr(last_event_index), 1},
+       {"num_cmd_h2c_fail", item_size(num_cmd_host_to_card_failure),
+        item_addr(num_cmd_host_to_card_failure), 1},
+       {"num_cmd_sleep_cfm_fail",
+        item_size(num_cmd_sleep_cfm_host_to_card_failure),
+        item_addr(num_cmd_sleep_cfm_host_to_card_failure), 1},
+       {"num_tx_h2c_fail", item_size(num_tx_host_to_card_failure),
+        item_addr(num_tx_host_to_card_failure), 1},
+       {"num_evt_deauth", item_size(num_event_deauth),
+        item_addr(num_event_deauth), 1},
+       {"num_evt_disassoc", item_size(num_event_disassoc),
+        item_addr(num_event_disassoc), 1},
+       {"num_evt_link_lost", item_size(num_event_link_lost),
+        item_addr(num_event_link_lost), 1},
+       {"num_cmd_deauth", item_size(num_cmd_deauth),
+        item_addr(num_cmd_deauth), 1},
+       {"num_cmd_assoc_ok", item_size(num_cmd_assoc_success),
+        item_addr(num_cmd_assoc_success), 1},
+       {"num_cmd_assoc_fail", item_size(num_cmd_assoc_failure),
+        item_addr(num_cmd_assoc_failure), 1},
+       {"cmd_sent", item_size(cmd_sent),
+        item_addr(cmd_sent), 1},
+       {"data_sent", item_size(data_sent),
+        item_addr(data_sent), 1},
+       {"cmd_resp_received", item_size(cmd_resp_received),
+        item_addr(cmd_resp_received), 1},
+       {"event_received", item_size(event_received),
+        item_addr(event_received), 1},
+
+       /* variables defined in struct mwifiex_adapter */
+       {"cmd_pending", adapter_item_size(cmd_pending),
+        adapter_item_addr(cmd_pending), 1},
+       {"tx_pending", adapter_item_size(tx_pending),
+        adapter_item_addr(tx_pending), 1},
+       {"rx_pending", adapter_item_size(rx_pending),
+        adapter_item_addr(rx_pending), 1},
+};
+
+static int num_of_items = ARRAY_SIZE(items);
+
+/*
+ * Firmware initialization complete callback handler.
+ *
+ * This function wakes up the function waiting on the init
+ * wait queue for the firmware initialization to complete.
+ */
+int mwifiex_init_fw_complete(struct mwifiex_adapter *adapter)
+{
+
+       if (adapter->hw_status == MWIFIEX_HW_STATUS_READY)
+               if (adapter->if_ops.init_fw_port)
+                       adapter->if_ops.init_fw_port(adapter);
+
+       adapter->init_wait_q_woken = true;
+       wake_up_interruptible(&adapter->init_wait_q);
+       return 0;
+}
+
+/*
+ * Firmware shutdown complete callback handler.
+ *
+ * This function sets the hardware status to not ready and wakes up
+ * the function waiting on the init wait queue for the firmware
+ * shutdown to complete.
+ */
+int mwifiex_shutdown_fw_complete(struct mwifiex_adapter *adapter)
+{
+       adapter->hw_status = MWIFIEX_HW_STATUS_NOT_READY;
+       adapter->init_wait_q_woken = true;
+       wake_up_interruptible(&adapter->init_wait_q);
+       return 0;
+}
+
+/*
+ * This function sends init/shutdown command
+ * to firmware.
+ */
+int mwifiex_init_shutdown_fw(struct mwifiex_private *priv,
+                            u32 func_init_shutdown)
+{
+       u16 cmd;
+
+       if (func_init_shutdown == MWIFIEX_FUNC_INIT) {
+               cmd = HostCmd_CMD_FUNC_INIT;
+       } else if (func_init_shutdown == MWIFIEX_FUNC_SHUTDOWN) {
+               cmd = HostCmd_CMD_FUNC_SHUTDOWN;
+       } else {
+               mwifiex_dbg(priv->adapter, ERROR,
+                           "unsupported parameter\n");
+               return -1;
+       }
+
+       return mwifiex_send_cmd(priv, cmd, HostCmd_ACT_GEN_SET, 0, NULL, true);
+}
+EXPORT_SYMBOL_GPL(mwifiex_init_shutdown_fw);
+
+/*
+ * IOCTL request handler to set/get debug information.
+ *
+ * This function collates/sets the information from/to different driver
+ * structures.
+ */
+int mwifiex_get_debug_info(struct mwifiex_private *priv,
+                          struct mwifiex_debug_info *info)
+{
+       struct mwifiex_adapter *adapter = priv->adapter;
+
+       if (info) {
+               info->debug_mask = adapter->debug_mask;
+               memcpy(info->packets_out,
+                      priv->wmm.packets_out,
+                      sizeof(priv->wmm.packets_out));
+               info->curr_tx_buf_size = (u32) adapter->curr_tx_buf_size;
+               info->tx_buf_size = (u32) adapter->tx_buf_size;
+               info->rx_tbl_num = mwifiex_get_rx_reorder_tbl(priv,
+                                                             info->rx_tbl);
+               info->tx_tbl_num = mwifiex_get_tx_ba_stream_tbl(priv,
+                                                               info->tx_tbl);
+               info->tdls_peer_num = mwifiex_get_tdls_list(priv,
+                                                           info->tdls_list);
+               info->ps_mode = adapter->ps_mode;
+               info->ps_state = adapter->ps_state;
+               info->is_deep_sleep = adapter->is_deep_sleep;
+               info->pm_wakeup_card_req = adapter->pm_wakeup_card_req;
+               info->pm_wakeup_fw_try = adapter->pm_wakeup_fw_try;
+               info->is_hs_configured = adapter->is_hs_configured;
+               info->hs_activated = adapter->hs_activated;
+               info->is_cmd_timedout = adapter->is_cmd_timedout;
+               info->num_cmd_host_to_card_failure
+                               = adapter->dbg.num_cmd_host_to_card_failure;
+               info->num_cmd_sleep_cfm_host_to_card_failure
+                       = adapter->dbg.num_cmd_sleep_cfm_host_to_card_failure;
+               info->num_tx_host_to_card_failure
+                               = adapter->dbg.num_tx_host_to_card_failure;
+               info->num_event_deauth = adapter->dbg.num_event_deauth;
+               info->num_event_disassoc = adapter->dbg.num_event_disassoc;
+               info->num_event_link_lost = adapter->dbg.num_event_link_lost;
+               info->num_cmd_deauth = adapter->dbg.num_cmd_deauth;
+               info->num_cmd_assoc_success =
+                                       adapter->dbg.num_cmd_assoc_success;
+               info->num_cmd_assoc_failure =
+                                       adapter->dbg.num_cmd_assoc_failure;
+               info->num_tx_timeout = adapter->dbg.num_tx_timeout;
+               info->timeout_cmd_id = adapter->dbg.timeout_cmd_id;
+               info->timeout_cmd_act = adapter->dbg.timeout_cmd_act;
+               memcpy(info->last_cmd_id, adapter->dbg.last_cmd_id,
+                      sizeof(adapter->dbg.last_cmd_id));
+               memcpy(info->last_cmd_act, adapter->dbg.last_cmd_act,
+                      sizeof(adapter->dbg.last_cmd_act));
+               info->last_cmd_index = adapter->dbg.last_cmd_index;
+               memcpy(info->last_cmd_resp_id, adapter->dbg.last_cmd_resp_id,
+                      sizeof(adapter->dbg.last_cmd_resp_id));
+               info->last_cmd_resp_index = adapter->dbg.last_cmd_resp_index;
+               memcpy(info->last_event, adapter->dbg.last_event,
+                      sizeof(adapter->dbg.last_event));
+               info->last_event_index = adapter->dbg.last_event_index;
+               info->data_sent = adapter->data_sent;
+               info->cmd_sent = adapter->cmd_sent;
+               info->cmd_resp_received = adapter->cmd_resp_received;
+       }
+
+       return 0;
+}
+
+int mwifiex_debug_info_to_buffer(struct mwifiex_private *priv, char *buf,
+                                struct mwifiex_debug_info *info)
+{
+       char *p = buf;
+       struct mwifiex_debug_data *d = &items[0];
+       size_t size, addr;
+       long val;
+       int i, j;
+
+       if (!info)
+               return 0;
+
+       for (i = 0; i < num_of_items; i++) {
+               p += sprintf(p, "%s=", d[i].name);
+
+               size = d[i].size / d[i].num;
+
+               if (i < (num_of_items - 3))
+                       addr = d[i].addr + (size_t)info;
+               else /* The last 3 items are struct mwifiex_adapter variables */
+                       addr = d[i].addr + (size_t)priv->adapter;
+
+               for (j = 0; j < d[i].num; j++) {
+                       switch (size) {
+                       case 1:
+                               val = *((u8 *)addr);
+                               break;
+                       case 2:
+                               val = *((u16 *)addr);
+                               break;
+                       case 4:
+                               val = *((u32 *)addr);
+                               break;
+                       case 8:
+                               val = *((long long *)addr);
+                               break;
+                       default:
+                               val = -1;
+                               break;
+                       }
+
+                       p += sprintf(p, "%#lx ", val);
+                       addr += size;
+               }
+
+               p += sprintf(p, "\n");
+       }
+
+       if (info->tx_tbl_num) {
+               p += sprintf(p, "Tx BA stream table:\n");
+               for (i = 0; i < info->tx_tbl_num; i++)
+                       p += sprintf(p, "tid = %d, ra = %pM\n",
+                                    info->tx_tbl[i].tid, info->tx_tbl[i].ra);
+       }
+
+       if (info->rx_tbl_num) {
+               p += sprintf(p, "Rx reorder table:\n");
+               for (i = 0; i < info->rx_tbl_num; i++) {
+                       p += sprintf(p, "tid = %d, ta = %pM, ",
+                                    info->rx_tbl[i].tid,
+                                    info->rx_tbl[i].ta);
+                       p += sprintf(p, "start_win = %d, ",
+                                    info->rx_tbl[i].start_win);
+                       p += sprintf(p, "win_size = %d, buffer: ",
+                                    info->rx_tbl[i].win_size);
+
+                       for (j = 0; j < info->rx_tbl[i].win_size; j++)
+                               p += sprintf(p, "%c ",
+                                            info->rx_tbl[i].buffer[j] ?
+                                            '1' : '0');
+
+                       p += sprintf(p, "\n");
+               }
+       }
+
+       if (info->tdls_peer_num) {
+               p += sprintf(p, "TDLS peer table:\n");
+               for (i = 0; i < info->tdls_peer_num; i++) {
+                       p += sprintf(p, "peer = %pM",
+                                    info->tdls_list[i].peer_addr);
+                       p += sprintf(p, "\n");
+               }
+       }
+
+       return p - buf;
+}
+
+static int
+mwifiex_parse_mgmt_packet(struct mwifiex_private *priv, u8 *payload, u16 len,
+                         struct rxpd *rx_pd)
+{
+       u16 stype;
+       u8 category, action_code, *addr2;
+       struct ieee80211_hdr *ieee_hdr = (void *)payload;
+
+       stype = (le16_to_cpu(ieee_hdr->frame_control) & IEEE80211_FCTL_STYPE);
+
+       switch (stype) {
+       case IEEE80211_STYPE_ACTION:
+               category = *(payload + sizeof(struct ieee80211_hdr));
+               switch (category) {
+               case WLAN_CATEGORY_PUBLIC:
+                       action_code = *(payload + sizeof(struct ieee80211_hdr)
+                                       + 1);
+                       if (action_code == WLAN_PUB_ACTION_TDLS_DISCOVER_RES) {
+                               addr2 = ieee_hdr->addr2;
+                               mwifiex_dbg(priv->adapter, INFO,
+                                           "TDLS discovery response %pM nf=%d, snr=%d\n",
+                                           addr2, rx_pd->nf, rx_pd->snr);
+                               mwifiex_auto_tdls_update_peer_signal(priv,
+                                                                    addr2,
+                                                                    rx_pd->snr,
+                                                                    rx_pd->nf);
+                       }
+                       break;
+               case WLAN_CATEGORY_BACK:
+                       /*we dont indicate BACK action frames to cfg80211*/
+                       mwifiex_dbg(priv->adapter, INFO,
+                                   "drop BACK action frames");
+                       return -1;
+               default:
+                       mwifiex_dbg(priv->adapter, INFO,
+                                   "unknown public action frame category %d\n",
+                                   category);
+               }
+       default:
+               mwifiex_dbg(priv->adapter, INFO,
+                   "unknown mgmt frame subtype %#x\n", stype);
+               return 0;
+       }
+
+       return 0;
+}
+/*
+ * This function processes the received management packet and send it
+ * to the kernel.
+ */
+int
+mwifiex_process_mgmt_packet(struct mwifiex_private *priv,
+                           struct sk_buff *skb)
+{
+       struct rxpd *rx_pd;
+       u16 pkt_len;
+       struct ieee80211_hdr *ieee_hdr;
+
+       if (!skb)
+               return -1;
+
+       if (!priv->mgmt_frame_mask ||
+           priv->wdev.iftype == NL80211_IFTYPE_UNSPECIFIED) {
+               mwifiex_dbg(priv->adapter, ERROR,
+                           "do not receive mgmt frames on uninitialized intf");
+               return -1;
+       }
+
+       rx_pd = (struct rxpd *)skb->data;
+
+       skb_pull(skb, le16_to_cpu(rx_pd->rx_pkt_offset));
+       skb_pull(skb, sizeof(pkt_len));
+
+       pkt_len = le16_to_cpu(rx_pd->rx_pkt_length);
+
+       ieee_hdr = (void *)skb->data;
+       if (ieee80211_is_mgmt(ieee_hdr->frame_control)) {
+               if (mwifiex_parse_mgmt_packet(priv, (u8 *)ieee_hdr,
+                                             pkt_len, rx_pd))
+                       return -1;
+       }
+       /* Remove address4 */
+       memmove(skb->data + sizeof(struct ieee80211_hdr_3addr),
+               skb->data + sizeof(struct ieee80211_hdr),
+               pkt_len - sizeof(struct ieee80211_hdr));
+
+       pkt_len -= ETH_ALEN + sizeof(pkt_len);
+       rx_pd->rx_pkt_length = cpu_to_le16(pkt_len);
+
+       cfg80211_rx_mgmt(&priv->wdev, priv->roc_cfg.chan.center_freq,
+                        CAL_RSSI(rx_pd->snr, rx_pd->nf), skb->data, pkt_len,
+                        0);
+
+       return 0;
+}
+
+/*
+ * This function processes the received packet before sending it to the
+ * kernel.
+ *
+ * It extracts the SKB from the received buffer and sends it to kernel.
+ * In case the received buffer does not contain the data in SKB format,
+ * the function creates a blank SKB, fills it with the data from the
+ * received buffer and then sends this new SKB to the kernel.
+ */
+int mwifiex_recv_packet(struct mwifiex_private *priv, struct sk_buff *skb)
+{
+       struct mwifiex_sta_node *src_node;
+       struct ethhdr *p_ethhdr;
+
+       if (!skb)
+               return -1;
+
+       priv->stats.rx_bytes += skb->len;
+       priv->stats.rx_packets++;
+
+       if (GET_BSS_ROLE(priv) == MWIFIEX_BSS_ROLE_UAP) {
+               p_ethhdr = (void *)skb->data;
+               src_node = mwifiex_get_sta_entry(priv, p_ethhdr->h_source);
+               if (src_node) {
+                       src_node->stats.last_rx = jiffies;
+                       src_node->stats.rx_bytes += skb->len;
+                       src_node->stats.rx_packets++;
+               }
+       }
+
+       skb->dev = priv->netdev;
+       skb->protocol = eth_type_trans(skb, priv->netdev);
+       skb->ip_summed = CHECKSUM_NONE;
+
+       /* This is required only in case of 11n and USB/PCIE as we alloc
+        * a buffer of 4K only if its 11N (to be able to receive 4K
+        * AMSDU packets). In case of SD we allocate buffers based
+        * on the size of packet and hence this is not needed.
+        *
+        * Modifying the truesize here as our allocation for each
+        * skb is 4K but we only receive 2K packets and this cause
+        * the kernel to start dropping packets in case where
+        * application has allocated buffer based on 2K size i.e.
+        * if there a 64K packet received (in IP fragments and
+        * application allocates 64K to receive this packet but
+        * this packet would almost double up because we allocate
+        * each 1.5K fragment in 4K and pass it up. As soon as the
+        * 64K limit hits kernel will start to drop rest of the
+        * fragments. Currently we fail the Filesndl-ht.scr script
+        * for UDP, hence this fix
+        */
+       if ((priv->adapter->iface_type == MWIFIEX_USB ||
+            priv->adapter->iface_type == MWIFIEX_PCIE) &&
+           (skb->truesize > MWIFIEX_RX_DATA_BUF_SIZE))
+               skb->truesize += (skb->len - MWIFIEX_RX_DATA_BUF_SIZE);
+
+       if (in_interrupt())
+               netif_rx(skb);
+       else
+               netif_rx_ni(skb);
+
+       return 0;
+}
+
+/*
+ * IOCTL completion callback handler.
+ *
+ * This function is called when a pending IOCTL is completed.
+ *
+ * If work queue support is enabled, the function wakes up the
+ * corresponding waiting function. Otherwise, it processes the
+ * IOCTL response and frees the response buffer.
+ */
+int mwifiex_complete_cmd(struct mwifiex_adapter *adapter,
+                        struct cmd_ctrl_node *cmd_node)
+{
+       WARN_ON(!cmd_node->wait_q_enabled);
+       mwifiex_dbg(adapter, CMD, "cmd completed: status=%d\n",
+                   adapter->cmd_wait_q.status);
+
+       *cmd_node->condition = true;
+       wake_up_interruptible(&adapter->cmd_wait_q.wait);
+
+       return 0;
+}
+
+/* This function will return the pointer to station entry in station list
+ * table which matches specified mac address.
+ * This function should be called after acquiring RA list spinlock.
+ * NULL is returned if station entry is not found in associated STA list.
+ */
+struct mwifiex_sta_node *
+mwifiex_get_sta_entry(struct mwifiex_private *priv, const u8 *mac)
+{
+       struct mwifiex_sta_node *node;
+
+       if (!mac)
+               return NULL;
+
+       list_for_each_entry(node, &priv->sta_list, list) {
+               if (!memcmp(node->mac_addr, mac, ETH_ALEN))
+                       return node;
+       }
+
+       return NULL;
+}
+
+static struct mwifiex_sta_node *
+mwifiex_get_tdls_sta_entry(struct mwifiex_private *priv, u8 status)
+{
+       struct mwifiex_sta_node *node;
+
+       list_for_each_entry(node, &priv->sta_list, list) {
+               if (node->tdls_status == status)
+                       return node;
+       }
+
+       return NULL;
+}
+
+/* If tdls channel switching is on-going, tx data traffic should be
+ * blocked until the switching stage completed.
+ */
+u8 mwifiex_is_tdls_chan_switching(struct mwifiex_private *priv)
+{
+       struct mwifiex_sta_node *sta_ptr;
+
+       if (!priv || !ISSUPP_TDLS_ENABLED(priv->adapter->fw_cap_info))
+               return false;
+
+       sta_ptr = mwifiex_get_tdls_sta_entry(priv, TDLS_CHAN_SWITCHING);
+       if (sta_ptr)
+               return true;
+
+       return false;
+}
+
+u8 mwifiex_is_tdls_off_chan(struct mwifiex_private *priv)
+{
+       struct mwifiex_sta_node *sta_ptr;
+
+       if (!priv || !ISSUPP_TDLS_ENABLED(priv->adapter->fw_cap_info))
+               return false;
+
+       sta_ptr = mwifiex_get_tdls_sta_entry(priv, TDLS_IN_OFF_CHAN);
+       if (sta_ptr)
+               return true;
+
+       return false;
+}
+
+/* If tdls channel switching is on-going or tdls operate on off-channel,
+ * cmd path should be blocked until tdls switched to base-channel.
+ */
+u8 mwifiex_is_send_cmd_allowed(struct mwifiex_private *priv)
+{
+       if (!priv || !ISSUPP_TDLS_ENABLED(priv->adapter->fw_cap_info))
+               return true;
+
+       if (mwifiex_is_tdls_chan_switching(priv) ||
+           mwifiex_is_tdls_off_chan(priv))
+               return false;
+
+       return true;
+}
+
+/* This function will add a sta_node entry to associated station list
+ * table with the given mac address.
+ * If entry exist already, existing entry is returned.
+ * If received mac address is NULL, NULL is returned.
+ */
+struct mwifiex_sta_node *
+mwifiex_add_sta_entry(struct mwifiex_private *priv, const u8 *mac)
+{
+       struct mwifiex_sta_node *node;
+       unsigned long flags;
+
+       if (!mac)
+               return NULL;
+
+       spin_lock_irqsave(&priv->sta_list_spinlock, flags);
+       node = mwifiex_get_sta_entry(priv, mac);
+       if (node)
+               goto done;
+
+       node = kzalloc(sizeof(*node), GFP_ATOMIC);
+       if (!node)
+               goto done;
+
+       memcpy(node->mac_addr, mac, ETH_ALEN);
+       list_add_tail(&node->list, &priv->sta_list);
+
+done:
+       spin_unlock_irqrestore(&priv->sta_list_spinlock, flags);
+       return node;
+}
+
+/* This function will search for HT IE in association request IEs
+ * and set station HT parameters accordingly.
+ */
+void
+mwifiex_set_sta_ht_cap(struct mwifiex_private *priv, const u8 *ies,
+                      int ies_len, struct mwifiex_sta_node *node)
+{
+       struct ieee_types_header *ht_cap_ie;
+       const struct ieee80211_ht_cap *ht_cap;
+
+       if (!ies)
+               return;
+
+       ht_cap_ie = (void *)cfg80211_find_ie(WLAN_EID_HT_CAPABILITY, ies,
+                                            ies_len);
+       if (ht_cap_ie) {
+               ht_cap = (void *)(ht_cap_ie + 1);
+               node->is_11n_enabled = 1;
+               node->max_amsdu = le16_to_cpu(ht_cap->cap_info) &
+                                 IEEE80211_HT_CAP_MAX_AMSDU ?
+                                 MWIFIEX_TX_DATA_BUF_SIZE_8K :
+                                 MWIFIEX_TX_DATA_BUF_SIZE_4K;
+       } else {
+               node->is_11n_enabled = 0;
+       }
+
+       return;
+}
+
+/* This function will delete a station entry from station list */
+void mwifiex_del_sta_entry(struct mwifiex_private *priv, const u8 *mac)
+{
+       struct mwifiex_sta_node *node;
+       unsigned long flags;
+
+       spin_lock_irqsave(&priv->sta_list_spinlock, flags);
+
+       node = mwifiex_get_sta_entry(priv, mac);
+       if (node) {
+               list_del(&node->list);
+               kfree(node);
+       }
+
+       spin_unlock_irqrestore(&priv->sta_list_spinlock, flags);
+       return;
+}
+
+/* This function will delete all stations from associated station list. */
+void mwifiex_del_all_sta_list(struct mwifiex_private *priv)
+{
+       struct mwifiex_sta_node *node, *tmp;
+       unsigned long flags;
+
+       spin_lock_irqsave(&priv->sta_list_spinlock, flags);
+
+       list_for_each_entry_safe(node, tmp, &priv->sta_list, list) {
+               list_del(&node->list);
+               kfree(node);
+       }
+
+       INIT_LIST_HEAD(&priv->sta_list);
+       spin_unlock_irqrestore(&priv->sta_list_spinlock, flags);
+       return;
+}
+
+/* This function adds histogram data to histogram array*/
+void mwifiex_hist_data_add(struct mwifiex_private *priv,
+                          u8 rx_rate, s8 snr, s8 nflr)
+{
+       struct mwifiex_histogram_data *phist_data = priv->hist_data;
+
+       if (atomic_read(&phist_data->num_samples) > MWIFIEX_HIST_MAX_SAMPLES)
+               mwifiex_hist_data_reset(priv);
+       mwifiex_hist_data_set(priv, rx_rate, snr, nflr);
+}
+
+/* function to add histogram record */
+void mwifiex_hist_data_set(struct mwifiex_private *priv, u8 rx_rate, s8 snr,
+                          s8 nflr)
+{
+       struct mwifiex_histogram_data *phist_data = priv->hist_data;
+
+       atomic_inc(&phist_data->num_samples);
+       atomic_inc(&phist_data->rx_rate[rx_rate]);
+       atomic_inc(&phist_data->snr[snr]);
+       atomic_inc(&phist_data->noise_flr[128 + nflr]);
+       atomic_inc(&phist_data->sig_str[nflr - snr]);
+}
+
+/* function to reset histogram data during init/reset */
+void mwifiex_hist_data_reset(struct mwifiex_private *priv)
+{
+       int ix;
+       struct mwifiex_histogram_data *phist_data = priv->hist_data;
+
+       atomic_set(&phist_data->num_samples, 0);
+       for (ix = 0; ix < MWIFIEX_MAX_AC_RX_RATES; ix++)
+               atomic_set(&phist_data->rx_rate[ix], 0);
+       for (ix = 0; ix < MWIFIEX_MAX_SNR; ix++)
+               atomic_set(&phist_data->snr[ix], 0);
+       for (ix = 0; ix < MWIFIEX_MAX_NOISE_FLR; ix++)
+               atomic_set(&phist_data->noise_flr[ix], 0);
+       for (ix = 0; ix < MWIFIEX_MAX_SIG_STRENGTH; ix++)
+               atomic_set(&phist_data->sig_str[ix], 0);
+}
+
+void *mwifiex_alloc_dma_align_buf(int rx_len, gfp_t flags)
+{
+       struct sk_buff *skb;
+       int buf_len, pad;
+
+       buf_len = rx_len + MWIFIEX_RX_HEADROOM + MWIFIEX_DMA_ALIGN_SZ;
+
+       skb = __dev_alloc_skb(buf_len, flags);
+
+       if (!skb)
+               return NULL;
+
+       skb_reserve(skb, MWIFIEX_RX_HEADROOM);
+
+       pad = MWIFIEX_ALIGN_ADDR(skb->data, MWIFIEX_DMA_ALIGN_SZ) -
+             (long)skb->data;
+
+       skb_reserve(skb, pad);
+
+       return skb;
+}
+EXPORT_SYMBOL_GPL(mwifiex_alloc_dma_align_buf);
diff --git a/drivers/net/wireless/marvell/mwifiex/util.h b/drivers/net/wireless/marvell/mwifiex/util.h
new file mode 100644 (file)
index 0000000..b541d66
--- /dev/null
@@ -0,0 +1,96 @@
+/*
+ * Marvell Wireless LAN device driver: utility functions
+ *
+ * Copyright (C) 2011-2014, Marvell International Ltd.
+ *
+ * This software file (the "File") is distributed by Marvell International
+ * Ltd. under the terms of the GNU General Public License Version 2, June 1991
+ * (the "License").  You may use, redistribute and/or modify this File in
+ * accordance with the terms and conditions of the License, a copy of which
+ * is available by writing to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the
+ * worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
+ *
+ * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
+ * ARE EXPRESSLY DISCLAIMED.  The License provides additional details about
+ * this warranty disclaimer.
+ */
+
+#ifndef _MWIFIEX_UTIL_H_
+#define _MWIFIEX_UTIL_H_
+
+struct mwifiex_private;
+
+struct mwifiex_dma_mapping {
+       dma_addr_t addr;
+       size_t len;
+};
+
+struct mwifiex_cb {
+       struct mwifiex_dma_mapping dma_mapping;
+       union {
+               struct mwifiex_rxinfo rx_info;
+               struct mwifiex_txinfo tx_info;
+       };
+};
+
+/* size/addr for mwifiex_debug_info */
+#define item_size(n)           (FIELD_SIZEOF(struct mwifiex_debug_info, n))
+#define item_addr(n)           (offsetof(struct mwifiex_debug_info, n))
+
+/* size/addr for struct mwifiex_adapter */
+#define adapter_item_size(n)   (FIELD_SIZEOF(struct mwifiex_adapter, n))
+#define adapter_item_addr(n)   (offsetof(struct mwifiex_adapter, n))
+
+struct mwifiex_debug_data {
+       char name[32];          /* variable/array name */
+       u32 size;               /* size of the variable/array */
+       size_t addr;            /* address of the variable/array */
+       int num;                /* number of variables in an array */
+};
+
+static inline struct mwifiex_rxinfo *MWIFIEX_SKB_RXCB(struct sk_buff *skb)
+{
+       struct mwifiex_cb *cb = (struct mwifiex_cb *)skb->cb;
+
+       BUILD_BUG_ON(sizeof(struct mwifiex_cb) > sizeof(skb->cb));
+       return &cb->rx_info;
+}
+
+static inline struct mwifiex_txinfo *MWIFIEX_SKB_TXCB(struct sk_buff *skb)
+{
+       struct mwifiex_cb *cb = (struct mwifiex_cb *)skb->cb;
+
+       return &cb->tx_info;
+}
+
+static inline void mwifiex_store_mapping(struct sk_buff *skb,
+                                        struct mwifiex_dma_mapping *mapping)
+{
+       struct mwifiex_cb *cb = (struct mwifiex_cb *)skb->cb;
+
+       memcpy(&cb->dma_mapping, mapping, sizeof(*mapping));
+}
+
+static inline void mwifiex_get_mapping(struct sk_buff *skb,
+                                      struct mwifiex_dma_mapping *mapping)
+{
+       struct mwifiex_cb *cb = (struct mwifiex_cb *)skb->cb;
+
+       memcpy(mapping, &cb->dma_mapping, sizeof(*mapping));
+}
+
+static inline dma_addr_t MWIFIEX_SKB_DMA_ADDR(struct sk_buff *skb)
+{
+       struct mwifiex_dma_mapping mapping;
+
+       mwifiex_get_mapping(skb, &mapping);
+
+       return mapping.addr;
+}
+
+int mwifiex_debug_info_to_buffer(struct mwifiex_private *priv, char *buf,
+                                struct mwifiex_debug_info *info);
+
+#endif /* !_MWIFIEX_UTIL_H_ */
diff --git a/drivers/net/wireless/marvell/mwifiex/wmm.c b/drivers/net/wireless/marvell/mwifiex/wmm.c
new file mode 100644 (file)
index 0000000..acccd67
--- /dev/null
@@ -0,0 +1,1531 @@
+/*
+ * Marvell Wireless LAN device driver: WMM
+ *
+ * Copyright (C) 2011-2014, Marvell International Ltd.
+ *
+ * This software file (the "File") is distributed by Marvell International
+ * Ltd. under the terms of the GNU General Public License Version 2, June 1991
+ * (the "License").  You may use, redistribute and/or modify this File in
+ * accordance with the terms and conditions of the License, a copy of which
+ * is available by writing to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the
+ * worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
+ *
+ * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
+ * ARE EXPRESSLY DISCLAIMED.  The License provides additional details about
+ * this warranty disclaimer.
+ */
+
+#include "decl.h"
+#include "ioctl.h"
+#include "util.h"
+#include "fw.h"
+#include "main.h"
+#include "wmm.h"
+#include "11n.h"
+
+
+/* Maximum value FW can accept for driver delay in packet transmission */
+#define DRV_PKT_DELAY_TO_FW_MAX   512
+
+
+#define WMM_QUEUED_PACKET_LOWER_LIMIT   180
+
+#define WMM_QUEUED_PACKET_UPPER_LIMIT   200
+
+/* Offset for TOS field in the IP header */
+#define IPTOS_OFFSET 5
+
+static bool disable_tx_amsdu;
+module_param(disable_tx_amsdu, bool, 0644);
+
+/* WMM information IE */
+static const u8 wmm_info_ie[] = { WLAN_EID_VENDOR_SPECIFIC, 0x07,
+       0x00, 0x50, 0xf2, 0x02,
+       0x00, 0x01, 0x00
+};
+
+static const u8 wmm_aci_to_qidx_map[] = { WMM_AC_BE,
+       WMM_AC_BK,
+       WMM_AC_VI,
+       WMM_AC_VO
+};
+
+static u8 tos_to_tid[] = {
+       /* TID DSCP_P2 DSCP_P1 DSCP_P0 WMM_AC */
+       0x01,                   /* 0 1 0 AC_BK */
+       0x02,                   /* 0 0 0 AC_BK */
+       0x00,                   /* 0 0 1 AC_BE */
+       0x03,                   /* 0 1 1 AC_BE */
+       0x04,                   /* 1 0 0 AC_VI */
+       0x05,                   /* 1 0 1 AC_VI */
+       0x06,                   /* 1 1 0 AC_VO */
+       0x07                    /* 1 1 1 AC_VO */
+};
+
+static u8 ac_to_tid[4][2] = { {1, 2}, {0, 3}, {4, 5}, {6, 7} };
+
+/*
+ * This function debug prints the priority parameters for a WMM AC.
+ */
+static void
+mwifiex_wmm_ac_debug_print(const struct ieee_types_wmm_ac_parameters *ac_param)
+{
+       const char *ac_str[] = { "BK", "BE", "VI", "VO" };
+
+       pr_debug("info: WMM AC_%s: ACI=%d, ACM=%d, Aifsn=%d, "
+                "EcwMin=%d, EcwMax=%d, TxopLimit=%d\n",
+                ac_str[wmm_aci_to_qidx_map[(ac_param->aci_aifsn_bitmap
+                                            & MWIFIEX_ACI) >> 5]],
+                (ac_param->aci_aifsn_bitmap & MWIFIEX_ACI) >> 5,
+                (ac_param->aci_aifsn_bitmap & MWIFIEX_ACM) >> 4,
+                ac_param->aci_aifsn_bitmap & MWIFIEX_AIFSN,
+                ac_param->ecw_bitmap & MWIFIEX_ECW_MIN,
+                (ac_param->ecw_bitmap & MWIFIEX_ECW_MAX) >> 4,
+                le16_to_cpu(ac_param->tx_op_limit));
+}
+
+/*
+ * This function allocates a route address list.
+ *
+ * The function also initializes the list with the provided RA.
+ */
+static struct mwifiex_ra_list_tbl *
+mwifiex_wmm_allocate_ralist_node(struct mwifiex_adapter *adapter, const u8 *ra)
+{
+       struct mwifiex_ra_list_tbl *ra_list;
+
+       ra_list = kzalloc(sizeof(struct mwifiex_ra_list_tbl), GFP_ATOMIC);
+       if (!ra_list)
+               return NULL;
+
+       INIT_LIST_HEAD(&ra_list->list);
+       skb_queue_head_init(&ra_list->skb_head);
+
+       memcpy(ra_list->ra, ra, ETH_ALEN);
+
+       ra_list->total_pkt_count = 0;
+
+       mwifiex_dbg(adapter, INFO, "info: allocated ra_list %p\n", ra_list);
+
+       return ra_list;
+}
+
+/* This function returns random no between 16 and 32 to be used as threshold
+ * for no of packets after which BA setup is initiated.
+ */
+static u8 mwifiex_get_random_ba_threshold(void)
+{
+       u64 ns;
+       /* setup ba_packet_threshold here random number between
+        * [BA_SETUP_PACKET_OFFSET,
+        * BA_SETUP_PACKET_OFFSET+BA_SETUP_MAX_PACKET_THRESHOLD-1]
+        */
+       ns = ktime_get_ns();
+       ns += (ns >> 32) + (ns >> 16);
+
+       return ((u8)ns % BA_SETUP_MAX_PACKET_THRESHOLD) + BA_SETUP_PACKET_OFFSET;
+}
+
+/*
+ * This function allocates and adds a RA list for all TIDs
+ * with the given RA.
+ */
+void mwifiex_ralist_add(struct mwifiex_private *priv, const u8 *ra)
+{
+       int i;
+       struct mwifiex_ra_list_tbl *ra_list;
+       struct mwifiex_adapter *adapter = priv->adapter;
+       struct mwifiex_sta_node *node;
+       unsigned long flags;
+
+
+       for (i = 0; i < MAX_NUM_TID; ++i) {
+               ra_list = mwifiex_wmm_allocate_ralist_node(adapter, ra);
+               mwifiex_dbg(adapter, INFO,
+                           "info: created ra_list %p\n", ra_list);
+
+               if (!ra_list)
+                       break;
+
+               ra_list->is_11n_enabled = 0;
+               ra_list->tdls_link = false;
+               ra_list->ba_status = BA_SETUP_NONE;
+               ra_list->amsdu_in_ampdu = false;
+               if (!mwifiex_queuing_ra_based(priv)) {
+                       if (mwifiex_is_tdls_link_setup
+                               (mwifiex_get_tdls_link_status(priv, ra))) {
+                               ra_list->tdls_link = true;
+                               ra_list->is_11n_enabled =
+                                       mwifiex_tdls_peer_11n_enabled(priv, ra);
+                       } else {
+                               ra_list->is_11n_enabled = IS_11N_ENABLED(priv);
+                       }
+               } else {
+                       spin_lock_irqsave(&priv->sta_list_spinlock, flags);
+                       node = mwifiex_get_sta_entry(priv, ra);
+                       if (node)
+                               ra_list->tx_paused = node->tx_pause;
+                       ra_list->is_11n_enabled =
+                                     mwifiex_is_sta_11n_enabled(priv, node);
+                       if (ra_list->is_11n_enabled)
+                               ra_list->max_amsdu = node->max_amsdu;
+                       spin_unlock_irqrestore(&priv->sta_list_spinlock, flags);
+               }
+
+               mwifiex_dbg(adapter, DATA, "data: ralist %p: is_11n_enabled=%d\n",
+                           ra_list, ra_list->is_11n_enabled);
+
+               if (ra_list->is_11n_enabled) {
+                       ra_list->ba_pkt_count = 0;
+                       ra_list->ba_packet_thr =
+                                             mwifiex_get_random_ba_threshold();
+               }
+               list_add_tail(&ra_list->list,
+                             &priv->wmm.tid_tbl_ptr[i].ra_list);
+       }
+}
+
+/*
+ * This function sets the WMM queue priorities to their default values.
+ */
+static void mwifiex_wmm_default_queue_priorities(struct mwifiex_private *priv)
+{
+       /* Default queue priorities: VO->VI->BE->BK */
+       priv->wmm.queue_priority[0] = WMM_AC_VO;
+       priv->wmm.queue_priority[1] = WMM_AC_VI;
+       priv->wmm.queue_priority[2] = WMM_AC_BE;
+       priv->wmm.queue_priority[3] = WMM_AC_BK;
+}
+
+/*
+ * This function map ACs to TIDs.
+ */
+static void
+mwifiex_wmm_queue_priorities_tid(struct mwifiex_private *priv)
+{
+       struct mwifiex_wmm_desc *wmm = &priv->wmm;
+       u8 *queue_priority = wmm->queue_priority;
+       int i;
+
+       for (i = 0; i < 4; ++i) {
+               tos_to_tid[7 - (i * 2)] = ac_to_tid[queue_priority[i]][1];
+               tos_to_tid[6 - (i * 2)] = ac_to_tid[queue_priority[i]][0];
+       }
+
+       for (i = 0; i < MAX_NUM_TID; ++i)
+               priv->tos_to_tid_inv[tos_to_tid[i]] = (u8)i;
+
+       atomic_set(&wmm->highest_queued_prio, HIGH_PRIO_TID);
+}
+
+/*
+ * This function initializes WMM priority queues.
+ */
+void
+mwifiex_wmm_setup_queue_priorities(struct mwifiex_private *priv,
+                                  struct ieee_types_wmm_parameter *wmm_ie)
+{
+       u16 cw_min, avg_back_off, tmp[4];
+       u32 i, j, num_ac;
+       u8 ac_idx;
+
+       if (!wmm_ie || !priv->wmm_enabled) {
+               /* WMM is not enabled, just set the defaults and return */
+               mwifiex_wmm_default_queue_priorities(priv);
+               return;
+       }
+
+       mwifiex_dbg(priv->adapter, INFO,
+                   "info: WMM Parameter IE: version=%d,\t"
+                   "qos_info Parameter Set Count=%d, Reserved=%#x\n",
+                   wmm_ie->vend_hdr.version, wmm_ie->qos_info_bitmap &
+                   IEEE80211_WMM_IE_AP_QOSINFO_PARAM_SET_CNT_MASK,
+                   wmm_ie->reserved);
+
+       for (num_ac = 0; num_ac < ARRAY_SIZE(wmm_ie->ac_params); num_ac++) {
+               u8 ecw = wmm_ie->ac_params[num_ac].ecw_bitmap;
+               u8 aci_aifsn = wmm_ie->ac_params[num_ac].aci_aifsn_bitmap;
+               cw_min = (1 << (ecw & MWIFIEX_ECW_MIN)) - 1;
+               avg_back_off = (cw_min >> 1) + (aci_aifsn & MWIFIEX_AIFSN);
+
+               ac_idx = wmm_aci_to_qidx_map[(aci_aifsn & MWIFIEX_ACI) >> 5];
+               priv->wmm.queue_priority[ac_idx] = ac_idx;
+               tmp[ac_idx] = avg_back_off;
+
+               mwifiex_dbg(priv->adapter, INFO,
+                           "info: WMM: CWmax=%d CWmin=%d Avg Back-off=%d\n",
+                           (1 << ((ecw & MWIFIEX_ECW_MAX) >> 4)) - 1,
+                           cw_min, avg_back_off);
+               mwifiex_wmm_ac_debug_print(&wmm_ie->ac_params[num_ac]);
+       }
+
+       /* Bubble sort */
+       for (i = 0; i < num_ac; i++) {
+               for (j = 1; j < num_ac - i; j++) {
+                       if (tmp[j - 1] > tmp[j]) {
+                               swap(tmp[j - 1], tmp[j]);
+                               swap(priv->wmm.queue_priority[j - 1],
+                                    priv->wmm.queue_priority[j]);
+                       } else if (tmp[j - 1] == tmp[j]) {
+                               if (priv->wmm.queue_priority[j - 1]
+                                   < priv->wmm.queue_priority[j])
+                                       swap(priv->wmm.queue_priority[j - 1],
+                                            priv->wmm.queue_priority[j]);
+                       }
+               }
+       }
+
+       mwifiex_wmm_queue_priorities_tid(priv);
+}
+
+/*
+ * This function evaluates whether or not an AC is to be downgraded.
+ *
+ * In case the AC is not enabled, the highest AC is returned that is
+ * enabled and does not require admission control.
+ */
+static enum mwifiex_wmm_ac_e
+mwifiex_wmm_eval_downgrade_ac(struct mwifiex_private *priv,
+                             enum mwifiex_wmm_ac_e eval_ac)
+{
+       int down_ac;
+       enum mwifiex_wmm_ac_e ret_ac;
+       struct mwifiex_wmm_ac_status *ac_status;
+
+       ac_status = &priv->wmm.ac_status[eval_ac];
+
+       if (!ac_status->disabled)
+               /* Okay to use this AC, its enabled */
+               return eval_ac;
+
+       /* Setup a default return value of the lowest priority */
+       ret_ac = WMM_AC_BK;
+
+       /*
+        *  Find the highest AC that is enabled and does not require
+        *  admission control. The spec disallows downgrading to an AC,
+        *  which is enabled due to a completed admission control.
+        *  Unadmitted traffic is not to be sent on an AC with admitted
+        *  traffic.
+        */
+       for (down_ac = WMM_AC_BK; down_ac < eval_ac; down_ac++) {
+               ac_status = &priv->wmm.ac_status[down_ac];
+
+               if (!ac_status->disabled && !ac_status->flow_required)
+                       /* AC is enabled and does not require admission
+                          control */
+                       ret_ac = (enum mwifiex_wmm_ac_e) down_ac;
+       }
+
+       return ret_ac;
+}
+
+/*
+ * This function downgrades WMM priority queue.
+ */
+void
+mwifiex_wmm_setup_ac_downgrade(struct mwifiex_private *priv)
+{
+       int ac_val;
+
+       mwifiex_dbg(priv->adapter, INFO, "info: WMM: AC Priorities:\t"
+                   "BK(0), BE(1), VI(2), VO(3)\n");
+
+       if (!priv->wmm_enabled) {
+               /* WMM is not enabled, default priorities */
+               for (ac_val = WMM_AC_BK; ac_val <= WMM_AC_VO; ac_val++)
+                       priv->wmm.ac_down_graded_vals[ac_val] =
+                                               (enum mwifiex_wmm_ac_e) ac_val;
+       } else {
+               for (ac_val = WMM_AC_BK; ac_val <= WMM_AC_VO; ac_val++) {
+                       priv->wmm.ac_down_graded_vals[ac_val]
+                               = mwifiex_wmm_eval_downgrade_ac(priv,
+                                               (enum mwifiex_wmm_ac_e) ac_val);
+                       mwifiex_dbg(priv->adapter, INFO,
+                                   "info: WMM: AC PRIO %d maps to %d\n",
+                                   ac_val,
+                                   priv->wmm.ac_down_graded_vals[ac_val]);
+               }
+       }
+}
+
+/*
+ * This function converts the IP TOS field to an WMM AC
+ * Queue assignment.
+ */
+static enum mwifiex_wmm_ac_e
+mwifiex_wmm_convert_tos_to_ac(struct mwifiex_adapter *adapter, u32 tos)
+{
+       /* Map of TOS UP values to WMM AC */
+       const enum mwifiex_wmm_ac_e tos_to_ac[] = { WMM_AC_BE,
+               WMM_AC_BK,
+               WMM_AC_BK,
+               WMM_AC_BE,
+               WMM_AC_VI,
+               WMM_AC_VI,
+               WMM_AC_VO,
+               WMM_AC_VO
+       };
+
+       if (tos >= ARRAY_SIZE(tos_to_ac))
+               return WMM_AC_BE;
+
+       return tos_to_ac[tos];
+}
+
+/*
+ * This function evaluates a given TID and downgrades it to a lower
+ * TID if the WMM Parameter IE received from the AP indicates that the
+ * AP is disabled (due to call admission control (ACM bit). Mapping
+ * of TID to AC is taken care of internally.
+ */
+u8 mwifiex_wmm_downgrade_tid(struct mwifiex_private *priv, u32 tid)
+{
+       enum mwifiex_wmm_ac_e ac, ac_down;
+       u8 new_tid;
+
+       ac = mwifiex_wmm_convert_tos_to_ac(priv->adapter, tid);
+       ac_down = priv->wmm.ac_down_graded_vals[ac];
+
+       /* Send the index to tid array, picking from the array will be
+        * taken care by dequeuing function
+        */
+       new_tid = ac_to_tid[ac_down][tid % 2];
+
+       return new_tid;
+}
+
+/*
+ * This function initializes the WMM state information and the
+ * WMM data path queues.
+ */
+void
+mwifiex_wmm_init(struct mwifiex_adapter *adapter)
+{
+       int i, j;
+       struct mwifiex_private *priv;
+
+       for (j = 0; j < adapter->priv_num; ++j) {
+               priv = adapter->priv[j];
+               if (!priv)
+                       continue;
+
+               for (i = 0; i < MAX_NUM_TID; ++i) {
+                       if (!disable_tx_amsdu &&
+                           adapter->tx_buf_size > MWIFIEX_TX_DATA_BUF_SIZE_2K)
+                               priv->aggr_prio_tbl[i].amsdu =
+                                                       priv->tos_to_tid_inv[i];
+                       else
+                               priv->aggr_prio_tbl[i].amsdu =
+                                                       BA_STREAM_NOT_ALLOWED;
+                       priv->aggr_prio_tbl[i].ampdu_ap =
+                                                       priv->tos_to_tid_inv[i];
+                       priv->aggr_prio_tbl[i].ampdu_user =
+                                                       priv->tos_to_tid_inv[i];
+               }
+
+               priv->aggr_prio_tbl[6].amsdu
+                                       = priv->aggr_prio_tbl[6].ampdu_ap
+                                       = priv->aggr_prio_tbl[6].ampdu_user
+                                       = BA_STREAM_NOT_ALLOWED;
+
+               priv->aggr_prio_tbl[7].amsdu = priv->aggr_prio_tbl[7].ampdu_ap
+                                       = priv->aggr_prio_tbl[7].ampdu_user
+                                       = BA_STREAM_NOT_ALLOWED;
+
+               mwifiex_set_ba_params(priv);
+               mwifiex_reset_11n_rx_seq_num(priv);
+
+               atomic_set(&priv->wmm.tx_pkts_queued, 0);
+               atomic_set(&priv->wmm.highest_queued_prio, HIGH_PRIO_TID);
+       }
+}
+
+int mwifiex_bypass_txlist_empty(struct mwifiex_adapter *adapter)
+{
+       struct mwifiex_private *priv;
+       int i;
+
+       for (i = 0; i < adapter->priv_num; i++) {
+               priv = adapter->priv[i];
+               if (!priv)
+                       continue;
+               if (adapter->if_ops.is_port_ready &&
+                   !adapter->if_ops.is_port_ready(priv))
+                       continue;
+               if (!skb_queue_empty(&priv->bypass_txq))
+                       return false;
+       }
+
+       return true;
+}
+
+/*
+ * This function checks if WMM Tx queue is empty.
+ */
+int
+mwifiex_wmm_lists_empty(struct mwifiex_adapter *adapter)
+{
+       int i;
+       struct mwifiex_private *priv;
+
+       for (i = 0; i < adapter->priv_num; ++i) {
+               priv = adapter->priv[i];
+               if (!priv)
+                       continue;
+               if (!priv->port_open)
+                       continue;
+               if (adapter->if_ops.is_port_ready &&
+                   !adapter->if_ops.is_port_ready(priv))
+                       continue;
+               if (atomic_read(&priv->wmm.tx_pkts_queued))
+                       return false;
+       }
+
+       return true;
+}
+
+/*
+ * This function deletes all packets in an RA list node.
+ *
+ * The packet sent completion callback handler are called with
+ * status failure, after they are dequeued to ensure proper
+ * cleanup. The RA list node itself is freed at the end.
+ */
+static void
+mwifiex_wmm_del_pkts_in_ralist_node(struct mwifiex_private *priv,
+                                   struct mwifiex_ra_list_tbl *ra_list)
+{
+       struct mwifiex_adapter *adapter = priv->adapter;
+       struct sk_buff *skb, *tmp;
+
+       skb_queue_walk_safe(&ra_list->skb_head, skb, tmp)
+               mwifiex_write_data_complete(adapter, skb, 0, -1);
+}
+
+/*
+ * This function deletes all packets in an RA list.
+ *
+ * Each nodes in the RA list are freed individually first, and then
+ * the RA list itself is freed.
+ */
+static void
+mwifiex_wmm_del_pkts_in_ralist(struct mwifiex_private *priv,
+                              struct list_head *ra_list_head)
+{
+       struct mwifiex_ra_list_tbl *ra_list;
+
+       list_for_each_entry(ra_list, ra_list_head, list)
+               mwifiex_wmm_del_pkts_in_ralist_node(priv, ra_list);
+}
+
+/*
+ * This function deletes all packets in all RA lists.
+ */
+static void mwifiex_wmm_cleanup_queues(struct mwifiex_private *priv)
+{
+       int i;
+
+       for (i = 0; i < MAX_NUM_TID; i++)
+               mwifiex_wmm_del_pkts_in_ralist(priv, &priv->wmm.tid_tbl_ptr[i].
+                                                                      ra_list);
+
+       atomic_set(&priv->wmm.tx_pkts_queued, 0);
+       atomic_set(&priv->wmm.highest_queued_prio, HIGH_PRIO_TID);
+}
+
+/*
+ * This function deletes all route addresses from all RA lists.
+ */
+static void mwifiex_wmm_delete_all_ralist(struct mwifiex_private *priv)
+{
+       struct mwifiex_ra_list_tbl *ra_list, *tmp_node;
+       int i;
+
+       for (i = 0; i < MAX_NUM_TID; ++i) {
+               mwifiex_dbg(priv->adapter, INFO,
+                           "info: ra_list: freeing buf for tid %d\n", i);
+               list_for_each_entry_safe(ra_list, tmp_node,
+                                        &priv->wmm.tid_tbl_ptr[i].ra_list,
+                                        list) {
+                       list_del(&ra_list->list);
+                       kfree(ra_list);
+               }
+
+               INIT_LIST_HEAD(&priv->wmm.tid_tbl_ptr[i].ra_list);
+       }
+}
+
+static int mwifiex_free_ack_frame(int id, void *p, void *data)
+{
+       pr_warn("Have pending ack frames!\n");
+       kfree_skb(p);
+       return 0;
+}
+
+/*
+ * This function cleans up the Tx and Rx queues.
+ *
+ * Cleanup includes -
+ *      - All packets in RA lists
+ *      - All entries in Rx reorder table
+ *      - All entries in Tx BA stream table
+ *      - MPA buffer (if required)
+ *      - All RA lists
+ */
+void
+mwifiex_clean_txrx(struct mwifiex_private *priv)
+{
+       unsigned long flags;
+       struct sk_buff *skb, *tmp;
+
+       mwifiex_11n_cleanup_reorder_tbl(priv);
+       spin_lock_irqsave(&priv->wmm.ra_list_spinlock, flags);
+
+       mwifiex_wmm_cleanup_queues(priv);
+       mwifiex_11n_delete_all_tx_ba_stream_tbl(priv);
+
+       if (priv->adapter->if_ops.cleanup_mpa_buf)
+               priv->adapter->if_ops.cleanup_mpa_buf(priv->adapter);
+
+       mwifiex_wmm_delete_all_ralist(priv);
+       memcpy(tos_to_tid, ac_to_tid, sizeof(tos_to_tid));
+
+       if (priv->adapter->if_ops.clean_pcie_ring &&
+           !priv->adapter->surprise_removed)
+               priv->adapter->if_ops.clean_pcie_ring(priv->adapter);
+       spin_unlock_irqrestore(&priv->wmm.ra_list_spinlock, flags);
+
+       skb_queue_walk_safe(&priv->tdls_txq, skb, tmp)
+               mwifiex_write_data_complete(priv->adapter, skb, 0, -1);
+
+       skb_queue_walk_safe(&priv->bypass_txq, skb, tmp)
+               mwifiex_write_data_complete(priv->adapter, skb, 0, -1);
+       atomic_set(&priv->adapter->bypass_tx_pending, 0);
+
+       idr_for_each(&priv->ack_status_frames, mwifiex_free_ack_frame, NULL);
+       idr_destroy(&priv->ack_status_frames);
+}
+
+/*
+ * This function retrieves a particular RA list node, matching with the
+ * given TID and RA address.
+ */
+struct mwifiex_ra_list_tbl *
+mwifiex_wmm_get_ralist_node(struct mwifiex_private *priv, u8 tid,
+                           const u8 *ra_addr)
+{
+       struct mwifiex_ra_list_tbl *ra_list;
+
+       list_for_each_entry(ra_list, &priv->wmm.tid_tbl_ptr[tid].ra_list,
+                           list) {
+               if (!memcmp(ra_list->ra, ra_addr, ETH_ALEN))
+                       return ra_list;
+       }
+
+       return NULL;
+}
+
+void mwifiex_update_ralist_tx_pause(struct mwifiex_private *priv, u8 *mac,
+                                   u8 tx_pause)
+{
+       struct mwifiex_ra_list_tbl *ra_list;
+       u32 pkt_cnt = 0, tx_pkts_queued;
+       unsigned long flags;
+       int i;
+
+       spin_lock_irqsave(&priv->wmm.ra_list_spinlock, flags);
+
+       for (i = 0; i < MAX_NUM_TID; ++i) {
+               ra_list = mwifiex_wmm_get_ralist_node(priv, i, mac);
+               if (ra_list && ra_list->tx_paused != tx_pause) {
+                       pkt_cnt += ra_list->total_pkt_count;
+                       ra_list->tx_paused = tx_pause;
+                       if (tx_pause)
+                               priv->wmm.pkts_paused[i] +=
+                                       ra_list->total_pkt_count;
+                       else
+                               priv->wmm.pkts_paused[i] -=
+                                       ra_list->total_pkt_count;
+               }
+       }
+
+       if (pkt_cnt) {
+               tx_pkts_queued = atomic_read(&priv->wmm.tx_pkts_queued);
+               if (tx_pause)
+                       tx_pkts_queued -= pkt_cnt;
+               else
+                       tx_pkts_queued += pkt_cnt;
+
+               atomic_set(&priv->wmm.tx_pkts_queued, tx_pkts_queued);
+               atomic_set(&priv->wmm.highest_queued_prio, HIGH_PRIO_TID);
+       }
+       spin_unlock_irqrestore(&priv->wmm.ra_list_spinlock, flags);
+}
+
+/* This function update non-tdls peer ralist tx_pause while
+ * tdls channel swithing
+ */
+void mwifiex_update_ralist_tx_pause_in_tdls_cs(struct mwifiex_private *priv,
+                                              u8 *mac, u8 tx_pause)
+{
+       struct mwifiex_ra_list_tbl *ra_list;
+       u32 pkt_cnt = 0, tx_pkts_queued;
+       unsigned long flags;
+       int i;
+
+       spin_lock_irqsave(&priv->wmm.ra_list_spinlock, flags);
+
+       for (i = 0; i < MAX_NUM_TID; ++i) {
+               list_for_each_entry(ra_list, &priv->wmm.tid_tbl_ptr[i].ra_list,
+                                   list) {
+                       if (!memcmp(ra_list->ra, mac, ETH_ALEN))
+                               continue;
+
+                       if (ra_list->tx_paused != tx_pause) {
+                               pkt_cnt += ra_list->total_pkt_count;
+                               ra_list->tx_paused = tx_pause;
+                               if (tx_pause)
+                                       priv->wmm.pkts_paused[i] +=
+                                               ra_list->total_pkt_count;
+                               else
+                                       priv->wmm.pkts_paused[i] -=
+                                               ra_list->total_pkt_count;
+                       }
+               }
+       }
+
+       if (pkt_cnt) {
+               tx_pkts_queued = atomic_read(&priv->wmm.tx_pkts_queued);
+               if (tx_pause)
+                       tx_pkts_queued -= pkt_cnt;
+               else
+                       tx_pkts_queued += pkt_cnt;
+
+               atomic_set(&priv->wmm.tx_pkts_queued, tx_pkts_queued);
+               atomic_set(&priv->wmm.highest_queued_prio, HIGH_PRIO_TID);
+       }
+       spin_unlock_irqrestore(&priv->wmm.ra_list_spinlock, flags);
+}
+
+/*
+ * This function retrieves an RA list node for a given TID and
+ * RA address pair.
+ *
+ * If no such node is found, a new node is added first and then
+ * retrieved.
+ */
+struct mwifiex_ra_list_tbl *
+mwifiex_wmm_get_queue_raptr(struct mwifiex_private *priv, u8 tid,
+                           const u8 *ra_addr)
+{
+       struct mwifiex_ra_list_tbl *ra_list;
+
+       ra_list = mwifiex_wmm_get_ralist_node(priv, tid, ra_addr);
+       if (ra_list)
+               return ra_list;
+       mwifiex_ralist_add(priv, ra_addr);
+
+       return mwifiex_wmm_get_ralist_node(priv, tid, ra_addr);
+}
+
+/*
+ * This function deletes RA list nodes for given mac for all TIDs.
+ * Function also decrements TX pending count accordingly.
+ */
+void
+mwifiex_wmm_del_peer_ra_list(struct mwifiex_private *priv, const u8 *ra_addr)
+{
+       struct mwifiex_ra_list_tbl *ra_list;
+       unsigned long flags;
+       int i;
+
+       spin_lock_irqsave(&priv->wmm.ra_list_spinlock, flags);
+
+       for (i = 0; i < MAX_NUM_TID; ++i) {
+               ra_list = mwifiex_wmm_get_ralist_node(priv, i, ra_addr);
+
+               if (!ra_list)
+                       continue;
+               mwifiex_wmm_del_pkts_in_ralist_node(priv, ra_list);
+               if (ra_list->tx_paused)
+                       priv->wmm.pkts_paused[i] -= ra_list->total_pkt_count;
+               else
+                       atomic_sub(ra_list->total_pkt_count,
+                                  &priv->wmm.tx_pkts_queued);
+               list_del(&ra_list->list);
+               kfree(ra_list);
+       }
+       spin_unlock_irqrestore(&priv->wmm.ra_list_spinlock, flags);
+}
+
+/*
+ * This function checks if a particular RA list node exists in a given TID
+ * table index.
+ */
+int
+mwifiex_is_ralist_valid(struct mwifiex_private *priv,
+                       struct mwifiex_ra_list_tbl *ra_list, int ptr_index)
+{
+       struct mwifiex_ra_list_tbl *rlist;
+
+       list_for_each_entry(rlist, &priv->wmm.tid_tbl_ptr[ptr_index].ra_list,
+                           list) {
+               if (rlist == ra_list)
+                       return true;
+       }
+
+       return false;
+}
+
+/*
+ * This function adds a packet to bypass TX queue.
+ * This is special TX queue for packets which can be sent even when port_open
+ * is false.
+ */
+void
+mwifiex_wmm_add_buf_bypass_txqueue(struct mwifiex_private *priv,
+                                  struct sk_buff *skb)
+{
+       skb_queue_tail(&priv->bypass_txq, skb);
+}
+
+/*
+ * This function adds a packet to WMM queue.
+ *
+ * In disconnected state the packet is immediately dropped and the
+ * packet send completion callback is called with status failure.
+ *
+ * Otherwise, the correct RA list node is located and the packet
+ * is queued at the list tail.
+ */
+void
+mwifiex_wmm_add_buf_txqueue(struct mwifiex_private *priv,
+                           struct sk_buff *skb)
+{
+       struct mwifiex_adapter *adapter = priv->adapter;
+       u32 tid;
+       struct mwifiex_ra_list_tbl *ra_list;
+       u8 ra[ETH_ALEN], tid_down;
+       unsigned long flags;
+       struct list_head list_head;
+       int tdls_status = TDLS_NOT_SETUP;
+       struct ethhdr *eth_hdr = (struct ethhdr *)skb->data;
+       struct mwifiex_txinfo *tx_info = MWIFIEX_SKB_TXCB(skb);
+
+       memcpy(ra, eth_hdr->h_dest, ETH_ALEN);
+
+       if (GET_BSS_ROLE(priv) == MWIFIEX_BSS_ROLE_STA &&
+           ISSUPP_TDLS_ENABLED(adapter->fw_cap_info)) {
+               if (ntohs(eth_hdr->h_proto) == ETH_P_TDLS)
+                       mwifiex_dbg(adapter, DATA,
+                                   "TDLS setup packet for %pM.\t"
+                                   "Don't block\n", ra);
+               else if (memcmp(priv->cfg_bssid, ra, ETH_ALEN))
+                       tdls_status = mwifiex_get_tdls_link_status(priv, ra);
+       }
+
+       if (!priv->media_connected && !mwifiex_is_skb_mgmt_frame(skb)) {
+               mwifiex_dbg(adapter, DATA, "data: drop packet in disconnect\n");
+               mwifiex_write_data_complete(adapter, skb, 0, -1);
+               return;
+       }
+
+       tid = skb->priority;
+
+       spin_lock_irqsave(&priv->wmm.ra_list_spinlock, flags);
+
+       tid_down = mwifiex_wmm_downgrade_tid(priv, tid);
+
+       /* In case of infra as we have already created the list during
+          association we just don't have to call get_queue_raptr, we will
+          have only 1 raptr for a tid in case of infra */
+       if (!mwifiex_queuing_ra_based(priv) &&
+           !mwifiex_is_skb_mgmt_frame(skb)) {
+               switch (tdls_status) {
+               case TDLS_SETUP_COMPLETE:
+               case TDLS_CHAN_SWITCHING:
+               case TDLS_IN_BASE_CHAN:
+               case TDLS_IN_OFF_CHAN:
+                       ra_list = mwifiex_wmm_get_queue_raptr(priv, tid_down,
+                                                             ra);
+                       tx_info->flags |= MWIFIEX_BUF_FLAG_TDLS_PKT;
+                       break;
+               case TDLS_SETUP_INPROGRESS:
+                       skb_queue_tail(&priv->tdls_txq, skb);
+                       spin_unlock_irqrestore(&priv->wmm.ra_list_spinlock,
+                                              flags);
+                       return;
+               default:
+                       list_head = priv->wmm.tid_tbl_ptr[tid_down].ra_list;
+                       if (!list_empty(&list_head))
+                               ra_list = list_first_entry(
+                                       &list_head, struct mwifiex_ra_list_tbl,
+                                       list);
+                       else
+                               ra_list = NULL;
+                       break;
+               }
+       } else {
+               memcpy(ra, skb->data, ETH_ALEN);
+               if (ra[0] & 0x01 || mwifiex_is_skb_mgmt_frame(skb))
+                       eth_broadcast_addr(ra);
+               ra_list = mwifiex_wmm_get_queue_raptr(priv, tid_down, ra);
+       }
+
+       if (!ra_list) {
+               spin_unlock_irqrestore(&priv->wmm.ra_list_spinlock, flags);
+               mwifiex_write_data_complete(adapter, skb, 0, -1);
+               return;
+       }
+
+       skb_queue_tail(&ra_list->skb_head, skb);
+
+       ra_list->ba_pkt_count++;
+       ra_list->total_pkt_count++;
+
+       if (atomic_read(&priv->wmm.highest_queued_prio) <
+                                               priv->tos_to_tid_inv[tid_down])
+               atomic_set(&priv->wmm.highest_queued_prio,
+                          priv->tos_to_tid_inv[tid_down]);
+
+       if (ra_list->tx_paused)
+               priv->wmm.pkts_paused[tid_down]++;
+       else
+               atomic_inc(&priv->wmm.tx_pkts_queued);
+
+       spin_unlock_irqrestore(&priv->wmm.ra_list_spinlock, flags);
+}
+
+/*
+ * This function processes the get WMM status command response from firmware.
+ *
+ * The response may contain multiple TLVs -
+ *      - AC Queue status TLVs
+ *      - Current WMM Parameter IE TLV
+ *      - Admission Control action frame TLVs
+ *
+ * This function parses the TLVs and then calls further specific functions
+ * to process any changes in the queue prioritize or state.
+ */
+int mwifiex_ret_wmm_get_status(struct mwifiex_private *priv,
+                              const struct host_cmd_ds_command *resp)
+{
+       u8 *curr = (u8 *) &resp->params.get_wmm_status;
+       uint16_t resp_len = le16_to_cpu(resp->size), tlv_len;
+       int mask = IEEE80211_WMM_IE_AP_QOSINFO_PARAM_SET_CNT_MASK;
+       bool valid = true;
+
+       struct mwifiex_ie_types_data *tlv_hdr;
+       struct mwifiex_ie_types_wmm_queue_status *tlv_wmm_qstatus;
+       struct ieee_types_wmm_parameter *wmm_param_ie = NULL;
+       struct mwifiex_wmm_ac_status *ac_status;
+
+       mwifiex_dbg(priv->adapter, INFO,
+                   "info: WMM: WMM_GET_STATUS cmdresp received: %d\n",
+                   resp_len);
+
+       while ((resp_len >= sizeof(tlv_hdr->header)) && valid) {
+               tlv_hdr = (struct mwifiex_ie_types_data *) curr;
+               tlv_len = le16_to_cpu(tlv_hdr->header.len);
+
+               if (resp_len < tlv_len + sizeof(tlv_hdr->header))
+                       break;
+
+               switch (le16_to_cpu(tlv_hdr->header.type)) {
+               case TLV_TYPE_WMMQSTATUS:
+                       tlv_wmm_qstatus =
+                               (struct mwifiex_ie_types_wmm_queue_status *)
+                               tlv_hdr;
+                       mwifiex_dbg(priv->adapter, CMD,
+                                   "info: CMD_RESP: WMM_GET_STATUS:\t"
+                                   "QSTATUS TLV: %d, %d, %d\n",
+                                   tlv_wmm_qstatus->queue_index,
+                                   tlv_wmm_qstatus->flow_required,
+                                   tlv_wmm_qstatus->disabled);
+
+                       ac_status = &priv->wmm.ac_status[tlv_wmm_qstatus->
+                                                        queue_index];
+                       ac_status->disabled = tlv_wmm_qstatus->disabled;
+                       ac_status->flow_required =
+                                               tlv_wmm_qstatus->flow_required;
+                       ac_status->flow_created = tlv_wmm_qstatus->flow_created;
+                       break;
+
+               case WLAN_EID_VENDOR_SPECIFIC:
+                       /*
+                        * Point the regular IEEE IE 2 bytes into the Marvell IE
+                        *   and setup the IEEE IE type and length byte fields
+                        */
+
+                       wmm_param_ie =
+                               (struct ieee_types_wmm_parameter *) (curr +
+                                                                   2);
+                       wmm_param_ie->vend_hdr.len = (u8) tlv_len;
+                       wmm_param_ie->vend_hdr.element_id =
+                                               WLAN_EID_VENDOR_SPECIFIC;
+
+                       mwifiex_dbg(priv->adapter, CMD,
+                                   "info: CMD_RESP: WMM_GET_STATUS:\t"
+                                   "WMM Parameter Set Count: %d\n",
+                                   wmm_param_ie->qos_info_bitmap & mask);
+
+                       memcpy((u8 *) &priv->curr_bss_params.bss_descriptor.
+                              wmm_ie, wmm_param_ie,
+                              wmm_param_ie->vend_hdr.len + 2);
+
+                       break;
+
+               default:
+                       valid = false;
+                       break;
+               }
+
+               curr += (tlv_len + sizeof(tlv_hdr->header));
+               resp_len -= (tlv_len + sizeof(tlv_hdr->header));
+       }
+
+       mwifiex_wmm_setup_queue_priorities(priv, wmm_param_ie);
+       mwifiex_wmm_setup_ac_downgrade(priv);
+
+       return 0;
+}
+
+/*
+ * Callback handler from the command module to allow insertion of a WMM TLV.
+ *
+ * If the BSS we are associating to supports WMM, this function adds the
+ * required WMM Information IE to the association request command buffer in
+ * the form of a Marvell extended IEEE IE.
+ */
+u32
+mwifiex_wmm_process_association_req(struct mwifiex_private *priv,
+                                   u8 **assoc_buf,
+                                   struct ieee_types_wmm_parameter *wmm_ie,
+                                   struct ieee80211_ht_cap *ht_cap)
+{
+       struct mwifiex_ie_types_wmm_param_set *wmm_tlv;
+       u32 ret_len = 0;
+
+       /* Null checks */
+       if (!assoc_buf)
+               return 0;
+       if (!(*assoc_buf))
+               return 0;
+
+       if (!wmm_ie)
+               return 0;
+
+       mwifiex_dbg(priv->adapter, INFO,
+                   "info: WMM: process assoc req: bss->wmm_ie=%#x\n",
+                   wmm_ie->vend_hdr.element_id);
+
+       if ((priv->wmm_required ||
+            (ht_cap && (priv->adapter->config_bands & BAND_GN ||
+            priv->adapter->config_bands & BAND_AN))) &&
+           wmm_ie->vend_hdr.element_id == WLAN_EID_VENDOR_SPECIFIC) {
+               wmm_tlv = (struct mwifiex_ie_types_wmm_param_set *) *assoc_buf;
+               wmm_tlv->header.type = cpu_to_le16((u16) wmm_info_ie[0]);
+               wmm_tlv->header.len = cpu_to_le16((u16) wmm_info_ie[1]);
+               memcpy(wmm_tlv->wmm_ie, &wmm_info_ie[2],
+                      le16_to_cpu(wmm_tlv->header.len));
+               if (wmm_ie->qos_info_bitmap & IEEE80211_WMM_IE_AP_QOSINFO_UAPSD)
+                       memcpy((u8 *) (wmm_tlv->wmm_ie
+                                      + le16_to_cpu(wmm_tlv->header.len)
+                                      - sizeof(priv->wmm_qosinfo)),
+                              &priv->wmm_qosinfo, sizeof(priv->wmm_qosinfo));
+
+               ret_len = sizeof(wmm_tlv->header)
+                         + le16_to_cpu(wmm_tlv->header.len);
+
+               *assoc_buf += ret_len;
+       }
+
+       return ret_len;
+}
+
+/*
+ * This function computes the time delay in the driver queues for a
+ * given packet.
+ *
+ * When the packet is received at the OS/Driver interface, the current
+ * time is set in the packet structure. The difference between the present
+ * time and that received time is computed in this function and limited
+ * based on pre-compiled limits in the driver.
+ */
+u8
+mwifiex_wmm_compute_drv_pkt_delay(struct mwifiex_private *priv,
+                                 const struct sk_buff *skb)
+{
+       u32 queue_delay = ktime_to_ms(net_timedelta(skb->tstamp));
+       u8 ret_val;
+
+       /*
+        * Queue delay is passed as a uint8 in units of 2ms (ms shifted
+        *  by 1). Min value (other than 0) is therefore 2ms, max is 510ms.
+        *
+        * Pass max value if queue_delay is beyond the uint8 range
+        */
+       ret_val = (u8) (min(queue_delay, priv->wmm.drv_pkt_delay_max) >> 1);
+
+       mwifiex_dbg(priv->adapter, DATA, "data: WMM: Pkt Delay: %d ms,\t"
+                   "%d ms sent to FW\n", queue_delay, ret_val);
+
+       return ret_val;
+}
+
+/*
+ * This function retrieves the highest priority RA list table pointer.
+ */
+static struct mwifiex_ra_list_tbl *
+mwifiex_wmm_get_highest_priolist_ptr(struct mwifiex_adapter *adapter,
+                                    struct mwifiex_private **priv, int *tid)
+{
+       struct mwifiex_private *priv_tmp;
+       struct mwifiex_ra_list_tbl *ptr;
+       struct mwifiex_tid_tbl *tid_ptr;
+       atomic_t *hqp;
+       unsigned long flags_ra;
+       int i, j;
+
+       /* check the BSS with highest priority first */
+       for (j = adapter->priv_num - 1; j >= 0; --j) {
+               /* iterate over BSS with the equal priority */
+               list_for_each_entry(adapter->bss_prio_tbl[j].bss_prio_cur,
+                                   &adapter->bss_prio_tbl[j].bss_prio_head,
+                                   list) {
+
+                       priv_tmp = adapter->bss_prio_tbl[j].bss_prio_cur->priv;
+
+                       if (!priv_tmp->port_open ||
+                           (atomic_read(&priv_tmp->wmm.tx_pkts_queued) == 0))
+                               continue;
+
+                       if (adapter->if_ops.is_port_ready &&
+                           !adapter->if_ops.is_port_ready(priv_tmp))
+                               continue;
+
+                       /* iterate over the WMM queues of the BSS */
+                       hqp = &priv_tmp->wmm.highest_queued_prio;
+                       for (i = atomic_read(hqp); i >= LOW_PRIO_TID; --i) {
+
+                               spin_lock_irqsave(&priv_tmp->wmm.
+                                                 ra_list_spinlock, flags_ra);
+
+                               tid_ptr = &(priv_tmp)->wmm.
+                                       tid_tbl_ptr[tos_to_tid[i]];
+
+                               /* iterate over receiver addresses */
+                               list_for_each_entry(ptr, &tid_ptr->ra_list,
+                                                   list) {
+
+                                       if (!ptr->tx_paused &&
+                                           !skb_queue_empty(&ptr->skb_head))
+                                               /* holds both locks */
+                                               goto found;
+                               }
+
+                               spin_unlock_irqrestore(&priv_tmp->wmm.
+                                                      ra_list_spinlock,
+                                                      flags_ra);
+                       }
+               }
+
+       }
+
+       return NULL;
+
+found:
+       /* holds ra_list_spinlock */
+       if (atomic_read(hqp) > i)
+               atomic_set(hqp, i);
+       spin_unlock_irqrestore(&priv_tmp->wmm.ra_list_spinlock, flags_ra);
+
+       *priv = priv_tmp;
+       *tid = tos_to_tid[i];
+
+       return ptr;
+}
+
+/* This functions rotates ra and bss lists so packets are picked round robin.
+ *
+ * After a packet is successfully transmitted, rotate the ra list, so the ra
+ * next to the one transmitted, will come first in the list. This way we pick
+ * the ra' in a round robin fashion. Same applies to bss nodes of equal
+ * priority.
+ *
+ * Function also increments wmm.packets_out counter.
+ */
+void mwifiex_rotate_priolists(struct mwifiex_private *priv,
+                                struct mwifiex_ra_list_tbl *ra,
+                                int tid)
+{
+       struct mwifiex_adapter *adapter = priv->adapter;
+       struct mwifiex_bss_prio_tbl *tbl = adapter->bss_prio_tbl;
+       struct mwifiex_tid_tbl *tid_ptr = &priv->wmm.tid_tbl_ptr[tid];
+       unsigned long flags;
+
+       spin_lock_irqsave(&tbl[priv->bss_priority].bss_prio_lock, flags);
+       /*
+        * dirty trick: we remove 'head' temporarily and reinsert it after
+        * curr bss node. imagine list to stay fixed while head is moved
+        */
+       list_move(&tbl[priv->bss_priority].bss_prio_head,
+                 &tbl[priv->bss_priority].bss_prio_cur->list);
+       spin_unlock_irqrestore(&tbl[priv->bss_priority].bss_prio_lock, flags);
+
+       spin_lock_irqsave(&priv->wmm.ra_list_spinlock, flags);
+       if (mwifiex_is_ralist_valid(priv, ra, tid)) {
+               priv->wmm.packets_out[tid]++;
+               /* same as above */
+               list_move(&tid_ptr->ra_list, &ra->list);
+       }
+       spin_unlock_irqrestore(&priv->wmm.ra_list_spinlock, flags);
+}
+
+/*
+ * This function checks if 11n aggregation is possible.
+ */
+static int
+mwifiex_is_11n_aggragation_possible(struct mwifiex_private *priv,
+                                   struct mwifiex_ra_list_tbl *ptr,
+                                   int max_buf_size)
+{
+       int count = 0, total_size = 0;
+       struct sk_buff *skb, *tmp;
+       int max_amsdu_size;
+
+       if (priv->bss_role == MWIFIEX_BSS_ROLE_UAP && priv->ap_11n_enabled &&
+           ptr->is_11n_enabled)
+               max_amsdu_size = min_t(int, ptr->max_amsdu, max_buf_size);
+       else
+               max_amsdu_size = max_buf_size;
+
+       skb_queue_walk_safe(&ptr->skb_head, skb, tmp) {
+               total_size += skb->len;
+               if (total_size >= max_amsdu_size)
+                       break;
+               if (++count >= MIN_NUM_AMSDU)
+                       return true;
+       }
+
+       return false;
+}
+
+/*
+ * This function sends a single packet to firmware for transmission.
+ */
+static void
+mwifiex_send_single_packet(struct mwifiex_private *priv,
+                          struct mwifiex_ra_list_tbl *ptr, int ptr_index,
+                          unsigned long ra_list_flags)
+                          __releases(&priv->wmm.ra_list_spinlock)
+{
+       struct sk_buff *skb, *skb_next;
+       struct mwifiex_tx_param tx_param;
+       struct mwifiex_adapter *adapter = priv->adapter;
+       struct mwifiex_txinfo *tx_info;
+
+       if (skb_queue_empty(&ptr->skb_head)) {
+               spin_unlock_irqrestore(&priv->wmm.ra_list_spinlock,
+                                      ra_list_flags);
+               mwifiex_dbg(adapter, DATA, "data: nothing to send\n");
+               return;
+       }
+
+       skb = skb_dequeue(&ptr->skb_head);
+
+       tx_info = MWIFIEX_SKB_TXCB(skb);
+       mwifiex_dbg(adapter, DATA,
+                   "data: dequeuing the packet %p %p\n", ptr, skb);
+
+       ptr->total_pkt_count--;
+
+       if (!skb_queue_empty(&ptr->skb_head))
+               skb_next = skb_peek(&ptr->skb_head);
+       else
+               skb_next = NULL;
+
+       spin_unlock_irqrestore(&priv->wmm.ra_list_spinlock, ra_list_flags);
+
+       tx_param.next_pkt_len = ((skb_next) ? skb_next->len +
+                               sizeof(struct txpd) : 0);
+
+       if (mwifiex_process_tx(priv, skb, &tx_param) == -EBUSY) {
+               /* Queue the packet back at the head */
+               spin_lock_irqsave(&priv->wmm.ra_list_spinlock, ra_list_flags);
+
+               if (!mwifiex_is_ralist_valid(priv, ptr, ptr_index)) {
+                       spin_unlock_irqrestore(&priv->wmm.ra_list_spinlock,
+                                              ra_list_flags);
+                       mwifiex_write_data_complete(adapter, skb, 0, -1);
+                       return;
+               }
+
+               skb_queue_tail(&ptr->skb_head, skb);
+
+               ptr->total_pkt_count++;
+               ptr->ba_pkt_count++;
+               tx_info->flags |= MWIFIEX_BUF_FLAG_REQUEUED_PKT;
+               spin_unlock_irqrestore(&priv->wmm.ra_list_spinlock,
+                                      ra_list_flags);
+       } else {
+               mwifiex_rotate_priolists(priv, ptr, ptr_index);
+               atomic_dec(&priv->wmm.tx_pkts_queued);
+       }
+}
+
+/*
+ * This function checks if the first packet in the given RA list
+ * is already processed or not.
+ */
+static int
+mwifiex_is_ptr_processed(struct mwifiex_private *priv,
+                        struct mwifiex_ra_list_tbl *ptr)
+{
+       struct sk_buff *skb;
+       struct mwifiex_txinfo *tx_info;
+
+       if (skb_queue_empty(&ptr->skb_head))
+               return false;
+
+       skb = skb_peek(&ptr->skb_head);
+
+       tx_info = MWIFIEX_SKB_TXCB(skb);
+       if (tx_info->flags & MWIFIEX_BUF_FLAG_REQUEUED_PKT)
+               return true;
+
+       return false;
+}
+
+/*
+ * This function sends a single processed packet to firmware for
+ * transmission.
+ */
+static void
+mwifiex_send_processed_packet(struct mwifiex_private *priv,
+                             struct mwifiex_ra_list_tbl *ptr, int ptr_index,
+                             unsigned long ra_list_flags)
+                               __releases(&priv->wmm.ra_list_spinlock)
+{
+       struct mwifiex_tx_param tx_param;
+       struct mwifiex_adapter *adapter = priv->adapter;
+       int ret = -1;
+       struct sk_buff *skb, *skb_next;
+       struct mwifiex_txinfo *tx_info;
+
+       if (skb_queue_empty(&ptr->skb_head)) {
+               spin_unlock_irqrestore(&priv->wmm.ra_list_spinlock,
+                                      ra_list_flags);
+               return;
+       }
+
+       skb = skb_dequeue(&ptr->skb_head);
+
+       if (adapter->data_sent || adapter->tx_lock_flag) {
+               spin_unlock_irqrestore(&priv->wmm.ra_list_spinlock,
+                                      ra_list_flags);
+               skb_queue_tail(&adapter->tx_data_q, skb);
+               atomic_inc(&adapter->tx_queued);
+               return;
+       }
+
+       if (!skb_queue_empty(&ptr->skb_head))
+               skb_next = skb_peek(&ptr->skb_head);
+       else
+               skb_next = NULL;
+
+       tx_info = MWIFIEX_SKB_TXCB(skb);
+
+       spin_unlock_irqrestore(&priv->wmm.ra_list_spinlock, ra_list_flags);
+
+       if (adapter->iface_type == MWIFIEX_USB) {
+               ret = adapter->if_ops.host_to_card(adapter, priv->usb_port,
+                                                  skb, NULL);
+       } else {
+               tx_param.next_pkt_len =
+                       ((skb_next) ? skb_next->len +
+                        sizeof(struct txpd) : 0);
+               ret = adapter->if_ops.host_to_card(adapter, MWIFIEX_TYPE_DATA,
+                                                  skb, &tx_param);
+       }
+
+       switch (ret) {
+       case -EBUSY:
+               mwifiex_dbg(adapter, ERROR, "data: -EBUSY is returned\n");
+               spin_lock_irqsave(&priv->wmm.ra_list_spinlock, ra_list_flags);
+
+               if (!mwifiex_is_ralist_valid(priv, ptr, ptr_index)) {
+                       spin_unlock_irqrestore(&priv->wmm.ra_list_spinlock,
+                                              ra_list_flags);
+                       mwifiex_write_data_complete(adapter, skb, 0, -1);
+                       return;
+               }
+
+               skb_queue_tail(&ptr->skb_head, skb);
+
+               tx_info->flags |= MWIFIEX_BUF_FLAG_REQUEUED_PKT;
+               spin_unlock_irqrestore(&priv->wmm.ra_list_spinlock,
+                                      ra_list_flags);
+               break;
+       case -1:
+               mwifiex_dbg(adapter, ERROR, "host_to_card failed: %#x\n", ret);
+               adapter->dbg.num_tx_host_to_card_failure++;
+               mwifiex_write_data_complete(adapter, skb, 0, ret);
+               break;
+       case -EINPROGRESS:
+               break;
+       case 0:
+               mwifiex_write_data_complete(adapter, skb, 0, ret);
+       default:
+               break;
+       }
+       if (ret != -EBUSY) {
+               mwifiex_rotate_priolists(priv, ptr, ptr_index);
+               atomic_dec(&priv->wmm.tx_pkts_queued);
+       }
+}
+
+/*
+ * This function dequeues a packet from the highest priority list
+ * and transmits it.
+ */
+static int
+mwifiex_dequeue_tx_packet(struct mwifiex_adapter *adapter)
+{
+       struct mwifiex_ra_list_tbl *ptr;
+       struct mwifiex_private *priv = NULL;
+       int ptr_index = 0;
+       u8 ra[ETH_ALEN];
+       int tid_del = 0, tid = 0;
+       unsigned long flags;
+
+       ptr = mwifiex_wmm_get_highest_priolist_ptr(adapter, &priv, &ptr_index);
+       if (!ptr)
+               return -1;
+
+       tid = mwifiex_get_tid(ptr);
+
+       mwifiex_dbg(adapter, DATA, "data: tid=%d\n", tid);
+
+       spin_lock_irqsave(&priv->wmm.ra_list_spinlock, flags);
+       if (!mwifiex_is_ralist_valid(priv, ptr, ptr_index)) {
+               spin_unlock_irqrestore(&priv->wmm.ra_list_spinlock, flags);
+               return -1;
+       }
+
+       if (mwifiex_is_ptr_processed(priv, ptr)) {
+               mwifiex_send_processed_packet(priv, ptr, ptr_index, flags);
+               /* ra_list_spinlock has been freed in
+                  mwifiex_send_processed_packet() */
+               return 0;
+       }
+
+       if (!ptr->is_11n_enabled ||
+               ptr->ba_status ||
+               priv->wps.session_enable) {
+               if (ptr->is_11n_enabled &&
+                       ptr->ba_status &&
+                       ptr->amsdu_in_ampdu &&
+                       mwifiex_is_amsdu_allowed(priv, tid) &&
+                       mwifiex_is_11n_aggragation_possible(priv, ptr,
+                                                       adapter->tx_buf_size))
+                       mwifiex_11n_aggregate_pkt(priv, ptr, ptr_index, flags);
+                       /* ra_list_spinlock has been freed in
+                        * mwifiex_11n_aggregate_pkt()
+                        */
+               else
+                       mwifiex_send_single_packet(priv, ptr, ptr_index, flags);
+                       /* ra_list_spinlock has been freed in
+                        * mwifiex_send_single_packet()
+                        */
+       } else {
+               if (mwifiex_is_ampdu_allowed(priv, ptr, tid) &&
+                   ptr->ba_pkt_count > ptr->ba_packet_thr) {
+                       if (mwifiex_space_avail_for_new_ba_stream(adapter)) {
+                               mwifiex_create_ba_tbl(priv, ptr->ra, tid,
+                                                     BA_SETUP_INPROGRESS);
+                               mwifiex_send_addba(priv, tid, ptr->ra);
+                       } else if (mwifiex_find_stream_to_delete
+                                  (priv, tid, &tid_del, ra)) {
+                               mwifiex_create_ba_tbl(priv, ptr->ra, tid,
+                                                     BA_SETUP_INPROGRESS);
+                               mwifiex_send_delba(priv, tid_del, ra, 1);
+                       }
+               }
+               if (mwifiex_is_amsdu_allowed(priv, tid) &&
+                   mwifiex_is_11n_aggragation_possible(priv, ptr,
+                                                       adapter->tx_buf_size))
+                       mwifiex_11n_aggregate_pkt(priv, ptr, ptr_index, flags);
+                       /* ra_list_spinlock has been freed in
+                          mwifiex_11n_aggregate_pkt() */
+               else
+                       mwifiex_send_single_packet(priv, ptr, ptr_index, flags);
+                       /* ra_list_spinlock has been freed in
+                          mwifiex_send_single_packet() */
+       }
+       return 0;
+}
+
+void mwifiex_process_bypass_tx(struct mwifiex_adapter *adapter)
+{
+       struct mwifiex_tx_param tx_param;
+       struct sk_buff *skb;
+       struct mwifiex_txinfo *tx_info;
+       struct mwifiex_private *priv;
+       int i;
+
+       if (adapter->data_sent || adapter->tx_lock_flag)
+               return;
+
+       for (i = 0; i < adapter->priv_num; ++i) {
+               priv = adapter->priv[i];
+
+               if (!priv)
+                       continue;
+
+               if (adapter->if_ops.is_port_ready &&
+                   !adapter->if_ops.is_port_ready(priv))
+                       continue;
+
+               if (skb_queue_empty(&priv->bypass_txq))
+                       continue;
+
+               skb = skb_dequeue(&priv->bypass_txq);
+               tx_info = MWIFIEX_SKB_TXCB(skb);
+
+               /* no aggregation for bypass packets */
+               tx_param.next_pkt_len = 0;
+
+               if (mwifiex_process_tx(priv, skb, &tx_param) == -EBUSY) {
+                       skb_queue_head(&priv->bypass_txq, skb);
+                       tx_info->flags |= MWIFIEX_BUF_FLAG_REQUEUED_PKT;
+               } else {
+                       atomic_dec(&adapter->bypass_tx_pending);
+               }
+       }
+}
+
+/*
+ * This function transmits the highest priority packet awaiting in the
+ * WMM Queues.
+ */
+void
+mwifiex_wmm_process_tx(struct mwifiex_adapter *adapter)
+{
+       do {
+               if (mwifiex_dequeue_tx_packet(adapter))
+                       break;
+               if (adapter->iface_type != MWIFIEX_SDIO) {
+                       if (adapter->data_sent ||
+                           adapter->tx_lock_flag)
+                               break;
+               } else {
+                       if (atomic_read(&adapter->tx_queued) >=
+                           MWIFIEX_MAX_PKTS_TXQ)
+                               break;
+               }
+       } while (!mwifiex_wmm_lists_empty(adapter));
+}
diff --git a/drivers/net/wireless/marvell/mwifiex/wmm.h b/drivers/net/wireless/marvell/mwifiex/wmm.h
new file mode 100644 (file)
index 0000000..38f0976
--- /dev/null
@@ -0,0 +1,140 @@
+/*
+ * Marvell Wireless LAN device driver: WMM
+ *
+ * Copyright (C) 2011-2014, Marvell International Ltd.
+ *
+ * This software file (the "File") is distributed by Marvell International
+ * Ltd. under the terms of the GNU General Public License Version 2, June 1991
+ * (the "License").  You may use, redistribute and/or modify this File in
+ * accordance with the terms and conditions of the License, a copy of which
+ * is available by writing to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the
+ * worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
+ *
+ * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
+ * ARE EXPRESSLY DISCLAIMED.  The License provides additional details about
+ * this warranty disclaimer.
+ */
+
+#ifndef _MWIFIEX_WMM_H_
+#define _MWIFIEX_WMM_H_
+
+enum ieee_types_wmm_aciaifsn_bitmasks {
+       MWIFIEX_AIFSN = (BIT(0) | BIT(1) | BIT(2) | BIT(3)),
+       MWIFIEX_ACM = BIT(4),
+       MWIFIEX_ACI = (BIT(5) | BIT(6)),
+};
+
+enum ieee_types_wmm_ecw_bitmasks {
+       MWIFIEX_ECW_MIN = (BIT(0) | BIT(1) | BIT(2) | BIT(3)),
+       MWIFIEX_ECW_MAX = (BIT(4) | BIT(5) | BIT(6) | BIT(7)),
+};
+
+static const u16 mwifiex_1d_to_wmm_queue[8] = { 1, 0, 0, 1, 2, 2, 3, 3 };
+
+/*
+ * This table inverses the tos_to_tid operation to get a priority
+ * which is in sequential order, and can be compared.
+ * Use this to compare the priority of two different TIDs.
+ */
+static const u8 tos_to_tid_inv[] = {
+       0x02,  /* from tos_to_tid[2] = 0 */
+       0x00,  /* from tos_to_tid[0] = 1 */
+       0x01,  /* from tos_to_tid[1] = 2 */
+       0x03,
+       0x04,
+       0x05,
+       0x06,
+       0x07};
+
+/*
+ * This function retrieves the TID of the given RA list.
+ */
+static inline int
+mwifiex_get_tid(struct mwifiex_ra_list_tbl *ptr)
+{
+       struct sk_buff *skb;
+
+       if (skb_queue_empty(&ptr->skb_head))
+               return 0;
+
+       skb = skb_peek(&ptr->skb_head);
+
+       return skb->priority;
+}
+
+/*
+ * This function gets the length of a list.
+ */
+static inline int
+mwifiex_wmm_list_len(struct list_head *head)
+{
+       struct list_head *pos;
+       int count = 0;
+
+       list_for_each(pos, head)
+               ++count;
+
+       return count;
+}
+
+/*
+ * This function checks if a RA list is empty or not.
+ */
+static inline u8
+mwifiex_wmm_is_ra_list_empty(struct list_head *ra_list_hhead)
+{
+       struct mwifiex_ra_list_tbl *ra_list;
+       int is_list_empty;
+
+       list_for_each_entry(ra_list, ra_list_hhead, list) {
+               is_list_empty = skb_queue_empty(&ra_list->skb_head);
+               if (!is_list_empty)
+                       return false;
+       }
+
+       return true;
+}
+
+void mwifiex_wmm_add_buf_txqueue(struct mwifiex_private *priv,
+                                struct sk_buff *skb);
+void mwifiex_wmm_add_buf_bypass_txqueue(struct mwifiex_private *priv,
+                                       struct sk_buff *skb);
+void mwifiex_ralist_add(struct mwifiex_private *priv, const u8 *ra);
+void mwifiex_rotate_priolists(struct mwifiex_private *priv,
+                             struct mwifiex_ra_list_tbl *ra, int tid);
+
+int mwifiex_wmm_lists_empty(struct mwifiex_adapter *adapter);
+int mwifiex_bypass_txlist_empty(struct mwifiex_adapter *adapter);
+void mwifiex_wmm_process_tx(struct mwifiex_adapter *adapter);
+void mwifiex_process_bypass_tx(struct mwifiex_adapter *adapter);
+int mwifiex_is_ralist_valid(struct mwifiex_private *priv,
+                           struct mwifiex_ra_list_tbl *ra_list, int tid);
+
+u8 mwifiex_wmm_compute_drv_pkt_delay(struct mwifiex_private *priv,
+                                    const struct sk_buff *skb);
+void mwifiex_wmm_init(struct mwifiex_adapter *adapter);
+
+u32 mwifiex_wmm_process_association_req(struct mwifiex_private *priv,
+                                       u8 **assoc_buf,
+                                       struct ieee_types_wmm_parameter *wmmie,
+                                       struct ieee80211_ht_cap *htcap);
+
+void mwifiex_wmm_setup_queue_priorities(struct mwifiex_private *priv,
+                                       struct ieee_types_wmm_parameter *wmm_ie);
+void mwifiex_wmm_setup_ac_downgrade(struct mwifiex_private *priv);
+int mwifiex_ret_wmm_get_status(struct mwifiex_private *priv,
+                              const struct host_cmd_ds_command *resp);
+struct mwifiex_ra_list_tbl *
+mwifiex_wmm_get_queue_raptr(struct mwifiex_private *priv, u8 tid,
+                           const u8 *ra_addr);
+u8 mwifiex_wmm_downgrade_tid(struct mwifiex_private *priv, u32 tid);
+void mwifiex_update_ralist_tx_pause(struct mwifiex_private *priv, u8 *mac,
+                                   u8 tx_pause);
+void mwifiex_update_ralist_tx_pause_in_tdls_cs(struct mwifiex_private *priv,
+                                              u8 *mac, u8 tx_pause);
+
+struct mwifiex_ra_list_tbl *mwifiex_wmm_get_ralist_node(struct mwifiex_private
+                                       *priv, u8 tid, const u8 *ra_addr);
+#endif /* !_MWIFIEX_WMM_H_ */
diff --git a/drivers/net/wireless/mwifiex/11ac.c b/drivers/net/wireless/mwifiex/11ac.c
deleted file mode 100644 (file)
index 59d23fb..0000000
+++ /dev/null
@@ -1,382 +0,0 @@
-/*
- * Marvell Wireless LAN device driver: 802.11ac
- *
- * Copyright (C) 2013-2014, Marvell International Ltd.
- *
- * This software file (the "File") is distributed by Marvell International
- * Ltd. under the terms of the GNU General Public License Version 2, June 1991
- * (the "License").  You may use, redistribute and/or modify this File in
- * accordance with the terms and conditions of the License, a copy of which
- * is available by writing to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the
- * worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
- *
- * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
- * ARE EXPRESSLY DISCLAIMED.  The License provides additional details about
- * this warranty disclaimer.
- */
-
-#include "decl.h"
-#include "ioctl.h"
-#include "fw.h"
-#include "main.h"
-#include "11ac.h"
-
-/* Tables of the MCS map to the highest data rate (in Mbps) supported
- * for long GI.
- */
-static const u16 max_rate_lgi_80MHZ[8][3] = {
-       {0x124, 0x15F, 0x186},  /* NSS = 1 */
-       {0x249, 0x2BE, 0x30C},  /* NSS = 2 */
-       {0x36D, 0x41D, 0x492},  /* NSS = 3 */
-       {0x492, 0x57C, 0x618},  /* NSS = 4 */
-       {0x5B6, 0x6DB, 0x79E},  /* NSS = 5 */
-       {0x6DB, 0x83A, 0x0},    /* NSS = 6 */
-       {0x7FF, 0x999, 0xAAA},  /* NSS = 7 */
-       {0x924, 0xAF8, 0xC30}   /* NSS = 8 */
-};
-
-static const u16 max_rate_lgi_160MHZ[8][3] = {
-       {0x249, 0x2BE, 0x30C},   /* NSS = 1 */
-       {0x492, 0x57C, 0x618},   /* NSS = 2 */
-       {0x6DB, 0x83A, 0x0},     /* NSS = 3 */
-       {0x924, 0xAF8, 0xC30},   /* NSS = 4 */
-       {0xB6D, 0xDB6, 0xF3C},   /* NSS = 5 */
-       {0xDB6, 0x1074, 0x1248}, /* NSS = 6 */
-       {0xFFF, 0x1332, 0x1554}, /* NSS = 7 */
-       {0x1248, 0x15F0, 0x1860} /* NSS = 8 */
-};
-
-/* This function converts the 2-bit MCS map to the highest long GI
- * VHT data rate.
- */
-static u16
-mwifiex_convert_mcsmap_to_maxrate(struct mwifiex_private *priv,
-                                 u8 bands, u16 mcs_map)
-{
-       u8 i, nss, mcs;
-       u16 max_rate = 0;
-       u32 usr_vht_cap_info = 0;
-       struct mwifiex_adapter *adapter = priv->adapter;
-
-       if (bands & BAND_AAC)
-               usr_vht_cap_info = adapter->usr_dot_11ac_dev_cap_a;
-       else
-               usr_vht_cap_info = adapter->usr_dot_11ac_dev_cap_bg;
-
-       /* find the max NSS supported */
-       nss = 1;
-       for (i = 1; i <= 8; i++) {
-               mcs = GET_VHTNSSMCS(mcs_map, i);
-               if (mcs < IEEE80211_VHT_MCS_NOT_SUPPORTED)
-                       nss = i;
-       }
-       mcs = GET_VHTNSSMCS(mcs_map, nss);
-
-       /* if mcs is 3, nss must be 1 (NSS = 1). Default mcs to MCS 0~9 */
-       if (mcs == IEEE80211_VHT_MCS_NOT_SUPPORTED)
-               mcs = IEEE80211_VHT_MCS_SUPPORT_0_9;
-
-       if (GET_VHTCAP_CHWDSET(usr_vht_cap_info)) {
-               /* support 160 MHz */
-               max_rate = max_rate_lgi_160MHZ[nss - 1][mcs];
-               if (!max_rate)
-                       /* MCS9 is not supported in NSS6 */
-                       max_rate = max_rate_lgi_160MHZ[nss - 1][mcs - 1];
-       } else {
-               max_rate = max_rate_lgi_80MHZ[nss - 1][mcs];
-               if (!max_rate)
-                       /* MCS9 is not supported in NSS3 */
-                       max_rate = max_rate_lgi_80MHZ[nss - 1][mcs - 1];
-       }
-
-       return max_rate;
-}
-
-static void
-mwifiex_fill_vht_cap_info(struct mwifiex_private *priv,
-                         struct ieee80211_vht_cap *vht_cap, u8 bands)
-{
-       struct mwifiex_adapter *adapter = priv->adapter;
-
-       if (bands & BAND_A)
-               vht_cap->vht_cap_info =
-                               cpu_to_le32(adapter->usr_dot_11ac_dev_cap_a);
-       else
-               vht_cap->vht_cap_info =
-                               cpu_to_le32(adapter->usr_dot_11ac_dev_cap_bg);
-}
-
-void mwifiex_fill_vht_cap_tlv(struct mwifiex_private *priv,
-                             struct ieee80211_vht_cap *vht_cap, u8 bands)
-{
-       struct mwifiex_adapter *adapter = priv->adapter;
-       u16 mcs_map_user, mcs_map_resp, mcs_map_result;
-       u16 mcs_user, mcs_resp, nss, tmp;
-
-       /* Fill VHT cap info */
-       mwifiex_fill_vht_cap_info(priv, vht_cap, bands);
-
-       /* rx MCS Set: find the minimum of the user rx mcs and ap rx mcs */
-       mcs_map_user = GET_DEVRXMCSMAP(adapter->usr_dot_11ac_mcs_support);
-       mcs_map_resp = le16_to_cpu(vht_cap->supp_mcs.rx_mcs_map);
-       mcs_map_result = 0;
-
-       for (nss = 1; nss <= 8; nss++) {
-               mcs_user = GET_VHTNSSMCS(mcs_map_user, nss);
-               mcs_resp = GET_VHTNSSMCS(mcs_map_resp, nss);
-
-               if ((mcs_user == IEEE80211_VHT_MCS_NOT_SUPPORTED) ||
-                   (mcs_resp == IEEE80211_VHT_MCS_NOT_SUPPORTED))
-                       SET_VHTNSSMCS(mcs_map_result, nss,
-                                     IEEE80211_VHT_MCS_NOT_SUPPORTED);
-               else
-                       SET_VHTNSSMCS(mcs_map_result, nss,
-                                     min(mcs_user, mcs_resp));
-       }
-
-       vht_cap->supp_mcs.rx_mcs_map = cpu_to_le16(mcs_map_result);
-
-       tmp = mwifiex_convert_mcsmap_to_maxrate(priv, bands, mcs_map_result);
-       vht_cap->supp_mcs.rx_highest = cpu_to_le16(tmp);
-
-       /* tx MCS Set: find the minimum of the user tx mcs and ap tx mcs */
-       mcs_map_user = GET_DEVTXMCSMAP(adapter->usr_dot_11ac_mcs_support);
-       mcs_map_resp = le16_to_cpu(vht_cap->supp_mcs.tx_mcs_map);
-       mcs_map_result = 0;
-
-       for (nss = 1; nss <= 8; nss++) {
-               mcs_user = GET_VHTNSSMCS(mcs_map_user, nss);
-               mcs_resp = GET_VHTNSSMCS(mcs_map_resp, nss);
-               if ((mcs_user == IEEE80211_VHT_MCS_NOT_SUPPORTED) ||
-                   (mcs_resp == IEEE80211_VHT_MCS_NOT_SUPPORTED))
-                       SET_VHTNSSMCS(mcs_map_result, nss,
-                                     IEEE80211_VHT_MCS_NOT_SUPPORTED);
-               else
-                       SET_VHTNSSMCS(mcs_map_result, nss,
-                                     min(mcs_user, mcs_resp));
-       }
-
-       vht_cap->supp_mcs.tx_mcs_map = cpu_to_le16(mcs_map_result);
-
-       tmp = mwifiex_convert_mcsmap_to_maxrate(priv, bands, mcs_map_result);
-       vht_cap->supp_mcs.tx_highest = cpu_to_le16(tmp);
-
-       return;
-}
-
-int mwifiex_cmd_append_11ac_tlv(struct mwifiex_private *priv,
-                            struct mwifiex_bssdescriptor *bss_desc,
-                            u8 **buffer)
-{
-       struct mwifiex_ie_types_vhtcap *vht_cap;
-       struct mwifiex_ie_types_oper_mode_ntf *oper_ntf;
-       struct ieee_types_oper_mode_ntf *ieee_oper_ntf;
-       struct mwifiex_ie_types_vht_oper *vht_op;
-       struct mwifiex_adapter *adapter = priv->adapter;
-       u8 supp_chwd_set;
-       u32 usr_vht_cap_info;
-       int ret_len = 0;
-
-       if (bss_desc->bss_band & BAND_A)
-               usr_vht_cap_info = adapter->usr_dot_11ac_dev_cap_a;
-       else
-               usr_vht_cap_info = adapter->usr_dot_11ac_dev_cap_bg;
-
-       /* VHT Capabilities IE */
-       if (bss_desc->bcn_vht_cap) {
-               vht_cap = (struct mwifiex_ie_types_vhtcap *)*buffer;
-               memset(vht_cap, 0, sizeof(*vht_cap));
-               vht_cap->header.type = cpu_to_le16(WLAN_EID_VHT_CAPABILITY);
-               vht_cap->header.len  =
-                               cpu_to_le16(sizeof(struct ieee80211_vht_cap));
-               memcpy((u8 *)vht_cap + sizeof(struct mwifiex_ie_types_header),
-                      (u8 *)bss_desc->bcn_vht_cap,
-                      le16_to_cpu(vht_cap->header.len));
-
-               mwifiex_fill_vht_cap_tlv(priv, &vht_cap->vht_cap,
-                                        bss_desc->bss_band);
-               *buffer += sizeof(*vht_cap);
-               ret_len += sizeof(*vht_cap);
-       }
-
-       /* VHT Operation IE */
-       if (bss_desc->bcn_vht_oper) {
-               if (priv->bss_mode == NL80211_IFTYPE_STATION) {
-                       vht_op = (struct mwifiex_ie_types_vht_oper *)*buffer;
-                       memset(vht_op, 0, sizeof(*vht_op));
-                       vht_op->header.type =
-                                       cpu_to_le16(WLAN_EID_VHT_OPERATION);
-                       vht_op->header.len  = cpu_to_le16(sizeof(*vht_op) -
-                                     sizeof(struct mwifiex_ie_types_header));
-                       memcpy((u8 *)vht_op +
-                               sizeof(struct mwifiex_ie_types_header),
-                              (u8 *)bss_desc->bcn_vht_oper,
-                              le16_to_cpu(vht_op->header.len));
-
-                       /* negotiate the channel width and central freq
-                        * and keep the central freq as the peer suggests
-                        */
-                       supp_chwd_set = GET_VHTCAP_CHWDSET(usr_vht_cap_info);
-
-                       switch (supp_chwd_set) {
-                       case 0:
-                               vht_op->chan_width =
-                                    min_t(u8, IEEE80211_VHT_CHANWIDTH_80MHZ,
-                                          bss_desc->bcn_vht_oper->chan_width);
-                               break;
-                       case 1:
-                               vht_op->chan_width =
-                                    min_t(u8, IEEE80211_VHT_CHANWIDTH_160MHZ,
-                                          bss_desc->bcn_vht_oper->chan_width);
-                               break;
-                       case 2:
-                               vht_op->chan_width =
-                                    min_t(u8, IEEE80211_VHT_CHANWIDTH_80P80MHZ,
-                                          bss_desc->bcn_vht_oper->chan_width);
-                               break;
-                       default:
-                               vht_op->chan_width =
-                                    IEEE80211_VHT_CHANWIDTH_USE_HT;
-                               break;
-                       }
-
-                       *buffer += sizeof(*vht_op);
-                       ret_len += sizeof(*vht_op);
-               }
-       }
-
-       /* Operating Mode Notification IE */
-       if (bss_desc->oper_mode) {
-               ieee_oper_ntf = bss_desc->oper_mode;
-               oper_ntf = (void *)*buffer;
-               memset(oper_ntf, 0, sizeof(*oper_ntf));
-               oper_ntf->header.type = cpu_to_le16(WLAN_EID_OPMODE_NOTIF);
-               oper_ntf->header.len = cpu_to_le16(sizeof(u8));
-               oper_ntf->oper_mode = ieee_oper_ntf->oper_mode;
-               *buffer += sizeof(*oper_ntf);
-               ret_len += sizeof(*oper_ntf);
-       }
-
-       return ret_len;
-}
-
-int mwifiex_cmd_11ac_cfg(struct mwifiex_private *priv,
-                        struct host_cmd_ds_command *cmd, u16 cmd_action,
-                        struct mwifiex_11ac_vht_cfg *cfg)
-{
-       struct host_cmd_11ac_vht_cfg *vhtcfg = &cmd->params.vht_cfg;
-
-       cmd->command = cpu_to_le16(HostCmd_CMD_11AC_CFG);
-       cmd->size = cpu_to_le16(sizeof(struct host_cmd_11ac_vht_cfg) +
-                               S_DS_GEN);
-       vhtcfg->action = cpu_to_le16(cmd_action);
-       vhtcfg->band_config = cfg->band_config;
-       vhtcfg->misc_config = cfg->misc_config;
-       vhtcfg->cap_info = cpu_to_le32(cfg->cap_info);
-       vhtcfg->mcs_tx_set = cpu_to_le32(cfg->mcs_tx_set);
-       vhtcfg->mcs_rx_set = cpu_to_le32(cfg->mcs_rx_set);
-
-       return 0;
-}
-
-/* This function initializes the BlockACK setup information for given
- * mwifiex_private structure for 11ac enabled networks.
- */
-void mwifiex_set_11ac_ba_params(struct mwifiex_private *priv)
-{
-       priv->add_ba_param.timeout = MWIFIEX_DEFAULT_BLOCK_ACK_TIMEOUT;
-
-       if (GET_BSS_ROLE(priv) == MWIFIEX_BSS_ROLE_UAP) {
-               priv->add_ba_param.tx_win_size =
-                                          MWIFIEX_11AC_UAP_AMPDU_DEF_TXWINSIZE;
-               priv->add_ba_param.rx_win_size =
-                                          MWIFIEX_11AC_UAP_AMPDU_DEF_RXWINSIZE;
-       } else {
-               priv->add_ba_param.tx_win_size =
-                                          MWIFIEX_11AC_STA_AMPDU_DEF_TXWINSIZE;
-               priv->add_ba_param.rx_win_size =
-                                          MWIFIEX_11AC_STA_AMPDU_DEF_RXWINSIZE;
-       }
-
-       return;
-}
-
-bool mwifiex_is_bss_in_11ac_mode(struct mwifiex_private *priv)
-{
-       struct mwifiex_bssdescriptor *bss_desc;
-       struct ieee80211_vht_operation *vht_oper;
-
-       bss_desc = &priv->curr_bss_params.bss_descriptor;
-       vht_oper = bss_desc->bcn_vht_oper;
-
-       if (!bss_desc->bcn_vht_cap || !vht_oper)
-               return false;
-
-       if (vht_oper->chan_width == IEEE80211_VHT_CHANWIDTH_USE_HT)
-               return false;
-
-       return true;
-}
-
-u8 mwifiex_get_center_freq_index(struct mwifiex_private *priv, u8 band,
-                                u32 pri_chan, u8 chan_bw)
-{
-       u8 center_freq_idx = 0;
-
-       if (band & BAND_AAC) {
-               switch (pri_chan) {
-               case 36:
-               case 40:
-               case 44:
-               case 48:
-                       if (chan_bw == IEEE80211_VHT_CHANWIDTH_80MHZ)
-                               center_freq_idx = 42;
-                       break;
-               case 52:
-               case 56:
-               case 60:
-               case 64:
-                       if (chan_bw == IEEE80211_VHT_CHANWIDTH_80MHZ)
-                               center_freq_idx = 58;
-                       else if (chan_bw == IEEE80211_VHT_CHANWIDTH_160MHZ)
-                               center_freq_idx = 50;
-                       break;
-               case 100:
-               case 104:
-               case 108:
-               case 112:
-                       if (chan_bw == IEEE80211_VHT_CHANWIDTH_80MHZ)
-                               center_freq_idx = 106;
-                       break;
-               case 116:
-               case 120:
-               case 124:
-               case 128:
-                       if (chan_bw == IEEE80211_VHT_CHANWIDTH_80MHZ)
-                               center_freq_idx = 122;
-                       else if (chan_bw == IEEE80211_VHT_CHANWIDTH_160MHZ)
-                               center_freq_idx = 114;
-                       break;
-               case 132:
-               case 136:
-               case 140:
-               case 144:
-                       if (chan_bw == IEEE80211_VHT_CHANWIDTH_80MHZ)
-                               center_freq_idx = 138;
-                       break;
-               case 149:
-               case 153:
-               case 157:
-               case 161:
-                       if (chan_bw == IEEE80211_VHT_CHANWIDTH_80MHZ)
-                               center_freq_idx = 155;
-                       break;
-               default:
-                       center_freq_idx = 42;
-               }
-       }
-
-       return center_freq_idx;
-}
diff --git a/drivers/net/wireless/mwifiex/11ac.h b/drivers/net/wireless/mwifiex/11ac.h
deleted file mode 100644 (file)
index 1ca92c7..0000000
+++ /dev/null
@@ -1,45 +0,0 @@
-/*
- * Marvell Wireless LAN device driver: 802.11ac
- *
- * Copyright (C) 2013-2014, Marvell International Ltd.
- *
- * This software file (the "File") is distributed by Marvell International
- * Ltd. under the terms of the GNU General Public License Version 2, June 1991
- * (the "License").  You may use, redistribute and/or modify this File in
- * accordance with the terms and conditions of the License, a copy of which
- * is available by writing to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the
- * worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
- *
- * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
- * ARE EXPRESSLY DISCLAIMED.  The License provides additional details about
- * this warranty disclaimer.
- */
-
-#ifndef _MWIFIEX_11AC_H_
-#define _MWIFIEX_11AC_H_
-
-#define VHT_CFG_2GHZ BIT(0)
-#define VHT_CFG_5GHZ BIT(1)
-
-enum vht_cfg_misc_config {
-       VHT_CAP_TX_OPERATION = 1,
-       VHT_CAP_ASSOCIATION,
-       VHT_CAP_UAP_ONLY
-};
-
-#define DEFAULT_VHT_MCS_SET 0xfffa
-#define DISABLE_VHT_MCS_SET 0xffff
-
-#define VHT_BW_80_160_80P80 BIT(2)
-
-int mwifiex_cmd_append_11ac_tlv(struct mwifiex_private *priv,
-                               struct mwifiex_bssdescriptor *bss_desc,
-                               u8 **buffer);
-int mwifiex_cmd_11ac_cfg(struct mwifiex_private *priv,
-                        struct host_cmd_ds_command *cmd, u16 cmd_action,
-                        struct mwifiex_11ac_vht_cfg *cfg);
-void mwifiex_fill_vht_cap_tlv(struct mwifiex_private *priv,
-                             struct ieee80211_vht_cap *vht_cap, u8 bands);
-#endif /* _MWIFIEX_11AC_H_ */
diff --git a/drivers/net/wireless/mwifiex/11h.c b/drivers/net/wireless/mwifiex/11h.c
deleted file mode 100644 (file)
index 71a1b58..0000000
+++ /dev/null
@@ -1,319 +0,0 @@
-/*
- * Marvell Wireless LAN device driver: 802.11h
- *
- * Copyright (C) 2013-2014, Marvell International Ltd.
- *
- * This software file (the "File") is distributed by Marvell International
- * Ltd. under the terms of the GNU General Public License Version 2, June 1991
- * (the "License").  You may use, redistribute and/or modify this File in
- * accordance with the terms and conditions of the License, a copy of which
- * is available by writing to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the
- * worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
- *
- * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
- * ARE EXPRESSLY DISCLAIMED.  The License provides additional details about
- * this warranty disclaimer.
- */
-
-#include "main.h"
-#include "fw.h"
-
-
-void mwifiex_init_11h_params(struct mwifiex_private *priv)
-{
-       priv->state_11h.is_11h_enabled = true;
-       priv->state_11h.is_11h_active = false;
-}
-
-inline int mwifiex_is_11h_active(struct mwifiex_private *priv)
-{
-       return priv->state_11h.is_11h_active;
-}
-/* This function appends 11h info to a buffer while joining an
- * infrastructure BSS
- */
-static void
-mwifiex_11h_process_infra_join(struct mwifiex_private *priv, u8 **buffer,
-                              struct mwifiex_bssdescriptor *bss_desc)
-{
-       struct mwifiex_ie_types_header *ie_header;
-       struct mwifiex_ie_types_pwr_capability *cap;
-       struct mwifiex_ie_types_local_pwr_constraint *constraint;
-       struct ieee80211_supported_band *sband;
-       u8 radio_type;
-       int i;
-
-       if (!buffer || !(*buffer))
-               return;
-
-       radio_type = mwifiex_band_to_radio_type((u8) bss_desc->bss_band);
-       sband = priv->wdev.wiphy->bands[radio_type];
-
-       cap = (struct mwifiex_ie_types_pwr_capability *)*buffer;
-       cap->header.type = cpu_to_le16(WLAN_EID_PWR_CAPABILITY);
-       cap->header.len = cpu_to_le16(2);
-       cap->min_pwr = 0;
-       cap->max_pwr = 0;
-       *buffer += sizeof(*cap);
-
-       constraint = (struct mwifiex_ie_types_local_pwr_constraint *)*buffer;
-       constraint->header.type = cpu_to_le16(WLAN_EID_PWR_CONSTRAINT);
-       constraint->header.len = cpu_to_le16(2);
-       constraint->chan = bss_desc->channel;
-       constraint->constraint = bss_desc->local_constraint;
-       *buffer += sizeof(*constraint);
-
-       ie_header = (struct mwifiex_ie_types_header *)*buffer;
-       ie_header->type = cpu_to_le16(TLV_TYPE_PASSTHROUGH);
-       ie_header->len  = cpu_to_le16(2 * sband->n_channels + 2);
-       *buffer += sizeof(*ie_header);
-       *(*buffer)++ = WLAN_EID_SUPPORTED_CHANNELS;
-       *(*buffer)++ = 2 * sband->n_channels;
-       for (i = 0; i < sband->n_channels; i++) {
-               *(*buffer)++ = ieee80211_frequency_to_channel(
-                                       sband->channels[i].center_freq);
-               *(*buffer)++ = 1; /* one channel in the subband */
-       }
-}
-
-/* Enable or disable the 11h extensions in the firmware */
-int mwifiex_11h_activate(struct mwifiex_private *priv, bool flag)
-{
-       u32 enable = flag;
-
-       /* enable master mode radar detection on AP interface */
-       if ((GET_BSS_ROLE(priv) == MWIFIEX_BSS_ROLE_UAP) && enable)
-               enable |= MWIFIEX_MASTER_RADAR_DET_MASK;
-
-       return mwifiex_send_cmd(priv, HostCmd_CMD_802_11_SNMP_MIB,
-                               HostCmd_ACT_GEN_SET, DOT11H_I, &enable, true);
-}
-
-/* This functions processes TLV buffer for a pending BSS Join command.
- *
- * Activate 11h functionality in the firmware if the spectrum management
- * capability bit is found in the network we are joining. Also, necessary
- * TLVs are set based on requested network's 11h capability.
- */
-void mwifiex_11h_process_join(struct mwifiex_private *priv, u8 **buffer,
-                             struct mwifiex_bssdescriptor *bss_desc)
-{
-       if (bss_desc->sensed_11h) {
-               /* Activate 11h functions in firmware, turns on capability
-                * bit
-                */
-               mwifiex_11h_activate(priv, true);
-               priv->state_11h.is_11h_active = true;
-               bss_desc->cap_info_bitmap |= WLAN_CAPABILITY_SPECTRUM_MGMT;
-               mwifiex_11h_process_infra_join(priv, buffer, bss_desc);
-       } else {
-               /* Deactivate 11h functions in the firmware */
-               mwifiex_11h_activate(priv, false);
-               priv->state_11h.is_11h_active = false;
-               bss_desc->cap_info_bitmap &= ~WLAN_CAPABILITY_SPECTRUM_MGMT;
-       }
-}
-
-/* This is DFS CAC work queue function.
- * This delayed work emits CAC finished event for cfg80211 if
- * CAC was started earlier.
- */
-void mwifiex_dfs_cac_work_queue(struct work_struct *work)
-{
-       struct cfg80211_chan_def chandef;
-       struct delayed_work *delayed_work =
-                       container_of(work, struct delayed_work, work);
-       struct mwifiex_private *priv =
-                       container_of(delayed_work, struct mwifiex_private,
-                                    dfs_cac_work);
-
-       if (WARN_ON(!priv))
-               return;
-
-       chandef = priv->dfs_chandef;
-       if (priv->wdev.cac_started) {
-               mwifiex_dbg(priv->adapter, MSG,
-                           "CAC timer finished; No radar detected\n");
-               cfg80211_cac_event(priv->netdev, &chandef,
-                                  NL80211_RADAR_CAC_FINISHED,
-                                  GFP_KERNEL);
-       }
-}
-
-/* This function prepares channel report request command to FW for
- * starting radar detection.
- */
-int mwifiex_cmd_issue_chan_report_request(struct mwifiex_private *priv,
-                                         struct host_cmd_ds_command *cmd,
-                                         void *data_buf)
-{
-       struct host_cmd_ds_chan_rpt_req *cr_req = &cmd->params.chan_rpt_req;
-       struct mwifiex_radar_params *radar_params = (void *)data_buf;
-
-       cmd->command = cpu_to_le16(HostCmd_CMD_CHAN_REPORT_REQUEST);
-       cmd->size = cpu_to_le16(S_DS_GEN);
-       le16_add_cpu(&cmd->size, sizeof(struct host_cmd_ds_chan_rpt_req));
-
-       cr_req->chan_desc.start_freq = cpu_to_le16(MWIFIEX_A_BAND_START_FREQ);
-       cr_req->chan_desc.chan_num = radar_params->chandef->chan->hw_value;
-       cr_req->chan_desc.chan_width = radar_params->chandef->width;
-       cr_req->msec_dwell_time = cpu_to_le32(radar_params->cac_time_ms);
-
-       if (radar_params->cac_time_ms)
-               mwifiex_dbg(priv->adapter, MSG,
-                           "11h: issuing DFS Radar check for channel=%d\n",
-                           radar_params->chandef->chan->hw_value);
-       else
-               mwifiex_dbg(priv->adapter, MSG, "cancelling CAC\n");
-
-       return 0;
-}
-
-int mwifiex_stop_radar_detection(struct mwifiex_private *priv,
-                                struct cfg80211_chan_def *chandef)
-{
-       struct mwifiex_radar_params radar_params;
-
-       memset(&radar_params, 0, sizeof(struct mwifiex_radar_params));
-       radar_params.chandef = chandef;
-       radar_params.cac_time_ms = 0;
-
-       return mwifiex_send_cmd(priv, HostCmd_CMD_CHAN_REPORT_REQUEST,
-                               HostCmd_ACT_GEN_SET, 0, &radar_params, true);
-}
-
-/* This function is to abort ongoing CAC upon stopping AP operations
- * or during unload.
- */
-void mwifiex_abort_cac(struct mwifiex_private *priv)
-{
-       if (priv->wdev.cac_started) {
-               if (mwifiex_stop_radar_detection(priv, &priv->dfs_chandef))
-                       mwifiex_dbg(priv->adapter, ERROR,
-                                   "failed to stop CAC in FW\n");
-               mwifiex_dbg(priv->adapter, MSG,
-                           "Aborting delayed work for CAC.\n");
-               cancel_delayed_work_sync(&priv->dfs_cac_work);
-               cfg80211_cac_event(priv->netdev, &priv->dfs_chandef,
-                                  NL80211_RADAR_CAC_ABORTED, GFP_KERNEL);
-       }
-}
-
-/* This function handles channel report event from FW during CAC period.
- * If radar is detected during CAC, driver indicates the same to cfg80211
- * and also cancels ongoing delayed work.
- */
-int mwifiex_11h_handle_chanrpt_ready(struct mwifiex_private *priv,
-                                    struct sk_buff *skb)
-{
-       struct host_cmd_ds_chan_rpt_event *rpt_event;
-       struct mwifiex_ie_types_chan_rpt_data *rpt;
-       u8 *evt_buf;
-       u16 event_len, tlv_len;
-
-       rpt_event = (void *)(skb->data + sizeof(u32));
-       event_len = skb->len - (sizeof(struct host_cmd_ds_chan_rpt_event)+
-                               sizeof(u32));
-
-       if (le32_to_cpu(rpt_event->result) != HostCmd_RESULT_OK) {
-               mwifiex_dbg(priv->adapter, ERROR,
-                           "Error in channel report event\n");
-               return -1;
-       }
-
-       evt_buf = (void *)&rpt_event->tlvbuf;
-
-       while (event_len >= sizeof(struct mwifiex_ie_types_header)) {
-               rpt = (void *)&rpt_event->tlvbuf;
-               tlv_len = le16_to_cpu(rpt->header.len);
-
-               switch (le16_to_cpu(rpt->header.type)) {
-               case TLV_TYPE_CHANRPT_11H_BASIC:
-                       if (rpt->map.radar) {
-                               mwifiex_dbg(priv->adapter, MSG,
-                                           "RADAR Detected on channel %d!\n",
-                                           priv->dfs_chandef.chan->hw_value);
-                               cancel_delayed_work_sync(&priv->dfs_cac_work);
-                               cfg80211_cac_event(priv->netdev,
-                                                  &priv->dfs_chandef,
-                                                  NL80211_RADAR_DETECTED,
-                                                  GFP_KERNEL);
-                       }
-                       break;
-               default:
-                       break;
-               }
-
-               evt_buf += (tlv_len + sizeof(rpt->header));
-               event_len -= (tlv_len + sizeof(rpt->header));
-       }
-
-       return 0;
-}
-
-/* Handler for radar detected event from FW.*/
-int mwifiex_11h_handle_radar_detected(struct mwifiex_private *priv,
-                                     struct sk_buff *skb)
-{
-       struct mwifiex_radar_det_event *rdr_event;
-
-       rdr_event = (void *)(skb->data + sizeof(u32));
-
-       if (le32_to_cpu(rdr_event->passed)) {
-               mwifiex_dbg(priv->adapter, MSG,
-                           "radar detected; indicating kernel\n");
-               if (mwifiex_stop_radar_detection(priv, &priv->dfs_chandef))
-                       mwifiex_dbg(priv->adapter, ERROR,
-                                   "Failed to stop CAC in FW\n");
-               cfg80211_radar_event(priv->adapter->wiphy, &priv->dfs_chandef,
-                                    GFP_KERNEL);
-               mwifiex_dbg(priv->adapter, MSG, "regdomain: %d\n",
-                           rdr_event->reg_domain);
-               mwifiex_dbg(priv->adapter, MSG, "radar detection type: %d\n",
-                           rdr_event->det_type);
-       } else {
-               mwifiex_dbg(priv->adapter, MSG,
-                           "false radar detection event!\n");
-       }
-
-       return 0;
-}
-
-/* This is work queue function for channel switch handling.
- * This function takes care of updating new channel definitin to
- * bss config structure, restart AP and indicate channel switch success
- * to cfg80211.
- */
-void mwifiex_dfs_chan_sw_work_queue(struct work_struct *work)
-{
-       struct mwifiex_uap_bss_param *bss_cfg;
-       struct delayed_work *delayed_work =
-                       container_of(work, struct delayed_work, work);
-       struct mwifiex_private *priv =
-                       container_of(delayed_work, struct mwifiex_private,
-                                    dfs_chan_sw_work);
-
-       if (WARN_ON(!priv))
-               return;
-
-       bss_cfg = &priv->bss_cfg;
-       if (!bss_cfg->beacon_period) {
-               mwifiex_dbg(priv->adapter, ERROR,
-                           "channel switch: AP already stopped\n");
-               return;
-       }
-
-       mwifiex_uap_set_channel(priv, bss_cfg, priv->dfs_chandef);
-
-       if (mwifiex_config_start_uap(priv, bss_cfg)) {
-               mwifiex_dbg(priv->adapter, ERROR,
-                           "Failed to start AP after channel switch\n");
-               return;
-       }
-
-       mwifiex_dbg(priv->adapter, MSG,
-                   "indicating channel switch completion to kernel\n");
-       cfg80211_ch_switch_notify(priv->netdev, &priv->dfs_chandef);
-}
diff --git a/drivers/net/wireless/mwifiex/11n.c b/drivers/net/wireless/mwifiex/11n.c
deleted file mode 100644 (file)
index c174e79..0000000
+++ /dev/null
@@ -1,914 +0,0 @@
-/*
- * Marvell Wireless LAN device driver: 802.11n
- *
- * Copyright (C) 2011-2014, Marvell International Ltd.
- *
- * This software file (the "File") is distributed by Marvell International
- * Ltd. under the terms of the GNU General Public License Version 2, June 1991
- * (the "License").  You may use, redistribute and/or modify this File in
- * accordance with the terms and conditions of the License, a copy of which
- * is available by writing to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the
- * worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
- *
- * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
- * ARE EXPRESSLY DISCLAIMED.  The License provides additional details about
- * this warranty disclaimer.
- */
-
-#include "decl.h"
-#include "ioctl.h"
-#include "util.h"
-#include "fw.h"
-#include "main.h"
-#include "wmm.h"
-#include "11n.h"
-
-/*
- * Fills HT capability information field, AMPDU Parameters field, HT extended
- * capability field, and supported MCS set fields.
- *
- * HT capability information field, AMPDU Parameters field, supported MCS set
- * fields are retrieved from cfg80211 stack
- *
- * RD responder bit to set to clear in the extended capability header.
- */
-int mwifiex_fill_cap_info(struct mwifiex_private *priv, u8 radio_type,
-                         struct ieee80211_ht_cap *ht_cap)
-{
-       uint16_t ht_ext_cap = le16_to_cpu(ht_cap->extended_ht_cap_info);
-       struct ieee80211_supported_band *sband =
-                                       priv->wdev.wiphy->bands[radio_type];
-
-       if (WARN_ON_ONCE(!sband)) {
-               mwifiex_dbg(priv->adapter, ERROR, "Invalid radio type!\n");
-               return -EINVAL;
-       }
-
-       ht_cap->ampdu_params_info =
-               (sband->ht_cap.ampdu_factor &
-                IEEE80211_HT_AMPDU_PARM_FACTOR) |
-               ((sband->ht_cap.ampdu_density <<
-                IEEE80211_HT_AMPDU_PARM_DENSITY_SHIFT) &
-                IEEE80211_HT_AMPDU_PARM_DENSITY);
-
-       memcpy((u8 *)&ht_cap->mcs, &sband->ht_cap.mcs,
-              sizeof(sband->ht_cap.mcs));
-
-       if (priv->bss_mode == NL80211_IFTYPE_STATION ||
-           (sband->ht_cap.cap & IEEE80211_HT_CAP_SUP_WIDTH_20_40 &&
-            (priv->adapter->sec_chan_offset !=
-                                       IEEE80211_HT_PARAM_CHA_SEC_NONE)))
-               /* Set MCS32 for infra mode or ad-hoc mode with 40MHz support */
-               SETHT_MCS32(ht_cap->mcs.rx_mask);
-
-       /* Clear RD responder bit */
-       ht_ext_cap &= ~IEEE80211_HT_EXT_CAP_RD_RESPONDER;
-
-       ht_cap->cap_info = cpu_to_le16(sband->ht_cap.cap);
-       ht_cap->extended_ht_cap_info = cpu_to_le16(ht_ext_cap);
-
-       if (ISSUPP_BEAMFORMING(priv->adapter->hw_dot_11n_dev_cap))
-               ht_cap->tx_BF_cap_info = cpu_to_le32(MWIFIEX_DEF_11N_TX_BF_CAP);
-
-       return 0;
-}
-
-/*
- * This function returns the pointer to an entry in BA Stream
- * table which matches the requested BA status.
- */
-static struct mwifiex_tx_ba_stream_tbl *
-mwifiex_get_ba_status(struct mwifiex_private *priv,
-                     enum mwifiex_ba_status ba_status)
-{
-       struct mwifiex_tx_ba_stream_tbl *tx_ba_tsr_tbl;
-       unsigned long flags;
-
-       spin_lock_irqsave(&priv->tx_ba_stream_tbl_lock, flags);
-       list_for_each_entry(tx_ba_tsr_tbl, &priv->tx_ba_stream_tbl_ptr, list) {
-               if (tx_ba_tsr_tbl->ba_status == ba_status) {
-                       spin_unlock_irqrestore(&priv->tx_ba_stream_tbl_lock,
-                                              flags);
-                       return tx_ba_tsr_tbl;
-               }
-       }
-       spin_unlock_irqrestore(&priv->tx_ba_stream_tbl_lock, flags);
-       return NULL;
-}
-
-/*
- * This function handles the command response of delete a block
- * ack request.
- *
- * The function checks the response success status and takes action
- * accordingly (send an add BA request in case of success, or recreate
- * the deleted stream in case of failure, if the add BA was also
- * initiated by us).
- */
-int mwifiex_ret_11n_delba(struct mwifiex_private *priv,
-                         struct host_cmd_ds_command *resp)
-{
-       int tid;
-       struct mwifiex_tx_ba_stream_tbl *tx_ba_tbl;
-       struct host_cmd_ds_11n_delba *del_ba = &resp->params.del_ba;
-       uint16_t del_ba_param_set = le16_to_cpu(del_ba->del_ba_param_set);
-
-       tid = del_ba_param_set >> DELBA_TID_POS;
-       if (del_ba->del_result == BA_RESULT_SUCCESS) {
-               mwifiex_del_ba_tbl(priv, tid, del_ba->peer_mac_addr,
-                                  TYPE_DELBA_SENT,
-                                  INITIATOR_BIT(del_ba_param_set));
-
-               tx_ba_tbl = mwifiex_get_ba_status(priv, BA_SETUP_INPROGRESS);
-               if (tx_ba_tbl)
-                       mwifiex_send_addba(priv, tx_ba_tbl->tid,
-                                          tx_ba_tbl->ra);
-       } else { /*
-                 * In case of failure, recreate the deleted stream in case
-                 * we initiated the ADDBA
-                 */
-               if (!INITIATOR_BIT(del_ba_param_set))
-                       return 0;
-
-               mwifiex_create_ba_tbl(priv, del_ba->peer_mac_addr, tid,
-                                     BA_SETUP_INPROGRESS);
-
-               tx_ba_tbl = mwifiex_get_ba_status(priv, BA_SETUP_INPROGRESS);
-
-               if (tx_ba_tbl)
-                       mwifiex_del_ba_tbl(priv, tx_ba_tbl->tid, tx_ba_tbl->ra,
-                                          TYPE_DELBA_SENT, true);
-       }
-
-       return 0;
-}
-
-/*
- * This function handles the command response of add a block
- * ack request.
- *
- * Handling includes changing the header fields to CPU formats, checking
- * the response success status and taking actions accordingly (delete the
- * BA stream table in case of failure).
- */
-int mwifiex_ret_11n_addba_req(struct mwifiex_private *priv,
-                             struct host_cmd_ds_command *resp)
-{
-       int tid, tid_down;
-       struct host_cmd_ds_11n_addba_rsp *add_ba_rsp = &resp->params.add_ba_rsp;
-       struct mwifiex_tx_ba_stream_tbl *tx_ba_tbl;
-       struct mwifiex_ra_list_tbl *ra_list;
-       u16 block_ack_param_set = le16_to_cpu(add_ba_rsp->block_ack_param_set);
-
-       add_ba_rsp->ssn = cpu_to_le16((le16_to_cpu(add_ba_rsp->ssn))
-                       & SSN_MASK);
-
-       tid = (block_ack_param_set & IEEE80211_ADDBA_PARAM_TID_MASK)
-              >> BLOCKACKPARAM_TID_POS;
-
-       tid_down = mwifiex_wmm_downgrade_tid(priv, tid);
-       ra_list = mwifiex_wmm_get_ralist_node(priv, tid_down, add_ba_rsp->
-               peer_mac_addr);
-       if (le16_to_cpu(add_ba_rsp->status_code) != BA_RESULT_SUCCESS) {
-               if (ra_list) {
-                       ra_list->ba_status = BA_SETUP_NONE;
-                       ra_list->amsdu_in_ampdu = false;
-               }
-               mwifiex_del_ba_tbl(priv, tid, add_ba_rsp->peer_mac_addr,
-                                  TYPE_DELBA_SENT, true);
-               if (add_ba_rsp->add_rsp_result != BA_RESULT_TIMEOUT)
-                       priv->aggr_prio_tbl[tid].ampdu_ap =
-                               BA_STREAM_NOT_ALLOWED;
-               return 0;
-       }
-
-       tx_ba_tbl = mwifiex_get_ba_tbl(priv, tid, add_ba_rsp->peer_mac_addr);
-       if (tx_ba_tbl) {
-               mwifiex_dbg(priv->adapter, EVENT, "info: BA stream complete\n");
-               tx_ba_tbl->ba_status = BA_SETUP_COMPLETE;
-               if ((block_ack_param_set & BLOCKACKPARAM_AMSDU_SUPP_MASK) &&
-                   priv->add_ba_param.tx_amsdu &&
-                   (priv->aggr_prio_tbl[tid].amsdu != BA_STREAM_NOT_ALLOWED))
-                       tx_ba_tbl->amsdu = true;
-               else
-                       tx_ba_tbl->amsdu = false;
-               if (ra_list) {
-                       ra_list->amsdu_in_ampdu = tx_ba_tbl->amsdu;
-                       ra_list->ba_status = BA_SETUP_COMPLETE;
-               }
-       } else {
-               mwifiex_dbg(priv->adapter, ERROR, "BA stream not created\n");
-       }
-
-       return 0;
-}
-
-/*
- * This function prepares command of reconfigure Tx buffer.
- *
- * Preparation includes -
- *      - Setting command ID, action and proper size
- *      - Setting Tx buffer size (for SET only)
- *      - Ensuring correct endian-ness
- */
-int mwifiex_cmd_recfg_tx_buf(struct mwifiex_private *priv,
-                            struct host_cmd_ds_command *cmd, int cmd_action,
-                            u16 *buf_size)
-{
-       struct host_cmd_ds_txbuf_cfg *tx_buf = &cmd->params.tx_buf;
-       u16 action = (u16) cmd_action;
-
-       cmd->command = cpu_to_le16(HostCmd_CMD_RECONFIGURE_TX_BUFF);
-       cmd->size =
-               cpu_to_le16(sizeof(struct host_cmd_ds_txbuf_cfg) + S_DS_GEN);
-       tx_buf->action = cpu_to_le16(action);
-       switch (action) {
-       case HostCmd_ACT_GEN_SET:
-               mwifiex_dbg(priv->adapter, CMD,
-                           "cmd: set tx_buf=%d\n", *buf_size);
-               tx_buf->buff_size = cpu_to_le16(*buf_size);
-               break;
-       case HostCmd_ACT_GEN_GET:
-       default:
-               tx_buf->buff_size = 0;
-               break;
-       }
-       return 0;
-}
-
-/*
- * This function prepares command of AMSDU aggregation control.
- *
- * Preparation includes -
- *      - Setting command ID, action and proper size
- *      - Setting AMSDU control parameters (for SET only)
- *      - Ensuring correct endian-ness
- */
-int mwifiex_cmd_amsdu_aggr_ctrl(struct host_cmd_ds_command *cmd,
-                               int cmd_action,
-                               struct mwifiex_ds_11n_amsdu_aggr_ctrl *aa_ctrl)
-{
-       struct host_cmd_ds_amsdu_aggr_ctrl *amsdu_ctrl =
-               &cmd->params.amsdu_aggr_ctrl;
-       u16 action = (u16) cmd_action;
-
-       cmd->command = cpu_to_le16(HostCmd_CMD_AMSDU_AGGR_CTRL);
-       cmd->size = cpu_to_le16(sizeof(struct host_cmd_ds_amsdu_aggr_ctrl)
-                               + S_DS_GEN);
-       amsdu_ctrl->action = cpu_to_le16(action);
-       switch (action) {
-       case HostCmd_ACT_GEN_SET:
-               amsdu_ctrl->enable = cpu_to_le16(aa_ctrl->enable);
-               amsdu_ctrl->curr_buf_size = 0;
-               break;
-       case HostCmd_ACT_GEN_GET:
-       default:
-               amsdu_ctrl->curr_buf_size = 0;
-               break;
-       }
-       return 0;
-}
-
-/*
- * This function prepares 11n configuration command.
- *
- * Preparation includes -
- *      - Setting command ID, action and proper size
- *      - Setting HT Tx capability and HT Tx information fields
- *      - Ensuring correct endian-ness
- */
-int mwifiex_cmd_11n_cfg(struct mwifiex_private *priv,
-                       struct host_cmd_ds_command *cmd, u16 cmd_action,
-                       struct mwifiex_ds_11n_tx_cfg *txcfg)
-{
-       struct host_cmd_ds_11n_cfg *htcfg = &cmd->params.htcfg;
-
-       cmd->command = cpu_to_le16(HostCmd_CMD_11N_CFG);
-       cmd->size = cpu_to_le16(sizeof(struct host_cmd_ds_11n_cfg) + S_DS_GEN);
-       htcfg->action = cpu_to_le16(cmd_action);
-       htcfg->ht_tx_cap = cpu_to_le16(txcfg->tx_htcap);
-       htcfg->ht_tx_info = cpu_to_le16(txcfg->tx_htinfo);
-
-       if (priv->adapter->is_hw_11ac_capable)
-               htcfg->misc_config = cpu_to_le16(txcfg->misc_config);
-
-       return 0;
-}
-
-/*
- * This function appends an 11n TLV to a buffer.
- *
- * Buffer allocation is responsibility of the calling
- * function. No size validation is made here.
- *
- * The function fills up the following sections, if applicable -
- *      - HT capability IE
- *      - HT information IE (with channel list)
- *      - 20/40 BSS Coexistence IE
- *      - HT Extended Capabilities IE
- */
-int
-mwifiex_cmd_append_11n_tlv(struct mwifiex_private *priv,
-                          struct mwifiex_bssdescriptor *bss_desc,
-                          u8 **buffer)
-{
-       struct mwifiex_ie_types_htcap *ht_cap;
-       struct mwifiex_ie_types_htinfo *ht_info;
-       struct mwifiex_ie_types_chan_list_param_set *chan_list;
-       struct mwifiex_ie_types_2040bssco *bss_co_2040;
-       struct mwifiex_ie_types_extcap *ext_cap;
-       int ret_len = 0;
-       struct ieee80211_supported_band *sband;
-       struct ieee_types_header *hdr;
-       u8 radio_type;
-
-       if (!buffer || !*buffer)
-               return ret_len;
-
-       radio_type = mwifiex_band_to_radio_type((u8) bss_desc->bss_band);
-       sband = priv->wdev.wiphy->bands[radio_type];
-
-       if (bss_desc->bcn_ht_cap) {
-               ht_cap = (struct mwifiex_ie_types_htcap *) *buffer;
-               memset(ht_cap, 0, sizeof(struct mwifiex_ie_types_htcap));
-               ht_cap->header.type = cpu_to_le16(WLAN_EID_HT_CAPABILITY);
-               ht_cap->header.len =
-                               cpu_to_le16(sizeof(struct ieee80211_ht_cap));
-               memcpy((u8 *) ht_cap + sizeof(struct mwifiex_ie_types_header),
-                      (u8 *)bss_desc->bcn_ht_cap,
-                      le16_to_cpu(ht_cap->header.len));
-
-               mwifiex_fill_cap_info(priv, radio_type, &ht_cap->ht_cap);
-
-               *buffer += sizeof(struct mwifiex_ie_types_htcap);
-               ret_len += sizeof(struct mwifiex_ie_types_htcap);
-       }
-
-       if (bss_desc->bcn_ht_oper) {
-               if (priv->bss_mode == NL80211_IFTYPE_ADHOC) {
-                       ht_info = (struct mwifiex_ie_types_htinfo *) *buffer;
-                       memset(ht_info, 0,
-                              sizeof(struct mwifiex_ie_types_htinfo));
-                       ht_info->header.type =
-                                       cpu_to_le16(WLAN_EID_HT_OPERATION);
-                       ht_info->header.len =
-                               cpu_to_le16(
-                                       sizeof(struct ieee80211_ht_operation));
-
-                       memcpy((u8 *) ht_info +
-                              sizeof(struct mwifiex_ie_types_header),
-                              (u8 *)bss_desc->bcn_ht_oper,
-                              le16_to_cpu(ht_info->header.len));
-
-                       if (!(sband->ht_cap.cap &
-                                       IEEE80211_HT_CAP_SUP_WIDTH_20_40))
-                               ht_info->ht_oper.ht_param &=
-                                       ~(IEEE80211_HT_PARAM_CHAN_WIDTH_ANY |
-                                       IEEE80211_HT_PARAM_CHA_SEC_OFFSET);
-
-                       *buffer += sizeof(struct mwifiex_ie_types_htinfo);
-                       ret_len += sizeof(struct mwifiex_ie_types_htinfo);
-               }
-
-               chan_list =
-                       (struct mwifiex_ie_types_chan_list_param_set *) *buffer;
-               memset(chan_list, 0,
-                      sizeof(struct mwifiex_ie_types_chan_list_param_set));
-               chan_list->header.type = cpu_to_le16(TLV_TYPE_CHANLIST);
-               chan_list->header.len = cpu_to_le16(
-                       sizeof(struct mwifiex_ie_types_chan_list_param_set) -
-                       sizeof(struct mwifiex_ie_types_header));
-               chan_list->chan_scan_param[0].chan_number =
-                       bss_desc->bcn_ht_oper->primary_chan;
-               chan_list->chan_scan_param[0].radio_type =
-                       mwifiex_band_to_radio_type((u8) bss_desc->bss_band);
-
-               if (sband->ht_cap.cap & IEEE80211_HT_CAP_SUP_WIDTH_20_40 &&
-                   bss_desc->bcn_ht_oper->ht_param &
-                   IEEE80211_HT_PARAM_CHAN_WIDTH_ANY)
-                       SET_SECONDARYCHAN(chan_list->chan_scan_param[0].
-                                         radio_type,
-                                         (bss_desc->bcn_ht_oper->ht_param &
-                                         IEEE80211_HT_PARAM_CHA_SEC_OFFSET));
-
-               *buffer += sizeof(struct mwifiex_ie_types_chan_list_param_set);
-               ret_len += sizeof(struct mwifiex_ie_types_chan_list_param_set);
-       }
-
-       if (bss_desc->bcn_bss_co_2040) {
-               bss_co_2040 = (struct mwifiex_ie_types_2040bssco *) *buffer;
-               memset(bss_co_2040, 0,
-                      sizeof(struct mwifiex_ie_types_2040bssco));
-               bss_co_2040->header.type = cpu_to_le16(WLAN_EID_BSS_COEX_2040);
-               bss_co_2040->header.len =
-                      cpu_to_le16(sizeof(bss_co_2040->bss_co_2040));
-
-               memcpy((u8 *) bss_co_2040 +
-                      sizeof(struct mwifiex_ie_types_header),
-                      bss_desc->bcn_bss_co_2040 +
-                      sizeof(struct ieee_types_header),
-                      le16_to_cpu(bss_co_2040->header.len));
-
-               *buffer += sizeof(struct mwifiex_ie_types_2040bssco);
-               ret_len += sizeof(struct mwifiex_ie_types_2040bssco);
-       }
-
-       if (bss_desc->bcn_ext_cap) {
-               hdr = (void *)bss_desc->bcn_ext_cap;
-               ext_cap = (struct mwifiex_ie_types_extcap *) *buffer;
-               memset(ext_cap, 0, sizeof(struct mwifiex_ie_types_extcap));
-               ext_cap->header.type = cpu_to_le16(WLAN_EID_EXT_CAPABILITY);
-               ext_cap->header.len = cpu_to_le16(hdr->len);
-
-               memcpy((u8 *)ext_cap->ext_capab,
-                      bss_desc->bcn_ext_cap + sizeof(struct ieee_types_header),
-                      le16_to_cpu(ext_cap->header.len));
-
-               if (hdr->len > 3 &&
-                   ext_cap->ext_capab[3] & WLAN_EXT_CAPA4_INTERWORKING_ENABLED)
-                       priv->hs2_enabled = true;
-               else
-                       priv->hs2_enabled = false;
-
-               *buffer += sizeof(struct mwifiex_ie_types_extcap) + hdr->len;
-               ret_len += sizeof(struct mwifiex_ie_types_extcap) + hdr->len;
-       }
-
-       return ret_len;
-}
-
-/*
- * This function checks if the given pointer is valid entry of
- * Tx BA Stream table.
- */
-static int mwifiex_is_tx_ba_stream_ptr_valid(struct mwifiex_private *priv,
-                               struct mwifiex_tx_ba_stream_tbl *tx_tbl_ptr)
-{
-       struct mwifiex_tx_ba_stream_tbl *tx_ba_tsr_tbl;
-
-       list_for_each_entry(tx_ba_tsr_tbl, &priv->tx_ba_stream_tbl_ptr, list) {
-               if (tx_ba_tsr_tbl == tx_tbl_ptr)
-                       return true;
-       }
-
-       return false;
-}
-
-/*
- * This function deletes the given entry in Tx BA Stream table.
- *
- * The function also performs a validity check on the supplied
- * pointer before trying to delete.
- */
-void mwifiex_11n_delete_tx_ba_stream_tbl_entry(struct mwifiex_private *priv,
-                               struct mwifiex_tx_ba_stream_tbl *tx_ba_tsr_tbl)
-{
-       if (!tx_ba_tsr_tbl &&
-           mwifiex_is_tx_ba_stream_ptr_valid(priv, tx_ba_tsr_tbl))
-               return;
-
-       mwifiex_dbg(priv->adapter, INFO,
-                   "info: tx_ba_tsr_tbl %p\n", tx_ba_tsr_tbl);
-
-       list_del(&tx_ba_tsr_tbl->list);
-
-       kfree(tx_ba_tsr_tbl);
-}
-
-/*
- * This function deletes all the entries in Tx BA Stream table.
- */
-void mwifiex_11n_delete_all_tx_ba_stream_tbl(struct mwifiex_private *priv)
-{
-       int i;
-       struct mwifiex_tx_ba_stream_tbl *del_tbl_ptr, *tmp_node;
-       unsigned long flags;
-
-       spin_lock_irqsave(&priv->tx_ba_stream_tbl_lock, flags);
-       list_for_each_entry_safe(del_tbl_ptr, tmp_node,
-                                &priv->tx_ba_stream_tbl_ptr, list)
-               mwifiex_11n_delete_tx_ba_stream_tbl_entry(priv, del_tbl_ptr);
-       spin_unlock_irqrestore(&priv->tx_ba_stream_tbl_lock, flags);
-
-       INIT_LIST_HEAD(&priv->tx_ba_stream_tbl_ptr);
-
-       for (i = 0; i < MAX_NUM_TID; ++i)
-               priv->aggr_prio_tbl[i].ampdu_ap =
-                       priv->aggr_prio_tbl[i].ampdu_user;
-}
-
-/*
- * This function returns the pointer to an entry in BA Stream
- * table which matches the given RA/TID pair.
- */
-struct mwifiex_tx_ba_stream_tbl *
-mwifiex_get_ba_tbl(struct mwifiex_private *priv, int tid, u8 *ra)
-{
-       struct mwifiex_tx_ba_stream_tbl *tx_ba_tsr_tbl;
-       unsigned long flags;
-
-       spin_lock_irqsave(&priv->tx_ba_stream_tbl_lock, flags);
-       list_for_each_entry(tx_ba_tsr_tbl, &priv->tx_ba_stream_tbl_ptr, list) {
-               if (ether_addr_equal_unaligned(tx_ba_tsr_tbl->ra, ra) &&
-                   tx_ba_tsr_tbl->tid == tid) {
-                       spin_unlock_irqrestore(&priv->tx_ba_stream_tbl_lock,
-                                              flags);
-                       return tx_ba_tsr_tbl;
-               }
-       }
-       spin_unlock_irqrestore(&priv->tx_ba_stream_tbl_lock, flags);
-       return NULL;
-}
-
-/*
- * This function creates an entry in Tx BA stream table for the
- * given RA/TID pair.
- */
-void mwifiex_create_ba_tbl(struct mwifiex_private *priv, u8 *ra, int tid,
-                          enum mwifiex_ba_status ba_status)
-{
-       struct mwifiex_tx_ba_stream_tbl *new_node;
-       struct mwifiex_ra_list_tbl *ra_list;
-       unsigned long flags;
-       int tid_down;
-
-       if (!mwifiex_get_ba_tbl(priv, tid, ra)) {
-               new_node = kzalloc(sizeof(struct mwifiex_tx_ba_stream_tbl),
-                                  GFP_ATOMIC);
-               if (!new_node)
-                       return;
-
-               tid_down = mwifiex_wmm_downgrade_tid(priv, tid);
-               ra_list = mwifiex_wmm_get_ralist_node(priv, tid_down, ra);
-               if (ra_list) {
-                       ra_list->ba_status = ba_status;
-                       ra_list->amsdu_in_ampdu = false;
-               }
-               INIT_LIST_HEAD(&new_node->list);
-
-               new_node->tid = tid;
-               new_node->ba_status = ba_status;
-               memcpy(new_node->ra, ra, ETH_ALEN);
-
-               spin_lock_irqsave(&priv->tx_ba_stream_tbl_lock, flags);
-               list_add_tail(&new_node->list, &priv->tx_ba_stream_tbl_ptr);
-               spin_unlock_irqrestore(&priv->tx_ba_stream_tbl_lock, flags);
-       }
-}
-
-/*
- * This function sends an add BA request to the given TID/RA pair.
- */
-int mwifiex_send_addba(struct mwifiex_private *priv, int tid, u8 *peer_mac)
-{
-       struct host_cmd_ds_11n_addba_req add_ba_req;
-       u32 tx_win_size = priv->add_ba_param.tx_win_size;
-       static u8 dialog_tok;
-       int ret;
-       unsigned long flags;
-       u16 block_ack_param_set;
-
-       mwifiex_dbg(priv->adapter, CMD, "cmd: %s: tid %d\n", __func__, tid);
-
-       if ((GET_BSS_ROLE(priv) == MWIFIEX_BSS_ROLE_STA) &&
-           ISSUPP_TDLS_ENABLED(priv->adapter->fw_cap_info) &&
-           priv->adapter->is_hw_11ac_capable &&
-           memcmp(priv->cfg_bssid, peer_mac, ETH_ALEN)) {
-               struct mwifiex_sta_node *sta_ptr;
-
-               spin_lock_irqsave(&priv->sta_list_spinlock, flags);
-               sta_ptr = mwifiex_get_sta_entry(priv, peer_mac);
-               if (!sta_ptr) {
-                       spin_unlock_irqrestore(&priv->sta_list_spinlock, flags);
-                       mwifiex_dbg(priv->adapter, ERROR,
-                                   "BA setup with unknown TDLS peer %pM!\n",
-                                   peer_mac);
-                       return -1;
-               }
-               if (sta_ptr->is_11ac_enabled)
-                       tx_win_size = MWIFIEX_11AC_STA_AMPDU_DEF_TXWINSIZE;
-               spin_unlock_irqrestore(&priv->sta_list_spinlock, flags);
-       }
-
-       block_ack_param_set = (u16)((tid << BLOCKACKPARAM_TID_POS) |
-                                   tx_win_size << BLOCKACKPARAM_WINSIZE_POS |
-                                   IMMEDIATE_BLOCK_ACK);
-
-       /* enable AMSDU inside AMPDU */
-       if (priv->add_ba_param.tx_amsdu &&
-           (priv->aggr_prio_tbl[tid].amsdu != BA_STREAM_NOT_ALLOWED))
-               block_ack_param_set |= BLOCKACKPARAM_AMSDU_SUPP_MASK;
-
-       add_ba_req.block_ack_param_set = cpu_to_le16(block_ack_param_set);
-       add_ba_req.block_ack_tmo = cpu_to_le16((u16)priv->add_ba_param.timeout);
-
-       ++dialog_tok;
-
-       if (dialog_tok == 0)
-               dialog_tok = 1;
-
-       add_ba_req.dialog_token = dialog_tok;
-       memcpy(&add_ba_req.peer_mac_addr, peer_mac, ETH_ALEN);
-
-       /* We don't wait for the response of this command */
-       ret = mwifiex_send_cmd(priv, HostCmd_CMD_11N_ADDBA_REQ,
-                              0, 0, &add_ba_req, false);
-
-       return ret;
-}
-
-/*
- * This function sends a delete BA request to the given TID/RA pair.
- */
-int mwifiex_send_delba(struct mwifiex_private *priv, int tid, u8 *peer_mac,
-                      int initiator)
-{
-       struct host_cmd_ds_11n_delba delba;
-       int ret;
-       uint16_t del_ba_param_set;
-
-       memset(&delba, 0, sizeof(delba));
-       delba.del_ba_param_set = cpu_to_le16(tid << DELBA_TID_POS);
-
-       del_ba_param_set = le16_to_cpu(delba.del_ba_param_set);
-       if (initiator)
-               del_ba_param_set |= IEEE80211_DELBA_PARAM_INITIATOR_MASK;
-       else
-               del_ba_param_set &= ~IEEE80211_DELBA_PARAM_INITIATOR_MASK;
-
-       memcpy(&delba.peer_mac_addr, peer_mac, ETH_ALEN);
-
-       /* We don't wait for the response of this command */
-       ret = mwifiex_send_cmd(priv, HostCmd_CMD_11N_DELBA,
-                              HostCmd_ACT_GEN_SET, 0, &delba, false);
-
-       return ret;
-}
-
-/*
- * This function sends delba to specific tid
- */
-void mwifiex_11n_delba(struct mwifiex_private *priv, int tid)
-{
-       struct mwifiex_rx_reorder_tbl *rx_reor_tbl_ptr;
-
-       if (list_empty(&priv->rx_reorder_tbl_ptr)) {
-               dev_dbg(priv->adapter->dev,
-                       "mwifiex_11n_delba: rx_reorder_tbl_ptr empty\n");
-               return;
-       }
-
-       list_for_each_entry(rx_reor_tbl_ptr, &priv->rx_reorder_tbl_ptr, list) {
-               if (rx_reor_tbl_ptr->tid == tid) {
-                       dev_dbg(priv->adapter->dev,
-                               "Send delba to tid=%d, %pM\n",
-                               tid, rx_reor_tbl_ptr->ta);
-                       mwifiex_send_delba(priv, tid, rx_reor_tbl_ptr->ta, 0);
-                       return;
-               }
-       }
-}
-
-/*
- * This function handles the command response of a delete BA request.
- */
-void mwifiex_11n_delete_ba_stream(struct mwifiex_private *priv, u8 *del_ba)
-{
-       struct host_cmd_ds_11n_delba *cmd_del_ba =
-               (struct host_cmd_ds_11n_delba *) del_ba;
-       uint16_t del_ba_param_set = le16_to_cpu(cmd_del_ba->del_ba_param_set);
-       int tid;
-
-       tid = del_ba_param_set >> DELBA_TID_POS;
-
-       mwifiex_del_ba_tbl(priv, tid, cmd_del_ba->peer_mac_addr,
-                          TYPE_DELBA_RECEIVE, INITIATOR_BIT(del_ba_param_set));
-}
-
-/*
- * This function retrieves the Rx reordering table.
- */
-int mwifiex_get_rx_reorder_tbl(struct mwifiex_private *priv,
-                              struct mwifiex_ds_rx_reorder_tbl *buf)
-{
-       int i;
-       struct mwifiex_ds_rx_reorder_tbl *rx_reo_tbl = buf;
-       struct mwifiex_rx_reorder_tbl *rx_reorder_tbl_ptr;
-       int count = 0;
-       unsigned long flags;
-
-       spin_lock_irqsave(&priv->rx_reorder_tbl_lock, flags);
-       list_for_each_entry(rx_reorder_tbl_ptr, &priv->rx_reorder_tbl_ptr,
-                           list) {
-               rx_reo_tbl->tid = (u16) rx_reorder_tbl_ptr->tid;
-               memcpy(rx_reo_tbl->ta, rx_reorder_tbl_ptr->ta, ETH_ALEN);
-               rx_reo_tbl->start_win = rx_reorder_tbl_ptr->start_win;
-               rx_reo_tbl->win_size = rx_reorder_tbl_ptr->win_size;
-               for (i = 0; i < rx_reorder_tbl_ptr->win_size; ++i) {
-                       if (rx_reorder_tbl_ptr->rx_reorder_ptr[i])
-                               rx_reo_tbl->buffer[i] = true;
-                       else
-                               rx_reo_tbl->buffer[i] = false;
-               }
-               rx_reo_tbl++;
-               count++;
-
-               if (count >= MWIFIEX_MAX_RX_BASTREAM_SUPPORTED)
-                       break;
-       }
-       spin_unlock_irqrestore(&priv->rx_reorder_tbl_lock, flags);
-
-       return count;
-}
-
-/*
- * This function retrieves the Tx BA stream table.
- */
-int mwifiex_get_tx_ba_stream_tbl(struct mwifiex_private *priv,
-                                struct mwifiex_ds_tx_ba_stream_tbl *buf)
-{
-       struct mwifiex_tx_ba_stream_tbl *tx_ba_tsr_tbl;
-       struct mwifiex_ds_tx_ba_stream_tbl *rx_reo_tbl = buf;
-       int count = 0;
-       unsigned long flags;
-
-       spin_lock_irqsave(&priv->tx_ba_stream_tbl_lock, flags);
-       list_for_each_entry(tx_ba_tsr_tbl, &priv->tx_ba_stream_tbl_ptr, list) {
-               rx_reo_tbl->tid = (u16) tx_ba_tsr_tbl->tid;
-               mwifiex_dbg(priv->adapter, DATA, "data: %s tid=%d\n",
-                           __func__, rx_reo_tbl->tid);
-               memcpy(rx_reo_tbl->ra, tx_ba_tsr_tbl->ra, ETH_ALEN);
-               rx_reo_tbl->amsdu = tx_ba_tsr_tbl->amsdu;
-               rx_reo_tbl++;
-               count++;
-               if (count >= MWIFIEX_MAX_TX_BASTREAM_SUPPORTED)
-                       break;
-       }
-       spin_unlock_irqrestore(&priv->tx_ba_stream_tbl_lock, flags);
-
-       return count;
-}
-
-/*
- * This function retrieves the entry for specific tx BA stream table by RA and
- * deletes it.
- */
-void mwifiex_del_tx_ba_stream_tbl_by_ra(struct mwifiex_private *priv, u8 *ra)
-{
-       struct mwifiex_tx_ba_stream_tbl *tbl, *tmp;
-       unsigned long flags;
-
-       if (!ra)
-               return;
-
-       spin_lock_irqsave(&priv->tx_ba_stream_tbl_lock, flags);
-       list_for_each_entry_safe(tbl, tmp, &priv->tx_ba_stream_tbl_ptr, list) {
-               if (!memcmp(tbl->ra, ra, ETH_ALEN)) {
-                       spin_unlock_irqrestore(&priv->tx_ba_stream_tbl_lock,
-                                              flags);
-                       mwifiex_11n_delete_tx_ba_stream_tbl_entry(priv, tbl);
-                       spin_lock_irqsave(&priv->tx_ba_stream_tbl_lock, flags);
-               }
-       }
-       spin_unlock_irqrestore(&priv->tx_ba_stream_tbl_lock, flags);
-
-       return;
-}
-
-/* This function initializes the BlockACK setup information for given
- * mwifiex_private structure.
- */
-void mwifiex_set_ba_params(struct mwifiex_private *priv)
-{
-       priv->add_ba_param.timeout = MWIFIEX_DEFAULT_BLOCK_ACK_TIMEOUT;
-
-       if (GET_BSS_ROLE(priv) == MWIFIEX_BSS_ROLE_UAP) {
-               priv->add_ba_param.tx_win_size =
-                                               MWIFIEX_UAP_AMPDU_DEF_TXWINSIZE;
-               priv->add_ba_param.rx_win_size =
-                                               MWIFIEX_UAP_AMPDU_DEF_RXWINSIZE;
-       } else {
-               priv->add_ba_param.tx_win_size =
-                                               MWIFIEX_STA_AMPDU_DEF_TXWINSIZE;
-               priv->add_ba_param.rx_win_size =
-                                               MWIFIEX_STA_AMPDU_DEF_RXWINSIZE;
-       }
-
-       priv->add_ba_param.tx_amsdu = true;
-       priv->add_ba_param.rx_amsdu = true;
-
-       return;
-}
-
-u8 mwifiex_get_sec_chan_offset(int chan)
-{
-       u8 sec_offset;
-
-       switch (chan) {
-       case 36:
-       case 44:
-       case 52:
-       case 60:
-       case 100:
-       case 108:
-       case 116:
-       case 124:
-       case 132:
-       case 140:
-       case 149:
-       case 157:
-               sec_offset = IEEE80211_HT_PARAM_CHA_SEC_ABOVE;
-               break;
-       case 40:
-       case 48:
-       case 56:
-       case 64:
-       case 104:
-       case 112:
-       case 120:
-       case 128:
-       case 136:
-       case 144:
-       case 153:
-       case 161:
-               sec_offset = IEEE80211_HT_PARAM_CHA_SEC_BELOW;
-               break;
-       case 165:
-       default:
-               sec_offset = IEEE80211_HT_PARAM_CHA_SEC_NONE;
-               break;
-       }
-
-       return sec_offset;
-}
-
-/* This function will send DELBA to entries in the priv's
- * Tx BA stream table
- */
-static void
-mwifiex_send_delba_txbastream_tbl(struct mwifiex_private *priv, u8 tid)
-{
-       struct mwifiex_adapter *adapter = priv->adapter;
-       struct mwifiex_tx_ba_stream_tbl *tx_ba_stream_tbl_ptr;
-
-       if (list_empty(&priv->tx_ba_stream_tbl_ptr))
-               return;
-
-       list_for_each_entry(tx_ba_stream_tbl_ptr,
-                           &priv->tx_ba_stream_tbl_ptr, list) {
-               if (tx_ba_stream_tbl_ptr->ba_status == BA_SETUP_COMPLETE) {
-                       if (tid == tx_ba_stream_tbl_ptr->tid) {
-                               dev_dbg(adapter->dev,
-                                       "Tx:Send delba to tid=%d, %pM\n", tid,
-                                       tx_ba_stream_tbl_ptr->ra);
-                               mwifiex_send_delba(priv,
-                                                  tx_ba_stream_tbl_ptr->tid,
-                                                  tx_ba_stream_tbl_ptr->ra, 1);
-                               return;
-                       }
-               }
-       }
-}
-
-/* This function updates all the tx_win_size
- */
-void mwifiex_update_ampdu_txwinsize(struct mwifiex_adapter *adapter)
-{
-       u8 i;
-       u32 tx_win_size;
-       struct mwifiex_private *priv;
-
-       for (i = 0; i < adapter->priv_num; i++) {
-               if (!adapter->priv[i])
-                       continue;
-               priv = adapter->priv[i];
-               tx_win_size = priv->add_ba_param.tx_win_size;
-
-               if (priv->bss_type == MWIFIEX_BSS_TYPE_STA)
-                       priv->add_ba_param.tx_win_size =
-                               MWIFIEX_STA_AMPDU_DEF_TXWINSIZE;
-
-               if (priv->bss_type == MWIFIEX_BSS_TYPE_P2P)
-                       priv->add_ba_param.tx_win_size =
-                               MWIFIEX_STA_AMPDU_DEF_TXWINSIZE;
-
-               if (priv->bss_type == MWIFIEX_BSS_TYPE_UAP)
-                       priv->add_ba_param.tx_win_size =
-                               MWIFIEX_UAP_AMPDU_DEF_TXWINSIZE;
-
-               if (adapter->coex_win_size) {
-                       if (adapter->coex_tx_win_size)
-                               priv->add_ba_param.tx_win_size =
-                                       adapter->coex_tx_win_size;
-               }
-
-               if (tx_win_size != priv->add_ba_param.tx_win_size) {
-                       if (!priv->media_connected)
-                               continue;
-                       for (i = 0; i < MAX_NUM_TID; i++)
-                               mwifiex_send_delba_txbastream_tbl(priv, i);
-               }
-       }
-}
diff --git a/drivers/net/wireless/mwifiex/11n.h b/drivers/net/wireless/mwifiex/11n.h
deleted file mode 100644 (file)
index afdd58a..0000000
+++ /dev/null
@@ -1,191 +0,0 @@
-/*
- * Marvell Wireless LAN device driver: 802.11n
- *
- * Copyright (C) 2011-2014, Marvell International Ltd.
- *
- * This software file (the "File") is distributed by Marvell International
- * Ltd. under the terms of the GNU General Public License Version 2, June 1991
- * (the "License").  You may use, redistribute and/or modify this File in
- * accordance with the terms and conditions of the License, a copy of which
- * is available by writing to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the
- * worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
- *
- * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
- * ARE EXPRESSLY DISCLAIMED.  The License provides additional details about
- * this warranty disclaimer.
- */
-
-#ifndef _MWIFIEX_11N_H_
-#define _MWIFIEX_11N_H_
-
-#include "11n_aggr.h"
-#include "11n_rxreorder.h"
-#include "wmm.h"
-
-int mwifiex_ret_11n_delba(struct mwifiex_private *priv,
-                         struct host_cmd_ds_command *resp);
-int mwifiex_ret_11n_addba_req(struct mwifiex_private *priv,
-                             struct host_cmd_ds_command *resp);
-int mwifiex_cmd_11n_cfg(struct mwifiex_private *priv,
-                       struct host_cmd_ds_command *cmd, u16 cmd_action,
-                       struct mwifiex_ds_11n_tx_cfg *txcfg);
-int mwifiex_cmd_append_11n_tlv(struct mwifiex_private *priv,
-                              struct mwifiex_bssdescriptor *bss_desc,
-                              u8 **buffer);
-int mwifiex_fill_cap_info(struct mwifiex_private *, u8 radio_type,
-                         struct ieee80211_ht_cap *);
-int mwifiex_set_get_11n_htcap_cfg(struct mwifiex_private *priv,
-                                 u16 action, int *htcap_cfg);
-void mwifiex_11n_delete_tx_ba_stream_tbl_entry(struct mwifiex_private *priv,
-                                            struct mwifiex_tx_ba_stream_tbl
-                                            *tx_tbl);
-void mwifiex_11n_delete_all_tx_ba_stream_tbl(struct mwifiex_private *priv);
-struct mwifiex_tx_ba_stream_tbl *mwifiex_get_ba_tbl(struct
-                                                            mwifiex_private
-                                                            *priv, int tid,
-                                                            u8 *ra);
-void mwifiex_create_ba_tbl(struct mwifiex_private *priv, u8 *ra, int tid,
-                          enum mwifiex_ba_status ba_status);
-int mwifiex_send_addba(struct mwifiex_private *priv, int tid, u8 *peer_mac);
-int mwifiex_send_delba(struct mwifiex_private *priv, int tid, u8 *peer_mac,
-                      int initiator);
-void mwifiex_11n_delete_ba_stream(struct mwifiex_private *priv, u8 *del_ba);
-int mwifiex_get_rx_reorder_tbl(struct mwifiex_private *priv,
-                             struct mwifiex_ds_rx_reorder_tbl *buf);
-int mwifiex_get_tx_ba_stream_tbl(struct mwifiex_private *priv,
-                              struct mwifiex_ds_tx_ba_stream_tbl *buf);
-int mwifiex_cmd_recfg_tx_buf(struct mwifiex_private *priv,
-                            struct host_cmd_ds_command *cmd,
-                            int cmd_action, u16 *buf_size);
-int mwifiex_cmd_amsdu_aggr_ctrl(struct host_cmd_ds_command *cmd,
-                               int cmd_action,
-                               struct mwifiex_ds_11n_amsdu_aggr_ctrl *aa_ctrl);
-void mwifiex_del_tx_ba_stream_tbl_by_ra(struct mwifiex_private *priv, u8 *ra);
-u8 mwifiex_get_sec_chan_offset(int chan);
-
-static inline u8
-mwifiex_is_station_ampdu_allowed(struct mwifiex_private *priv,
-                                struct mwifiex_ra_list_tbl *ptr, int tid)
-{
-       struct mwifiex_sta_node *node = mwifiex_get_sta_entry(priv, ptr->ra);
-
-       if (unlikely(!node))
-               return false;
-
-       return (node->ampdu_sta[tid] != BA_STREAM_NOT_ALLOWED) ? true : false;
-}
-
-/* This function checks whether AMPDU is allowed or not for a particular TID. */
-static inline u8
-mwifiex_is_ampdu_allowed(struct mwifiex_private *priv,
-                        struct mwifiex_ra_list_tbl *ptr, int tid)
-{
-       if (is_broadcast_ether_addr(ptr->ra))
-               return false;
-       if (GET_BSS_ROLE(priv) == MWIFIEX_BSS_ROLE_UAP) {
-               return mwifiex_is_station_ampdu_allowed(priv, ptr, tid);
-       } else {
-               if (ptr->tdls_link)
-                       return mwifiex_is_station_ampdu_allowed(priv, ptr, tid);
-
-               return (priv->aggr_prio_tbl[tid].ampdu_ap !=
-                       BA_STREAM_NOT_ALLOWED) ? true : false;
-       }
-}
-
-/*
- * This function checks whether AMSDU is allowed or not for a particular TID.
- */
-static inline u8
-mwifiex_is_amsdu_allowed(struct mwifiex_private *priv, int tid)
-{
-       return (((priv->aggr_prio_tbl[tid].amsdu != BA_STREAM_NOT_ALLOWED) &&
-                (priv->is_data_rate_auto || !(priv->bitmap_rates[2] & 0x03)))
-               ? true : false);
-}
-
-/*
- * This function checks whether a space is available for new BA stream or not.
- */
-static inline u8 mwifiex_space_avail_for_new_ba_stream(
-                                       struct mwifiex_adapter *adapter)
-{
-       struct mwifiex_private *priv;
-       u8 i;
-       u32 ba_stream_num = 0, ba_stream_max;
-
-       ba_stream_max = MWIFIEX_MAX_TX_BASTREAM_SUPPORTED;
-
-       for (i = 0; i < adapter->priv_num; i++) {
-               priv = adapter->priv[i];
-               if (priv)
-                       ba_stream_num += mwifiex_wmm_list_len(
-                               &priv->tx_ba_stream_tbl_ptr);
-       }
-
-       if (adapter->fw_api_ver == MWIFIEX_FW_V15) {
-               ba_stream_max =
-                              GETSUPP_TXBASTREAMS(adapter->hw_dot_11n_dev_cap);
-               if (!ba_stream_max)
-                       ba_stream_max = MWIFIEX_MAX_TX_BASTREAM_SUPPORTED;
-       }
-
-       return ((ba_stream_num < ba_stream_max) ? true : false);
-}
-
-/*
- * This function finds the correct Tx BA stream to delete.
- *
- * Upon successfully locating, both the TID and the RA are returned.
- */
-static inline u8
-mwifiex_find_stream_to_delete(struct mwifiex_private *priv, int ptr_tid,
-                             int *ptid, u8 *ra)
-{
-       int tid;
-       u8 ret = false;
-       struct mwifiex_tx_ba_stream_tbl *tx_tbl;
-       unsigned long flags;
-
-       tid = priv->aggr_prio_tbl[ptr_tid].ampdu_user;
-
-       spin_lock_irqsave(&priv->tx_ba_stream_tbl_lock, flags);
-       list_for_each_entry(tx_tbl, &priv->tx_ba_stream_tbl_ptr, list) {
-               if (tid > priv->aggr_prio_tbl[tx_tbl->tid].ampdu_user) {
-                       tid = priv->aggr_prio_tbl[tx_tbl->tid].ampdu_user;
-                       *ptid = tx_tbl->tid;
-                       memcpy(ra, tx_tbl->ra, ETH_ALEN);
-                       ret = true;
-               }
-       }
-       spin_unlock_irqrestore(&priv->tx_ba_stream_tbl_lock, flags);
-
-       return ret;
-}
-
-/*
- * This function checks whether associated station is 11n enabled
- */
-static inline int mwifiex_is_sta_11n_enabled(struct mwifiex_private *priv,
-                                            struct mwifiex_sta_node *node)
-{
-
-       if (!node || (priv->bss_role != MWIFIEX_BSS_ROLE_UAP) ||
-           !priv->ap_11n_enabled)
-               return 0;
-
-       return node->is_11n_enabled;
-}
-
-static inline u8
-mwifiex_tdls_peer_11n_enabled(struct mwifiex_private *priv, const u8 *ra)
-{
-       struct mwifiex_sta_node *node = mwifiex_get_sta_entry(priv, ra);
-       if (node)
-               return node->is_11n_enabled;
-
-       return false;
-}
-#endif /* !_MWIFIEX_11N_H_ */
diff --git a/drivers/net/wireless/mwifiex/11n_aggr.c b/drivers/net/wireless/mwifiex/11n_aggr.c
deleted file mode 100644 (file)
index aa498e0..0000000
+++ /dev/null
@@ -1,318 +0,0 @@
-/*
- * Marvell Wireless LAN device driver: 802.11n Aggregation
- *
- * Copyright (C) 2011-2014, Marvell International Ltd.
- *
- * This software file (the "File") is distributed by Marvell International
- * Ltd. under the terms of the GNU General Public License Version 2, June 1991
- * (the "License").  You may use, redistribute and/or modify this File in
- * accordance with the terms and conditions of the License, a copy of which
- * is available by writing to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the
- * worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
- *
- * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
- * ARE EXPRESSLY DISCLAIMED.  The License provides additional details about
- * this warranty disclaimer.
- */
-
-#include "decl.h"
-#include "ioctl.h"
-#include "util.h"
-#include "fw.h"
-#include "main.h"
-#include "wmm.h"
-#include "11n.h"
-#include "11n_aggr.h"
-
-/*
- * Creates an AMSDU subframe for aggregation into one AMSDU packet.
- *
- * The resultant AMSDU subframe format is -
- *
- * +---- ~ -----+---- ~ ------+---- ~ -----+----- ~ -----+---- ~ -----+
- * |     DA     |     SA      |   Length   | SNAP header |   MSDU     |
- * | data[0..5] | data[6..11] |            |             | data[14..] |
- * +---- ~ -----+---- ~ ------+---- ~ -----+----- ~ -----+---- ~ -----+
- * <--6-bytes--> <--6-bytes--> <--2-bytes--><--8-bytes--> <--n-bytes-->
- *
- * This function also computes the amount of padding required to make the
- * buffer length multiple of 4 bytes.
- *
- * Data => |DA|SA|SNAP-TYPE|........    .|
- * MSDU => |DA|SA|Length|SNAP|......   ..|
- */
-static int
-mwifiex_11n_form_amsdu_pkt(struct sk_buff *skb_aggr,
-                          struct sk_buff *skb_src, int *pad)
-
-{
-       int dt_offset;
-       struct rfc_1042_hdr snap = {
-               0xaa,           /* LLC DSAP */
-               0xaa,           /* LLC SSAP */
-               0x03,           /* LLC CTRL */
-               {0x00, 0x00, 0x00},     /* SNAP OUI */
-               0x0000          /* SNAP type */
-                       /*
-                        * This field will be overwritten
-                        * later with ethertype
-                        */
-       };
-       struct tx_packet_hdr *tx_header;
-
-       tx_header = (void *)skb_put(skb_aggr, sizeof(*tx_header));
-
-       /* Copy DA and SA */
-       dt_offset = 2 * ETH_ALEN;
-       memcpy(&tx_header->eth803_hdr, skb_src->data, dt_offset);
-
-       /* Copy SNAP header */
-       snap.snap_type = ((struct ethhdr *)skb_src->data)->h_proto;
-
-       dt_offset += sizeof(__be16);
-
-       memcpy(&tx_header->rfc1042_hdr, &snap, sizeof(struct rfc_1042_hdr));
-
-       skb_pull(skb_src, dt_offset);
-
-       /* Update Length field */
-       tx_header->eth803_hdr.h_proto = htons(skb_src->len + LLC_SNAP_LEN);
-
-       /* Add payload */
-       memcpy(skb_put(skb_aggr, skb_src->len), skb_src->data, skb_src->len);
-
-       /* Add padding for new MSDU to start from 4 byte boundary */
-       *pad = (4 - ((unsigned long)skb_aggr->tail & 0x3)) % 4;
-
-       return skb_aggr->len + *pad;
-}
-
-/*
- * Adds TxPD to AMSDU header.
- *
- * Each AMSDU packet will contain one TxPD at the beginning,
- * followed by multiple AMSDU subframes.
- */
-static void
-mwifiex_11n_form_amsdu_txpd(struct mwifiex_private *priv,
-                           struct sk_buff *skb)
-{
-       struct txpd *local_tx_pd;
-       struct mwifiex_txinfo *tx_info = MWIFIEX_SKB_TXCB(skb);
-       unsigned int pad;
-       int headroom = (priv->adapter->iface_type ==
-                       MWIFIEX_USB) ? 0 : INTF_HEADER_LEN;
-
-       pad = ((void *)skb->data - sizeof(*local_tx_pd) -
-               headroom - NULL) & (MWIFIEX_DMA_ALIGN_SZ - 1);
-       skb_push(skb, pad);
-
-       skb_push(skb, sizeof(*local_tx_pd));
-
-       local_tx_pd = (struct txpd *) skb->data;
-       memset(local_tx_pd, 0, sizeof(struct txpd));
-
-       /* Original priority has been overwritten */
-       local_tx_pd->priority = (u8) skb->priority;
-       local_tx_pd->pkt_delay_2ms =
-               mwifiex_wmm_compute_drv_pkt_delay(priv, skb);
-       local_tx_pd->bss_num = priv->bss_num;
-       local_tx_pd->bss_type = priv->bss_type;
-       /* Always zero as the data is followed by struct txpd */
-       local_tx_pd->tx_pkt_offset = cpu_to_le16(sizeof(struct txpd) +
-                                                pad);
-       local_tx_pd->tx_pkt_type = cpu_to_le16(PKT_TYPE_AMSDU);
-       local_tx_pd->tx_pkt_length = cpu_to_le16(skb->len -
-                                                sizeof(*local_tx_pd) -
-                                                pad);
-
-       if (tx_info->flags & MWIFIEX_BUF_FLAG_TDLS_PKT)
-               local_tx_pd->flags |= MWIFIEX_TXPD_FLAGS_TDLS_PACKET;
-
-       if (local_tx_pd->tx_control == 0)
-               /* TxCtrl set by user or default */
-               local_tx_pd->tx_control = cpu_to_le32(priv->pkt_tx_ctrl);
-
-       if (GET_BSS_ROLE(priv) == MWIFIEX_BSS_ROLE_STA &&
-           priv->adapter->pps_uapsd_mode) {
-               if (true == mwifiex_check_last_packet_indication(priv)) {
-                       priv->adapter->tx_lock_flag = true;
-                       local_tx_pd->flags =
-                               MWIFIEX_TxPD_POWER_MGMT_LAST_PACKET;
-               }
-       }
-}
-
-/*
- * Create aggregated packet.
- *
- * This function creates an aggregated MSDU packet, by combining buffers
- * from the RA list. Each individual buffer is encapsulated as an AMSDU
- * subframe and all such subframes are concatenated together to form the
- * AMSDU packet.
- *
- * A TxPD is also added to the front of the resultant AMSDU packets for
- * transmission. The resultant packets format is -
- *
- * +---- ~ ----+------ ~ ------+------ ~ ------+-..-+------ ~ ------+
- * |    TxPD   |AMSDU sub-frame|AMSDU sub-frame| .. |AMSDU sub-frame|
- * |           |       1       |       2       | .. |       n       |
- * +---- ~ ----+------ ~ ------+------ ~ ------+ .. +------ ~ ------+
- */
-int
-mwifiex_11n_aggregate_pkt(struct mwifiex_private *priv,
-                         struct mwifiex_ra_list_tbl *pra_list,
-                         int ptrindex, unsigned long ra_list_flags)
-                         __releases(&priv->wmm.ra_list_spinlock)
-{
-       struct mwifiex_adapter *adapter = priv->adapter;
-       struct sk_buff *skb_aggr, *skb_src;
-       struct mwifiex_txinfo *tx_info_aggr, *tx_info_src;
-       int pad = 0, aggr_num = 0, ret;
-       struct mwifiex_tx_param tx_param;
-       struct txpd *ptx_pd = NULL;
-       int headroom = adapter->iface_type == MWIFIEX_USB ? 0 : INTF_HEADER_LEN;
-
-       skb_src = skb_peek(&pra_list->skb_head);
-       if (!skb_src) {
-               spin_unlock_irqrestore(&priv->wmm.ra_list_spinlock,
-                                      ra_list_flags);
-               return 0;
-       }
-
-       tx_info_src = MWIFIEX_SKB_TXCB(skb_src);
-       skb_aggr = mwifiex_alloc_dma_align_buf(adapter->tx_buf_size,
-                                              GFP_ATOMIC | GFP_DMA);
-       if (!skb_aggr) {
-               spin_unlock_irqrestore(&priv->wmm.ra_list_spinlock,
-                                      ra_list_flags);
-               return -1;
-       }
-       skb_reserve(skb_aggr, MWIFIEX_MIN_DATA_HEADER_LEN);
-       tx_info_aggr =  MWIFIEX_SKB_TXCB(skb_aggr);
-
-       memset(tx_info_aggr, 0, sizeof(*tx_info_aggr));
-       tx_info_aggr->bss_type = tx_info_src->bss_type;
-       tx_info_aggr->bss_num = tx_info_src->bss_num;
-
-       if (tx_info_src->flags & MWIFIEX_BUF_FLAG_TDLS_PKT)
-               tx_info_aggr->flags |= MWIFIEX_BUF_FLAG_TDLS_PKT;
-       tx_info_aggr->flags |= MWIFIEX_BUF_FLAG_AGGR_PKT;
-       skb_aggr->priority = skb_src->priority;
-       skb_aggr->tstamp = skb_src->tstamp;
-
-       skb_aggr->tstamp = ktime_get_real();
-
-       do {
-               /* Check if AMSDU can accommodate this MSDU */
-               if (skb_tailroom(skb_aggr) < (skb_src->len + LLC_SNAP_LEN))
-                       break;
-
-               skb_src = skb_dequeue(&pra_list->skb_head);
-               pra_list->total_pkt_count--;
-               atomic_dec(&priv->wmm.tx_pkts_queued);
-               aggr_num++;
-               spin_unlock_irqrestore(&priv->wmm.ra_list_spinlock,
-                                      ra_list_flags);
-               mwifiex_11n_form_amsdu_pkt(skb_aggr, skb_src, &pad);
-
-               mwifiex_write_data_complete(adapter, skb_src, 0, 0);
-
-               spin_lock_irqsave(&priv->wmm.ra_list_spinlock, ra_list_flags);
-
-               if (!mwifiex_is_ralist_valid(priv, pra_list, ptrindex)) {
-                       spin_unlock_irqrestore(&priv->wmm.ra_list_spinlock,
-                                              ra_list_flags);
-                       return -1;
-               }
-
-               if (skb_tailroom(skb_aggr) < pad) {
-                       pad = 0;
-                       break;
-               }
-               skb_put(skb_aggr, pad);
-
-               skb_src = skb_peek(&pra_list->skb_head);
-
-       } while (skb_src);
-
-       spin_unlock_irqrestore(&priv->wmm.ra_list_spinlock, ra_list_flags);
-
-       /* Last AMSDU packet does not need padding */
-       skb_trim(skb_aggr, skb_aggr->len - pad);
-
-       /* Form AMSDU */
-       mwifiex_11n_form_amsdu_txpd(priv, skb_aggr);
-       if (GET_BSS_ROLE(priv) == MWIFIEX_BSS_ROLE_STA)
-               ptx_pd = (struct txpd *)skb_aggr->data;
-
-       skb_push(skb_aggr, headroom);
-       tx_info_aggr->aggr_num = aggr_num * 2;
-       if (adapter->data_sent || adapter->tx_lock_flag) {
-               atomic_add(aggr_num * 2, &adapter->tx_queued);
-               skb_queue_tail(&adapter->tx_data_q, skb_aggr);
-               return 0;
-       }
-
-       if (adapter->iface_type == MWIFIEX_USB) {
-               ret = adapter->if_ops.host_to_card(adapter, priv->usb_port,
-                                                  skb_aggr, NULL);
-       } else {
-               if (skb_src)
-                       tx_param.next_pkt_len =
-                                       skb_src->len + sizeof(struct txpd);
-               else
-                       tx_param.next_pkt_len = 0;
-
-               ret = adapter->if_ops.host_to_card(adapter, MWIFIEX_TYPE_DATA,
-                                                  skb_aggr, &tx_param);
-       }
-       switch (ret) {
-       case -EBUSY:
-               spin_lock_irqsave(&priv->wmm.ra_list_spinlock, ra_list_flags);
-               if (!mwifiex_is_ralist_valid(priv, pra_list, ptrindex)) {
-                       spin_unlock_irqrestore(&priv->wmm.ra_list_spinlock,
-                                              ra_list_flags);
-                       mwifiex_write_data_complete(adapter, skb_aggr, 1, -1);
-                       return -1;
-               }
-               if (GET_BSS_ROLE(priv) == MWIFIEX_BSS_ROLE_STA &&
-                   adapter->pps_uapsd_mode && adapter->tx_lock_flag) {
-                               priv->adapter->tx_lock_flag = false;
-                               if (ptx_pd)
-                                       ptx_pd->flags = 0;
-               }
-
-               skb_queue_tail(&pra_list->skb_head, skb_aggr);
-
-               pra_list->total_pkt_count++;
-
-               atomic_inc(&priv->wmm.tx_pkts_queued);
-
-               tx_info_aggr->flags |= MWIFIEX_BUF_FLAG_REQUEUED_PKT;
-               spin_unlock_irqrestore(&priv->wmm.ra_list_spinlock,
-                                      ra_list_flags);
-               mwifiex_dbg(adapter, ERROR, "data: -EBUSY is returned\n");
-               break;
-       case -1:
-               mwifiex_dbg(adapter, ERROR, "%s: host_to_card failed: %#x\n",
-                           __func__, ret);
-               adapter->dbg.num_tx_host_to_card_failure++;
-               mwifiex_write_data_complete(adapter, skb_aggr, 1, ret);
-               return 0;
-       case -EINPROGRESS:
-               break;
-       case 0:
-               mwifiex_write_data_complete(adapter, skb_aggr, 1, ret);
-               break;
-       default:
-               break;
-       }
-       if (ret != -EBUSY) {
-               mwifiex_rotate_priolists(priv, pra_list, ptrindex);
-       }
-
-       return 0;
-}
diff --git a/drivers/net/wireless/mwifiex/11n_aggr.h b/drivers/net/wireless/mwifiex/11n_aggr.h
deleted file mode 100644 (file)
index 0cd2a3e..0000000
+++ /dev/null
@@ -1,33 +0,0 @@
-/*
- * Marvell Wireless LAN device driver: 802.11n Aggregation
- *
- * Copyright (C) 2011-2014, Marvell International Ltd.
- *
- * This software file (the "File") is distributed by Marvell International
- * Ltd. under the terms of the GNU General Public License Version 2, June 1991
- * (the "License").  You may use, redistribute and/or modify this File in
- * accordance with the terms and conditions of the License, a copy of which
- * is available by writing to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the
- * worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
- *
- * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
- * ARE EXPRESSLY DISCLAIMED.  The License provides additional details about
- * this warranty disclaimer.
- */
-
-#ifndef _MWIFIEX_11N_AGGR_H_
-#define _MWIFIEX_11N_AGGR_H_
-
-#define PKT_TYPE_AMSDU 0xE6
-#define MIN_NUM_AMSDU 2
-
-int mwifiex_11n_deaggregate_pkt(struct mwifiex_private *priv,
-                               struct sk_buff *skb);
-int mwifiex_11n_aggregate_pkt(struct mwifiex_private *priv,
-                             struct mwifiex_ra_list_tbl *ptr,
-                             int ptr_index, unsigned long flags)
-                             __releases(&priv->wmm.ra_list_spinlock);
-
-#endif /* !_MWIFIEX_11N_AGGR_H_ */
diff --git a/drivers/net/wireless/mwifiex/11n_rxreorder.c b/drivers/net/wireless/mwifiex/11n_rxreorder.c
deleted file mode 100644 (file)
index b3970a8..0000000
+++ /dev/null
@@ -1,910 +0,0 @@
-/*
- * Marvell Wireless LAN device driver: 802.11n RX Re-ordering
- *
- * Copyright (C) 2011-2014, Marvell International Ltd.
- *
- * This software file (the "File") is distributed by Marvell International
- * Ltd. under the terms of the GNU General Public License Version 2, June 1991
- * (the "License").  You may use, redistribute and/or modify this File in
- * accordance with the terms and conditions of the License, a copy of which
- * is available by writing to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the
- * worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
- *
- * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
- * ARE EXPRESSLY DISCLAIMED.  The License provides additional details about
- * this warranty disclaimer.
- */
-
-#include "decl.h"
-#include "ioctl.h"
-#include "util.h"
-#include "fw.h"
-#include "main.h"
-#include "wmm.h"
-#include "11n.h"
-#include "11n_rxreorder.h"
-
-/* This function will dispatch amsdu packet and forward it to kernel/upper
- * layer.
- */
-static int mwifiex_11n_dispatch_amsdu_pkt(struct mwifiex_private *priv,
-                                         struct sk_buff *skb)
-{
-       struct rxpd *local_rx_pd = (struct rxpd *)(skb->data);
-       int ret;
-
-       if (le16_to_cpu(local_rx_pd->rx_pkt_type) == PKT_TYPE_AMSDU) {
-               struct sk_buff_head list;
-               struct sk_buff *rx_skb;
-
-               __skb_queue_head_init(&list);
-
-               skb_pull(skb, le16_to_cpu(local_rx_pd->rx_pkt_offset));
-               skb_trim(skb, le16_to_cpu(local_rx_pd->rx_pkt_length));
-
-               ieee80211_amsdu_to_8023s(skb, &list, priv->curr_addr,
-                                        priv->wdev.iftype, 0, false);
-
-               while (!skb_queue_empty(&list)) {
-                       rx_skb = __skb_dequeue(&list);
-                       ret = mwifiex_recv_packet(priv, rx_skb);
-                       if (ret == -1)
-                               mwifiex_dbg(priv->adapter, ERROR,
-                                           "Rx of A-MSDU failed");
-               }
-               return 0;
-       }
-
-       return -1;
-}
-
-/* This function will process the rx packet and forward it to kernel/upper
- * layer.
- */
-static int mwifiex_11n_dispatch_pkt(struct mwifiex_private *priv, void *payload)
-{
-       int ret = mwifiex_11n_dispatch_amsdu_pkt(priv, payload);
-
-       if (!ret)
-               return 0;
-
-       if (priv->bss_role == MWIFIEX_BSS_ROLE_UAP)
-               return mwifiex_handle_uap_rx_forward(priv, payload);
-
-       return mwifiex_process_rx_packet(priv, payload);
-}
-
-/*
- * This function dispatches all packets in the Rx reorder table until the
- * start window.
- *
- * There could be holes in the buffer, which are skipped by the function.
- * Since the buffer is linear, the function uses rotation to simulate
- * circular buffer.
- */
-static void
-mwifiex_11n_dispatch_pkt_until_start_win(struct mwifiex_private *priv,
-                                        struct mwifiex_rx_reorder_tbl *tbl,
-                                        int start_win)
-{
-       int pkt_to_send, i;
-       void *rx_tmp_ptr;
-       unsigned long flags;
-
-       pkt_to_send = (start_win > tbl->start_win) ?
-                     min((start_win - tbl->start_win), tbl->win_size) :
-                     tbl->win_size;
-
-       for (i = 0; i < pkt_to_send; ++i) {
-               spin_lock_irqsave(&priv->rx_pkt_lock, flags);
-               rx_tmp_ptr = NULL;
-               if (tbl->rx_reorder_ptr[i]) {
-                       rx_tmp_ptr = tbl->rx_reorder_ptr[i];
-                       tbl->rx_reorder_ptr[i] = NULL;
-               }
-               spin_unlock_irqrestore(&priv->rx_pkt_lock, flags);
-               if (rx_tmp_ptr)
-                       mwifiex_11n_dispatch_pkt(priv, rx_tmp_ptr);
-       }
-
-       spin_lock_irqsave(&priv->rx_pkt_lock, flags);
-       /*
-        * We don't have a circular buffer, hence use rotation to simulate
-        * circular buffer
-        */
-       for (i = 0; i < tbl->win_size - pkt_to_send; ++i) {
-               tbl->rx_reorder_ptr[i] = tbl->rx_reorder_ptr[pkt_to_send + i];
-               tbl->rx_reorder_ptr[pkt_to_send + i] = NULL;
-       }
-
-       tbl->start_win = start_win;
-       spin_unlock_irqrestore(&priv->rx_pkt_lock, flags);
-}
-
-/*
- * This function dispatches all packets in the Rx reorder table until
- * a hole is found.
- *
- * The start window is adjusted automatically when a hole is located.
- * Since the buffer is linear, the function uses rotation to simulate
- * circular buffer.
- */
-static void
-mwifiex_11n_scan_and_dispatch(struct mwifiex_private *priv,
-                             struct mwifiex_rx_reorder_tbl *tbl)
-{
-       int i, j, xchg;
-       void *rx_tmp_ptr;
-       unsigned long flags;
-
-       for (i = 0; i < tbl->win_size; ++i) {
-               spin_lock_irqsave(&priv->rx_pkt_lock, flags);
-               if (!tbl->rx_reorder_ptr[i]) {
-                       spin_unlock_irqrestore(&priv->rx_pkt_lock, flags);
-                       break;
-               }
-               rx_tmp_ptr = tbl->rx_reorder_ptr[i];
-               tbl->rx_reorder_ptr[i] = NULL;
-               spin_unlock_irqrestore(&priv->rx_pkt_lock, flags);
-               mwifiex_11n_dispatch_pkt(priv, rx_tmp_ptr);
-       }
-
-       spin_lock_irqsave(&priv->rx_pkt_lock, flags);
-       /*
-        * We don't have a circular buffer, hence use rotation to simulate
-        * circular buffer
-        */
-       if (i > 0) {
-               xchg = tbl->win_size - i;
-               for (j = 0; j < xchg; ++j) {
-                       tbl->rx_reorder_ptr[j] = tbl->rx_reorder_ptr[i + j];
-                       tbl->rx_reorder_ptr[i + j] = NULL;
-               }
-       }
-       tbl->start_win = (tbl->start_win + i) & (MAX_TID_VALUE - 1);
-       spin_unlock_irqrestore(&priv->rx_pkt_lock, flags);
-}
-
-/*
- * This function deletes the Rx reorder table and frees the memory.
- *
- * The function stops the associated timer and dispatches all the
- * pending packets in the Rx reorder table before deletion.
- */
-static void
-mwifiex_del_rx_reorder_entry(struct mwifiex_private *priv,
-                            struct mwifiex_rx_reorder_tbl *tbl)
-{
-       unsigned long flags;
-       int start_win;
-
-       if (!tbl)
-               return;
-
-       spin_lock_irqsave(&priv->adapter->rx_proc_lock, flags);
-       priv->adapter->rx_locked = true;
-       if (priv->adapter->rx_processing) {
-               spin_unlock_irqrestore(&priv->adapter->rx_proc_lock, flags);
-               flush_workqueue(priv->adapter->rx_workqueue);
-       } else {
-               spin_unlock_irqrestore(&priv->adapter->rx_proc_lock, flags);
-       }
-
-       start_win = (tbl->start_win + tbl->win_size) & (MAX_TID_VALUE - 1);
-       mwifiex_11n_dispatch_pkt_until_start_win(priv, tbl, start_win);
-
-       del_timer_sync(&tbl->timer_context.timer);
-       tbl->timer_context.timer_is_set = false;
-
-       spin_lock_irqsave(&priv->rx_reorder_tbl_lock, flags);
-       list_del(&tbl->list);
-       spin_unlock_irqrestore(&priv->rx_reorder_tbl_lock, flags);
-
-       kfree(tbl->rx_reorder_ptr);
-       kfree(tbl);
-
-       spin_lock_irqsave(&priv->adapter->rx_proc_lock, flags);
-       priv->adapter->rx_locked = false;
-       spin_unlock_irqrestore(&priv->adapter->rx_proc_lock, flags);
-
-}
-
-/*
- * This function returns the pointer to an entry in Rx reordering
- * table which matches the given TA/TID pair.
- */
-struct mwifiex_rx_reorder_tbl *
-mwifiex_11n_get_rx_reorder_tbl(struct mwifiex_private *priv, int tid, u8 *ta)
-{
-       struct mwifiex_rx_reorder_tbl *tbl;
-       unsigned long flags;
-
-       spin_lock_irqsave(&priv->rx_reorder_tbl_lock, flags);
-       list_for_each_entry(tbl, &priv->rx_reorder_tbl_ptr, list) {
-               if (!memcmp(tbl->ta, ta, ETH_ALEN) && tbl->tid == tid) {
-                       spin_unlock_irqrestore(&priv->rx_reorder_tbl_lock,
-                                              flags);
-                       return tbl;
-               }
-       }
-       spin_unlock_irqrestore(&priv->rx_reorder_tbl_lock, flags);
-
-       return NULL;
-}
-
-/* This function retrieves the pointer to an entry in Rx reordering
- * table which matches the given TA and deletes it.
- */
-void mwifiex_11n_del_rx_reorder_tbl_by_ta(struct mwifiex_private *priv, u8 *ta)
-{
-       struct mwifiex_rx_reorder_tbl *tbl, *tmp;
-       unsigned long flags;
-
-       if (!ta)
-               return;
-
-       spin_lock_irqsave(&priv->rx_reorder_tbl_lock, flags);
-       list_for_each_entry_safe(tbl, tmp, &priv->rx_reorder_tbl_ptr, list) {
-               if (!memcmp(tbl->ta, ta, ETH_ALEN)) {
-                       spin_unlock_irqrestore(&priv->rx_reorder_tbl_lock,
-                                              flags);
-                       mwifiex_del_rx_reorder_entry(priv, tbl);
-                       spin_lock_irqsave(&priv->rx_reorder_tbl_lock, flags);
-               }
-       }
-       spin_unlock_irqrestore(&priv->rx_reorder_tbl_lock, flags);
-
-       return;
-}
-
-/*
- * This function finds the last sequence number used in the packets
- * buffered in Rx reordering table.
- */
-static int
-mwifiex_11n_find_last_seq_num(struct reorder_tmr_cnxt *ctx)
-{
-       struct mwifiex_rx_reorder_tbl *rx_reorder_tbl_ptr = ctx->ptr;
-       struct mwifiex_private *priv = ctx->priv;
-       unsigned long flags;
-       int i;
-
-       spin_lock_irqsave(&priv->rx_reorder_tbl_lock, flags);
-       for (i = rx_reorder_tbl_ptr->win_size - 1; i >= 0; --i) {
-               if (rx_reorder_tbl_ptr->rx_reorder_ptr[i]) {
-                       spin_unlock_irqrestore(&priv->rx_reorder_tbl_lock,
-                                              flags);
-                       return i;
-               }
-       }
-       spin_unlock_irqrestore(&priv->rx_reorder_tbl_lock, flags);
-
-       return -1;
-}
-
-/*
- * This function flushes all the packets in Rx reordering table.
- *
- * The function checks if any packets are currently buffered in the
- * table or not. In case there are packets available, it dispatches
- * them and then dumps the Rx reordering table.
- */
-static void
-mwifiex_flush_data(unsigned long context)
-{
-       struct reorder_tmr_cnxt *ctx =
-               (struct reorder_tmr_cnxt *) context;
-       int start_win, seq_num;
-
-       ctx->timer_is_set = false;
-       seq_num = mwifiex_11n_find_last_seq_num(ctx);
-
-       if (seq_num < 0)
-               return;
-
-       mwifiex_dbg(ctx->priv->adapter, INFO, "info: flush data %d\n", seq_num);
-       start_win = (ctx->ptr->start_win + seq_num + 1) & (MAX_TID_VALUE - 1);
-       mwifiex_11n_dispatch_pkt_until_start_win(ctx->priv, ctx->ptr,
-                                                start_win);
-}
-
-/*
- * This function creates an entry in Rx reordering table for the
- * given TA/TID.
- *
- * The function also initializes the entry with sequence number, window
- * size as well as initializes the timer.
- *
- * If the received TA/TID pair is already present, all the packets are
- * dispatched and the window size is moved until the SSN.
- */
-static void
-mwifiex_11n_create_rx_reorder_tbl(struct mwifiex_private *priv, u8 *ta,
-                                 int tid, int win_size, int seq_num)
-{
-       int i;
-       struct mwifiex_rx_reorder_tbl *tbl, *new_node;
-       u16 last_seq = 0;
-       unsigned long flags;
-       struct mwifiex_sta_node *node;
-
-       /*
-        * If we get a TID, ta pair which is already present dispatch all the
-        * the packets and move the window size until the ssn
-        */
-       tbl = mwifiex_11n_get_rx_reorder_tbl(priv, tid, ta);
-       if (tbl) {
-               mwifiex_11n_dispatch_pkt_until_start_win(priv, tbl, seq_num);
-               return;
-       }
-       /* if !tbl then create one */
-       new_node = kzalloc(sizeof(struct mwifiex_rx_reorder_tbl), GFP_KERNEL);
-       if (!new_node)
-               return;
-
-       INIT_LIST_HEAD(&new_node->list);
-       new_node->tid = tid;
-       memcpy(new_node->ta, ta, ETH_ALEN);
-       new_node->start_win = seq_num;
-       new_node->init_win = seq_num;
-       new_node->flags = 0;
-
-       spin_lock_irqsave(&priv->sta_list_spinlock, flags);
-       if (mwifiex_queuing_ra_based(priv)) {
-               if (priv->bss_role == MWIFIEX_BSS_ROLE_UAP) {
-                       node = mwifiex_get_sta_entry(priv, ta);
-                       if (node)
-                               last_seq = node->rx_seq[tid];
-               }
-       } else {
-               node = mwifiex_get_sta_entry(priv, ta);
-               if (node)
-                       last_seq = node->rx_seq[tid];
-               else
-                       last_seq = priv->rx_seq[tid];
-       }
-       spin_unlock_irqrestore(&priv->sta_list_spinlock, flags);
-
-       mwifiex_dbg(priv->adapter, INFO,
-                   "info: last_seq=%d start_win=%d\n",
-                   last_seq, new_node->start_win);
-
-       if (last_seq != MWIFIEX_DEF_11N_RX_SEQ_NUM &&
-           last_seq >= new_node->start_win) {
-               new_node->start_win = last_seq + 1;
-               new_node->flags |= RXREOR_INIT_WINDOW_SHIFT;
-       }
-
-       new_node->win_size = win_size;
-
-       new_node->rx_reorder_ptr = kzalloc(sizeof(void *) * win_size,
-                                       GFP_KERNEL);
-       if (!new_node->rx_reorder_ptr) {
-               kfree((u8 *) new_node);
-               mwifiex_dbg(priv->adapter, ERROR,
-                           "%s: failed to alloc reorder_ptr\n", __func__);
-               return;
-       }
-
-       new_node->timer_context.ptr = new_node;
-       new_node->timer_context.priv = priv;
-       new_node->timer_context.timer_is_set = false;
-
-       setup_timer(&new_node->timer_context.timer, mwifiex_flush_data,
-                   (unsigned long)&new_node->timer_context);
-
-       for (i = 0; i < win_size; ++i)
-               new_node->rx_reorder_ptr[i] = NULL;
-
-       spin_lock_irqsave(&priv->rx_reorder_tbl_lock, flags);
-       list_add_tail(&new_node->list, &priv->rx_reorder_tbl_ptr);
-       spin_unlock_irqrestore(&priv->rx_reorder_tbl_lock, flags);
-}
-
-static void
-mwifiex_11n_rxreorder_timer_restart(struct mwifiex_rx_reorder_tbl *tbl)
-{
-       u32 min_flush_time;
-
-       if (tbl->win_size >= MWIFIEX_BA_WIN_SIZE_32)
-               min_flush_time = MIN_FLUSH_TIMER_15_MS;
-       else
-               min_flush_time = MIN_FLUSH_TIMER_MS;
-
-       mod_timer(&tbl->timer_context.timer,
-                 jiffies + msecs_to_jiffies(min_flush_time * tbl->win_size));
-
-       tbl->timer_context.timer_is_set = true;
-}
-
-/*
- * This function prepares command for adding a BA request.
- *
- * Preparation includes -
- *      - Setting command ID and proper size
- *      - Setting add BA request buffer
- *      - Ensuring correct endian-ness
- */
-int mwifiex_cmd_11n_addba_req(struct host_cmd_ds_command *cmd, void *data_buf)
-{
-       struct host_cmd_ds_11n_addba_req *add_ba_req = &cmd->params.add_ba_req;
-
-       cmd->command = cpu_to_le16(HostCmd_CMD_11N_ADDBA_REQ);
-       cmd->size = cpu_to_le16(sizeof(*add_ba_req) + S_DS_GEN);
-       memcpy(add_ba_req, data_buf, sizeof(*add_ba_req));
-
-       return 0;
-}
-
-/*
- * This function prepares command for adding a BA response.
- *
- * Preparation includes -
- *      - Setting command ID and proper size
- *      - Setting add BA response buffer
- *      - Ensuring correct endian-ness
- */
-int mwifiex_cmd_11n_addba_rsp_gen(struct mwifiex_private *priv,
-                                 struct host_cmd_ds_command *cmd,
-                                 struct host_cmd_ds_11n_addba_req
-                                 *cmd_addba_req)
-{
-       struct host_cmd_ds_11n_addba_rsp *add_ba_rsp = &cmd->params.add_ba_rsp;
-       struct mwifiex_sta_node *sta_ptr;
-       u32 rx_win_size = priv->add_ba_param.rx_win_size;
-       u8 tid;
-       int win_size;
-       unsigned long flags;
-       uint16_t block_ack_param_set;
-
-       if ((GET_BSS_ROLE(priv) == MWIFIEX_BSS_ROLE_STA) &&
-           ISSUPP_TDLS_ENABLED(priv->adapter->fw_cap_info) &&
-           priv->adapter->is_hw_11ac_capable &&
-           memcmp(priv->cfg_bssid, cmd_addba_req->peer_mac_addr, ETH_ALEN)) {
-               spin_lock_irqsave(&priv->sta_list_spinlock, flags);
-               sta_ptr = mwifiex_get_sta_entry(priv,
-                                               cmd_addba_req->peer_mac_addr);
-               if (!sta_ptr) {
-                       spin_unlock_irqrestore(&priv->sta_list_spinlock, flags);
-                       mwifiex_dbg(priv->adapter, ERROR,
-                                   "BA setup with unknown TDLS peer %pM!\n",
-                                   cmd_addba_req->peer_mac_addr);
-                       return -1;
-               }
-               if (sta_ptr->is_11ac_enabled)
-                       rx_win_size = MWIFIEX_11AC_STA_AMPDU_DEF_RXWINSIZE;
-               spin_unlock_irqrestore(&priv->sta_list_spinlock, flags);
-       }
-
-       cmd->command = cpu_to_le16(HostCmd_CMD_11N_ADDBA_RSP);
-       cmd->size = cpu_to_le16(sizeof(*add_ba_rsp) + S_DS_GEN);
-
-       memcpy(add_ba_rsp->peer_mac_addr, cmd_addba_req->peer_mac_addr,
-              ETH_ALEN);
-       add_ba_rsp->dialog_token = cmd_addba_req->dialog_token;
-       add_ba_rsp->block_ack_tmo = cmd_addba_req->block_ack_tmo;
-       add_ba_rsp->ssn = cmd_addba_req->ssn;
-
-       block_ack_param_set = le16_to_cpu(cmd_addba_req->block_ack_param_set);
-       tid = (block_ack_param_set & IEEE80211_ADDBA_PARAM_TID_MASK)
-               >> BLOCKACKPARAM_TID_POS;
-       add_ba_rsp->status_code = cpu_to_le16(ADDBA_RSP_STATUS_ACCEPT);
-       block_ack_param_set &= ~IEEE80211_ADDBA_PARAM_BUF_SIZE_MASK;
-
-       /* If we don't support AMSDU inside AMPDU, reset the bit */
-       if (!priv->add_ba_param.rx_amsdu ||
-           (priv->aggr_prio_tbl[tid].amsdu == BA_STREAM_NOT_ALLOWED))
-               block_ack_param_set &= ~BLOCKACKPARAM_AMSDU_SUPP_MASK;
-       block_ack_param_set |= rx_win_size << BLOCKACKPARAM_WINSIZE_POS;
-       add_ba_rsp->block_ack_param_set = cpu_to_le16(block_ack_param_set);
-       win_size = (le16_to_cpu(add_ba_rsp->block_ack_param_set)
-                                       & IEEE80211_ADDBA_PARAM_BUF_SIZE_MASK)
-                                       >> BLOCKACKPARAM_WINSIZE_POS;
-       cmd_addba_req->block_ack_param_set = cpu_to_le16(block_ack_param_set);
-
-       mwifiex_11n_create_rx_reorder_tbl(priv, cmd_addba_req->peer_mac_addr,
-                                         tid, win_size,
-                                         le16_to_cpu(cmd_addba_req->ssn));
-       return 0;
-}
-
-/*
- * This function prepares command for deleting a BA request.
- *
- * Preparation includes -
- *      - Setting command ID and proper size
- *      - Setting del BA request buffer
- *      - Ensuring correct endian-ness
- */
-int mwifiex_cmd_11n_delba(struct host_cmd_ds_command *cmd, void *data_buf)
-{
-       struct host_cmd_ds_11n_delba *del_ba = &cmd->params.del_ba;
-
-       cmd->command = cpu_to_le16(HostCmd_CMD_11N_DELBA);
-       cmd->size = cpu_to_le16(sizeof(*del_ba) + S_DS_GEN);
-       memcpy(del_ba, data_buf, sizeof(*del_ba));
-
-       return 0;
-}
-
-/*
- * This function identifies if Rx reordering is needed for a received packet.
- *
- * In case reordering is required, the function will do the reordering
- * before sending it to kernel.
- *
- * The Rx reorder table is checked first with the received TID/TA pair. If
- * not found, the received packet is dispatched immediately. But if found,
- * the packet is reordered and all the packets in the updated Rx reordering
- * table is dispatched until a hole is found.
- *
- * For sequence number less than the starting window, the packet is dropped.
- */
-int mwifiex_11n_rx_reorder_pkt(struct mwifiex_private *priv,
-                               u16 seq_num, u16 tid,
-                               u8 *ta, u8 pkt_type, void *payload)
-{
-       struct mwifiex_rx_reorder_tbl *tbl;
-       int prev_start_win, start_win, end_win, win_size;
-       u16 pkt_index;
-       bool init_window_shift = false;
-       int ret = 0;
-
-       tbl = mwifiex_11n_get_rx_reorder_tbl(priv, tid, ta);
-       if (!tbl) {
-               if (pkt_type != PKT_TYPE_BAR)
-                       mwifiex_11n_dispatch_pkt(priv, payload);
-               return ret;
-       }
-
-       if ((pkt_type == PKT_TYPE_AMSDU) && !tbl->amsdu) {
-               mwifiex_11n_dispatch_pkt(priv, payload);
-               return ret;
-       }
-
-       start_win = tbl->start_win;
-       prev_start_win = start_win;
-       win_size = tbl->win_size;
-       end_win = ((start_win + win_size) - 1) & (MAX_TID_VALUE - 1);
-       if (tbl->flags & RXREOR_INIT_WINDOW_SHIFT) {
-               init_window_shift = true;
-               tbl->flags &= ~RXREOR_INIT_WINDOW_SHIFT;
-       }
-
-       if (tbl->flags & RXREOR_FORCE_NO_DROP) {
-               mwifiex_dbg(priv->adapter, INFO,
-                           "RXREOR_FORCE_NO_DROP when HS is activated\n");
-               tbl->flags &= ~RXREOR_FORCE_NO_DROP;
-       } else if (init_window_shift && seq_num < start_win &&
-                  seq_num >= tbl->init_win) {
-               mwifiex_dbg(priv->adapter, INFO,
-                           "Sender TID sequence number reset %d->%d for SSN %d\n",
-                           start_win, seq_num, tbl->init_win);
-               tbl->start_win = start_win = seq_num;
-               end_win = ((start_win + win_size) - 1) & (MAX_TID_VALUE - 1);
-       } else {
-               /*
-                * If seq_num is less then starting win then ignore and drop
-                * the packet
-                */
-               if ((start_win + TWOPOW11) > (MAX_TID_VALUE - 1)) {
-                       if (seq_num >= ((start_win + TWOPOW11) &
-                                       (MAX_TID_VALUE - 1)) &&
-                           seq_num < start_win) {
-                               ret = -1;
-                               goto done;
-                       }
-               } else if ((seq_num < start_win) ||
-                          (seq_num >= (start_win + TWOPOW11))) {
-                       ret = -1;
-                       goto done;
-               }
-       }
-
-       /*
-        * If this packet is a BAR we adjust seq_num as
-        * WinStart = seq_num
-        */
-       if (pkt_type == PKT_TYPE_BAR)
-               seq_num = ((seq_num + win_size) - 1) & (MAX_TID_VALUE - 1);
-
-       if (((end_win < start_win) &&
-            (seq_num < start_win) && (seq_num > end_win)) ||
-           ((end_win > start_win) && ((seq_num > end_win) ||
-                                      (seq_num < start_win)))) {
-               end_win = seq_num;
-               if (((end_win - win_size) + 1) >= 0)
-                       start_win = (end_win - win_size) + 1;
-               else
-                       start_win = (MAX_TID_VALUE - (win_size - end_win)) + 1;
-               mwifiex_11n_dispatch_pkt_until_start_win(priv, tbl, start_win);
-       }
-
-       if (pkt_type != PKT_TYPE_BAR) {
-               if (seq_num >= start_win)
-                       pkt_index = seq_num - start_win;
-               else
-                       pkt_index = (seq_num+MAX_TID_VALUE) - start_win;
-
-               if (tbl->rx_reorder_ptr[pkt_index]) {
-                       ret = -1;
-                       goto done;
-               }
-
-               tbl->rx_reorder_ptr[pkt_index] = payload;
-       }
-
-       /*
-        * Dispatch all packets sequentially from start_win until a
-        * hole is found and adjust the start_win appropriately
-        */
-       mwifiex_11n_scan_and_dispatch(priv, tbl);
-
-done:
-       if (!tbl->timer_context.timer_is_set ||
-           prev_start_win != tbl->start_win)
-               mwifiex_11n_rxreorder_timer_restart(tbl);
-       return ret;
-}
-
-/*
- * This function deletes an entry for a given TID/TA pair.
- *
- * The TID/TA are taken from del BA event body.
- */
-void
-mwifiex_del_ba_tbl(struct mwifiex_private *priv, int tid, u8 *peer_mac,
-                  u8 type, int initiator)
-{
-       struct mwifiex_rx_reorder_tbl *tbl;
-       struct mwifiex_tx_ba_stream_tbl *ptx_tbl;
-       struct mwifiex_ra_list_tbl *ra_list;
-       u8 cleanup_rx_reorder_tbl;
-       unsigned long flags;
-       int tid_down;
-
-       if (type == TYPE_DELBA_RECEIVE)
-               cleanup_rx_reorder_tbl = (initiator) ? true : false;
-       else
-               cleanup_rx_reorder_tbl = (initiator) ? false : true;
-
-       mwifiex_dbg(priv->adapter, EVENT, "event: DELBA: %pM tid=%d initiator=%d\n",
-                   peer_mac, tid, initiator);
-
-       if (cleanup_rx_reorder_tbl) {
-               tbl = mwifiex_11n_get_rx_reorder_tbl(priv, tid,
-                                                                peer_mac);
-               if (!tbl) {
-                       mwifiex_dbg(priv->adapter, EVENT,
-                                   "event: TID, TA not found in table\n");
-                       return;
-               }
-               mwifiex_del_rx_reorder_entry(priv, tbl);
-       } else {
-               ptx_tbl = mwifiex_get_ba_tbl(priv, tid, peer_mac);
-               if (!ptx_tbl) {
-                       mwifiex_dbg(priv->adapter, EVENT,
-                                   "event: TID, RA not found in table\n");
-                       return;
-               }
-
-               tid_down = mwifiex_wmm_downgrade_tid(priv, tid);
-               ra_list = mwifiex_wmm_get_ralist_node(priv, tid_down, peer_mac);
-               if (ra_list) {
-                       ra_list->amsdu_in_ampdu = false;
-                       ra_list->ba_status = BA_SETUP_NONE;
-               }
-               spin_lock_irqsave(&priv->tx_ba_stream_tbl_lock, flags);
-               mwifiex_11n_delete_tx_ba_stream_tbl_entry(priv, ptx_tbl);
-               spin_unlock_irqrestore(&priv->tx_ba_stream_tbl_lock, flags);
-       }
-}
-
-/*
- * This function handles the command response of an add BA response.
- *
- * Handling includes changing the header fields into CPU format and
- * creating the stream, provided the add BA is accepted.
- */
-int mwifiex_ret_11n_addba_resp(struct mwifiex_private *priv,
-                              struct host_cmd_ds_command *resp)
-{
-       struct host_cmd_ds_11n_addba_rsp *add_ba_rsp = &resp->params.add_ba_rsp;
-       int tid, win_size;
-       struct mwifiex_rx_reorder_tbl *tbl;
-       uint16_t block_ack_param_set;
-
-       block_ack_param_set = le16_to_cpu(add_ba_rsp->block_ack_param_set);
-
-       tid = (block_ack_param_set & IEEE80211_ADDBA_PARAM_TID_MASK)
-               >> BLOCKACKPARAM_TID_POS;
-       /*
-        * Check if we had rejected the ADDBA, if yes then do not create
-        * the stream
-        */
-       if (le16_to_cpu(add_ba_rsp->status_code) != BA_RESULT_SUCCESS) {
-               mwifiex_dbg(priv->adapter, ERROR, "ADDBA RSP: failed %pM tid=%d)\n",
-                           add_ba_rsp->peer_mac_addr, tid);
-
-               tbl = mwifiex_11n_get_rx_reorder_tbl(priv, tid,
-                                                    add_ba_rsp->peer_mac_addr);
-               if (tbl)
-                       mwifiex_del_rx_reorder_entry(priv, tbl);
-
-               return 0;
-       }
-
-       win_size = (block_ack_param_set & IEEE80211_ADDBA_PARAM_BUF_SIZE_MASK)
-                   >> BLOCKACKPARAM_WINSIZE_POS;
-
-       tbl = mwifiex_11n_get_rx_reorder_tbl(priv, tid,
-                                            add_ba_rsp->peer_mac_addr);
-       if (tbl) {
-               if ((block_ack_param_set & BLOCKACKPARAM_AMSDU_SUPP_MASK) &&
-                   priv->add_ba_param.rx_amsdu &&
-                   (priv->aggr_prio_tbl[tid].amsdu != BA_STREAM_NOT_ALLOWED))
-                       tbl->amsdu = true;
-               else
-                       tbl->amsdu = false;
-       }
-
-       mwifiex_dbg(priv->adapter, CMD,
-                   "cmd: ADDBA RSP: %pM tid=%d ssn=%d win_size=%d\n",
-               add_ba_rsp->peer_mac_addr, tid, add_ba_rsp->ssn, win_size);
-
-       return 0;
-}
-
-/*
- * This function handles BA stream timeout event by preparing and sending
- * a command to the firmware.
- */
-void mwifiex_11n_ba_stream_timeout(struct mwifiex_private *priv,
-                                  struct host_cmd_ds_11n_batimeout *event)
-{
-       struct host_cmd_ds_11n_delba delba;
-
-       memset(&delba, 0, sizeof(struct host_cmd_ds_11n_delba));
-       memcpy(delba.peer_mac_addr, event->peer_mac_addr, ETH_ALEN);
-
-       delba.del_ba_param_set |=
-               cpu_to_le16((u16) event->tid << DELBA_TID_POS);
-       delba.del_ba_param_set |= cpu_to_le16(
-               (u16) event->origninator << DELBA_INITIATOR_POS);
-       delba.reason_code = cpu_to_le16(WLAN_REASON_QSTA_TIMEOUT);
-       mwifiex_send_cmd(priv, HostCmd_CMD_11N_DELBA, 0, 0, &delba, false);
-}
-
-/*
- * This function cleans up the Rx reorder table by deleting all the entries
- * and re-initializing.
- */
-void mwifiex_11n_cleanup_reorder_tbl(struct mwifiex_private *priv)
-{
-       struct mwifiex_rx_reorder_tbl *del_tbl_ptr, *tmp_node;
-       unsigned long flags;
-
-       spin_lock_irqsave(&priv->rx_reorder_tbl_lock, flags);
-       list_for_each_entry_safe(del_tbl_ptr, tmp_node,
-                                &priv->rx_reorder_tbl_ptr, list) {
-               spin_unlock_irqrestore(&priv->rx_reorder_tbl_lock, flags);
-               mwifiex_del_rx_reorder_entry(priv, del_tbl_ptr);
-               spin_lock_irqsave(&priv->rx_reorder_tbl_lock, flags);
-       }
-       INIT_LIST_HEAD(&priv->rx_reorder_tbl_ptr);
-       spin_unlock_irqrestore(&priv->rx_reorder_tbl_lock, flags);
-
-       mwifiex_reset_11n_rx_seq_num(priv);
-}
-
-/*
- * This function updates all rx_reorder_tbl's flags.
- */
-void mwifiex_update_rxreor_flags(struct mwifiex_adapter *adapter, u8 flags)
-{
-       struct mwifiex_private *priv;
-       struct mwifiex_rx_reorder_tbl *tbl;
-       unsigned long lock_flags;
-       int i;
-
-       for (i = 0; i < adapter->priv_num; i++) {
-               priv = adapter->priv[i];
-               if (!priv)
-                       continue;
-
-               spin_lock_irqsave(&priv->rx_reorder_tbl_lock, lock_flags);
-               if (list_empty(&priv->rx_reorder_tbl_ptr)) {
-                       spin_unlock_irqrestore(&priv->rx_reorder_tbl_lock,
-                                              lock_flags);
-                       continue;
-               }
-
-               list_for_each_entry(tbl, &priv->rx_reorder_tbl_ptr, list)
-                       tbl->flags = flags;
-               spin_unlock_irqrestore(&priv->rx_reorder_tbl_lock, lock_flags);
-       }
-
-       return;
-}
-
-/* This function update all the rx_win_size based on coex flag
- */
-static void mwifiex_update_ampdu_rxwinsize(struct mwifiex_adapter *adapter,
-                                          bool coex_flag)
-{
-       u8 i;
-       u32 rx_win_size;
-       struct mwifiex_private *priv;
-
-       dev_dbg(adapter->dev, "Update rxwinsize %d\n", coex_flag);
-
-       for (i = 0; i < adapter->priv_num; i++) {
-               if (!adapter->priv[i])
-                       continue;
-               priv = adapter->priv[i];
-               rx_win_size = priv->add_ba_param.rx_win_size;
-               if (coex_flag) {
-                       if (priv->bss_type == MWIFIEX_BSS_TYPE_STA)
-                               priv->add_ba_param.rx_win_size =
-                                       MWIFIEX_STA_COEX_AMPDU_DEF_RXWINSIZE;
-                       if (priv->bss_type == MWIFIEX_BSS_TYPE_P2P)
-                               priv->add_ba_param.rx_win_size =
-                                       MWIFIEX_STA_COEX_AMPDU_DEF_RXWINSIZE;
-                       if (priv->bss_type == MWIFIEX_BSS_TYPE_UAP)
-                               priv->add_ba_param.rx_win_size =
-                                       MWIFIEX_UAP_COEX_AMPDU_DEF_RXWINSIZE;
-               } else {
-                       if (priv->bss_type == MWIFIEX_BSS_TYPE_STA)
-                               priv->add_ba_param.rx_win_size =
-                                       MWIFIEX_STA_AMPDU_DEF_RXWINSIZE;
-                       if (priv->bss_type == MWIFIEX_BSS_TYPE_P2P)
-                               priv->add_ba_param.rx_win_size =
-                                       MWIFIEX_STA_AMPDU_DEF_RXWINSIZE;
-                       if (priv->bss_type == MWIFIEX_BSS_TYPE_UAP)
-                               priv->add_ba_param.rx_win_size =
-                                       MWIFIEX_UAP_AMPDU_DEF_RXWINSIZE;
-               }
-
-               if (adapter->coex_win_size && adapter->coex_rx_win_size)
-                       priv->add_ba_param.rx_win_size =
-                                       adapter->coex_rx_win_size;
-
-               if (rx_win_size != priv->add_ba_param.rx_win_size) {
-                       if (!priv->media_connected)
-                               continue;
-                       for (i = 0; i < MAX_NUM_TID; i++)
-                               mwifiex_11n_delba(priv, i);
-               }
-       }
-}
-
-/* This function check coex for RX BA
- */
-void mwifiex_coex_ampdu_rxwinsize(struct mwifiex_adapter *adapter)
-{
-       u8 i;
-       struct mwifiex_private *priv;
-       u8 count = 0;
-
-       for (i = 0; i < adapter->priv_num; i++) {
-               if (adapter->priv[i]) {
-                       priv = adapter->priv[i];
-                       if (GET_BSS_ROLE(priv) == MWIFIEX_BSS_ROLE_STA) {
-                               if (priv->media_connected)
-                                       count++;
-                       }
-                       if (GET_BSS_ROLE(priv) == MWIFIEX_BSS_ROLE_UAP) {
-                               if (priv->bss_started)
-                                       count++;
-                       }
-               }
-               if (count >= MWIFIEX_BSS_COEX_COUNT)
-                       break;
-       }
-       if (count >= MWIFIEX_BSS_COEX_COUNT)
-               mwifiex_update_ampdu_rxwinsize(adapter, true);
-       else
-               mwifiex_update_ampdu_rxwinsize(adapter, false);
-}
diff --git a/drivers/net/wireless/mwifiex/11n_rxreorder.h b/drivers/net/wireless/mwifiex/11n_rxreorder.h
deleted file mode 100644 (file)
index 63ecea8..0000000
+++ /dev/null
@@ -1,85 +0,0 @@
-/*
- * Marvell Wireless LAN device driver: 802.11n RX Re-ordering
- *
- * Copyright (C) 2011-2014, Marvell International Ltd.
- *
- * This software file (the "File") is distributed by Marvell International
- * Ltd. under the terms of the GNU General Public License Version 2, June 1991
- * (the "License").  You may use, redistribute and/or modify this File in
- * accordance with the terms and conditions of the License, a copy of which
- * is available by writing to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the
- * worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
- *
- * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
- * ARE EXPRESSLY DISCLAIMED.  The License provides additional details about
- * this warranty disclaimer.
- */
-
-#ifndef _MWIFIEX_11N_RXREORDER_H_
-#define _MWIFIEX_11N_RXREORDER_H_
-
-#define MIN_FLUSH_TIMER_MS             50
-#define MIN_FLUSH_TIMER_15_MS          15
-#define MWIFIEX_BA_WIN_SIZE_32         32
-
-#define PKT_TYPE_BAR 0xE7
-#define MAX_TID_VALUE                  (2 << 11)
-#define TWOPOW11                       (2 << 10)
-
-#define BLOCKACKPARAM_TID_POS          2
-#define BLOCKACKPARAM_AMSDU_SUPP_MASK  0x1
-#define BLOCKACKPARAM_WINSIZE_POS      6
-#define DELBA_TID_POS                  12
-#define DELBA_INITIATOR_POS            11
-#define TYPE_DELBA_SENT                        1
-#define TYPE_DELBA_RECEIVE             2
-#define IMMEDIATE_BLOCK_ACK            0x2
-
-#define ADDBA_RSP_STATUS_ACCEPT 0
-
-#define MWIFIEX_DEF_11N_RX_SEQ_NUM     0xffff
-#define BA_SETUP_MAX_PACKET_THRESHOLD  16
-#define BA_SETUP_PACKET_OFFSET         16
-
-enum mwifiex_rxreor_flags {
-       RXREOR_FORCE_NO_DROP            = 1<<0,
-       RXREOR_INIT_WINDOW_SHIFT        = 1<<1,
-};
-
-static inline void mwifiex_reset_11n_rx_seq_num(struct mwifiex_private *priv)
-{
-       memset(priv->rx_seq, 0xff, sizeof(priv->rx_seq));
-}
-
-int mwifiex_11n_rx_reorder_pkt(struct mwifiex_private *,
-                              u16 seqNum,
-                              u16 tid, u8 *ta,
-                              u8 pkttype, void *payload);
-void mwifiex_del_ba_tbl(struct mwifiex_private *priv, int Tid,
-                       u8 *PeerMACAddr, u8 type, int initiator);
-void mwifiex_11n_ba_stream_timeout(struct mwifiex_private *priv,
-                                  struct host_cmd_ds_11n_batimeout *event);
-int mwifiex_ret_11n_addba_resp(struct mwifiex_private *priv,
-                              struct host_cmd_ds_command
-                              *resp);
-int mwifiex_cmd_11n_delba(struct host_cmd_ds_command *cmd,
-                         void *data_buf);
-int mwifiex_cmd_11n_addba_rsp_gen(struct mwifiex_private *priv,
-                                 struct host_cmd_ds_command *cmd,
-                                 struct host_cmd_ds_11n_addba_req
-                                 *cmd_addba_req);
-int mwifiex_cmd_11n_addba_req(struct host_cmd_ds_command *cmd,
-                             void *data_buf);
-void mwifiex_11n_cleanup_reorder_tbl(struct mwifiex_private *priv);
-struct mwifiex_rx_reorder_tbl *mwifiex_11n_get_rxreorder_tbl(struct
-                                                          mwifiex_private
-                                                          *priv, int tid,
-                                                          u8 *ta);
-struct mwifiex_rx_reorder_tbl *
-mwifiex_11n_get_rx_reorder_tbl(struct mwifiex_private *priv, int tid, u8 *ta);
-void mwifiex_11n_del_rx_reorder_tbl_by_ta(struct mwifiex_private *priv, u8 *ta);
-void mwifiex_update_rxreor_flags(struct mwifiex_adapter *adapter, u8 flags);
-
-#endif /* _MWIFIEX_11N_RXREORDER_H_ */
diff --git a/drivers/net/wireless/mwifiex/Kconfig b/drivers/net/wireless/mwifiex/Kconfig
deleted file mode 100644 (file)
index 279167d..0000000
+++ /dev/null
@@ -1,44 +0,0 @@
-config MWIFIEX
-       tristate "Marvell WiFi-Ex Driver"
-       depends on CFG80211
-       ---help---
-         This adds support for wireless adapters based on Marvell
-         802.11n/ac chipsets.
-
-         If you choose to build it as a module, it will be called
-         mwifiex.
-
-config MWIFIEX_SDIO
-       tristate "Marvell WiFi-Ex Driver for SD8786/SD8787/SD8797/SD8887/SD8897/SD8997"
-       depends on MWIFIEX && MMC
-       select FW_LOADER
-       select WANT_DEV_COREDUMP
-       ---help---
-         This adds support for wireless adapters based on Marvell
-         8786/8787/8797/8887/8897/8997 chipsets with SDIO interface.
-
-         If you choose to build it as a module, it will be called
-         mwifiex_sdio.
-
-config MWIFIEX_PCIE
-       tristate "Marvell WiFi-Ex Driver for PCIE 8766/8897/8997"
-       depends on MWIFIEX && PCI
-       select FW_LOADER
-       select WANT_DEV_COREDUMP
-       ---help---
-         This adds support for wireless adapters based on Marvell
-         8766/8897/8997 chipsets with PCIe interface.
-
-         If you choose to build it as a module, it will be called
-         mwifiex_pcie.
-
-config MWIFIEX_USB
-       tristate "Marvell WiFi-Ex Driver for USB8766/8797/8997"
-       depends on MWIFIEX && USB
-       select FW_LOADER
-       ---help---
-         This adds support for wireless adapters based on Marvell
-         8797/8997 chipset with USB interface.
-
-         If you choose to build it as a module, it will be called
-         mwifiex_usb.
diff --git a/drivers/net/wireless/mwifiex/Makefile b/drivers/net/wireless/mwifiex/Makefile
deleted file mode 100644 (file)
index fdfd9bf..0000000
+++ /dev/null
@@ -1,57 +0,0 @@
-#
-# Copyright (C) 2011-2014, Marvell International Ltd.
-#
-# This software file (the "File") is distributed by Marvell International
-# Ltd. under the terms of the GNU General Public License Version 2, June 1991
-# (the "License").  You may use, redistribute and/or modify this File in
-# accordance with the terms and conditions of the License, a copy of which
-# is available by writing to the Free Software Foundation, Inc.,
-# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the
-# worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
-#
-# THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
-# IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
-# ARE EXPRESSLY DISCLAIMED.  The License provides additional details about
-# this warranty disclaimer.
-
-
-mwifiex-y += main.o
-mwifiex-y += init.o
-mwifiex-y += cfp.o
-mwifiex-y += cmdevt.o
-mwifiex-y += util.o
-mwifiex-y += txrx.o
-mwifiex-y += wmm.o
-mwifiex-y += 11n.o
-mwifiex-y += 11ac.o
-mwifiex-y += 11n_aggr.o
-mwifiex-y += 11n_rxreorder.o
-mwifiex-y += scan.o
-mwifiex-y += join.o
-mwifiex-y += sta_ioctl.o
-mwifiex-y += sta_cmd.o
-mwifiex-y += uap_cmd.o
-mwifiex-y += ie.o
-mwifiex-y += sta_cmdresp.o
-mwifiex-y += sta_event.o
-mwifiex-y += uap_event.o
-mwifiex-y += sta_tx.o
-mwifiex-y += sta_rx.o
-mwifiex-y += uap_txrx.o
-mwifiex-y += cfg80211.o
-mwifiex-y += ethtool.o
-mwifiex-y += 11h.o
-mwifiex-y += tdls.o
-mwifiex-$(CONFIG_DEBUG_FS) += debugfs.o
-obj-$(CONFIG_MWIFIEX) += mwifiex.o
-
-mwifiex_sdio-y += sdio.o
-obj-$(CONFIG_MWIFIEX_SDIO) += mwifiex_sdio.o
-
-mwifiex_pcie-y += pcie.o
-obj-$(CONFIG_MWIFIEX_PCIE) += mwifiex_pcie.o
-
-mwifiex_usb-y += usb.o
-obj-$(CONFIG_MWIFIEX_USB) += mwifiex_usb.o
-
-ccflags-y += -D__CHECK_ENDIAN
diff --git a/drivers/net/wireless/mwifiex/README b/drivers/net/wireless/mwifiex/README
deleted file mode 100644 (file)
index 2f0f9b5..0000000
+++ /dev/null
@@ -1,240 +0,0 @@
-# Copyright (C) 2011-2014, Marvell International Ltd.
-#
-# This software file (the "File") is distributed by Marvell International
-# Ltd. under the terms of the GNU General Public License Version 2, June 1991
-# (the "License").  You may use, redistribute and/or modify this File in
-# accordance with the terms and conditions of the License, a copy of which
-# is available by writing to the Free Software Foundation, Inc.,
-# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the
-# worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
-#
-# THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
-# IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
-# ARE EXPRESSLY DISCLAIMED.  The License provides additional details about
-# this warranty disclaimer.
-
-
-===============================================================================
-                       U S E R  M A N U A L
-
-1) FOR DRIVER INSTALL
-
-       a) Copy sd8787.bin to /lib/firmware/mrvl/ directory,
-          create the directory if it doesn't exist.
-       b) Install WLAN driver,
-               insmod mwifiex.ko
-       c) Uninstall WLAN driver,
-               ifconfig mlanX down
-               rmmod mwifiex
-
-
-2) FOR DRIVER CONFIGURATION AND INFO
-       The configurations can be done either using the 'iw' user space
-       utility or debugfs.
-
-       a) 'iw' utility commands
-
-       Following are some useful iw commands:-
-
-iw dev mlan0 scan
-
-       This command will trigger a scan.
-       The command will then display the scan table entries
-
-iw dev mlan0 connect -w <SSID> [<freq in MHz>] [<bssid>] [key 0:abcde d:1123456789a]
-       The above command can be used to connect to an AP with a particular SSID.
-       Ap's operating frequency can be specified or even the bssid. If the AP is using
-       WEP encryption, wep keys can be specified in the command.
-       Note: Every time before connecting to an AP scan command (iw dev mlan0 scan) should be used by user.
-
-iw dev mlan0 disconnect
-       This command will be used to disconnect from an AP.
-
-
-iw dev mlan0 ibss join <SSID> <freq in MHz> [fixed-freq] [fixed-bssid] [key 0:abcde]
-       The command will be used to join or create an ibss. Optionally, operating frequency,
-       bssid and the security related parameters can be specified while joining/creating
-       and ibss.
-
-iw dev mlan0 ibss leave
-       The command will be used to leave an ibss network.
-
-iw dev mlan0 link
-       The command will be used to get the connection status. The command will return parameters
-       such as SSID, operating frequency, rx/tx packets, signal strength, tx bitrate.
-
-       Apart from the iw utility all standard configurations using the 'iwconfig' utility are also supported.
-
-       b) Debugfs interface
-
-       The debugfs interface can be used for configurations and for getting
-       some useful information from the driver.
-       The section below explains the configurations that can be
-       done.
-
-       Mount debugfs to /debugfs mount point:
-
-               mkdir /debugfs
-               mount -t debugfs debugfs /debugfs
-
-       The information is provided in /debugfs/mwifiex/mlanX/:
-
-iw reg set <country code>
-       The command will be used to change the regulatory domain.
-
-iw reg get
-       The command will be used to get current regulatory domain.
-
-info
-       This command is used to get driver info.
-
-       Usage:
-               cat info
-
-       driver_name = "mwifiex"
-       driver_version = <driver_name, driver_version, (firmware_version)>
-       interface_name = "mlanX"
-       bss_mode = "Ad-hoc" | "Managed" | "Auto" | "Unknown"
-       media_state = "Disconnected" | "Connected"
-       mac_address = <6-byte adapter MAC address>
-       multicase_count = <multicast address count>
-       essid = <current SSID>
-       bssid = <current BSSID>
-       channel = <current channel>
-       region_code = <current region code>
-       multicasr_address[n] = <multicast address>
-       num_tx_bytes = <number of bytes sent to device>
-       num_rx_bytes = <number of bytes received from device and sent to kernel>
-       num_tx_pkts = <number of packets sent to device>
-       num_rx_pkts = <number of packets received from device and sent to kernel>
-       num_tx_pkts_dropped = <number of Tx packets dropped by driver>
-       num_rx_pkts_dropped = <number of Rx packets dropped by driver>
-       num_tx_pkts_err = <number of Tx packets failed to send to device>
-       num_rx_pkts_err = <number of Rx packets failed to receive from device>
-       carrier "on" | "off"
-       tx queue "stopped" | "started"
-
-       The following debug info are provided in /debugfs/mwifiex/mlanX/debug:
-
-       int_counter = <interrupt count, cleared when interrupt handled>
-       wmm_ac_vo = <number of packets sent to device from WMM AcVo queue>
-       wmm_ac_vi = <number of packets sent to device from WMM AcVi queue>
-       wmm_ac_be = <number of packets sent to device from WMM AcBE queue>
-       wmm_ac_bk = <number of packets sent to device from WMM AcBK queue>
-       tx_buf_size = <current Tx buffer size>
-       curr_tx_buf_size = <current Tx buffer size>
-       ps_mode = <0/1, CAM mode/PS mode>
-       ps_state = <0/1/2/3, full power state/awake state/pre-sleep state/sleep state>
-       is_deep_sleep = <0/1, not deep sleep state/deep sleep state>
-       wakeup_dev_req = <0/1, wakeup device not required/required>
-       wakeup_tries = <wakeup device count, cleared when device awake>
-       hs_configured = <0/1, host sleep not configured/configured>
-       hs_activated = <0/1, extended host sleep not activated/activated>
-       num_tx_timeout = <number of Tx timeout>
-       is_cmd_timedout = <0/1 command timeout not occurred/occurred>
-       timeout_cmd_id = <command id of the last timeout command>
-       timeout_cmd_act = <command action of the last timeout command>
-       last_cmd_id = <command id of the last several commands sent to device>
-       last_cmd_act = <command action of the last several commands sent to device>
-       last_cmd_index = <0 based last command index>
-       last_cmd_resp_id = <command id of the last several command responses received from device>
-       last_cmd_resp_index = <0 based last command response index>
-       last_event = <event id of the last several events received from device>
-       last_event_index = <0 based last event index>
-       num_cmd_h2c_fail = <number of commands failed to send to device>
-       num_cmd_sleep_cfm_fail = <number of sleep confirm failed to send to device>
-       num_tx_h2c_fail = <number of data packets failed to send to device>
-       num_evt_deauth = <number of deauthenticated events received from device>
-       num_evt_disassoc = <number of disassociated events received from device>
-       num_evt_link_lost = <number of link lost events received from device>
-       num_cmd_deauth = <number of deauthenticate commands sent to device>
-       num_cmd_assoc_ok = <number of associate commands with success return>
-       num_cmd_assoc_fail = <number of associate commands with failure return>
-       cmd_sent = <0/1, send command resources available/sending command to device>
-       data_sent = <0/1, send data resources available/sending data to device>
-       mp_rd_bitmap = <SDIO multi-port read bitmap>
-       mp_wr_bitmap = <SDIO multi-port write bitmap>
-       cmd_resp_received = <0/1, no cmd response to process/response received and yet to process>
-       event_received = <0/1, no event to process/event received and yet to process>
-       cmd_pending = <number of cmd pending>
-       tx_pending = <number of Tx packet pending>
-       rx_pending = <number of Rx packet pending>
-
-
-3) FOR DRIVER CONFIGURATION
-
-regrdwr
-       This command is used to read/write the adapter register.
-
-       Usage:
-               echo " <type> <offset> [value]" > regrdwr
-               cat regrdwr
-
-       where the parameters are,
-               <type>:     1:MAC/SOC, 2:BBP, 3:RF, 4:PMIC, 5:CAU
-               <offset>:   offset of register
-               [value]:    value to be written
-
-       Examples:
-               echo "1 0xa060" > regrdwr           : Read the MAC register
-               echo "1 0xa060 0x12" > regrdwr      : Write the MAC register
-               echo "1 0xa794 0x80000000" > regrdwr
-                                                   : Write 0x80000000 to MAC register
-rdeeprom
-       This command is used to read the EEPROM contents of the card.
-
-       Usage:
-               echo "<offset> <length>" > rdeeprom
-               cat rdeeprom
-
-       where the parameters are,
-               <offset>:   multiples of 4
-               <length>:   4-20, multiples of 4
-
-       Example:
-               echo "0 20" > rdeeprom      : Read 20 bytes of EEPROM data from offset 0
-
-hscfg
-       This command is used to debug/simulate host sleep feature using
-       different configuration parameters.
-
-       Usage:
-               echo "<condition> [GPIO# [gap]]]" > hscfg
-               cat hscfg
-
-       where the parameters are,
-               <condition>: bit 0 = 1   -- broadcast data
-                            bit 1 = 1   -- unicast data
-                            bit 2 = 1   -- mac event
-                            bit 3 = 1   -- multicast data
-               [GPIO#]: pin number of GPIO used to wakeup the host.
-                        GPIO pin# (e.g. 0-7) or 0xff (interface, e.g. SDIO
-                        will be used instead).
-               [gap]:   the gap in milliseconds between wakeup signal and
-                        wakeup event or 0xff for special setting (host
-                        acknowledge required) when GPIO is used to wakeup host.
-
-       Examples:
-               echo "-1" > hscfg        : Cancel host sleep mode
-               echo "3" > hscfg         : Broadcast and unicast data;
-                                          Use GPIO and gap set previously
-               echo "2 3" > hscfg       : Unicast data and GPIO 3;
-                                          Use gap set previously
-               echo "2 1 160" > hscfg   : Unicast data, GPIO 1 and gap 160 ms
-               echo "2 1 0xff" > hscfg  : Unicast data, GPIO 1; Wait for host
-                                          to ack before sending wakeup event
-
-getlog
-        This command is used to get the statistics available in the station.
-       Usage:
-
-       cat getlog
-
-device_dump
-       This command is used to dump driver information and firmware memory
-       segments.
-       Usage:
-
-       cat fw_dump
-
-===============================================================================
diff --git a/drivers/net/wireless/mwifiex/cfg80211.c b/drivers/net/wireless/mwifiex/cfg80211.c
deleted file mode 100644 (file)
index 4073116..0000000
+++ /dev/null
@@ -1,3887 +0,0 @@
-/*
- * Marvell Wireless LAN device driver: CFG80211
- *
- * Copyright (C) 2011-2014, Marvell International Ltd.
- *
- * This software file (the "File") is distributed by Marvell International
- * Ltd. under the terms of the GNU General Public License Version 2, June 1991
- * (the "License").  You may use, redistribute and/or modify this File in
- * accordance with the terms and conditions of the License, a copy of which
- * is available by writing to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the
- * worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
- *
- * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
- * ARE EXPRESSLY DISCLAIMED.  The License provides additional details about
- * this warranty disclaimer.
- */
-
-#include "cfg80211.h"
-#include "main.h"
-#include "11n.h"
-
-static char *reg_alpha2;
-module_param(reg_alpha2, charp, 0);
-
-static const struct ieee80211_iface_limit mwifiex_ap_sta_limits[] = {
-       {
-               .max = 2, .types = BIT(NL80211_IFTYPE_STATION) |
-                                  BIT(NL80211_IFTYPE_P2P_GO) |
-                                  BIT(NL80211_IFTYPE_P2P_CLIENT),
-       },
-       {
-               .max = 1, .types = BIT(NL80211_IFTYPE_AP),
-       },
-};
-
-static const struct ieee80211_iface_combination
-mwifiex_iface_comb_ap_sta = {
-       .limits = mwifiex_ap_sta_limits,
-       .num_different_channels = 1,
-       .n_limits = ARRAY_SIZE(mwifiex_ap_sta_limits),
-       .max_interfaces = MWIFIEX_MAX_BSS_NUM,
-       .beacon_int_infra_match = true,
-       .radar_detect_widths =  BIT(NL80211_CHAN_WIDTH_20_NOHT) |
-                               BIT(NL80211_CHAN_WIDTH_20) |
-                               BIT(NL80211_CHAN_WIDTH_40),
-};
-
-static const struct ieee80211_iface_combination
-mwifiex_iface_comb_ap_sta_vht = {
-       .limits = mwifiex_ap_sta_limits,
-       .num_different_channels = 1,
-       .n_limits = ARRAY_SIZE(mwifiex_ap_sta_limits),
-       .max_interfaces = MWIFIEX_MAX_BSS_NUM,
-       .beacon_int_infra_match = true,
-       .radar_detect_widths =  BIT(NL80211_CHAN_WIDTH_20_NOHT) |
-                               BIT(NL80211_CHAN_WIDTH_20) |
-                               BIT(NL80211_CHAN_WIDTH_40) |
-                               BIT(NL80211_CHAN_WIDTH_80),
-};
-
-static const struct
-ieee80211_iface_combination mwifiex_iface_comb_ap_sta_drcs = {
-       .limits = mwifiex_ap_sta_limits,
-       .num_different_channels = 2,
-       .n_limits = ARRAY_SIZE(mwifiex_ap_sta_limits),
-       .max_interfaces = MWIFIEX_MAX_BSS_NUM,
-       .beacon_int_infra_match = true,
-};
-
-/*
- * This function maps the nl802.11 channel type into driver channel type.
- *
- * The mapping is as follows -
- *      NL80211_CHAN_NO_HT     -> IEEE80211_HT_PARAM_CHA_SEC_NONE
- *      NL80211_CHAN_HT20      -> IEEE80211_HT_PARAM_CHA_SEC_NONE
- *      NL80211_CHAN_HT40PLUS  -> IEEE80211_HT_PARAM_CHA_SEC_ABOVE
- *      NL80211_CHAN_HT40MINUS -> IEEE80211_HT_PARAM_CHA_SEC_BELOW
- *      Others                 -> IEEE80211_HT_PARAM_CHA_SEC_NONE
- */
-u8 mwifiex_chan_type_to_sec_chan_offset(enum nl80211_channel_type chan_type)
-{
-       switch (chan_type) {
-       case NL80211_CHAN_NO_HT:
-       case NL80211_CHAN_HT20:
-               return IEEE80211_HT_PARAM_CHA_SEC_NONE;
-       case NL80211_CHAN_HT40PLUS:
-               return IEEE80211_HT_PARAM_CHA_SEC_ABOVE;
-       case NL80211_CHAN_HT40MINUS:
-               return IEEE80211_HT_PARAM_CHA_SEC_BELOW;
-       default:
-               return IEEE80211_HT_PARAM_CHA_SEC_NONE;
-       }
-}
-
-/* This function maps IEEE HT secondary channel type to NL80211 channel type
- */
-u8 mwifiex_sec_chan_offset_to_chan_type(u8 second_chan_offset)
-{
-       switch (second_chan_offset) {
-       case IEEE80211_HT_PARAM_CHA_SEC_NONE:
-               return NL80211_CHAN_HT20;
-       case IEEE80211_HT_PARAM_CHA_SEC_ABOVE:
-               return NL80211_CHAN_HT40PLUS;
-       case IEEE80211_HT_PARAM_CHA_SEC_BELOW:
-               return NL80211_CHAN_HT40MINUS;
-       default:
-               return NL80211_CHAN_HT20;
-       }
-}
-
-/*
- * This function checks whether WEP is set.
- */
-static int
-mwifiex_is_alg_wep(u32 cipher)
-{
-       switch (cipher) {
-       case WLAN_CIPHER_SUITE_WEP40:
-       case WLAN_CIPHER_SUITE_WEP104:
-               return 1;
-       default:
-               break;
-       }
-
-       return 0;
-}
-
-/*
- * This function retrieves the private structure from kernel wiphy structure.
- */
-static void *mwifiex_cfg80211_get_adapter(struct wiphy *wiphy)
-{
-       return (void *) (*(unsigned long *) wiphy_priv(wiphy));
-}
-
-/*
- * CFG802.11 operation handler to delete a network key.
- */
-static int
-mwifiex_cfg80211_del_key(struct wiphy *wiphy, struct net_device *netdev,
-                        u8 key_index, bool pairwise, const u8 *mac_addr)
-{
-       struct mwifiex_private *priv = mwifiex_netdev_get_priv(netdev);
-       const u8 bc_mac[] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
-       const u8 *peer_mac = pairwise ? mac_addr : bc_mac;
-
-       if (mwifiex_set_encode(priv, NULL, NULL, 0, key_index, peer_mac, 1)) {
-               mwifiex_dbg(priv->adapter, ERROR, "deleting the crypto keys\n");
-               return -EFAULT;
-       }
-
-       mwifiex_dbg(priv->adapter, INFO, "info: crypto keys deleted\n");
-       return 0;
-}
-
-/*
- * This function forms an skb for management frame.
- */
-static int
-mwifiex_form_mgmt_frame(struct sk_buff *skb, const u8 *buf, size_t len)
-{
-       u8 addr[ETH_ALEN] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF};
-       u16 pkt_len;
-       u32 tx_control = 0, pkt_type = PKT_TYPE_MGMT;
-
-       pkt_len = len + ETH_ALEN;
-
-       skb_reserve(skb, MWIFIEX_MIN_DATA_HEADER_LEN +
-                   MWIFIEX_MGMT_FRAME_HEADER_SIZE + sizeof(pkt_len));
-       memcpy(skb_push(skb, sizeof(pkt_len)), &pkt_len, sizeof(pkt_len));
-
-       memcpy(skb_push(skb, sizeof(tx_control)),
-              &tx_control, sizeof(tx_control));
-
-       memcpy(skb_push(skb, sizeof(pkt_type)), &pkt_type, sizeof(pkt_type));
-
-       /* Add packet data and address4 */
-       memcpy(skb_put(skb, sizeof(struct ieee80211_hdr_3addr)), buf,
-              sizeof(struct ieee80211_hdr_3addr));
-       memcpy(skb_put(skb, ETH_ALEN), addr, ETH_ALEN);
-       memcpy(skb_put(skb, len - sizeof(struct ieee80211_hdr_3addr)),
-              buf + sizeof(struct ieee80211_hdr_3addr),
-              len - sizeof(struct ieee80211_hdr_3addr));
-
-       skb->priority = LOW_PRIO_TID;
-       __net_timestamp(skb);
-
-       return 0;
-}
-
-/*
- * CFG802.11 operation handler to transmit a management frame.
- */
-static int
-mwifiex_cfg80211_mgmt_tx(struct wiphy *wiphy, struct wireless_dev *wdev,
-                        struct cfg80211_mgmt_tx_params *params, u64 *cookie)
-{
-       const u8 *buf = params->buf;
-       size_t len = params->len;
-       struct sk_buff *skb;
-       u16 pkt_len;
-       const struct ieee80211_mgmt *mgmt;
-       struct mwifiex_txinfo *tx_info;
-       struct mwifiex_private *priv = mwifiex_netdev_get_priv(wdev->netdev);
-
-       if (!buf || !len) {
-               mwifiex_dbg(priv->adapter, ERROR, "invalid buffer and length\n");
-               return -EFAULT;
-       }
-
-       mgmt = (const struct ieee80211_mgmt *)buf;
-       if (GET_BSS_ROLE(priv) != MWIFIEX_BSS_ROLE_STA &&
-           ieee80211_is_probe_resp(mgmt->frame_control)) {
-               /* Since we support offload probe resp, we need to skip probe
-                * resp in AP or GO mode */
-               mwifiex_dbg(priv->adapter, INFO,
-                           "info: skip to send probe resp in AP or GO mode\n");
-               return 0;
-       }
-
-       pkt_len = len + ETH_ALEN;
-       skb = dev_alloc_skb(MWIFIEX_MIN_DATA_HEADER_LEN +
-                           MWIFIEX_MGMT_FRAME_HEADER_SIZE +
-                           pkt_len + sizeof(pkt_len));
-
-       if (!skb) {
-               mwifiex_dbg(priv->adapter, ERROR,
-                           "allocate skb failed for management frame\n");
-               return -ENOMEM;
-       }
-
-       tx_info = MWIFIEX_SKB_TXCB(skb);
-       memset(tx_info, 0, sizeof(*tx_info));
-       tx_info->bss_num = priv->bss_num;
-       tx_info->bss_type = priv->bss_type;
-       tx_info->pkt_len = pkt_len;
-
-       mwifiex_form_mgmt_frame(skb, buf, len);
-       *cookie = prandom_u32() | 1;
-
-       if (ieee80211_is_action(mgmt->frame_control))
-               skb = mwifiex_clone_skb_for_tx_status(priv,
-                                                     skb,
-                               MWIFIEX_BUF_FLAG_ACTION_TX_STATUS, cookie);
-       else
-               cfg80211_mgmt_tx_status(wdev, *cookie, buf, len, true,
-                                       GFP_ATOMIC);
-
-       mwifiex_queue_tx_pkt(priv, skb);
-
-       mwifiex_dbg(priv->adapter, INFO, "info: management frame transmitted\n");
-       return 0;
-}
-
-/*
- * CFG802.11 operation handler to register a mgmt frame.
- */
-static void
-mwifiex_cfg80211_mgmt_frame_register(struct wiphy *wiphy,
-                                    struct wireless_dev *wdev,
-                                    u16 frame_type, bool reg)
-{
-       struct mwifiex_private *priv = mwifiex_netdev_get_priv(wdev->netdev);
-       u32 mask;
-
-       if (reg)
-               mask = priv->mgmt_frame_mask | BIT(frame_type >> 4);
-       else
-               mask = priv->mgmt_frame_mask & ~BIT(frame_type >> 4);
-
-       if (mask != priv->mgmt_frame_mask) {
-               priv->mgmt_frame_mask = mask;
-               mwifiex_send_cmd(priv, HostCmd_CMD_MGMT_FRAME_REG,
-                                HostCmd_ACT_GEN_SET, 0,
-                                &priv->mgmt_frame_mask, false);
-               mwifiex_dbg(priv->adapter, INFO, "info: mgmt frame registered\n");
-       }
-}
-
-/*
- * CFG802.11 operation handler to remain on channel.
- */
-static int
-mwifiex_cfg80211_remain_on_channel(struct wiphy *wiphy,
-                                  struct wireless_dev *wdev,
-                                  struct ieee80211_channel *chan,
-                                  unsigned int duration, u64 *cookie)
-{
-       struct mwifiex_private *priv = mwifiex_netdev_get_priv(wdev->netdev);
-       int ret;
-
-       if (!chan || !cookie) {
-               mwifiex_dbg(priv->adapter, ERROR, "Invalid parameter for ROC\n");
-               return -EINVAL;
-       }
-
-       if (priv->roc_cfg.cookie) {
-               mwifiex_dbg(priv->adapter, INFO,
-                           "info: ongoing ROC, cookie = 0x%llx\n",
-                           priv->roc_cfg.cookie);
-               return -EBUSY;
-       }
-
-       ret = mwifiex_remain_on_chan_cfg(priv, HostCmd_ACT_GEN_SET, chan,
-                                        duration);
-
-       if (!ret) {
-               *cookie = prandom_u32() | 1;
-               priv->roc_cfg.cookie = *cookie;
-               priv->roc_cfg.chan = *chan;
-
-               cfg80211_ready_on_channel(wdev, *cookie, chan,
-                                         duration, GFP_ATOMIC);
-
-               mwifiex_dbg(priv->adapter, INFO,
-                           "info: ROC, cookie = 0x%llx\n", *cookie);
-       }
-
-       return ret;
-}
-
-/*
- * CFG802.11 operation handler to cancel remain on channel.
- */
-static int
-mwifiex_cfg80211_cancel_remain_on_channel(struct wiphy *wiphy,
-                                         struct wireless_dev *wdev, u64 cookie)
-{
-       struct mwifiex_private *priv = mwifiex_netdev_get_priv(wdev->netdev);
-       int ret;
-
-       if (cookie != priv->roc_cfg.cookie)
-               return -ENOENT;
-
-       ret = mwifiex_remain_on_chan_cfg(priv, HostCmd_ACT_GEN_REMOVE,
-                                        &priv->roc_cfg.chan, 0);
-
-       if (!ret) {
-               cfg80211_remain_on_channel_expired(wdev, cookie,
-                                                  &priv->roc_cfg.chan,
-                                                  GFP_ATOMIC);
-
-               memset(&priv->roc_cfg, 0, sizeof(struct mwifiex_roc_cfg));
-
-               mwifiex_dbg(priv->adapter, INFO,
-                           "info: cancel ROC, cookie = 0x%llx\n", cookie);
-       }
-
-       return ret;
-}
-
-/*
- * CFG802.11 operation handler to set Tx power.
- */
-static int
-mwifiex_cfg80211_set_tx_power(struct wiphy *wiphy,
-                             struct wireless_dev *wdev,
-                             enum nl80211_tx_power_setting type,
-                             int mbm)
-{
-       struct mwifiex_adapter *adapter = mwifiex_cfg80211_get_adapter(wiphy);
-       struct mwifiex_private *priv;
-       struct mwifiex_power_cfg power_cfg;
-       int dbm = MBM_TO_DBM(mbm);
-
-       if (type == NL80211_TX_POWER_FIXED) {
-               power_cfg.is_power_auto = 0;
-               power_cfg.power_level = dbm;
-       } else {
-               power_cfg.is_power_auto = 1;
-       }
-
-       priv = mwifiex_get_priv(adapter, MWIFIEX_BSS_ROLE_ANY);
-
-       return mwifiex_set_tx_power(priv, &power_cfg);
-}
-
-/*
- * CFG802.11 operation handler to set Power Save option.
- *
- * The timeout value, if provided, is currently ignored.
- */
-static int
-mwifiex_cfg80211_set_power_mgmt(struct wiphy *wiphy,
-                               struct net_device *dev,
-                               bool enabled, int timeout)
-{
-       struct mwifiex_private *priv = mwifiex_netdev_get_priv(dev);
-       u32 ps_mode;
-
-       if (timeout)
-               mwifiex_dbg(priv->adapter, INFO,
-                           "info: ignore timeout value for IEEE Power Save\n");
-
-       ps_mode = enabled;
-
-       return mwifiex_drv_set_power(priv, &ps_mode);
-}
-
-/*
- * CFG802.11 operation handler to set the default network key.
- */
-static int
-mwifiex_cfg80211_set_default_key(struct wiphy *wiphy, struct net_device *netdev,
-                                u8 key_index, bool unicast,
-                                bool multicast)
-{
-       struct mwifiex_private *priv = mwifiex_netdev_get_priv(netdev);
-
-       /* Return if WEP key not configured */
-       if (!priv->sec_info.wep_enabled)
-               return 0;
-
-       if (priv->bss_type == MWIFIEX_BSS_TYPE_UAP) {
-               priv->wep_key_curr_index = key_index;
-       } else if (mwifiex_set_encode(priv, NULL, NULL, 0, key_index,
-                                     NULL, 0)) {
-               mwifiex_dbg(priv->adapter, ERROR, "set default Tx key index\n");
-               return -EFAULT;
-       }
-
-       return 0;
-}
-
-/*
- * CFG802.11 operation handler to add a network key.
- */
-static int
-mwifiex_cfg80211_add_key(struct wiphy *wiphy, struct net_device *netdev,
-                        u8 key_index, bool pairwise, const u8 *mac_addr,
-                        struct key_params *params)
-{
-       struct mwifiex_private *priv = mwifiex_netdev_get_priv(netdev);
-       struct mwifiex_wep_key *wep_key;
-       const u8 bc_mac[] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
-       const u8 *peer_mac = pairwise ? mac_addr : bc_mac;
-
-       if (GET_BSS_ROLE(priv) == MWIFIEX_BSS_ROLE_UAP &&
-           (params->cipher == WLAN_CIPHER_SUITE_WEP40 ||
-            params->cipher == WLAN_CIPHER_SUITE_WEP104)) {
-               if (params->key && params->key_len) {
-                       wep_key = &priv->wep_key[key_index];
-                       memset(wep_key, 0, sizeof(struct mwifiex_wep_key));
-                       memcpy(wep_key->key_material, params->key,
-                              params->key_len);
-                       wep_key->key_index = key_index;
-                       wep_key->key_length = params->key_len;
-                       priv->sec_info.wep_enabled = 1;
-               }
-               return 0;
-       }
-
-       if (mwifiex_set_encode(priv, params, params->key, params->key_len,
-                              key_index, peer_mac, 0)) {
-               mwifiex_dbg(priv->adapter, ERROR, "crypto keys added\n");
-               return -EFAULT;
-       }
-
-       return 0;
-}
-
-/*
- * This function sends domain information to the firmware.
- *
- * The following information are passed to the firmware -
- *      - Country codes
- *      - Sub bands (first channel, number of channels, maximum Tx power)
- */
-int mwifiex_send_domain_info_cmd_fw(struct wiphy *wiphy)
-{
-       u8 no_of_triplet = 0;
-       struct ieee80211_country_ie_triplet *t;
-       u8 no_of_parsed_chan = 0;
-       u8 first_chan = 0, next_chan = 0, max_pwr = 0;
-       u8 i, flag = 0;
-       enum ieee80211_band band;
-       struct ieee80211_supported_band *sband;
-       struct ieee80211_channel *ch;
-       struct mwifiex_adapter *adapter = mwifiex_cfg80211_get_adapter(wiphy);
-       struct mwifiex_private *priv;
-       struct mwifiex_802_11d_domain_reg *domain_info = &adapter->domain_reg;
-
-       /* Set country code */
-       domain_info->country_code[0] = adapter->country_code[0];
-       domain_info->country_code[1] = adapter->country_code[1];
-       domain_info->country_code[2] = ' ';
-
-       band = mwifiex_band_to_radio_type(adapter->config_bands);
-       if (!wiphy->bands[band]) {
-               mwifiex_dbg(adapter, ERROR,
-                           "11D: setting domain info in FW\n");
-               return -1;
-       }
-
-       sband = wiphy->bands[band];
-
-       for (i = 0; i < sband->n_channels ; i++) {
-               ch = &sband->channels[i];
-               if (ch->flags & IEEE80211_CHAN_DISABLED)
-                       continue;
-
-               if (!flag) {
-                       flag = 1;
-                       first_chan = (u32) ch->hw_value;
-                       next_chan = first_chan;
-                       max_pwr = ch->max_power;
-                       no_of_parsed_chan = 1;
-                       continue;
-               }
-
-               if (ch->hw_value == next_chan + 1 &&
-                   ch->max_power == max_pwr) {
-                       next_chan++;
-                       no_of_parsed_chan++;
-               } else {
-                       t = &domain_info->triplet[no_of_triplet];
-                       t->chans.first_channel = first_chan;
-                       t->chans.num_channels = no_of_parsed_chan;
-                       t->chans.max_power = max_pwr;
-                       no_of_triplet++;
-                       first_chan = (u32) ch->hw_value;
-                       next_chan = first_chan;
-                       max_pwr = ch->max_power;
-                       no_of_parsed_chan = 1;
-               }
-       }
-
-       if (flag) {
-               t = &domain_info->triplet[no_of_triplet];
-               t->chans.first_channel = first_chan;
-               t->chans.num_channels = no_of_parsed_chan;
-               t->chans.max_power = max_pwr;
-               no_of_triplet++;
-       }
-
-       domain_info->no_of_triplet = no_of_triplet;
-
-       priv = mwifiex_get_priv(adapter, MWIFIEX_BSS_ROLE_ANY);
-
-       if (mwifiex_send_cmd(priv, HostCmd_CMD_802_11D_DOMAIN_INFO,
-                            HostCmd_ACT_GEN_SET, 0, NULL, false)) {
-               mwifiex_dbg(adapter, INFO,
-                           "11D: setting domain info in FW\n");
-               return -1;
-       }
-
-       return 0;
-}
-
-/*
- * CFG802.11 regulatory domain callback function.
- *
- * This function is called when the regulatory domain is changed due to the
- * following reasons -
- *      - Set by driver
- *      - Set by system core
- *      - Set by user
- *      - Set bt Country IE
- */
-static void mwifiex_reg_notifier(struct wiphy *wiphy,
-                                struct regulatory_request *request)
-{
-       struct mwifiex_adapter *adapter = mwifiex_cfg80211_get_adapter(wiphy);
-       struct mwifiex_private *priv = mwifiex_get_priv(adapter,
-                                                       MWIFIEX_BSS_ROLE_ANY);
-       mwifiex_dbg(adapter, INFO,
-                   "info: cfg80211 regulatory domain callback for %c%c\n",
-                   request->alpha2[0], request->alpha2[1]);
-
-       switch (request->initiator) {
-       case NL80211_REGDOM_SET_BY_DRIVER:
-       case NL80211_REGDOM_SET_BY_CORE:
-       case NL80211_REGDOM_SET_BY_USER:
-       case NL80211_REGDOM_SET_BY_COUNTRY_IE:
-               break;
-       default:
-               mwifiex_dbg(adapter, ERROR,
-                           "unknown regdom initiator: %d\n",
-                           request->initiator);
-               return;
-       }
-
-       /* Don't send world or same regdom info to firmware */
-       if (strncmp(request->alpha2, "00", 2) &&
-           strncmp(request->alpha2, adapter->country_code,
-                   sizeof(request->alpha2))) {
-               memcpy(adapter->country_code, request->alpha2,
-                      sizeof(request->alpha2));
-               mwifiex_send_domain_info_cmd_fw(wiphy);
-               mwifiex_dnld_txpwr_table(priv);
-       }
-}
-
-/*
- * This function sets the fragmentation threshold.
- *
- * The fragmentation threshold value must lie between MWIFIEX_FRAG_MIN_VALUE
- * and MWIFIEX_FRAG_MAX_VALUE.
- */
-static int
-mwifiex_set_frag(struct mwifiex_private *priv, u32 frag_thr)
-{
-       if (frag_thr < MWIFIEX_FRAG_MIN_VALUE ||
-           frag_thr > MWIFIEX_FRAG_MAX_VALUE)
-               frag_thr = MWIFIEX_FRAG_MAX_VALUE;
-
-       return mwifiex_send_cmd(priv, HostCmd_CMD_802_11_SNMP_MIB,
-                               HostCmd_ACT_GEN_SET, FRAG_THRESH_I,
-                               &frag_thr, true);
-}
-
-/*
- * This function sets the RTS threshold.
-
- * The rts value must lie between MWIFIEX_RTS_MIN_VALUE
- * and MWIFIEX_RTS_MAX_VALUE.
- */
-static int
-mwifiex_set_rts(struct mwifiex_private *priv, u32 rts_thr)
-{
-       if (rts_thr < MWIFIEX_RTS_MIN_VALUE || rts_thr > MWIFIEX_RTS_MAX_VALUE)
-               rts_thr = MWIFIEX_RTS_MAX_VALUE;
-
-       return mwifiex_send_cmd(priv, HostCmd_CMD_802_11_SNMP_MIB,
-                               HostCmd_ACT_GEN_SET, RTS_THRESH_I,
-                               &rts_thr, true);
-}
-
-/*
- * CFG802.11 operation handler to set wiphy parameters.
- *
- * This function can be used to set the RTS threshold and the
- * Fragmentation threshold of the driver.
- */
-static int
-mwifiex_cfg80211_set_wiphy_params(struct wiphy *wiphy, u32 changed)
-{
-       struct mwifiex_adapter *adapter = mwifiex_cfg80211_get_adapter(wiphy);
-       struct mwifiex_private *priv;
-       struct mwifiex_uap_bss_param *bss_cfg;
-       int ret;
-
-       priv = mwifiex_get_priv(adapter, MWIFIEX_BSS_ROLE_ANY);
-
-       switch (priv->bss_role) {
-       case MWIFIEX_BSS_ROLE_UAP:
-               if (priv->bss_started) {
-                       mwifiex_dbg(adapter, ERROR,
-                                   "cannot change wiphy params when bss started");
-                       return -EINVAL;
-               }
-
-               bss_cfg = kzalloc(sizeof(*bss_cfg), GFP_KERNEL);
-               if (!bss_cfg)
-                       return -ENOMEM;
-
-               mwifiex_set_sys_config_invalid_data(bss_cfg);
-
-               if (changed & WIPHY_PARAM_RTS_THRESHOLD)
-                       bss_cfg->rts_threshold = wiphy->rts_threshold;
-               if (changed & WIPHY_PARAM_FRAG_THRESHOLD)
-                       bss_cfg->frag_threshold = wiphy->frag_threshold;
-               if (changed & WIPHY_PARAM_RETRY_LONG)
-                       bss_cfg->retry_limit = wiphy->retry_long;
-
-               ret = mwifiex_send_cmd(priv, HostCmd_CMD_UAP_SYS_CONFIG,
-                                      HostCmd_ACT_GEN_SET,
-                                      UAP_BSS_PARAMS_I, bss_cfg,
-                                      false);
-
-               kfree(bss_cfg);
-               if (ret) {
-                       mwifiex_dbg(adapter, ERROR,
-                                   "Failed to set wiphy phy params\n");
-                       return ret;
-               }
-               break;
-
-               case MWIFIEX_BSS_ROLE_STA:
-               if (priv->media_connected) {
-                       mwifiex_dbg(adapter, ERROR,
-                                   "cannot change wiphy params when connected");
-                       return -EINVAL;
-               }
-               if (changed & WIPHY_PARAM_RTS_THRESHOLD) {
-                       ret = mwifiex_set_rts(priv,
-                                             wiphy->rts_threshold);
-                       if (ret)
-                               return ret;
-               }
-               if (changed & WIPHY_PARAM_FRAG_THRESHOLD) {
-                       ret = mwifiex_set_frag(priv,
-                                              wiphy->frag_threshold);
-                       if (ret)
-                               return ret;
-               }
-               break;
-       }
-
-       return 0;
-}
-
-static int
-mwifiex_cfg80211_deinit_p2p(struct mwifiex_private *priv)
-{
-       u16 mode = P2P_MODE_DISABLE;
-
-       if (mwifiex_send_cmd(priv, HostCmd_CMD_P2P_MODE_CFG,
-                            HostCmd_ACT_GEN_SET, 0, &mode, true))
-               return -1;
-
-       return 0;
-}
-
-/*
- * This function initializes the functionalities for P2P client.
- * The P2P client initialization sequence is:
- * disable -> device -> client
- */
-static int
-mwifiex_cfg80211_init_p2p_client(struct mwifiex_private *priv)
-{
-       u16 mode;
-
-       if (mwifiex_cfg80211_deinit_p2p(priv))
-               return -1;
-
-       mode = P2P_MODE_DEVICE;
-       if (mwifiex_send_cmd(priv, HostCmd_CMD_P2P_MODE_CFG,
-                            HostCmd_ACT_GEN_SET, 0, &mode, true))
-               return -1;
-
-       mode = P2P_MODE_CLIENT;
-       if (mwifiex_send_cmd(priv, HostCmd_CMD_P2P_MODE_CFG,
-                            HostCmd_ACT_GEN_SET, 0, &mode, true))
-               return -1;
-
-       return 0;
-}
-
-/*
- * This function initializes the functionalities for P2P GO.
- * The P2P GO initialization sequence is:
- * disable -> device -> GO
- */
-static int
-mwifiex_cfg80211_init_p2p_go(struct mwifiex_private *priv)
-{
-       u16 mode;
-
-       if (mwifiex_cfg80211_deinit_p2p(priv))
-               return -1;
-
-       mode = P2P_MODE_DEVICE;
-       if (mwifiex_send_cmd(priv, HostCmd_CMD_P2P_MODE_CFG,
-                            HostCmd_ACT_GEN_SET, 0, &mode, true))
-               return -1;
-
-       mode = P2P_MODE_GO;
-       if (mwifiex_send_cmd(priv, HostCmd_CMD_P2P_MODE_CFG,
-                            HostCmd_ACT_GEN_SET, 0, &mode, true))
-               return -1;
-
-       return 0;
-}
-
-static int mwifiex_deinit_priv_params(struct mwifiex_private *priv)
-{
-       struct mwifiex_adapter *adapter = priv->adapter;
-       unsigned long flags;
-
-       priv->mgmt_frame_mask = 0;
-       if (mwifiex_send_cmd(priv, HostCmd_CMD_MGMT_FRAME_REG,
-                            HostCmd_ACT_GEN_SET, 0,
-                            &priv->mgmt_frame_mask, false)) {
-               mwifiex_dbg(adapter, ERROR,
-                           "could not unregister mgmt frame rx\n");
-               return -1;
-       }
-
-       mwifiex_deauthenticate(priv, NULL);
-
-       spin_lock_irqsave(&adapter->main_proc_lock, flags);
-       adapter->main_locked = true;
-       if (adapter->mwifiex_processing) {
-               spin_unlock_irqrestore(&adapter->main_proc_lock, flags);
-               flush_workqueue(adapter->workqueue);
-       } else {
-               spin_unlock_irqrestore(&adapter->main_proc_lock, flags);
-       }
-
-       spin_lock_irqsave(&adapter->rx_proc_lock, flags);
-       adapter->rx_locked = true;
-       if (adapter->rx_processing) {
-               spin_unlock_irqrestore(&adapter->rx_proc_lock, flags);
-               flush_workqueue(adapter->rx_workqueue);
-       } else {
-       spin_unlock_irqrestore(&adapter->rx_proc_lock, flags);
-       }
-
-       mwifiex_free_priv(priv);
-       priv->wdev.iftype = NL80211_IFTYPE_UNSPECIFIED;
-       priv->bss_mode = NL80211_IFTYPE_UNSPECIFIED;
-       priv->sec_info.authentication_mode = NL80211_AUTHTYPE_OPEN_SYSTEM;
-
-       return 0;
-}
-
-static int
-mwifiex_init_new_priv_params(struct mwifiex_private *priv,
-                            struct net_device *dev,
-                            enum nl80211_iftype type)
-{
-       struct mwifiex_adapter *adapter = priv->adapter;
-       unsigned long flags;
-
-       mwifiex_init_priv(priv);
-
-       priv->bss_mode = type;
-       priv->wdev.iftype = type;
-
-       mwifiex_init_priv_params(priv, priv->netdev);
-       priv->bss_started = 0;
-
-       switch (type) {
-       case NL80211_IFTYPE_STATION:
-       case NL80211_IFTYPE_ADHOC:
-               priv->bss_role =  MWIFIEX_BSS_ROLE_STA;
-               priv->bss_type = MWIFIEX_BSS_TYPE_STA;
-               break;
-       case NL80211_IFTYPE_P2P_CLIENT:
-               priv->bss_role =  MWIFIEX_BSS_ROLE_STA;
-               priv->bss_type = MWIFIEX_BSS_TYPE_P2P;
-               break;
-       case NL80211_IFTYPE_P2P_GO:
-               priv->bss_role =  MWIFIEX_BSS_ROLE_UAP;
-               priv->bss_type = MWIFIEX_BSS_TYPE_P2P;
-               break;
-       case NL80211_IFTYPE_AP:
-               priv->bss_type = MWIFIEX_BSS_TYPE_UAP;
-               priv->bss_role = MWIFIEX_BSS_ROLE_UAP;
-               break;
-       default:
-               mwifiex_dbg(adapter, ERROR,
-                           "%s: changing to %d not supported\n",
-                           dev->name, type);
-               return -EOPNOTSUPP;
-       }
-
-       spin_lock_irqsave(&adapter->main_proc_lock, flags);
-       adapter->main_locked = false;
-       spin_unlock_irqrestore(&adapter->main_proc_lock, flags);
-
-       spin_lock_irqsave(&adapter->rx_proc_lock, flags);
-       adapter->rx_locked = false;
-       spin_unlock_irqrestore(&adapter->rx_proc_lock, flags);
-
-       return 0;
-}
-
-static int
-mwifiex_change_vif_to_p2p(struct net_device *dev,
-                         enum nl80211_iftype curr_iftype,
-                         enum nl80211_iftype type, u32 *flags,
-                         struct vif_params *params)
-{
-       struct mwifiex_private *priv;
-       struct mwifiex_adapter *adapter;
-
-       priv = mwifiex_netdev_get_priv(dev);
-
-       if (!priv)
-               return -1;
-
-       adapter = priv->adapter;
-
-       if (adapter->curr_iface_comb.p2p_intf ==
-           adapter->iface_limit.p2p_intf) {
-               mwifiex_dbg(adapter, ERROR,
-                           "cannot create multiple P2P ifaces\n");
-               return -1;
-       }
-
-       mwifiex_dbg(adapter, INFO,
-                   "%s: changing role to p2p\n", dev->name);
-
-       if (mwifiex_deinit_priv_params(priv))
-               return -1;
-       if (mwifiex_init_new_priv_params(priv, dev, type))
-               return -1;
-
-       switch (type) {
-       case NL80211_IFTYPE_P2P_CLIENT:
-               if (mwifiex_cfg80211_init_p2p_client(priv))
-                       return -EFAULT;
-               break;
-       case NL80211_IFTYPE_P2P_GO:
-               if (mwifiex_cfg80211_init_p2p_go(priv))
-                       return -EFAULT;
-               break;
-       default:
-               mwifiex_dbg(adapter, ERROR,
-                           "%s: changing to %d not supported\n",
-                           dev->name, type);
-               return -EOPNOTSUPP;
-       }
-
-       if (mwifiex_send_cmd(priv, HostCmd_CMD_SET_BSS_MODE,
-                            HostCmd_ACT_GEN_SET, 0, NULL, true))
-               return -1;
-
-       if (mwifiex_sta_init_cmd(priv, false, false))
-               return -1;
-
-       switch (curr_iftype) {
-       case NL80211_IFTYPE_STATION:
-       case NL80211_IFTYPE_ADHOC:
-               adapter->curr_iface_comb.sta_intf--;
-               break;
-       case NL80211_IFTYPE_AP:
-               adapter->curr_iface_comb.uap_intf--;
-               break;
-       default:
-               break;
-       }
-
-       adapter->curr_iface_comb.p2p_intf++;
-       dev->ieee80211_ptr->iftype = type;
-
-       return 0;
-}
-
-static int
-mwifiex_change_vif_to_sta_adhoc(struct net_device *dev,
-                               enum nl80211_iftype curr_iftype,
-                               enum nl80211_iftype type, u32 *flags,
-                               struct vif_params *params)
-{
-       struct mwifiex_private *priv;
-       struct mwifiex_adapter *adapter;
-
-       priv = mwifiex_netdev_get_priv(dev);
-
-       if (!priv)
-               return -1;
-
-       adapter = priv->adapter;
-
-       if ((curr_iftype != NL80211_IFTYPE_P2P_CLIENT &&
-            curr_iftype != NL80211_IFTYPE_P2P_GO) &&
-           (adapter->curr_iface_comb.sta_intf ==
-            adapter->iface_limit.sta_intf)) {
-               mwifiex_dbg(adapter, ERROR,
-                           "cannot create multiple station/adhoc ifaces\n");
-               return -1;
-       }
-
-       if (type == NL80211_IFTYPE_STATION)
-               mwifiex_dbg(adapter, INFO,
-                           "%s: changing role to station\n", dev->name);
-       else
-               mwifiex_dbg(adapter, INFO,
-                           "%s: changing role to adhoc\n", dev->name);
-
-       if (mwifiex_deinit_priv_params(priv))
-               return -1;
-       if (mwifiex_init_new_priv_params(priv, dev, type))
-               return -1;
-       if (mwifiex_send_cmd(priv, HostCmd_CMD_SET_BSS_MODE,
-                            HostCmd_ACT_GEN_SET, 0, NULL, true))
-               return -1;
-       if (mwifiex_sta_init_cmd(priv, false, false))
-               return -1;
-
-       switch (curr_iftype) {
-       case NL80211_IFTYPE_P2P_CLIENT:
-       case NL80211_IFTYPE_P2P_GO:
-               adapter->curr_iface_comb.p2p_intf--;
-               break;
-       case NL80211_IFTYPE_AP:
-               adapter->curr_iface_comb.uap_intf--;
-               break;
-       default:
-               break;
-       }
-
-       adapter->curr_iface_comb.sta_intf++;
-       dev->ieee80211_ptr->iftype = type;
-       return 0;
-}
-
-static int
-mwifiex_change_vif_to_ap(struct net_device *dev,
-                        enum nl80211_iftype curr_iftype,
-                        enum nl80211_iftype type, u32 *flags,
-                        struct vif_params *params)
-{
-       struct mwifiex_private *priv;
-       struct mwifiex_adapter *adapter;
-
-       priv = mwifiex_netdev_get_priv(dev);
-
-       if (!priv)
-               return -1;
-
-       adapter = priv->adapter;
-
-       if (adapter->curr_iface_comb.uap_intf ==
-           adapter->iface_limit.uap_intf) {
-               mwifiex_dbg(adapter, ERROR,
-                           "cannot create multiple AP ifaces\n");
-               return -1;
-       }
-
-       mwifiex_dbg(adapter, INFO,
-                   "%s: changing role to AP\n", dev->name);
-
-       if (mwifiex_deinit_priv_params(priv))
-               return -1;
-       if (mwifiex_init_new_priv_params(priv, dev, type))
-               return -1;
-       if (mwifiex_send_cmd(priv, HostCmd_CMD_SET_BSS_MODE,
-                            HostCmd_ACT_GEN_SET, 0, NULL, true))
-               return -1;
-       if (mwifiex_sta_init_cmd(priv, false, false))
-               return -1;
-
-       switch (curr_iftype) {
-       case NL80211_IFTYPE_P2P_CLIENT:
-       case NL80211_IFTYPE_P2P_GO:
-               adapter->curr_iface_comb.p2p_intf--;
-               break;
-       case NL80211_IFTYPE_STATION:
-       case NL80211_IFTYPE_ADHOC:
-               adapter->curr_iface_comb.sta_intf--;
-               break;
-       default:
-               break;
-       }
-
-       adapter->curr_iface_comb.uap_intf++;
-       dev->ieee80211_ptr->iftype = type;
-       return 0;
-}
-/*
- * CFG802.11 operation handler to change interface type.
- */
-static int
-mwifiex_cfg80211_change_virtual_intf(struct wiphy *wiphy,
-                                    struct net_device *dev,
-                                    enum nl80211_iftype type, u32 *flags,
-                                    struct vif_params *params)
-{
-       struct mwifiex_private *priv = mwifiex_netdev_get_priv(dev);
-       enum nl80211_iftype curr_iftype = dev->ieee80211_ptr->iftype;
-
-       switch (curr_iftype) {
-       case NL80211_IFTYPE_ADHOC:
-               switch (type) {
-               case NL80211_IFTYPE_STATION:
-                       priv->bss_mode = type;
-                       priv->sec_info.authentication_mode =
-                                                  NL80211_AUTHTYPE_OPEN_SYSTEM;
-                       dev->ieee80211_ptr->iftype = type;
-                       mwifiex_deauthenticate(priv, NULL);
-                       return mwifiex_send_cmd(priv, HostCmd_CMD_SET_BSS_MODE,
-                                               HostCmd_ACT_GEN_SET, 0, NULL,
-                                               true);
-               case NL80211_IFTYPE_P2P_CLIENT:
-               case NL80211_IFTYPE_P2P_GO:
-                       return mwifiex_change_vif_to_p2p(dev, curr_iftype,
-                                                        type, flags, params);
-               case NL80211_IFTYPE_AP:
-                       return mwifiex_change_vif_to_ap(dev, curr_iftype, type,
-                                                       flags, params);
-               case NL80211_IFTYPE_UNSPECIFIED:
-                       mwifiex_dbg(priv->adapter, INFO,
-                                   "%s: kept type as IBSS\n", dev->name);
-               case NL80211_IFTYPE_ADHOC:      /* This shouldn't happen */
-                       return 0;
-               default:
-                       mwifiex_dbg(priv->adapter, ERROR,
-                                   "%s: changing to %d not supported\n",
-                                   dev->name, type);
-                       return -EOPNOTSUPP;
-               }
-               break;
-       case NL80211_IFTYPE_STATION:
-               switch (type) {
-               case NL80211_IFTYPE_ADHOC:
-                       priv->bss_mode = type;
-                       priv->sec_info.authentication_mode =
-                                                  NL80211_AUTHTYPE_OPEN_SYSTEM;
-                       dev->ieee80211_ptr->iftype = type;
-                       mwifiex_deauthenticate(priv, NULL);
-                       return mwifiex_send_cmd(priv, HostCmd_CMD_SET_BSS_MODE,
-                                               HostCmd_ACT_GEN_SET, 0, NULL,
-                                               true);
-               case NL80211_IFTYPE_P2P_CLIENT:
-               case NL80211_IFTYPE_P2P_GO:
-                       return mwifiex_change_vif_to_p2p(dev, curr_iftype,
-                                                        type, flags, params);
-               case NL80211_IFTYPE_AP:
-                       return mwifiex_change_vif_to_ap(dev, curr_iftype, type,
-                                                       flags, params);
-               case NL80211_IFTYPE_UNSPECIFIED:
-                       mwifiex_dbg(priv->adapter, INFO,
-                                   "%s: kept type as STA\n", dev->name);
-               case NL80211_IFTYPE_STATION:    /* This shouldn't happen */
-                       return 0;
-               default:
-                       mwifiex_dbg(priv->adapter, ERROR,
-                                   "%s: changing to %d not supported\n",
-                                   dev->name, type);
-                       return -EOPNOTSUPP;
-               }
-               break;
-       case NL80211_IFTYPE_AP:
-               switch (type) {
-               case NL80211_IFTYPE_ADHOC:
-               case NL80211_IFTYPE_STATION:
-                       return mwifiex_change_vif_to_sta_adhoc(dev, curr_iftype,
-                                                              type, flags,
-                                                              params);
-                       break;
-               case NL80211_IFTYPE_P2P_CLIENT:
-               case NL80211_IFTYPE_P2P_GO:
-                       return mwifiex_change_vif_to_p2p(dev, curr_iftype,
-                                                        type, flags, params);
-               case NL80211_IFTYPE_UNSPECIFIED:
-                       mwifiex_dbg(priv->adapter, INFO,
-                                   "%s: kept type as AP\n", dev->name);
-               case NL80211_IFTYPE_AP:         /* This shouldn't happen */
-                       return 0;
-               default:
-                       mwifiex_dbg(priv->adapter, ERROR,
-                                   "%s: changing to %d not supported\n",
-                                   dev->name, type);
-                       return -EOPNOTSUPP;
-               }
-               break;
-       case NL80211_IFTYPE_P2P_CLIENT:
-       case NL80211_IFTYPE_P2P_GO:
-               switch (type) {
-               case NL80211_IFTYPE_STATION:
-                       if (mwifiex_cfg80211_deinit_p2p(priv))
-                               return -EFAULT;
-                       priv->adapter->curr_iface_comb.p2p_intf--;
-                       priv->adapter->curr_iface_comb.sta_intf++;
-                       dev->ieee80211_ptr->iftype = type;
-                       break;
-               case NL80211_IFTYPE_ADHOC:
-                       if (mwifiex_cfg80211_deinit_p2p(priv))
-                               return -EFAULT;
-                       return mwifiex_change_vif_to_sta_adhoc(dev, curr_iftype,
-                                                              type, flags,
-                                                              params);
-                       break;
-               case NL80211_IFTYPE_AP:
-                       if (mwifiex_cfg80211_deinit_p2p(priv))
-                               return -EFAULT;
-                       return mwifiex_change_vif_to_ap(dev, curr_iftype, type,
-                                                       flags, params);
-               case NL80211_IFTYPE_UNSPECIFIED:
-                       mwifiex_dbg(priv->adapter, INFO,
-                                   "%s: kept type as P2P\n", dev->name);
-               case NL80211_IFTYPE_P2P_CLIENT:
-               case NL80211_IFTYPE_P2P_GO:
-                       return 0;
-               default:
-                       mwifiex_dbg(priv->adapter, ERROR,
-                                   "%s: changing to %d not supported\n",
-                                   dev->name, type);
-                       return -EOPNOTSUPP;
-               }
-               break;
-       default:
-               mwifiex_dbg(priv->adapter, ERROR,
-                           "%s: unknown iftype: %d\n",
-                           dev->name, dev->ieee80211_ptr->iftype);
-               return -EOPNOTSUPP;
-       }
-
-
-       return 0;
-}
-
-static void
-mwifiex_parse_htinfo(struct mwifiex_private *priv, u8 tx_htinfo,
-                    struct rate_info *rate)
-{
-       struct mwifiex_adapter *adapter = priv->adapter;
-
-       if (adapter->is_hw_11ac_capable) {
-               /* bit[1-0]: 00=LG 01=HT 10=VHT */
-               if (tx_htinfo & BIT(0)) {
-                       /* HT */
-                       rate->mcs = priv->tx_rate;
-                       rate->flags |= RATE_INFO_FLAGS_MCS;
-               }
-               if (tx_htinfo & BIT(1)) {
-                       /* VHT */
-                       rate->mcs = priv->tx_rate & 0x0F;
-                       rate->flags |= RATE_INFO_FLAGS_VHT_MCS;
-               }
-
-               if (tx_htinfo & (BIT(1) | BIT(0))) {
-                       /* HT or VHT */
-                       switch (tx_htinfo & (BIT(3) | BIT(2))) {
-                       case 0:
-                               rate->bw = RATE_INFO_BW_20;
-                               break;
-                       case (BIT(2)):
-                               rate->bw = RATE_INFO_BW_40;
-                               break;
-                       case (BIT(3)):
-                               rate->bw = RATE_INFO_BW_80;
-                               break;
-                       case (BIT(3) | BIT(2)):
-                               rate->bw = RATE_INFO_BW_160;
-                               break;
-                       }
-
-                       if (tx_htinfo & BIT(4))
-                               rate->flags |= RATE_INFO_FLAGS_SHORT_GI;
-
-                       if ((priv->tx_rate >> 4) == 1)
-                               rate->nss = 2;
-                       else
-                               rate->nss = 1;
-               }
-       } else {
-               /*
-                * Bit 0 in tx_htinfo indicates that current Tx rate
-                * is 11n rate. Valid MCS index values for us are 0 to 15.
-                */
-               if ((tx_htinfo & BIT(0)) && (priv->tx_rate < 16)) {
-                       rate->mcs = priv->tx_rate;
-                       rate->flags |= RATE_INFO_FLAGS_MCS;
-                       rate->bw = RATE_INFO_BW_20;
-                       if (tx_htinfo & BIT(1))
-                               rate->bw = RATE_INFO_BW_40;
-                       if (tx_htinfo & BIT(2))
-                               rate->flags |= RATE_INFO_FLAGS_SHORT_GI;
-               }
-       }
-}
-
-/*
- * This function dumps the station information on a buffer.
- *
- * The following information are shown -
- *      - Total bytes transmitted
- *      - Total bytes received
- *      - Total packets transmitted
- *      - Total packets received
- *      - Signal quality level
- *      - Transmission rate
- */
-static int
-mwifiex_dump_station_info(struct mwifiex_private *priv,
-                         struct mwifiex_sta_node *node,
-                         struct station_info *sinfo)
-{
-       u32 rate;
-
-       sinfo->filled = BIT(NL80211_STA_INFO_RX_BYTES) | BIT(NL80211_STA_INFO_TX_BYTES) |
-                       BIT(NL80211_STA_INFO_RX_PACKETS) | BIT(NL80211_STA_INFO_TX_PACKETS) |
-                       BIT(NL80211_STA_INFO_TX_BITRATE) |
-                       BIT(NL80211_STA_INFO_SIGNAL) | BIT(NL80211_STA_INFO_SIGNAL_AVG);
-
-       if (GET_BSS_ROLE(priv) == MWIFIEX_BSS_ROLE_UAP) {
-               if (!node)
-                       return -ENOENT;
-
-               sinfo->filled |= BIT(NL80211_STA_INFO_INACTIVE_TIME) |
-                               BIT(NL80211_STA_INFO_TX_FAILED);
-               sinfo->inactive_time =
-                       jiffies_to_msecs(jiffies - node->stats.last_rx);
-
-               sinfo->signal = node->stats.rssi;
-               sinfo->signal_avg = node->stats.rssi;
-               sinfo->rx_bytes = node->stats.rx_bytes;
-               sinfo->tx_bytes = node->stats.tx_bytes;
-               sinfo->rx_packets = node->stats.rx_packets;
-               sinfo->tx_packets = node->stats.tx_packets;
-               sinfo->tx_failed = node->stats.tx_failed;
-
-               mwifiex_parse_htinfo(priv, node->stats.last_tx_htinfo,
-                                    &sinfo->txrate);
-               sinfo->txrate.legacy = node->stats.last_tx_rate * 5;
-
-               return 0;
-       }
-
-       /* Get signal information from the firmware */
-       if (mwifiex_send_cmd(priv, HostCmd_CMD_RSSI_INFO,
-                            HostCmd_ACT_GEN_GET, 0, NULL, true)) {
-               mwifiex_dbg(priv->adapter, ERROR,
-                           "failed to get signal information\n");
-               return -EFAULT;
-       }
-
-       if (mwifiex_drv_get_data_rate(priv, &rate)) {
-               mwifiex_dbg(priv->adapter, ERROR,
-                           "getting data rate error\n");
-               return -EFAULT;
-       }
-
-       /* Get DTIM period information from firmware */
-       mwifiex_send_cmd(priv, HostCmd_CMD_802_11_SNMP_MIB,
-                        HostCmd_ACT_GEN_GET, DTIM_PERIOD_I,
-                        &priv->dtim_period, true);
-
-       mwifiex_parse_htinfo(priv, priv->tx_htinfo, &sinfo->txrate);
-
-       sinfo->signal_avg = priv->bcn_rssi_avg;
-       sinfo->rx_bytes = priv->stats.rx_bytes;
-       sinfo->tx_bytes = priv->stats.tx_bytes;
-       sinfo->rx_packets = priv->stats.rx_packets;
-       sinfo->tx_packets = priv->stats.tx_packets;
-       sinfo->signal = priv->bcn_rssi_avg;
-       /* bit rate is in 500 kb/s units. Convert it to 100kb/s units */
-       sinfo->txrate.legacy = rate * 5;
-
-       if (priv->bss_mode == NL80211_IFTYPE_STATION) {
-               sinfo->filled |= BIT(NL80211_STA_INFO_BSS_PARAM);
-               sinfo->bss_param.flags = 0;
-               if (priv->curr_bss_params.bss_descriptor.cap_info_bitmap &
-                                               WLAN_CAPABILITY_SHORT_PREAMBLE)
-                       sinfo->bss_param.flags |=
-                                       BSS_PARAM_FLAGS_SHORT_PREAMBLE;
-               if (priv->curr_bss_params.bss_descriptor.cap_info_bitmap &
-                                               WLAN_CAPABILITY_SHORT_SLOT_TIME)
-                       sinfo->bss_param.flags |=
-                                       BSS_PARAM_FLAGS_SHORT_SLOT_TIME;
-               sinfo->bss_param.dtim_period = priv->dtim_period;
-               sinfo->bss_param.beacon_interval =
-                       priv->curr_bss_params.bss_descriptor.beacon_period;
-       }
-
-       return 0;
-}
-
-/*
- * CFG802.11 operation handler to get station information.
- *
- * This function only works in connected mode, and dumps the
- * requested station information, if available.
- */
-static int
-mwifiex_cfg80211_get_station(struct wiphy *wiphy, struct net_device *dev,
-                            const u8 *mac, struct station_info *sinfo)
-{
-       struct mwifiex_private *priv = mwifiex_netdev_get_priv(dev);
-
-       if (!priv->media_connected)
-               return -ENOENT;
-       if (memcmp(mac, priv->cfg_bssid, ETH_ALEN))
-               return -ENOENT;
-
-       return mwifiex_dump_station_info(priv, NULL, sinfo);
-}
-
-/*
- * CFG802.11 operation handler to dump station information.
- */
-static int
-mwifiex_cfg80211_dump_station(struct wiphy *wiphy, struct net_device *dev,
-                             int idx, u8 *mac, struct station_info *sinfo)
-{
-       struct mwifiex_private *priv = mwifiex_netdev_get_priv(dev);
-       static struct mwifiex_sta_node *node;
-
-       if ((GET_BSS_ROLE(priv) == MWIFIEX_BSS_ROLE_STA) &&
-           priv->media_connected && idx == 0) {
-               ether_addr_copy(mac, priv->cfg_bssid);
-               return mwifiex_dump_station_info(priv, NULL, sinfo);
-       } else if (GET_BSS_ROLE(priv) == MWIFIEX_BSS_ROLE_UAP) {
-               mwifiex_send_cmd(priv, HOST_CMD_APCMD_STA_LIST,
-                                HostCmd_ACT_GEN_GET, 0, NULL, true);
-
-               if (node && (&node->list == &priv->sta_list)) {
-                       node = NULL;
-                       return -ENOENT;
-               }
-
-               node = list_prepare_entry(node, &priv->sta_list, list);
-               list_for_each_entry_continue(node, &priv->sta_list, list) {
-                       ether_addr_copy(mac, node->mac_addr);
-                       return mwifiex_dump_station_info(priv, node, sinfo);
-               }
-       }
-
-       return -ENOENT;
-}
-
-static int
-mwifiex_cfg80211_dump_survey(struct wiphy *wiphy, struct net_device *dev,
-                            int idx, struct survey_info *survey)
-{
-       struct mwifiex_private *priv = mwifiex_netdev_get_priv(dev);
-       struct mwifiex_chan_stats *pchan_stats = priv->adapter->chan_stats;
-       enum ieee80211_band band;
-
-       mwifiex_dbg(priv->adapter, DUMP, "dump_survey idx=%d\n", idx);
-
-       memset(survey, 0, sizeof(struct survey_info));
-
-       if ((GET_BSS_ROLE(priv) == MWIFIEX_BSS_ROLE_STA) &&
-           priv->media_connected && idx == 0) {
-                       u8 curr_bss_band = priv->curr_bss_params.band;
-                       u32 chan = priv->curr_bss_params.bss_descriptor.channel;
-
-                       band = mwifiex_band_to_radio_type(curr_bss_band);
-                       survey->channel = ieee80211_get_channel(wiphy,
-                               ieee80211_channel_to_frequency(chan, band));
-
-                       if (priv->bcn_nf_last) {
-                               survey->filled = SURVEY_INFO_NOISE_DBM;
-                               survey->noise = priv->bcn_nf_last;
-                       }
-                       return 0;
-       }
-
-       if (idx >= priv->adapter->num_in_chan_stats)
-               return -ENOENT;
-
-       if (!pchan_stats[idx].cca_scan_dur)
-               return 0;
-
-       band = pchan_stats[idx].bandcfg;
-       survey->channel = ieee80211_get_channel(wiphy,
-           ieee80211_channel_to_frequency(pchan_stats[idx].chan_num, band));
-       survey->filled = SURVEY_INFO_NOISE_DBM |
-                        SURVEY_INFO_TIME |
-                        SURVEY_INFO_TIME_BUSY;
-       survey->noise = pchan_stats[idx].noise;
-       survey->time = pchan_stats[idx].cca_scan_dur;
-       survey->time_busy = pchan_stats[idx].cca_busy_dur;
-
-       return 0;
-}
-
-/* Supported rates to be advertised to the cfg80211 */
-static struct ieee80211_rate mwifiex_rates[] = {
-       {.bitrate = 10, .hw_value = 2, },
-       {.bitrate = 20, .hw_value = 4, },
-       {.bitrate = 55, .hw_value = 11, },
-       {.bitrate = 110, .hw_value = 22, },
-       {.bitrate = 60, .hw_value = 12, },
-       {.bitrate = 90, .hw_value = 18, },
-       {.bitrate = 120, .hw_value = 24, },
-       {.bitrate = 180, .hw_value = 36, },
-       {.bitrate = 240, .hw_value = 48, },
-       {.bitrate = 360, .hw_value = 72, },
-       {.bitrate = 480, .hw_value = 96, },
-       {.bitrate = 540, .hw_value = 108, },
-};
-
-/* Channel definitions to be advertised to cfg80211 */
-static struct ieee80211_channel mwifiex_channels_2ghz[] = {
-       {.center_freq = 2412, .hw_value = 1, },
-       {.center_freq = 2417, .hw_value = 2, },
-       {.center_freq = 2422, .hw_value = 3, },
-       {.center_freq = 2427, .hw_value = 4, },
-       {.center_freq = 2432, .hw_value = 5, },
-       {.center_freq = 2437, .hw_value = 6, },
-       {.center_freq = 2442, .hw_value = 7, },
-       {.center_freq = 2447, .hw_value = 8, },
-       {.center_freq = 2452, .hw_value = 9, },
-       {.center_freq = 2457, .hw_value = 10, },
-       {.center_freq = 2462, .hw_value = 11, },
-       {.center_freq = 2467, .hw_value = 12, },
-       {.center_freq = 2472, .hw_value = 13, },
-       {.center_freq = 2484, .hw_value = 14, },
-};
-
-static struct ieee80211_supported_band mwifiex_band_2ghz = {
-       .channels = mwifiex_channels_2ghz,
-       .n_channels = ARRAY_SIZE(mwifiex_channels_2ghz),
-       .bitrates = mwifiex_rates,
-       .n_bitrates = ARRAY_SIZE(mwifiex_rates),
-};
-
-static struct ieee80211_channel mwifiex_channels_5ghz[] = {
-       {.center_freq = 5040, .hw_value = 8, },
-       {.center_freq = 5060, .hw_value = 12, },
-       {.center_freq = 5080, .hw_value = 16, },
-       {.center_freq = 5170, .hw_value = 34, },
-       {.center_freq = 5190, .hw_value = 38, },
-       {.center_freq = 5210, .hw_value = 42, },
-       {.center_freq = 5230, .hw_value = 46, },
-       {.center_freq = 5180, .hw_value = 36, },
-       {.center_freq = 5200, .hw_value = 40, },
-       {.center_freq = 5220, .hw_value = 44, },
-       {.center_freq = 5240, .hw_value = 48, },
-       {.center_freq = 5260, .hw_value = 52, },
-       {.center_freq = 5280, .hw_value = 56, },
-       {.center_freq = 5300, .hw_value = 60, },
-       {.center_freq = 5320, .hw_value = 64, },
-       {.center_freq = 5500, .hw_value = 100, },
-       {.center_freq = 5520, .hw_value = 104, },
-       {.center_freq = 5540, .hw_value = 108, },
-       {.center_freq = 5560, .hw_value = 112, },
-       {.center_freq = 5580, .hw_value = 116, },
-       {.center_freq = 5600, .hw_value = 120, },
-       {.center_freq = 5620, .hw_value = 124, },
-       {.center_freq = 5640, .hw_value = 128, },
-       {.center_freq = 5660, .hw_value = 132, },
-       {.center_freq = 5680, .hw_value = 136, },
-       {.center_freq = 5700, .hw_value = 140, },
-       {.center_freq = 5745, .hw_value = 149, },
-       {.center_freq = 5765, .hw_value = 153, },
-       {.center_freq = 5785, .hw_value = 157, },
-       {.center_freq = 5805, .hw_value = 161, },
-       {.center_freq = 5825, .hw_value = 165, },
-};
-
-static struct ieee80211_supported_band mwifiex_band_5ghz = {
-       .channels = mwifiex_channels_5ghz,
-       .n_channels = ARRAY_SIZE(mwifiex_channels_5ghz),
-       .bitrates = mwifiex_rates + 4,
-       .n_bitrates = ARRAY_SIZE(mwifiex_rates) - 4,
-};
-
-
-/* Supported crypto cipher suits to be advertised to cfg80211 */
-static const u32 mwifiex_cipher_suites[] = {
-       WLAN_CIPHER_SUITE_WEP40,
-       WLAN_CIPHER_SUITE_WEP104,
-       WLAN_CIPHER_SUITE_TKIP,
-       WLAN_CIPHER_SUITE_CCMP,
-       WLAN_CIPHER_SUITE_AES_CMAC,
-};
-
-/* Supported mgmt frame types to be advertised to cfg80211 */
-static const struct ieee80211_txrx_stypes
-mwifiex_mgmt_stypes[NUM_NL80211_IFTYPES] = {
-       [NL80211_IFTYPE_STATION] = {
-               .tx = BIT(IEEE80211_STYPE_ACTION >> 4) |
-                     BIT(IEEE80211_STYPE_PROBE_RESP >> 4),
-               .rx = BIT(IEEE80211_STYPE_ACTION >> 4) |
-                     BIT(IEEE80211_STYPE_PROBE_REQ >> 4),
-       },
-       [NL80211_IFTYPE_AP] = {
-               .tx = BIT(IEEE80211_STYPE_ACTION >> 4) |
-                     BIT(IEEE80211_STYPE_PROBE_RESP >> 4),
-               .rx = BIT(IEEE80211_STYPE_ACTION >> 4) |
-                     BIT(IEEE80211_STYPE_PROBE_REQ >> 4),
-       },
-       [NL80211_IFTYPE_P2P_CLIENT] = {
-               .tx = BIT(IEEE80211_STYPE_ACTION >> 4) |
-                     BIT(IEEE80211_STYPE_PROBE_RESP >> 4),
-               .rx = BIT(IEEE80211_STYPE_ACTION >> 4) |
-                     BIT(IEEE80211_STYPE_PROBE_REQ >> 4),
-       },
-       [NL80211_IFTYPE_P2P_GO] = {
-               .tx = BIT(IEEE80211_STYPE_ACTION >> 4) |
-                     BIT(IEEE80211_STYPE_PROBE_RESP >> 4),
-               .rx = BIT(IEEE80211_STYPE_ACTION >> 4) |
-                     BIT(IEEE80211_STYPE_PROBE_REQ >> 4),
-       },
-};
-
-/*
- * CFG802.11 operation handler for setting bit rates.
- *
- * Function configures data rates to firmware using bitrate mask
- * provided by cfg80211.
- */
-static int mwifiex_cfg80211_set_bitrate_mask(struct wiphy *wiphy,
-                               struct net_device *dev,
-                               const u8 *peer,
-                               const struct cfg80211_bitrate_mask *mask)
-{
-       struct mwifiex_private *priv = mwifiex_netdev_get_priv(dev);
-       u16 bitmap_rates[MAX_BITMAP_RATES_SIZE];
-       enum ieee80211_band band;
-       struct mwifiex_adapter *adapter = priv->adapter;
-
-       if (!priv->media_connected) {
-               mwifiex_dbg(adapter, ERROR,
-                           "Can not set Tx data rate in disconnected state\n");
-               return -EINVAL;
-       }
-
-       band = mwifiex_band_to_radio_type(priv->curr_bss_params.band);
-
-       memset(bitmap_rates, 0, sizeof(bitmap_rates));
-
-       /* Fill HR/DSSS rates. */
-       if (band == IEEE80211_BAND_2GHZ)
-               bitmap_rates[0] = mask->control[band].legacy & 0x000f;
-
-       /* Fill OFDM rates */
-       if (band == IEEE80211_BAND_2GHZ)
-               bitmap_rates[1] = (mask->control[band].legacy & 0x0ff0) >> 4;
-       else
-               bitmap_rates[1] = mask->control[band].legacy;
-
-       /* Fill HT MCS rates */
-       bitmap_rates[2] = mask->control[band].ht_mcs[0];
-       if (adapter->hw_dev_mcs_support == HT_STREAM_2X2)
-               bitmap_rates[2] |= mask->control[band].ht_mcs[1] << 8;
-
-       /* Fill VHT MCS rates */
-       if (adapter->fw_api_ver == MWIFIEX_FW_V15) {
-               bitmap_rates[10] = mask->control[band].vht_mcs[0];
-               if (adapter->hw_dev_mcs_support == HT_STREAM_2X2)
-                       bitmap_rates[11] = mask->control[band].vht_mcs[1];
-       }
-
-       return mwifiex_send_cmd(priv, HostCmd_CMD_TX_RATE_CFG,
-                               HostCmd_ACT_GEN_SET, 0, bitmap_rates, true);
-}
-
-/*
- * CFG802.11 operation handler for connection quality monitoring.
- *
- * This function subscribes/unsubscribes HIGH_RSSI and LOW_RSSI
- * events to FW.
- */
-static int mwifiex_cfg80211_set_cqm_rssi_config(struct wiphy *wiphy,
-                                               struct net_device *dev,
-                                               s32 rssi_thold, u32 rssi_hyst)
-{
-       struct mwifiex_private *priv = mwifiex_netdev_get_priv(dev);
-       struct mwifiex_ds_misc_subsc_evt subsc_evt;
-
-       priv->cqm_rssi_thold = rssi_thold;
-       priv->cqm_rssi_hyst = rssi_hyst;
-
-       memset(&subsc_evt, 0x00, sizeof(struct mwifiex_ds_misc_subsc_evt));
-       subsc_evt.events = BITMASK_BCN_RSSI_LOW | BITMASK_BCN_RSSI_HIGH;
-
-       /* Subscribe/unsubscribe low and high rssi events */
-       if (rssi_thold && rssi_hyst) {
-               subsc_evt.action = HostCmd_ACT_BITWISE_SET;
-               subsc_evt.bcn_l_rssi_cfg.abs_value = abs(rssi_thold);
-               subsc_evt.bcn_h_rssi_cfg.abs_value = abs(rssi_thold);
-               subsc_evt.bcn_l_rssi_cfg.evt_freq = 1;
-               subsc_evt.bcn_h_rssi_cfg.evt_freq = 1;
-               return mwifiex_send_cmd(priv,
-                                       HostCmd_CMD_802_11_SUBSCRIBE_EVENT,
-                                       0, 0, &subsc_evt, true);
-       } else {
-               subsc_evt.action = HostCmd_ACT_BITWISE_CLR;
-               return mwifiex_send_cmd(priv,
-                                       HostCmd_CMD_802_11_SUBSCRIBE_EVENT,
-                                       0, 0, &subsc_evt, true);
-       }
-
-       return 0;
-}
-
-/* cfg80211 operation handler for change_beacon.
- * Function retrieves and sets modified management IEs to FW.
- */
-static int mwifiex_cfg80211_change_beacon(struct wiphy *wiphy,
-                                         struct net_device *dev,
-                                         struct cfg80211_beacon_data *data)
-{
-       struct mwifiex_private *priv = mwifiex_netdev_get_priv(dev);
-
-       if (GET_BSS_ROLE(priv) != MWIFIEX_BSS_ROLE_UAP) {
-               mwifiex_dbg(priv->adapter, ERROR,
-                           "%s: bss_type mismatched\n", __func__);
-               return -EINVAL;
-       }
-
-       if (!priv->bss_started) {
-               mwifiex_dbg(priv->adapter, ERROR,
-                           "%s: bss not started\n", __func__);
-               return -EINVAL;
-       }
-
-       if (mwifiex_set_mgmt_ies(priv, data)) {
-               mwifiex_dbg(priv->adapter, ERROR,
-                           "%s: setting mgmt ies failed\n", __func__);
-               return -EFAULT;
-       }
-
-       return 0;
-}
-
-/* cfg80211 operation handler for del_station.
- * Function deauthenticates station which value is provided in mac parameter.
- * If mac is NULL/broadcast, all stations in associated station list are
- * deauthenticated. If bss is not started or there are no stations in
- * associated stations list, no action is taken.
- */
-static int
-mwifiex_cfg80211_del_station(struct wiphy *wiphy, struct net_device *dev,
-                            struct station_del_parameters *params)
-{
-       struct mwifiex_private *priv = mwifiex_netdev_get_priv(dev);
-       struct mwifiex_sta_node *sta_node;
-       u8 deauth_mac[ETH_ALEN];
-       unsigned long flags;
-
-       if (list_empty(&priv->sta_list) || !priv->bss_started)
-               return 0;
-
-       if (!params->mac || is_broadcast_ether_addr(params->mac))
-               return 0;
-
-       mwifiex_dbg(priv->adapter, INFO, "%s: mac address %pM\n",
-                   __func__, params->mac);
-
-       eth_zero_addr(deauth_mac);
-
-       spin_lock_irqsave(&priv->sta_list_spinlock, flags);
-       sta_node = mwifiex_get_sta_entry(priv, params->mac);
-       if (sta_node)
-               ether_addr_copy(deauth_mac, params->mac);
-       spin_unlock_irqrestore(&priv->sta_list_spinlock, flags);
-
-       if (is_valid_ether_addr(deauth_mac)) {
-               if (mwifiex_send_cmd(priv, HostCmd_CMD_UAP_STA_DEAUTH,
-                                    HostCmd_ACT_GEN_SET, 0,
-                                    deauth_mac, true))
-                       return -1;
-       }
-
-       return 0;
-}
-
-static int
-mwifiex_cfg80211_set_antenna(struct wiphy *wiphy, u32 tx_ant, u32 rx_ant)
-{
-       struct mwifiex_adapter *adapter = mwifiex_cfg80211_get_adapter(wiphy);
-       struct mwifiex_private *priv = mwifiex_get_priv(adapter,
-                                                       MWIFIEX_BSS_ROLE_ANY);
-       struct mwifiex_ds_ant_cfg ant_cfg;
-
-       if (!tx_ant || !rx_ant)
-               return -EOPNOTSUPP;
-
-       if (adapter->hw_dev_mcs_support != HT_STREAM_2X2) {
-               /* Not a MIMO chip. User should provide specific antenna number
-                * for Tx/Rx path or enable all antennas for diversity
-                */
-               if (tx_ant != rx_ant)
-                       return -EOPNOTSUPP;
-
-               if ((tx_ant & (tx_ant - 1)) &&
-                   (tx_ant != BIT(adapter->number_of_antenna) - 1))
-                       return -EOPNOTSUPP;
-
-               if ((tx_ant == BIT(adapter->number_of_antenna) - 1) &&
-                   (priv->adapter->number_of_antenna > 1)) {
-                       tx_ant = RF_ANTENNA_AUTO;
-                       rx_ant = RF_ANTENNA_AUTO;
-               }
-       } else {
-               struct ieee80211_sta_ht_cap *ht_info;
-               int rx_mcs_supp;
-               enum ieee80211_band band;
-
-               if ((tx_ant == 0x1 && rx_ant == 0x1)) {
-                       adapter->user_dev_mcs_support = HT_STREAM_1X1;
-                       if (adapter->is_hw_11ac_capable)
-                               adapter->usr_dot_11ac_mcs_support =
-                                               MWIFIEX_11AC_MCS_MAP_1X1;
-               } else {
-                       adapter->user_dev_mcs_support = HT_STREAM_2X2;
-                       if (adapter->is_hw_11ac_capable)
-                               adapter->usr_dot_11ac_mcs_support =
-                                               MWIFIEX_11AC_MCS_MAP_2X2;
-               }
-
-               for (band = 0; band < IEEE80211_NUM_BANDS; band++) {
-                       if (!adapter->wiphy->bands[band])
-                               continue;
-
-                       ht_info = &adapter->wiphy->bands[band]->ht_cap;
-                       rx_mcs_supp =
-                               GET_RXMCSSUPP(adapter->user_dev_mcs_support);
-                       memset(&ht_info->mcs, 0, adapter->number_of_antenna);
-                       memset(&ht_info->mcs, 0xff, rx_mcs_supp);
-               }
-       }
-
-       ant_cfg.tx_ant = tx_ant;
-       ant_cfg.rx_ant = rx_ant;
-
-       return mwifiex_send_cmd(priv, HostCmd_CMD_RF_ANTENNA,
-                               HostCmd_ACT_GEN_SET, 0, &ant_cfg, true);
-}
-
-/* cfg80211 operation handler for stop ap.
- * Function stops BSS running at uAP interface.
- */
-static int mwifiex_cfg80211_stop_ap(struct wiphy *wiphy, struct net_device *dev)
-{
-       struct mwifiex_private *priv = mwifiex_netdev_get_priv(dev);
-
-       mwifiex_abort_cac(priv);
-
-       if (mwifiex_del_mgmt_ies(priv))
-               mwifiex_dbg(priv->adapter, ERROR,
-                           "Failed to delete mgmt IEs!\n");
-
-       priv->ap_11n_enabled = 0;
-       memset(&priv->bss_cfg, 0, sizeof(priv->bss_cfg));
-
-       if (mwifiex_send_cmd(priv, HostCmd_CMD_UAP_BSS_STOP,
-                            HostCmd_ACT_GEN_SET, 0, NULL, true)) {
-               mwifiex_dbg(priv->adapter, ERROR,
-                           "Failed to stop the BSS\n");
-               return -1;
-       }
-
-       if (mwifiex_send_cmd(priv, HOST_CMD_APCMD_SYS_RESET,
-                            HostCmd_ACT_GEN_SET, 0, NULL, true)) {
-               mwifiex_dbg(priv->adapter, ERROR,
-                           "Failed to reset BSS\n");
-               return -1;
-       }
-
-       if (netif_carrier_ok(priv->netdev))
-               netif_carrier_off(priv->netdev);
-       mwifiex_stop_net_dev_queue(priv->netdev, priv->adapter);
-
-       return 0;
-}
-
-/* cfg80211 operation handler for start_ap.
- * Function sets beacon period, DTIM period, SSID and security into
- * AP config structure.
- * AP is configured with these settings and BSS is started.
- */
-static int mwifiex_cfg80211_start_ap(struct wiphy *wiphy,
-                                    struct net_device *dev,
-                                    struct cfg80211_ap_settings *params)
-{
-       struct mwifiex_uap_bss_param *bss_cfg;
-       struct mwifiex_private *priv = mwifiex_netdev_get_priv(dev);
-
-       if (GET_BSS_ROLE(priv) != MWIFIEX_BSS_ROLE_UAP)
-               return -1;
-
-       bss_cfg = kzalloc(sizeof(struct mwifiex_uap_bss_param), GFP_KERNEL);
-       if (!bss_cfg)
-               return -ENOMEM;
-
-       mwifiex_set_sys_config_invalid_data(bss_cfg);
-
-       if (params->beacon_interval)
-               bss_cfg->beacon_period = params->beacon_interval;
-       if (params->dtim_period)
-               bss_cfg->dtim_period = params->dtim_period;
-
-       if (params->ssid && params->ssid_len) {
-               memcpy(bss_cfg->ssid.ssid, params->ssid, params->ssid_len);
-               bss_cfg->ssid.ssid_len = params->ssid_len;
-       }
-       if (params->inactivity_timeout > 0) {
-               /* sta_ao_timer/ps_sta_ao_timer is in unit of 100ms */
-               bss_cfg->sta_ao_timer = 10 * params->inactivity_timeout;
-               bss_cfg->ps_sta_ao_timer = 10 * params->inactivity_timeout;
-       }
-
-       switch (params->hidden_ssid) {
-       case NL80211_HIDDEN_SSID_NOT_IN_USE:
-               bss_cfg->bcast_ssid_ctl = 1;
-               break;
-       case NL80211_HIDDEN_SSID_ZERO_LEN:
-               bss_cfg->bcast_ssid_ctl = 0;
-               break;
-       case NL80211_HIDDEN_SSID_ZERO_CONTENTS:
-               /* firmware doesn't support this type of hidden SSID */
-       default:
-               kfree(bss_cfg);
-               return -EINVAL;
-       }
-
-       mwifiex_uap_set_channel(priv, bss_cfg, params->chandef);
-       mwifiex_set_uap_rates(bss_cfg, params);
-
-       if (mwifiex_set_secure_params(priv, bss_cfg, params)) {
-               kfree(bss_cfg);
-               mwifiex_dbg(priv->adapter, ERROR,
-                           "Failed to parse secuirty parameters!\n");
-               return -1;
-       }
-
-       mwifiex_set_ht_params(priv, bss_cfg, params);
-
-       if (priv->adapter->is_hw_11ac_capable) {
-               mwifiex_set_vht_params(priv, bss_cfg, params);
-               mwifiex_set_vht_width(priv, params->chandef.width,
-                                     priv->ap_11ac_enabled);
-       }
-
-       if (priv->ap_11ac_enabled)
-               mwifiex_set_11ac_ba_params(priv);
-       else
-               mwifiex_set_ba_params(priv);
-
-       mwifiex_set_wmm_params(priv, bss_cfg, params);
-
-       if (mwifiex_is_11h_active(priv))
-               mwifiex_set_tpc_params(priv, bss_cfg, params);
-
-       if (mwifiex_is_11h_active(priv) &&
-           !cfg80211_chandef_dfs_required(wiphy, &params->chandef,
-                                          priv->bss_mode)) {
-               mwifiex_dbg(priv->adapter, INFO,
-                           "Disable 11h extensions in FW\n");
-               if (mwifiex_11h_activate(priv, false)) {
-                       mwifiex_dbg(priv->adapter, ERROR,
-                                   "Failed to disable 11h extensions!!");
-                       return -1;
-               }
-               priv->state_11h.is_11h_active = false;
-       }
-
-       if (mwifiex_config_start_uap(priv, bss_cfg)) {
-               mwifiex_dbg(priv->adapter, ERROR,
-                           "Failed to start AP\n");
-               kfree(bss_cfg);
-               return -1;
-       }
-
-       if (mwifiex_set_mgmt_ies(priv, &params->beacon))
-               return -1;
-
-       if (!netif_carrier_ok(priv->netdev))
-               netif_carrier_on(priv->netdev);
-       mwifiex_wake_up_net_dev_queue(priv->netdev, priv->adapter);
-
-       memcpy(&priv->bss_cfg, bss_cfg, sizeof(priv->bss_cfg));
-       kfree(bss_cfg);
-       return 0;
-}
-
-/*
- * CFG802.11 operation handler for disconnection request.
- *
- * This function does not work when there is already a disconnection
- * procedure going on.
- */
-static int
-mwifiex_cfg80211_disconnect(struct wiphy *wiphy, struct net_device *dev,
-                           u16 reason_code)
-{
-       struct mwifiex_private *priv = mwifiex_netdev_get_priv(dev);
-
-       if (mwifiex_deauthenticate(priv, NULL))
-               return -EFAULT;
-
-       mwifiex_dbg(priv->adapter, MSG,
-                   "info: successfully disconnected from %pM:\t"
-                   "reason code %d\n", priv->cfg_bssid, reason_code);
-
-       eth_zero_addr(priv->cfg_bssid);
-       priv->hs2_enabled = false;
-
-       return 0;
-}
-
-/*
- * This function informs the CFG802.11 subsystem of a new IBSS.
- *
- * The following information are sent to the CFG802.11 subsystem
- * to register the new IBSS. If we do not register the new IBSS,
- * a kernel panic will result.
- *      - SSID
- *      - SSID length
- *      - BSSID
- *      - Channel
- */
-static int mwifiex_cfg80211_inform_ibss_bss(struct mwifiex_private *priv)
-{
-       struct ieee80211_channel *chan;
-       struct mwifiex_bss_info bss_info;
-       struct cfg80211_bss *bss;
-       int ie_len;
-       u8 ie_buf[IEEE80211_MAX_SSID_LEN + sizeof(struct ieee_types_header)];
-       enum ieee80211_band band;
-
-       if (mwifiex_get_bss_info(priv, &bss_info))
-               return -1;
-
-       ie_buf[0] = WLAN_EID_SSID;
-       ie_buf[1] = bss_info.ssid.ssid_len;
-
-       memcpy(&ie_buf[sizeof(struct ieee_types_header)],
-              &bss_info.ssid.ssid, bss_info.ssid.ssid_len);
-       ie_len = ie_buf[1] + sizeof(struct ieee_types_header);
-
-       band = mwifiex_band_to_radio_type(priv->curr_bss_params.band);
-       chan = __ieee80211_get_channel(priv->wdev.wiphy,
-                       ieee80211_channel_to_frequency(bss_info.bss_chan,
-                                                      band));
-
-       bss = cfg80211_inform_bss(priv->wdev.wiphy, chan,
-                                 CFG80211_BSS_FTYPE_UNKNOWN,
-                                 bss_info.bssid, 0, WLAN_CAPABILITY_IBSS,
-                                 0, ie_buf, ie_len, 0, GFP_KERNEL);
-       if (bss) {
-               cfg80211_put_bss(priv->wdev.wiphy, bss);
-               ether_addr_copy(priv->cfg_bssid, bss_info.bssid);
-       }
-
-       return 0;
-}
-
-/*
- * This function connects with a BSS.
- *
- * This function handles both Infra and Ad-Hoc modes. It also performs
- * validity checking on the provided parameters, disconnects from the
- * current BSS (if any), sets up the association/scan parameters,
- * including security settings, and performs specific SSID scan before
- * trying to connect.
- *
- * For Infra mode, the function returns failure if the specified SSID
- * is not found in scan table. However, for Ad-Hoc mode, it can create
- * the IBSS if it does not exist. On successful completion in either case,
- * the function notifies the CFG802.11 subsystem of the new BSS connection.
- */
-static int
-mwifiex_cfg80211_assoc(struct mwifiex_private *priv, size_t ssid_len,
-                      const u8 *ssid, const u8 *bssid, int mode,
-                      struct ieee80211_channel *channel,
-                      struct cfg80211_connect_params *sme, bool privacy)
-{
-       struct cfg80211_ssid req_ssid;
-       int ret, auth_type = 0;
-       struct cfg80211_bss *bss = NULL;
-       u8 is_scanning_required = 0;
-
-       memset(&req_ssid, 0, sizeof(struct cfg80211_ssid));
-
-       req_ssid.ssid_len = ssid_len;
-       if (ssid_len > IEEE80211_MAX_SSID_LEN) {
-               mwifiex_dbg(priv->adapter, ERROR, "invalid SSID - aborting\n");
-               return -EINVAL;
-       }
-
-       memcpy(req_ssid.ssid, ssid, ssid_len);
-       if (!req_ssid.ssid_len || req_ssid.ssid[0] < 0x20) {
-               mwifiex_dbg(priv->adapter, ERROR, "invalid SSID - aborting\n");
-               return -EINVAL;
-       }
-
-       /* As this is new association, clear locally stored
-        * keys and security related flags */
-       priv->sec_info.wpa_enabled = false;
-       priv->sec_info.wpa2_enabled = false;
-       priv->wep_key_curr_index = 0;
-       priv->sec_info.encryption_mode = 0;
-       priv->sec_info.is_authtype_auto = 0;
-       ret = mwifiex_set_encode(priv, NULL, NULL, 0, 0, NULL, 1);
-
-       if (mode == NL80211_IFTYPE_ADHOC) {
-               /* "privacy" is set only for ad-hoc mode */
-               if (privacy) {
-                       /*
-                        * Keep WLAN_CIPHER_SUITE_WEP104 for now so that
-                        * the firmware can find a matching network from the
-                        * scan. The cfg80211 does not give us the encryption
-                        * mode at this stage so just setting it to WEP here.
-                        */
-                       priv->sec_info.encryption_mode =
-                                       WLAN_CIPHER_SUITE_WEP104;
-                       priv->sec_info.authentication_mode =
-                                       NL80211_AUTHTYPE_OPEN_SYSTEM;
-               }
-
-               goto done;
-       }
-
-       /* Now handle infra mode. "sme" is valid for infra mode only */
-       if (sme->auth_type == NL80211_AUTHTYPE_AUTOMATIC) {
-               auth_type = NL80211_AUTHTYPE_OPEN_SYSTEM;
-               priv->sec_info.is_authtype_auto = 1;
-       } else {
-               auth_type = sme->auth_type;
-       }
-
-       if (sme->crypto.n_ciphers_pairwise) {
-               priv->sec_info.encryption_mode =
-                                               sme->crypto.ciphers_pairwise[0];
-               priv->sec_info.authentication_mode = auth_type;
-       }
-
-       if (sme->crypto.cipher_group) {
-               priv->sec_info.encryption_mode = sme->crypto.cipher_group;
-               priv->sec_info.authentication_mode = auth_type;
-       }
-       if (sme->ie)
-               ret = mwifiex_set_gen_ie(priv, sme->ie, sme->ie_len);
-
-       if (sme->key) {
-               if (mwifiex_is_alg_wep(priv->sec_info.encryption_mode)) {
-                       mwifiex_dbg(priv->adapter, INFO,
-                                   "info: setting wep encryption\t"
-                                   "with key len %d\n", sme->key_len);
-                       priv->wep_key_curr_index = sme->key_idx;
-                       ret = mwifiex_set_encode(priv, NULL, sme->key,
-                                                sme->key_len, sme->key_idx,
-                                                NULL, 0);
-               }
-       }
-done:
-       /*
-        * Scan entries are valid for some time (15 sec). So we can save one
-        * active scan time if we just try cfg80211_get_bss first. If it fails
-        * then request scan and cfg80211_get_bss() again for final output.
-        */
-       while (1) {
-               if (is_scanning_required) {
-                       /* Do specific SSID scanning */
-                       if (mwifiex_request_scan(priv, &req_ssid)) {
-                               mwifiex_dbg(priv->adapter, ERROR, "scan error\n");
-                               return -EFAULT;
-                       }
-               }
-
-               /* Find the BSS we want using available scan results */
-               if (mode == NL80211_IFTYPE_ADHOC)
-                       bss = cfg80211_get_bss(priv->wdev.wiphy, channel,
-                                              bssid, ssid, ssid_len,
-                                              IEEE80211_BSS_TYPE_IBSS,
-                                              IEEE80211_PRIVACY_ANY);
-               else
-                       bss = cfg80211_get_bss(priv->wdev.wiphy, channel,
-                                              bssid, ssid, ssid_len,
-                                              IEEE80211_BSS_TYPE_ESS,
-                                              IEEE80211_PRIVACY_ANY);
-
-               if (!bss) {
-                       if (is_scanning_required) {
-                               mwifiex_dbg(priv->adapter, WARN,
-                                           "assoc: requested bss not found in scan results\n");
-                               break;
-                       }
-                       is_scanning_required = 1;
-               } else {
-                       mwifiex_dbg(priv->adapter, MSG,
-                                   "info: trying to associate to '%s' bssid %pM\n",
-                                   (char *)req_ssid.ssid, bss->bssid);
-                       memcpy(&priv->cfg_bssid, bss->bssid, ETH_ALEN);
-                       break;
-               }
-       }
-
-       ret = mwifiex_bss_start(priv, bss, &req_ssid);
-       if (ret)
-               return ret;
-
-       if (mode == NL80211_IFTYPE_ADHOC) {
-               /* Inform the BSS information to kernel, otherwise
-                * kernel will give a panic after successful assoc */
-               if (mwifiex_cfg80211_inform_ibss_bss(priv))
-                       return -EFAULT;
-       }
-
-       return ret;
-}
-
-/*
- * CFG802.11 operation handler for association request.
- *
- * This function does not work when the current mode is set to Ad-Hoc, or
- * when there is already an association procedure going on. The given BSS
- * information is used to associate.
- */
-static int
-mwifiex_cfg80211_connect(struct wiphy *wiphy, struct net_device *dev,
-                        struct cfg80211_connect_params *sme)
-{
-       struct mwifiex_private *priv = mwifiex_netdev_get_priv(dev);
-       struct mwifiex_adapter *adapter = priv->adapter;
-       int ret;
-
-       if (GET_BSS_ROLE(priv) != MWIFIEX_BSS_ROLE_STA) {
-               mwifiex_dbg(adapter, ERROR,
-                           "%s: reject infra assoc request in non-STA role\n",
-                           dev->name);
-               return -EINVAL;
-       }
-
-       if (priv->wdev.current_bss) {
-               mwifiex_dbg(adapter, ERROR,
-                           "%s: already connected\n", dev->name);
-               return -EALREADY;
-       }
-
-       if (adapter->surprise_removed || adapter->is_cmd_timedout) {
-               mwifiex_dbg(adapter, ERROR,
-                           "%s: Ignore connection.\t"
-                           "Card removed or FW in bad state\n",
-                           dev->name);
-               return -EFAULT;
-       }
-
-       mwifiex_dbg(adapter, INFO,
-                   "info: Trying to associate to %s and bssid %pM\n",
-                   (char *)sme->ssid, sme->bssid);
-
-       ret = mwifiex_cfg80211_assoc(priv, sme->ssid_len, sme->ssid, sme->bssid,
-                                    priv->bss_mode, sme->channel, sme, 0);
-       if (!ret) {
-               cfg80211_connect_result(priv->netdev, priv->cfg_bssid, NULL, 0,
-                                       NULL, 0, WLAN_STATUS_SUCCESS,
-                                       GFP_KERNEL);
-               mwifiex_dbg(priv->adapter, MSG,
-                           "info: associated to bssid %pM successfully\n",
-                           priv->cfg_bssid);
-               if (ISSUPP_TDLS_ENABLED(priv->adapter->fw_cap_info) &&
-                   priv->adapter->auto_tdls &&
-                   priv->bss_type == MWIFIEX_BSS_TYPE_STA)
-                       mwifiex_setup_auto_tdls_timer(priv);
-       } else {
-               mwifiex_dbg(priv->adapter, ERROR,
-                           "info: association to bssid %pM failed\n",
-                           priv->cfg_bssid);
-               eth_zero_addr(priv->cfg_bssid);
-
-               if (ret > 0)
-                       cfg80211_connect_result(priv->netdev, priv->cfg_bssid,
-                                               NULL, 0, NULL, 0, ret,
-                                               GFP_KERNEL);
-               else
-                       cfg80211_connect_result(priv->netdev, priv->cfg_bssid,
-                                               NULL, 0, NULL, 0,
-                                               WLAN_STATUS_UNSPECIFIED_FAILURE,
-                                               GFP_KERNEL);
-       }
-
-       return 0;
-}
-
-/*
- * This function sets following parameters for ibss network.
- *  -  channel
- *  -  start band
- *  -  11n flag
- *  -  secondary channel offset
- */
-static int mwifiex_set_ibss_params(struct mwifiex_private *priv,
-                                  struct cfg80211_ibss_params *params)
-{
-       struct mwifiex_adapter *adapter = priv->adapter;
-       int index = 0, i;
-       u8 config_bands = 0;
-
-       if (params->chandef.chan->band == IEEE80211_BAND_2GHZ) {
-               if (!params->basic_rates) {
-                       config_bands = BAND_B | BAND_G;
-               } else {
-                       for (i = 0; i < mwifiex_band_2ghz.n_bitrates; i++) {
-                               /*
-                                * Rates below 6 Mbps in the table are CCK
-                                * rates; 802.11b and from 6 they are OFDM;
-                                * 802.11G
-                                */
-                               if (mwifiex_rates[i].bitrate == 60) {
-                                       index = 1 << i;
-                                       break;
-                               }
-                       }
-
-                       if (params->basic_rates < index) {
-                               config_bands = BAND_B;
-                       } else {
-                               config_bands = BAND_G;
-                               if (params->basic_rates % index)
-                                       config_bands |= BAND_B;
-                       }
-               }
-
-               if (cfg80211_get_chandef_type(&params->chandef) !=
-                                               NL80211_CHAN_NO_HT)
-                       config_bands |= BAND_G | BAND_GN;
-       } else {
-               if (cfg80211_get_chandef_type(&params->chandef) ==
-                                               NL80211_CHAN_NO_HT)
-                       config_bands = BAND_A;
-               else
-                       config_bands = BAND_AN | BAND_A;
-       }
-
-       if (!((config_bands | adapter->fw_bands) & ~adapter->fw_bands)) {
-               adapter->config_bands = config_bands;
-               adapter->adhoc_start_band = config_bands;
-
-               if ((config_bands & BAND_GN) || (config_bands & BAND_AN))
-                       adapter->adhoc_11n_enabled = true;
-               else
-                       adapter->adhoc_11n_enabled = false;
-       }
-
-       adapter->sec_chan_offset =
-               mwifiex_chan_type_to_sec_chan_offset(
-                       cfg80211_get_chandef_type(&params->chandef));
-       priv->adhoc_channel = ieee80211_frequency_to_channel(
-                               params->chandef.chan->center_freq);
-
-       mwifiex_dbg(adapter, INFO,
-                   "info: set ibss band %d, chan %d, chan offset %d\n",
-                   config_bands, priv->adhoc_channel,
-                   adapter->sec_chan_offset);
-
-       return 0;
-}
-
-/*
- * CFG802.11 operation handler to join an IBSS.
- *
- * This function does not work in any mode other than Ad-Hoc, or if
- * a join operation is already in progress.
- */
-static int
-mwifiex_cfg80211_join_ibss(struct wiphy *wiphy, struct net_device *dev,
-                          struct cfg80211_ibss_params *params)
-{
-       struct mwifiex_private *priv = mwifiex_netdev_get_priv(dev);
-       int ret = 0;
-
-       if (priv->bss_mode != NL80211_IFTYPE_ADHOC) {
-               mwifiex_dbg(priv->adapter, ERROR,
-                           "request to join ibss received\t"
-                           "when station is not in ibss mode\n");
-               goto done;
-       }
-
-       mwifiex_dbg(priv->adapter, MSG,
-                   "info: trying to join to %s and bssid %pM\n",
-                   (char *)params->ssid, params->bssid);
-
-       mwifiex_set_ibss_params(priv, params);
-
-       ret = mwifiex_cfg80211_assoc(priv, params->ssid_len, params->ssid,
-                                    params->bssid, priv->bss_mode,
-                                    params->chandef.chan, NULL,
-                                    params->privacy);
-done:
-       if (!ret) {
-               cfg80211_ibss_joined(priv->netdev, priv->cfg_bssid,
-                                    params->chandef.chan, GFP_KERNEL);
-               mwifiex_dbg(priv->adapter, MSG,
-                           "info: joined/created adhoc network with bssid\t"
-                           "%pM successfully\n", priv->cfg_bssid);
-       } else {
-               mwifiex_dbg(priv->adapter, ERROR,
-                           "info: failed creating/joining adhoc network\n");
-       }
-
-       return ret;
-}
-
-/*
- * CFG802.11 operation handler to leave an IBSS.
- *
- * This function does not work if a leave operation is
- * already in progress.
- */
-static int
-mwifiex_cfg80211_leave_ibss(struct wiphy *wiphy, struct net_device *dev)
-{
-       struct mwifiex_private *priv = mwifiex_netdev_get_priv(dev);
-
-       mwifiex_dbg(priv->adapter, MSG, "info: disconnecting from essid %pM\n",
-                   priv->cfg_bssid);
-       if (mwifiex_deauthenticate(priv, NULL))
-               return -EFAULT;
-
-       eth_zero_addr(priv->cfg_bssid);
-
-       return 0;
-}
-
-/*
- * CFG802.11 operation handler for scan request.
- *
- * This function issues a scan request to the firmware based upon
- * the user specified scan configuration. On successful completion,
- * it also informs the results.
- */
-static int
-mwifiex_cfg80211_scan(struct wiphy *wiphy,
-                     struct cfg80211_scan_request *request)
-{
-       struct net_device *dev = request->wdev->netdev;
-       struct mwifiex_private *priv = mwifiex_netdev_get_priv(dev);
-       int i, offset, ret;
-       struct ieee80211_channel *chan;
-       struct ieee_types_header *ie;
-       struct mwifiex_user_scan_cfg *user_scan_cfg;
-
-       mwifiex_dbg(priv->adapter, CMD,
-                   "info: received scan request on %s\n", dev->name);
-
-       /* Block scan request if scan operation or scan cleanup when interface
-        * is disabled is in process
-        */
-       if (priv->scan_request || priv->scan_aborting) {
-               mwifiex_dbg(priv->adapter, WARN,
-                           "cmd: Scan already in process..\n");
-               return -EBUSY;
-       }
-
-       user_scan_cfg = kzalloc(sizeof(*user_scan_cfg), GFP_KERNEL);
-       if (!user_scan_cfg)
-               return -ENOMEM;
-
-       priv->scan_request = request;
-
-       user_scan_cfg->num_ssids = request->n_ssids;
-       user_scan_cfg->ssid_list = request->ssids;
-
-       if (request->ie && request->ie_len) {
-               offset = 0;
-               for (i = 0; i < MWIFIEX_MAX_VSIE_NUM; i++) {
-                       if (priv->vs_ie[i].mask != MWIFIEX_VSIE_MASK_CLEAR)
-                               continue;
-                       priv->vs_ie[i].mask = MWIFIEX_VSIE_MASK_SCAN;
-                       ie = (struct ieee_types_header *)(request->ie + offset);
-                       memcpy(&priv->vs_ie[i].ie, ie, sizeof(*ie) + ie->len);
-                       offset += sizeof(*ie) + ie->len;
-
-                       if (offset >= request->ie_len)
-                               break;
-               }
-       }
-
-       for (i = 0; i < min_t(u32, request->n_channels,
-                             MWIFIEX_USER_SCAN_CHAN_MAX); i++) {
-               chan = request->channels[i];
-               user_scan_cfg->chan_list[i].chan_number = chan->hw_value;
-               user_scan_cfg->chan_list[i].radio_type = chan->band;
-
-               if ((chan->flags & IEEE80211_CHAN_NO_IR) || !request->n_ssids)
-                       user_scan_cfg->chan_list[i].scan_type =
-                                               MWIFIEX_SCAN_TYPE_PASSIVE;
-               else
-                       user_scan_cfg->chan_list[i].scan_type =
-                                               MWIFIEX_SCAN_TYPE_ACTIVE;
-
-               user_scan_cfg->chan_list[i].scan_time = 0;
-       }
-
-       if (priv->adapter->scan_chan_gap_enabled &&
-           mwifiex_is_any_intf_active(priv))
-               user_scan_cfg->scan_chan_gap =
-                                             priv->adapter->scan_chan_gap_time;
-
-       ret = mwifiex_scan_networks(priv, user_scan_cfg);
-       kfree(user_scan_cfg);
-       if (ret) {
-               mwifiex_dbg(priv->adapter, ERROR,
-                           "scan failed: %d\n", ret);
-               priv->scan_aborting = false;
-               priv->scan_request = NULL;
-               return ret;
-       }
-
-       if (request->ie && request->ie_len) {
-               for (i = 0; i < MWIFIEX_MAX_VSIE_NUM; i++) {
-                       if (priv->vs_ie[i].mask == MWIFIEX_VSIE_MASK_SCAN) {
-                               priv->vs_ie[i].mask = MWIFIEX_VSIE_MASK_CLEAR;
-                               memset(&priv->vs_ie[i].ie, 0,
-                                      MWIFIEX_MAX_VSIE_LEN);
-                       }
-               }
-       }
-       return 0;
-}
-
-static void mwifiex_setup_vht_caps(struct ieee80211_sta_vht_cap *vht_info,
-                                  struct mwifiex_private *priv)
-{
-       struct mwifiex_adapter *adapter = priv->adapter;
-
-       vht_info->vht_supported = true;
-
-       vht_info->cap = adapter->hw_dot_11ac_dev_cap;
-       /* Update MCS support for VHT */
-       vht_info->vht_mcs.rx_mcs_map = cpu_to_le16(
-                               adapter->hw_dot_11ac_mcs_support & 0xFFFF);
-       vht_info->vht_mcs.rx_highest = 0;
-       vht_info->vht_mcs.tx_mcs_map = cpu_to_le16(
-                               adapter->hw_dot_11ac_mcs_support >> 16);
-       vht_info->vht_mcs.tx_highest = 0;
-}
-
-/*
- * This function sets up the CFG802.11 specific HT capability fields
- * with default values.
- *
- * The following default values are set -
- *      - HT Supported = True
- *      - Maximum AMPDU length factor = IEEE80211_HT_MAX_AMPDU_64K
- *      - Minimum AMPDU spacing = IEEE80211_HT_MPDU_DENSITY_NONE
- *      - HT Capabilities supported by firmware
- *      - MCS information, Rx mask = 0xff
- *      - MCD information, Tx parameters = IEEE80211_HT_MCS_TX_DEFINED (0x01)
- */
-static void
-mwifiex_setup_ht_caps(struct ieee80211_sta_ht_cap *ht_info,
-                     struct mwifiex_private *priv)
-{
-       int rx_mcs_supp;
-       struct ieee80211_mcs_info mcs_set;
-       u8 *mcs = (u8 *)&mcs_set;
-       struct mwifiex_adapter *adapter = priv->adapter;
-
-       ht_info->ht_supported = true;
-       ht_info->ampdu_factor = IEEE80211_HT_MAX_AMPDU_64K;
-       ht_info->ampdu_density = IEEE80211_HT_MPDU_DENSITY_NONE;
-
-       memset(&ht_info->mcs, 0, sizeof(ht_info->mcs));
-
-       /* Fill HT capability information */
-       if (ISSUPP_CHANWIDTH40(adapter->hw_dot_11n_dev_cap))
-               ht_info->cap |= IEEE80211_HT_CAP_SUP_WIDTH_20_40;
-       else
-               ht_info->cap &= ~IEEE80211_HT_CAP_SUP_WIDTH_20_40;
-
-       if (ISSUPP_SHORTGI20(adapter->hw_dot_11n_dev_cap))
-               ht_info->cap |= IEEE80211_HT_CAP_SGI_20;
-       else
-               ht_info->cap &= ~IEEE80211_HT_CAP_SGI_20;
-
-       if (ISSUPP_SHORTGI40(adapter->hw_dot_11n_dev_cap))
-               ht_info->cap |= IEEE80211_HT_CAP_SGI_40;
-       else
-               ht_info->cap &= ~IEEE80211_HT_CAP_SGI_40;
-
-       if (adapter->user_dev_mcs_support == HT_STREAM_2X2)
-               ht_info->cap |= 3 << IEEE80211_HT_CAP_RX_STBC_SHIFT;
-       else
-               ht_info->cap |= 1 << IEEE80211_HT_CAP_RX_STBC_SHIFT;
-
-       if (ISSUPP_TXSTBC(adapter->hw_dot_11n_dev_cap))
-               ht_info->cap |= IEEE80211_HT_CAP_TX_STBC;
-       else
-               ht_info->cap &= ~IEEE80211_HT_CAP_TX_STBC;
-
-       if (ISSUPP_GREENFIELD(adapter->hw_dot_11n_dev_cap))
-               ht_info->cap |= IEEE80211_HT_CAP_GRN_FLD;
-       else
-               ht_info->cap &= ~IEEE80211_HT_CAP_GRN_FLD;
-
-       if (ISENABLED_40MHZ_INTOLERANT(adapter->hw_dot_11n_dev_cap))
-               ht_info->cap |= IEEE80211_HT_CAP_40MHZ_INTOLERANT;
-       else
-               ht_info->cap &= ~IEEE80211_HT_CAP_40MHZ_INTOLERANT;
-
-       if (ISSUPP_RXLDPC(adapter->hw_dot_11n_dev_cap))
-               ht_info->cap |= IEEE80211_HT_CAP_LDPC_CODING;
-       else
-               ht_info->cap &= ~IEEE80211_HT_CAP_LDPC_CODING;
-
-       ht_info->cap &= ~IEEE80211_HT_CAP_MAX_AMSDU;
-       ht_info->cap |= IEEE80211_HT_CAP_SM_PS;
-
-       rx_mcs_supp = GET_RXMCSSUPP(adapter->user_dev_mcs_support);
-       /* Set MCS for 1x1/2x2 */
-       memset(mcs, 0xff, rx_mcs_supp);
-       /* Clear all the other values */
-       memset(&mcs[rx_mcs_supp], 0,
-              sizeof(struct ieee80211_mcs_info) - rx_mcs_supp);
-       if (priv->bss_mode == NL80211_IFTYPE_STATION ||
-           ISSUPP_CHANWIDTH40(adapter->hw_dot_11n_dev_cap))
-               /* Set MCS32 for infra mode or ad-hoc mode with 40MHz support */
-               SETHT_MCS32(mcs_set.rx_mask);
-
-       memcpy((u8 *) &ht_info->mcs, mcs, sizeof(struct ieee80211_mcs_info));
-
-       ht_info->mcs.tx_params = IEEE80211_HT_MCS_TX_DEFINED;
-}
-
-/*
- *  create a new virtual interface with the given name and name assign type
- */
-struct wireless_dev *mwifiex_add_virtual_intf(struct wiphy *wiphy,
-                                             const char *name,
-                                             unsigned char name_assign_type,
-                                             enum nl80211_iftype type,
-                                             u32 *flags,
-                                             struct vif_params *params)
-{
-       struct mwifiex_adapter *adapter = mwifiex_cfg80211_get_adapter(wiphy);
-       struct mwifiex_private *priv;
-       struct net_device *dev;
-       void *mdev_priv;
-
-       if (!adapter)
-               return ERR_PTR(-EFAULT);
-
-       switch (type) {
-       case NL80211_IFTYPE_UNSPECIFIED:
-       case NL80211_IFTYPE_STATION:
-       case NL80211_IFTYPE_ADHOC:
-               if (adapter->curr_iface_comb.sta_intf ==
-                   adapter->iface_limit.sta_intf) {
-                       mwifiex_dbg(adapter, ERROR,
-                                   "cannot create multiple sta/adhoc ifaces\n");
-                       return ERR_PTR(-EINVAL);
-               }
-
-               priv = mwifiex_get_unused_priv(adapter);
-               if (!priv) {
-                       mwifiex_dbg(adapter, ERROR,
-                                   "could not get free private struct\n");
-                       return ERR_PTR(-EFAULT);
-               }
-
-               priv->wdev.wiphy = wiphy;
-               priv->wdev.iftype = NL80211_IFTYPE_STATION;
-
-               if (type == NL80211_IFTYPE_UNSPECIFIED)
-                       priv->bss_mode = NL80211_IFTYPE_STATION;
-               else
-                       priv->bss_mode = type;
-
-               priv->bss_type = MWIFIEX_BSS_TYPE_STA;
-               priv->frame_type = MWIFIEX_DATA_FRAME_TYPE_ETH_II;
-               priv->bss_priority = 0;
-               priv->bss_role = MWIFIEX_BSS_ROLE_STA;
-               priv->bss_num = adapter->curr_iface_comb.sta_intf;
-
-               break;
-       case NL80211_IFTYPE_AP:
-               if (adapter->curr_iface_comb.uap_intf ==
-                   adapter->iface_limit.uap_intf) {
-                       mwifiex_dbg(adapter, ERROR,
-                                   "cannot create multiple AP ifaces\n");
-                       return ERR_PTR(-EINVAL);
-               }
-
-               priv = mwifiex_get_unused_priv(adapter);
-               if (!priv) {
-                       mwifiex_dbg(adapter, ERROR,
-                                   "could not get free private struct\n");
-                       return ERR_PTR(-EFAULT);
-               }
-
-               priv->wdev.wiphy = wiphy;
-               priv->wdev.iftype = NL80211_IFTYPE_AP;
-
-               priv->bss_type = MWIFIEX_BSS_TYPE_UAP;
-               priv->frame_type = MWIFIEX_DATA_FRAME_TYPE_ETH_II;
-               priv->bss_priority = 0;
-               priv->bss_role = MWIFIEX_BSS_ROLE_UAP;
-               priv->bss_started = 0;
-               priv->bss_num = adapter->curr_iface_comb.uap_intf;
-               priv->bss_mode = type;
-
-               break;
-       case NL80211_IFTYPE_P2P_CLIENT:
-               if (adapter->curr_iface_comb.p2p_intf ==
-                   adapter->iface_limit.p2p_intf) {
-                       mwifiex_dbg(adapter, ERROR,
-                                   "cannot create multiple P2P ifaces\n");
-                       return ERR_PTR(-EINVAL);
-               }
-
-               priv = mwifiex_get_unused_priv(adapter);
-               if (!priv) {
-                       mwifiex_dbg(adapter, ERROR,
-                                   "could not get free private struct\n");
-                       return ERR_PTR(-EFAULT);
-               }
-
-               priv->wdev.wiphy = wiphy;
-               /* At start-up, wpa_supplicant tries to change the interface
-                * to NL80211_IFTYPE_STATION if it is not managed mode.
-                */
-               priv->wdev.iftype = NL80211_IFTYPE_P2P_CLIENT;
-               priv->bss_mode = NL80211_IFTYPE_P2P_CLIENT;
-
-               /* Setting bss_type to P2P tells firmware that this interface
-                * is receiving P2P peers found during find phase and doing
-                * action frame handshake.
-                */
-               priv->bss_type = MWIFIEX_BSS_TYPE_P2P;
-
-               priv->frame_type = MWIFIEX_DATA_FRAME_TYPE_ETH_II;
-               priv->bss_priority = MWIFIEX_BSS_ROLE_STA;
-               priv->bss_role = MWIFIEX_BSS_ROLE_STA;
-               priv->bss_started = 0;
-               priv->bss_num = adapter->curr_iface_comb.p2p_intf;
-
-               if (mwifiex_cfg80211_init_p2p_client(priv)) {
-                       memset(&priv->wdev, 0, sizeof(priv->wdev));
-                       priv->wdev.iftype = NL80211_IFTYPE_UNSPECIFIED;
-                       return ERR_PTR(-EFAULT);
-               }
-
-               break;
-       default:
-               mwifiex_dbg(adapter, ERROR, "type not supported\n");
-               return ERR_PTR(-EINVAL);
-       }
-
-       dev = alloc_netdev_mqs(sizeof(struct mwifiex_private *), name,
-                              name_assign_type, ether_setup,
-                              IEEE80211_NUM_ACS, 1);
-       if (!dev) {
-               mwifiex_dbg(adapter, ERROR,
-                           "no memory available for netdevice\n");
-               memset(&priv->wdev, 0, sizeof(priv->wdev));
-               priv->wdev.iftype = NL80211_IFTYPE_UNSPECIFIED;
-               priv->bss_mode = NL80211_IFTYPE_UNSPECIFIED;
-               return ERR_PTR(-ENOMEM);
-       }
-
-       mwifiex_init_priv_params(priv, dev);
-       priv->netdev = dev;
-
-       mwifiex_setup_ht_caps(&wiphy->bands[IEEE80211_BAND_2GHZ]->ht_cap, priv);
-       if (adapter->is_hw_11ac_capable)
-               mwifiex_setup_vht_caps(
-                       &wiphy->bands[IEEE80211_BAND_2GHZ]->vht_cap, priv);
-
-       if (adapter->config_bands & BAND_A)
-               mwifiex_setup_ht_caps(
-                       &wiphy->bands[IEEE80211_BAND_5GHZ]->ht_cap, priv);
-
-       if ((adapter->config_bands & BAND_A) && adapter->is_hw_11ac_capable)
-               mwifiex_setup_vht_caps(
-                       &wiphy->bands[IEEE80211_BAND_5GHZ]->vht_cap, priv);
-
-       dev_net_set(dev, wiphy_net(wiphy));
-       dev->ieee80211_ptr = &priv->wdev;
-       dev->ieee80211_ptr->iftype = priv->bss_mode;
-       memcpy(dev->dev_addr, wiphy->perm_addr, ETH_ALEN);
-       SET_NETDEV_DEV(dev, wiphy_dev(wiphy));
-
-       dev->flags |= IFF_BROADCAST | IFF_MULTICAST;
-       dev->watchdog_timeo = MWIFIEX_DEFAULT_WATCHDOG_TIMEOUT;
-       dev->hard_header_len += MWIFIEX_MIN_DATA_HEADER_LEN;
-       dev->ethtool_ops = &mwifiex_ethtool_ops;
-
-       mdev_priv = netdev_priv(dev);
-       *((unsigned long *) mdev_priv) = (unsigned long) priv;
-
-       SET_NETDEV_DEV(dev, adapter->dev);
-
-       /* Register network device */
-       if (register_netdevice(dev)) {
-               mwifiex_dbg(adapter, ERROR,
-                           "cannot register virtual network device\n");
-               free_netdev(dev);
-               priv->bss_mode = NL80211_IFTYPE_UNSPECIFIED;
-               priv->netdev = NULL;
-               memset(&priv->wdev, 0, sizeof(priv->wdev));
-               priv->wdev.iftype = NL80211_IFTYPE_UNSPECIFIED;
-               return ERR_PTR(-EFAULT);
-       }
-
-       priv->dfs_cac_workqueue = alloc_workqueue("MWIFIEX_DFS_CAC%s",
-                                                 WQ_HIGHPRI |
-                                                 WQ_MEM_RECLAIM |
-                                                 WQ_UNBOUND, 1, name);
-       if (!priv->dfs_cac_workqueue) {
-               mwifiex_dbg(adapter, ERROR,
-                           "cannot register virtual network device\n");
-               free_netdev(dev);
-               priv->bss_mode = NL80211_IFTYPE_UNSPECIFIED;
-               priv->netdev = NULL;
-               memset(&priv->wdev, 0, sizeof(priv->wdev));
-               priv->wdev.iftype = NL80211_IFTYPE_UNSPECIFIED;
-               return ERR_PTR(-ENOMEM);
-       }
-
-       INIT_DELAYED_WORK(&priv->dfs_cac_work, mwifiex_dfs_cac_work_queue);
-
-       priv->dfs_chan_sw_workqueue = alloc_workqueue("MWIFIEX_DFS_CHSW%s",
-                                                     WQ_HIGHPRI | WQ_UNBOUND |
-                                                     WQ_MEM_RECLAIM, 1, name);
-       if (!priv->dfs_chan_sw_workqueue) {
-               mwifiex_dbg(adapter, ERROR,
-                           "cannot register virtual network device\n");
-               free_netdev(dev);
-               priv->bss_mode = NL80211_IFTYPE_UNSPECIFIED;
-               priv->netdev = NULL;
-               memset(&priv->wdev, 0, sizeof(priv->wdev));
-               priv->wdev.iftype = NL80211_IFTYPE_UNSPECIFIED;
-               return ERR_PTR(-ENOMEM);
-       }
-
-       INIT_DELAYED_WORK(&priv->dfs_chan_sw_work,
-                         mwifiex_dfs_chan_sw_work_queue);
-
-       sema_init(&priv->async_sem, 1);
-
-       mwifiex_dbg(adapter, INFO,
-                   "info: %s: Marvell 802.11 Adapter\n", dev->name);
-
-#ifdef CONFIG_DEBUG_FS
-       mwifiex_dev_debugfs_init(priv);
-#endif
-
-       switch (type) {
-       case NL80211_IFTYPE_UNSPECIFIED:
-       case NL80211_IFTYPE_STATION:
-       case NL80211_IFTYPE_ADHOC:
-               adapter->curr_iface_comb.sta_intf++;
-               break;
-       case NL80211_IFTYPE_AP:
-               adapter->curr_iface_comb.uap_intf++;
-               break;
-       case NL80211_IFTYPE_P2P_CLIENT:
-               adapter->curr_iface_comb.p2p_intf++;
-               break;
-       default:
-               mwifiex_dbg(adapter, ERROR, "type not supported\n");
-               return ERR_PTR(-EINVAL);
-       }
-
-       return &priv->wdev;
-}
-EXPORT_SYMBOL_GPL(mwifiex_add_virtual_intf);
-
-/*
- * del_virtual_intf: remove the virtual interface determined by dev
- */
-int mwifiex_del_virtual_intf(struct wiphy *wiphy, struct wireless_dev *wdev)
-{
-       struct mwifiex_private *priv = mwifiex_netdev_get_priv(wdev->netdev);
-       struct mwifiex_adapter *adapter = priv->adapter;
-       struct sk_buff *skb, *tmp;
-
-#ifdef CONFIG_DEBUG_FS
-       mwifiex_dev_debugfs_remove(priv);
-#endif
-
-       mwifiex_stop_net_dev_queue(priv->netdev, adapter);
-
-       skb_queue_walk_safe(&priv->bypass_txq, skb, tmp)
-               mwifiex_write_data_complete(priv->adapter, skb, 0, -1);
-
-       if (netif_carrier_ok(priv->netdev))
-               netif_carrier_off(priv->netdev);
-
-       if (wdev->netdev->reg_state == NETREG_REGISTERED)
-               unregister_netdevice(wdev->netdev);
-
-       if (priv->dfs_cac_workqueue) {
-               flush_workqueue(priv->dfs_cac_workqueue);
-               destroy_workqueue(priv->dfs_cac_workqueue);
-               priv->dfs_cac_workqueue = NULL;
-       }
-
-       if (priv->dfs_chan_sw_workqueue) {
-               flush_workqueue(priv->dfs_chan_sw_workqueue);
-               destroy_workqueue(priv->dfs_chan_sw_workqueue);
-               priv->dfs_chan_sw_workqueue = NULL;
-       }
-       /* Clear the priv in adapter */
-       priv->netdev->ieee80211_ptr = NULL;
-       priv->netdev = NULL;
-       priv->wdev.iftype = NL80211_IFTYPE_UNSPECIFIED;
-
-       priv->media_connected = false;
-
-       switch (priv->bss_mode) {
-       case NL80211_IFTYPE_UNSPECIFIED:
-       case NL80211_IFTYPE_STATION:
-       case NL80211_IFTYPE_ADHOC:
-               adapter->curr_iface_comb.sta_intf--;
-               break;
-       case NL80211_IFTYPE_AP:
-               adapter->curr_iface_comb.uap_intf--;
-               break;
-       case NL80211_IFTYPE_P2P_CLIENT:
-       case NL80211_IFTYPE_P2P_GO:
-               adapter->curr_iface_comb.p2p_intf--;
-               break;
-       default:
-               mwifiex_dbg(adapter, ERROR,
-                           "del_virtual_intf: type not supported\n");
-               break;
-       }
-
-       priv->bss_mode = NL80211_IFTYPE_UNSPECIFIED;
-
-       if (GET_BSS_ROLE(priv) == MWIFIEX_BSS_ROLE_STA ||
-           GET_BSS_ROLE(priv) == MWIFIEX_BSS_ROLE_UAP)
-               kfree(priv->hist_data);
-
-       return 0;
-}
-EXPORT_SYMBOL_GPL(mwifiex_del_virtual_intf);
-
-static bool
-mwifiex_is_pattern_supported(struct cfg80211_pkt_pattern *pat, s8 *byte_seq,
-                            u8 max_byte_seq)
-{
-       int j, k, valid_byte_cnt = 0;
-       bool dont_care_byte = false;
-
-       for (j = 0; j < DIV_ROUND_UP(pat->pattern_len, 8); j++) {
-               for (k = 0; k < 8; k++) {
-                       if (pat->mask[j] & 1 << k) {
-                               memcpy(byte_seq + valid_byte_cnt,
-                                      &pat->pattern[j * 8 + k], 1);
-                               valid_byte_cnt++;
-                               if (dont_care_byte)
-                                       return false;
-                       } else {
-                               if (valid_byte_cnt)
-                                       dont_care_byte = true;
-                       }
-
-                       if (valid_byte_cnt > max_byte_seq)
-                               return false;
-               }
-       }
-
-       byte_seq[max_byte_seq] = valid_byte_cnt;
-
-       return true;
-}
-
-#ifdef CONFIG_PM
-static void mwifiex_set_auto_arp_mef_entry(struct mwifiex_private *priv,
-                                          struct mwifiex_mef_entry *mef_entry)
-{
-       int i, filt_num = 0, num_ipv4 = 0;
-       struct in_device *in_dev;
-       struct in_ifaddr *ifa;
-       __be32 ips[MWIFIEX_MAX_SUPPORTED_IPADDR];
-       struct mwifiex_adapter *adapter = priv->adapter;
-
-       mef_entry->mode = MEF_MODE_HOST_SLEEP;
-       mef_entry->action = MEF_ACTION_AUTO_ARP;
-
-       /* Enable ARP offload feature */
-       memset(ips, 0, sizeof(ips));
-       for (i = 0; i < MWIFIEX_MAX_BSS_NUM; i++) {
-               if (adapter->priv[i]->netdev) {
-                       in_dev = __in_dev_get_rtnl(adapter->priv[i]->netdev);
-                       if (!in_dev)
-                               continue;
-                       ifa = in_dev->ifa_list;
-                       if (!ifa || !ifa->ifa_local)
-                               continue;
-                       ips[i] = ifa->ifa_local;
-                       num_ipv4++;
-               }
-       }
-
-       for (i = 0; i < num_ipv4; i++) {
-               if (!ips[i])
-                       continue;
-               mef_entry->filter[filt_num].repeat = 1;
-               memcpy(mef_entry->filter[filt_num].byte_seq,
-                      (u8 *)&ips[i], sizeof(ips[i]));
-               mef_entry->filter[filt_num].
-                       byte_seq[MWIFIEX_MEF_MAX_BYTESEQ] =
-                       sizeof(ips[i]);
-               mef_entry->filter[filt_num].offset = 46;
-               mef_entry->filter[filt_num].filt_type = TYPE_EQ;
-               if (filt_num) {
-                       mef_entry->filter[filt_num].filt_action =
-                               TYPE_OR;
-               }
-               filt_num++;
-       }
-
-       mef_entry->filter[filt_num].repeat = 1;
-       mef_entry->filter[filt_num].byte_seq[0] = 0x08;
-       mef_entry->filter[filt_num].byte_seq[1] = 0x06;
-       mef_entry->filter[filt_num].byte_seq[MWIFIEX_MEF_MAX_BYTESEQ] = 2;
-       mef_entry->filter[filt_num].offset = 20;
-       mef_entry->filter[filt_num].filt_type = TYPE_EQ;
-       mef_entry->filter[filt_num].filt_action = TYPE_AND;
-}
-
-static int mwifiex_set_wowlan_mef_entry(struct mwifiex_private *priv,
-                                       struct mwifiex_ds_mef_cfg *mef_cfg,
-                                       struct mwifiex_mef_entry *mef_entry,
-                                       struct cfg80211_wowlan *wowlan)
-{
-       int i, filt_num = 0, ret = 0;
-       bool first_pat = true;
-       u8 byte_seq[MWIFIEX_MEF_MAX_BYTESEQ + 1];
-       const u8 ipv4_mc_mac[] = {0x33, 0x33};
-       const u8 ipv6_mc_mac[] = {0x01, 0x00, 0x5e};
-
-       mef_entry->mode = MEF_MODE_HOST_SLEEP;
-       mef_entry->action = MEF_ACTION_ALLOW_AND_WAKEUP_HOST;
-
-       for (i = 0; i < wowlan->n_patterns; i++) {
-               memset(byte_seq, 0, sizeof(byte_seq));
-               if (!mwifiex_is_pattern_supported(&wowlan->patterns[i],
-                                       byte_seq,
-                                       MWIFIEX_MEF_MAX_BYTESEQ)) {
-                       mwifiex_dbg(priv->adapter, ERROR,
-                                   "Pattern not supported\n");
-                       return -EOPNOTSUPP;
-               }
-
-               if (!wowlan->patterns[i].pkt_offset) {
-                       if (!(byte_seq[0] & 0x01) &&
-                           (byte_seq[MWIFIEX_MEF_MAX_BYTESEQ] == 1)) {
-                               mef_cfg->criteria |= MWIFIEX_CRITERIA_UNICAST;
-                               continue;
-                       } else if (is_broadcast_ether_addr(byte_seq)) {
-                               mef_cfg->criteria |= MWIFIEX_CRITERIA_BROADCAST;
-                               continue;
-                       } else if ((!memcmp(byte_seq, ipv4_mc_mac, 2) &&
-                                   (byte_seq[MWIFIEX_MEF_MAX_BYTESEQ] == 2)) ||
-                                  (!memcmp(byte_seq, ipv6_mc_mac, 3) &&
-                                   (byte_seq[MWIFIEX_MEF_MAX_BYTESEQ] == 3))) {
-                               mef_cfg->criteria |= MWIFIEX_CRITERIA_MULTICAST;
-                               continue;
-                       }
-               }
-               mef_entry->filter[filt_num].repeat = 1;
-               mef_entry->filter[filt_num].offset =
-                       wowlan->patterns[i].pkt_offset;
-               memcpy(mef_entry->filter[filt_num].byte_seq, byte_seq,
-                               sizeof(byte_seq));
-               mef_entry->filter[filt_num].filt_type = TYPE_EQ;
-
-               if (first_pat)
-                       first_pat = false;
-               else
-                       mef_entry->filter[filt_num].filt_action = TYPE_AND;
-
-               filt_num++;
-       }
-
-       if (wowlan->magic_pkt) {
-               mef_cfg->criteria |= MWIFIEX_CRITERIA_UNICAST;
-               mef_entry->filter[filt_num].repeat = 16;
-               memcpy(mef_entry->filter[filt_num].byte_seq, priv->curr_addr,
-                               ETH_ALEN);
-               mef_entry->filter[filt_num].byte_seq[MWIFIEX_MEF_MAX_BYTESEQ] =
-                       ETH_ALEN;
-               mef_entry->filter[filt_num].offset = 28;
-               mef_entry->filter[filt_num].filt_type = TYPE_EQ;
-               if (filt_num)
-                       mef_entry->filter[filt_num].filt_action = TYPE_OR;
-
-               filt_num++;
-               mef_entry->filter[filt_num].repeat = 16;
-               memcpy(mef_entry->filter[filt_num].byte_seq, priv->curr_addr,
-                               ETH_ALEN);
-               mef_entry->filter[filt_num].byte_seq[MWIFIEX_MEF_MAX_BYTESEQ] =
-                       ETH_ALEN;
-               mef_entry->filter[filt_num].offset = 56;
-               mef_entry->filter[filt_num].filt_type = TYPE_EQ;
-               mef_entry->filter[filt_num].filt_action = TYPE_OR;
-       }
-       return ret;
-}
-
-static int mwifiex_set_mef_filter(struct mwifiex_private *priv,
-                                 struct cfg80211_wowlan *wowlan)
-{
-       int ret = 0, num_entries = 1;
-       struct mwifiex_ds_mef_cfg mef_cfg;
-       struct mwifiex_mef_entry *mef_entry;
-
-       if (wowlan->n_patterns || wowlan->magic_pkt)
-               num_entries++;
-
-       mef_entry = kcalloc(num_entries, sizeof(*mef_entry), GFP_KERNEL);
-       if (!mef_entry)
-               return -ENOMEM;
-
-       memset(&mef_cfg, 0, sizeof(mef_cfg));
-       mef_cfg.criteria |= MWIFIEX_CRITERIA_BROADCAST |
-               MWIFIEX_CRITERIA_UNICAST;
-       mef_cfg.num_entries = num_entries;
-       mef_cfg.mef_entry = mef_entry;
-
-       mwifiex_set_auto_arp_mef_entry(priv, &mef_entry[0]);
-
-       if (wowlan->n_patterns || wowlan->magic_pkt) {
-               ret = mwifiex_set_wowlan_mef_entry(priv, &mef_cfg,
-                                                  &mef_entry[1], wowlan);
-               if (ret)
-                       goto err;
-       }
-
-       if (!mef_cfg.criteria)
-               mef_cfg.criteria = MWIFIEX_CRITERIA_BROADCAST |
-                       MWIFIEX_CRITERIA_UNICAST |
-                       MWIFIEX_CRITERIA_MULTICAST;
-
-       ret = mwifiex_send_cmd(priv, HostCmd_CMD_MEF_CFG,
-                       HostCmd_ACT_GEN_SET, 0,
-                       &mef_cfg, true);
-
-err:
-       kfree(mef_entry);
-       return ret;
-}
-
-static int mwifiex_cfg80211_suspend(struct wiphy *wiphy,
-                                   struct cfg80211_wowlan *wowlan)
-{
-       struct mwifiex_adapter *adapter = mwifiex_cfg80211_get_adapter(wiphy);
-       struct mwifiex_ds_hs_cfg hs_cfg;
-       int i, ret = 0;
-       struct mwifiex_private *priv;
-
-       for (i = 0; i < adapter->priv_num; i++) {
-               priv = adapter->priv[i];
-               mwifiex_abort_cac(priv);
-       }
-
-       mwifiex_cancel_all_pending_cmd(adapter);
-
-       if (!wowlan) {
-               mwifiex_dbg(adapter, ERROR,
-                           "None of the WOWLAN triggers enabled\n");
-               return 0;
-       }
-
-       priv = mwifiex_get_priv(adapter, MWIFIEX_BSS_ROLE_STA);
-
-       if (!priv->media_connected) {
-               mwifiex_dbg(adapter, ERROR,
-                           "Can not configure WOWLAN in disconnected state\n");
-               return 0;
-       }
-
-       ret = mwifiex_set_mef_filter(priv, wowlan);
-       if (ret) {
-               mwifiex_dbg(adapter, ERROR, "Failed to set MEF filter\n");
-               return ret;
-       }
-
-       if (wowlan->disconnect) {
-               memset(&hs_cfg, 0, sizeof(hs_cfg));
-               hs_cfg.is_invoke_hostcmd = false;
-               hs_cfg.conditions = HS_CFG_COND_MAC_EVENT;
-               hs_cfg.gpio = HS_CFG_GPIO_DEF;
-               hs_cfg.gap = HS_CFG_GAP_DEF;
-               ret = mwifiex_set_hs_params(priv, HostCmd_ACT_GEN_SET,
-                                           MWIFIEX_SYNC_CMD, &hs_cfg);
-               if (ret) {
-                       mwifiex_dbg(adapter, ERROR,
-                                   "Failed to set HS params\n");
-                       return ret;
-               }
-       }
-
-       return ret;
-}
-
-static int mwifiex_cfg80211_resume(struct wiphy *wiphy)
-{
-       return 0;
-}
-
-static void mwifiex_cfg80211_set_wakeup(struct wiphy *wiphy,
-                                      bool enabled)
-{
-       struct mwifiex_adapter *adapter = mwifiex_cfg80211_get_adapter(wiphy);
-
-       device_set_wakeup_enable(adapter->dev, enabled);
-}
-#endif
-
-static int mwifiex_get_coalesce_pkt_type(u8 *byte_seq)
-{
-       const u8 ipv4_mc_mac[] = {0x33, 0x33};
-       const u8 ipv6_mc_mac[] = {0x01, 0x00, 0x5e};
-       const u8 bc_mac[] = {0xff, 0xff, 0xff, 0xff};
-
-       if ((byte_seq[0] & 0x01) &&
-           (byte_seq[MWIFIEX_COALESCE_MAX_BYTESEQ] == 1))
-               return PACKET_TYPE_UNICAST;
-       else if (!memcmp(byte_seq, bc_mac, 4))
-               return PACKET_TYPE_BROADCAST;
-       else if ((!memcmp(byte_seq, ipv4_mc_mac, 2) &&
-                 byte_seq[MWIFIEX_COALESCE_MAX_BYTESEQ] == 2) ||
-                (!memcmp(byte_seq, ipv6_mc_mac, 3) &&
-                 byte_seq[MWIFIEX_COALESCE_MAX_BYTESEQ] == 3))
-               return PACKET_TYPE_MULTICAST;
-
-       return 0;
-}
-
-static int
-mwifiex_fill_coalesce_rule_info(struct mwifiex_private *priv,
-                               struct cfg80211_coalesce_rules *crule,
-                               struct mwifiex_coalesce_rule *mrule)
-{
-       u8 byte_seq[MWIFIEX_COALESCE_MAX_BYTESEQ + 1];
-       struct filt_field_param *param;
-       int i;
-
-       mrule->max_coalescing_delay = crule->delay;
-
-       param = mrule->params;
-
-       for (i = 0; i < crule->n_patterns; i++) {
-               memset(byte_seq, 0, sizeof(byte_seq));
-               if (!mwifiex_is_pattern_supported(&crule->patterns[i],
-                                                 byte_seq,
-                                               MWIFIEX_COALESCE_MAX_BYTESEQ)) {
-                       mwifiex_dbg(priv->adapter, ERROR,
-                                   "Pattern not supported\n");
-                       return -EOPNOTSUPP;
-               }
-
-               if (!crule->patterns[i].pkt_offset) {
-                       u8 pkt_type;
-
-                       pkt_type = mwifiex_get_coalesce_pkt_type(byte_seq);
-                       if (pkt_type && mrule->pkt_type) {
-                               mwifiex_dbg(priv->adapter, ERROR,
-                                           "Multiple packet types not allowed\n");
-                               return -EOPNOTSUPP;
-                       } else if (pkt_type) {
-                               mrule->pkt_type = pkt_type;
-                               continue;
-                       }
-               }
-
-               if (crule->condition == NL80211_COALESCE_CONDITION_MATCH)
-                       param->operation = RECV_FILTER_MATCH_TYPE_EQ;
-               else
-                       param->operation = RECV_FILTER_MATCH_TYPE_NE;
-
-               param->operand_len = byte_seq[MWIFIEX_COALESCE_MAX_BYTESEQ];
-               memcpy(param->operand_byte_stream, byte_seq,
-                      param->operand_len);
-               param->offset = crule->patterns[i].pkt_offset;
-               param++;
-
-               mrule->num_of_fields++;
-       }
-
-       if (!mrule->pkt_type) {
-               mwifiex_dbg(priv->adapter, ERROR,
-                           "Packet type can not be determined\n");
-               return -EOPNOTSUPP;
-       }
-
-       return 0;
-}
-
-static int mwifiex_cfg80211_set_coalesce(struct wiphy *wiphy,
-                                        struct cfg80211_coalesce *coalesce)
-{
-       struct mwifiex_adapter *adapter = mwifiex_cfg80211_get_adapter(wiphy);
-       int i, ret;
-       struct mwifiex_ds_coalesce_cfg coalesce_cfg;
-       struct mwifiex_private *priv =
-                       mwifiex_get_priv(adapter, MWIFIEX_BSS_ROLE_STA);
-
-       memset(&coalesce_cfg, 0, sizeof(coalesce_cfg));
-       if (!coalesce) {
-               mwifiex_dbg(adapter, WARN,
-                           "Disable coalesce and reset all previous rules\n");
-               return mwifiex_send_cmd(priv, HostCmd_CMD_COALESCE_CFG,
-                                       HostCmd_ACT_GEN_SET, 0,
-                                       &coalesce_cfg, true);
-       }
-
-       coalesce_cfg.num_of_rules = coalesce->n_rules;
-       for (i = 0; i < coalesce->n_rules; i++) {
-               ret = mwifiex_fill_coalesce_rule_info(priv, &coalesce->rules[i],
-                                                     &coalesce_cfg.rule[i]);
-               if (ret) {
-                       mwifiex_dbg(adapter, ERROR,
-                                   "Recheck the patterns provided for rule %d\n",
-                               i + 1);
-                       return ret;
-               }
-       }
-
-       return mwifiex_send_cmd(priv, HostCmd_CMD_COALESCE_CFG,
-                               HostCmd_ACT_GEN_SET, 0, &coalesce_cfg, true);
-}
-
-/* cfg80211 ops handler for tdls_mgmt.
- * Function prepares TDLS action frame packets and forwards them to FW
- */
-static int
-mwifiex_cfg80211_tdls_mgmt(struct wiphy *wiphy, struct net_device *dev,
-                          const u8 *peer, u8 action_code, u8 dialog_token,
-                          u16 status_code, u32 peer_capability,
-                          bool initiator, const u8 *extra_ies,
-                          size_t extra_ies_len)
-{
-       struct mwifiex_private *priv = mwifiex_netdev_get_priv(dev);
-       int ret;
-
-       if (!(wiphy->flags & WIPHY_FLAG_SUPPORTS_TDLS))
-               return -ENOTSUPP;
-
-       /* make sure we are in station mode and connected */
-       if (!(priv->bss_type == MWIFIEX_BSS_TYPE_STA && priv->media_connected))
-               return -ENOTSUPP;
-
-       switch (action_code) {
-       case WLAN_TDLS_SETUP_REQUEST:
-               mwifiex_dbg(priv->adapter, MSG,
-                           "Send TDLS Setup Request to %pM status_code=%d\n",
-                           peer, status_code);
-               mwifiex_add_auto_tdls_peer(priv, peer);
-               ret = mwifiex_send_tdls_data_frame(priv, peer, action_code,
-                                                  dialog_token, status_code,
-                                                  extra_ies, extra_ies_len);
-               break;
-       case WLAN_TDLS_SETUP_RESPONSE:
-               mwifiex_add_auto_tdls_peer(priv, peer);
-               mwifiex_dbg(priv->adapter, MSG,
-                           "Send TDLS Setup Response to %pM status_code=%d\n",
-                           peer, status_code);
-               ret = mwifiex_send_tdls_data_frame(priv, peer, action_code,
-                                                  dialog_token, status_code,
-                                                  extra_ies, extra_ies_len);
-               break;
-       case WLAN_TDLS_SETUP_CONFIRM:
-               mwifiex_dbg(priv->adapter, MSG,
-                           "Send TDLS Confirm to %pM status_code=%d\n", peer,
-                           status_code);
-               ret = mwifiex_send_tdls_data_frame(priv, peer, action_code,
-                                                  dialog_token, status_code,
-                                                  extra_ies, extra_ies_len);
-               break;
-       case WLAN_TDLS_TEARDOWN:
-               mwifiex_dbg(priv->adapter, MSG,
-                           "Send TDLS Tear down to %pM\n", peer);
-               ret = mwifiex_send_tdls_data_frame(priv, peer, action_code,
-                                                  dialog_token, status_code,
-                                                  extra_ies, extra_ies_len);
-               break;
-       case WLAN_TDLS_DISCOVERY_REQUEST:
-               mwifiex_dbg(priv->adapter, MSG,
-                           "Send TDLS Discovery Request to %pM\n", peer);
-               ret = mwifiex_send_tdls_data_frame(priv, peer, action_code,
-                                                  dialog_token, status_code,
-                                                  extra_ies, extra_ies_len);
-               break;
-       case WLAN_PUB_ACTION_TDLS_DISCOVER_RES:
-               mwifiex_dbg(priv->adapter, MSG,
-                           "Send TDLS Discovery Response to %pM\n", peer);
-               ret = mwifiex_send_tdls_action_frame(priv, peer, action_code,
-                                                  dialog_token, status_code,
-                                                  extra_ies, extra_ies_len);
-               break;
-       default:
-               mwifiex_dbg(priv->adapter, ERROR,
-                           "Unknown TDLS mgmt/action frame %pM\n", peer);
-               ret = -EINVAL;
-               break;
-       }
-
-       return ret;
-}
-
-static int
-mwifiex_cfg80211_tdls_oper(struct wiphy *wiphy, struct net_device *dev,
-                          const u8 *peer, enum nl80211_tdls_operation action)
-{
-       struct mwifiex_private *priv = mwifiex_netdev_get_priv(dev);
-
-       if (!(wiphy->flags & WIPHY_FLAG_SUPPORTS_TDLS) ||
-           !(wiphy->flags & WIPHY_FLAG_TDLS_EXTERNAL_SETUP))
-               return -ENOTSUPP;
-
-       /* make sure we are in station mode and connected */
-       if (!(priv->bss_type == MWIFIEX_BSS_TYPE_STA && priv->media_connected))
-               return -ENOTSUPP;
-
-       mwifiex_dbg(priv->adapter, MSG,
-                   "TDLS peer=%pM, oper=%d\n", peer, action);
-
-       switch (action) {
-       case NL80211_TDLS_ENABLE_LINK:
-               action = MWIFIEX_TDLS_ENABLE_LINK;
-               break;
-       case NL80211_TDLS_DISABLE_LINK:
-               action = MWIFIEX_TDLS_DISABLE_LINK;
-               break;
-       case NL80211_TDLS_TEARDOWN:
-               /* shouldn't happen!*/
-               mwifiex_dbg(priv->adapter, ERROR,
-                           "tdls_oper: teardown from driver not supported\n");
-               return -EINVAL;
-       case NL80211_TDLS_SETUP:
-               /* shouldn't happen!*/
-               mwifiex_dbg(priv->adapter, ERROR,
-                           "tdls_oper: setup from driver not supported\n");
-               return -EINVAL;
-       case NL80211_TDLS_DISCOVERY_REQ:
-               /* shouldn't happen!*/
-               mwifiex_dbg(priv->adapter, ERROR,
-                           "tdls_oper: discovery from driver not supported\n");
-               return -EINVAL;
-       default:
-               mwifiex_dbg(priv->adapter, ERROR,
-                           "tdls_oper: operation not supported\n");
-               return -ENOTSUPP;
-       }
-
-       return mwifiex_tdls_oper(priv, peer, action);
-}
-
-static int
-mwifiex_cfg80211_tdls_chan_switch(struct wiphy *wiphy, struct net_device *dev,
-                                 const u8 *addr, u8 oper_class,
-                                 struct cfg80211_chan_def *chandef)
-{
-       struct mwifiex_sta_node *sta_ptr;
-       unsigned long flags;
-       u16 chan;
-       u8 second_chan_offset, band;
-       struct mwifiex_private *priv = mwifiex_netdev_get_priv(dev);
-
-       spin_lock_irqsave(&priv->sta_list_spinlock, flags);
-       sta_ptr = mwifiex_get_sta_entry(priv, addr);
-       spin_unlock_irqrestore(&priv->sta_list_spinlock, flags);
-
-       if (!sta_ptr) {
-               wiphy_err(wiphy, "%s: Invalid TDLS peer %pM\n",
-                         __func__, addr);
-               return -ENOENT;
-       }
-
-       if (!(sta_ptr->tdls_cap.extcap.ext_capab[3] &
-             WLAN_EXT_CAPA4_TDLS_CHAN_SWITCH)) {
-               wiphy_err(wiphy, "%pM do not support tdls cs\n", addr);
-               return -ENOENT;
-       }
-
-       if (sta_ptr->tdls_status == TDLS_CHAN_SWITCHING ||
-           sta_ptr->tdls_status == TDLS_IN_OFF_CHAN) {
-               wiphy_err(wiphy, "channel switch is running, abort request\n");
-               return -EALREADY;
-       }
-
-       chan = chandef->chan->hw_value;
-       second_chan_offset = mwifiex_get_sec_chan_offset(chan);
-       band = chandef->chan->band;
-       mwifiex_start_tdls_cs(priv, addr, chan, second_chan_offset, band);
-
-       return 0;
-}
-
-static void
-mwifiex_cfg80211_tdls_cancel_chan_switch(struct wiphy *wiphy,
-                                        struct net_device *dev,
-                                        const u8 *addr)
-{
-       struct mwifiex_sta_node *sta_ptr;
-       unsigned long flags;
-       struct mwifiex_private *priv = mwifiex_netdev_get_priv(dev);
-
-       spin_lock_irqsave(&priv->sta_list_spinlock, flags);
-       sta_ptr = mwifiex_get_sta_entry(priv, addr);
-       spin_unlock_irqrestore(&priv->sta_list_spinlock, flags);
-
-       if (!sta_ptr) {
-               wiphy_err(wiphy, "%s: Invalid TDLS peer %pM\n",
-                         __func__, addr);
-       } else if (!(sta_ptr->tdls_status == TDLS_CHAN_SWITCHING ||
-                    sta_ptr->tdls_status == TDLS_IN_BASE_CHAN ||
-                    sta_ptr->tdls_status == TDLS_IN_OFF_CHAN)) {
-               wiphy_err(wiphy, "tdls chan switch not initialize by %pM\n",
-                         addr);
-       } else
-               mwifiex_stop_tdls_cs(priv, addr);
-}
-
-static int
-mwifiex_cfg80211_add_station(struct wiphy *wiphy, struct net_device *dev,
-                            const u8 *mac, struct station_parameters *params)
-{
-       struct mwifiex_private *priv = mwifiex_netdev_get_priv(dev);
-
-       if (!(params->sta_flags_set & BIT(NL80211_STA_FLAG_TDLS_PEER)))
-               return -ENOTSUPP;
-
-       /* make sure we are in station mode and connected */
-       if ((priv->bss_type != MWIFIEX_BSS_TYPE_STA) || !priv->media_connected)
-               return -ENOTSUPP;
-
-       return mwifiex_tdls_oper(priv, mac, MWIFIEX_TDLS_CREATE_LINK);
-}
-
-static int
-mwifiex_cfg80211_channel_switch(struct wiphy *wiphy, struct net_device *dev,
-                               struct cfg80211_csa_settings *params)
-{
-       struct ieee_types_header *chsw_ie;
-       struct ieee80211_channel_sw_ie *channel_sw;
-       int chsw_msec;
-       struct mwifiex_private *priv = mwifiex_netdev_get_priv(dev);
-
-       if (priv->adapter->scan_processing) {
-               mwifiex_dbg(priv->adapter, ERROR,
-                           "radar detection: scan in process...\n");
-               return -EBUSY;
-       }
-
-       if (priv->wdev.cac_started)
-               return -EBUSY;
-
-       if (cfg80211_chandef_identical(&params->chandef,
-                                      &priv->dfs_chandef))
-               return -EINVAL;
-
-       chsw_ie = (void *)cfg80211_find_ie(WLAN_EID_CHANNEL_SWITCH,
-                                          params->beacon_csa.tail,
-                                          params->beacon_csa.tail_len);
-       if (!chsw_ie) {
-               mwifiex_dbg(priv->adapter, ERROR,
-                           "Could not parse channel switch announcement IE\n");
-               return -EINVAL;
-       }
-
-       channel_sw = (void *)(chsw_ie + 1);
-       if (channel_sw->mode) {
-               if (netif_carrier_ok(priv->netdev))
-                       netif_carrier_off(priv->netdev);
-               mwifiex_stop_net_dev_queue(priv->netdev, priv->adapter);
-       }
-
-       if (mwifiex_del_mgmt_ies(priv))
-               mwifiex_dbg(priv->adapter, ERROR,
-                           "Failed to delete mgmt IEs!\n");
-
-       if (mwifiex_set_mgmt_ies(priv, &params->beacon_csa)) {
-               mwifiex_dbg(priv->adapter, ERROR,
-                           "%s: setting mgmt ies failed\n", __func__);
-               return -EFAULT;
-       }
-
-       memcpy(&priv->dfs_chandef, &params->chandef, sizeof(priv->dfs_chandef));
-       memcpy(&priv->beacon_after, &params->beacon_after,
-              sizeof(priv->beacon_after));
-
-       chsw_msec = max(channel_sw->count * priv->bss_cfg.beacon_period, 100);
-       queue_delayed_work(priv->dfs_chan_sw_workqueue, &priv->dfs_chan_sw_work,
-                          msecs_to_jiffies(chsw_msec));
-       return 0;
-}
-
-static int mwifiex_cfg80211_get_channel(struct wiphy *wiphy,
-                                       struct wireless_dev *wdev,
-                                       struct cfg80211_chan_def *chandef)
-{
-       struct mwifiex_private *priv = mwifiex_netdev_get_priv(wdev->netdev);
-       struct mwifiex_bssdescriptor *curr_bss;
-       struct ieee80211_channel *chan;
-       u8 second_chan_offset;
-       enum nl80211_channel_type chan_type;
-       enum ieee80211_band band;
-       int freq;
-       int ret = -ENODATA;
-
-       if (GET_BSS_ROLE(priv) == MWIFIEX_BSS_ROLE_UAP &&
-           cfg80211_chandef_valid(&priv->bss_chandef)) {
-               *chandef = priv->bss_chandef;
-               ret = 0;
-       } else if (priv->media_connected) {
-               curr_bss = &priv->curr_bss_params.bss_descriptor;
-               band = mwifiex_band_to_radio_type(priv->curr_bss_params.band);
-               freq = ieee80211_channel_to_frequency(curr_bss->channel, band);
-               chan = ieee80211_get_channel(wiphy, freq);
-
-               if (curr_bss->bcn_ht_oper) {
-                       second_chan_offset = curr_bss->bcn_ht_oper->ht_param &
-                                       IEEE80211_HT_PARAM_CHA_SEC_OFFSET;
-                       chan_type = mwifiex_sec_chan_offset_to_chan_type
-                                                       (second_chan_offset);
-                       cfg80211_chandef_create(chandef, chan, chan_type);
-               } else {
-                       cfg80211_chandef_create(chandef, chan,
-                                               NL80211_CHAN_NO_HT);
-               }
-               ret = 0;
-       }
-
-       return ret;
-}
-
-static int
-mwifiex_cfg80211_start_radar_detection(struct wiphy *wiphy,
-                                      struct net_device *dev,
-                                      struct cfg80211_chan_def *chandef,
-                                      u32 cac_time_ms)
-{
-       struct mwifiex_private *priv = mwifiex_netdev_get_priv(dev);
-       struct mwifiex_radar_params radar_params;
-
-       if (priv->adapter->scan_processing) {
-               mwifiex_dbg(priv->adapter, ERROR,
-                           "radar detection: scan already in process...\n");
-               return -EBUSY;
-       }
-
-       if (!mwifiex_is_11h_active(priv)) {
-               mwifiex_dbg(priv->adapter, INFO,
-                           "Enable 11h extensions in FW\n");
-               if (mwifiex_11h_activate(priv, true)) {
-                       mwifiex_dbg(priv->adapter, ERROR,
-                                   "Failed to activate 11h extensions!!");
-                       return -1;
-               }
-               priv->state_11h.is_11h_active = true;
-       }
-
-       memset(&radar_params, 0, sizeof(struct mwifiex_radar_params));
-       radar_params.chandef = chandef;
-       radar_params.cac_time_ms = cac_time_ms;
-
-       memcpy(&priv->dfs_chandef, chandef, sizeof(priv->dfs_chandef));
-
-       if (mwifiex_send_cmd(priv, HostCmd_CMD_CHAN_REPORT_REQUEST,
-                            HostCmd_ACT_GEN_SET, 0, &radar_params, true))
-               return -1;
-
-       queue_delayed_work(priv->dfs_cac_workqueue, &priv->dfs_cac_work,
-                          msecs_to_jiffies(cac_time_ms));
-       return 0;
-}
-
-static int
-mwifiex_cfg80211_change_station(struct wiphy *wiphy, struct net_device *dev,
-                               const u8 *mac,
-                               struct station_parameters *params)
-{
-       int ret;
-       struct mwifiex_private *priv = mwifiex_netdev_get_priv(dev);
-
-       /* we support change_station handler only for TDLS peers*/
-       if (!(params->sta_flags_set & BIT(NL80211_STA_FLAG_TDLS_PEER)))
-               return -ENOTSUPP;
-
-       /* make sure we are in station mode and connected */
-       if ((priv->bss_type != MWIFIEX_BSS_TYPE_STA) || !priv->media_connected)
-               return -ENOTSUPP;
-
-       priv->sta_params = params;
-
-       ret = mwifiex_tdls_oper(priv, mac, MWIFIEX_TDLS_CONFIG_LINK);
-       priv->sta_params = NULL;
-
-       return ret;
-}
-
-/* station cfg80211 operations */
-static struct cfg80211_ops mwifiex_cfg80211_ops = {
-       .add_virtual_intf = mwifiex_add_virtual_intf,
-       .del_virtual_intf = mwifiex_del_virtual_intf,
-       .change_virtual_intf = mwifiex_cfg80211_change_virtual_intf,
-       .scan = mwifiex_cfg80211_scan,
-       .connect = mwifiex_cfg80211_connect,
-       .disconnect = mwifiex_cfg80211_disconnect,
-       .get_station = mwifiex_cfg80211_get_station,
-       .dump_station = mwifiex_cfg80211_dump_station,
-       .dump_survey = mwifiex_cfg80211_dump_survey,
-       .set_wiphy_params = mwifiex_cfg80211_set_wiphy_params,
-       .join_ibss = mwifiex_cfg80211_join_ibss,
-       .leave_ibss = mwifiex_cfg80211_leave_ibss,
-       .add_key = mwifiex_cfg80211_add_key,
-       .del_key = mwifiex_cfg80211_del_key,
-       .mgmt_tx = mwifiex_cfg80211_mgmt_tx,
-       .mgmt_frame_register = mwifiex_cfg80211_mgmt_frame_register,
-       .remain_on_channel = mwifiex_cfg80211_remain_on_channel,
-       .cancel_remain_on_channel = mwifiex_cfg80211_cancel_remain_on_channel,
-       .set_default_key = mwifiex_cfg80211_set_default_key,
-       .set_power_mgmt = mwifiex_cfg80211_set_power_mgmt,
-       .set_tx_power = mwifiex_cfg80211_set_tx_power,
-       .set_bitrate_mask = mwifiex_cfg80211_set_bitrate_mask,
-       .start_ap = mwifiex_cfg80211_start_ap,
-       .stop_ap = mwifiex_cfg80211_stop_ap,
-       .change_beacon = mwifiex_cfg80211_change_beacon,
-       .set_cqm_rssi_config = mwifiex_cfg80211_set_cqm_rssi_config,
-       .set_antenna = mwifiex_cfg80211_set_antenna,
-       .del_station = mwifiex_cfg80211_del_station,
-#ifdef CONFIG_PM
-       .suspend = mwifiex_cfg80211_suspend,
-       .resume = mwifiex_cfg80211_resume,
-       .set_wakeup = mwifiex_cfg80211_set_wakeup,
-#endif
-       .set_coalesce = mwifiex_cfg80211_set_coalesce,
-       .tdls_mgmt = mwifiex_cfg80211_tdls_mgmt,
-       .tdls_oper = mwifiex_cfg80211_tdls_oper,
-       .tdls_channel_switch = mwifiex_cfg80211_tdls_chan_switch,
-       .tdls_cancel_channel_switch = mwifiex_cfg80211_tdls_cancel_chan_switch,
-       .add_station = mwifiex_cfg80211_add_station,
-       .change_station = mwifiex_cfg80211_change_station,
-       .get_channel = mwifiex_cfg80211_get_channel,
-       .start_radar_detection = mwifiex_cfg80211_start_radar_detection,
-       .channel_switch = mwifiex_cfg80211_channel_switch,
-};
-
-#ifdef CONFIG_PM
-static const struct wiphy_wowlan_support mwifiex_wowlan_support = {
-       .flags = WIPHY_WOWLAN_MAGIC_PKT | WIPHY_WOWLAN_DISCONNECT,
-       .n_patterns = MWIFIEX_MEF_MAX_FILTERS,
-       .pattern_min_len = 1,
-       .pattern_max_len = MWIFIEX_MAX_PATTERN_LEN,
-       .max_pkt_offset = MWIFIEX_MAX_OFFSET_LEN,
-};
-#endif
-
-static bool mwifiex_is_valid_alpha2(const char *alpha2)
-{
-       if (!alpha2 || strlen(alpha2) != 2)
-               return false;
-
-       if (isalpha(alpha2[0]) && isalpha(alpha2[1]))
-               return true;
-
-       return false;
-}
-
-static const struct wiphy_coalesce_support mwifiex_coalesce_support = {
-       .n_rules = MWIFIEX_COALESCE_MAX_RULES,
-       .max_delay = MWIFIEX_MAX_COALESCING_DELAY,
-       .n_patterns = MWIFIEX_COALESCE_MAX_FILTERS,
-       .pattern_min_len = 1,
-       .pattern_max_len = MWIFIEX_MAX_PATTERN_LEN,
-       .max_pkt_offset = MWIFIEX_MAX_OFFSET_LEN,
-};
-
-int mwifiex_init_channel_scan_gap(struct mwifiex_adapter *adapter)
-{
-       u32 n_channels_bg, n_channels_a = 0;
-
-       n_channels_bg = mwifiex_band_2ghz.n_channels;
-
-       if (adapter->config_bands & BAND_A)
-               n_channels_a = mwifiex_band_5ghz.n_channels;
-
-       adapter->num_in_chan_stats = max_t(u32, n_channels_bg, n_channels_a);
-       adapter->chan_stats = vmalloc(sizeof(*adapter->chan_stats) *
-                                     adapter->num_in_chan_stats);
-
-       if (!adapter->chan_stats)
-               return -ENOMEM;
-
-       return 0;
-}
-
-/*
- * This function registers the device with CFG802.11 subsystem.
- *
- * The function creates the wireless device/wiphy, populates it with
- * default parameters and handler function pointers, and finally
- * registers the device.
- */
-
-int mwifiex_register_cfg80211(struct mwifiex_adapter *adapter)
-{
-       int ret;
-       void *wdev_priv;
-       struct wiphy *wiphy;
-       struct mwifiex_private *priv = adapter->priv[MWIFIEX_BSS_TYPE_STA];
-       u8 *country_code;
-       u32 thr, retry;
-
-       /* create a new wiphy for use with cfg80211 */
-       wiphy = wiphy_new(&mwifiex_cfg80211_ops,
-                         sizeof(struct mwifiex_adapter *));
-       if (!wiphy) {
-               mwifiex_dbg(adapter, ERROR,
-                           "%s: creating new wiphy\n", __func__);
-               return -ENOMEM;
-       }
-       wiphy->max_scan_ssids = MWIFIEX_MAX_SSID_LIST_LENGTH;
-       wiphy->max_scan_ie_len = MWIFIEX_MAX_VSIE_LEN;
-       wiphy->mgmt_stypes = mwifiex_mgmt_stypes;
-       wiphy->max_remain_on_channel_duration = 5000;
-       wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION) |
-                                BIT(NL80211_IFTYPE_ADHOC) |
-                                BIT(NL80211_IFTYPE_P2P_CLIENT) |
-                                BIT(NL80211_IFTYPE_P2P_GO) |
-                                BIT(NL80211_IFTYPE_AP);
-
-       wiphy->bands[IEEE80211_BAND_2GHZ] = &mwifiex_band_2ghz;
-       if (adapter->config_bands & BAND_A)
-               wiphy->bands[IEEE80211_BAND_5GHZ] = &mwifiex_band_5ghz;
-       else
-               wiphy->bands[IEEE80211_BAND_5GHZ] = NULL;
-
-       if (adapter->drcs_enabled && ISSUPP_DRCS_ENABLED(adapter->fw_cap_info))
-               wiphy->iface_combinations = &mwifiex_iface_comb_ap_sta_drcs;
-       else if (adapter->is_hw_11ac_capable)
-               wiphy->iface_combinations = &mwifiex_iface_comb_ap_sta_vht;
-       else
-               wiphy->iface_combinations = &mwifiex_iface_comb_ap_sta;
-       wiphy->n_iface_combinations = 1;
-
-       /* Initialize cipher suits */
-       wiphy->cipher_suites = mwifiex_cipher_suites;
-       wiphy->n_cipher_suites = ARRAY_SIZE(mwifiex_cipher_suites);
-
-       ether_addr_copy(wiphy->perm_addr, adapter->perm_addr);
-       wiphy->signal_type = CFG80211_SIGNAL_TYPE_MBM;
-       wiphy->flags |= WIPHY_FLAG_HAVE_AP_SME |
-                       WIPHY_FLAG_AP_PROBE_RESP_OFFLOAD |
-                       WIPHY_FLAG_AP_UAPSD |
-                       WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL |
-                       WIPHY_FLAG_HAS_CHANNEL_SWITCH |
-                       WIPHY_FLAG_PS_ON_BY_DEFAULT;
-
-       if (ISSUPP_TDLS_ENABLED(adapter->fw_cap_info))
-               wiphy->flags |= WIPHY_FLAG_SUPPORTS_TDLS |
-                               WIPHY_FLAG_TDLS_EXTERNAL_SETUP;
-
-#ifdef CONFIG_PM
-       wiphy->wowlan = &mwifiex_wowlan_support;
-#endif
-
-       wiphy->coalesce = &mwifiex_coalesce_support;
-
-       wiphy->probe_resp_offload = NL80211_PROBE_RESP_OFFLOAD_SUPPORT_WPS |
-                                   NL80211_PROBE_RESP_OFFLOAD_SUPPORT_WPS2 |
-                                   NL80211_PROBE_RESP_OFFLOAD_SUPPORT_P2P;
-
-       wiphy->available_antennas_tx = BIT(adapter->number_of_antenna) - 1;
-       wiphy->available_antennas_rx = BIT(adapter->number_of_antenna) - 1;
-
-       wiphy->features |= NL80211_FEATURE_HT_IBSS |
-                          NL80211_FEATURE_INACTIVITY_TIMER |
-                          NL80211_FEATURE_NEED_OBSS_SCAN;
-
-       if (ISSUPP_TDLS_ENABLED(adapter->fw_cap_info))
-               wiphy->features |= NL80211_FEATURE_TDLS_CHANNEL_SWITCH;
-
-       if (adapter->fw_api_ver == MWIFIEX_FW_V15)
-               wiphy->features |= NL80211_FEATURE_SK_TX_STATUS;
-
-       /* Reserve space for mwifiex specific private data for BSS */
-       wiphy->bss_priv_size = sizeof(struct mwifiex_bss_priv);
-
-       wiphy->reg_notifier = mwifiex_reg_notifier;
-
-       /* Set struct mwifiex_adapter pointer in wiphy_priv */
-       wdev_priv = wiphy_priv(wiphy);
-       *(unsigned long *)wdev_priv = (unsigned long)adapter;
-
-       set_wiphy_dev(wiphy, priv->adapter->dev);
-
-       ret = wiphy_register(wiphy);
-       if (ret < 0) {
-               mwifiex_dbg(adapter, ERROR,
-                           "%s: wiphy_register failed: %d\n", __func__, ret);
-               wiphy_free(wiphy);
-               return ret;
-       }
-
-       if (reg_alpha2 && mwifiex_is_valid_alpha2(reg_alpha2)) {
-               mwifiex_dbg(adapter, INFO,
-                           "driver hint alpha2: %2.2s\n", reg_alpha2);
-               regulatory_hint(wiphy, reg_alpha2);
-       } else {
-               country_code = mwifiex_11d_code_2_region(adapter->region_code);
-               if (country_code)
-                       mwifiex_dbg(adapter, WARN,
-                                   "ignoring F/W country code %2.2s\n",
-                                   country_code);
-       }
-
-       mwifiex_send_cmd(priv, HostCmd_CMD_802_11_SNMP_MIB,
-                        HostCmd_ACT_GEN_GET, FRAG_THRESH_I, &thr, true);
-       wiphy->frag_threshold = thr;
-       mwifiex_send_cmd(priv, HostCmd_CMD_802_11_SNMP_MIB,
-                        HostCmd_ACT_GEN_GET, RTS_THRESH_I, &thr, true);
-       wiphy->rts_threshold = thr;
-       mwifiex_send_cmd(priv, HostCmd_CMD_802_11_SNMP_MIB,
-                        HostCmd_ACT_GEN_GET, SHORT_RETRY_LIM_I, &retry, true);
-       wiphy->retry_short = (u8) retry;
-       mwifiex_send_cmd(priv, HostCmd_CMD_802_11_SNMP_MIB,
-                        HostCmd_ACT_GEN_GET, LONG_RETRY_LIM_I, &retry, true);
-       wiphy->retry_long = (u8) retry;
-
-       adapter->wiphy = wiphy;
-       return ret;
-}
diff --git a/drivers/net/wireless/mwifiex/cfg80211.h b/drivers/net/wireless/mwifiex/cfg80211.h
deleted file mode 100644 (file)
index 9083678..0000000
+++ /dev/null
@@ -1,29 +0,0 @@
-/*
- * Marvell Wireless LAN device driver: CFG80211
- *
- * Copyright (C) 2011-2014, Marvell International Ltd.
- *
- * This software file (the "File") is distributed by Marvell International
- * Ltd. under the terms of the GNU General Public License Version 2, June 1991
- * (the "License").  You may use, redistribute and/or modify this File in
- * accordance with the terms and conditions of the License, a copy of which
- * is available by writing to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the
- * worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
- *
- * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
- * ARE EXPRESSLY DISCLAIMED.  The License provides additional details about
- * this warranty disclaimer.
- */
-
-#ifndef __MWIFIEX_CFG80211__
-#define __MWIFIEX_CFG80211__
-
-#include <net/cfg80211.h>
-
-#include "main.h"
-
-int mwifiex_register_cfg80211(struct mwifiex_adapter *);
-
-#endif
diff --git a/drivers/net/wireless/mwifiex/cfp.c b/drivers/net/wireless/mwifiex/cfp.c
deleted file mode 100644 (file)
index 3ddb8ec..0000000
+++ /dev/null
@@ -1,537 +0,0 @@
-/*
- * Marvell Wireless LAN device driver: Channel, Frequence and Power
- *
- * Copyright (C) 2011-2014, Marvell International Ltd.
- *
- * This software file (the "File") is distributed by Marvell International
- * Ltd. under the terms of the GNU General Public License Version 2, June 1991
- * (the "License").  You may use, redistribute and/or modify this File in
- * accordance with the terms and conditions of the License, a copy of which
- * is available by writing to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the
- * worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
- *
- * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
- * ARE EXPRESSLY DISCLAIMED.  The License provides additional details about
- * this warranty disclaimer.
- */
-
-#include "decl.h"
-#include "ioctl.h"
-#include "util.h"
-#include "fw.h"
-#include "main.h"
-#include "cfg80211.h"
-
-/* 100mW */
-#define MWIFIEX_TX_PWR_DEFAULT     20
-/* 100mW */
-#define MWIFIEX_TX_PWR_US_DEFAULT      20
-/* 50mW */
-#define MWIFIEX_TX_PWR_JP_DEFAULT      16
-/* 100mW */
-#define MWIFIEX_TX_PWR_FR_100MW        20
-/* 10mW */
-#define MWIFIEX_TX_PWR_FR_10MW         10
-/* 100mW */
-#define MWIFIEX_TX_PWR_EMEA_DEFAULT    20
-
-static u8 adhoc_rates_b[B_SUPPORTED_RATES] = { 0x82, 0x84, 0x8b, 0x96, 0 };
-
-static u8 adhoc_rates_g[G_SUPPORTED_RATES] = { 0x8c, 0x12, 0x98, 0x24,
-                                              0xb0, 0x48, 0x60, 0x6c, 0 };
-
-static u8 adhoc_rates_bg[BG_SUPPORTED_RATES] = { 0x82, 0x84, 0x8b, 0x96,
-                                                0x0c, 0x12, 0x18, 0x24,
-                                                0x30, 0x48, 0x60, 0x6c, 0 };
-
-static u8 adhoc_rates_a[A_SUPPORTED_RATES] = { 0x8c, 0x12, 0x98, 0x24,
-                                              0xb0, 0x48, 0x60, 0x6c, 0 };
-static u8 supported_rates_a[A_SUPPORTED_RATES] = { 0x0c, 0x12, 0x18, 0x24,
-                                       0xb0, 0x48, 0x60, 0x6c, 0 };
-static u16 mwifiex_data_rates[MWIFIEX_SUPPORTED_RATES_EXT] = { 0x02, 0x04,
-                                       0x0B, 0x16, 0x00, 0x0C, 0x12, 0x18,
-                                       0x24, 0x30, 0x48, 0x60, 0x6C, 0x90,
-                                       0x0D, 0x1A, 0x27, 0x34, 0x4E, 0x68,
-                                       0x75, 0x82, 0x0C, 0x1B, 0x36, 0x51,
-                                       0x6C, 0xA2, 0xD8, 0xF3, 0x10E, 0x00 };
-
-static u8 supported_rates_b[B_SUPPORTED_RATES] = { 0x02, 0x04, 0x0b, 0x16, 0 };
-
-static u8 supported_rates_g[G_SUPPORTED_RATES] = { 0x0c, 0x12, 0x18, 0x24,
-                                       0x30, 0x48, 0x60, 0x6c, 0 };
-
-static u8 supported_rates_bg[BG_SUPPORTED_RATES] = { 0x02, 0x04, 0x0b, 0x0c,
-                                       0x12, 0x16, 0x18, 0x24, 0x30, 0x48,
-                                       0x60, 0x6c, 0 };
-
-u16 region_code_index[MWIFIEX_MAX_REGION_CODE] = { 0x10, 0x20, 0x30,
-                                               0x32, 0x40, 0x41, 0xff };
-
-static u8 supported_rates_n[N_SUPPORTED_RATES] = { 0x02, 0x04, 0 };
-
-/* For every mcs_rate line, the first 8 bytes are for stream 1x1,
- * and all 16 bytes are for stream 2x2.
- */
-static const u16 mcs_rate[4][16] = {
-       /* LGI 40M */
-       { 0x1b, 0x36, 0x51, 0x6c, 0xa2, 0xd8, 0xf3, 0x10e,
-         0x36, 0x6c, 0xa2, 0xd8, 0x144, 0x1b0, 0x1e6, 0x21c },
-
-       /* SGI 40M */
-       { 0x1e, 0x3c, 0x5a, 0x78, 0xb4, 0xf0, 0x10e, 0x12c,
-         0x3c, 0x78, 0xb4, 0xf0, 0x168, 0x1e0, 0x21c, 0x258 },
-
-       /* LGI 20M */
-       { 0x0d, 0x1a, 0x27, 0x34, 0x4e, 0x68, 0x75, 0x82,
-         0x1a, 0x34, 0x4e, 0x68, 0x9c, 0xd0, 0xea, 0x104 },
-
-       /* SGI 20M */
-       { 0x0e, 0x1c, 0x2b, 0x39, 0x56, 0x73, 0x82, 0x90,
-         0x1c, 0x39, 0x56, 0x73, 0xad, 0xe7, 0x104, 0x120 }
-};
-
-/* AC rates */
-static const u16 ac_mcs_rate_nss1[8][10] = {
-       /* LG 160M */
-       { 0x75, 0xEA, 0x15F, 0x1D4, 0x2BE, 0x3A8, 0x41D,
-         0x492, 0x57C, 0x618 },
-
-       /* SG 160M */
-       { 0x82, 0x104, 0x186, 0x208, 0x30C, 0x410, 0x492,
-         0x514, 0x618, 0x6C6 },
-
-       /* LG 80M */
-       { 0x3B, 0x75, 0xB0, 0xEA, 0x15F, 0x1D4, 0x20F,
-         0x249, 0x2BE, 0x30C },
-
-       /* SG 80M */
-       { 0x41, 0x82, 0xC3, 0x104, 0x186, 0x208, 0x249,
-         0x28A, 0x30C, 0x363 },
-
-       /* LG 40M */
-       { 0x1B, 0x36, 0x51, 0x6C, 0xA2, 0xD8, 0xF3,
-         0x10E, 0x144, 0x168 },
-
-       /* SG 40M */
-       { 0x1E, 0x3C, 0x5A, 0x78, 0xB4, 0xF0, 0x10E,
-         0x12C, 0x168, 0x190 },
-
-       /* LG 20M */
-       { 0xD, 0x1A, 0x27, 0x34, 0x4E, 0x68, 0x75, 0x82, 0x9C, 0x00 },
-
-       /* SG 20M */
-       { 0xF, 0x1D, 0x2C, 0x3A, 0x57, 0x74, 0x82, 0x91, 0xAE, 0x00 },
-};
-
-/* NSS2 note: the value in the table is 2 multiplier of the actual rate */
-static const u16 ac_mcs_rate_nss2[8][10] = {
-       /* LG 160M */
-       { 0xEA, 0x1D4, 0x2BE, 0x3A8, 0x57C, 0x750, 0x83A,
-         0x924, 0xAF8, 0xC30 },
-
-       /* SG 160M */
-       { 0x104, 0x208, 0x30C, 0x410, 0x618, 0x820, 0x924,
-         0xA28, 0xC30, 0xD8B },
-
-       /* LG 80M */
-       { 0x75, 0xEA, 0x15F, 0x1D4, 0x2BE, 0x3A8, 0x41D,
-         0x492, 0x57C, 0x618 },
-
-       /* SG 80M */
-       { 0x82, 0x104, 0x186, 0x208, 0x30C, 0x410, 0x492,
-         0x514, 0x618, 0x6C6 },
-
-       /* LG 40M */
-       { 0x36, 0x6C, 0xA2, 0xD8, 0x144, 0x1B0, 0x1E6,
-         0x21C, 0x288, 0x2D0 },
-
-       /* SG 40M */
-       { 0x3C, 0x78, 0xB4, 0xF0, 0x168, 0x1E0, 0x21C,
-         0x258, 0x2D0, 0x320 },
-
-       /* LG 20M */
-       { 0x1A, 0x34, 0x4A, 0x68, 0x9C, 0xD0, 0xEA, 0x104,
-         0x138, 0x00 },
-
-       /* SG 20M */
-       { 0x1D, 0x3A, 0x57, 0x74, 0xAE, 0xE6, 0x104, 0x121,
-         0x15B, 0x00 },
-};
-
-struct region_code_mapping {
-       u8 code;
-       u8 region[IEEE80211_COUNTRY_STRING_LEN];
-};
-
-static struct region_code_mapping region_code_mapping_t[] = {
-       { 0x10, "US " }, /* US FCC */
-       { 0x20, "CA " }, /* IC Canada */
-       { 0x30, "EU " }, /* ETSI */
-       { 0x31, "ES " }, /* Spain */
-       { 0x32, "FR " }, /* France */
-       { 0x40, "JP " }, /* Japan */
-       { 0x41, "JP " }, /* Japan */
-       { 0x50, "CN " }, /* China */
-};
-
-/* This function converts integer code to region string */
-u8 *mwifiex_11d_code_2_region(u8 code)
-{
-       u8 i;
-       u8 size = sizeof(region_code_mapping_t)/
-                               sizeof(struct region_code_mapping);
-
-       /* Look for code in mapping table */
-       for (i = 0; i < size; i++)
-               if (region_code_mapping_t[i].code == code)
-                       return region_code_mapping_t[i].region;
-
-       return NULL;
-}
-
-/*
- * This function maps an index in supported rates table into
- * the corresponding data rate.
- */
-u32 mwifiex_index_to_acs_data_rate(struct mwifiex_private *priv,
-                                  u8 index, u8 ht_info)
-{
-       u32 rate = 0;
-       u8 mcs_index = 0;
-       u8 bw = 0;
-       u8 gi = 0;
-
-       if ((ht_info & 0x3) == MWIFIEX_RATE_FORMAT_VHT) {
-               mcs_index = min(index & 0xF, 9);
-
-               /* 20M: bw=0, 40M: bw=1, 80M: bw=2, 160M: bw=3 */
-               bw = (ht_info & 0xC) >> 2;
-
-               /* LGI: gi =0, SGI: gi = 1 */
-               gi = (ht_info & 0x10) >> 4;
-
-               if ((index >> 4) == 1)  /* NSS = 2 */
-                       rate = ac_mcs_rate_nss2[2 * (3 - bw) + gi][mcs_index];
-               else                    /* NSS = 1 */
-                       rate = ac_mcs_rate_nss1[2 * (3 - bw) + gi][mcs_index];
-       } else if ((ht_info & 0x3) == MWIFIEX_RATE_FORMAT_HT) {
-               /* 20M: bw=0, 40M: bw=1 */
-               bw = (ht_info & 0xC) >> 2;
-
-               /* LGI: gi =0, SGI: gi = 1 */
-               gi = (ht_info & 0x10) >> 4;
-
-               if (index == MWIFIEX_RATE_BITMAP_MCS0) {
-                       if (gi == 1)
-                               rate = 0x0D;    /* MCS 32 SGI rate */
-                       else
-                               rate = 0x0C;    /* MCS 32 LGI rate */
-               } else if (index < 16) {
-                       if ((bw == 1) || (bw == 0))
-                               rate = mcs_rate[2 * (1 - bw) + gi][index];
-                       else
-                               rate = mwifiex_data_rates[0];
-               } else {
-                       rate = mwifiex_data_rates[0];
-               }
-       } else {
-               /* 11n non-HT rates */
-               if (index >= MWIFIEX_SUPPORTED_RATES_EXT)
-                       index = 0;
-               rate = mwifiex_data_rates[index];
-       }
-
-       return rate;
-}
-
-/* This function maps an index in supported rates table into
- * the corresponding data rate.
- */
-u32 mwifiex_index_to_data_rate(struct mwifiex_private *priv,
-                              u8 index, u8 ht_info)
-{
-       u32 mcs_num_supp =
-               (priv->adapter->user_dev_mcs_support == HT_STREAM_2X2) ? 16 : 8;
-       u32 rate;
-
-       if (priv->adapter->is_hw_11ac_capable)
-               return mwifiex_index_to_acs_data_rate(priv, index, ht_info);
-
-       if (ht_info & BIT(0)) {
-               if (index == MWIFIEX_RATE_BITMAP_MCS0) {
-                       if (ht_info & BIT(2))
-                               rate = 0x0D;    /* MCS 32 SGI rate */
-                       else
-                               rate = 0x0C;    /* MCS 32 LGI rate */
-               } else if (index < mcs_num_supp) {
-                       if (ht_info & BIT(1)) {
-                               if (ht_info & BIT(2))
-                                       /* SGI, 40M */
-                                       rate = mcs_rate[1][index];
-                               else
-                                       /* LGI, 40M */
-                                       rate = mcs_rate[0][index];
-                       } else {
-                               if (ht_info & BIT(2))
-                                       /* SGI, 20M */
-                                       rate = mcs_rate[3][index];
-                               else
-                                       /* LGI, 20M */
-                                       rate = mcs_rate[2][index];
-                       }
-               } else
-                       rate = mwifiex_data_rates[0];
-       } else {
-               if (index >= MWIFIEX_SUPPORTED_RATES_EXT)
-                       index = 0;
-               rate = mwifiex_data_rates[index];
-       }
-       return rate;
-}
-
-/*
- * This function returns the current active data rates.
- *
- * The result may vary depending upon connection status.
- */
-u32 mwifiex_get_active_data_rates(struct mwifiex_private *priv, u8 *rates)
-{
-       if (!priv->media_connected)
-               return mwifiex_get_supported_rates(priv, rates);
-       else
-               return mwifiex_copy_rates(rates, 0,
-                                         priv->curr_bss_params.data_rates,
-                                         priv->curr_bss_params.num_of_rates);
-}
-
-/*
- * This function locates the Channel-Frequency-Power triplet based upon
- * band and channel/frequency parameters.
- */
-struct mwifiex_chan_freq_power *
-mwifiex_get_cfp(struct mwifiex_private *priv, u8 band, u16 channel, u32 freq)
-{
-       struct mwifiex_chan_freq_power *cfp = NULL;
-       struct ieee80211_supported_band *sband;
-       struct ieee80211_channel *ch = NULL;
-       int i;
-
-       if (!channel && !freq)
-               return cfp;
-
-       if (mwifiex_band_to_radio_type(band) == HostCmd_SCAN_RADIO_TYPE_BG)
-               sband = priv->wdev.wiphy->bands[IEEE80211_BAND_2GHZ];
-       else
-               sband = priv->wdev.wiphy->bands[IEEE80211_BAND_5GHZ];
-
-       if (!sband) {
-               mwifiex_dbg(priv->adapter, ERROR,
-                           "%s: cannot find cfp by band %d\n",
-                           __func__, band);
-               return cfp;
-       }
-
-       for (i = 0; i < sband->n_channels; i++) {
-               ch = &sband->channels[i];
-
-               if (ch->flags & IEEE80211_CHAN_DISABLED)
-                       continue;
-
-               if (freq) {
-                       if (ch->center_freq == freq)
-                               break;
-               } else {
-                       /* find by valid channel*/
-                       if (ch->hw_value == channel ||
-                           channel == FIRST_VALID_CHANNEL)
-                               break;
-               }
-       }
-       if (i == sband->n_channels) {
-               mwifiex_dbg(priv->adapter, ERROR,
-                           "%s: cannot find cfp by band %d\t"
-                           "& channel=%d freq=%d\n",
-                           __func__, band, channel, freq);
-       } else {
-               if (!ch)
-                       return cfp;
-
-               priv->cfp.channel = ch->hw_value;
-               priv->cfp.freq = ch->center_freq;
-               priv->cfp.max_tx_power = ch->max_power;
-               cfp = &priv->cfp;
-       }
-
-       return cfp;
-}
-
-/*
- * This function checks if the data rate is set to auto.
- */
-u8
-mwifiex_is_rate_auto(struct mwifiex_private *priv)
-{
-       u32 i;
-       int rate_num = 0;
-
-       for (i = 0; i < ARRAY_SIZE(priv->bitmap_rates); i++)
-               if (priv->bitmap_rates[i])
-                       rate_num++;
-
-       if (rate_num > 1)
-               return true;
-       else
-               return false;
-}
-
-/* This function gets the supported data rates from bitmask inside
- * cfg80211_scan_request.
- */
-u32 mwifiex_get_rates_from_cfg80211(struct mwifiex_private *priv,
-                                   u8 *rates, u8 radio_type)
-{
-       struct wiphy *wiphy = priv->adapter->wiphy;
-       struct cfg80211_scan_request *request = priv->scan_request;
-       u32 num_rates, rate_mask;
-       struct ieee80211_supported_band *sband;
-       int i;
-
-       if (radio_type) {
-               sband = wiphy->bands[IEEE80211_BAND_5GHZ];
-               if (WARN_ON_ONCE(!sband))
-                       return 0;
-               rate_mask = request->rates[IEEE80211_BAND_5GHZ];
-       } else {
-               sband = wiphy->bands[IEEE80211_BAND_2GHZ];
-               if (WARN_ON_ONCE(!sband))
-                       return 0;
-               rate_mask = request->rates[IEEE80211_BAND_2GHZ];
-       }
-
-       num_rates = 0;
-       for (i = 0; i < sband->n_bitrates; i++) {
-               if ((BIT(i) & rate_mask) == 0)
-                       continue; /* skip rate */
-               rates[num_rates++] = (u8)(sband->bitrates[i].bitrate / 5);
-       }
-
-       return num_rates;
-}
-
-/* This function gets the supported data rates. The function works in
- * both Ad-Hoc and infra mode by printing the band and returning the
- * data rates.
- */
-u32 mwifiex_get_supported_rates(struct mwifiex_private *priv, u8 *rates)
-{
-       u32 k = 0;
-       struct mwifiex_adapter *adapter = priv->adapter;
-
-       if (priv->bss_mode == NL80211_IFTYPE_STATION ||
-           priv->bss_mode == NL80211_IFTYPE_P2P_CLIENT) {
-               switch (adapter->config_bands) {
-               case BAND_B:
-                       mwifiex_dbg(adapter, INFO, "info: infra band=%d\t"
-                                   "supported_rates_b\n",
-                                   adapter->config_bands);
-                       k = mwifiex_copy_rates(rates, k, supported_rates_b,
-                                              sizeof(supported_rates_b));
-                       break;
-               case BAND_G:
-               case BAND_G | BAND_GN:
-                       mwifiex_dbg(adapter, INFO, "info: infra band=%d\t"
-                                   "supported_rates_g\n",
-                                   adapter->config_bands);
-                       k = mwifiex_copy_rates(rates, k, supported_rates_g,
-                                              sizeof(supported_rates_g));
-                       break;
-               case BAND_B | BAND_G:
-               case BAND_A | BAND_B | BAND_G:
-               case BAND_A | BAND_B:
-               case BAND_A | BAND_B | BAND_G | BAND_GN | BAND_AN:
-               case BAND_A | BAND_B | BAND_G | BAND_GN | BAND_AN | BAND_AAC:
-               case BAND_B | BAND_G | BAND_GN:
-                       mwifiex_dbg(adapter, INFO, "info: infra band=%d\t"
-                                   "supported_rates_bg\n",
-                                   adapter->config_bands);
-                       k = mwifiex_copy_rates(rates, k, supported_rates_bg,
-                                              sizeof(supported_rates_bg));
-                       break;
-               case BAND_A:
-               case BAND_A | BAND_G:
-                       mwifiex_dbg(adapter, INFO, "info: infra band=%d\t"
-                                   "supported_rates_a\n",
-                                   adapter->config_bands);
-                       k = mwifiex_copy_rates(rates, k, supported_rates_a,
-                                              sizeof(supported_rates_a));
-                       break;
-               case BAND_AN:
-               case BAND_A | BAND_AN:
-               case BAND_A | BAND_AN | BAND_AAC:
-               case BAND_A | BAND_G | BAND_AN | BAND_GN:
-               case BAND_A | BAND_G | BAND_AN | BAND_GN | BAND_AAC:
-                       mwifiex_dbg(adapter, INFO, "info: infra band=%d\t"
-                                   "supported_rates_a\n",
-                                   adapter->config_bands);
-                       k = mwifiex_copy_rates(rates, k, supported_rates_a,
-                                              sizeof(supported_rates_a));
-                       break;
-               case BAND_GN:
-                       mwifiex_dbg(adapter, INFO, "info: infra band=%d\t"
-                                   "supported_rates_n\n",
-                                   adapter->config_bands);
-                       k = mwifiex_copy_rates(rates, k, supported_rates_n,
-                                              sizeof(supported_rates_n));
-                       break;
-               }
-       } else {
-               /* Ad-hoc mode */
-               switch (adapter->adhoc_start_band) {
-               case BAND_B:
-                       mwifiex_dbg(adapter, INFO, "info: adhoc B\n");
-                       k = mwifiex_copy_rates(rates, k, adhoc_rates_b,
-                                              sizeof(adhoc_rates_b));
-                       break;
-               case BAND_G:
-               case BAND_G | BAND_GN:
-                       mwifiex_dbg(adapter, INFO, "info: adhoc G only\n");
-                       k = mwifiex_copy_rates(rates, k, adhoc_rates_g,
-                                              sizeof(adhoc_rates_g));
-                       break;
-               case BAND_B | BAND_G:
-               case BAND_B | BAND_G | BAND_GN:
-                       mwifiex_dbg(adapter, INFO, "info: adhoc BG\n");
-                       k = mwifiex_copy_rates(rates, k, adhoc_rates_bg,
-                                              sizeof(adhoc_rates_bg));
-                       break;
-               case BAND_A:
-               case BAND_A | BAND_AN:
-                       mwifiex_dbg(adapter, INFO, "info: adhoc A\n");
-                       k = mwifiex_copy_rates(rates, k, adhoc_rates_a,
-                                              sizeof(adhoc_rates_a));
-                       break;
-               }
-       }
-
-       return k;
-}
-
-u8 mwifiex_adjust_data_rate(struct mwifiex_private *priv,
-                           u8 rx_rate, u8 rate_info)
-{
-       u8 rate_index = 0;
-
-       /* HT40 */
-       if ((rate_info & BIT(0)) && (rate_info & BIT(1)))
-               rate_index = MWIFIEX_RATE_INDEX_MCS0 +
-                            MWIFIEX_BW20_MCS_NUM + rx_rate;
-       else if (rate_info & BIT(0)) /* HT20 */
-               rate_index = MWIFIEX_RATE_INDEX_MCS0 + rx_rate;
-       else
-               rate_index = (rx_rate > MWIFIEX_RATE_INDEX_OFDM0) ?
-                             rx_rate - 1 : rx_rate;
-
-       return rate_index;
-}
diff --git a/drivers/net/wireless/mwifiex/cmdevt.c b/drivers/net/wireless/mwifiex/cmdevt.c
deleted file mode 100644 (file)
index 45ae38e..0000000
+++ /dev/null
@@ -1,1659 +0,0 @@
-/*
- * Marvell Wireless LAN device driver: commands and events
- *
- * Copyright (C) 2011-2014, Marvell International Ltd.
- *
- * This software file (the "File") is distributed by Marvell International
- * Ltd. under the terms of the GNU General Public License Version 2, June 1991
- * (the "License").  You may use, redistribute and/or modify this File in
- * accordance with the terms and conditions of the License, a copy of which
- * is available by writing to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the
- * worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
- *
- * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
- * ARE EXPRESSLY DISCLAIMED.  The License provides additional details about
- * this warranty disclaimer.
- */
-
-#include "decl.h"
-#include "ioctl.h"
-#include "util.h"
-#include "fw.h"
-#include "main.h"
-#include "wmm.h"
-#include "11n.h"
-#include "11ac.h"
-
-/*
- * This function initializes a command node.
- *
- * The actual allocation of the node is not done by this function. It only
- * initiates a node by filling it with default parameters. Similarly,
- * allocation of the different buffers used (IOCTL buffer, data buffer) are
- * not done by this function either.
- */
-static void
-mwifiex_init_cmd_node(struct mwifiex_private *priv,
-                     struct cmd_ctrl_node *cmd_node,
-                     u32 cmd_oid, void *data_buf, bool sync)
-{
-       cmd_node->priv = priv;
-       cmd_node->cmd_oid = cmd_oid;
-       if (sync) {
-               cmd_node->wait_q_enabled = true;
-               cmd_node->cmd_wait_q_woken = false;
-               cmd_node->condition = &cmd_node->cmd_wait_q_woken;
-       }
-       cmd_node->data_buf = data_buf;
-       cmd_node->cmd_skb = cmd_node->skb;
-}
-
-/*
- * This function returns a command node from the free queue depending upon
- * availability.
- */
-static struct cmd_ctrl_node *
-mwifiex_get_cmd_node(struct mwifiex_adapter *adapter)
-{
-       struct cmd_ctrl_node *cmd_node;
-       unsigned long flags;
-
-       spin_lock_irqsave(&adapter->cmd_free_q_lock, flags);
-       if (list_empty(&adapter->cmd_free_q)) {
-               mwifiex_dbg(adapter, ERROR,
-                           "GET_CMD_NODE: cmd node not available\n");
-               spin_unlock_irqrestore(&adapter->cmd_free_q_lock, flags);
-               return NULL;
-       }
-       cmd_node = list_first_entry(&adapter->cmd_free_q,
-                                   struct cmd_ctrl_node, list);
-       list_del(&cmd_node->list);
-       spin_unlock_irqrestore(&adapter->cmd_free_q_lock, flags);
-
-       return cmd_node;
-}
-
-/*
- * This function cleans up a command node.
- *
- * The function resets the fields including the buffer pointers.
- * This function does not try to free the buffers. They must be
- * freed before calling this function.
- *
- * This function will however call the receive completion callback
- * in case a response buffer is still available before resetting
- * the pointer.
- */
-static void
-mwifiex_clean_cmd_node(struct mwifiex_adapter *adapter,
-                      struct cmd_ctrl_node *cmd_node)
-{
-       cmd_node->cmd_oid = 0;
-       cmd_node->cmd_flag = 0;
-       cmd_node->data_buf = NULL;
-       cmd_node->wait_q_enabled = false;
-
-       if (cmd_node->cmd_skb)
-               skb_trim(cmd_node->cmd_skb, 0);
-
-       if (cmd_node->resp_skb) {
-               adapter->if_ops.cmdrsp_complete(adapter, cmd_node->resp_skb);
-               cmd_node->resp_skb = NULL;
-       }
-}
-
-/*
- * This function sends a host command to the firmware.
- *
- * The function copies the host command into the driver command
- * buffer, which will be transferred to the firmware later by the
- * main thread.
- */
-static int mwifiex_cmd_host_cmd(struct mwifiex_private *priv,
-                               struct host_cmd_ds_command *cmd,
-                               struct mwifiex_ds_misc_cmd *pcmd_ptr)
-{
-       /* Copy the HOST command to command buffer */
-       memcpy(cmd, pcmd_ptr->cmd, pcmd_ptr->len);
-       mwifiex_dbg(priv->adapter, CMD,
-                   "cmd: host cmd size = %d\n", pcmd_ptr->len);
-       return 0;
-}
-
-/*
- * This function downloads a command to the firmware.
- *
- * The function performs sanity tests, sets the command sequence
- * number and size, converts the header fields to CPU format before
- * sending. Afterwards, it logs the command ID and action for debugging
- * and sets up the command timeout timer.
- */
-static int mwifiex_dnld_cmd_to_fw(struct mwifiex_private *priv,
-                                 struct cmd_ctrl_node *cmd_node)
-{
-
-       struct mwifiex_adapter *adapter = priv->adapter;
-       int ret;
-       struct host_cmd_ds_command *host_cmd;
-       uint16_t cmd_code;
-       uint16_t cmd_size;
-       unsigned long flags;
-       __le32 tmp;
-
-       if (!adapter || !cmd_node)
-               return -1;
-
-       host_cmd = (struct host_cmd_ds_command *) (cmd_node->cmd_skb->data);
-
-       /* Sanity test */
-       if (host_cmd == NULL || host_cmd->size == 0) {
-               mwifiex_dbg(adapter, ERROR,
-                           "DNLD_CMD: host_cmd is null\t"
-                           "or cmd size is 0, not sending\n");
-               if (cmd_node->wait_q_enabled)
-                       adapter->cmd_wait_q.status = -1;
-               mwifiex_recycle_cmd_node(adapter, cmd_node);
-               return -1;
-       }
-
-       cmd_code = le16_to_cpu(host_cmd->command);
-       cmd_size = le16_to_cpu(host_cmd->size);
-
-       if (adapter->hw_status == MWIFIEX_HW_STATUS_RESET &&
-           cmd_code != HostCmd_CMD_FUNC_SHUTDOWN &&
-           cmd_code != HostCmd_CMD_FUNC_INIT) {
-               mwifiex_dbg(adapter, ERROR,
-                           "DNLD_CMD: FW in reset state, ignore cmd %#x\n",
-                       cmd_code);
-               mwifiex_recycle_cmd_node(adapter, cmd_node);
-               queue_work(adapter->workqueue, &adapter->main_work);
-               return -1;
-       }
-
-       /* Set command sequence number */
-       adapter->seq_num++;
-       host_cmd->seq_num = cpu_to_le16(HostCmd_SET_SEQ_NO_BSS_INFO
-                                       (adapter->seq_num,
-                                        cmd_node->priv->bss_num,
-                                        cmd_node->priv->bss_type));
-
-       spin_lock_irqsave(&adapter->mwifiex_cmd_lock, flags);
-       adapter->curr_cmd = cmd_node;
-       spin_unlock_irqrestore(&adapter->mwifiex_cmd_lock, flags);
-
-       /* Adjust skb length */
-       if (cmd_node->cmd_skb->len > cmd_size)
-               /*
-                * cmd_size is less than sizeof(struct host_cmd_ds_command).
-                * Trim off the unused portion.
-                */
-               skb_trim(cmd_node->cmd_skb, cmd_size);
-       else if (cmd_node->cmd_skb->len < cmd_size)
-               /*
-                * cmd_size is larger than sizeof(struct host_cmd_ds_command)
-                * because we have appended custom IE TLV. Increase skb length
-                * accordingly.
-                */
-               skb_put(cmd_node->cmd_skb, cmd_size - cmd_node->cmd_skb->len);
-
-       mwifiex_dbg(adapter, CMD,
-                   "cmd: DNLD_CMD: %#x, act %#x, len %d, seqno %#x\n",
-                   cmd_code,
-                   le16_to_cpu(*(__le16 *)((u8 *)host_cmd + S_DS_GEN)),
-                   cmd_size, le16_to_cpu(host_cmd->seq_num));
-       mwifiex_dbg_dump(adapter, CMD_D, "cmd buffer:", host_cmd, cmd_size);
-
-       if (adapter->iface_type == MWIFIEX_USB) {
-               tmp = cpu_to_le32(MWIFIEX_USB_TYPE_CMD);
-               skb_push(cmd_node->cmd_skb, MWIFIEX_TYPE_LEN);
-               memcpy(cmd_node->cmd_skb->data, &tmp, MWIFIEX_TYPE_LEN);
-               adapter->cmd_sent = true;
-               ret = adapter->if_ops.host_to_card(adapter,
-                                                  MWIFIEX_USB_EP_CMD_EVENT,
-                                                  cmd_node->cmd_skb, NULL);
-               skb_pull(cmd_node->cmd_skb, MWIFIEX_TYPE_LEN);
-               if (ret == -EBUSY)
-                       cmd_node->cmd_skb = NULL;
-       } else {
-               skb_push(cmd_node->cmd_skb, INTF_HEADER_LEN);
-               ret = adapter->if_ops.host_to_card(adapter, MWIFIEX_TYPE_CMD,
-                                                  cmd_node->cmd_skb, NULL);
-               skb_pull(cmd_node->cmd_skb, INTF_HEADER_LEN);
-       }
-
-       if (ret == -1) {
-               mwifiex_dbg(adapter, ERROR,
-                           "DNLD_CMD: host to card failed\n");
-               if (adapter->iface_type == MWIFIEX_USB)
-                       adapter->cmd_sent = false;
-               if (cmd_node->wait_q_enabled)
-                       adapter->cmd_wait_q.status = -1;
-               mwifiex_recycle_cmd_node(adapter, adapter->curr_cmd);
-
-               spin_lock_irqsave(&adapter->mwifiex_cmd_lock, flags);
-               adapter->curr_cmd = NULL;
-               spin_unlock_irqrestore(&adapter->mwifiex_cmd_lock, flags);
-
-               adapter->dbg.num_cmd_host_to_card_failure++;
-               return -1;
-       }
-
-       /* Save the last command id and action to debug log */
-       adapter->dbg.last_cmd_index =
-                       (adapter->dbg.last_cmd_index + 1) % DBG_CMD_NUM;
-       adapter->dbg.last_cmd_id[adapter->dbg.last_cmd_index] = cmd_code;
-       adapter->dbg.last_cmd_act[adapter->dbg.last_cmd_index] =
-                       le16_to_cpu(*(__le16 *) ((u8 *) host_cmd + S_DS_GEN));
-
-       /* Clear BSS_NO_BITS from HostCmd */
-       cmd_code &= HostCmd_CMD_ID_MASK;
-
-       /* Setup the timer after transmit command */
-       mod_timer(&adapter->cmd_timer,
-                 jiffies + msecs_to_jiffies(MWIFIEX_TIMER_10S));
-
-       return 0;
-}
-
-/*
- * This function downloads a sleep confirm command to the firmware.
- *
- * The function performs sanity tests, sets the command sequence
- * number and size, converts the header fields to CPU format before
- * sending.
- *
- * No responses are needed for sleep confirm command.
- */
-static int mwifiex_dnld_sleep_confirm_cmd(struct mwifiex_adapter *adapter)
-{
-       int ret;
-       struct mwifiex_private *priv;
-       struct mwifiex_opt_sleep_confirm *sleep_cfm_buf =
-                               (struct mwifiex_opt_sleep_confirm *)
-                                               adapter->sleep_cfm->data;
-       struct sk_buff *sleep_cfm_tmp;
-       __le32 tmp;
-
-       priv = mwifiex_get_priv(adapter, MWIFIEX_BSS_ROLE_ANY);
-
-       adapter->seq_num++;
-       sleep_cfm_buf->seq_num =
-               cpu_to_le16((HostCmd_SET_SEQ_NO_BSS_INFO
-                                       (adapter->seq_num, priv->bss_num,
-                                        priv->bss_type)));
-
-       mwifiex_dbg(adapter, CMD,
-                   "cmd: DNLD_CMD: %#x, act %#x, len %d, seqno %#x\n",
-               le16_to_cpu(sleep_cfm_buf->command),
-               le16_to_cpu(sleep_cfm_buf->action),
-               le16_to_cpu(sleep_cfm_buf->size),
-               le16_to_cpu(sleep_cfm_buf->seq_num));
-       mwifiex_dbg_dump(adapter, CMD_D, "SLEEP_CFM buffer: ", sleep_cfm_buf,
-                        le16_to_cpu(sleep_cfm_buf->size));
-
-       if (adapter->iface_type == MWIFIEX_USB) {
-               sleep_cfm_tmp =
-                       dev_alloc_skb(sizeof(struct mwifiex_opt_sleep_confirm)
-                                     + MWIFIEX_TYPE_LEN);
-               skb_put(sleep_cfm_tmp, sizeof(struct mwifiex_opt_sleep_confirm)
-                       + MWIFIEX_TYPE_LEN);
-               tmp = cpu_to_le32(MWIFIEX_USB_TYPE_CMD);
-               memcpy(sleep_cfm_tmp->data, &tmp, MWIFIEX_TYPE_LEN);
-               memcpy(sleep_cfm_tmp->data + MWIFIEX_TYPE_LEN,
-                      adapter->sleep_cfm->data,
-                      sizeof(struct mwifiex_opt_sleep_confirm));
-               ret = adapter->if_ops.host_to_card(adapter,
-                                                  MWIFIEX_USB_EP_CMD_EVENT,
-                                                  sleep_cfm_tmp, NULL);
-               if (ret != -EBUSY)
-                       dev_kfree_skb_any(sleep_cfm_tmp);
-       } else {
-               skb_push(adapter->sleep_cfm, INTF_HEADER_LEN);
-               ret = adapter->if_ops.host_to_card(adapter, MWIFIEX_TYPE_CMD,
-                                                  adapter->sleep_cfm, NULL);
-               skb_pull(adapter->sleep_cfm, INTF_HEADER_LEN);
-       }
-
-       if (ret == -1) {
-               mwifiex_dbg(adapter, ERROR, "SLEEP_CFM: failed\n");
-               adapter->dbg.num_cmd_sleep_cfm_host_to_card_failure++;
-               return -1;
-       }
-
-       if (!le16_to_cpu(sleep_cfm_buf->resp_ctrl))
-               /* Response is not needed for sleep confirm command */
-               adapter->ps_state = PS_STATE_SLEEP;
-       else
-               adapter->ps_state = PS_STATE_SLEEP_CFM;
-
-       if (!le16_to_cpu(sleep_cfm_buf->resp_ctrl) &&
-           (adapter->is_hs_configured &&
-            !adapter->sleep_period.period)) {
-               adapter->pm_wakeup_card_req = true;
-               mwifiex_hs_activated_event(mwifiex_get_priv
-                               (adapter, MWIFIEX_BSS_ROLE_ANY), true);
-       }
-
-       return ret;
-}
-
-/*
- * This function allocates the command buffers and links them to
- * the command free queue.
- *
- * The driver uses a pre allocated number of command buffers, which
- * are created at driver initializations and freed at driver cleanup.
- * Every command needs to obtain a command buffer from this pool before
- * it can be issued. The command free queue lists the command buffers
- * currently free to use, while the command pending queue lists the
- * command buffers already in use and awaiting handling. Command buffers
- * are returned to the free queue after use.
- */
-int mwifiex_alloc_cmd_buffer(struct mwifiex_adapter *adapter)
-{
-       struct cmd_ctrl_node *cmd_array;
-       u32 i;
-
-       /* Allocate and initialize struct cmd_ctrl_node */
-       cmd_array = kcalloc(MWIFIEX_NUM_OF_CMD_BUFFER,
-                           sizeof(struct cmd_ctrl_node), GFP_KERNEL);
-       if (!cmd_array)
-               return -ENOMEM;
-
-       adapter->cmd_pool = cmd_array;
-
-       /* Allocate and initialize command buffers */
-       for (i = 0; i < MWIFIEX_NUM_OF_CMD_BUFFER; i++) {
-               cmd_array[i].skb = dev_alloc_skb(MWIFIEX_SIZE_OF_CMD_BUFFER);
-               if (!cmd_array[i].skb) {
-                       mwifiex_dbg(adapter, ERROR,
-                                   "unable to allocate command buffer\n");
-                       return -ENOMEM;
-               }
-       }
-
-       for (i = 0; i < MWIFIEX_NUM_OF_CMD_BUFFER; i++)
-               mwifiex_insert_cmd_to_free_q(adapter, &cmd_array[i]);
-
-       return 0;
-}
-
-/*
- * This function frees the command buffers.
- *
- * The function calls the completion callback for all the command
- * buffers that still have response buffers associated with them.
- */
-int mwifiex_free_cmd_buffer(struct mwifiex_adapter *adapter)
-{
-       struct cmd_ctrl_node *cmd_array;
-       u32 i;
-
-       /* Need to check if cmd pool is allocated or not */
-       if (!adapter->cmd_pool) {
-               mwifiex_dbg(adapter, FATAL,
-                           "info: FREE_CMD_BUF: cmd_pool is null\n");
-               return 0;
-       }
-
-       cmd_array = adapter->cmd_pool;
-
-       /* Release shared memory buffers */
-       for (i = 0; i < MWIFIEX_NUM_OF_CMD_BUFFER; i++) {
-               if (cmd_array[i].skb) {
-                       mwifiex_dbg(adapter, CMD,
-                                   "cmd: free cmd buffer %d\n", i);
-                       dev_kfree_skb_any(cmd_array[i].skb);
-               }
-               if (!cmd_array[i].resp_skb)
-                       continue;
-
-               if (adapter->iface_type == MWIFIEX_USB)
-                       adapter->if_ops.cmdrsp_complete(adapter,
-                                                       cmd_array[i].resp_skb);
-               else
-                       dev_kfree_skb_any(cmd_array[i].resp_skb);
-       }
-       /* Release struct cmd_ctrl_node */
-       if (adapter->cmd_pool) {
-               mwifiex_dbg(adapter, CMD,
-                           "cmd: free cmd pool\n");
-               kfree(adapter->cmd_pool);
-               adapter->cmd_pool = NULL;
-       }
-
-       return 0;
-}
-
-/*
- * This function handles events generated by firmware.
- *
- * Event body of events received from firmware are not used (though they are
- * saved), only the event ID is used. Some events are re-invoked by
- * the driver, with a new event body.
- *
- * After processing, the function calls the completion callback
- * for cleanup.
- */
-int mwifiex_process_event(struct mwifiex_adapter *adapter)
-{
-       int ret;
-       struct mwifiex_private *priv =
-               mwifiex_get_priv(adapter, MWIFIEX_BSS_ROLE_ANY);
-       struct sk_buff *skb = adapter->event_skb;
-       u32 eventcause = adapter->event_cause;
-       struct mwifiex_rxinfo *rx_info;
-
-       /* Save the last event to debug log */
-       adapter->dbg.last_event_index =
-                       (adapter->dbg.last_event_index + 1) % DBG_CMD_NUM;
-       adapter->dbg.last_event[adapter->dbg.last_event_index] =
-                                                       (u16) eventcause;
-
-       /* Get BSS number and corresponding priv */
-       priv = mwifiex_get_priv_by_id(adapter, EVENT_GET_BSS_NUM(eventcause),
-                                     EVENT_GET_BSS_TYPE(eventcause));
-       if (!priv)
-               priv = mwifiex_get_priv(adapter, MWIFIEX_BSS_ROLE_ANY);
-
-       /* Clear BSS_NO_BITS from event */
-       eventcause &= EVENT_ID_MASK;
-       adapter->event_cause = eventcause;
-
-       if (skb) {
-               rx_info = MWIFIEX_SKB_RXCB(skb);
-               memset(rx_info, 0, sizeof(*rx_info));
-               rx_info->bss_num = priv->bss_num;
-               rx_info->bss_type = priv->bss_type;
-               mwifiex_dbg_dump(adapter, EVT_D, "Event Buf:",
-                                skb->data, skb->len);
-       }
-
-       mwifiex_dbg(adapter, EVENT, "EVENT: cause: %#x\n", eventcause);
-
-       if (priv->bss_role == MWIFIEX_BSS_ROLE_UAP)
-               ret = mwifiex_process_uap_event(priv);
-       else
-               ret = mwifiex_process_sta_event(priv);
-
-       adapter->event_cause = 0;
-       adapter->event_skb = NULL;
-       adapter->if_ops.event_complete(adapter, skb);
-
-       return ret;
-}
-
-/*
- * This function prepares a command and send it to the firmware.
- *
- * Preparation includes -
- *      - Sanity tests to make sure the card is still present or the FW
- *        is not reset
- *      - Getting a new command node from the command free queue
- *      - Initializing the command node for default parameters
- *      - Fill up the non-default parameters and buffer pointers
- *      - Add the command to pending queue
- */
-int mwifiex_send_cmd(struct mwifiex_private *priv, u16 cmd_no,
-                    u16 cmd_action, u32 cmd_oid, void *data_buf, bool sync)
-{
-       int ret;
-       struct mwifiex_adapter *adapter = priv->adapter;
-       struct cmd_ctrl_node *cmd_node;
-       struct host_cmd_ds_command *cmd_ptr;
-
-       if (!adapter) {
-               pr_err("PREP_CMD: adapter is NULL\n");
-               return -1;
-       }
-
-       if (adapter->is_suspended) {
-               mwifiex_dbg(adapter, ERROR,
-                           "PREP_CMD: device in suspended state\n");
-               return -1;
-       }
-
-       if (adapter->hs_enabling && cmd_no != HostCmd_CMD_802_11_HS_CFG_ENH) {
-               mwifiex_dbg(adapter, ERROR,
-                           "PREP_CMD: host entering sleep state\n");
-               return -1;
-       }
-
-       if (adapter->surprise_removed) {
-               mwifiex_dbg(adapter, ERROR,
-                           "PREP_CMD: card is removed\n");
-               return -1;
-       }
-
-       if (adapter->is_cmd_timedout) {
-               mwifiex_dbg(adapter, ERROR,
-                           "PREP_CMD: FW is in bad state\n");
-               return -1;
-       }
-
-       if (adapter->hw_status == MWIFIEX_HW_STATUS_RESET) {
-               if (cmd_no != HostCmd_CMD_FUNC_INIT) {
-                       mwifiex_dbg(adapter, ERROR,
-                                   "PREP_CMD: FW in reset state\n");
-                       return -1;
-               }
-       }
-
-       /* Get a new command node */
-       cmd_node = mwifiex_get_cmd_node(adapter);
-
-       if (!cmd_node) {
-               mwifiex_dbg(adapter, ERROR,
-                           "PREP_CMD: no free cmd node\n");
-               return -1;
-       }
-
-       /* Initialize the command node */
-       mwifiex_init_cmd_node(priv, cmd_node, cmd_oid, data_buf, sync);
-
-       if (!cmd_node->cmd_skb) {
-               mwifiex_dbg(adapter, ERROR,
-                           "PREP_CMD: no free cmd buf\n");
-               return -1;
-       }
-
-       memset(skb_put(cmd_node->cmd_skb, sizeof(struct host_cmd_ds_command)),
-              0, sizeof(struct host_cmd_ds_command));
-
-       cmd_ptr = (struct host_cmd_ds_command *) (cmd_node->cmd_skb->data);
-       cmd_ptr->command = cpu_to_le16(cmd_no);
-       cmd_ptr->result = 0;
-
-       /* Prepare command */
-       if (cmd_no) {
-               switch (cmd_no) {
-               case HostCmd_CMD_UAP_SYS_CONFIG:
-               case HostCmd_CMD_UAP_BSS_START:
-               case HostCmd_CMD_UAP_BSS_STOP:
-               case HostCmd_CMD_UAP_STA_DEAUTH:
-               case HOST_CMD_APCMD_SYS_RESET:
-               case HOST_CMD_APCMD_STA_LIST:
-                       ret = mwifiex_uap_prepare_cmd(priv, cmd_no, cmd_action,
-                                                     cmd_oid, data_buf,
-                                                     cmd_ptr);
-                       break;
-               default:
-                       ret = mwifiex_sta_prepare_cmd(priv, cmd_no, cmd_action,
-                                                     cmd_oid, data_buf,
-                                                     cmd_ptr);
-                       break;
-               }
-       } else {
-               ret = mwifiex_cmd_host_cmd(priv, cmd_ptr, data_buf);
-               cmd_node->cmd_flag |= CMD_F_HOSTCMD;
-       }
-
-       /* Return error, since the command preparation failed */
-       if (ret) {
-               mwifiex_dbg(adapter, ERROR,
-                           "PREP_CMD: cmd %#x preparation failed\n",
-                       cmd_no);
-               mwifiex_insert_cmd_to_free_q(adapter, cmd_node);
-               return -1;
-       }
-
-       /* Send command */
-       if (cmd_no == HostCmd_CMD_802_11_SCAN ||
-           cmd_no == HostCmd_CMD_802_11_SCAN_EXT) {
-               mwifiex_queue_scan_cmd(priv, cmd_node);
-       } else {
-               mwifiex_insert_cmd_to_pending_q(adapter, cmd_node, true);
-               queue_work(adapter->workqueue, &adapter->main_work);
-               if (cmd_node->wait_q_enabled)
-                       ret = mwifiex_wait_queue_complete(adapter, cmd_node);
-       }
-
-       return ret;
-}
-
-/*
- * This function returns a command to the command free queue.
- *
- * The function also calls the completion callback if required, before
- * cleaning the command node and re-inserting it into the free queue.
- */
-void
-mwifiex_insert_cmd_to_free_q(struct mwifiex_adapter *adapter,
-                            struct cmd_ctrl_node *cmd_node)
-{
-       unsigned long flags;
-
-       if (!cmd_node)
-               return;
-
-       if (cmd_node->wait_q_enabled)
-               mwifiex_complete_cmd(adapter, cmd_node);
-       /* Clean the node */
-       mwifiex_clean_cmd_node(adapter, cmd_node);
-
-       /* Insert node into cmd_free_q */
-       spin_lock_irqsave(&adapter->cmd_free_q_lock, flags);
-       list_add_tail(&cmd_node->list, &adapter->cmd_free_q);
-       spin_unlock_irqrestore(&adapter->cmd_free_q_lock, flags);
-}
-
-/* This function reuses a command node. */
-void mwifiex_recycle_cmd_node(struct mwifiex_adapter *adapter,
-                             struct cmd_ctrl_node *cmd_node)
-{
-       struct host_cmd_ds_command *host_cmd = (void *)cmd_node->cmd_skb->data;
-
-       mwifiex_insert_cmd_to_free_q(adapter, cmd_node);
-
-       atomic_dec(&adapter->cmd_pending);
-       mwifiex_dbg(adapter, CMD,
-                   "cmd: FREE_CMD: cmd=%#x, cmd_pending=%d\n",
-               le16_to_cpu(host_cmd->command),
-               atomic_read(&adapter->cmd_pending));
-}
-
-/*
- * This function queues a command to the command pending queue.
- *
- * This in effect adds the command to the command list to be executed.
- * Exit PS command is handled specially, by placing it always to the
- * front of the command queue.
- */
-void
-mwifiex_insert_cmd_to_pending_q(struct mwifiex_adapter *adapter,
-                               struct cmd_ctrl_node *cmd_node, u32 add_tail)
-{
-       struct host_cmd_ds_command *host_cmd = NULL;
-       u16 command;
-       unsigned long flags;
-
-       host_cmd = (struct host_cmd_ds_command *) (cmd_node->cmd_skb->data);
-       if (!host_cmd) {
-               mwifiex_dbg(adapter, ERROR, "QUEUE_CMD: host_cmd is NULL\n");
-               return;
-       }
-
-       command = le16_to_cpu(host_cmd->command);
-
-       /* Exit_PS command needs to be queued in the header always. */
-       if (command == HostCmd_CMD_802_11_PS_MODE_ENH) {
-               struct host_cmd_ds_802_11_ps_mode_enh *pm =
-                                               &host_cmd->params.psmode_enh;
-               if ((le16_to_cpu(pm->action) == DIS_PS) ||
-                   (le16_to_cpu(pm->action) == DIS_AUTO_PS)) {
-                       if (adapter->ps_state != PS_STATE_AWAKE)
-                               add_tail = false;
-               }
-       }
-
-       spin_lock_irqsave(&adapter->cmd_pending_q_lock, flags);
-       if (add_tail)
-               list_add_tail(&cmd_node->list, &adapter->cmd_pending_q);
-       else
-               list_add(&cmd_node->list, &adapter->cmd_pending_q);
-       spin_unlock_irqrestore(&adapter->cmd_pending_q_lock, flags);
-
-       atomic_inc(&adapter->cmd_pending);
-       mwifiex_dbg(adapter, CMD,
-                   "cmd: QUEUE_CMD: cmd=%#x, cmd_pending=%d\n",
-               command, atomic_read(&adapter->cmd_pending));
-}
-
-/*
- * This function executes the next command in command pending queue.
- *
- * This function will fail if a command is already in processing stage,
- * otherwise it will dequeue the first command from the command pending
- * queue and send to the firmware.
- *
- * If the device is currently in host sleep mode, any commands, except the
- * host sleep configuration command will de-activate the host sleep. For PS
- * mode, the function will put the firmware back to sleep if applicable.
- */
-int mwifiex_exec_next_cmd(struct mwifiex_adapter *adapter)
-{
-       struct mwifiex_private *priv;
-       struct cmd_ctrl_node *cmd_node;
-       int ret = 0;
-       struct host_cmd_ds_command *host_cmd;
-       unsigned long cmd_flags;
-       unsigned long cmd_pending_q_flags;
-
-       /* Check if already in processing */
-       if (adapter->curr_cmd) {
-               mwifiex_dbg(adapter, FATAL,
-                           "EXEC_NEXT_CMD: cmd in processing\n");
-               return -1;
-       }
-
-       spin_lock_irqsave(&adapter->mwifiex_cmd_lock, cmd_flags);
-       /* Check if any command is pending */
-       spin_lock_irqsave(&adapter->cmd_pending_q_lock, cmd_pending_q_flags);
-       if (list_empty(&adapter->cmd_pending_q)) {
-               spin_unlock_irqrestore(&adapter->cmd_pending_q_lock,
-                                      cmd_pending_q_flags);
-               spin_unlock_irqrestore(&adapter->mwifiex_cmd_lock, cmd_flags);
-               return 0;
-       }
-       cmd_node = list_first_entry(&adapter->cmd_pending_q,
-                                   struct cmd_ctrl_node, list);
-       spin_unlock_irqrestore(&adapter->cmd_pending_q_lock,
-                              cmd_pending_q_flags);
-
-       host_cmd = (struct host_cmd_ds_command *) (cmd_node->cmd_skb->data);
-       priv = cmd_node->priv;
-
-       if (adapter->ps_state != PS_STATE_AWAKE) {
-               mwifiex_dbg(adapter, ERROR,
-                           "%s: cannot send cmd in sleep state,\t"
-                           "this should not happen\n", __func__);
-               spin_unlock_irqrestore(&adapter->mwifiex_cmd_lock, cmd_flags);
-               return ret;
-       }
-
-       spin_lock_irqsave(&adapter->cmd_pending_q_lock, cmd_pending_q_flags);
-       list_del(&cmd_node->list);
-       spin_unlock_irqrestore(&adapter->cmd_pending_q_lock,
-                              cmd_pending_q_flags);
-
-       spin_unlock_irqrestore(&adapter->mwifiex_cmd_lock, cmd_flags);
-       ret = mwifiex_dnld_cmd_to_fw(priv, cmd_node);
-       priv = mwifiex_get_priv(adapter, MWIFIEX_BSS_ROLE_ANY);
-       /* Any command sent to the firmware when host is in sleep
-        * mode should de-configure host sleep. We should skip the
-        * host sleep configuration command itself though
-        */
-       if (priv && (host_cmd->command !=
-            cpu_to_le16(HostCmd_CMD_802_11_HS_CFG_ENH))) {
-               if (adapter->hs_activated) {
-                       adapter->is_hs_configured = false;
-                       mwifiex_hs_activated_event(priv, false);
-               }
-       }
-
-       return ret;
-}
-
-/*
- * This function handles the command response.
- *
- * After processing, the function cleans the command node and puts
- * it back to the command free queue.
- */
-int mwifiex_process_cmdresp(struct mwifiex_adapter *adapter)
-{
-       struct host_cmd_ds_command *resp;
-       struct mwifiex_private *priv =
-               mwifiex_get_priv(adapter, MWIFIEX_BSS_ROLE_ANY);
-       int ret = 0;
-       uint16_t orig_cmdresp_no;
-       uint16_t cmdresp_no;
-       uint16_t cmdresp_result;
-       unsigned long flags;
-
-       /* Now we got response from FW, cancel the command timer */
-       del_timer_sync(&adapter->cmd_timer);
-
-       if (!adapter->curr_cmd || !adapter->curr_cmd->resp_skb) {
-               resp = (struct host_cmd_ds_command *) adapter->upld_buf;
-               mwifiex_dbg(adapter, ERROR,
-                           "CMD_RESP: NULL curr_cmd, %#x\n",
-                           le16_to_cpu(resp->command));
-               return -1;
-       }
-
-       adapter->is_cmd_timedout = 0;
-
-       resp = (struct host_cmd_ds_command *) adapter->curr_cmd->resp_skb->data;
-       if (adapter->curr_cmd->cmd_flag & CMD_F_HOSTCMD) {
-               /* Copy original response back to response buffer */
-               struct mwifiex_ds_misc_cmd *hostcmd;
-               uint16_t size = le16_to_cpu(resp->size);
-               mwifiex_dbg(adapter, INFO,
-                           "info: host cmd resp size = %d\n", size);
-               size = min_t(u16, size, MWIFIEX_SIZE_OF_CMD_BUFFER);
-               if (adapter->curr_cmd->data_buf) {
-                       hostcmd = adapter->curr_cmd->data_buf;
-                       hostcmd->len = size;
-                       memcpy(hostcmd->cmd, resp, size);
-               }
-       }
-       orig_cmdresp_no = le16_to_cpu(resp->command);
-
-       /* Get BSS number and corresponding priv */
-       priv = mwifiex_get_priv_by_id(adapter,
-                            HostCmd_GET_BSS_NO(le16_to_cpu(resp->seq_num)),
-                            HostCmd_GET_BSS_TYPE(le16_to_cpu(resp->seq_num)));
-       if (!priv)
-               priv = mwifiex_get_priv(adapter, MWIFIEX_BSS_ROLE_ANY);
-       /* Clear RET_BIT from HostCmd */
-       resp->command = cpu_to_le16(orig_cmdresp_no & HostCmd_CMD_ID_MASK);
-
-       cmdresp_no = le16_to_cpu(resp->command);
-       cmdresp_result = le16_to_cpu(resp->result);
-
-       /* Save the last command response to debug log */
-       adapter->dbg.last_cmd_resp_index =
-                       (adapter->dbg.last_cmd_resp_index + 1) % DBG_CMD_NUM;
-       adapter->dbg.last_cmd_resp_id[adapter->dbg.last_cmd_resp_index] =
-                                                               orig_cmdresp_no;
-
-       mwifiex_dbg(adapter, CMD,
-                   "cmd: CMD_RESP: 0x%x, result %d, len %d, seqno 0x%x\n",
-                   orig_cmdresp_no, cmdresp_result,
-                   le16_to_cpu(resp->size), le16_to_cpu(resp->seq_num));
-       mwifiex_dbg_dump(adapter, CMD_D, "CMD_RESP buffer:", resp,
-                        le16_to_cpu(resp->size));
-
-       if (!(orig_cmdresp_no & HostCmd_RET_BIT)) {
-               mwifiex_dbg(adapter, ERROR, "CMD_RESP: invalid cmd resp\n");
-               if (adapter->curr_cmd->wait_q_enabled)
-                       adapter->cmd_wait_q.status = -1;
-
-               mwifiex_recycle_cmd_node(adapter, adapter->curr_cmd);
-               spin_lock_irqsave(&adapter->mwifiex_cmd_lock, flags);
-               adapter->curr_cmd = NULL;
-               spin_unlock_irqrestore(&adapter->mwifiex_cmd_lock, flags);
-               return -1;
-       }
-
-       if (adapter->curr_cmd->cmd_flag & CMD_F_HOSTCMD) {
-               adapter->curr_cmd->cmd_flag &= ~CMD_F_HOSTCMD;
-               if ((cmdresp_result == HostCmd_RESULT_OK) &&
-                   (cmdresp_no == HostCmd_CMD_802_11_HS_CFG_ENH))
-                       ret = mwifiex_ret_802_11_hs_cfg(priv, resp);
-       } else {
-               /* handle response */
-               ret = mwifiex_process_sta_cmdresp(priv, cmdresp_no, resp);
-       }
-
-       /* Check init command response */
-       if (adapter->hw_status == MWIFIEX_HW_STATUS_INITIALIZING) {
-               if (ret) {
-                       mwifiex_dbg(adapter, ERROR,
-                                   "%s: cmd %#x failed during\t"
-                                   "initialization\n", __func__, cmdresp_no);
-                       mwifiex_init_fw_complete(adapter);
-                       return -1;
-               } else if (adapter->last_init_cmd == cmdresp_no)
-                       adapter->hw_status = MWIFIEX_HW_STATUS_INIT_DONE;
-       }
-
-       if (adapter->curr_cmd) {
-               if (adapter->curr_cmd->wait_q_enabled)
-                       adapter->cmd_wait_q.status = ret;
-
-               mwifiex_recycle_cmd_node(adapter, adapter->curr_cmd);
-
-               spin_lock_irqsave(&adapter->mwifiex_cmd_lock, flags);
-               adapter->curr_cmd = NULL;
-               spin_unlock_irqrestore(&adapter->mwifiex_cmd_lock, flags);
-       }
-
-       return ret;
-}
-
-/*
- * This function handles the timeout of command sending.
- *
- * It will re-send the same command again.
- */
-void
-mwifiex_cmd_timeout_func(unsigned long function_context)
-{
-       struct mwifiex_adapter *adapter =
-               (struct mwifiex_adapter *) function_context;
-       struct cmd_ctrl_node *cmd_node;
-
-       adapter->is_cmd_timedout = 1;
-       if (!adapter->curr_cmd) {
-               mwifiex_dbg(adapter, ERROR,
-                           "cmd: empty curr_cmd\n");
-               return;
-       }
-       cmd_node = adapter->curr_cmd;
-       if (cmd_node) {
-               adapter->dbg.timeout_cmd_id =
-                       adapter->dbg.last_cmd_id[adapter->dbg.last_cmd_index];
-               adapter->dbg.timeout_cmd_act =
-                       adapter->dbg.last_cmd_act[adapter->dbg.last_cmd_index];
-               mwifiex_dbg(adapter, MSG,
-                           "%s: Timeout cmd id = %#x, act = %#x\n", __func__,
-                           adapter->dbg.timeout_cmd_id,
-                           adapter->dbg.timeout_cmd_act);
-
-               mwifiex_dbg(adapter, MSG,
-                           "num_data_h2c_failure = %d\n",
-                           adapter->dbg.num_tx_host_to_card_failure);
-               mwifiex_dbg(adapter, MSG,
-                           "num_cmd_h2c_failure = %d\n",
-                           adapter->dbg.num_cmd_host_to_card_failure);
-
-               mwifiex_dbg(adapter, MSG,
-                           "is_cmd_timedout = %d\n",
-                           adapter->is_cmd_timedout);
-               mwifiex_dbg(adapter, MSG,
-                           "num_tx_timeout = %d\n",
-                           adapter->dbg.num_tx_timeout);
-
-               mwifiex_dbg(adapter, MSG,
-                           "last_cmd_index = %d\n",
-                           adapter->dbg.last_cmd_index);
-               mwifiex_dbg(adapter, MSG,
-                           "last_cmd_id: %*ph\n",
-                           (int)sizeof(adapter->dbg.last_cmd_id),
-                           adapter->dbg.last_cmd_id);
-               mwifiex_dbg(adapter, MSG,
-                           "last_cmd_act: %*ph\n",
-                           (int)sizeof(adapter->dbg.last_cmd_act),
-                           adapter->dbg.last_cmd_act);
-
-               mwifiex_dbg(adapter, MSG,
-                           "last_cmd_resp_index = %d\n",
-                           adapter->dbg.last_cmd_resp_index);
-               mwifiex_dbg(adapter, MSG,
-                           "last_cmd_resp_id: %*ph\n",
-                           (int)sizeof(adapter->dbg.last_cmd_resp_id),
-                           adapter->dbg.last_cmd_resp_id);
-
-               mwifiex_dbg(adapter, MSG,
-                           "last_event_index = %d\n",
-                           adapter->dbg.last_event_index);
-               mwifiex_dbg(adapter, MSG,
-                           "last_event: %*ph\n",
-                           (int)sizeof(adapter->dbg.last_event),
-                           adapter->dbg.last_event);
-
-               mwifiex_dbg(adapter, MSG,
-                           "data_sent=%d cmd_sent=%d\n",
-                           adapter->data_sent, adapter->cmd_sent);
-
-               mwifiex_dbg(adapter, MSG,
-                           "ps_mode=%d ps_state=%d\n",
-                           adapter->ps_mode, adapter->ps_state);
-
-               if (cmd_node->wait_q_enabled) {
-                       adapter->cmd_wait_q.status = -ETIMEDOUT;
-                       mwifiex_cancel_pending_ioctl(adapter);
-               }
-       }
-       if (adapter->hw_status == MWIFIEX_HW_STATUS_INITIALIZING) {
-               mwifiex_init_fw_complete(adapter);
-               return;
-       }
-
-       if (adapter->if_ops.device_dump)
-               adapter->if_ops.device_dump(adapter);
-
-       if (adapter->if_ops.card_reset)
-               adapter->if_ops.card_reset(adapter);
-}
-
-/*
- * This function cancels all the pending commands.
- *
- * The current command, all commands in command pending queue and all scan
- * commands in scan pending queue are cancelled. All the completion callbacks
- * are called with failure status to ensure cleanup.
- */
-void
-mwifiex_cancel_all_pending_cmd(struct mwifiex_adapter *adapter)
-{
-       struct cmd_ctrl_node *cmd_node = NULL, *tmp_node;
-       unsigned long flags, cmd_flags;
-       struct mwifiex_private *priv;
-       int i;
-
-       spin_lock_irqsave(&adapter->mwifiex_cmd_lock, cmd_flags);
-       /* Cancel current cmd */
-       if ((adapter->curr_cmd) && (adapter->curr_cmd->wait_q_enabled)) {
-               adapter->curr_cmd->wait_q_enabled = false;
-               adapter->cmd_wait_q.status = -1;
-               mwifiex_complete_cmd(adapter, adapter->curr_cmd);
-               /* no recycle probably wait for response */
-       }
-       /* Cancel all pending command */
-       spin_lock_irqsave(&adapter->cmd_pending_q_lock, flags);
-       list_for_each_entry_safe(cmd_node, tmp_node,
-                                &adapter->cmd_pending_q, list) {
-               list_del(&cmd_node->list);
-               spin_unlock_irqrestore(&adapter->cmd_pending_q_lock, flags);
-
-               if (cmd_node->wait_q_enabled)
-                       adapter->cmd_wait_q.status = -1;
-               mwifiex_recycle_cmd_node(adapter, cmd_node);
-               spin_lock_irqsave(&adapter->cmd_pending_q_lock, flags);
-       }
-       spin_unlock_irqrestore(&adapter->cmd_pending_q_lock, flags);
-       spin_unlock_irqrestore(&adapter->mwifiex_cmd_lock, cmd_flags);
-
-       /* Cancel all pending scan command */
-       spin_lock_irqsave(&adapter->scan_pending_q_lock, flags);
-       list_for_each_entry_safe(cmd_node, tmp_node,
-                                &adapter->scan_pending_q, list) {
-               list_del(&cmd_node->list);
-
-               cmd_node->wait_q_enabled = false;
-               mwifiex_insert_cmd_to_free_q(adapter, cmd_node);
-       }
-       spin_unlock_irqrestore(&adapter->scan_pending_q_lock, flags);
-
-       if (adapter->scan_processing) {
-               spin_lock_irqsave(&adapter->mwifiex_cmd_lock, cmd_flags);
-               adapter->scan_processing = false;
-               spin_unlock_irqrestore(&adapter->mwifiex_cmd_lock, cmd_flags);
-               for (i = 0; i < adapter->priv_num; i++) {
-                       priv = adapter->priv[i];
-                       if (!priv)
-                               continue;
-                       if (priv->scan_request) {
-                               mwifiex_dbg(adapter, WARN, "info: aborting scan\n");
-                               cfg80211_scan_done(priv->scan_request, 1);
-                               priv->scan_request = NULL;
-                       }
-               }
-       }
-}
-
-/*
- * This function cancels all pending commands that matches with
- * the given IOCTL request.
- *
- * Both the current command buffer and the pending command queue are
- * searched for matching IOCTL request. The completion callback of
- * the matched command is called with failure status to ensure cleanup.
- * In case of scan commands, all pending commands in scan pending queue
- * are cancelled.
- */
-void
-mwifiex_cancel_pending_ioctl(struct mwifiex_adapter *adapter)
-{
-       struct cmd_ctrl_node *cmd_node = NULL, *tmp_node = NULL;
-       unsigned long cmd_flags;
-       unsigned long scan_pending_q_flags;
-       struct mwifiex_private *priv;
-       int i;
-
-       if ((adapter->curr_cmd) &&
-           (adapter->curr_cmd->wait_q_enabled)) {
-               spin_lock_irqsave(&adapter->mwifiex_cmd_lock, cmd_flags);
-               cmd_node = adapter->curr_cmd;
-               /* setting curr_cmd to NULL is quite dangerous, because
-                * mwifiex_process_cmdresp checks curr_cmd to be != NULL
-                * at the beginning then relies on it and dereferences
-                * it at will
-                * this probably works since mwifiex_cmd_timeout_func
-                * is the only caller of this function and responses
-                * at that point
-                */
-               adapter->curr_cmd = NULL;
-               spin_unlock_irqrestore(&adapter->mwifiex_cmd_lock, cmd_flags);
-
-               mwifiex_recycle_cmd_node(adapter, cmd_node);
-       }
-
-       /* Cancel all pending scan command */
-       spin_lock_irqsave(&adapter->scan_pending_q_lock,
-                         scan_pending_q_flags);
-       list_for_each_entry_safe(cmd_node, tmp_node,
-                                &adapter->scan_pending_q, list) {
-               list_del(&cmd_node->list);
-               cmd_node->wait_q_enabled = false;
-               mwifiex_insert_cmd_to_free_q(adapter, cmd_node);
-       }
-       spin_unlock_irqrestore(&adapter->scan_pending_q_lock,
-                              scan_pending_q_flags);
-
-       if (adapter->scan_processing) {
-               spin_lock_irqsave(&adapter->mwifiex_cmd_lock, cmd_flags);
-               adapter->scan_processing = false;
-               spin_unlock_irqrestore(&adapter->mwifiex_cmd_lock, cmd_flags);
-               for (i = 0; i < adapter->priv_num; i++) {
-                       priv = adapter->priv[i];
-                       if (!priv)
-                               continue;
-                       if (priv->scan_request) {
-                               mwifiex_dbg(adapter, WARN, "info: aborting scan\n");
-                               cfg80211_scan_done(priv->scan_request, 1);
-                               priv->scan_request = NULL;
-                       }
-               }
-       }
-}
-
-/*
- * This function sends the sleep confirm command to firmware, if
- * possible.
- *
- * The sleep confirm command cannot be issued if command response,
- * data response or event response is awaiting handling, or if we
- * are in the middle of sending a command, or expecting a command
- * response.
- */
-void
-mwifiex_check_ps_cond(struct mwifiex_adapter *adapter)
-{
-       if (!adapter->cmd_sent &&
-           !adapter->curr_cmd && !IS_CARD_RX_RCVD(adapter))
-               mwifiex_dnld_sleep_confirm_cmd(adapter);
-       else
-               mwifiex_dbg(adapter, CMD,
-                           "cmd: Delay Sleep Confirm (%s%s%s)\n",
-                           (adapter->cmd_sent) ? "D" : "",
-                           (adapter->curr_cmd) ? "C" : "",
-                           (IS_CARD_RX_RCVD(adapter)) ? "R" : "");
-}
-
-/*
- * This function sends a Host Sleep activated event to applications.
- *
- * This event is generated by the driver, with a blank event body.
- */
-void
-mwifiex_hs_activated_event(struct mwifiex_private *priv, u8 activated)
-{
-       if (activated) {
-               if (priv->adapter->is_hs_configured) {
-                       priv->adapter->hs_activated = true;
-                       mwifiex_update_rxreor_flags(priv->adapter,
-                                                   RXREOR_FORCE_NO_DROP);
-                       mwifiex_dbg(priv->adapter, EVENT,
-                                   "event: hs_activated\n");
-                       priv->adapter->hs_activate_wait_q_woken = true;
-                       wake_up_interruptible(
-                               &priv->adapter->hs_activate_wait_q);
-               } else {
-                       mwifiex_dbg(priv->adapter, EVENT,
-                                   "event: HS not configured\n");
-               }
-       } else {
-               mwifiex_dbg(priv->adapter, EVENT,
-                           "event: hs_deactivated\n");
-               priv->adapter->hs_activated = false;
-       }
-}
-
-/*
- * This function handles the command response of a Host Sleep configuration
- * command.
- *
- * Handling includes changing the header fields into CPU format
- * and setting the current host sleep activation status in driver.
- *
- * In case host sleep status change, the function generates an event to
- * notify the applications.
- */
-int mwifiex_ret_802_11_hs_cfg(struct mwifiex_private *priv,
-                             struct host_cmd_ds_command *resp)
-{
-       struct mwifiex_adapter *adapter = priv->adapter;
-       struct host_cmd_ds_802_11_hs_cfg_enh *phs_cfg =
-               &resp->params.opt_hs_cfg;
-       uint32_t conditions = le32_to_cpu(phs_cfg->params.hs_config.conditions);
-
-       if (phs_cfg->action == cpu_to_le16(HS_ACTIVATE) &&
-           adapter->iface_type != MWIFIEX_USB) {
-               mwifiex_hs_activated_event(priv, true);
-               return 0;
-       } else {
-               mwifiex_dbg(adapter, CMD,
-                           "cmd: CMD_RESP: HS_CFG cmd reply\t"
-                           " result=%#x, conditions=0x%x gpio=0x%x gap=0x%x\n",
-                           resp->result, conditions,
-                           phs_cfg->params.hs_config.gpio,
-                           phs_cfg->params.hs_config.gap);
-       }
-       if (conditions != HS_CFG_CANCEL) {
-               adapter->is_hs_configured = true;
-               if (adapter->iface_type == MWIFIEX_USB)
-                       mwifiex_hs_activated_event(priv, true);
-       } else {
-               adapter->is_hs_configured = false;
-               if (adapter->hs_activated)
-                       mwifiex_hs_activated_event(priv, false);
-       }
-
-       return 0;
-}
-
-/*
- * This function wakes up the adapter and generates a Host Sleep
- * cancel event on receiving the power up interrupt.
- */
-void
-mwifiex_process_hs_config(struct mwifiex_adapter *adapter)
-{
-       mwifiex_dbg(adapter, INFO,
-                   "info: %s: auto cancelling host sleep\t"
-                   "since there is interrupt from the firmware\n",
-                   __func__);
-
-       adapter->if_ops.wakeup(adapter);
-       adapter->hs_activated = false;
-       adapter->is_hs_configured = false;
-       adapter->is_suspended = false;
-       mwifiex_hs_activated_event(mwifiex_get_priv(adapter,
-                                                   MWIFIEX_BSS_ROLE_ANY),
-                                  false);
-}
-EXPORT_SYMBOL_GPL(mwifiex_process_hs_config);
-
-/*
- * This function handles the command response of a sleep confirm command.
- *
- * The function sets the card state to SLEEP if the response indicates success.
- */
-void
-mwifiex_process_sleep_confirm_resp(struct mwifiex_adapter *adapter,
-                                  u8 *pbuf, u32 upld_len)
-{
-       struct host_cmd_ds_command *cmd = (struct host_cmd_ds_command *) pbuf;
-       struct mwifiex_private *priv =
-               mwifiex_get_priv(adapter, MWIFIEX_BSS_ROLE_ANY);
-       uint16_t result = le16_to_cpu(cmd->result);
-       uint16_t command = le16_to_cpu(cmd->command);
-       uint16_t seq_num = le16_to_cpu(cmd->seq_num);
-
-       if (!upld_len) {
-               mwifiex_dbg(adapter, ERROR,
-                           "%s: cmd size is 0\n", __func__);
-               return;
-       }
-
-       mwifiex_dbg(adapter, CMD,
-                   "cmd: CMD_RESP: 0x%x, result %d, len %d, seqno 0x%x\n",
-                   command, result, le16_to_cpu(cmd->size), seq_num);
-
-       /* Get BSS number and corresponding priv */
-       priv = mwifiex_get_priv_by_id(adapter, HostCmd_GET_BSS_NO(seq_num),
-                                     HostCmd_GET_BSS_TYPE(seq_num));
-       if (!priv)
-               priv = mwifiex_get_priv(adapter, MWIFIEX_BSS_ROLE_ANY);
-
-       /* Update sequence number */
-       seq_num = HostCmd_GET_SEQ_NO(seq_num);
-       /* Clear RET_BIT from HostCmd */
-       command &= HostCmd_CMD_ID_MASK;
-
-       if (command != HostCmd_CMD_802_11_PS_MODE_ENH) {
-               mwifiex_dbg(adapter, ERROR,
-                           "%s: rcvd unexpected resp for cmd %#x, result = %x\n",
-                           __func__, command, result);
-               return;
-       }
-
-       if (result) {
-               mwifiex_dbg(adapter, ERROR,
-                           "%s: sleep confirm cmd failed\n",
-                           __func__);
-               adapter->pm_wakeup_card_req = false;
-               adapter->ps_state = PS_STATE_AWAKE;
-               return;
-       }
-       adapter->pm_wakeup_card_req = true;
-       if (adapter->is_hs_configured)
-               mwifiex_hs_activated_event(mwifiex_get_priv
-                                               (adapter, MWIFIEX_BSS_ROLE_ANY),
-                                          true);
-       adapter->ps_state = PS_STATE_SLEEP;
-       cmd->command = cpu_to_le16(command);
-       cmd->seq_num = cpu_to_le16(seq_num);
-}
-EXPORT_SYMBOL_GPL(mwifiex_process_sleep_confirm_resp);
-
-/*
- * This function prepares an enhanced power mode command.
- *
- * This function can be used to disable power save or to configure
- * power save with auto PS or STA PS or auto deep sleep.
- *
- * Preparation includes -
- *      - Setting command ID, action and proper size
- *      - Setting Power Save bitmap, PS parameters TLV, PS mode TLV,
- *        auto deep sleep TLV (as required)
- *      - Ensuring correct endian-ness
- */
-int mwifiex_cmd_enh_power_mode(struct mwifiex_private *priv,
-                              struct host_cmd_ds_command *cmd,
-                              u16 cmd_action, uint16_t ps_bitmap,
-                              struct mwifiex_ds_auto_ds *auto_ds)
-{
-       struct host_cmd_ds_802_11_ps_mode_enh *psmode_enh =
-               &cmd->params.psmode_enh;
-       u8 *tlv;
-       u16 cmd_size = 0;
-
-       cmd->command = cpu_to_le16(HostCmd_CMD_802_11_PS_MODE_ENH);
-       if (cmd_action == DIS_AUTO_PS) {
-               psmode_enh->action = cpu_to_le16(DIS_AUTO_PS);
-               psmode_enh->params.ps_bitmap = cpu_to_le16(ps_bitmap);
-               cmd->size = cpu_to_le16(S_DS_GEN + sizeof(psmode_enh->action) +
-                                       sizeof(psmode_enh->params.ps_bitmap));
-       } else if (cmd_action == GET_PS) {
-               psmode_enh->action = cpu_to_le16(GET_PS);
-               psmode_enh->params.ps_bitmap = cpu_to_le16(ps_bitmap);
-               cmd->size = cpu_to_le16(S_DS_GEN + sizeof(psmode_enh->action) +
-                                       sizeof(psmode_enh->params.ps_bitmap));
-       } else if (cmd_action == EN_AUTO_PS) {
-               psmode_enh->action = cpu_to_le16(EN_AUTO_PS);
-               psmode_enh->params.ps_bitmap = cpu_to_le16(ps_bitmap);
-               cmd_size = S_DS_GEN + sizeof(psmode_enh->action) +
-                                       sizeof(psmode_enh->params.ps_bitmap);
-               tlv = (u8 *) cmd + cmd_size;
-               if (ps_bitmap & BITMAP_STA_PS) {
-                       struct mwifiex_adapter *adapter = priv->adapter;
-                       struct mwifiex_ie_types_ps_param *ps_tlv =
-                               (struct mwifiex_ie_types_ps_param *) tlv;
-                       struct mwifiex_ps_param *ps_mode = &ps_tlv->param;
-                       ps_tlv->header.type = cpu_to_le16(TLV_TYPE_PS_PARAM);
-                       ps_tlv->header.len = cpu_to_le16(sizeof(*ps_tlv) -
-                                       sizeof(struct mwifiex_ie_types_header));
-                       cmd_size += sizeof(*ps_tlv);
-                       tlv += sizeof(*ps_tlv);
-                       mwifiex_dbg(priv->adapter, CMD,
-                                   "cmd: PS Command: Enter PS\n");
-                       ps_mode->null_pkt_interval =
-                                       cpu_to_le16(adapter->null_pkt_interval);
-                       ps_mode->multiple_dtims =
-                                       cpu_to_le16(adapter->multiple_dtim);
-                       ps_mode->bcn_miss_timeout =
-                                       cpu_to_le16(adapter->bcn_miss_time_out);
-                       ps_mode->local_listen_interval =
-                               cpu_to_le16(adapter->local_listen_interval);
-                       ps_mode->adhoc_wake_period =
-                               cpu_to_le16(adapter->adhoc_awake_period);
-                       ps_mode->delay_to_ps =
-                                       cpu_to_le16(adapter->delay_to_ps);
-                       ps_mode->mode = cpu_to_le16(adapter->enhanced_ps_mode);
-
-               }
-               if (ps_bitmap & BITMAP_AUTO_DS) {
-                       struct mwifiex_ie_types_auto_ds_param *auto_ds_tlv =
-                               (struct mwifiex_ie_types_auto_ds_param *) tlv;
-                       u16 idletime = 0;
-
-                       auto_ds_tlv->header.type =
-                               cpu_to_le16(TLV_TYPE_AUTO_DS_PARAM);
-                       auto_ds_tlv->header.len =
-                               cpu_to_le16(sizeof(*auto_ds_tlv) -
-                                       sizeof(struct mwifiex_ie_types_header));
-                       cmd_size += sizeof(*auto_ds_tlv);
-                       tlv += sizeof(*auto_ds_tlv);
-                       if (auto_ds)
-                               idletime = auto_ds->idle_time;
-                       mwifiex_dbg(priv->adapter, CMD,
-                                   "cmd: PS Command: Enter Auto Deep Sleep\n");
-                       auto_ds_tlv->deep_sleep_timeout = cpu_to_le16(idletime);
-               }
-               cmd->size = cpu_to_le16(cmd_size);
-       }
-       return 0;
-}
-
-/*
- * This function handles the command response of an enhanced power mode
- * command.
- *
- * Handling includes changing the header fields into CPU format
- * and setting the current enhanced power mode in driver.
- */
-int mwifiex_ret_enh_power_mode(struct mwifiex_private *priv,
-                              struct host_cmd_ds_command *resp,
-                              struct mwifiex_ds_pm_cfg *pm_cfg)
-{
-       struct mwifiex_adapter *adapter = priv->adapter;
-       struct host_cmd_ds_802_11_ps_mode_enh *ps_mode =
-               &resp->params.psmode_enh;
-       uint16_t action = le16_to_cpu(ps_mode->action);
-       uint16_t ps_bitmap = le16_to_cpu(ps_mode->params.ps_bitmap);
-       uint16_t auto_ps_bitmap =
-               le16_to_cpu(ps_mode->params.ps_bitmap);
-
-       mwifiex_dbg(adapter, INFO,
-                   "info: %s: PS_MODE cmd reply result=%#x action=%#X\n",
-                   __func__, resp->result, action);
-       if (action == EN_AUTO_PS) {
-               if (auto_ps_bitmap & BITMAP_AUTO_DS) {
-                       mwifiex_dbg(adapter, CMD,
-                                   "cmd: Enabled auto deep sleep\n");
-                       priv->adapter->is_deep_sleep = true;
-               }
-               if (auto_ps_bitmap & BITMAP_STA_PS) {
-                       mwifiex_dbg(adapter, CMD,
-                                   "cmd: Enabled STA power save\n");
-                       if (adapter->sleep_period.period)
-                               mwifiex_dbg(adapter, CMD,
-                                           "cmd: set to uapsd/pps mode\n");
-               }
-       } else if (action == DIS_AUTO_PS) {
-               if (ps_bitmap & BITMAP_AUTO_DS) {
-                       priv->adapter->is_deep_sleep = false;
-                       mwifiex_dbg(adapter, CMD,
-                                   "cmd: Disabled auto deep sleep\n");
-               }
-               if (ps_bitmap & BITMAP_STA_PS) {
-                       mwifiex_dbg(adapter, CMD,
-                                   "cmd: Disabled STA power save\n");
-                       if (adapter->sleep_period.period) {
-                               adapter->delay_null_pkt = false;
-                               adapter->tx_lock_flag = false;
-                               adapter->pps_uapsd_mode = false;
-                       }
-               }
-       } else if (action == GET_PS) {
-               if (ps_bitmap & BITMAP_STA_PS)
-                       adapter->ps_mode = MWIFIEX_802_11_POWER_MODE_PSP;
-               else
-                       adapter->ps_mode = MWIFIEX_802_11_POWER_MODE_CAM;
-
-               mwifiex_dbg(adapter, CMD,
-                           "cmd: ps_bitmap=%#x\n", ps_bitmap);
-
-               if (pm_cfg) {
-                       /* This section is for get power save mode */
-                       if (ps_bitmap & BITMAP_STA_PS)
-                               pm_cfg->param.ps_mode = 1;
-                       else
-                               pm_cfg->param.ps_mode = 0;
-               }
-       }
-       return 0;
-}
-
-/*
- * This function prepares command to get hardware specifications.
- *
- * Preparation includes -
- *      - Setting command ID, action and proper size
- *      - Setting permanent address parameter
- *      - Ensuring correct endian-ness
- */
-int mwifiex_cmd_get_hw_spec(struct mwifiex_private *priv,
-                           struct host_cmd_ds_command *cmd)
-{
-       struct host_cmd_ds_get_hw_spec *hw_spec = &cmd->params.hw_spec;
-
-       cmd->command = cpu_to_le16(HostCmd_CMD_GET_HW_SPEC);
-       cmd->size =
-               cpu_to_le16(sizeof(struct host_cmd_ds_get_hw_spec) + S_DS_GEN);
-       memcpy(hw_spec->permanent_addr, priv->curr_addr, ETH_ALEN);
-
-       return 0;
-}
-
-/*
- * This function handles the command response of get hardware
- * specifications.
- *
- * Handling includes changing the header fields into CPU format
- * and saving/updating the following parameters in driver -
- *      - Firmware capability information
- *      - Firmware band settings
- *      - Ad-hoc start band and channel
- *      - Ad-hoc 11n activation status
- *      - Firmware release number
- *      - Number of antennas
- *      - Hardware address
- *      - Hardware interface version
- *      - Firmware version
- *      - Region code
- *      - 11n capabilities
- *      - MCS support fields
- *      - MP end port
- */
-int mwifiex_ret_get_hw_spec(struct mwifiex_private *priv,
-                           struct host_cmd_ds_command *resp)
-{
-       struct host_cmd_ds_get_hw_spec *hw_spec = &resp->params.hw_spec;
-       struct mwifiex_adapter *adapter = priv->adapter;
-       struct mwifiex_ie_types_header *tlv;
-       struct hw_spec_api_rev *api_rev;
-       u16 resp_size, api_id;
-       int i, left_len, parsed_len = 0;
-
-       adapter->fw_cap_info = le32_to_cpu(hw_spec->fw_cap_info);
-
-       if (IS_SUPPORT_MULTI_BANDS(adapter))
-               adapter->fw_bands = (u8) GET_FW_DEFAULT_BANDS(adapter);
-       else
-               adapter->fw_bands = BAND_B;
-
-       adapter->config_bands = adapter->fw_bands;
-
-       if (adapter->fw_bands & BAND_A) {
-               if (adapter->fw_bands & BAND_GN) {
-                       adapter->config_bands |= BAND_AN;
-                       adapter->fw_bands |= BAND_AN;
-               }
-               if (adapter->fw_bands & BAND_AN) {
-                       adapter->adhoc_start_band = BAND_A | BAND_AN;
-                       adapter->adhoc_11n_enabled = true;
-               } else {
-                       adapter->adhoc_start_band = BAND_A;
-               }
-               priv->adhoc_channel = DEFAULT_AD_HOC_CHANNEL_A;
-       } else if (adapter->fw_bands & BAND_GN) {
-               adapter->adhoc_start_band = BAND_G | BAND_B | BAND_GN;
-               priv->adhoc_channel = DEFAULT_AD_HOC_CHANNEL;
-               adapter->adhoc_11n_enabled = true;
-       } else if (adapter->fw_bands & BAND_G) {
-               adapter->adhoc_start_band = BAND_G | BAND_B;
-               priv->adhoc_channel = DEFAULT_AD_HOC_CHANNEL;
-       } else if (adapter->fw_bands & BAND_B) {
-               adapter->adhoc_start_band = BAND_B;
-               priv->adhoc_channel = DEFAULT_AD_HOC_CHANNEL;
-       }
-
-       adapter->fw_release_number = le32_to_cpu(hw_spec->fw_release_number);
-       adapter->fw_api_ver = (adapter->fw_release_number >> 16) & 0xff;
-       adapter->number_of_antenna = le16_to_cpu(hw_spec->number_of_antenna);
-
-       if (le32_to_cpu(hw_spec->dot_11ac_dev_cap)) {
-               adapter->is_hw_11ac_capable = true;
-
-               /* Copy 11AC cap */
-               adapter->hw_dot_11ac_dev_cap =
-                                       le32_to_cpu(hw_spec->dot_11ac_dev_cap);
-               adapter->usr_dot_11ac_dev_cap_bg = adapter->hw_dot_11ac_dev_cap
-                                       & ~MWIFIEX_DEF_11AC_CAP_BF_RESET_MASK;
-               adapter->usr_dot_11ac_dev_cap_a = adapter->hw_dot_11ac_dev_cap
-                                       & ~MWIFIEX_DEF_11AC_CAP_BF_RESET_MASK;
-
-               /* Copy 11AC mcs */
-               adapter->hw_dot_11ac_mcs_support =
-                               le32_to_cpu(hw_spec->dot_11ac_mcs_support);
-               adapter->usr_dot_11ac_mcs_support =
-                                       adapter->hw_dot_11ac_mcs_support;
-       } else {
-               adapter->is_hw_11ac_capable = false;
-       }
-
-       resp_size = le16_to_cpu(resp->size) - S_DS_GEN;
-       if (resp_size > sizeof(struct host_cmd_ds_get_hw_spec)) {
-               /* we have variable HW SPEC information */
-               left_len = resp_size - sizeof(struct host_cmd_ds_get_hw_spec);
-               while (left_len > sizeof(struct mwifiex_ie_types_header)) {
-                       tlv = (void *)&hw_spec->tlvs + parsed_len;
-                       switch (le16_to_cpu(tlv->type)) {
-                       case TLV_TYPE_API_REV:
-                               api_rev = (struct hw_spec_api_rev *)tlv;
-                               api_id = le16_to_cpu(api_rev->api_id);
-                               switch (api_id) {
-                               case KEY_API_VER_ID:
-                                       adapter->key_api_major_ver =
-                                                       api_rev->major_ver;
-                                       adapter->key_api_minor_ver =
-                                                       api_rev->minor_ver;
-                                       mwifiex_dbg(adapter, INFO,
-                                                   "key_api v%d.%d\n",
-                                                   adapter->key_api_major_ver,
-                                                   adapter->key_api_minor_ver);
-                                       break;
-                               case FW_API_VER_ID:
-                                       adapter->fw_api_ver =
-                                                       api_rev->major_ver;
-                                       mwifiex_dbg(adapter, INFO,
-                                                   "Firmware api version %d\n",
-                                                   adapter->fw_api_ver);
-                                       break;
-                               default:
-                                       mwifiex_dbg(adapter, FATAL,
-                                                   "Unknown api_id: %d\n",
-                                                   api_id);
-                                       break;
-                               }
-                               break;
-                       default:
-                               mwifiex_dbg(adapter, FATAL,
-                                           "Unknown GET_HW_SPEC TLV type: %#x\n",
-                                           le16_to_cpu(tlv->type));
-                               break;
-                       }
-                       parsed_len += le16_to_cpu(tlv->len) +
-                                     sizeof(struct mwifiex_ie_types_header);
-                       left_len -= le16_to_cpu(tlv->len) +
-                                     sizeof(struct mwifiex_ie_types_header);
-               }
-       }
-
-       mwifiex_dbg(adapter, INFO,
-                   "info: GET_HW_SPEC: fw_release_number- %#x\n",
-                   adapter->fw_release_number);
-       mwifiex_dbg(adapter, INFO,
-                   "info: GET_HW_SPEC: permanent addr: %pM\n",
-                   hw_spec->permanent_addr);
-       mwifiex_dbg(adapter, INFO,
-                   "info: GET_HW_SPEC: hw_if_version=%#x version=%#x\n",
-                   le16_to_cpu(hw_spec->hw_if_version),
-                   le16_to_cpu(hw_spec->version));
-
-       ether_addr_copy(priv->adapter->perm_addr, hw_spec->permanent_addr);
-       adapter->region_code = le16_to_cpu(hw_spec->region_code);
-
-       for (i = 0; i < MWIFIEX_MAX_REGION_CODE; i++)
-               /* Use the region code to search for the index */
-               if (adapter->region_code == region_code_index[i])
-                       break;
-
-       /* If it's unidentified region code, use the default (USA) */
-       if (i >= MWIFIEX_MAX_REGION_CODE) {
-               adapter->region_code = 0x10;
-               mwifiex_dbg(adapter, WARN,
-                           "cmd: unknown region code, use default (USA)\n");
-       }
-
-       adapter->hw_dot_11n_dev_cap = le32_to_cpu(hw_spec->dot_11n_dev_cap);
-       adapter->hw_dev_mcs_support = hw_spec->dev_mcs_support;
-       adapter->user_dev_mcs_support = adapter->hw_dev_mcs_support;
-
-       if (adapter->if_ops.update_mp_end_port)
-               adapter->if_ops.update_mp_end_port(adapter,
-                                       le16_to_cpu(hw_spec->mp_end_port));
-
-       if (adapter->fw_api_ver == MWIFIEX_FW_V15)
-               adapter->scan_chan_gap_enabled = true;
-
-       return 0;
-}
diff --git a/drivers/net/wireless/mwifiex/debugfs.c b/drivers/net/wireless/mwifiex/debugfs.c
deleted file mode 100644 (file)
index 9824d8d..0000000
+++ /dev/null
@@ -1,1005 +0,0 @@
-/*
- * Marvell Wireless LAN device driver: debugfs
- *
- * Copyright (C) 2011-2014, Marvell International Ltd.
- *
- * This software file (the "File") is distributed by Marvell International
- * Ltd. under the terms of the GNU General Public License Version 2, June 1991
- * (the "License").  You may use, redistribute and/or modify this File in
- * accordance with the terms and conditions of the License, a copy of which
- * is available by writing to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the
- * worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
- *
- * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
- * ARE EXPRESSLY DISCLAIMED.  The License provides additional details about
- * this warranty disclaimer.
- */
-
-#include <linux/debugfs.h>
-
-#include "main.h"
-#include "11n.h"
-
-
-static struct dentry *mwifiex_dfs_dir;
-
-static char *bss_modes[] = {
-       "UNSPECIFIED",
-       "ADHOC",
-       "STATION",
-       "AP",
-       "AP_VLAN",
-       "WDS",
-       "MONITOR",
-       "MESH_POINT",
-       "P2P_CLIENT",
-       "P2P_GO",
-       "P2P_DEVICE",
-};
-
-/*
- * Proc info file read handler.
- *
- * This function is called when the 'info' file is opened for reading.
- * It prints the following driver related information -
- *      - Driver name
- *      - Driver version
- *      - Driver extended version
- *      - Interface name
- *      - BSS mode
- *      - Media state (connected or disconnected)
- *      - MAC address
- *      - Total number of Tx bytes
- *      - Total number of Rx bytes
- *      - Total number of Tx packets
- *      - Total number of Rx packets
- *      - Total number of dropped Tx packets
- *      - Total number of dropped Rx packets
- *      - Total number of corrupted Tx packets
- *      - Total number of corrupted Rx packets
- *      - Carrier status (on or off)
- *      - Tx queue status (started or stopped)
- *
- * For STA mode drivers, it also prints the following extra -
- *      - ESSID
- *      - BSSID
- *      - Channel
- *      - Region code
- *      - Multicast count
- *      - Multicast addresses
- */
-static ssize_t
-mwifiex_info_read(struct file *file, char __user *ubuf,
-                 size_t count, loff_t *ppos)
-{
-       struct mwifiex_private *priv =
-               (struct mwifiex_private *) file->private_data;
-       struct net_device *netdev = priv->netdev;
-       struct netdev_hw_addr *ha;
-       struct netdev_queue *txq;
-       unsigned long page = get_zeroed_page(GFP_KERNEL);
-       char *p = (char *) page, fmt[64];
-       struct mwifiex_bss_info info;
-       ssize_t ret;
-       int i = 0;
-
-       if (!p)
-               return -ENOMEM;
-
-       memset(&info, 0, sizeof(info));
-       ret = mwifiex_get_bss_info(priv, &info);
-       if (ret)
-               goto free_and_exit;
-
-       mwifiex_drv_get_driver_version(priv->adapter, fmt, sizeof(fmt) - 1);
-
-       if (!priv->version_str[0])
-               mwifiex_get_ver_ext(priv);
-
-       p += sprintf(p, "driver_name = " "\"mwifiex\"\n");
-       p += sprintf(p, "driver_version = %s", fmt);
-       p += sprintf(p, "\nverext = %s", priv->version_str);
-       p += sprintf(p, "\ninterface_name=\"%s\"\n", netdev->name);
-
-       if (info.bss_mode >= ARRAY_SIZE(bss_modes))
-               p += sprintf(p, "bss_mode=\"%d\"\n", info.bss_mode);
-       else
-               p += sprintf(p, "bss_mode=\"%s\"\n", bss_modes[info.bss_mode]);
-
-       p += sprintf(p, "media_state=\"%s\"\n",
-                    (!priv->media_connected ? "Disconnected" : "Connected"));
-       p += sprintf(p, "mac_address=\"%pM\"\n", netdev->dev_addr);
-
-       if (GET_BSS_ROLE(priv) == MWIFIEX_BSS_ROLE_STA) {
-               p += sprintf(p, "multicast_count=\"%d\"\n",
-                            netdev_mc_count(netdev));
-               p += sprintf(p, "essid=\"%s\"\n", info.ssid.ssid);
-               p += sprintf(p, "bssid=\"%pM\"\n", info.bssid);
-               p += sprintf(p, "channel=\"%d\"\n", (int) info.bss_chan);
-               p += sprintf(p, "country_code = \"%s\"\n", info.country_code);
-
-               netdev_for_each_mc_addr(ha, netdev)
-                       p += sprintf(p, "multicast_address[%d]=\"%pM\"\n",
-                                       i++, ha->addr);
-       }
-
-       p += sprintf(p, "num_tx_bytes = %lu\n", priv->stats.tx_bytes);
-       p += sprintf(p, "num_rx_bytes = %lu\n", priv->stats.rx_bytes);
-       p += sprintf(p, "num_tx_pkts = %lu\n", priv->stats.tx_packets);
-       p += sprintf(p, "num_rx_pkts = %lu\n", priv->stats.rx_packets);
-       p += sprintf(p, "num_tx_pkts_dropped = %lu\n", priv->stats.tx_dropped);
-       p += sprintf(p, "num_rx_pkts_dropped = %lu\n", priv->stats.rx_dropped);
-       p += sprintf(p, "num_tx_pkts_err = %lu\n", priv->stats.tx_errors);
-       p += sprintf(p, "num_rx_pkts_err = %lu\n", priv->stats.rx_errors);
-       p += sprintf(p, "carrier %s\n", ((netif_carrier_ok(priv->netdev))
-                                        ? "on" : "off"));
-       p += sprintf(p, "tx queue");
-       for (i = 0; i < netdev->num_tx_queues; i++) {
-               txq = netdev_get_tx_queue(netdev, i);
-               p += sprintf(p, " %d:%s", i, netif_tx_queue_stopped(txq) ?
-                            "stopped" : "started");
-       }
-       p += sprintf(p, "\n");
-
-       ret = simple_read_from_buffer(ubuf, count, ppos, (char *) page,
-                                     (unsigned long) p - page);
-
-free_and_exit:
-       free_page(page);
-       return ret;
-}
-
-/*
- * Proc device dump read handler.
- *
- * This function is called when the 'device_dump' file is opened for
- * reading.
- * This function dumps driver information and firmware memory segments
- * (ex. DTCM, ITCM, SQRAM etc.) for
- * debugging.
- */
-static ssize_t
-mwifiex_device_dump_read(struct file *file, char __user *ubuf,
-                        size_t count, loff_t *ppos)
-{
-       struct mwifiex_private *priv = file->private_data;
-
-       if (!priv->adapter->if_ops.device_dump)
-               return -EIO;
-
-       priv->adapter->if_ops.device_dump(priv->adapter);
-
-       return 0;
-}
-
-/*
- * Proc getlog file read handler.
- *
- * This function is called when the 'getlog' file is opened for reading
- * It prints the following log information -
- *      - Number of multicast Tx frames
- *      - Number of failed packets
- *      - Number of Tx retries
- *      - Number of multicast Tx retries
- *      - Number of duplicate frames
- *      - Number of RTS successes
- *      - Number of RTS failures
- *      - Number of ACK failures
- *      - Number of fragmented Rx frames
- *      - Number of multicast Rx frames
- *      - Number of FCS errors
- *      - Number of Tx frames
- *      - WEP ICV error counts
- *      - Number of received beacons
- *      - Number of missed beacons
- */
-static ssize_t
-mwifiex_getlog_read(struct file *file, char __user *ubuf,
-                   size_t count, loff_t *ppos)
-{
-       struct mwifiex_private *priv =
-               (struct mwifiex_private *) file->private_data;
-       unsigned long page = get_zeroed_page(GFP_KERNEL);
-       char *p = (char *) page;
-       ssize_t ret;
-       struct mwifiex_ds_get_stats stats;
-
-       if (!p)
-               return -ENOMEM;
-
-       memset(&stats, 0, sizeof(stats));
-       ret = mwifiex_get_stats_info(priv, &stats);
-       if (ret)
-               goto free_and_exit;
-
-       p += sprintf(p, "\n"
-                    "mcasttxframe     %u\n"
-                    "failed           %u\n"
-                    "retry            %u\n"
-                    "multiretry       %u\n"
-                    "framedup         %u\n"
-                    "rtssuccess       %u\n"
-                    "rtsfailure       %u\n"
-                    "ackfailure       %u\n"
-                    "rxfrag           %u\n"
-                    "mcastrxframe     %u\n"
-                    "fcserror         %u\n"
-                    "txframe          %u\n"
-                    "wepicverrcnt-1   %u\n"
-                    "wepicverrcnt-2   %u\n"
-                    "wepicverrcnt-3   %u\n"
-                    "wepicverrcnt-4   %u\n"
-                    "bcn_rcv_cnt   %u\n"
-                    "bcn_miss_cnt   %u\n",
-                    stats.mcast_tx_frame,
-                    stats.failed,
-                    stats.retry,
-                    stats.multi_retry,
-                    stats.frame_dup,
-                    stats.rts_success,
-                    stats.rts_failure,
-                    stats.ack_failure,
-                    stats.rx_frag,
-                    stats.mcast_rx_frame,
-                    stats.fcs_error,
-                    stats.tx_frame,
-                    stats.wep_icv_error[0],
-                    stats.wep_icv_error[1],
-                    stats.wep_icv_error[2],
-                    stats.wep_icv_error[3],
-                    stats.bcn_rcv_cnt,
-                    stats.bcn_miss_cnt);
-
-
-       ret = simple_read_from_buffer(ubuf, count, ppos, (char *) page,
-                                     (unsigned long) p - page);
-
-free_and_exit:
-       free_page(page);
-       return ret;
-}
-
-/* Sysfs histogram file read handler.
- *
- * This function is called when the 'histogram' file is opened for reading
- * It prints the following histogram information -
- *      - Number of histogram samples
- *      - Receive packet number of each rx_rate
- *      - Receive packet number of each snr
- *      - Receive packet number of each nosie_flr
- *      - Receive packet number of each signal streath
- */
-static ssize_t
-mwifiex_histogram_read(struct file *file, char __user *ubuf,
-                      size_t count, loff_t *ppos)
-{
-       struct mwifiex_private *priv =
-               (struct mwifiex_private *)file->private_data;
-       ssize_t ret;
-       struct mwifiex_histogram_data *phist_data;
-       int i, value;
-       unsigned long page = get_zeroed_page(GFP_KERNEL);
-       char *p = (char *)page;
-
-       if (!p)
-               return -ENOMEM;
-
-       if (!priv || !priv->hist_data)
-               return -EFAULT;
-       phist_data = priv->hist_data;
-
-       p += sprintf(p, "\n"
-                    "total samples = %d\n",
-                    atomic_read(&phist_data->num_samples));
-
-       p += sprintf(p, "rx rates (in Mbps): 0=1M   1=2M");
-       p += sprintf(p, "2=5.5M  3=11M   4=6M   5=9M  6=12M\n");
-       p += sprintf(p, "7=18M  8=24M  9=36M  10=48M  11=54M");
-       p += sprintf(p, "12-27=MCS0-15(BW20) 28-43=MCS0-15(BW40)\n");
-
-       if (ISSUPP_11ACENABLED(priv->adapter->fw_cap_info)) {
-               p += sprintf(p, "44-53=MCS0-9(VHT:BW20)");
-               p += sprintf(p, "54-63=MCS0-9(VHT:BW40)");
-               p += sprintf(p, "64-73=MCS0-9(VHT:BW80)\n\n");
-       } else {
-               p += sprintf(p, "\n");
-       }
-
-       for (i = 0; i < MWIFIEX_MAX_RX_RATES; i++) {
-               value = atomic_read(&phist_data->rx_rate[i]);
-               if (value)
-                       p += sprintf(p, "rx_rate[%02d] = %d\n", i, value);
-       }
-
-       if (ISSUPP_11ACENABLED(priv->adapter->fw_cap_info)) {
-               for (i = MWIFIEX_MAX_RX_RATES; i < MWIFIEX_MAX_AC_RX_RATES;
-                    i++) {
-                       value = atomic_read(&phist_data->rx_rate[i]);
-                       if (value)
-                               p += sprintf(p, "rx_rate[%02d] = %d\n",
-                                          i, value);
-               }
-       }
-
-       for (i = 0; i < MWIFIEX_MAX_SNR; i++) {
-               value =  atomic_read(&phist_data->snr[i]);
-               if (value)
-                       p += sprintf(p, "snr[%02ddB] = %d\n", i, value);
-       }
-       for (i = 0; i < MWIFIEX_MAX_NOISE_FLR; i++) {
-               value = atomic_read(&phist_data->noise_flr[i]);
-               if (value)
-                       p += sprintf(p, "noise_flr[-%02ddBm] = %d\n",
-                               (int)(i-128), value);
-       }
-       for (i = 0; i < MWIFIEX_MAX_SIG_STRENGTH; i++) {
-               value = atomic_read(&phist_data->sig_str[i]);
-               if (value)
-                       p += sprintf(p, "sig_strength[-%02ddBm] = %d\n",
-                               i, value);
-       }
-
-       ret = simple_read_from_buffer(ubuf, count, ppos, (char *)page,
-                                     (unsigned long)p - page);
-
-       return ret;
-}
-
-static ssize_t
-mwifiex_histogram_write(struct file *file, const char __user *ubuf,
-                       size_t count, loff_t *ppos)
-{
-       struct mwifiex_private *priv = (void *)file->private_data;
-
-       if (priv && priv->hist_data)
-               mwifiex_hist_data_reset(priv);
-       return 0;
-}
-
-static struct mwifiex_debug_info info;
-
-/*
- * Proc debug file read handler.
- *
- * This function is called when the 'debug' file is opened for reading
- * It prints the following log information -
- *      - Interrupt count
- *      - WMM AC VO packets count
- *      - WMM AC VI packets count
- *      - WMM AC BE packets count
- *      - WMM AC BK packets count
- *      - Maximum Tx buffer size
- *      - Tx buffer size
- *      - Current Tx buffer size
- *      - Power Save mode
- *      - Power Save state
- *      - Deep Sleep status
- *      - Device wakeup required status
- *      - Number of wakeup tries
- *      - Host Sleep configured status
- *      - Host Sleep activated status
- *      - Number of Tx timeouts
- *      - Number of command timeouts
- *      - Last timed out command ID
- *      - Last timed out command action
- *      - Last command ID
- *      - Last command action
- *      - Last command index
- *      - Last command response ID
- *      - Last command response index
- *      - Last event
- *      - Last event index
- *      - Number of host to card command failures
- *      - Number of sleep confirm command failures
- *      - Number of host to card data failure
- *      - Number of deauthentication events
- *      - Number of disassociation events
- *      - Number of link lost events
- *      - Number of deauthentication commands
- *      - Number of association success commands
- *      - Number of association failure commands
- *      - Number of commands sent
- *      - Number of data packets sent
- *      - Number of command responses received
- *      - Number of events received
- *      - Tx BA stream table (TID, RA)
- *      - Rx reorder table (TID, TA, Start window, Window size, Buffer)
- */
-static ssize_t
-mwifiex_debug_read(struct file *file, char __user *ubuf,
-                  size_t count, loff_t *ppos)
-{
-       struct mwifiex_private *priv =
-               (struct mwifiex_private *) file->private_data;
-       unsigned long page = get_zeroed_page(GFP_KERNEL);
-       char *p = (char *) page;
-       ssize_t ret;
-
-       if (!p)
-               return -ENOMEM;
-
-       ret = mwifiex_get_debug_info(priv, &info);
-       if (ret)
-               goto free_and_exit;
-
-       p += mwifiex_debug_info_to_buffer(priv, p, &info);
-
-       ret = simple_read_from_buffer(ubuf, count, ppos, (char *) page,
-                                     (unsigned long) p - page);
-
-free_and_exit:
-       free_page(page);
-       return ret;
-}
-
-static u32 saved_reg_type, saved_reg_offset, saved_reg_value;
-
-/*
- * Proc regrdwr file write handler.
- *
- * This function is called when the 'regrdwr' file is opened for writing
- *
- * This function can be used to write to a register.
- */
-static ssize_t
-mwifiex_regrdwr_write(struct file *file,
-                     const char __user *ubuf, size_t count, loff_t *ppos)
-{
-       unsigned long addr = get_zeroed_page(GFP_KERNEL);
-       char *buf = (char *) addr;
-       size_t buf_size = min_t(size_t, count, PAGE_SIZE - 1);
-       int ret;
-       u32 reg_type = 0, reg_offset = 0, reg_value = UINT_MAX;
-
-       if (!buf)
-               return -ENOMEM;
-
-
-       if (copy_from_user(buf, ubuf, buf_size)) {
-               ret = -EFAULT;
-               goto done;
-       }
-
-       sscanf(buf, "%u %x %x", &reg_type, &reg_offset, &reg_value);
-
-       if (reg_type == 0 || reg_offset == 0) {
-               ret = -EINVAL;
-               goto done;
-       } else {
-               saved_reg_type = reg_type;
-               saved_reg_offset = reg_offset;
-               saved_reg_value = reg_value;
-               ret = count;
-       }
-done:
-       free_page(addr);
-       return ret;
-}
-
-/*
- * Proc regrdwr file read handler.
- *
- * This function is called when the 'regrdwr' file is opened for reading
- *
- * This function can be used to read from a register.
- */
-static ssize_t
-mwifiex_regrdwr_read(struct file *file, char __user *ubuf,
-                    size_t count, loff_t *ppos)
-{
-       struct mwifiex_private *priv =
-               (struct mwifiex_private *) file->private_data;
-       unsigned long addr = get_zeroed_page(GFP_KERNEL);
-       char *buf = (char *) addr;
-       int pos = 0, ret = 0;
-       u32 reg_value;
-
-       if (!buf)
-               return -ENOMEM;
-
-       if (!saved_reg_type) {
-               /* No command has been given */
-               pos += snprintf(buf, PAGE_SIZE, "0");
-               goto done;
-       }
-       /* Set command has been given */
-       if (saved_reg_value != UINT_MAX) {
-               ret = mwifiex_reg_write(priv, saved_reg_type, saved_reg_offset,
-                                       saved_reg_value);
-
-               pos += snprintf(buf, PAGE_SIZE, "%u 0x%x 0x%x\n",
-                               saved_reg_type, saved_reg_offset,
-                               saved_reg_value);
-
-               ret = simple_read_from_buffer(ubuf, count, ppos, buf, pos);
-
-               goto done;
-       }
-       /* Get command has been given */
-       ret = mwifiex_reg_read(priv, saved_reg_type,
-                              saved_reg_offset, &reg_value);
-       if (ret) {
-               ret = -EINVAL;
-               goto done;
-       }
-
-       pos += snprintf(buf, PAGE_SIZE, "%u 0x%x 0x%x\n", saved_reg_type,
-                       saved_reg_offset, reg_value);
-
-       ret = simple_read_from_buffer(ubuf, count, ppos, buf, pos);
-
-done:
-       free_page(addr);
-       return ret;
-}
-
-/* Proc debug_mask file read handler.
- * This function is called when the 'debug_mask' file is opened for reading
- * This function can be used read driver debugging mask value.
- */
-static ssize_t
-mwifiex_debug_mask_read(struct file *file, char __user *ubuf,
-                       size_t count, loff_t *ppos)
-{
-       struct mwifiex_private *priv =
-               (struct mwifiex_private *)file->private_data;
-       unsigned long page = get_zeroed_page(GFP_KERNEL);
-       char *buf = (char *)page;
-       size_t ret = 0;
-       int pos = 0;
-
-       if (!buf)
-               return -ENOMEM;
-
-       pos += snprintf(buf, PAGE_SIZE, "debug mask=0x%08x\n",
-                       priv->adapter->debug_mask);
-       ret = simple_read_from_buffer(ubuf, count, ppos, buf, pos);
-
-       free_page(page);
-       return ret;
-}
-
-/* Proc debug_mask file read handler.
- * This function is called when the 'debug_mask' file is opened for reading
- * This function can be used read driver debugging mask value.
- */
-static ssize_t
-mwifiex_debug_mask_write(struct file *file, const char __user *ubuf,
-                        size_t count, loff_t *ppos)
-{
-       int ret;
-       unsigned long debug_mask;
-       struct mwifiex_private *priv = (void *)file->private_data;
-       unsigned long addr = get_zeroed_page(GFP_KERNEL);
-       char *buf = (void *)addr;
-       size_t buf_size = min(count, (size_t)(PAGE_SIZE - 1));
-
-       if (!buf)
-               return -ENOMEM;
-
-       if (copy_from_user(buf, ubuf, buf_size)) {
-               ret = -EFAULT;
-               goto done;
-       }
-
-       if (kstrtoul(buf, 0, &debug_mask)) {
-               ret = -EINVAL;
-               goto done;
-       }
-
-       priv->adapter->debug_mask = debug_mask;
-       ret = count;
-done:
-       free_page(addr);
-       return ret;
-}
-
-/* Proc memrw file write handler.
- * This function is called when the 'memrw' file is opened for writing
- * This function can be used to write to a memory location.
- */
-static ssize_t
-mwifiex_memrw_write(struct file *file, const char __user *ubuf, size_t count,
-                   loff_t *ppos)
-{
-       int ret;
-       char cmd;
-       struct mwifiex_ds_mem_rw mem_rw;
-       u16 cmd_action;
-       struct mwifiex_private *priv = (void *)file->private_data;
-       unsigned long addr = get_zeroed_page(GFP_KERNEL);
-       char *buf = (void *)addr;
-       size_t buf_size = min(count, (size_t)(PAGE_SIZE - 1));
-
-       if (!buf)
-               return -ENOMEM;
-
-       if (copy_from_user(buf, ubuf, buf_size)) {
-               ret = -EFAULT;
-               goto done;
-       }
-
-       ret = sscanf(buf, "%c %x %x", &cmd, &mem_rw.addr, &mem_rw.value);
-       if (ret != 3) {
-               ret = -EINVAL;
-               goto done;
-       }
-
-       if ((cmd == 'r') || (cmd == 'R')) {
-               cmd_action = HostCmd_ACT_GEN_GET;
-               mem_rw.value = 0;
-       } else if ((cmd == 'w') || (cmd == 'W')) {
-               cmd_action = HostCmd_ACT_GEN_SET;
-       } else {
-               ret = -EINVAL;
-               goto done;
-       }
-
-       memcpy(&priv->mem_rw, &mem_rw, sizeof(mem_rw));
-       if (mwifiex_send_cmd(priv, HostCmd_CMD_MEM_ACCESS, cmd_action, 0,
-                            &mem_rw, true))
-               ret = -1;
-       else
-               ret = count;
-
-done:
-       free_page(addr);
-       return ret;
-}
-
-/* Proc memrw file read handler.
- * This function is called when the 'memrw' file is opened for reading
- * This function can be used to read from a memory location.
- */
-static ssize_t
-mwifiex_memrw_read(struct file *file, char __user *ubuf,
-                  size_t count, loff_t *ppos)
-{
-       struct mwifiex_private *priv = (void *)file->private_data;
-       unsigned long addr = get_zeroed_page(GFP_KERNEL);
-       char *buf = (char *)addr;
-       int ret, pos = 0;
-
-       if (!buf)
-               return -ENOMEM;
-
-       pos += snprintf(buf, PAGE_SIZE, "0x%x 0x%x\n", priv->mem_rw.addr,
-                       priv->mem_rw.value);
-       ret = simple_read_from_buffer(ubuf, count, ppos, buf, pos);
-
-       free_page(addr);
-       return ret;
-}
-
-static u32 saved_offset = -1, saved_bytes = -1;
-
-/*
- * Proc rdeeprom file write handler.
- *
- * This function is called when the 'rdeeprom' file is opened for writing
- *
- * This function can be used to write to a RDEEPROM location.
- */
-static ssize_t
-mwifiex_rdeeprom_write(struct file *file,
-                      const char __user *ubuf, size_t count, loff_t *ppos)
-{
-       unsigned long addr = get_zeroed_page(GFP_KERNEL);
-       char *buf = (char *) addr;
-       size_t buf_size = min_t(size_t, count, PAGE_SIZE - 1);
-       int ret = 0;
-       int offset = -1, bytes = -1;
-
-       if (!buf)
-               return -ENOMEM;
-
-
-       if (copy_from_user(buf, ubuf, buf_size)) {
-               ret = -EFAULT;
-               goto done;
-       }
-
-       sscanf(buf, "%d %d", &offset, &bytes);
-
-       if (offset == -1 || bytes == -1) {
-               ret = -EINVAL;
-               goto done;
-       } else {
-               saved_offset = offset;
-               saved_bytes = bytes;
-               ret = count;
-       }
-done:
-       free_page(addr);
-       return ret;
-}
-
-/*
- * Proc rdeeprom read write handler.
- *
- * This function is called when the 'rdeeprom' file is opened for reading
- *
- * This function can be used to read from a RDEEPROM location.
- */
-static ssize_t
-mwifiex_rdeeprom_read(struct file *file, char __user *ubuf,
-                     size_t count, loff_t *ppos)
-{
-       struct mwifiex_private *priv =
-               (struct mwifiex_private *) file->private_data;
-       unsigned long addr = get_zeroed_page(GFP_KERNEL);
-       char *buf = (char *) addr;
-       int pos, ret, i;
-       u8 value[MAX_EEPROM_DATA];
-
-       if (!buf)
-               return -ENOMEM;
-
-       if (saved_offset == -1) {
-               /* No command has been given */
-               pos = snprintf(buf, PAGE_SIZE, "0");
-               goto done;
-       }
-
-       /* Get command has been given */
-       ret = mwifiex_eeprom_read(priv, (u16) saved_offset,
-                                 (u16) saved_bytes, value);
-       if (ret) {
-               ret = -EINVAL;
-               goto out_free;
-       }
-
-       pos = snprintf(buf, PAGE_SIZE, "%d %d ", saved_offset, saved_bytes);
-
-       for (i = 0; i < saved_bytes; i++)
-               pos += scnprintf(buf + pos, PAGE_SIZE - pos, "%d ", value[i]);
-
-done:
-       ret = simple_read_from_buffer(ubuf, count, ppos, buf, pos);
-out_free:
-       free_page(addr);
-       return ret;
-}
-
-/* Proc hscfg file write handler
- * This function can be used to configure the host sleep parameters.
- */
-static ssize_t
-mwifiex_hscfg_write(struct file *file, const char __user *ubuf,
-                   size_t count, loff_t *ppos)
-{
-       struct mwifiex_private *priv = (void *)file->private_data;
-       unsigned long addr = get_zeroed_page(GFP_KERNEL);
-       char *buf = (char *)addr;
-       size_t buf_size = min_t(size_t, count, PAGE_SIZE - 1);
-       int ret, arg_num;
-       struct mwifiex_ds_hs_cfg hscfg;
-       int conditions = HS_CFG_COND_DEF;
-       u32 gpio = HS_CFG_GPIO_DEF, gap = HS_CFG_GAP_DEF;
-
-       if (!buf)
-               return -ENOMEM;
-
-       if (copy_from_user(buf, ubuf, buf_size)) {
-               ret = -EFAULT;
-               goto done;
-       }
-
-       arg_num = sscanf(buf, "%d %x %x", &conditions, &gpio, &gap);
-
-       memset(&hscfg, 0, sizeof(struct mwifiex_ds_hs_cfg));
-
-       if (arg_num > 3) {
-               mwifiex_dbg(priv->adapter, ERROR,
-                           "Too many arguments\n");
-               ret = -EINVAL;
-               goto done;
-       }
-
-       if (arg_num >= 1 && arg_num < 3)
-               mwifiex_set_hs_params(priv, HostCmd_ACT_GEN_GET,
-                                     MWIFIEX_SYNC_CMD, &hscfg);
-
-       if (arg_num) {
-               if (conditions == HS_CFG_CANCEL) {
-                       mwifiex_cancel_hs(priv, MWIFIEX_ASYNC_CMD);
-                       ret = count;
-                       goto done;
-               }
-               hscfg.conditions = conditions;
-       }
-       if (arg_num >= 2)
-               hscfg.gpio = gpio;
-       if (arg_num == 3)
-               hscfg.gap = gap;
-
-       hscfg.is_invoke_hostcmd = false;
-       mwifiex_set_hs_params(priv, HostCmd_ACT_GEN_SET,
-                             MWIFIEX_SYNC_CMD, &hscfg);
-
-       mwifiex_enable_hs(priv->adapter);
-       priv->adapter->hs_enabling = false;
-       ret = count;
-done:
-       free_page(addr);
-       return ret;
-}
-
-/* Proc hscfg file read handler
- * This function can be used to read host sleep configuration
- * parameters from driver.
- */
-static ssize_t
-mwifiex_hscfg_read(struct file *file, char __user *ubuf,
-                  size_t count, loff_t *ppos)
-{
-       struct mwifiex_private *priv = (void *)file->private_data;
-       unsigned long addr = get_zeroed_page(GFP_KERNEL);
-       char *buf = (char *)addr;
-       int pos, ret;
-       struct mwifiex_ds_hs_cfg hscfg;
-
-       if (!buf)
-               return -ENOMEM;
-
-       mwifiex_set_hs_params(priv, HostCmd_ACT_GEN_GET,
-                             MWIFIEX_SYNC_CMD, &hscfg);
-
-       pos = snprintf(buf, PAGE_SIZE, "%u 0x%x 0x%x\n", hscfg.conditions,
-                      hscfg.gpio, hscfg.gap);
-
-       ret = simple_read_from_buffer(ubuf, count, ppos, buf, pos);
-
-       free_page(addr);
-       return ret;
-}
-
-static ssize_t
-mwifiex_timeshare_coex_read(struct file *file, char __user *ubuf,
-                           size_t count, loff_t *ppos)
-{
-       struct mwifiex_private *priv = file->private_data;
-       char buf[3];
-       bool timeshare_coex;
-       int ret;
-       unsigned int len;
-
-       if (priv->adapter->fw_api_ver != MWIFIEX_FW_V15)
-               return -EOPNOTSUPP;
-
-       ret = mwifiex_send_cmd(priv, HostCmd_CMD_ROBUST_COEX,
-                              HostCmd_ACT_GEN_GET, 0, &timeshare_coex, true);
-       if (ret)
-               return ret;
-
-       len = sprintf(buf, "%d\n", timeshare_coex);
-       return simple_read_from_buffer(ubuf, count, ppos, buf, len);
-}
-
-static ssize_t
-mwifiex_timeshare_coex_write(struct file *file, const char __user *ubuf,
-                            size_t count, loff_t *ppos)
-{
-       bool timeshare_coex;
-       struct mwifiex_private *priv = file->private_data;
-       char kbuf[16];
-       int ret;
-
-       if (priv->adapter->fw_api_ver != MWIFIEX_FW_V15)
-               return -EOPNOTSUPP;
-
-       memset(kbuf, 0, sizeof(kbuf));
-
-       if (copy_from_user(&kbuf, ubuf, min_t(size_t, sizeof(kbuf) - 1, count)))
-               return -EFAULT;
-
-       if (strtobool(kbuf, &timeshare_coex))
-               return -EINVAL;
-
-       ret = mwifiex_send_cmd(priv, HostCmd_CMD_ROBUST_COEX,
-                              HostCmd_ACT_GEN_SET, 0, &timeshare_coex, true);
-       if (ret)
-               return ret;
-       else
-               return count;
-}
-
-#define MWIFIEX_DFS_ADD_FILE(name) do {                                 \
-       if (!debugfs_create_file(#name, 0644, priv->dfs_dev_dir,        \
-                       priv, &mwifiex_dfs_##name##_fops))              \
-               return;                                                 \
-} while (0);
-
-#define MWIFIEX_DFS_FILE_OPS(name)                                      \
-static const struct file_operations mwifiex_dfs_##name##_fops = {       \
-       .read = mwifiex_##name##_read,                                  \
-       .write = mwifiex_##name##_write,                                \
-       .open = simple_open,                                            \
-};
-
-#define MWIFIEX_DFS_FILE_READ_OPS(name)                                 \
-static const struct file_operations mwifiex_dfs_##name##_fops = {       \
-       .read = mwifiex_##name##_read,                                  \
-       .open = simple_open,                                            \
-};
-
-#define MWIFIEX_DFS_FILE_WRITE_OPS(name)                                \
-static const struct file_operations mwifiex_dfs_##name##_fops = {       \
-       .write = mwifiex_##name##_write,                                \
-       .open = simple_open,                                            \
-};
-
-
-MWIFIEX_DFS_FILE_READ_OPS(info);
-MWIFIEX_DFS_FILE_READ_OPS(debug);
-MWIFIEX_DFS_FILE_READ_OPS(getlog);
-MWIFIEX_DFS_FILE_READ_OPS(device_dump);
-MWIFIEX_DFS_FILE_OPS(regrdwr);
-MWIFIEX_DFS_FILE_OPS(rdeeprom);
-MWIFIEX_DFS_FILE_OPS(memrw);
-MWIFIEX_DFS_FILE_OPS(hscfg);
-MWIFIEX_DFS_FILE_OPS(histogram);
-MWIFIEX_DFS_FILE_OPS(debug_mask);
-MWIFIEX_DFS_FILE_OPS(timeshare_coex);
-
-/*
- * This function creates the debug FS directory structure and the files.
- */
-void
-mwifiex_dev_debugfs_init(struct mwifiex_private *priv)
-{
-       if (!mwifiex_dfs_dir || !priv)
-               return;
-
-       priv->dfs_dev_dir = debugfs_create_dir(priv->netdev->name,
-                                              mwifiex_dfs_dir);
-
-       if (!priv->dfs_dev_dir)
-               return;
-
-       MWIFIEX_DFS_ADD_FILE(info);
-       MWIFIEX_DFS_ADD_FILE(debug);
-       MWIFIEX_DFS_ADD_FILE(getlog);
-       MWIFIEX_DFS_ADD_FILE(regrdwr);
-       MWIFIEX_DFS_ADD_FILE(rdeeprom);
-       MWIFIEX_DFS_ADD_FILE(device_dump);
-       MWIFIEX_DFS_ADD_FILE(memrw);
-       MWIFIEX_DFS_ADD_FILE(hscfg);
-       MWIFIEX_DFS_ADD_FILE(histogram);
-       MWIFIEX_DFS_ADD_FILE(debug_mask);
-       MWIFIEX_DFS_ADD_FILE(timeshare_coex);
-}
-
-/*
- * This function removes the debug FS directory structure and the files.
- */
-void
-mwifiex_dev_debugfs_remove(struct mwifiex_private *priv)
-{
-       if (!priv)
-               return;
-
-       debugfs_remove_recursive(priv->dfs_dev_dir);
-}
-
-/*
- * This function creates the top level proc directory.
- */
-void
-mwifiex_debugfs_init(void)
-{
-       if (!mwifiex_dfs_dir)
-               mwifiex_dfs_dir = debugfs_create_dir("mwifiex", NULL);
-}
-
-/*
- * This function removes the top level proc directory.
- */
-void
-mwifiex_debugfs_remove(void)
-{
-       if (mwifiex_dfs_dir)
-               debugfs_remove(mwifiex_dfs_dir);
-}
diff --git a/drivers/net/wireless/mwifiex/decl.h b/drivers/net/wireless/mwifiex/decl.h
deleted file mode 100644 (file)
index 098e1f1..0000000
+++ /dev/null
@@ -1,273 +0,0 @@
-/*
- * Marvell Wireless LAN device driver: generic data structures and APIs
- *
- * Copyright (C) 2011-2014, Marvell International Ltd.
- *
- * This software file (the "File") is distributed by Marvell International
- * Ltd. under the terms of the GNU General Public License Version 2, June 1991
- * (the "License").  You may use, redistribute and/or modify this File in
- * accordance with the terms and conditions of the License, a copy of which
- * is available by writing to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the
- * worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
- *
- * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
- * ARE EXPRESSLY DISCLAIMED.  The License provides additional details about
- * this warranty disclaimer.
- */
-
-#ifndef _MWIFIEX_DECL_H_
-#define _MWIFIEX_DECL_H_
-
-#undef pr_fmt
-#define pr_fmt(fmt)    KBUILD_MODNAME ": " fmt
-
-#include <linux/wait.h>
-#include <linux/timer.h>
-#include <linux/ieee80211.h>
-#include <uapi/linux/if_arp.h>
-#include <net/mac80211.h>
-
-#define MWIFIEX_BSS_COEX_COUNT      2
-#define MWIFIEX_MAX_BSS_NUM         (3)
-
-#define MWIFIEX_DMA_ALIGN_SZ       64
-#define MWIFIEX_RX_HEADROOM        64
-#define MAX_TXPD_SZ                32
-#define INTF_HDR_ALIGN              4
-
-#define MWIFIEX_MIN_DATA_HEADER_LEN (MWIFIEX_DMA_ALIGN_SZ + INTF_HDR_ALIGN + \
-                                    MAX_TXPD_SZ)
-#define MWIFIEX_MGMT_FRAME_HEADER_SIZE 8       /* sizeof(pkt_type)
-                                                *   + sizeof(tx_control)
-                                                */
-
-#define MWIFIEX_MAX_TX_BASTREAM_SUPPORTED      2
-#define MWIFIEX_MAX_RX_BASTREAM_SUPPORTED      16
-#define MWIFIEX_MAX_TDLS_PEER_SUPPORTED 8
-
-#define MWIFIEX_STA_AMPDU_DEF_TXWINSIZE        64
-#define MWIFIEX_STA_AMPDU_DEF_RXWINSIZE        64
-#define MWIFIEX_STA_COEX_AMPDU_DEF_RXWINSIZE   16
-
-#define MWIFIEX_UAP_AMPDU_DEF_TXWINSIZE        32
-
-#define MWIFIEX_UAP_COEX_AMPDU_DEF_RXWINSIZE   16
-
-#define MWIFIEX_UAP_AMPDU_DEF_RXWINSIZE        16
-#define MWIFIEX_11AC_STA_AMPDU_DEF_TXWINSIZE   64
-#define MWIFIEX_11AC_STA_AMPDU_DEF_RXWINSIZE   64
-#define MWIFIEX_11AC_UAP_AMPDU_DEF_TXWINSIZE   64
-#define MWIFIEX_11AC_UAP_AMPDU_DEF_RXWINSIZE   64
-
-#define MWIFIEX_DEFAULT_BLOCK_ACK_TIMEOUT  0xffff
-
-#define MWIFIEX_RATE_BITMAP_MCS0   32
-
-#define MWIFIEX_RX_DATA_BUF_SIZE     (4 * 1024)
-#define MWIFIEX_RX_CMD_BUF_SIZE             (2 * 1024)
-
-#define MAX_BEACON_PERIOD                  (4000)
-#define MIN_BEACON_PERIOD                  (50)
-#define MAX_DTIM_PERIOD                    (100)
-#define MIN_DTIM_PERIOD                    (1)
-
-#define MWIFIEX_RTS_MIN_VALUE              (0)
-#define MWIFIEX_RTS_MAX_VALUE              (2347)
-#define MWIFIEX_FRAG_MIN_VALUE             (256)
-#define MWIFIEX_FRAG_MAX_VALUE             (2346)
-#define MWIFIEX_WMM_VERSION                0x01
-#define MWIFIEX_WMM_SUBTYPE                0x01
-
-#define MWIFIEX_RETRY_LIMIT                14
-#define MWIFIEX_SDIO_BLOCK_SIZE            256
-
-#define MWIFIEX_BUF_FLAG_REQUEUED_PKT      BIT(0)
-#define MWIFIEX_BUF_FLAG_BRIDGED_PKT      BIT(1)
-#define MWIFIEX_BUF_FLAG_TDLS_PKT         BIT(2)
-#define MWIFIEX_BUF_FLAG_EAPOL_TX_STATUS   BIT(3)
-#define MWIFIEX_BUF_FLAG_ACTION_TX_STATUS  BIT(4)
-#define MWIFIEX_BUF_FLAG_AGGR_PKT          BIT(5)
-
-#define MWIFIEX_BRIDGED_PKTS_THR_HIGH      1024
-#define MWIFIEX_BRIDGED_PKTS_THR_LOW        128
-
-#define MWIFIEX_TDLS_DISABLE_LINK             0x00
-#define MWIFIEX_TDLS_ENABLE_LINK              0x01
-#define MWIFIEX_TDLS_CREATE_LINK              0x02
-#define MWIFIEX_TDLS_CONFIG_LINK              0x03
-
-#define MWIFIEX_TDLS_RSSI_HIGH         50
-#define MWIFIEX_TDLS_RSSI_LOW          55
-#define MWIFIEX_TDLS_MAX_FAIL_COUNT      4
-#define MWIFIEX_AUTO_TDLS_IDLE_TIME     10
-
-/* 54M rates, index from 0 to 11 */
-#define MWIFIEX_RATE_INDEX_MCS0 12
-/* 12-27=MCS0-15(BW20) */
-#define MWIFIEX_BW20_MCS_NUM 15
-
-/* Rate index for OFDM 0 */
-#define MWIFIEX_RATE_INDEX_OFDM0   4
-
-#define MWIFIEX_MAX_STA_NUM            1
-#define MWIFIEX_MAX_UAP_NUM            1
-#define MWIFIEX_MAX_P2P_NUM            1
-
-#define MWIFIEX_A_BAND_START_FREQ      5000
-
-/* SDIO Aggr data packet special info */
-#define SDIO_MAX_AGGR_BUF_SIZE         (256 * 255)
-#define BLOCK_NUMBER_OFFSET            15
-#define SDIO_HEADER_OFFSET             28
-
-enum mwifiex_bss_type {
-       MWIFIEX_BSS_TYPE_STA = 0,
-       MWIFIEX_BSS_TYPE_UAP = 1,
-       MWIFIEX_BSS_TYPE_P2P = 2,
-       MWIFIEX_BSS_TYPE_ANY = 0xff,
-};
-
-enum mwifiex_bss_role {
-       MWIFIEX_BSS_ROLE_STA = 0,
-       MWIFIEX_BSS_ROLE_UAP = 1,
-       MWIFIEX_BSS_ROLE_ANY = 0xff,
-};
-
-enum mwifiex_tdls_status {
-       TDLS_NOT_SETUP = 0,
-       TDLS_SETUP_INPROGRESS,
-       TDLS_SETUP_COMPLETE,
-       TDLS_SETUP_FAILURE,
-       TDLS_LINK_TEARDOWN,
-       TDLS_CHAN_SWITCHING,
-       TDLS_IN_BASE_CHAN,
-       TDLS_IN_OFF_CHAN,
-};
-
-enum mwifiex_tdls_error_code {
-       TDLS_ERR_NO_ERROR = 0,
-       TDLS_ERR_INTERNAL_ERROR,
-       TDLS_ERR_MAX_LINKS_EST,
-       TDLS_ERR_LINK_EXISTS,
-       TDLS_ERR_LINK_NONEXISTENT,
-       TDLS_ERR_PEER_STA_UNREACHABLE = 25,
-};
-
-#define BSS_ROLE_BIT_MASK    BIT(0)
-
-#define GET_BSS_ROLE(priv)   ((priv)->bss_role & BSS_ROLE_BIT_MASK)
-
-enum mwifiex_data_frame_type {
-       MWIFIEX_DATA_FRAME_TYPE_ETH_II = 0,
-       MWIFIEX_DATA_FRAME_TYPE_802_11,
-};
-
-struct mwifiex_fw_image {
-       u8 *helper_buf;
-       u32 helper_len;
-       u8 *fw_buf;
-       u32 fw_len;
-};
-
-struct mwifiex_802_11_ssid {
-       u32 ssid_len;
-       u8 ssid[IEEE80211_MAX_SSID_LEN];
-};
-
-struct mwifiex_wait_queue {
-       wait_queue_head_t wait;
-       int status;
-};
-
-struct mwifiex_rxinfo {
-       struct sk_buff *parent;
-       u8 bss_num;
-       u8 bss_type;
-       u8 use_count;
-       u8 buf_type;
-};
-
-struct mwifiex_txinfo {
-       u32 status_code;
-       u8 flags;
-       u8 bss_num;
-       u8 bss_type;
-       u8 aggr_num;
-       u32 pkt_len;
-       u8 ack_frame_id;
-       u64 cookie;
-};
-
-enum mwifiex_wmm_ac_e {
-       WMM_AC_BK,
-       WMM_AC_BE,
-       WMM_AC_VI,
-       WMM_AC_VO
-} __packed;
-
-struct ieee_types_wmm_ac_parameters {
-       u8 aci_aifsn_bitmap;
-       u8 ecw_bitmap;
-       __le16 tx_op_limit;
-} __packed;
-
-struct mwifiex_types_wmm_info {
-       u8 oui[4];
-       u8 subtype;
-       u8 version;
-       u8 qos_info;
-       u8 reserved;
-       struct ieee_types_wmm_ac_parameters ac_params[IEEE80211_NUM_ACS];
-} __packed;
-
-struct mwifiex_arp_eth_header {
-       struct arphdr hdr;
-       u8 ar_sha[ETH_ALEN];
-       u8 ar_sip[4];
-       u8 ar_tha[ETH_ALEN];
-       u8 ar_tip[4];
-} __packed;
-
-struct mwifiex_chan_stats {
-       u8 chan_num;
-       u8 bandcfg;
-       u8 flags;
-       s8 noise;
-       u16 total_bss;
-       u16 cca_scan_dur;
-       u16 cca_busy_dur;
-} __packed;
-
-#define MWIFIEX_HIST_MAX_SAMPLES       1048576
-#define MWIFIEX_MAX_RX_RATES                44
-#define MWIFIEX_MAX_AC_RX_RATES                     74
-#define MWIFIEX_MAX_SNR                            256
-#define MWIFIEX_MAX_NOISE_FLR              256
-#define MWIFIEX_MAX_SIG_STRENGTH           256
-
-struct mwifiex_histogram_data {
-       atomic_t rx_rate[MWIFIEX_MAX_AC_RX_RATES];
-       atomic_t snr[MWIFIEX_MAX_SNR];
-       atomic_t noise_flr[MWIFIEX_MAX_NOISE_FLR];
-       atomic_t sig_str[MWIFIEX_MAX_SIG_STRENGTH];
-       atomic_t num_samples;
-};
-
-struct mwifiex_iface_comb {
-       u8 sta_intf;
-       u8 uap_intf;
-       u8 p2p_intf;
-};
-
-struct mwifiex_radar_params {
-       struct cfg80211_chan_def *chandef;
-       u32 cac_time_ms;
-} __packed;
-
-struct mwifiex_11h_intf_state {
-       bool is_11h_enabled;
-       bool is_11h_active;
-} __packed;
-#endif /* !_MWIFIEX_DECL_H_ */
diff --git a/drivers/net/wireless/mwifiex/ethtool.c b/drivers/net/wireless/mwifiex/ethtool.c
deleted file mode 100644 (file)
index 58400c6..0000000
+++ /dev/null
@@ -1,70 +0,0 @@
-/*
- * Marvell Wireless LAN device driver: ethtool
- *
- * Copyright (C) 2013-2014, Marvell International Ltd.
- *
- * This software file (the "File") is distributed by Marvell International
- * Ltd. under the terms of the GNU General Public License Version 2, June 1991
- * (the "License").  You may use, redistribute and/or modify this File in
- * accordance with the terms and conditions of the License, a copy of which
- * is available by writing to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the
- * worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
- *
- * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
- * ARE EXPRESSLY DISCLAIMED.  The License provides additional details about
- * this warranty disclaimer.
- */
-
-#include "main.h"
-
-static void mwifiex_ethtool_get_wol(struct net_device *dev,
-                                   struct ethtool_wolinfo *wol)
-{
-       struct mwifiex_private *priv = mwifiex_netdev_get_priv(dev);
-       u32 conditions = le32_to_cpu(priv->adapter->hs_cfg.conditions);
-
-       wol->supported = WAKE_UCAST|WAKE_MCAST|WAKE_BCAST|WAKE_PHY;
-
-       if (conditions == HS_CFG_COND_DEF)
-               return;
-
-       if (conditions & HS_CFG_COND_UNICAST_DATA)
-               wol->wolopts |= WAKE_UCAST;
-       if (conditions & HS_CFG_COND_MULTICAST_DATA)
-               wol->wolopts |= WAKE_MCAST;
-       if (conditions & HS_CFG_COND_BROADCAST_DATA)
-               wol->wolopts |= WAKE_BCAST;
-       if (conditions & HS_CFG_COND_MAC_EVENT)
-               wol->wolopts |= WAKE_PHY;
-}
-
-static int mwifiex_ethtool_set_wol(struct net_device *dev,
-                                  struct ethtool_wolinfo *wol)
-{
-       struct mwifiex_private *priv = mwifiex_netdev_get_priv(dev);
-       u32 conditions = 0;
-
-       if (wol->wolopts & ~(WAKE_UCAST|WAKE_MCAST|WAKE_BCAST|WAKE_PHY))
-               return -EOPNOTSUPP;
-
-       if (wol->wolopts & WAKE_UCAST)
-               conditions |= HS_CFG_COND_UNICAST_DATA;
-       if (wol->wolopts & WAKE_MCAST)
-               conditions |= HS_CFG_COND_MULTICAST_DATA;
-       if (wol->wolopts & WAKE_BCAST)
-               conditions |= HS_CFG_COND_BROADCAST_DATA;
-       if (wol->wolopts & WAKE_PHY)
-               conditions |= HS_CFG_COND_MAC_EVENT;
-       if (wol->wolopts == 0)
-               conditions |= HS_CFG_COND_DEF;
-       priv->adapter->hs_cfg.conditions = cpu_to_le32(conditions);
-
-       return 0;
-}
-
-const struct ethtool_ops mwifiex_ethtool_ops = {
-       .get_wol = mwifiex_ethtool_get_wol,
-       .set_wol = mwifiex_ethtool_set_wol,
-};
diff --git a/drivers/net/wireless/mwifiex/fw.h b/drivers/net/wireless/mwifiex/fw.h
deleted file mode 100644 (file)
index 1e1e81a..0000000
+++ /dev/null
@@ -1,2177 +0,0 @@
-/*
- * Marvell Wireless LAN device driver: Firmware specific macros & structures
- *
- * Copyright (C) 2011-2014, Marvell International Ltd.
- *
- * This software file (the "File") is distributed by Marvell International
- * Ltd. under the terms of the GNU General Public License Version 2, June 1991
- * (the "License").  You may use, redistribute and/or modify this File in
- * accordance with the terms and conditions of the License, a copy of which
- * is available by writing to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the
- * worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
- *
- * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
- * ARE EXPRESSLY DISCLAIMED.  The License provides additional details about
- * this warranty disclaimer.
- */
-
-#ifndef _MWIFIEX_FW_H_
-#define _MWIFIEX_FW_H_
-
-#include <linux/if_ether.h>
-
-
-#define INTF_HEADER_LEN     4
-
-struct rfc_1042_hdr {
-       u8 llc_dsap;
-       u8 llc_ssap;
-       u8 llc_ctrl;
-       u8 snap_oui[3];
-       __be16 snap_type;
-};
-
-struct rx_packet_hdr {
-       struct ethhdr eth803_hdr;
-       struct rfc_1042_hdr rfc1042_hdr;
-};
-
-struct tx_packet_hdr {
-       struct ethhdr eth803_hdr;
-       struct rfc_1042_hdr rfc1042_hdr;
-};
-
-#define B_SUPPORTED_RATES               5
-#define G_SUPPORTED_RATES               9
-#define BG_SUPPORTED_RATES              13
-#define A_SUPPORTED_RATES               9
-#define HOSTCMD_SUPPORTED_RATES         14
-#define N_SUPPORTED_RATES               3
-#define ALL_802_11_BANDS           (BAND_A | BAND_B | BAND_G | BAND_GN | \
-                                   BAND_AN | BAND_AAC)
-
-#define FW_MULTI_BANDS_SUPPORT  (BIT(8) | BIT(9) | BIT(10) | BIT(11) | \
-                                BIT(13))
-#define IS_SUPPORT_MULTI_BANDS(adapter)        \
-       (adapter->fw_cap_info & FW_MULTI_BANDS_SUPPORT)
-
-/* bit 13: 11ac BAND_AAC
- * bit 12: reserved for lab testing, will be reused for BAND_AN
- * bit 11: 11n  BAND_GN
- * bit 10: 11a  BAND_A
- * bit 9: 11g   BAND_G
- * bit 8: 11b   BAND_B
- * Map these bits to band capability by right shifting 8 bits.
- */
-#define GET_FW_DEFAULT_BANDS(adapter)  \
-           (((adapter->fw_cap_info & 0x2f00) >> 8) & \
-            ALL_802_11_BANDS)
-
-#define HostCmd_WEP_KEY_INDEX_MASK              0x3fff
-
-#define KEY_INFO_ENABLED        0x01
-enum KEY_TYPE_ID {
-       KEY_TYPE_ID_WEP = 0,
-       KEY_TYPE_ID_TKIP,
-       KEY_TYPE_ID_AES,
-       KEY_TYPE_ID_WAPI,
-       KEY_TYPE_ID_AES_CMAC,
-};
-
-#define WPA_PN_SIZE            8
-#define KEY_PARAMS_FIXED_LEN   10
-#define KEY_INDEX_MASK         0xf
-#define KEY_API_VER_MAJOR_V2   2
-
-#define KEY_MCAST      BIT(0)
-#define KEY_UNICAST    BIT(1)
-#define KEY_ENABLED    BIT(2)
-#define KEY_DEFAULT    BIT(3)
-#define KEY_TX_KEY     BIT(4)
-#define KEY_RX_KEY     BIT(5)
-#define KEY_IGTK       BIT(10)
-
-#define WAPI_KEY_LEN                   (WLAN_KEY_LEN_SMS4 + PN_LEN + 2)
-
-#define MAX_POLL_TRIES                 100
-#define MAX_FIRMWARE_POLL_TRIES                        100
-
-#define FIRMWARE_READY_SDIO                            0xfedc
-#define FIRMWARE_READY_PCIE                            0xfedcba00
-
-#define MWIFIEX_COEX_MODE_TIMESHARE                    0x01
-#define MWIFIEX_COEX_MODE_SPATIAL                      0x82
-
-enum mwifiex_usb_ep {
-       MWIFIEX_USB_EP_CMD_EVENT = 1,
-       MWIFIEX_USB_EP_DATA = 2,
-       MWIFIEX_USB_EP_DATA_CH2 = 3,
-};
-
-enum MWIFIEX_802_11_PRIVACY_FILTER {
-       MWIFIEX_802_11_PRIV_FILTER_ACCEPT_ALL,
-       MWIFIEX_802_11_PRIV_FILTER_8021X_WEP
-};
-
-#define CAL_SNR(RSSI, NF)              ((s16)((s16)(RSSI)-(s16)(NF)))
-#define CAL_RSSI(SNR, NF)              ((s16)((s16)(SNR)+(s16)(NF)))
-
-#define UAP_BSS_PARAMS_I                       0
-#define UAP_CUSTOM_IE_I                                1
-#define MWIFIEX_AUTO_IDX_MASK                  0xffff
-#define MWIFIEX_DELETE_MASK                    0x0000
-#define MGMT_MASK_ASSOC_REQ                    0x01
-#define MGMT_MASK_REASSOC_REQ                  0x04
-#define MGMT_MASK_ASSOC_RESP                   0x02
-#define MGMT_MASK_REASSOC_RESP                 0x08
-#define MGMT_MASK_PROBE_REQ                    0x10
-#define MGMT_MASK_PROBE_RESP                   0x20
-#define MGMT_MASK_BEACON                       0x100
-
-#define TLV_TYPE_UAP_SSID                      0x0000
-#define TLV_TYPE_UAP_RATES                     0x0001
-#define TLV_TYPE_PWR_CONSTRAINT                        0x0020
-
-#define PROPRIETARY_TLV_BASE_ID                 0x0100
-#define TLV_TYPE_KEY_MATERIAL       (PROPRIETARY_TLV_BASE_ID + 0)
-#define TLV_TYPE_CHANLIST           (PROPRIETARY_TLV_BASE_ID + 1)
-#define TLV_TYPE_NUMPROBES          (PROPRIETARY_TLV_BASE_ID + 2)
-#define TLV_TYPE_RSSI_LOW           (PROPRIETARY_TLV_BASE_ID + 4)
-#define TLV_TYPE_PASSTHROUGH        (PROPRIETARY_TLV_BASE_ID + 10)
-#define TLV_TYPE_WMMQSTATUS         (PROPRIETARY_TLV_BASE_ID + 16)
-#define TLV_TYPE_WILDCARDSSID       (PROPRIETARY_TLV_BASE_ID + 18)
-#define TLV_TYPE_TSFTIMESTAMP       (PROPRIETARY_TLV_BASE_ID + 19)
-#define TLV_TYPE_RSSI_HIGH          (PROPRIETARY_TLV_BASE_ID + 22)
-#define TLV_TYPE_AUTH_TYPE          (PROPRIETARY_TLV_BASE_ID + 31)
-#define TLV_TYPE_STA_MAC_ADDR       (PROPRIETARY_TLV_BASE_ID + 32)
-#define TLV_TYPE_BSSID              (PROPRIETARY_TLV_BASE_ID + 35)
-#define TLV_TYPE_CHANNELBANDLIST    (PROPRIETARY_TLV_BASE_ID + 42)
-#define TLV_TYPE_UAP_BEACON_PERIOD  (PROPRIETARY_TLV_BASE_ID + 44)
-#define TLV_TYPE_UAP_DTIM_PERIOD    (PROPRIETARY_TLV_BASE_ID + 45)
-#define TLV_TYPE_UAP_BCAST_SSID     (PROPRIETARY_TLV_BASE_ID + 48)
-#define TLV_TYPE_UAP_RTS_THRESHOLD  (PROPRIETARY_TLV_BASE_ID + 51)
-#define TLV_TYPE_UAP_AO_TIMER       (PROPRIETARY_TLV_BASE_ID + 57)
-#define TLV_TYPE_UAP_WEP_KEY        (PROPRIETARY_TLV_BASE_ID + 59)
-#define TLV_TYPE_UAP_WPA_PASSPHRASE (PROPRIETARY_TLV_BASE_ID + 60)
-#define TLV_TYPE_UAP_ENCRY_PROTOCOL (PROPRIETARY_TLV_BASE_ID + 64)
-#define TLV_TYPE_UAP_AKMP           (PROPRIETARY_TLV_BASE_ID + 65)
-#define TLV_TYPE_UAP_FRAG_THRESHOLD (PROPRIETARY_TLV_BASE_ID + 70)
-#define TLV_TYPE_RATE_DROP_CONTROL  (PROPRIETARY_TLV_BASE_ID + 82)
-#define TLV_TYPE_RATE_SCOPE         (PROPRIETARY_TLV_BASE_ID + 83)
-#define TLV_TYPE_POWER_GROUP        (PROPRIETARY_TLV_BASE_ID + 84)
-#define TLV_TYPE_BSS_SCAN_RSP       (PROPRIETARY_TLV_BASE_ID + 86)
-#define TLV_TYPE_BSS_SCAN_INFO      (PROPRIETARY_TLV_BASE_ID + 87)
-#define TLV_TYPE_CHANRPT_11H_BASIC  (PROPRIETARY_TLV_BASE_ID + 91)
-#define TLV_TYPE_UAP_RETRY_LIMIT    (PROPRIETARY_TLV_BASE_ID + 93)
-#define TLV_TYPE_WAPI_IE            (PROPRIETARY_TLV_BASE_ID + 94)
-#define TLV_TYPE_ROBUST_COEX        (PROPRIETARY_TLV_BASE_ID + 96)
-#define TLV_TYPE_UAP_MGMT_FRAME     (PROPRIETARY_TLV_BASE_ID + 104)
-#define TLV_TYPE_MGMT_IE            (PROPRIETARY_TLV_BASE_ID + 105)
-#define TLV_TYPE_AUTO_DS_PARAM      (PROPRIETARY_TLV_BASE_ID + 113)
-#define TLV_TYPE_PS_PARAM           (PROPRIETARY_TLV_BASE_ID + 114)
-#define TLV_TYPE_UAP_PS_AO_TIMER    (PROPRIETARY_TLV_BASE_ID + 123)
-#define TLV_TYPE_PWK_CIPHER         (PROPRIETARY_TLV_BASE_ID + 145)
-#define TLV_TYPE_GWK_CIPHER         (PROPRIETARY_TLV_BASE_ID + 146)
-#define TLV_TYPE_TX_PAUSE           (PROPRIETARY_TLV_BASE_ID + 148)
-#define TLV_TYPE_COALESCE_RULE      (PROPRIETARY_TLV_BASE_ID + 154)
-#define TLV_TYPE_KEY_PARAM_V2       (PROPRIETARY_TLV_BASE_ID + 156)
-#define TLV_TYPE_MULTI_CHAN_INFO    (PROPRIETARY_TLV_BASE_ID + 183)
-#define TLV_TYPE_MC_GROUP_INFO      (PROPRIETARY_TLV_BASE_ID + 184)
-#define TLV_TYPE_TDLS_IDLE_TIMEOUT  (PROPRIETARY_TLV_BASE_ID + 194)
-#define TLV_TYPE_SCAN_CHANNEL_GAP   (PROPRIETARY_TLV_BASE_ID + 197)
-#define TLV_TYPE_API_REV            (PROPRIETARY_TLV_BASE_ID + 199)
-#define TLV_TYPE_CHANNEL_STATS      (PROPRIETARY_TLV_BASE_ID + 198)
-#define TLV_BTCOEX_WL_AGGR_WINSIZE  (PROPRIETARY_TLV_BASE_ID + 202)
-#define TLV_BTCOEX_WL_SCANTIME      (PROPRIETARY_TLV_BASE_ID + 203)
-#define TLV_TYPE_BSS_MODE           (PROPRIETARY_TLV_BASE_ID + 206)
-
-#define MWIFIEX_TX_DATA_BUF_SIZE_2K        2048
-
-#define SSN_MASK         0xfff0
-
-#define BA_RESULT_SUCCESS        0x0
-#define BA_RESULT_TIMEOUT        0x2
-
-#define IS_BASTREAM_SETUP(ptr)  (ptr->ba_status)
-
-#define BA_STREAM_NOT_ALLOWED   0xff
-
-#define IS_11N_ENABLED(priv) ((priv->adapter->config_bands & BAND_GN || \
-                       priv->adapter->config_bands & BAND_AN) && \
-                       priv->curr_bss_params.bss_descriptor.bcn_ht_cap)
-#define INITIATOR_BIT(DelBAParamSet) (((DelBAParamSet) &\
-                       BIT(DELBA_INITIATOR_POS)) >> DELBA_INITIATOR_POS)
-
-#define MWIFIEX_TX_DATA_BUF_SIZE_4K        4096
-#define MWIFIEX_TX_DATA_BUF_SIZE_8K        8192
-
-#define ISSUPP_11NENABLED(FwCapInfo) (FwCapInfo & BIT(11))
-#define ISSUPP_TDLS_ENABLED(FwCapInfo) (FwCapInfo & BIT(14))
-#define ISSUPP_DRCS_ENABLED(FwCapInfo) (FwCapInfo & BIT(15))
-#define ISSUPP_SDIO_SPA_ENABLED(FwCapInfo) (FwCapInfo & BIT(16))
-
-#define MWIFIEX_DEF_HT_CAP     (IEEE80211_HT_CAP_DSSSCCK40 | \
-                                (1 << IEEE80211_HT_CAP_RX_STBC_SHIFT) | \
-                                IEEE80211_HT_CAP_SM_PS)
-
-#define MWIFIEX_DEF_11N_TX_BF_CAP      0x09E1E008
-
-#define MWIFIEX_DEF_AMPDU      IEEE80211_HT_AMPDU_PARM_FACTOR
-
-#define GET_RXSTBC(x) (x & IEEE80211_HT_CAP_RX_STBC)
-#define MWIFIEX_RX_STBC1       0x0100
-#define MWIFIEX_RX_STBC12      0x0200
-#define MWIFIEX_RX_STBC123     0x0300
-
-/* dev_cap bitmap
- * BIT
- * 0-16                reserved
- * 17          IEEE80211_HT_CAP_SUP_WIDTH_20_40
- * 18-22       reserved
- * 23          IEEE80211_HT_CAP_SGI_20
- * 24          IEEE80211_HT_CAP_SGI_40
- * 25          IEEE80211_HT_CAP_TX_STBC
- * 26          IEEE80211_HT_CAP_RX_STBC
- * 27-28       reserved
- * 29          IEEE80211_HT_CAP_GRN_FLD
- * 30-31       reserved
- */
-#define ISSUPP_CHANWIDTH40(Dot11nDevCap) (Dot11nDevCap & BIT(17))
-#define ISSUPP_SHORTGI20(Dot11nDevCap) (Dot11nDevCap & BIT(23))
-#define ISSUPP_SHORTGI40(Dot11nDevCap) (Dot11nDevCap & BIT(24))
-#define ISSUPP_TXSTBC(Dot11nDevCap) (Dot11nDevCap & BIT(25))
-#define ISSUPP_RXSTBC(Dot11nDevCap) (Dot11nDevCap & BIT(26))
-#define ISSUPP_GREENFIELD(Dot11nDevCap) (Dot11nDevCap & BIT(29))
-#define ISENABLED_40MHZ_INTOLERANT(Dot11nDevCap) (Dot11nDevCap & BIT(8))
-#define ISSUPP_RXLDPC(Dot11nDevCap) (Dot11nDevCap & BIT(22))
-#define ISSUPP_BEAMFORMING(Dot11nDevCap) (Dot11nDevCap & BIT(30))
-#define ISALLOWED_CHANWIDTH40(ht_param) (ht_param & BIT(2))
-#define GETSUPP_TXBASTREAMS(Dot11nDevCap) ((Dot11nDevCap >> 18) & 0xF)
-
-/* httxcfg bitmap
- * 0           reserved
- * 1           20/40 Mhz enable(1)/disable(0)
- * 2-3         reserved
- * 4           green field enable(1)/disable(0)
- * 5           short GI in 20 Mhz enable(1)/disable(0)
- * 6           short GI in 40 Mhz enable(1)/disable(0)
- * 7-15                reserved
- */
-#define MWIFIEX_FW_DEF_HTTXCFG (BIT(1) | BIT(4) | BIT(5) | BIT(6))
-
-/* 11AC Tx and Rx MCS map for 1x1 mode:
- * IEEE80211_VHT_MCS_SUPPORT_0_9 for stream 1
- * IEEE80211_VHT_MCS_NOT_SUPPORTED for remaining 7 streams
- */
-#define MWIFIEX_11AC_MCS_MAP_1X1       0xfffefffe
-
-/* 11AC Tx and Rx MCS map for 2x2 mode:
- * IEEE80211_VHT_MCS_SUPPORT_0_9 for stream 1 and 2
- * IEEE80211_VHT_MCS_NOT_SUPPORTED for remaining 6 streams
- */
-#define MWIFIEX_11AC_MCS_MAP_2X2       0xfffafffa
-
-#define GET_RXMCSSUPP(DevMCSSupported) (DevMCSSupported & 0x0f)
-#define SETHT_MCS32(x) (x[4] |= 1)
-#define HT_STREAM_1X1  0x11
-#define HT_STREAM_2X2  0x22
-
-#define SET_SECONDARYCHAN(RadioType, SECCHAN) (RadioType |= (SECCHAN << 4))
-
-#define LLC_SNAP_LEN    8
-
-/* HW_SPEC fw_cap_info */
-
-#define ISSUPP_11ACENABLED(fw_cap_info) (fw_cap_info & BIT(13))
-
-#define GET_VHTCAP_CHWDSET(vht_cap_info)    ((vht_cap_info >> 2) & 0x3)
-#define GET_VHTNSSMCS(mcs_mapset, nss) ((mcs_mapset >> (2 * (nss - 1))) & 0x3)
-#define SET_VHTNSSMCS(mcs_mapset, nss, value) (mcs_mapset |= (value & 0x3) << \
-                                             (2 * (nss - 1)))
-#define GET_DEVTXMCSMAP(dev_mcs_map)      (dev_mcs_map >> 16)
-#define GET_DEVRXMCSMAP(dev_mcs_map)      (dev_mcs_map & 0xFFFF)
-
-/* Clear SU Beanformer, MU beanformer, MU beanformee and
- * sounding dimensions bits
- */
-#define MWIFIEX_DEF_11AC_CAP_BF_RESET_MASK \
-                       (IEEE80211_VHT_CAP_SU_BEAMFORMER_CAPABLE | \
-                        IEEE80211_VHT_CAP_MU_BEAMFORMER_CAPABLE | \
-                        IEEE80211_VHT_CAP_MU_BEAMFORMEE_CAPABLE | \
-                        IEEE80211_VHT_CAP_SOUNDING_DIMENSIONS_MASK)
-
-#define MOD_CLASS_HR_DSSS       0x03
-#define MOD_CLASS_OFDM          0x07
-#define MOD_CLASS_HT            0x08
-#define HT_BW_20    0
-#define HT_BW_40    1
-
-#define DFS_CHAN_MOVE_TIME      10000
-
-#define HostCmd_CMD_GET_HW_SPEC                       0x0003
-#define HostCmd_CMD_802_11_SCAN                       0x0006
-#define HostCmd_CMD_802_11_GET_LOG                    0x000b
-#define HostCmd_CMD_MAC_MULTICAST_ADR                 0x0010
-#define HostCmd_CMD_802_11_EEPROM_ACCESS              0x0059
-#define HostCmd_CMD_802_11_ASSOCIATE                  0x0012
-#define HostCmd_CMD_802_11_SNMP_MIB                   0x0016
-#define HostCmd_CMD_MAC_REG_ACCESS                    0x0019
-#define HostCmd_CMD_BBP_REG_ACCESS                    0x001a
-#define HostCmd_CMD_RF_REG_ACCESS                     0x001b
-#define HostCmd_CMD_PMIC_REG_ACCESS                   0x00ad
-#define HostCmd_CMD_RF_TX_PWR                         0x001e
-#define HostCmd_CMD_RF_ANTENNA                        0x0020
-#define HostCmd_CMD_802_11_DEAUTHENTICATE             0x0024
-#define HostCmd_CMD_MAC_CONTROL                       0x0028
-#define HostCmd_CMD_802_11_AD_HOC_START               0x002b
-#define HostCmd_CMD_802_11_AD_HOC_JOIN                0x002c
-#define HostCmd_CMD_802_11_AD_HOC_STOP                0x0040
-#define HostCmd_CMD_802_11_MAC_ADDRESS                0x004D
-#define HostCmd_CMD_802_11D_DOMAIN_INFO               0x005b
-#define HostCmd_CMD_802_11_KEY_MATERIAL               0x005e
-#define HostCmd_CMD_802_11_BG_SCAN_QUERY              0x006c
-#define HostCmd_CMD_WMM_GET_STATUS                    0x0071
-#define HostCmd_CMD_802_11_SUBSCRIBE_EVENT            0x0075
-#define HostCmd_CMD_802_11_TX_RATE_QUERY              0x007f
-#define HostCmd_CMD_802_11_IBSS_COALESCING_STATUS     0x0083
-#define HostCmd_CMD_MEM_ACCESS                        0x0086
-#define HostCmd_CMD_CFG_DATA                          0x008f
-#define HostCmd_CMD_VERSION_EXT                       0x0097
-#define HostCmd_CMD_MEF_CFG                           0x009a
-#define HostCmd_CMD_RSSI_INFO                         0x00a4
-#define HostCmd_CMD_FUNC_INIT                         0x00a9
-#define HostCmd_CMD_FUNC_SHUTDOWN                     0x00aa
-#define HOST_CMD_APCMD_SYS_RESET                      0x00af
-#define HostCmd_CMD_UAP_SYS_CONFIG                    0x00b0
-#define HostCmd_CMD_UAP_BSS_START                     0x00b1
-#define HostCmd_CMD_UAP_BSS_STOP                      0x00b2
-#define HOST_CMD_APCMD_STA_LIST                       0x00b3
-#define HostCmd_CMD_UAP_STA_DEAUTH                    0x00b5
-#define HostCmd_CMD_11N_CFG                           0x00cd
-#define HostCmd_CMD_11N_ADDBA_REQ                     0x00ce
-#define HostCmd_CMD_11N_ADDBA_RSP                     0x00cf
-#define HostCmd_CMD_11N_DELBA                         0x00d0
-#define HostCmd_CMD_RECONFIGURE_TX_BUFF               0x00d9
-#define HostCmd_CMD_CHAN_REPORT_REQUEST               0x00dd
-#define HostCmd_CMD_AMSDU_AGGR_CTRL                   0x00df
-#define HostCmd_CMD_TXPWR_CFG                         0x00d1
-#define HostCmd_CMD_TX_RATE_CFG                       0x00d6
-#define HostCmd_CMD_ROBUST_COEX                       0x00e0
-#define HostCmd_CMD_802_11_PS_MODE_ENH                0x00e4
-#define HostCmd_CMD_802_11_HS_CFG_ENH                 0x00e5
-#define HostCmd_CMD_P2P_MODE_CFG                      0x00eb
-#define HostCmd_CMD_CAU_REG_ACCESS                    0x00ed
-#define HostCmd_CMD_SET_BSS_MODE                      0x00f7
-#define HostCmd_CMD_PCIE_DESC_DETAILS                 0x00fa
-#define HostCmd_CMD_802_11_SCAN_EXT                   0x0107
-#define HostCmd_CMD_COALESCE_CFG                      0x010a
-#define HostCmd_CMD_MGMT_FRAME_REG                    0x010c
-#define HostCmd_CMD_REMAIN_ON_CHAN                    0x010d
-#define HostCmd_CMD_11AC_CFG                         0x0112
-#define HostCmd_CMD_TDLS_CONFIG                       0x0100
-#define HostCmd_CMD_MC_POLICY                         0x0121
-#define HostCmd_CMD_TDLS_OPER                         0x0122
-#define HostCmd_CMD_SDIO_SP_RX_AGGR_CFG               0x0223
-
-#define PROTOCOL_NO_SECURITY        0x01
-#define PROTOCOL_STATIC_WEP         0x02
-#define PROTOCOL_WPA                0x08
-#define PROTOCOL_WPA2               0x20
-#define PROTOCOL_WPA2_MIXED         0x28
-#define PROTOCOL_EAP                0x40
-#define KEY_MGMT_NONE               0x04
-#define KEY_MGMT_PSK                0x02
-#define KEY_MGMT_EAP                0x01
-#define CIPHER_TKIP                 0x04
-#define CIPHER_AES_CCMP             0x08
-#define VALID_CIPHER_BITMAP         0x0c
-
-enum ENH_PS_MODES {
-       EN_PS = 1,
-       DIS_PS = 2,
-       EN_AUTO_DS = 3,
-       DIS_AUTO_DS = 4,
-       SLEEP_CONFIRM = 5,
-       GET_PS = 0,
-       EN_AUTO_PS = 0xff,
-       DIS_AUTO_PS = 0xfe,
-};
-
-enum P2P_MODES {
-       P2P_MODE_DISABLE = 0,
-       P2P_MODE_DEVICE = 1,
-       P2P_MODE_GO = 2,
-       P2P_MODE_CLIENT = 3,
-};
-
-#define HostCmd_RET_BIT                       0x8000
-#define HostCmd_ACT_GEN_GET                   0x0000
-#define HostCmd_ACT_GEN_SET                   0x0001
-#define HostCmd_ACT_GEN_REMOVE                0x0004
-#define HostCmd_ACT_BITWISE_SET               0x0002
-#define HostCmd_ACT_BITWISE_CLR               0x0003
-#define HostCmd_RESULT_OK                     0x0000
-
-#define HostCmd_ACT_MAC_RX_ON                 0x0001
-#define HostCmd_ACT_MAC_TX_ON                 0x0002
-#define HostCmd_ACT_MAC_WEP_ENABLE            0x0008
-#define HostCmd_ACT_MAC_ETHERNETII_ENABLE     0x0010
-#define HostCmd_ACT_MAC_PROMISCUOUS_ENABLE    0x0080
-#define HostCmd_ACT_MAC_ALL_MULTICAST_ENABLE  0x0100
-#define HostCmd_ACT_MAC_ADHOC_G_PROTECTION_ON     0x2000
-
-#define HostCmd_BSS_MODE_IBSS               0x0002
-#define HostCmd_BSS_MODE_ANY                0x0003
-
-#define HostCmd_SCAN_RADIO_TYPE_BG          0
-#define HostCmd_SCAN_RADIO_TYPE_A           1
-
-#define HS_CFG_CANCEL                  0xffffffff
-#define HS_CFG_COND_DEF                        0x00000000
-#define HS_CFG_GPIO_DEF                        0xff
-#define HS_CFG_GAP_DEF                 0xff
-#define HS_CFG_COND_BROADCAST_DATA     0x00000001
-#define HS_CFG_COND_UNICAST_DATA       0x00000002
-#define HS_CFG_COND_MAC_EVENT          0x00000004
-#define HS_CFG_COND_MULTICAST_DATA     0x00000008
-
-#define CONNECT_ERR_AUTH_ERR_STA_FAILURE       0xFFFB
-#define CONNECT_ERR_ASSOC_ERR_TIMEOUT          0xFFFC
-#define CONNECT_ERR_ASSOC_ERR_AUTH_REFUSED     0xFFFD
-#define CONNECT_ERR_AUTH_MSG_UNHANDLED         0xFFFE
-#define CONNECT_ERR_STA_FAILURE                        0xFFFF
-
-
-#define CMD_F_HOSTCMD           (1 << 0)
-
-#define HostCmd_CMD_ID_MASK             0x0fff
-
-#define HostCmd_SEQ_NUM_MASK            0x00ff
-
-#define HostCmd_BSS_NUM_MASK            0x0f00
-
-#define HostCmd_BSS_TYPE_MASK           0xf000
-
-#define HostCmd_ACT_SET_RX              0x0001
-#define HostCmd_ACT_SET_TX              0x0002
-#define HostCmd_ACT_SET_BOTH            0x0003
-
-#define RF_ANTENNA_AUTO                 0xFFFF
-
-#define HostCmd_SET_SEQ_NO_BSS_INFO(seq, num, type) {   \
-       (((seq) & 0x00ff) |                             \
-        (((num) & 0x000f) << 8)) |                     \
-       (((type) & 0x000f) << 12);                  }
-
-#define HostCmd_GET_SEQ_NO(seq)       \
-       ((seq) & HostCmd_SEQ_NUM_MASK)
-
-#define HostCmd_GET_BSS_NO(seq)         \
-       (((seq) & HostCmd_BSS_NUM_MASK) >> 8)
-
-#define HostCmd_GET_BSS_TYPE(seq)       \
-       (((seq) & HostCmd_BSS_TYPE_MASK) >> 12)
-
-#define EVENT_DUMMY_HOST_WAKEUP_SIGNAL  0x00000001
-#define EVENT_LINK_LOST                 0x00000003
-#define EVENT_LINK_SENSED               0x00000004
-#define EVENT_MIB_CHANGED               0x00000006
-#define EVENT_INIT_DONE                 0x00000007
-#define EVENT_DEAUTHENTICATED           0x00000008
-#define EVENT_DISASSOCIATED             0x00000009
-#define EVENT_PS_AWAKE                  0x0000000a
-#define EVENT_PS_SLEEP                  0x0000000b
-#define EVENT_MIC_ERR_MULTICAST         0x0000000d
-#define EVENT_MIC_ERR_UNICAST           0x0000000e
-#define EVENT_DEEP_SLEEP_AWAKE          0x00000010
-#define EVENT_ADHOC_BCN_LOST            0x00000011
-
-#define EVENT_WMM_STATUS_CHANGE         0x00000017
-#define EVENT_BG_SCAN_REPORT            0x00000018
-#define EVENT_RSSI_LOW                  0x00000019
-#define EVENT_SNR_LOW                   0x0000001a
-#define EVENT_MAX_FAIL                  0x0000001b
-#define EVENT_RSSI_HIGH                 0x0000001c
-#define EVENT_SNR_HIGH                  0x0000001d
-#define EVENT_IBSS_COALESCED            0x0000001e
-#define EVENT_DATA_RSSI_LOW             0x00000024
-#define EVENT_DATA_SNR_LOW              0x00000025
-#define EVENT_DATA_RSSI_HIGH            0x00000026
-#define EVENT_DATA_SNR_HIGH             0x00000027
-#define EVENT_LINK_QUALITY              0x00000028
-#define EVENT_PORT_RELEASE              0x0000002b
-#define EVENT_UAP_STA_DEAUTH            0x0000002c
-#define EVENT_UAP_STA_ASSOC             0x0000002d
-#define EVENT_UAP_BSS_START             0x0000002e
-#define EVENT_PRE_BEACON_LOST           0x00000031
-#define EVENT_ADDBA                     0x00000033
-#define EVENT_DELBA                     0x00000034
-#define EVENT_BA_STREAM_TIEMOUT         0x00000037
-#define EVENT_AMSDU_AGGR_CTRL           0x00000042
-#define EVENT_UAP_BSS_IDLE              0x00000043
-#define EVENT_UAP_BSS_ACTIVE            0x00000044
-#define EVENT_WEP_ICV_ERR               0x00000046
-#define EVENT_HS_ACT_REQ                0x00000047
-#define EVENT_BW_CHANGE                 0x00000048
-#define EVENT_UAP_MIC_COUNTERMEASURES   0x0000004c
-#define EVENT_HOSTWAKE_STAIE           0x0000004d
-#define EVENT_CHANNEL_SWITCH_ANN        0x00000050
-#define EVENT_TDLS_GENERIC_EVENT        0x00000052
-#define EVENT_RADAR_DETECTED           0x00000053
-#define EVENT_CHANNEL_REPORT_RDY        0x00000054
-#define EVENT_TX_DATA_PAUSE             0x00000055
-#define EVENT_EXT_SCAN_REPORT           0x00000058
-#define EVENT_REMAIN_ON_CHAN_EXPIRED    0x0000005f
-#define EVENT_MULTI_CHAN_INFO           0x0000006a
-#define EVENT_TX_STATUS_REPORT         0x00000074
-#define EVENT_BT_COEX_WLAN_PARA_CHANGE 0X00000076
-
-#define EVENT_ID_MASK                   0xffff
-#define BSS_NUM_MASK                    0xf
-
-#define EVENT_GET_BSS_NUM(event_cause)          \
-       (((event_cause) >> 16) & BSS_NUM_MASK)
-
-#define EVENT_GET_BSS_TYPE(event_cause)         \
-       (((event_cause) >> 24) & 0x00ff)
-
-#define MWIFIEX_MAX_PATTERN_LEN                20
-#define MWIFIEX_MAX_OFFSET_LEN         100
-#define STACK_NBYTES                   100
-#define TYPE_DNUM                      1
-#define TYPE_BYTESEQ                   2
-#define MAX_OPERAND                    0x40
-#define TYPE_EQ                                (MAX_OPERAND+1)
-#define TYPE_EQ_DNUM                   (MAX_OPERAND+2)
-#define TYPE_EQ_BIT                    (MAX_OPERAND+3)
-#define TYPE_AND                       (MAX_OPERAND+4)
-#define TYPE_OR                                (MAX_OPERAND+5)
-#define MEF_MODE_HOST_SLEEP                    1
-#define MEF_ACTION_ALLOW_AND_WAKEUP_HOST       3
-#define MEF_ACTION_AUTO_ARP                    0x10
-#define MWIFIEX_CRITERIA_BROADCAST     BIT(0)
-#define MWIFIEX_CRITERIA_UNICAST       BIT(1)
-#define MWIFIEX_CRITERIA_MULTICAST     BIT(3)
-#define MWIFIEX_MAX_SUPPORTED_IPADDR              4
-
-#define ACT_TDLS_DELETE            0x00
-#define ACT_TDLS_CREATE            0x01
-#define ACT_TDLS_CONFIG            0x02
-
-#define TDLS_EVENT_LINK_TEAR_DOWN      3
-#define TDLS_EVENT_CHAN_SWITCH_RESULT  7
-#define TDLS_EVENT_START_CHAN_SWITCH   8
-#define TDLS_EVENT_CHAN_SWITCH_STOPPED 9
-
-#define TDLS_BASE_CHANNEL             0
-#define TDLS_OFF_CHANNEL              1
-
-#define ACT_TDLS_CS_ENABLE_CONFIG 0x00
-#define ACT_TDLS_CS_INIT         0x06
-#define ACT_TDLS_CS_STOP         0x07
-#define ACT_TDLS_CS_PARAMS       0x08
-
-#define MWIFIEX_DEF_CS_UNIT_TIME       2
-#define MWIFIEX_DEF_CS_THR_OTHERLINK   10
-#define MWIFIEX_DEF_THR_DIRECTLINK     0
-#define MWIFIEX_DEF_CS_TIME            10
-#define MWIFIEX_DEF_CS_TIMEOUT         16
-#define MWIFIEX_DEF_CS_REG_CLASS       12
-#define MWIFIEX_DEF_CS_PERIODICITY     1
-
-#define MWIFIEX_FW_V15            15
-
-#define MWIFIEX_MASTER_RADAR_DET_MASK BIT(1)
-
-struct mwifiex_ie_types_header {
-       __le16 type;
-       __le16 len;
-} __packed;
-
-struct mwifiex_ie_types_data {
-       struct mwifiex_ie_types_header header;
-       u8 data[1];
-} __packed;
-
-#define MWIFIEX_TxPD_POWER_MGMT_NULL_PACKET 0x01
-#define MWIFIEX_TxPD_POWER_MGMT_LAST_PACKET 0x08
-#define MWIFIEX_TXPD_FLAGS_TDLS_PACKET      0x10
-#define MWIFIEX_RXPD_FLAGS_TDLS_PACKET      0x01
-#define MWIFIEX_TXPD_FLAGS_REQ_TX_STATUS    0x20
-
-struct txpd {
-       u8 bss_type;
-       u8 bss_num;
-       __le16 tx_pkt_length;
-       __le16 tx_pkt_offset;
-       __le16 tx_pkt_type;
-       __le32 tx_control;
-       u8 priority;
-       u8 flags;
-       u8 pkt_delay_2ms;
-       u8 reserved1[2];
-       u8 tx_token_id;
-       u8 reserved[2];
-} __packed;
-
-struct rxpd {
-       u8 bss_type;
-       u8 bss_num;
-       __le16 rx_pkt_length;
-       __le16 rx_pkt_offset;
-       __le16 rx_pkt_type;
-       __le16 seq_num;
-       u8 priority;
-       u8 rx_rate;
-       s8 snr;
-       s8 nf;
-
-       /* For: Non-802.11 AC cards
-        *
-        * Ht Info [Bit 0] RxRate format: LG=0, HT=1
-        * [Bit 1]  HT Bandwidth: BW20 = 0, BW40 = 1
-        * [Bit 2]  HT Guard Interval: LGI = 0, SGI = 1
-        *
-        * For: 802.11 AC cards
-        * [Bit 1] [Bit 0] RxRate format: legacy rate = 00 HT = 01 VHT = 10
-        * [Bit 3] [Bit 2] HT/VHT Bandwidth BW20 = 00 BW40 = 01
-        *                                              BW80 = 10  BW160 = 11
-        * [Bit 4] HT/VHT Guard interval LGI = 0 SGI = 1
-        * [Bit 5] STBC support Enabled = 1
-        * [Bit 6] LDPC support Enabled = 1
-        * [Bit 7] Reserved
-        */
-       u8 ht_info;
-       u8 reserved[3];
-       u8 flags;
-} __packed;
-
-struct uap_txpd {
-       u8 bss_type;
-       u8 bss_num;
-       __le16 tx_pkt_length;
-       __le16 tx_pkt_offset;
-       __le16 tx_pkt_type;
-       __le32 tx_control;
-       u8 priority;
-       u8 flags;
-       u8 pkt_delay_2ms;
-       u8 reserved1[2];
-       u8 tx_token_id;
-       u8 reserved[2];
-};
-
-struct uap_rxpd {
-       u8 bss_type;
-       u8 bss_num;
-       __le16 rx_pkt_length;
-       __le16 rx_pkt_offset;
-       __le16 rx_pkt_type;
-       __le16 seq_num;
-       u8 priority;
-       u8 rx_rate;
-       s8 snr;
-       s8 nf;
-       u8 ht_info;
-       u8 reserved[3];
-       u8 flags;
-};
-
-struct mwifiex_fw_chan_stats {
-       u8 chan_num;
-       u8 bandcfg;
-       u8 flags;
-       s8 noise;
-       __le16 total_bss;
-       __le16 cca_scan_dur;
-       __le16 cca_busy_dur;
-} __packed;
-
-enum mwifiex_chan_scan_mode_bitmasks {
-       MWIFIEX_PASSIVE_SCAN = BIT(0),
-       MWIFIEX_DISABLE_CHAN_FILT = BIT(1),
-       MWIFIEX_HIDDEN_SSID_REPORT = BIT(4),
-};
-
-struct mwifiex_chan_scan_param_set {
-       u8 radio_type;
-       u8 chan_number;
-       u8 chan_scan_mode_bitmap;
-       __le16 min_scan_time;
-       __le16 max_scan_time;
-} __packed;
-
-struct mwifiex_ie_types_chan_list_param_set {
-       struct mwifiex_ie_types_header header;
-       struct mwifiex_chan_scan_param_set chan_scan_param[1];
-} __packed;
-
-struct chan_band_param_set {
-       u8 radio_type;
-       u8 chan_number;
-};
-
-struct mwifiex_ie_types_chan_band_list_param_set {
-       struct mwifiex_ie_types_header header;
-       struct chan_band_param_set chan_band_param[1];
-} __packed;
-
-struct mwifiex_ie_types_rates_param_set {
-       struct mwifiex_ie_types_header header;
-       u8 rates[1];
-} __packed;
-
-struct mwifiex_ie_types_ssid_param_set {
-       struct mwifiex_ie_types_header header;
-       u8 ssid[1];
-} __packed;
-
-struct mwifiex_ie_types_num_probes {
-       struct mwifiex_ie_types_header header;
-       __le16 num_probes;
-} __packed;
-
-struct mwifiex_ie_types_scan_chan_gap {
-       struct mwifiex_ie_types_header header;
-       /* time gap in TUs to be used between two consecutive channels scan */
-       __le16 chan_gap;
-} __packed;
-
-struct mwifiex_ietypes_chanstats {
-       struct mwifiex_ie_types_header header;
-       struct mwifiex_fw_chan_stats chanstats[0];
-} __packed;
-
-struct mwifiex_ie_types_wildcard_ssid_params {
-       struct mwifiex_ie_types_header header;
-       u8 max_ssid_length;
-       u8 ssid[1];
-} __packed;
-
-#define TSF_DATA_SIZE            8
-struct mwifiex_ie_types_tsf_timestamp {
-       struct mwifiex_ie_types_header header;
-       u8 tsf_data[1];
-} __packed;
-
-struct mwifiex_cf_param_set {
-       u8 cfp_cnt;
-       u8 cfp_period;
-       __le16 cfp_max_duration;
-       __le16 cfp_duration_remaining;
-} __packed;
-
-struct mwifiex_ibss_param_set {
-       __le16 atim_window;
-} __packed;
-
-struct mwifiex_ie_types_ss_param_set {
-       struct mwifiex_ie_types_header header;
-       union {
-               struct mwifiex_cf_param_set cf_param_set[1];
-               struct mwifiex_ibss_param_set ibss_param_set[1];
-       } cf_ibss;
-} __packed;
-
-struct mwifiex_fh_param_set {
-       __le16 dwell_time;
-       u8 hop_set;
-       u8 hop_pattern;
-       u8 hop_index;
-} __packed;
-
-struct mwifiex_ds_param_set {
-       u8 current_chan;
-} __packed;
-
-struct mwifiex_ie_types_phy_param_set {
-       struct mwifiex_ie_types_header header;
-       union {
-               struct mwifiex_fh_param_set fh_param_set[1];
-               struct mwifiex_ds_param_set ds_param_set[1];
-       } fh_ds;
-} __packed;
-
-struct mwifiex_ie_types_auth_type {
-       struct mwifiex_ie_types_header header;
-       __le16 auth_type;
-} __packed;
-
-struct mwifiex_ie_types_vendor_param_set {
-       struct mwifiex_ie_types_header header;
-       u8 ie[MWIFIEX_MAX_VSIE_LEN];
-};
-
-#define MWIFIEX_TDLS_IDLE_TIMEOUT_IN_SEC       60
-
-struct mwifiex_ie_types_tdls_idle_timeout {
-       struct mwifiex_ie_types_header header;
-       __le16 value;
-} __packed;
-
-struct mwifiex_ie_types_rsn_param_set {
-       struct mwifiex_ie_types_header header;
-       u8 rsn_ie[1];
-} __packed;
-
-#define KEYPARAMSET_FIXED_LEN 6
-
-struct mwifiex_ie_type_key_param_set {
-       __le16 type;
-       __le16 length;
-       __le16 key_type_id;
-       __le16 key_info;
-       __le16 key_len;
-       u8 key[50];
-} __packed;
-
-#define IGTK_PN_LEN            8
-
-struct mwifiex_cmac_param {
-       u8 ipn[IGTK_PN_LEN];
-       u8 key[WLAN_KEY_LEN_AES_CMAC];
-} __packed;
-
-struct mwifiex_wep_param {
-       __le16 key_len;
-       u8 key[WLAN_KEY_LEN_WEP104];
-} __packed;
-
-struct mwifiex_tkip_param {
-       u8 pn[WPA_PN_SIZE];
-       __le16 key_len;
-       u8 key[WLAN_KEY_LEN_TKIP];
-} __packed;
-
-struct mwifiex_aes_param {
-       u8 pn[WPA_PN_SIZE];
-       __le16 key_len;
-       u8 key[WLAN_KEY_LEN_CCMP];
-} __packed;
-
-struct mwifiex_wapi_param {
-       u8 pn[PN_LEN];
-       __le16 key_len;
-       u8 key[WLAN_KEY_LEN_SMS4];
-} __packed;
-
-struct mwifiex_cmac_aes_param {
-       u8 ipn[IGTK_PN_LEN];
-       __le16 key_len;
-       u8 key[WLAN_KEY_LEN_AES_CMAC];
-} __packed;
-
-struct mwifiex_ie_type_key_param_set_v2 {
-       __le16 type;
-       __le16 len;
-       u8 mac_addr[ETH_ALEN];
-       u8 key_idx;
-       u8 key_type;
-       __le16 key_info;
-       union {
-               struct mwifiex_wep_param wep;
-               struct mwifiex_tkip_param tkip;
-               struct mwifiex_aes_param aes;
-               struct mwifiex_wapi_param wapi;
-               struct mwifiex_cmac_aes_param cmac_aes;
-       } key_params;
-} __packed;
-
-struct host_cmd_ds_802_11_key_material_v2 {
-       __le16 action;
-       struct mwifiex_ie_type_key_param_set_v2 key_param_set;
-} __packed;
-
-struct host_cmd_ds_802_11_key_material {
-       __le16 action;
-       struct mwifiex_ie_type_key_param_set key_param_set;
-} __packed;
-
-struct host_cmd_ds_gen {
-       __le16 command;
-       __le16 size;
-       __le16 seq_num;
-       __le16 result;
-};
-
-#define S_DS_GEN        sizeof(struct host_cmd_ds_gen)
-
-enum sleep_resp_ctrl {
-       RESP_NOT_NEEDED = 0,
-       RESP_NEEDED,
-};
-
-struct mwifiex_ps_param {
-       __le16 null_pkt_interval;
-       __le16 multiple_dtims;
-       __le16 bcn_miss_timeout;
-       __le16 local_listen_interval;
-       __le16 adhoc_wake_period;
-       __le16 mode;
-       __le16 delay_to_ps;
-};
-
-#define BITMAP_AUTO_DS         0x01
-#define BITMAP_STA_PS          0x10
-
-struct mwifiex_ie_types_auto_ds_param {
-       struct mwifiex_ie_types_header header;
-       __le16 deep_sleep_timeout;
-} __packed;
-
-struct mwifiex_ie_types_ps_param {
-       struct mwifiex_ie_types_header header;
-       struct mwifiex_ps_param param;
-} __packed;
-
-struct host_cmd_ds_802_11_ps_mode_enh {
-       __le16 action;
-
-       union {
-               struct mwifiex_ps_param opt_ps;
-               __le16 ps_bitmap;
-       } params;
-} __packed;
-
-enum API_VER_ID {
-       KEY_API_VER_ID = 1,
-       FW_API_VER_ID = 2,
-};
-
-struct hw_spec_api_rev {
-       struct mwifiex_ie_types_header header;
-       __le16 api_id;
-       u8 major_ver;
-       u8 minor_ver;
-} __packed;
-
-struct host_cmd_ds_get_hw_spec {
-       __le16 hw_if_version;
-       __le16 version;
-       __le16 reserved;
-       __le16 num_of_mcast_adr;
-       u8 permanent_addr[ETH_ALEN];
-       __le16 region_code;
-       __le16 number_of_antenna;
-       __le32 fw_release_number;
-       __le32 reserved_1;
-       __le32 reserved_2;
-       __le32 reserved_3;
-       __le32 fw_cap_info;
-       __le32 dot_11n_dev_cap;
-       u8 dev_mcs_support;
-       __le16 mp_end_port;     /* SDIO only, reserved for other interfacces */
-       __le16 mgmt_buf_count;  /* mgmt IE buffer count */
-       __le32 reserved_5;
-       __le32 reserved_6;
-       __le32 dot_11ac_dev_cap;
-       __le32 dot_11ac_mcs_support;
-       u8 tlvs[0];
-} __packed;
-
-struct host_cmd_ds_802_11_rssi_info {
-       __le16 action;
-       __le16 ndata;
-       __le16 nbcn;
-       __le16 reserved[9];
-       long long reserved_1;
-};
-
-struct host_cmd_ds_802_11_rssi_info_rsp {
-       __le16 action;
-       __le16 ndata;
-       __le16 nbcn;
-       __le16 data_rssi_last;
-       __le16 data_nf_last;
-       __le16 data_rssi_avg;
-       __le16 data_nf_avg;
-       __le16 bcn_rssi_last;
-       __le16 bcn_nf_last;
-       __le16 bcn_rssi_avg;
-       __le16 bcn_nf_avg;
-       long long tsf_bcn;
-};
-
-struct host_cmd_ds_802_11_mac_address {
-       __le16 action;
-       u8 mac_addr[ETH_ALEN];
-};
-
-struct host_cmd_ds_mac_control {
-       __le16 action;
-       __le16 reserved;
-};
-
-struct host_cmd_ds_mac_multicast_adr {
-       __le16 action;
-       __le16 num_of_adrs;
-       u8 mac_list[MWIFIEX_MAX_MULTICAST_LIST_SIZE][ETH_ALEN];
-} __packed;
-
-struct host_cmd_ds_802_11_deauthenticate {
-       u8 mac_addr[ETH_ALEN];
-       __le16 reason_code;
-} __packed;
-
-struct host_cmd_ds_802_11_associate {
-       u8 peer_sta_addr[ETH_ALEN];
-       __le16 cap_info_bitmap;
-       __le16 listen_interval;
-       __le16 beacon_period;
-       u8 dtim_period;
-} __packed;
-
-struct ieee_types_assoc_rsp {
-       __le16 cap_info_bitmap;
-       __le16 status_code;
-       __le16 a_id;
-       u8 ie_buffer[1];
-} __packed;
-
-struct host_cmd_ds_802_11_associate_rsp {
-       struct ieee_types_assoc_rsp assoc_rsp;
-} __packed;
-
-struct ieee_types_cf_param_set {
-       u8 element_id;
-       u8 len;
-       u8 cfp_cnt;
-       u8 cfp_period;
-       __le16 cfp_max_duration;
-       __le16 cfp_duration_remaining;
-} __packed;
-
-struct ieee_types_ibss_param_set {
-       u8 element_id;
-       u8 len;
-       __le16 atim_window;
-} __packed;
-
-union ieee_types_ss_param_set {
-       struct ieee_types_cf_param_set cf_param_set;
-       struct ieee_types_ibss_param_set ibss_param_set;
-} __packed;
-
-struct ieee_types_fh_param_set {
-       u8 element_id;
-       u8 len;
-       __le16 dwell_time;
-       u8 hop_set;
-       u8 hop_pattern;
-       u8 hop_index;
-} __packed;
-
-struct ieee_types_ds_param_set {
-       u8 element_id;
-       u8 len;
-       u8 current_chan;
-} __packed;
-
-union ieee_types_phy_param_set {
-       struct ieee_types_fh_param_set fh_param_set;
-       struct ieee_types_ds_param_set ds_param_set;
-} __packed;
-
-struct ieee_types_oper_mode_ntf {
-       u8 element_id;
-       u8 len;
-       u8 oper_mode;
-} __packed;
-
-struct host_cmd_ds_802_11_ad_hoc_start {
-       u8 ssid[IEEE80211_MAX_SSID_LEN];
-       u8 bss_mode;
-       __le16 beacon_period;
-       u8 dtim_period;
-       union ieee_types_ss_param_set ss_param_set;
-       union ieee_types_phy_param_set phy_param_set;
-       u16 reserved1;
-       __le16 cap_info_bitmap;
-       u8 data_rate[HOSTCMD_SUPPORTED_RATES];
-} __packed;
-
-struct host_cmd_ds_802_11_ad_hoc_result {
-       u8 pad[3];
-       u8 bssid[ETH_ALEN];
-} __packed;
-
-struct adhoc_bss_desc {
-       u8 bssid[ETH_ALEN];
-       u8 ssid[IEEE80211_MAX_SSID_LEN];
-       u8 bss_mode;
-       __le16 beacon_period;
-       u8 dtim_period;
-       u8 time_stamp[8];
-       u8 local_time[8];
-       union ieee_types_phy_param_set phy_param_set;
-       union ieee_types_ss_param_set ss_param_set;
-       __le16 cap_info_bitmap;
-       u8 data_rates[HOSTCMD_SUPPORTED_RATES];
-
-       /*
-        *  DO NOT ADD ANY FIELDS TO THIS STRUCTURE.
-        *  It is used in the Adhoc join command and will cause a
-        *  binary layout mismatch with the firmware
-        */
-} __packed;
-
-struct host_cmd_ds_802_11_ad_hoc_join {
-       struct adhoc_bss_desc bss_descriptor;
-       u16 reserved1;
-       u16 reserved2;
-} __packed;
-
-struct host_cmd_ds_802_11_get_log {
-       __le32 mcast_tx_frame;
-       __le32 failed;
-       __le32 retry;
-       __le32 multi_retry;
-       __le32 frame_dup;
-       __le32 rts_success;
-       __le32 rts_failure;
-       __le32 ack_failure;
-       __le32 rx_frag;
-       __le32 mcast_rx_frame;
-       __le32 fcs_error;
-       __le32 tx_frame;
-       __le32 reserved;
-       __le32 wep_icv_err_cnt[4];
-       __le32 bcn_rcv_cnt;
-       __le32 bcn_miss_cnt;
-};
-
-/* Enumeration for rate format */
-enum _mwifiex_rate_format {
-       MWIFIEX_RATE_FORMAT_LG = 0,
-       MWIFIEX_RATE_FORMAT_HT,
-       MWIFIEX_RATE_FORMAT_VHT,
-       MWIFIEX_RATE_FORMAT_AUTO = 0xFF,
-};
-
-struct host_cmd_ds_tx_rate_query {
-       u8 tx_rate;
-       /* Tx Rate Info: For 802.11 AC cards
-        *
-        * [Bit 0-1] tx rate formate: LG = 0, HT = 1, VHT = 2
-        * [Bit 2-3] HT/VHT Bandwidth: BW20 = 0, BW40 = 1, BW80 = 2, BW160 = 3
-        * [Bit 4]   HT/VHT Guard Interval: LGI = 0, SGI = 1
-        *
-        * For non-802.11 AC cards
-        * Ht Info [Bit 0] RxRate format: LG=0, HT=1
-        * [Bit 1]  HT Bandwidth: BW20 = 0, BW40 = 1
-        * [Bit 2]  HT Guard Interval: LGI = 0, SGI = 1
-        */
-       u8 ht_info;
-} __packed;
-
-struct mwifiex_tx_pause_tlv {
-       struct mwifiex_ie_types_header header;
-       u8 peermac[ETH_ALEN];
-       u8 tx_pause;
-       u8 pkt_cnt;
-} __packed;
-
-enum Host_Sleep_Action {
-       HS_CONFIGURE = 0x0001,
-       HS_ACTIVATE  = 0x0002,
-};
-
-struct mwifiex_hs_config_param {
-       __le32 conditions;
-       u8 gpio;
-       u8 gap;
-} __packed;
-
-struct hs_activate_param {
-       __le16 resp_ctrl;
-} __packed;
-
-struct host_cmd_ds_802_11_hs_cfg_enh {
-       __le16 action;
-
-       union {
-               struct mwifiex_hs_config_param hs_config;
-               struct hs_activate_param hs_activate;
-       } params;
-} __packed;
-
-enum SNMP_MIB_INDEX {
-       OP_RATE_SET_I = 1,
-       DTIM_PERIOD_I = 3,
-       RTS_THRESH_I = 5,
-       SHORT_RETRY_LIM_I = 6,
-       LONG_RETRY_LIM_I = 7,
-       FRAG_THRESH_I = 8,
-       DOT11D_I = 9,
-       DOT11H_I = 10,
-};
-
-enum mwifiex_assocmd_failurepoint {
-       MWIFIEX_ASSOC_CMD_SUCCESS = 0,
-       MWIFIEX_ASSOC_CMD_FAILURE_ASSOC,
-       MWIFIEX_ASSOC_CMD_FAILURE_AUTH,
-       MWIFIEX_ASSOC_CMD_FAILURE_JOIN
-};
-
-#define MAX_SNMP_BUF_SIZE   128
-
-struct host_cmd_ds_802_11_snmp_mib {
-       __le16 query_type;
-       __le16 oid;
-       __le16 buf_size;
-       u8 value[1];
-} __packed;
-
-struct mwifiex_rate_scope {
-       __le16 type;
-       __le16 length;
-       __le16 hr_dsss_rate_bitmap;
-       __le16 ofdm_rate_bitmap;
-       __le16 ht_mcs_rate_bitmap[8];
-       __le16 vht_mcs_rate_bitmap[8];
-} __packed;
-
-struct mwifiex_rate_drop_pattern {
-       __le16 type;
-       __le16 length;
-       __le32 rate_drop_mode;
-} __packed;
-
-struct host_cmd_ds_tx_rate_cfg {
-       __le16 action;
-       __le16 cfg_index;
-} __packed;
-
-struct mwifiex_power_group {
-       u8 modulation_class;
-       u8 first_rate_code;
-       u8 last_rate_code;
-       s8 power_step;
-       s8 power_min;
-       s8 power_max;
-       u8 ht_bandwidth;
-       u8 reserved;
-} __packed;
-
-struct mwifiex_types_power_group {
-       __le16 type;
-       __le16 length;
-} __packed;
-
-struct host_cmd_ds_txpwr_cfg {
-       __le16 action;
-       __le16 cfg_index;
-       __le32 mode;
-} __packed;
-
-struct host_cmd_ds_rf_tx_pwr {
-       __le16 action;
-       __le16 cur_level;
-       u8 max_power;
-       u8 min_power;
-} __packed;
-
-struct host_cmd_ds_rf_ant_mimo {
-       __le16 action_tx;
-       __le16 tx_ant_mode;
-       __le16 action_rx;
-       __le16 rx_ant_mode;
-};
-
-struct host_cmd_ds_rf_ant_siso {
-       __le16 action;
-       __le16 ant_mode;
-};
-
-struct host_cmd_ds_tdls_oper {
-       __le16 tdls_action;
-       __le16 reason;
-       u8 peer_mac[ETH_ALEN];
-} __packed;
-
-struct mwifiex_tdls_config {
-       __le16 enable;
-};
-
-struct mwifiex_tdls_config_cs_params {
-       u8 unit_time;
-       u8 thr_otherlink;
-       u8 thr_directlink;
-};
-
-struct mwifiex_tdls_init_cs_params {
-       u8 peer_mac[ETH_ALEN];
-       u8 primary_chan;
-       u8 second_chan_offset;
-       u8 band;
-       __le16 switch_time;
-       __le16 switch_timeout;
-       u8 reg_class;
-       u8 periodicity;
-} __packed;
-
-struct mwifiex_tdls_stop_cs_params {
-       u8 peer_mac[ETH_ALEN];
-};
-
-struct host_cmd_ds_tdls_config {
-       __le16 tdls_action;
-       u8 tdls_data[1];
-} __packed;
-
-struct mwifiex_chan_desc {
-       __le16 start_freq;
-       u8 chan_width;
-       u8 chan_num;
-} __packed;
-
-struct host_cmd_ds_chan_rpt_req {
-       struct mwifiex_chan_desc chan_desc;
-       __le32 msec_dwell_time;
-} __packed;
-
-struct host_cmd_ds_chan_rpt_event {
-       __le32 result;
-       __le64 start_tsf;
-       __le32 duration;
-       u8 tlvbuf[0];
-} __packed;
-
-struct host_cmd_sdio_sp_rx_aggr_cfg {
-       u8 action;
-       u8 enable;
-       __le16 block_size;
-} __packed;
-
-struct mwifiex_fixed_bcn_param {
-       __le64 timestamp;
-       __le16 beacon_period;
-       __le16 cap_info_bitmap;
-} __packed;
-
-struct mwifiex_event_scan_result {
-       __le16 event_id;
-       u8 bss_index;
-       u8 bss_type;
-       u8 more_event;
-       u8 reserved[3];
-       __le16 buf_size;
-       u8 num_of_set;
-} __packed;
-
-struct tx_status_event {
-       u8 packet_type;
-       u8 tx_token_id;
-       u8 status;
-} __packed;
-
-#define MWIFIEX_USER_SCAN_CHAN_MAX             50
-
-#define MWIFIEX_MAX_SSID_LIST_LENGTH         10
-
-struct mwifiex_scan_cmd_config {
-       /*
-        *  BSS mode to be sent in the firmware command
-        */
-       u8 bss_mode;
-
-       /* Specific BSSID used to filter scan results in the firmware */
-       u8 specific_bssid[ETH_ALEN];
-
-       /* Length of TLVs sent in command starting at tlvBuffer */
-       u32 tlv_buf_len;
-
-       /*
-        *  SSID TLV(s) and ChanList TLVs to be sent in the firmware command
-        *
-        *  TLV_TYPE_CHANLIST, mwifiex_ie_types_chan_list_param_set
-        *  WLAN_EID_SSID, mwifiex_ie_types_ssid_param_set
-        */
-       u8 tlv_buf[1];  /* SSID TLV(s) and ChanList TLVs are stored
-                                  here */
-} __packed;
-
-struct mwifiex_user_scan_chan {
-       u8 chan_number;
-       u8 radio_type;
-       u8 scan_type;
-       u8 reserved;
-       u32 scan_time;
-} __packed;
-
-struct mwifiex_user_scan_cfg {
-       /*
-        *  BSS mode to be sent in the firmware command
-        */
-       u8 bss_mode;
-       /* Configure the number of probe requests for active chan scans */
-       u8 num_probes;
-       u8 reserved;
-       /* BSSID filter sent in the firmware command to limit the results */
-       u8 specific_bssid[ETH_ALEN];
-       /* SSID filter list used in the firmware to limit the scan results */
-       struct cfg80211_ssid *ssid_list;
-       u8 num_ssids;
-       /* Variable number (fixed maximum) of channels to scan up */
-       struct mwifiex_user_scan_chan chan_list[MWIFIEX_USER_SCAN_CHAN_MAX];
-       u16 scan_chan_gap;
-} __packed;
-
-struct ie_body {
-       u8 grp_key_oui[4];
-       u8 ptk_cnt[2];
-       u8 ptk_body[4];
-} __packed;
-
-struct host_cmd_ds_802_11_scan {
-       u8 bss_mode;
-       u8 bssid[ETH_ALEN];
-       u8 tlv_buffer[1];
-} __packed;
-
-struct host_cmd_ds_802_11_scan_rsp {
-       __le16 bss_descript_size;
-       u8 number_of_sets;
-       u8 bss_desc_and_tlv_buffer[1];
-} __packed;
-
-struct host_cmd_ds_802_11_scan_ext {
-       u32   reserved;
-       u8    tlv_buffer[1];
-} __packed;
-
-struct mwifiex_ie_types_bss_mode {
-       struct mwifiex_ie_types_header  header;
-       u8 bss_mode;
-} __packed;
-
-struct mwifiex_ie_types_bss_scan_rsp {
-       struct mwifiex_ie_types_header header;
-       u8 bssid[ETH_ALEN];
-       u8 frame_body[1];
-} __packed;
-
-struct mwifiex_ie_types_bss_scan_info {
-       struct mwifiex_ie_types_header header;
-       __le16 rssi;
-       __le16 anpi;
-       u8 cca_busy_fraction;
-       u8 radio_type;
-       u8 channel;
-       u8 reserved;
-       __le64 tsf;
-} __packed;
-
-struct host_cmd_ds_802_11_bg_scan_query {
-       u8 flush;
-} __packed;
-
-struct host_cmd_ds_802_11_bg_scan_query_rsp {
-       __le32 report_condition;
-       struct host_cmd_ds_802_11_scan_rsp scan_resp;
-} __packed;
-
-struct mwifiex_ietypes_domain_param_set {
-       struct mwifiex_ie_types_header header;
-       u8 country_code[IEEE80211_COUNTRY_STRING_LEN];
-       struct ieee80211_country_ie_triplet triplet[1];
-} __packed;
-
-struct host_cmd_ds_802_11d_domain_info {
-       __le16 action;
-       struct mwifiex_ietypes_domain_param_set domain;
-} __packed;
-
-struct host_cmd_ds_802_11d_domain_info_rsp {
-       __le16 action;
-       struct mwifiex_ietypes_domain_param_set domain;
-} __packed;
-
-struct host_cmd_ds_11n_addba_req {
-       u8 add_req_result;
-       u8 peer_mac_addr[ETH_ALEN];
-       u8 dialog_token;
-       __le16 block_ack_param_set;
-       __le16 block_ack_tmo;
-       __le16 ssn;
-} __packed;
-
-struct host_cmd_ds_11n_addba_rsp {
-       u8 add_rsp_result;
-       u8 peer_mac_addr[ETH_ALEN];
-       u8 dialog_token;
-       __le16 status_code;
-       __le16 block_ack_param_set;
-       __le16 block_ack_tmo;
-       __le16 ssn;
-} __packed;
-
-struct host_cmd_ds_11n_delba {
-       u8 del_result;
-       u8 peer_mac_addr[ETH_ALEN];
-       __le16 del_ba_param_set;
-       __le16 reason_code;
-       u8 reserved;
-} __packed;
-
-struct host_cmd_ds_11n_batimeout {
-       u8 tid;
-       u8 peer_mac_addr[ETH_ALEN];
-       u8 origninator;
-} __packed;
-
-struct host_cmd_ds_11n_cfg {
-       __le16 action;
-       __le16 ht_tx_cap;
-       __le16 ht_tx_info;
-       __le16 misc_config;     /* Needed for 802.11AC cards only */
-} __packed;
-
-struct host_cmd_ds_txbuf_cfg {
-       __le16 action;
-       __le16 buff_size;
-       __le16 mp_end_port;     /* SDIO only, reserved for other interfacces */
-       __le16 reserved3;
-} __packed;
-
-struct host_cmd_ds_amsdu_aggr_ctrl {
-       __le16 action;
-       __le16 enable;
-       __le16 curr_buf_size;
-} __packed;
-
-struct host_cmd_ds_sta_deauth {
-       u8 mac[ETH_ALEN];
-       __le16 reason;
-} __packed;
-
-struct mwifiex_ie_types_sta_info {
-       struct mwifiex_ie_types_header header;
-       u8 mac[ETH_ALEN];
-       u8 power_mfg_status;
-       s8 rssi;
-};
-
-struct host_cmd_ds_sta_list {
-       u16 sta_count;
-       u8 tlv[0];
-} __packed;
-
-struct mwifiex_ie_types_pwr_capability {
-       struct mwifiex_ie_types_header header;
-       s8 min_pwr;
-       s8 max_pwr;
-};
-
-struct mwifiex_ie_types_local_pwr_constraint {
-       struct mwifiex_ie_types_header header;
-       u8 chan;
-       u8 constraint;
-};
-
-struct mwifiex_ie_types_wmm_param_set {
-       struct mwifiex_ie_types_header header;
-       u8 wmm_ie[1];
-};
-
-struct mwifiex_ie_types_wmm_queue_status {
-       struct mwifiex_ie_types_header header;
-       u8 queue_index;
-       u8 disabled;
-       __le16 medium_time;
-       u8 flow_required;
-       u8 flow_created;
-       u32 reserved;
-};
-
-struct ieee_types_vendor_header {
-       u8 element_id;
-       u8 len;
-       u8 oui[4];      /* 0~2: oui, 3: oui_type */
-       u8 oui_subtype;
-       u8 version;
-} __packed;
-
-struct ieee_types_wmm_parameter {
-       /*
-        * WMM Parameter IE - Vendor Specific Header:
-        *   element_id  [221/0xdd]
-        *   Len         [24]
-        *   Oui         [00:50:f2]
-        *   OuiType     [2]
-        *   OuiSubType  [1]
-        *   Version     [1]
-        */
-       struct ieee_types_vendor_header vend_hdr;
-       u8 qos_info_bitmap;
-       u8 reserved;
-       struct ieee_types_wmm_ac_parameters ac_params[IEEE80211_NUM_ACS];
-} __packed;
-
-struct ieee_types_wmm_info {
-
-       /*
-        * WMM Info IE - Vendor Specific Header:
-        *   element_id  [221/0xdd]
-        *   Len         [7]
-        *   Oui         [00:50:f2]
-        *   OuiType     [2]
-        *   OuiSubType  [0]
-        *   Version     [1]
-        */
-       struct ieee_types_vendor_header vend_hdr;
-
-       u8 qos_info_bitmap;
-} __packed;
-
-struct host_cmd_ds_wmm_get_status {
-       u8 queue_status_tlv[sizeof(struct mwifiex_ie_types_wmm_queue_status) *
-                             IEEE80211_NUM_ACS];
-       u8 wmm_param_tlv[sizeof(struct ieee_types_wmm_parameter) + 2];
-} __packed;
-
-struct mwifiex_wmm_ac_status {
-       u8 disabled;
-       u8 flow_required;
-       u8 flow_created;
-};
-
-struct mwifiex_ie_types_htcap {
-       struct mwifiex_ie_types_header header;
-       struct ieee80211_ht_cap ht_cap;
-} __packed;
-
-struct mwifiex_ie_types_vhtcap {
-       struct mwifiex_ie_types_header header;
-       struct ieee80211_vht_cap vht_cap;
-} __packed;
-
-struct mwifiex_ie_types_aid {
-       struct mwifiex_ie_types_header header;
-       __le16 aid;
-} __packed;
-
-struct mwifiex_ie_types_oper_mode_ntf {
-       struct mwifiex_ie_types_header header;
-       u8 oper_mode;
-} __packed;
-
-/* VHT Operations IE */
-struct mwifiex_ie_types_vht_oper {
-       struct mwifiex_ie_types_header header;
-       u8 chan_width;
-       u8 chan_center_freq_1;
-       u8 chan_center_freq_2;
-       /* Basic MCS set map, each 2 bits stands for a NSS */
-       __le16 basic_mcs_map;
-} __packed;
-
-struct mwifiex_ie_types_wmmcap {
-       struct mwifiex_ie_types_header header;
-       struct mwifiex_types_wmm_info wmm_info;
-} __packed;
-
-struct mwifiex_ie_types_htinfo {
-       struct mwifiex_ie_types_header header;
-       struct ieee80211_ht_operation ht_oper;
-} __packed;
-
-struct mwifiex_ie_types_2040bssco {
-       struct mwifiex_ie_types_header header;
-       u8 bss_co_2040;
-} __packed;
-
-struct mwifiex_ie_types_extcap {
-       struct mwifiex_ie_types_header header;
-       u8 ext_capab[0];
-} __packed;
-
-struct host_cmd_ds_mem_access {
-       __le16 action;
-       __le16 reserved;
-       __le32 addr;
-       __le32 value;
-};
-
-struct mwifiex_ie_types_qos_info {
-       struct mwifiex_ie_types_header header;
-       u8 qos_info;
-} __packed;
-
-struct host_cmd_ds_mac_reg_access {
-       __le16 action;
-       __le16 offset;
-       __le32 value;
-} __packed;
-
-struct host_cmd_ds_bbp_reg_access {
-       __le16 action;
-       __le16 offset;
-       u8 value;
-       u8 reserved[3];
-} __packed;
-
-struct host_cmd_ds_rf_reg_access {
-       __le16 action;
-       __le16 offset;
-       u8 value;
-       u8 reserved[3];
-} __packed;
-
-struct host_cmd_ds_pmic_reg_access {
-       __le16 action;
-       __le16 offset;
-       u8 value;
-       u8 reserved[3];
-} __packed;
-
-struct host_cmd_ds_802_11_eeprom_access {
-       __le16 action;
-
-       __le16 offset;
-       __le16 byte_count;
-       u8 value;
-} __packed;
-
-struct mwifiex_assoc_event {
-       u8 sta_addr[ETH_ALEN];
-       __le16 type;
-       __le16 len;
-       __le16 frame_control;
-       __le16 cap_info;
-       __le16 listen_interval;
-       u8 data[0];
-} __packed;
-
-struct host_cmd_ds_sys_config {
-       __le16 action;
-       u8 tlv[0];
-};
-
-struct host_cmd_11ac_vht_cfg {
-       __le16 action;
-       u8 band_config;
-       u8 misc_config;
-       __le32 cap_info;
-       __le32 mcs_tx_set;
-       __le32 mcs_rx_set;
-} __packed;
-
-struct host_cmd_tlv_akmp {
-       struct mwifiex_ie_types_header header;
-       __le16 key_mgmt;
-       __le16 key_mgmt_operation;
-} __packed;
-
-struct host_cmd_tlv_pwk_cipher {
-       struct mwifiex_ie_types_header header;
-       __le16 proto;
-       u8 cipher;
-       u8 reserved;
-} __packed;
-
-struct host_cmd_tlv_gwk_cipher {
-       struct mwifiex_ie_types_header header;
-       u8 cipher;
-       u8 reserved;
-} __packed;
-
-struct host_cmd_tlv_passphrase {
-       struct mwifiex_ie_types_header header;
-       u8 passphrase[0];
-} __packed;
-
-struct host_cmd_tlv_wep_key {
-       struct mwifiex_ie_types_header header;
-       u8 key_index;
-       u8 is_default;
-       u8 key[1];
-};
-
-struct host_cmd_tlv_auth_type {
-       struct mwifiex_ie_types_header header;
-       u8 auth_type;
-} __packed;
-
-struct host_cmd_tlv_encrypt_protocol {
-       struct mwifiex_ie_types_header header;
-       __le16 proto;
-} __packed;
-
-struct host_cmd_tlv_ssid {
-       struct mwifiex_ie_types_header header;
-       u8 ssid[0];
-} __packed;
-
-struct host_cmd_tlv_rates {
-       struct mwifiex_ie_types_header header;
-       u8 rates[0];
-} __packed;
-
-struct mwifiex_ie_types_bssid_list {
-       struct mwifiex_ie_types_header header;
-       u8 bssid[ETH_ALEN];
-} __packed;
-
-struct host_cmd_tlv_bcast_ssid {
-       struct mwifiex_ie_types_header header;
-       u8 bcast_ctl;
-} __packed;
-
-struct host_cmd_tlv_beacon_period {
-       struct mwifiex_ie_types_header header;
-       __le16 period;
-} __packed;
-
-struct host_cmd_tlv_dtim_period {
-       struct mwifiex_ie_types_header header;
-       u8 period;
-} __packed;
-
-struct host_cmd_tlv_frag_threshold {
-       struct mwifiex_ie_types_header header;
-       __le16 frag_thr;
-} __packed;
-
-struct host_cmd_tlv_rts_threshold {
-       struct mwifiex_ie_types_header header;
-       __le16 rts_thr;
-} __packed;
-
-struct host_cmd_tlv_retry_limit {
-       struct mwifiex_ie_types_header header;
-       u8 limit;
-} __packed;
-
-struct host_cmd_tlv_mac_addr {
-       struct mwifiex_ie_types_header header;
-       u8 mac_addr[ETH_ALEN];
-} __packed;
-
-struct host_cmd_tlv_channel_band {
-       struct mwifiex_ie_types_header header;
-       u8 band_config;
-       u8 channel;
-} __packed;
-
-struct host_cmd_tlv_ageout_timer {
-       struct mwifiex_ie_types_header header;
-       __le32 sta_ao_timer;
-} __packed;
-
-struct host_cmd_tlv_power_constraint {
-       struct mwifiex_ie_types_header header;
-       u8 constraint;
-} __packed;
-
-struct mwifiex_ie_types_btcoex_scan_time {
-       struct mwifiex_ie_types_header header;
-       u8 coex_scan;
-       u8 reserved;
-       u16 min_scan_time;
-       u16 max_scan_time;
-} __packed;
-
-struct mwifiex_ie_types_btcoex_aggr_win_size {
-       struct mwifiex_ie_types_header header;
-       u8 coex_win_size;
-       u8 tx_win_size;
-       u8 rx_win_size;
-       u8 reserved;
-} __packed;
-
-struct mwifiex_ie_types_robust_coex {
-       struct mwifiex_ie_types_header header;
-       __le32 mode;
-} __packed;
-
-struct host_cmd_ds_version_ext {
-       u8 version_str_sel;
-       char version_str[128];
-} __packed;
-
-struct host_cmd_ds_mgmt_frame_reg {
-       __le16 action;
-       __le32 mask;
-} __packed;
-
-struct host_cmd_ds_p2p_mode_cfg {
-       __le16 action;
-       __le16 mode;
-} __packed;
-
-struct host_cmd_ds_remain_on_chan {
-       __le16 action;
-       u8 status;
-       u8 reserved;
-       u8 band_cfg;
-       u8 channel;
-       __le32 duration;
-} __packed;
-
-struct host_cmd_ds_802_11_ibss_status {
-       __le16 action;
-       __le16 enable;
-       u8 bssid[ETH_ALEN];
-       __le16 beacon_interval;
-       __le16 atim_window;
-       __le16 use_g_rate_protect;
-} __packed;
-
-struct mwifiex_fw_mef_entry {
-       u8 mode;
-       u8 action;
-       __le16 exprsize;
-       u8 expr[0];
-} __packed;
-
-struct host_cmd_ds_mef_cfg {
-       __le32 criteria;
-       __le16 num_entries;
-       struct mwifiex_fw_mef_entry mef_entry[0];
-} __packed;
-
-#define CONNECTION_TYPE_INFRA   0
-#define CONNECTION_TYPE_ADHOC   1
-#define CONNECTION_TYPE_AP      2
-
-struct host_cmd_ds_set_bss_mode {
-       u8 con_type;
-} __packed;
-
-struct host_cmd_ds_pcie_details {
-       /* TX buffer descriptor ring address */
-       u32 txbd_addr_lo;
-       u32 txbd_addr_hi;
-       /* TX buffer descriptor ring count */
-       u32 txbd_count;
-
-       /* RX buffer descriptor ring address */
-       u32 rxbd_addr_lo;
-       u32 rxbd_addr_hi;
-       /* RX buffer descriptor ring count */
-       u32 rxbd_count;
-
-       /* Event buffer descriptor ring address */
-       u32 evtbd_addr_lo;
-       u32 evtbd_addr_hi;
-       /* Event buffer descriptor ring count */
-       u32 evtbd_count;
-
-       /* Sleep cookie buffer physical address */
-       u32 sleep_cookie_addr_lo;
-       u32 sleep_cookie_addr_hi;
-} __packed;
-
-struct mwifiex_ie_types_rssi_threshold {
-       struct mwifiex_ie_types_header header;
-       u8 abs_value;
-       u8 evt_freq;
-} __packed;
-
-#define MWIFIEX_DFS_REC_HDR_LEN                8
-#define MWIFIEX_DFS_REC_HDR_NUM                10
-#define MWIFIEX_BIN_COUNTER_LEN                7
-
-struct mwifiex_radar_det_event {
-       __le32 detect_count;
-       u8 reg_domain;  /*1=fcc, 2=etsi, 3=mic*/
-       u8 det_type;  /*0=none, 1=pw(chirp), 2=pri(radar)*/
-       __le16 pw_chirp_type;
-       u8 pw_chirp_idx;
-       u8 pw_value;
-       u8 pri_radar_type;
-       u8 pri_bincnt;
-       u8 bin_counter[MWIFIEX_BIN_COUNTER_LEN];
-       u8 num_dfs_records;
-       u8 dfs_record_hdr[MWIFIEX_DFS_REC_HDR_NUM][MWIFIEX_DFS_REC_HDR_LEN];
-       __le32 passed;
-} __packed;
-
-struct mwifiex_ie_types_multi_chan_info {
-       struct mwifiex_ie_types_header header;
-       __le16 status;
-       u8 tlv_buffer[0];
-} __packed;
-
-struct mwifiex_ie_types_mc_group_info {
-       struct mwifiex_ie_types_header header;
-       u8 chan_group_id;
-       u8 chan_buf_weight;
-       u8 band_config;
-       u8 chan_num;
-       u32 chan_time;
-       u32 reserved;
-       union {
-               u8 sdio_func_num;
-               u8 usb_ep_num;
-       } hid_num;
-       u8 intf_num;
-       u8 bss_type_numlist[0];
-} __packed;
-
-struct meas_rpt_map {
-       u8 rssi:3;
-       u8 unmeasured:1;
-       u8 radar:1;
-       u8 unidentified_sig:1;
-       u8 ofdm_preamble:1;
-       u8 bss:1;
-} __packed;
-
-struct mwifiex_ie_types_chan_rpt_data {
-       struct mwifiex_ie_types_header header;
-       struct meas_rpt_map map;
-} __packed;
-
-struct host_cmd_ds_802_11_subsc_evt {
-       __le16 action;
-       __le16 events;
-} __packed;
-
-struct chan_switch_result {
-       u8 cur_chan;
-       u8 status;
-       u8 reason;
-} __packed;
-
-struct mwifiex_tdls_generic_event {
-       __le16 type;
-       u8 peer_mac[ETH_ALEN];
-       union {
-               struct chan_switch_result switch_result;
-               u8 cs_stop_reason;
-               __le16 reason_code;
-               __le16 reserved;
-       } u;
-} __packed;
-
-struct mwifiex_ie {
-       __le16 ie_index;
-       __le16 mgmt_subtype_mask;
-       __le16 ie_length;
-       u8 ie_buffer[IEEE_MAX_IE_SIZE];
-} __packed;
-
-#define MAX_MGMT_IE_INDEX      16
-struct mwifiex_ie_list {
-       __le16 type;
-       __le16 len;
-       struct mwifiex_ie ie_list[MAX_MGMT_IE_INDEX];
-} __packed;
-
-struct coalesce_filt_field_param {
-       u8 operation;
-       u8 operand_len;
-       __le16 offset;
-       u8 operand_byte_stream[4];
-};
-
-struct coalesce_receive_filt_rule {
-       struct mwifiex_ie_types_header header;
-       u8 num_of_fields;
-       u8 pkt_type;
-       __le16 max_coalescing_delay;
-       struct coalesce_filt_field_param params[0];
-} __packed;
-
-struct host_cmd_ds_coalesce_cfg {
-       __le16 action;
-       __le16 num_of_rules;
-       struct coalesce_receive_filt_rule rule[0];
-} __packed;
-
-struct host_cmd_ds_multi_chan_policy {
-       __le16 action;
-       __le16 policy;
-} __packed;
-
-struct host_cmd_ds_robust_coex {
-       __le16 action;
-       __le16 reserved;
-} __packed;
-
-struct host_cmd_ds_command {
-       __le16 command;
-       __le16 size;
-       __le16 seq_num;
-       __le16 result;
-       union {
-               struct host_cmd_ds_get_hw_spec hw_spec;
-               struct host_cmd_ds_mac_control mac_ctrl;
-               struct host_cmd_ds_802_11_mac_address mac_addr;
-               struct host_cmd_ds_mac_multicast_adr mc_addr;
-               struct host_cmd_ds_802_11_get_log get_log;
-               struct host_cmd_ds_802_11_rssi_info rssi_info;
-               struct host_cmd_ds_802_11_rssi_info_rsp rssi_info_rsp;
-               struct host_cmd_ds_802_11_snmp_mib smib;
-               struct host_cmd_ds_tx_rate_query tx_rate;
-               struct host_cmd_ds_tx_rate_cfg tx_rate_cfg;
-               struct host_cmd_ds_txpwr_cfg txp_cfg;
-               struct host_cmd_ds_rf_tx_pwr txp;
-               struct host_cmd_ds_rf_ant_mimo ant_mimo;
-               struct host_cmd_ds_rf_ant_siso ant_siso;
-               struct host_cmd_ds_802_11_ps_mode_enh psmode_enh;
-               struct host_cmd_ds_802_11_hs_cfg_enh opt_hs_cfg;
-               struct host_cmd_ds_802_11_scan scan;
-               struct host_cmd_ds_802_11_scan_ext ext_scan;
-               struct host_cmd_ds_802_11_scan_rsp scan_resp;
-               struct host_cmd_ds_802_11_bg_scan_query bg_scan_query;
-               struct host_cmd_ds_802_11_bg_scan_query_rsp bg_scan_query_resp;
-               struct host_cmd_ds_802_11_associate associate;
-               struct host_cmd_ds_802_11_associate_rsp associate_rsp;
-               struct host_cmd_ds_802_11_deauthenticate deauth;
-               struct host_cmd_ds_802_11_ad_hoc_start adhoc_start;
-               struct host_cmd_ds_802_11_ad_hoc_result adhoc_result;
-               struct host_cmd_ds_802_11_ad_hoc_join adhoc_join;
-               struct host_cmd_ds_802_11d_domain_info domain_info;
-               struct host_cmd_ds_802_11d_domain_info_rsp domain_info_resp;
-               struct host_cmd_ds_11n_addba_req add_ba_req;
-               struct host_cmd_ds_11n_addba_rsp add_ba_rsp;
-               struct host_cmd_ds_11n_delba del_ba;
-               struct host_cmd_ds_txbuf_cfg tx_buf;
-               struct host_cmd_ds_amsdu_aggr_ctrl amsdu_aggr_ctrl;
-               struct host_cmd_ds_11n_cfg htcfg;
-               struct host_cmd_ds_wmm_get_status get_wmm_status;
-               struct host_cmd_ds_802_11_key_material key_material;
-               struct host_cmd_ds_802_11_key_material_v2 key_material_v2;
-               struct host_cmd_ds_version_ext verext;
-               struct host_cmd_ds_mgmt_frame_reg reg_mask;
-               struct host_cmd_ds_remain_on_chan roc_cfg;
-               struct host_cmd_ds_p2p_mode_cfg mode_cfg;
-               struct host_cmd_ds_802_11_ibss_status ibss_coalescing;
-               struct host_cmd_ds_mef_cfg mef_cfg;
-               struct host_cmd_ds_mem_access mem;
-               struct host_cmd_ds_mac_reg_access mac_reg;
-               struct host_cmd_ds_bbp_reg_access bbp_reg;
-               struct host_cmd_ds_rf_reg_access rf_reg;
-               struct host_cmd_ds_pmic_reg_access pmic_reg;
-               struct host_cmd_ds_set_bss_mode bss_mode;
-               struct host_cmd_ds_pcie_details pcie_host_spec;
-               struct host_cmd_ds_802_11_eeprom_access eeprom;
-               struct host_cmd_ds_802_11_subsc_evt subsc_evt;
-               struct host_cmd_ds_sys_config uap_sys_config;
-               struct host_cmd_ds_sta_deauth sta_deauth;
-               struct host_cmd_ds_sta_list sta_list;
-               struct host_cmd_11ac_vht_cfg vht_cfg;
-               struct host_cmd_ds_coalesce_cfg coalesce_cfg;
-               struct host_cmd_ds_tdls_config tdls_config;
-               struct host_cmd_ds_tdls_oper tdls_oper;
-               struct host_cmd_ds_chan_rpt_req chan_rpt_req;
-               struct host_cmd_sdio_sp_rx_aggr_cfg sdio_rx_aggr_cfg;
-               struct host_cmd_ds_multi_chan_policy mc_policy;
-               struct host_cmd_ds_robust_coex coex;
-       } params;
-} __packed;
-
-struct mwifiex_opt_sleep_confirm {
-       __le16 command;
-       __le16 size;
-       __le16 seq_num;
-       __le16 result;
-       __le16 action;
-       __le16 resp_ctrl;
-} __packed;
-#endif /* !_MWIFIEX_FW_H_ */
diff --git a/drivers/net/wireless/mwifiex/ie.c b/drivers/net/wireless/mwifiex/ie.c
deleted file mode 100644 (file)
index abf52d2..0000000
+++ /dev/null
@@ -1,488 +0,0 @@
-/*
- * Marvell Wireless LAN device driver: management IE handling- setting and
- * deleting IE.
- *
- * Copyright (C) 2012-2014, Marvell International Ltd.
- *
- * This software file (the "File") is distributed by Marvell International
- * Ltd. under the terms of the GNU General Public License Version 2, June 1991
- * (the "License").  You may use, redistribute and/or modify this File in
- * accordance with the terms and conditions of the License, a copy of which
- * is available by writing to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the
- * worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
- *
- * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
- * ARE EXPRESSLY DISCLAIMED.  The License provides additional details about
- * this warranty disclaimer.
- */
-
-#include "main.h"
-
-/* This function checks if current IE index is used by any on other interface.
- * Return: -1: yes, current IE index is used by someone else.
- *          0: no, current IE index is NOT used by other interface.
- */
-static int
-mwifiex_ie_index_used_by_other_intf(struct mwifiex_private *priv, u16 idx)
-{
-       int i;
-       struct mwifiex_adapter *adapter = priv->adapter;
-       struct mwifiex_ie *ie;
-
-       for (i = 0; i < adapter->priv_num; i++) {
-               if (adapter->priv[i] != priv) {
-                       ie = &adapter->priv[i]->mgmt_ie[idx];
-                       if (ie->mgmt_subtype_mask && ie->ie_length)
-                               return -1;
-               }
-       }
-
-       return 0;
-}
-
-/* Get unused IE index. This index will be used for setting new IE */
-static int
-mwifiex_ie_get_autoidx(struct mwifiex_private *priv, u16 subtype_mask,
-                      struct mwifiex_ie *ie, u16 *index)
-{
-       u16 mask, len, i;
-
-       for (i = 0; i < priv->adapter->max_mgmt_ie_index; i++) {
-               mask = le16_to_cpu(priv->mgmt_ie[i].mgmt_subtype_mask);
-               len = le16_to_cpu(ie->ie_length);
-
-               if (mask == MWIFIEX_AUTO_IDX_MASK)
-                       continue;
-
-               if (mask == subtype_mask) {
-                       if (len > IEEE_MAX_IE_SIZE)
-                               continue;
-
-                       *index = i;
-                       return 0;
-               }
-
-               if (!priv->mgmt_ie[i].ie_length) {
-                       if (mwifiex_ie_index_used_by_other_intf(priv, i))
-                               continue;
-
-                       *index = i;
-                       return 0;
-               }
-       }
-
-       return -1;
-}
-
-/* This function prepares IE data buffer for command to be sent to FW */
-static int
-mwifiex_update_autoindex_ies(struct mwifiex_private *priv,
-                            struct mwifiex_ie_list *ie_list)
-{
-       u16 travel_len, index, mask;
-       s16 input_len, tlv_len;
-       struct mwifiex_ie *ie;
-       u8 *tmp;
-
-       input_len = le16_to_cpu(ie_list->len);
-       travel_len = sizeof(struct mwifiex_ie_types_header);
-
-       ie_list->len = 0;
-
-       while (input_len >= sizeof(struct mwifiex_ie_types_header)) {
-               ie = (struct mwifiex_ie *)(((u8 *)ie_list) + travel_len);
-               tlv_len = le16_to_cpu(ie->ie_length);
-               travel_len += tlv_len + MWIFIEX_IE_HDR_SIZE;
-
-               if (input_len < tlv_len + MWIFIEX_IE_HDR_SIZE)
-                       return -1;
-               index = le16_to_cpu(ie->ie_index);
-               mask = le16_to_cpu(ie->mgmt_subtype_mask);
-
-               if (index == MWIFIEX_AUTO_IDX_MASK) {
-                       /* automatic addition */
-                       if (mwifiex_ie_get_autoidx(priv, mask, ie, &index))
-                               return -1;
-                       if (index == MWIFIEX_AUTO_IDX_MASK)
-                               return -1;
-
-                       tmp = (u8 *)&priv->mgmt_ie[index].ie_buffer;
-                       memcpy(tmp, &ie->ie_buffer, le16_to_cpu(ie->ie_length));
-                       priv->mgmt_ie[index].ie_length = ie->ie_length;
-                       priv->mgmt_ie[index].ie_index = cpu_to_le16(index);
-                       priv->mgmt_ie[index].mgmt_subtype_mask =
-                                                       cpu_to_le16(mask);
-
-                       ie->ie_index = cpu_to_le16(index);
-               } else {
-                       if (mask != MWIFIEX_DELETE_MASK)
-                               return -1;
-                       /*
-                        * Check if this index is being used on any
-                        * other interface.
-                        */
-                       if (mwifiex_ie_index_used_by_other_intf(priv, index))
-                               return -1;
-
-                       ie->ie_length = 0;
-                       memcpy(&priv->mgmt_ie[index], ie,
-                              sizeof(struct mwifiex_ie));
-               }
-
-               le16_add_cpu(&ie_list->len,
-                            le16_to_cpu(priv->mgmt_ie[index].ie_length) +
-                            MWIFIEX_IE_HDR_SIZE);
-               input_len -= tlv_len + MWIFIEX_IE_HDR_SIZE;
-       }
-
-       if (GET_BSS_ROLE(priv) == MWIFIEX_BSS_ROLE_UAP)
-               return mwifiex_send_cmd(priv, HostCmd_CMD_UAP_SYS_CONFIG,
-                                       HostCmd_ACT_GEN_SET,
-                                       UAP_CUSTOM_IE_I, ie_list, false);
-
-       return 0;
-}
-
-/* Copy individual custom IEs for beacon, probe response and assoc response
- * and prepare single structure for IE setting.
- * This function also updates allocated IE indices from driver.
- */
-static int
-mwifiex_update_uap_custom_ie(struct mwifiex_private *priv,
-                            struct mwifiex_ie *beacon_ie, u16 *beacon_idx,
-                            struct mwifiex_ie *pr_ie, u16 *probe_idx,
-                            struct mwifiex_ie *ar_ie, u16 *assoc_idx)
-{
-       struct mwifiex_ie_list *ap_custom_ie;
-       u8 *pos;
-       u16 len;
-       int ret;
-
-       ap_custom_ie = kzalloc(sizeof(*ap_custom_ie), GFP_KERNEL);
-       if (!ap_custom_ie)
-               return -ENOMEM;
-
-       ap_custom_ie->type = cpu_to_le16(TLV_TYPE_MGMT_IE);
-       pos = (u8 *)ap_custom_ie->ie_list;
-
-       if (beacon_ie) {
-               len = sizeof(struct mwifiex_ie) - IEEE_MAX_IE_SIZE +
-                     le16_to_cpu(beacon_ie->ie_length);
-               memcpy(pos, beacon_ie, len);
-               pos += len;
-               le16_add_cpu(&ap_custom_ie->len, len);
-       }
-       if (pr_ie) {
-               len = sizeof(struct mwifiex_ie) - IEEE_MAX_IE_SIZE +
-                     le16_to_cpu(pr_ie->ie_length);
-               memcpy(pos, pr_ie, len);
-               pos += len;
-               le16_add_cpu(&ap_custom_ie->len, len);
-       }
-       if (ar_ie) {
-               len = sizeof(struct mwifiex_ie) - IEEE_MAX_IE_SIZE +
-                     le16_to_cpu(ar_ie->ie_length);
-               memcpy(pos, ar_ie, len);
-               pos += len;
-               le16_add_cpu(&ap_custom_ie->len, len);
-       }
-
-       ret = mwifiex_update_autoindex_ies(priv, ap_custom_ie);
-
-       pos = (u8 *)(&ap_custom_ie->ie_list[0].ie_index);
-       if (beacon_ie && *beacon_idx == MWIFIEX_AUTO_IDX_MASK) {
-               /* save beacon ie index after auto-indexing */
-               *beacon_idx = le16_to_cpu(ap_custom_ie->ie_list[0].ie_index);
-               len = sizeof(*beacon_ie) - IEEE_MAX_IE_SIZE +
-                     le16_to_cpu(beacon_ie->ie_length);
-               pos += len;
-       }
-       if (pr_ie && le16_to_cpu(pr_ie->ie_index) == MWIFIEX_AUTO_IDX_MASK) {
-               /* save probe resp ie index after auto-indexing */
-               *probe_idx = *((u16 *)pos);
-               len = sizeof(*pr_ie) - IEEE_MAX_IE_SIZE +
-                     le16_to_cpu(pr_ie->ie_length);
-               pos += len;
-       }
-       if (ar_ie && le16_to_cpu(ar_ie->ie_index) == MWIFIEX_AUTO_IDX_MASK)
-               /* save assoc resp ie index after auto-indexing */
-               *assoc_idx = *((u16 *)pos);
-
-       kfree(ap_custom_ie);
-       return ret;
-}
-
-/* This function checks if the vendor specified IE is present in passed buffer
- * and copies it to mwifiex_ie structure.
- * Function takes pointer to struct mwifiex_ie pointer as argument.
- * If the vendor specified IE is present then memory is allocated for
- * mwifiex_ie pointer and filled in with IE. Caller should take care of freeing
- * this memory.
- */
-static int mwifiex_update_vs_ie(const u8 *ies, int ies_len,
-                               struct mwifiex_ie **ie_ptr, u16 mask,
-                               unsigned int oui, u8 oui_type)
-{
-       struct ieee_types_header *vs_ie;
-       struct mwifiex_ie *ie = *ie_ptr;
-       const u8 *vendor_ie;
-
-       vendor_ie = cfg80211_find_vendor_ie(oui, oui_type, ies, ies_len);
-       if (vendor_ie) {
-               if (!*ie_ptr) {
-                       *ie_ptr = kzalloc(sizeof(struct mwifiex_ie),
-                                         GFP_KERNEL);
-                       if (!*ie_ptr)
-                               return -ENOMEM;
-                       ie = *ie_ptr;
-               }
-
-               vs_ie = (struct ieee_types_header *)vendor_ie;
-               memcpy(ie->ie_buffer + le16_to_cpu(ie->ie_length),
-                      vs_ie, vs_ie->len + 2);
-               le16_add_cpu(&ie->ie_length, vs_ie->len + 2);
-               ie->mgmt_subtype_mask = cpu_to_le16(mask);
-               ie->ie_index = cpu_to_le16(MWIFIEX_AUTO_IDX_MASK);
-       }
-
-       *ie_ptr = ie;
-       return 0;
-}
-
-/* This function parses beacon IEs, probe response IEs, association response IEs
- * from cfg80211_ap_settings->beacon and sets these IE to FW.
- */
-static int mwifiex_set_mgmt_beacon_data_ies(struct mwifiex_private *priv,
-                                           struct cfg80211_beacon_data *data)
-{
-       struct mwifiex_ie *beacon_ie = NULL, *pr_ie = NULL, *ar_ie = NULL;
-       u16 beacon_idx = MWIFIEX_AUTO_IDX_MASK, pr_idx = MWIFIEX_AUTO_IDX_MASK;
-       u16 ar_idx = MWIFIEX_AUTO_IDX_MASK;
-       int ret = 0;
-
-       if (data->beacon_ies && data->beacon_ies_len) {
-               mwifiex_update_vs_ie(data->beacon_ies, data->beacon_ies_len,
-                                    &beacon_ie, MGMT_MASK_BEACON,
-                                    WLAN_OUI_MICROSOFT,
-                                    WLAN_OUI_TYPE_MICROSOFT_WPS);
-               mwifiex_update_vs_ie(data->beacon_ies, data->beacon_ies_len,
-                                    &beacon_ie, MGMT_MASK_BEACON,
-                                    WLAN_OUI_WFA, WLAN_OUI_TYPE_WFA_P2P);
-       }
-
-       if (data->proberesp_ies && data->proberesp_ies_len) {
-               mwifiex_update_vs_ie(data->proberesp_ies,
-                                    data->proberesp_ies_len, &pr_ie,
-                                    MGMT_MASK_PROBE_RESP, WLAN_OUI_MICROSOFT,
-                                    WLAN_OUI_TYPE_MICROSOFT_WPS);
-               mwifiex_update_vs_ie(data->proberesp_ies,
-                                    data->proberesp_ies_len, &pr_ie,
-                                    MGMT_MASK_PROBE_RESP,
-                                    WLAN_OUI_WFA, WLAN_OUI_TYPE_WFA_P2P);
-       }
-
-       if (data->assocresp_ies && data->assocresp_ies_len) {
-               mwifiex_update_vs_ie(data->assocresp_ies,
-                                    data->assocresp_ies_len, &ar_ie,
-                                    MGMT_MASK_ASSOC_RESP |
-                                    MGMT_MASK_REASSOC_RESP,
-                                    WLAN_OUI_MICROSOFT,
-                                    WLAN_OUI_TYPE_MICROSOFT_WPS);
-               mwifiex_update_vs_ie(data->assocresp_ies,
-                                    data->assocresp_ies_len, &ar_ie,
-                                    MGMT_MASK_ASSOC_RESP |
-                                    MGMT_MASK_REASSOC_RESP, WLAN_OUI_WFA,
-                                    WLAN_OUI_TYPE_WFA_P2P);
-       }
-
-       if (beacon_ie || pr_ie || ar_ie) {
-               ret = mwifiex_update_uap_custom_ie(priv, beacon_ie,
-                                                  &beacon_idx, pr_ie,
-                                                  &pr_idx, ar_ie, &ar_idx);
-               if (ret)
-                       goto done;
-       }
-
-       priv->beacon_idx = beacon_idx;
-       priv->proberesp_idx = pr_idx;
-       priv->assocresp_idx = ar_idx;
-
-done:
-       kfree(beacon_ie);
-       kfree(pr_ie);
-       kfree(ar_ie);
-
-       return ret;
-}
-
-/* This function parses  head and tail IEs, from cfg80211_beacon_data and sets
- * these IE to FW.
- */
-static int mwifiex_uap_parse_tail_ies(struct mwifiex_private *priv,
-                                     struct cfg80211_beacon_data *info)
-{
-       struct mwifiex_ie *gen_ie;
-       struct ieee_types_header *hdr;
-       struct ieee80211_vendor_ie *vendorhdr;
-       u16 gen_idx = MWIFIEX_AUTO_IDX_MASK, ie_len = 0;
-       int left_len, parsed_len = 0;
-
-       if (!info->tail || !info->tail_len)
-               return 0;
-
-       gen_ie = kzalloc(sizeof(*gen_ie), GFP_KERNEL);
-       if (!gen_ie)
-               return -ENOMEM;
-
-       left_len = info->tail_len;
-
-       /* Many IEs are generated in FW by parsing bss configuration.
-        * Let's not add them here; else we may end up duplicating these IEs
-        */
-       while (left_len > sizeof(struct ieee_types_header)) {
-               hdr = (void *)(info->tail + parsed_len);
-               switch (hdr->element_id) {
-               case WLAN_EID_SSID:
-               case WLAN_EID_SUPP_RATES:
-               case WLAN_EID_COUNTRY:
-               case WLAN_EID_PWR_CONSTRAINT:
-               case WLAN_EID_EXT_SUPP_RATES:
-               case WLAN_EID_HT_CAPABILITY:
-               case WLAN_EID_HT_OPERATION:
-               case WLAN_EID_VHT_CAPABILITY:
-               case WLAN_EID_VHT_OPERATION:
-               case WLAN_EID_VENDOR_SPECIFIC:
-                       break;
-               default:
-                       memcpy(gen_ie->ie_buffer + ie_len, hdr,
-                              hdr->len + sizeof(struct ieee_types_header));
-                       ie_len += hdr->len + sizeof(struct ieee_types_header);
-                       break;
-               }
-               left_len -= hdr->len + sizeof(struct ieee_types_header);
-               parsed_len += hdr->len + sizeof(struct ieee_types_header);
-       }
-
-       /* parse only WPA vendor IE from tail, WMM IE is configured by
-        * bss_config command
-        */
-       vendorhdr = (void *)cfg80211_find_vendor_ie(WLAN_OUI_MICROSOFT,
-                                                   WLAN_OUI_TYPE_MICROSOFT_WPA,
-                                                   info->tail, info->tail_len);
-       if (vendorhdr) {
-               memcpy(gen_ie->ie_buffer + ie_len, vendorhdr,
-                      vendorhdr->len + sizeof(struct ieee_types_header));
-               ie_len += vendorhdr->len + sizeof(struct ieee_types_header);
-       }
-
-       if (!ie_len) {
-               kfree(gen_ie);
-               return 0;
-       }
-
-       gen_ie->ie_index = cpu_to_le16(gen_idx);
-       gen_ie->mgmt_subtype_mask = cpu_to_le16(MGMT_MASK_BEACON |
-                                               MGMT_MASK_PROBE_RESP |
-                                               MGMT_MASK_ASSOC_RESP);
-       gen_ie->ie_length = cpu_to_le16(ie_len);
-
-       if (mwifiex_update_uap_custom_ie(priv, gen_ie, &gen_idx, NULL, NULL,
-                                        NULL, NULL)) {
-               kfree(gen_ie);
-               return -1;
-       }
-
-       priv->gen_idx = gen_idx;
-       kfree(gen_ie);
-       return 0;
-}
-
-/* This function parses different IEs-head & tail IEs, beacon IEs,
- * probe response IEs, association response IEs from cfg80211_ap_settings
- * function and sets these IE to FW.
- */
-int mwifiex_set_mgmt_ies(struct mwifiex_private *priv,
-                        struct cfg80211_beacon_data *info)
-{
-       int ret;
-
-       ret = mwifiex_uap_parse_tail_ies(priv, info);
-
-       if (ret)
-               return ret;
-
-       return mwifiex_set_mgmt_beacon_data_ies(priv, info);
-}
-
-/* This function removes management IE set */
-int mwifiex_del_mgmt_ies(struct mwifiex_private *priv)
-{
-       struct mwifiex_ie *beacon_ie = NULL, *pr_ie = NULL;
-       struct mwifiex_ie *ar_ie = NULL, *gen_ie = NULL;
-       int ret = 0;
-
-       if (priv->gen_idx != MWIFIEX_AUTO_IDX_MASK) {
-               gen_ie = kmalloc(sizeof(*gen_ie), GFP_KERNEL);
-               if (!gen_ie)
-                       return -ENOMEM;
-
-               gen_ie->ie_index = cpu_to_le16(priv->gen_idx);
-               gen_ie->mgmt_subtype_mask = cpu_to_le16(MWIFIEX_DELETE_MASK);
-               gen_ie->ie_length = 0;
-               if (mwifiex_update_uap_custom_ie(priv, gen_ie, &priv->gen_idx,
-                                                NULL, &priv->proberesp_idx,
-                                                NULL, &priv->assocresp_idx)) {
-                       ret = -1;
-                       goto done;
-               }
-
-               priv->gen_idx = MWIFIEX_AUTO_IDX_MASK;
-       }
-
-       if (priv->beacon_idx != MWIFIEX_AUTO_IDX_MASK) {
-               beacon_ie = kmalloc(sizeof(struct mwifiex_ie), GFP_KERNEL);
-               if (!beacon_ie) {
-                       ret = -ENOMEM;
-                       goto done;
-               }
-               beacon_ie->ie_index = cpu_to_le16(priv->beacon_idx);
-               beacon_ie->mgmt_subtype_mask = cpu_to_le16(MWIFIEX_DELETE_MASK);
-               beacon_ie->ie_length = 0;
-       }
-       if (priv->proberesp_idx != MWIFIEX_AUTO_IDX_MASK) {
-               pr_ie = kmalloc(sizeof(struct mwifiex_ie), GFP_KERNEL);
-               if (!pr_ie) {
-                       ret = -ENOMEM;
-                       goto done;
-               }
-               pr_ie->ie_index = cpu_to_le16(priv->proberesp_idx);
-               pr_ie->mgmt_subtype_mask = cpu_to_le16(MWIFIEX_DELETE_MASK);
-               pr_ie->ie_length = 0;
-       }
-       if (priv->assocresp_idx != MWIFIEX_AUTO_IDX_MASK) {
-               ar_ie = kmalloc(sizeof(struct mwifiex_ie), GFP_KERNEL);
-               if (!ar_ie) {
-                       ret = -ENOMEM;
-                       goto done;
-               }
-               ar_ie->ie_index = cpu_to_le16(priv->assocresp_idx);
-               ar_ie->mgmt_subtype_mask = cpu_to_le16(MWIFIEX_DELETE_MASK);
-               ar_ie->ie_length = 0;
-       }
-
-       if (beacon_ie || pr_ie || ar_ie)
-               ret = mwifiex_update_uap_custom_ie(priv,
-                                                  beacon_ie, &priv->beacon_idx,
-                                                  pr_ie, &priv->proberesp_idx,
-                                                  ar_ie, &priv->assocresp_idx);
-
-done:
-       kfree(gen_ie);
-       kfree(beacon_ie);
-       kfree(pr_ie);
-       kfree(ar_ie);
-
-       return ret;
-}
diff --git a/drivers/net/wireless/mwifiex/init.c b/drivers/net/wireless/mwifiex/init.c
deleted file mode 100644 (file)
index de74a77..0000000
+++ /dev/null
@@ -1,782 +0,0 @@
-/*
- * Marvell Wireless LAN device driver: HW/FW Initialization
- *
- * Copyright (C) 2011-2014, Marvell International Ltd.
- *
- * This software file (the "File") is distributed by Marvell International
- * Ltd. under the terms of the GNU General Public License Version 2, June 1991
- * (the "License").  You may use, redistribute and/or modify this File in
- * accordance with the terms and conditions of the License, a copy of which
- * is available by writing to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the
- * worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
- *
- * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
- * ARE EXPRESSLY DISCLAIMED.  The License provides additional details about
- * this warranty disclaimer.
- */
-
-#include "decl.h"
-#include "ioctl.h"
-#include "util.h"
-#include "fw.h"
-#include "main.h"
-#include "wmm.h"
-#include "11n.h"
-
-/*
- * This function adds a BSS priority table to the table list.
- *
- * The function allocates a new BSS priority table node and adds it to
- * the end of BSS priority table list, kept in driver memory.
- */
-static int mwifiex_add_bss_prio_tbl(struct mwifiex_private *priv)
-{
-       struct mwifiex_adapter *adapter = priv->adapter;
-       struct mwifiex_bss_prio_node *bss_prio;
-       struct mwifiex_bss_prio_tbl *tbl = adapter->bss_prio_tbl;
-       unsigned long flags;
-
-       bss_prio = kzalloc(sizeof(struct mwifiex_bss_prio_node), GFP_KERNEL);
-       if (!bss_prio)
-               return -ENOMEM;
-
-       bss_prio->priv = priv;
-       INIT_LIST_HEAD(&bss_prio->list);
-
-       spin_lock_irqsave(&tbl[priv->bss_priority].bss_prio_lock, flags);
-       list_add_tail(&bss_prio->list, &tbl[priv->bss_priority].bss_prio_head);
-       spin_unlock_irqrestore(&tbl[priv->bss_priority].bss_prio_lock, flags);
-
-       return 0;
-}
-
-static void wakeup_timer_fn(unsigned long data)
-{
-       struct mwifiex_adapter *adapter = (struct mwifiex_adapter *)data;
-
-       mwifiex_dbg(adapter, ERROR, "Firmware wakeup failed\n");
-       adapter->hw_status = MWIFIEX_HW_STATUS_RESET;
-       mwifiex_cancel_all_pending_cmd(adapter);
-
-       if (adapter->if_ops.card_reset)
-               adapter->if_ops.card_reset(adapter);
-}
-
-/*
- * This function initializes the private structure and sets default
- * values to the members.
- *
- * Additionally, it also initializes all the locks and sets up all the
- * lists.
- */
-int mwifiex_init_priv(struct mwifiex_private *priv)
-{
-       u32 i;
-
-       priv->media_connected = false;
-       eth_broadcast_addr(priv->curr_addr);
-       priv->port_open = false;
-       priv->usb_port = MWIFIEX_USB_EP_DATA;
-       priv->pkt_tx_ctrl = 0;
-       priv->bss_mode = NL80211_IFTYPE_UNSPECIFIED;
-       priv->data_rate = 0;    /* Initially indicate the rate as auto */
-       priv->is_data_rate_auto = true;
-       priv->bcn_avg_factor = DEFAULT_BCN_AVG_FACTOR;
-       priv->data_avg_factor = DEFAULT_DATA_AVG_FACTOR;
-
-       priv->sec_info.wep_enabled = 0;
-       priv->sec_info.authentication_mode = NL80211_AUTHTYPE_OPEN_SYSTEM;
-       priv->sec_info.encryption_mode = 0;
-       for (i = 0; i < ARRAY_SIZE(priv->wep_key); i++)
-               memset(&priv->wep_key[i], 0, sizeof(struct mwifiex_wep_key));
-       priv->wep_key_curr_index = 0;
-       priv->curr_pkt_filter = HostCmd_ACT_MAC_RX_ON | HostCmd_ACT_MAC_TX_ON |
-                               HostCmd_ACT_MAC_ETHERNETII_ENABLE;
-
-       priv->beacon_period = 100; /* beacon interval */ ;
-       priv->attempted_bss_desc = NULL;
-       memset(&priv->curr_bss_params, 0, sizeof(priv->curr_bss_params));
-       priv->listen_interval = MWIFIEX_DEFAULT_LISTEN_INTERVAL;
-
-       memset(&priv->prev_ssid, 0, sizeof(priv->prev_ssid));
-       memset(&priv->prev_bssid, 0, sizeof(priv->prev_bssid));
-       memset(&priv->assoc_rsp_buf, 0, sizeof(priv->assoc_rsp_buf));
-       priv->assoc_rsp_size = 0;
-       priv->adhoc_channel = DEFAULT_AD_HOC_CHANNEL;
-       priv->atim_window = 0;
-       priv->adhoc_state = ADHOC_IDLE;
-       priv->tx_power_level = 0;
-       priv->max_tx_power_level = 0;
-       priv->min_tx_power_level = 0;
-       priv->tx_rate = 0;
-       priv->rxpd_htinfo = 0;
-       priv->rxpd_rate = 0;
-       priv->rate_bitmap = 0;
-       priv->data_rssi_last = 0;
-       priv->data_rssi_avg = 0;
-       priv->data_nf_avg = 0;
-       priv->data_nf_last = 0;
-       priv->bcn_rssi_last = 0;
-       priv->bcn_rssi_avg = 0;
-       priv->bcn_nf_avg = 0;
-       priv->bcn_nf_last = 0;
-       memset(&priv->wpa_ie, 0, sizeof(priv->wpa_ie));
-       memset(&priv->aes_key, 0, sizeof(priv->aes_key));
-       priv->wpa_ie_len = 0;
-       priv->wpa_is_gtk_set = false;
-
-       memset(&priv->assoc_tlv_buf, 0, sizeof(priv->assoc_tlv_buf));
-       priv->assoc_tlv_buf_len = 0;
-       memset(&priv->wps, 0, sizeof(priv->wps));
-       memset(&priv->gen_ie_buf, 0, sizeof(priv->gen_ie_buf));
-       priv->gen_ie_buf_len = 0;
-       memset(priv->vs_ie, 0, sizeof(priv->vs_ie));
-
-       priv->wmm_required = true;
-       priv->wmm_enabled = false;
-       priv->wmm_qosinfo = 0;
-       priv->curr_bcn_buf = NULL;
-       priv->curr_bcn_size = 0;
-       priv->wps_ie = NULL;
-       priv->wps_ie_len = 0;
-       priv->ap_11n_enabled = 0;
-       memset(&priv->roc_cfg, 0, sizeof(priv->roc_cfg));
-
-       priv->scan_block = false;
-
-       priv->csa_chan = 0;
-       priv->csa_expire_time = 0;
-       priv->del_list_idx = 0;
-       priv->hs2_enabled = false;
-       priv->check_tdls_tx = false;
-       memcpy(priv->tos_to_tid_inv, tos_to_tid_inv, MAX_NUM_TID);
-
-       mwifiex_init_11h_params(priv);
-
-       return mwifiex_add_bss_prio_tbl(priv);
-}
-
-/*
- * This function allocates buffers for members of the adapter
- * structure.
- *
- * The memory allocated includes scan table, command buffers, and
- * sleep confirm command buffer. In addition, the queues are
- * also initialized.
- */
-static int mwifiex_allocate_adapter(struct mwifiex_adapter *adapter)
-{
-       int ret;
-
-       /* Allocate command buffer */
-       ret = mwifiex_alloc_cmd_buffer(adapter);
-       if (ret) {
-               mwifiex_dbg(adapter, ERROR,
-                           "%s: failed to alloc cmd buffer\n",
-                           __func__);
-               return -1;
-       }
-
-       adapter->sleep_cfm =
-               dev_alloc_skb(sizeof(struct mwifiex_opt_sleep_confirm)
-                             + INTF_HEADER_LEN);
-
-       if (!adapter->sleep_cfm) {
-               mwifiex_dbg(adapter, ERROR,
-                           "%s: failed to alloc sleep cfm\t"
-                           " cmd buffer\n", __func__);
-               return -1;
-       }
-       skb_reserve(adapter->sleep_cfm, INTF_HEADER_LEN);
-
-       return 0;
-}
-
-/*
- * This function initializes the adapter structure and sets default
- * values to the members of adapter.
- *
- * This also initializes the WMM related parameters in the driver private
- * structures.
- */
-static void mwifiex_init_adapter(struct mwifiex_adapter *adapter)
-{
-       struct mwifiex_opt_sleep_confirm *sleep_cfm_buf = NULL;
-
-       skb_put(adapter->sleep_cfm, sizeof(struct mwifiex_opt_sleep_confirm));
-
-       adapter->cmd_sent = false;
-
-       if (adapter->iface_type == MWIFIEX_SDIO)
-               adapter->data_sent = true;
-       else
-               adapter->data_sent = false;
-
-       adapter->cmd_resp_received = false;
-       adapter->event_received = false;
-       adapter->data_received = false;
-
-       adapter->surprise_removed = false;
-
-       adapter->hw_status = MWIFIEX_HW_STATUS_INITIALIZING;
-
-       adapter->ps_mode = MWIFIEX_802_11_POWER_MODE_CAM;
-       adapter->ps_state = PS_STATE_AWAKE;
-       adapter->need_to_wakeup = false;
-
-       adapter->scan_mode = HostCmd_BSS_MODE_ANY;
-       adapter->specific_scan_time = MWIFIEX_SPECIFIC_SCAN_CHAN_TIME;
-       adapter->active_scan_time = MWIFIEX_ACTIVE_SCAN_CHAN_TIME;
-       adapter->passive_scan_time = MWIFIEX_PASSIVE_SCAN_CHAN_TIME;
-       adapter->scan_chan_gap_time = MWIFIEX_DEF_SCAN_CHAN_GAP_TIME;
-
-       adapter->scan_probes = 1;
-
-       adapter->multiple_dtim = 1;
-
-       adapter->local_listen_interval = 0;     /* default value in firmware
-                                                  will be used */
-
-       adapter->is_deep_sleep = false;
-
-       adapter->delay_null_pkt = false;
-       adapter->delay_to_ps = 1000;
-       adapter->enhanced_ps_mode = PS_MODE_AUTO;
-
-       adapter->gen_null_pkt = false;  /* Disable NULL Pkg generation by
-                                          default */
-       adapter->pps_uapsd_mode = false; /* Disable pps/uapsd mode by
-                                          default */
-       adapter->pm_wakeup_card_req = false;
-
-       adapter->pm_wakeup_fw_try = false;
-
-       adapter->curr_tx_buf_size = MWIFIEX_TX_DATA_BUF_SIZE_2K;
-
-       adapter->is_hs_configured = false;
-       adapter->hs_cfg.conditions = cpu_to_le32(HS_CFG_COND_DEF);
-       adapter->hs_cfg.gpio = HS_CFG_GPIO_DEF;
-       adapter->hs_cfg.gap = HS_CFG_GAP_DEF;
-       adapter->hs_activated = false;
-
-       memset(adapter->event_body, 0, sizeof(adapter->event_body));
-       adapter->hw_dot_11n_dev_cap = 0;
-       adapter->hw_dev_mcs_support = 0;
-       adapter->sec_chan_offset = 0;
-       adapter->adhoc_11n_enabled = false;
-
-       mwifiex_wmm_init(adapter);
-
-       sleep_cfm_buf = (struct mwifiex_opt_sleep_confirm *)
-                                       adapter->sleep_cfm->data;
-       memset(sleep_cfm_buf, 0, adapter->sleep_cfm->len);
-       sleep_cfm_buf->command = cpu_to_le16(HostCmd_CMD_802_11_PS_MODE_ENH);
-       sleep_cfm_buf->size = cpu_to_le16(adapter->sleep_cfm->len);
-       sleep_cfm_buf->result = 0;
-       sleep_cfm_buf->action = cpu_to_le16(SLEEP_CONFIRM);
-       sleep_cfm_buf->resp_ctrl = cpu_to_le16(RESP_NEEDED);
-
-       memset(&adapter->sleep_params, 0, sizeof(adapter->sleep_params));
-       memset(&adapter->sleep_period, 0, sizeof(adapter->sleep_period));
-       adapter->tx_lock_flag = false;
-       adapter->null_pkt_interval = 0;
-       adapter->fw_bands = 0;
-       adapter->config_bands = 0;
-       adapter->adhoc_start_band = 0;
-       adapter->scan_channels = NULL;
-       adapter->fw_release_number = 0;
-       adapter->fw_cap_info = 0;
-       memset(&adapter->upld_buf, 0, sizeof(adapter->upld_buf));
-       adapter->event_cause = 0;
-       adapter->region_code = 0;
-       adapter->bcn_miss_time_out = DEFAULT_BCN_MISS_TIMEOUT;
-       adapter->adhoc_awake_period = 0;
-       memset(&adapter->arp_filter, 0, sizeof(adapter->arp_filter));
-       adapter->arp_filter_size = 0;
-       adapter->max_mgmt_ie_index = MAX_MGMT_IE_INDEX;
-       adapter->key_api_major_ver = 0;
-       adapter->key_api_minor_ver = 0;
-       eth_broadcast_addr(adapter->perm_addr);
-       adapter->iface_limit.sta_intf = MWIFIEX_MAX_STA_NUM;
-       adapter->iface_limit.uap_intf = MWIFIEX_MAX_UAP_NUM;
-       adapter->iface_limit.p2p_intf = MWIFIEX_MAX_P2P_NUM;
-       adapter->active_scan_triggered = false;
-       setup_timer(&adapter->wakeup_timer, wakeup_timer_fn,
-                   (unsigned long)adapter);
-}
-
-/*
- * This function sets trans_start per tx_queue
- */
-void mwifiex_set_trans_start(struct net_device *dev)
-{
-       int i;
-
-       for (i = 0; i < dev->num_tx_queues; i++)
-               netdev_get_tx_queue(dev, i)->trans_start = jiffies;
-
-       dev->trans_start = jiffies;
-}
-
-/*
- * This function wakes up all queues in net_device
- */
-void mwifiex_wake_up_net_dev_queue(struct net_device *netdev,
-                                       struct mwifiex_adapter *adapter)
-{
-       unsigned long dev_queue_flags;
-       unsigned int i;
-
-       spin_lock_irqsave(&adapter->queue_lock, dev_queue_flags);
-
-       for (i = 0; i < netdev->num_tx_queues; i++) {
-               struct netdev_queue *txq = netdev_get_tx_queue(netdev, i);
-
-               if (netif_tx_queue_stopped(txq))
-                       netif_tx_wake_queue(txq);
-       }
-
-       spin_unlock_irqrestore(&adapter->queue_lock, dev_queue_flags);
-}
-
-/*
- * This function stops all queues in net_device
- */
-void mwifiex_stop_net_dev_queue(struct net_device *netdev,
-                                       struct mwifiex_adapter *adapter)
-{
-       unsigned long dev_queue_flags;
-       unsigned int i;
-
-       spin_lock_irqsave(&adapter->queue_lock, dev_queue_flags);
-
-       for (i = 0; i < netdev->num_tx_queues; i++) {
-               struct netdev_queue *txq = netdev_get_tx_queue(netdev, i);
-
-               if (!netif_tx_queue_stopped(txq))
-                       netif_tx_stop_queue(txq);
-       }
-
-       spin_unlock_irqrestore(&adapter->queue_lock, dev_queue_flags);
-}
-
-/*
- *  This function releases the lock variables and frees the locks and
- *  associated locks.
- */
-static void mwifiex_free_lock_list(struct mwifiex_adapter *adapter)
-{
-       struct mwifiex_private *priv;
-       s32 i, j;
-
-       /* Free lists */
-       list_del(&adapter->cmd_free_q);
-       list_del(&adapter->cmd_pending_q);
-       list_del(&adapter->scan_pending_q);
-
-       for (i = 0; i < adapter->priv_num; i++)
-               list_del(&adapter->bss_prio_tbl[i].bss_prio_head);
-
-       for (i = 0; i < adapter->priv_num; i++) {
-               if (adapter->priv[i]) {
-                       priv = adapter->priv[i];
-                       for (j = 0; j < MAX_NUM_TID; ++j)
-                               list_del(&priv->wmm.tid_tbl_ptr[j].ra_list);
-                       list_del(&priv->tx_ba_stream_tbl_ptr);
-                       list_del(&priv->rx_reorder_tbl_ptr);
-                       list_del(&priv->sta_list);
-                       list_del(&priv->auto_tdls_list);
-               }
-       }
-}
-
-/*
- * This function performs cleanup for adapter structure.
- *
- * The cleanup is done recursively, by canceling all pending
- * commands, freeing the member buffers previously allocated
- * (command buffers, scan table buffer, sleep confirm command
- * buffer), stopping the timers and calling the cleanup routines
- * for every interface.
- */
-static void
-mwifiex_adapter_cleanup(struct mwifiex_adapter *adapter)
-{
-       int idx;
-
-       if (!adapter) {
-               pr_err("%s: adapter is NULL\n", __func__);
-               return;
-       }
-
-       del_timer(&adapter->wakeup_timer);
-       mwifiex_cancel_all_pending_cmd(adapter);
-       wake_up_interruptible(&adapter->cmd_wait_q.wait);
-       wake_up_interruptible(&adapter->hs_activate_wait_q);
-
-       /* Free lock variables */
-       mwifiex_free_lock_list(adapter);
-
-       /* Free command buffer */
-       mwifiex_dbg(adapter, INFO, "info: free cmd buffer\n");
-       mwifiex_free_cmd_buffer(adapter);
-
-       for (idx = 0; idx < adapter->num_mem_types; idx++) {
-               struct memory_type_mapping *entry =
-                               &adapter->mem_type_mapping_tbl[idx];
-
-               if (entry->mem_ptr) {
-                       vfree(entry->mem_ptr);
-                       entry->mem_ptr = NULL;
-               }
-               entry->mem_size = 0;
-       }
-
-       if (adapter->drv_info_dump) {
-               vfree(adapter->drv_info_dump);
-               adapter->drv_info_dump = NULL;
-               adapter->drv_info_size = 0;
-       }
-
-       if (adapter->sleep_cfm)
-               dev_kfree_skb_any(adapter->sleep_cfm);
-}
-
-/*
- *  This function intializes the lock variables and
- *  the list heads.
- */
-int mwifiex_init_lock_list(struct mwifiex_adapter *adapter)
-{
-       struct mwifiex_private *priv;
-       s32 i, j;
-
-       spin_lock_init(&adapter->mwifiex_lock);
-       spin_lock_init(&adapter->int_lock);
-       spin_lock_init(&adapter->main_proc_lock);
-       spin_lock_init(&adapter->mwifiex_cmd_lock);
-       spin_lock_init(&adapter->queue_lock);
-       for (i = 0; i < adapter->priv_num; i++) {
-               if (adapter->priv[i]) {
-                       priv = adapter->priv[i];
-                       spin_lock_init(&priv->rx_pkt_lock);
-                       spin_lock_init(&priv->wmm.ra_list_spinlock);
-                       spin_lock_init(&priv->curr_bcn_buf_lock);
-                       spin_lock_init(&priv->sta_list_spinlock);
-                       spin_lock_init(&priv->auto_tdls_lock);
-               }
-       }
-
-       /* Initialize cmd_free_q */
-       INIT_LIST_HEAD(&adapter->cmd_free_q);
-       /* Initialize cmd_pending_q */
-       INIT_LIST_HEAD(&adapter->cmd_pending_q);
-       /* Initialize scan_pending_q */
-       INIT_LIST_HEAD(&adapter->scan_pending_q);
-
-       spin_lock_init(&adapter->cmd_free_q_lock);
-       spin_lock_init(&adapter->cmd_pending_q_lock);
-       spin_lock_init(&adapter->scan_pending_q_lock);
-       spin_lock_init(&adapter->rx_proc_lock);
-
-       skb_queue_head_init(&adapter->rx_data_q);
-       skb_queue_head_init(&adapter->tx_data_q);
-
-       for (i = 0; i < adapter->priv_num; ++i) {
-               INIT_LIST_HEAD(&adapter->bss_prio_tbl[i].bss_prio_head);
-               spin_lock_init(&adapter->bss_prio_tbl[i].bss_prio_lock);
-       }
-
-       for (i = 0; i < adapter->priv_num; i++) {
-               if (!adapter->priv[i])
-                       continue;
-               priv = adapter->priv[i];
-               for (j = 0; j < MAX_NUM_TID; ++j)
-                       INIT_LIST_HEAD(&priv->wmm.tid_tbl_ptr[j].ra_list);
-               INIT_LIST_HEAD(&priv->tx_ba_stream_tbl_ptr);
-               INIT_LIST_HEAD(&priv->rx_reorder_tbl_ptr);
-               INIT_LIST_HEAD(&priv->sta_list);
-               INIT_LIST_HEAD(&priv->auto_tdls_list);
-               skb_queue_head_init(&priv->tdls_txq);
-               skb_queue_head_init(&priv->bypass_txq);
-
-               spin_lock_init(&priv->tx_ba_stream_tbl_lock);
-               spin_lock_init(&priv->rx_reorder_tbl_lock);
-
-               spin_lock_init(&priv->ack_status_lock);
-               idr_init(&priv->ack_status_frames);
-       }
-
-       return 0;
-}
-
-/*
- * This function initializes the firmware.
- *
- * The following operations are performed sequentially -
- *      - Allocate adapter structure
- *      - Initialize the adapter structure
- *      - Initialize the private structure
- *      - Add BSS priority tables to the adapter structure
- *      - For each interface, send the init commands to firmware
- *      - Send the first command in command pending queue, if available
- */
-int mwifiex_init_fw(struct mwifiex_adapter *adapter)
-{
-       int ret;
-       struct mwifiex_private *priv;
-       u8 i, first_sta = true;
-       int is_cmd_pend_q_empty;
-       unsigned long flags;
-
-       adapter->hw_status = MWIFIEX_HW_STATUS_INITIALIZING;
-
-       /* Allocate memory for member of adapter structure */
-       ret = mwifiex_allocate_adapter(adapter);
-       if (ret)
-               return -1;
-
-       /* Initialize adapter structure */
-       mwifiex_init_adapter(adapter);
-
-       for (i = 0; i < adapter->priv_num; i++) {
-               if (adapter->priv[i]) {
-                       priv = adapter->priv[i];
-
-                       /* Initialize private structure */
-                       ret = mwifiex_init_priv(priv);
-                       if (ret)
-                               return -1;
-               }
-       }
-
-       for (i = 0; i < adapter->priv_num; i++) {
-               if (adapter->priv[i]) {
-                       ret = mwifiex_sta_init_cmd(adapter->priv[i], first_sta,
-                                                  true);
-                       if (ret == -1)
-                               return -1;
-
-                       first_sta = false;
-               }
-       }
-
-       spin_lock_irqsave(&adapter->cmd_pending_q_lock, flags);
-       is_cmd_pend_q_empty = list_empty(&adapter->cmd_pending_q);
-       spin_unlock_irqrestore(&adapter->cmd_pending_q_lock, flags);
-       if (!is_cmd_pend_q_empty) {
-               /* Send the first command in queue and return */
-               if (mwifiex_main_process(adapter) != -1)
-                       ret = -EINPROGRESS;
-       } else {
-               adapter->hw_status = MWIFIEX_HW_STATUS_READY;
-       }
-
-       return ret;
-}
-
-/*
- * This function deletes the BSS priority tables.
- *
- * The function traverses through all the allocated BSS priority nodes
- * in every BSS priority table and frees them.
- */
-static void mwifiex_delete_bss_prio_tbl(struct mwifiex_private *priv)
-{
-       int i;
-       struct mwifiex_adapter *adapter = priv->adapter;
-       struct mwifiex_bss_prio_node *bssprio_node, *tmp_node;
-       struct list_head *head;
-       spinlock_t *lock; /* bss priority lock */
-       unsigned long flags;
-
-       for (i = 0; i < adapter->priv_num; ++i) {
-               head = &adapter->bss_prio_tbl[i].bss_prio_head;
-               lock = &adapter->bss_prio_tbl[i].bss_prio_lock;
-               mwifiex_dbg(adapter, INFO,
-                           "info: delete BSS priority table,\t"
-                           "bss_type = %d, bss_num = %d, i = %d,\t"
-                           "head = %p\n",
-                           priv->bss_type, priv->bss_num, i, head);
-
-               {
-                       spin_lock_irqsave(lock, flags);
-                       if (list_empty(head)) {
-                               spin_unlock_irqrestore(lock, flags);
-                               continue;
-                       }
-                       list_for_each_entry_safe(bssprio_node, tmp_node, head,
-                                                list) {
-                               if (bssprio_node->priv == priv) {
-                                       mwifiex_dbg(adapter, INFO,
-                                                   "info: Delete\t"
-                                                   "node %p, next = %p\n",
-                                                   bssprio_node, tmp_node);
-                                       list_del(&bssprio_node->list);
-                                       kfree(bssprio_node);
-                               }
-                       }
-                       spin_unlock_irqrestore(lock, flags);
-               }
-       }
-}
-
-/*
- * This function frees the private structure, including cleans
- * up the TX and RX queues and frees the BSS priority tables.
- */
-void mwifiex_free_priv(struct mwifiex_private *priv)
-{
-       mwifiex_clean_txrx(priv);
-       mwifiex_delete_bss_prio_tbl(priv);
-       mwifiex_free_curr_bcn(priv);
-}
-
-/*
- * This function is used to shutdown the driver.
- *
- * The following operations are performed sequentially -
- *      - Check if already shut down
- *      - Make sure the main process has stopped
- *      - Clean up the Tx and Rx queues
- *      - Delete BSS priority tables
- *      - Free the adapter
- *      - Notify completion
- */
-int
-mwifiex_shutdown_drv(struct mwifiex_adapter *adapter)
-{
-       int ret = -EINPROGRESS;
-       struct mwifiex_private *priv;
-       s32 i;
-       unsigned long flags;
-       struct sk_buff *skb;
-
-       /* mwifiex already shutdown */
-       if (adapter->hw_status == MWIFIEX_HW_STATUS_NOT_READY)
-               return 0;
-
-       adapter->hw_status = MWIFIEX_HW_STATUS_CLOSING;
-       /* wait for mwifiex_process to complete */
-       if (adapter->mwifiex_processing) {
-               mwifiex_dbg(adapter, WARN,
-                           "main process is still running\n");
-               return ret;
-       }
-
-       /* cancel current command */
-       if (adapter->curr_cmd) {
-               mwifiex_dbg(adapter, WARN,
-                           "curr_cmd is still in processing\n");
-               del_timer_sync(&adapter->cmd_timer);
-               mwifiex_recycle_cmd_node(adapter, adapter->curr_cmd);
-               adapter->curr_cmd = NULL;
-       }
-
-       /* shut down mwifiex */
-       mwifiex_dbg(adapter, MSG,
-                   "info: shutdown mwifiex...\n");
-
-       /* Clean up Tx/Rx queues and delete BSS priority table */
-       for (i = 0; i < adapter->priv_num; i++) {
-               if (adapter->priv[i]) {
-                       priv = adapter->priv[i];
-
-                       mwifiex_clean_auto_tdls(priv);
-                       mwifiex_abort_cac(priv);
-                       mwifiex_clean_txrx(priv);
-                       mwifiex_delete_bss_prio_tbl(priv);
-               }
-       }
-
-       atomic_set(&adapter->tx_queued, 0);
-       while ((skb = skb_dequeue(&adapter->tx_data_q)))
-               mwifiex_write_data_complete(adapter, skb, 0, 0);
-
-       spin_lock_irqsave(&adapter->rx_proc_lock, flags);
-
-       while ((skb = skb_dequeue(&adapter->rx_data_q))) {
-               struct mwifiex_rxinfo *rx_info = MWIFIEX_SKB_RXCB(skb);
-
-               atomic_dec(&adapter->rx_pending);
-               priv = adapter->priv[rx_info->bss_num];
-               if (priv)
-                       priv->stats.rx_dropped++;
-
-               dev_kfree_skb_any(skb);
-       }
-
-       spin_unlock_irqrestore(&adapter->rx_proc_lock, flags);
-
-       spin_lock(&adapter->mwifiex_lock);
-
-       mwifiex_adapter_cleanup(adapter);
-
-       spin_unlock(&adapter->mwifiex_lock);
-
-       /* Notify completion */
-       ret = mwifiex_shutdown_fw_complete(adapter);
-
-       return ret;
-}
-
-/*
- * This function downloads the firmware to the card.
- *
- * The actual download is preceded by two sanity checks -
- *      - Check if firmware is already running
- *      - Check if the interface is the winner to download the firmware
- *
- * ...and followed by another -
- *      - Check if the firmware is downloaded successfully
- *
- * After download is successfully completed, the host interrupts are enabled.
- */
-int mwifiex_dnld_fw(struct mwifiex_adapter *adapter,
-                   struct mwifiex_fw_image *pmfw)
-{
-       int ret;
-       u32 poll_num = 1;
-
-       if (adapter->if_ops.check_fw_status) {
-               adapter->winner = 0;
-
-               /* check if firmware is already running */
-               ret = adapter->if_ops.check_fw_status(adapter, poll_num);
-               if (!ret) {
-                       mwifiex_dbg(adapter, MSG,
-                                   "WLAN FW already running! Skip FW dnld\n");
-                       return 0;
-               }
-
-               poll_num = MAX_FIRMWARE_POLL_TRIES;
-
-               /* check if we are the winner for downloading FW */
-               if (!adapter->winner) {
-                       mwifiex_dbg(adapter, MSG,
-                                   "FW already running! Skip FW dnld\n");
-                       goto poll_fw;
-               }
-       }
-
-       if (pmfw) {
-               /* Download firmware with helper */
-               ret = adapter->if_ops.prog_fw(adapter, pmfw);
-               if (ret) {
-                       mwifiex_dbg(adapter, ERROR,
-                                   "prog_fw failed ret=%#x\n", ret);
-                       return ret;
-               }
-       }
-
-poll_fw:
-       /* Check if the firmware is downloaded successfully or not */
-       ret = adapter->if_ops.check_fw_status(adapter, poll_num);
-       if (ret)
-               mwifiex_dbg(adapter, ERROR,
-                           "FW failed to be active in time\n");
-
-       return ret;
-}
diff --git a/drivers/net/wireless/mwifiex/ioctl.h b/drivers/net/wireless/mwifiex/ioctl.h
deleted file mode 100644 (file)
index 4f0174c..0000000
+++ /dev/null
@@ -1,470 +0,0 @@
-/*
- * Marvell Wireless LAN device driver: ioctl data structures & APIs
- *
- * Copyright (C) 2011-2014, Marvell International Ltd.
- *
- * This software file (the "File") is distributed by Marvell International
- * Ltd. under the terms of the GNU General Public License Version 2, June 1991
- * (the "License").  You may use, redistribute and/or modify this File in
- * accordance with the terms and conditions of the License, a copy of which
- * is available by writing to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the
- * worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
- *
- * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
- * ARE EXPRESSLY DISCLAIMED.  The License provides additional details about
- * this warranty disclaimer.
- */
-
-#ifndef _MWIFIEX_IOCTL_H_
-#define _MWIFIEX_IOCTL_H_
-
-#include <net/lib80211.h>
-
-enum {
-       MWIFIEX_SCAN_TYPE_UNCHANGED = 0,
-       MWIFIEX_SCAN_TYPE_ACTIVE,
-       MWIFIEX_SCAN_TYPE_PASSIVE
-};
-
-struct mwifiex_user_scan {
-       u32 scan_cfg_len;
-       u8 scan_cfg_buf[1];
-};
-
-#define MWIFIEX_PROMISC_MODE            1
-#define MWIFIEX_MULTICAST_MODE         2
-#define        MWIFIEX_ALL_MULTI_MODE          4
-#define MWIFIEX_MAX_MULTICAST_LIST_SIZE        32
-
-struct mwifiex_multicast_list {
-       u32 mode;
-       u32 num_multicast_addr;
-       u8 mac_list[MWIFIEX_MAX_MULTICAST_LIST_SIZE][ETH_ALEN];
-};
-
-struct mwifiex_chan_freq {
-       u32 channel;
-       u32 freq;
-};
-
-struct mwifiex_ssid_bssid {
-       struct cfg80211_ssid ssid;
-       u8 bssid[ETH_ALEN];
-};
-
-enum {
-       BAND_B = 1,
-       BAND_G = 2,
-       BAND_A = 4,
-       BAND_GN = 8,
-       BAND_AN = 16,
-       BAND_AAC = 32,
-};
-
-#define MWIFIEX_WPA_PASSHPHRASE_LEN 64
-struct wpa_param {
-       u8 pairwise_cipher_wpa;
-       u8 pairwise_cipher_wpa2;
-       u8 group_cipher;
-       u32 length;
-       u8 passphrase[MWIFIEX_WPA_PASSHPHRASE_LEN];
-};
-
-struct wep_key {
-       u8 key_index;
-       u8 is_default;
-       u16 length;
-       u8 key[WLAN_KEY_LEN_WEP104];
-};
-
-#define KEY_MGMT_ON_HOST        0x03
-#define MWIFIEX_AUTH_MODE_AUTO  0xFF
-#define BAND_CONFIG_BG          0x00
-#define BAND_CONFIG_A           0x01
-#define MWIFIEX_SUPPORTED_RATES                 14
-#define MWIFIEX_SUPPORTED_RATES_EXT             32
-#define MWIFIEX_TDLS_SUPPORTED_RATES           8
-#define MWIFIEX_TDLS_DEF_QOS_CAPAB             0xf
-#define MWIFIEX_PRIO_BK                                2
-#define MWIFIEX_PRIO_VI                                5
-
-struct mwifiex_uap_bss_param {
-       u8 channel;
-       u8 band_cfg;
-       u16 rts_threshold;
-       u16 frag_threshold;
-       u8 retry_limit;
-       struct mwifiex_802_11_ssid ssid;
-       u8 bcast_ssid_ctl;
-       u8 radio_ctl;
-       u8 dtim_period;
-       u16 beacon_period;
-       u16 auth_mode;
-       u16 protocol;
-       u16 key_mgmt;
-       u16 key_mgmt_operation;
-       struct wpa_param wpa_cfg;
-       struct wep_key wep_cfg[NUM_WEP_KEYS];
-       struct ieee80211_ht_cap ht_cap;
-       struct ieee80211_vht_cap vht_cap;
-       u8 rates[MWIFIEX_SUPPORTED_RATES];
-       u32 sta_ao_timer;
-       u32 ps_sta_ao_timer;
-       u8 qos_info;
-       u8 power_constraint;
-       struct mwifiex_types_wmm_info wmm_info;
-};
-
-enum {
-       ADHOC_IDLE,
-       ADHOC_STARTED,
-       ADHOC_JOINED,
-       ADHOC_COALESCED
-};
-
-struct mwifiex_ds_get_stats {
-       u32 mcast_tx_frame;
-       u32 failed;
-       u32 retry;
-       u32 multi_retry;
-       u32 frame_dup;
-       u32 rts_success;
-       u32 rts_failure;
-       u32 ack_failure;
-       u32 rx_frag;
-       u32 mcast_rx_frame;
-       u32 fcs_error;
-       u32 tx_frame;
-       u32 wep_icv_error[4];
-       u32 bcn_rcv_cnt;
-       u32 bcn_miss_cnt;
-};
-
-#define MWIFIEX_MAX_VER_STR_LEN    128
-
-struct mwifiex_ver_ext {
-       u32 version_str_sel;
-       char version_str[MWIFIEX_MAX_VER_STR_LEN];
-};
-
-struct mwifiex_bss_info {
-       u32 bss_mode;
-       struct cfg80211_ssid ssid;
-       u32 bss_chan;
-       u8 country_code[3];
-       u32 media_connected;
-       u32 max_power_level;
-       u32 min_power_level;
-       u32 adhoc_state;
-       signed int bcn_nf_last;
-       u32 wep_status;
-       u32 is_hs_configured;
-       u32 is_deep_sleep;
-       u8 bssid[ETH_ALEN];
-};
-
-#define MAX_NUM_TID     8
-
-#define MAX_RX_WINSIZE  64
-
-struct mwifiex_ds_rx_reorder_tbl {
-       u16 tid;
-       u8 ta[ETH_ALEN];
-       u32 start_win;
-       u32 win_size;
-       u32 buffer[MAX_RX_WINSIZE];
-};
-
-struct mwifiex_ds_tx_ba_stream_tbl {
-       u16 tid;
-       u8 ra[ETH_ALEN];
-       u8 amsdu;
-};
-
-#define DBG_CMD_NUM    5
-
-struct tdls_peer_info {
-       u8 peer_addr[ETH_ALEN];
-};
-
-struct mwifiex_debug_info {
-       unsigned int debug_mask;
-       u32 int_counter;
-       u32 packets_out[MAX_NUM_TID];
-       u32 tx_buf_size;
-       u32 curr_tx_buf_size;
-       u32 tx_tbl_num;
-       struct mwifiex_ds_tx_ba_stream_tbl
-               tx_tbl[MWIFIEX_MAX_TX_BASTREAM_SUPPORTED];
-       u32 rx_tbl_num;
-       struct mwifiex_ds_rx_reorder_tbl rx_tbl
-               [MWIFIEX_MAX_RX_BASTREAM_SUPPORTED];
-       u32 tdls_peer_num;
-       struct tdls_peer_info tdls_list
-               [MWIFIEX_MAX_TDLS_PEER_SUPPORTED];
-       u16 ps_mode;
-       u32 ps_state;
-       u8 is_deep_sleep;
-       u8 pm_wakeup_card_req;
-       u32 pm_wakeup_fw_try;
-       u8 is_hs_configured;
-       u8 hs_activated;
-       u32 num_cmd_host_to_card_failure;
-       u32 num_cmd_sleep_cfm_host_to_card_failure;
-       u32 num_tx_host_to_card_failure;
-       u32 num_event_deauth;
-       u32 num_event_disassoc;
-       u32 num_event_link_lost;
-       u32 num_cmd_deauth;
-       u32 num_cmd_assoc_success;
-       u32 num_cmd_assoc_failure;
-       u32 num_tx_timeout;
-       u8 is_cmd_timedout;
-       u16 timeout_cmd_id;
-       u16 timeout_cmd_act;
-       u16 last_cmd_id[DBG_CMD_NUM];
-       u16 last_cmd_act[DBG_CMD_NUM];
-       u16 last_cmd_index;
-       u16 last_cmd_resp_id[DBG_CMD_NUM];
-       u16 last_cmd_resp_index;
-       u16 last_event[DBG_CMD_NUM];
-       u16 last_event_index;
-       u8 data_sent;
-       u8 cmd_sent;
-       u8 cmd_resp_received;
-       u8 event_received;
-};
-
-#define MWIFIEX_KEY_INDEX_UNICAST      0x40000000
-#define PN_LEN                         16
-
-struct mwifiex_ds_encrypt_key {
-       u32 key_disable;
-       u32 key_index;
-       u32 key_len;
-       u8 key_material[WLAN_MAX_KEY_LEN];
-       u8 mac_addr[ETH_ALEN];
-       u32 is_wapi_key;
-       u8 pn[PN_LEN];          /* packet number */
-       u8 pn_len;
-       u8 is_igtk_key;
-       u8 is_current_wep_key;
-       u8 is_rx_seq_valid;
-};
-
-struct mwifiex_power_cfg {
-       u32 is_power_auto;
-       u32 power_level;
-};
-
-struct mwifiex_ds_hs_cfg {
-       u32 is_invoke_hostcmd;
-       /*  Bit0: non-unicast data
-        *  Bit1: unicast data
-        *  Bit2: mac events
-        *  Bit3: magic packet
-        */
-       u32 conditions;
-       u32 gpio;
-       u32 gap;
-};
-
-#define DEEP_SLEEP_ON  1
-#define DEEP_SLEEP_OFF 0
-#define DEEP_SLEEP_IDLE_TIME   100
-#define PS_MODE_AUTO           1
-
-struct mwifiex_ds_auto_ds {
-       u16 auto_ds;
-       u16 idle_time;
-};
-
-struct mwifiex_ds_pm_cfg {
-       union {
-               u32 ps_mode;
-               struct mwifiex_ds_hs_cfg hs_cfg;
-               struct mwifiex_ds_auto_ds auto_deep_sleep;
-               u32 sleep_period;
-       } param;
-};
-
-struct mwifiex_11ac_vht_cfg {
-       u8 band_config;
-       u8 misc_config;
-       u32 cap_info;
-       u32 mcs_tx_set;
-       u32 mcs_rx_set;
-};
-
-struct mwifiex_ds_11n_tx_cfg {
-       u16 tx_htcap;
-       u16 tx_htinfo;
-       u16 misc_config; /* Needed for 802.11AC cards only */
-};
-
-struct mwifiex_ds_11n_amsdu_aggr_ctrl {
-       u16 enable;
-       u16 curr_buf_size;
-};
-
-struct mwifiex_ds_ant_cfg {
-       u32 tx_ant;
-       u32 rx_ant;
-};
-
-#define MWIFIEX_NUM_OF_CMD_BUFFER      50
-#define MWIFIEX_SIZE_OF_CMD_BUFFER     2048
-
-enum {
-       MWIFIEX_IE_TYPE_GEN_IE = 0,
-       MWIFIEX_IE_TYPE_ARP_FILTER,
-};
-
-enum {
-       MWIFIEX_REG_MAC = 1,
-       MWIFIEX_REG_BBP,
-       MWIFIEX_REG_RF,
-       MWIFIEX_REG_PMIC,
-       MWIFIEX_REG_CAU,
-};
-
-struct mwifiex_ds_reg_rw {
-       __le32 type;
-       __le32 offset;
-       __le32 value;
-};
-
-#define MAX_EEPROM_DATA 256
-
-struct mwifiex_ds_read_eeprom {
-       __le16 offset;
-       __le16 byte_count;
-       u8 value[MAX_EEPROM_DATA];
-};
-
-struct mwifiex_ds_mem_rw {
-       u32 addr;
-       u32 value;
-};
-
-#define IEEE_MAX_IE_SIZE               256
-
-#define MWIFIEX_IE_HDR_SIZE    (sizeof(struct mwifiex_ie) - IEEE_MAX_IE_SIZE)
-
-struct mwifiex_ds_misc_gen_ie {
-       u32 type;
-       u32 len;
-       u8 ie_data[IEEE_MAX_IE_SIZE];
-};
-
-struct mwifiex_ds_misc_cmd {
-       u32 len;
-       u8 cmd[MWIFIEX_SIZE_OF_CMD_BUFFER];
-};
-
-#define BITMASK_BCN_RSSI_LOW   BIT(0)
-#define BITMASK_BCN_RSSI_HIGH  BIT(4)
-
-enum subsc_evt_rssi_state {
-       EVENT_HANDLED,
-       RSSI_LOW_RECVD,
-       RSSI_HIGH_RECVD
-};
-
-struct subsc_evt_cfg {
-       u8 abs_value;
-       u8 evt_freq;
-};
-
-struct mwifiex_ds_misc_subsc_evt {
-       u16 action;
-       u16 events;
-       struct subsc_evt_cfg bcn_l_rssi_cfg;
-       struct subsc_evt_cfg bcn_h_rssi_cfg;
-};
-
-#define MWIFIEX_MEF_MAX_BYTESEQ                6       /* non-adjustable */
-#define MWIFIEX_MEF_MAX_FILTERS                10
-
-struct mwifiex_mef_filter {
-       u16 repeat;
-       u16 offset;
-       s8 byte_seq[MWIFIEX_MEF_MAX_BYTESEQ + 1];
-       u8 filt_type;
-       u8 filt_action;
-};
-
-struct mwifiex_mef_entry {
-       u8 mode;
-       u8 action;
-       struct mwifiex_mef_filter filter[MWIFIEX_MEF_MAX_FILTERS];
-};
-
-struct mwifiex_ds_mef_cfg {
-       u32 criteria;
-       u16 num_entries;
-       struct mwifiex_mef_entry *mef_entry;
-};
-
-#define MWIFIEX_MAX_VSIE_LEN       (256)
-#define MWIFIEX_MAX_VSIE_NUM       (8)
-#define MWIFIEX_VSIE_MASK_CLEAR    0x00
-#define MWIFIEX_VSIE_MASK_SCAN     0x01
-#define MWIFIEX_VSIE_MASK_ASSOC    0x02
-#define MWIFIEX_VSIE_MASK_ADHOC    0x04
-
-enum {
-       MWIFIEX_FUNC_INIT = 1,
-       MWIFIEX_FUNC_SHUTDOWN,
-};
-
-enum COALESCE_OPERATION {
-       RECV_FILTER_MATCH_TYPE_EQ = 0x80,
-       RECV_FILTER_MATCH_TYPE_NE,
-};
-
-enum COALESCE_PACKET_TYPE {
-       PACKET_TYPE_UNICAST = 1,
-       PACKET_TYPE_MULTICAST = 2,
-       PACKET_TYPE_BROADCAST = 3
-};
-
-#define MWIFIEX_COALESCE_MAX_RULES     8
-#define MWIFIEX_COALESCE_MAX_BYTESEQ   4       /* non-adjustable */
-#define MWIFIEX_COALESCE_MAX_FILTERS   4
-#define MWIFIEX_MAX_COALESCING_DELAY   100     /* in msecs */
-
-struct filt_field_param {
-       u8 operation;
-       u8 operand_len;
-       u16 offset;
-       u8 operand_byte_stream[MWIFIEX_COALESCE_MAX_BYTESEQ];
-};
-
-struct mwifiex_coalesce_rule {
-       u16 max_coalescing_delay;
-       u8 num_of_fields;
-       u8 pkt_type;
-       struct filt_field_param params[MWIFIEX_COALESCE_MAX_FILTERS];
-};
-
-struct mwifiex_ds_coalesce_cfg {
-       u16 num_of_rules;
-       struct mwifiex_coalesce_rule rule[MWIFIEX_COALESCE_MAX_RULES];
-};
-
-struct mwifiex_ds_tdls_oper {
-       u16 tdls_action;
-       u8 peer_mac[ETH_ALEN];
-       u16 capability;
-       u8 qos_info;
-       u8 *ext_capab;
-       u8 ext_capab_len;
-       u8 *supp_rates;
-       u8 supp_rates_len;
-       u8 *ht_capab;
-};
-
-#endif /* !_MWIFIEX_IOCTL_H_ */
diff --git a/drivers/net/wireless/mwifiex/join.c b/drivers/net/wireless/mwifiex/join.c
deleted file mode 100644 (file)
index 3cda1f9..0000000
+++ /dev/null
@@ -1,1525 +0,0 @@
-/*
- * Marvell Wireless LAN device driver: association and ad-hoc start/join
- *
- * Copyright (C) 2011-2014, Marvell International Ltd.
- *
- * This software file (the "File") is distributed by Marvell International
- * Ltd. under the terms of the GNU General Public License Version 2, June 1991
- * (the "License").  You may use, redistribute and/or modify this File in
- * accordance with the terms and conditions of the License, a copy of which
- * is available by writing to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the
- * worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
- *
- * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
- * ARE EXPRESSLY DISCLAIMED.  The License provides additional details about
- * this warranty disclaimer.
- */
-
-#include "decl.h"
-#include "ioctl.h"
-#include "util.h"
-#include "fw.h"
-#include "main.h"
-#include "wmm.h"
-#include "11n.h"
-#include "11ac.h"
-
-#define CAPINFO_MASK    (~(BIT(15) | BIT(14) | BIT(12) | BIT(11) | BIT(9)))
-
-/*
- * Append a generic IE as a pass through TLV to a TLV buffer.
- *
- * This function is called from the network join command preparation routine.
- *
- * If the IE buffer has been setup by the application, this routine appends
- * the buffer as a pass through TLV type to the request.
- */
-static int
-mwifiex_cmd_append_generic_ie(struct mwifiex_private *priv, u8 **buffer)
-{
-       int ret_len = 0;
-       struct mwifiex_ie_types_header ie_header;
-
-       /* Null Checks */
-       if (!buffer)
-               return 0;
-       if (!(*buffer))
-               return 0;
-
-       /*
-        * If there is a generic ie buffer setup, append it to the return
-        *   parameter buffer pointer.
-        */
-       if (priv->gen_ie_buf_len) {
-               mwifiex_dbg(priv->adapter, INFO,
-                           "info: %s: append generic ie len %d to %p\n",
-                           __func__, priv->gen_ie_buf_len, *buffer);
-
-               /* Wrap the generic IE buffer with a pass through TLV type */
-               ie_header.type = cpu_to_le16(TLV_TYPE_PASSTHROUGH);
-               ie_header.len = cpu_to_le16(priv->gen_ie_buf_len);
-               memcpy(*buffer, &ie_header, sizeof(ie_header));
-
-               /* Increment the return size and the return buffer pointer
-                  param */
-               *buffer += sizeof(ie_header);
-               ret_len += sizeof(ie_header);
-
-               /* Copy the generic IE buffer to the output buffer, advance
-                  pointer */
-               memcpy(*buffer, priv->gen_ie_buf, priv->gen_ie_buf_len);
-
-               /* Increment the return size and the return buffer pointer
-                  param */
-               *buffer += priv->gen_ie_buf_len;
-               ret_len += priv->gen_ie_buf_len;
-
-               /* Reset the generic IE buffer */
-               priv->gen_ie_buf_len = 0;
-       }
-
-       /* return the length appended to the buffer */
-       return ret_len;
-}
-
-/*
- * Append TSF tracking info from the scan table for the target AP.
- *
- * This function is called from the network join command preparation routine.
- *
- * The TSF table TSF sent to the firmware contains two TSF values:
- *      - The TSF of the target AP from its previous beacon/probe response
- *      - The TSF timestamp of our local MAC at the time we observed the
- *        beacon/probe response.
- *
- * The firmware uses the timestamp values to set an initial TSF value
- * in the MAC for the new association after a reassociation attempt.
- */
-static int
-mwifiex_cmd_append_tsf_tlv(struct mwifiex_private *priv, u8 **buffer,
-                          struct mwifiex_bssdescriptor *bss_desc)
-{
-       struct mwifiex_ie_types_tsf_timestamp tsf_tlv;
-       __le64 tsf_val;
-
-       /* Null Checks */
-       if (buffer == NULL)
-               return 0;
-       if (*buffer == NULL)
-               return 0;
-
-       memset(&tsf_tlv, 0x00, sizeof(struct mwifiex_ie_types_tsf_timestamp));
-
-       tsf_tlv.header.type = cpu_to_le16(TLV_TYPE_TSFTIMESTAMP);
-       tsf_tlv.header.len = cpu_to_le16(2 * sizeof(tsf_val));
-
-       memcpy(*buffer, &tsf_tlv, sizeof(tsf_tlv.header));
-       *buffer += sizeof(tsf_tlv.header);
-
-       /* TSF at the time when beacon/probe_response was received */
-       tsf_val = cpu_to_le64(bss_desc->fw_tsf);
-       memcpy(*buffer, &tsf_val, sizeof(tsf_val));
-       *buffer += sizeof(tsf_val);
-
-       tsf_val = cpu_to_le64(bss_desc->timestamp);
-
-       mwifiex_dbg(priv->adapter, INFO,
-                   "info: %s: TSF offset calc: %016llx - %016llx\n",
-                   __func__, bss_desc->timestamp, bss_desc->fw_tsf);
-
-       memcpy(*buffer, &tsf_val, sizeof(tsf_val));
-       *buffer += sizeof(tsf_val);
-
-       return sizeof(tsf_tlv.header) + (2 * sizeof(tsf_val));
-}
-
-/*
- * This function finds out the common rates between rate1 and rate2.
- *
- * It will fill common rates in rate1 as output if found.
- *
- * NOTE: Setting the MSB of the basic rates needs to be taken
- * care of, either before or after calling this function.
- */
-static int mwifiex_get_common_rates(struct mwifiex_private *priv, u8 *rate1,
-                                   u32 rate1_size, u8 *rate2, u32 rate2_size)
-{
-       int ret;
-       u8 *ptr = rate1, *tmp;
-       u32 i, j;
-
-       tmp = kmemdup(rate1, rate1_size, GFP_KERNEL);
-       if (!tmp) {
-               mwifiex_dbg(priv->adapter, ERROR, "failed to alloc tmp buf\n");
-               return -ENOMEM;
-       }
-
-       memset(rate1, 0, rate1_size);
-
-       for (i = 0; i < rate2_size && rate2[i]; i++) {
-               for (j = 0; j < rate1_size && tmp[j]; j++) {
-                       /* Check common rate, excluding the bit for
-                          basic rate */
-                       if ((rate2[i] & 0x7F) == (tmp[j] & 0x7F)) {
-                               *rate1++ = tmp[j];
-                               break;
-                       }
-               }
-       }
-
-       mwifiex_dbg(priv->adapter, INFO, "info: Tx data rate set to %#x\n",
-                   priv->data_rate);
-
-       if (!priv->is_data_rate_auto) {
-               while (*ptr) {
-                       if ((*ptr & 0x7f) == priv->data_rate) {
-                               ret = 0;
-                               goto done;
-                       }
-                       ptr++;
-               }
-               mwifiex_dbg(priv->adapter, ERROR,
-                           "previously set fixed data rate %#x\t"
-                           "is not compatible with the network\n",
-                           priv->data_rate);
-
-               ret = -1;
-               goto done;
-       }
-
-       ret = 0;
-done:
-       kfree(tmp);
-       return ret;
-}
-
-/*
- * This function creates the intersection of the rates supported by a
- * target BSS and our adapter settings for use in an assoc/join command.
- */
-static int
-mwifiex_setup_rates_from_bssdesc(struct mwifiex_private *priv,
-                                struct mwifiex_bssdescriptor *bss_desc,
-                                u8 *out_rates, u32 *out_rates_size)
-{
-       u8 card_rates[MWIFIEX_SUPPORTED_RATES];
-       u32 card_rates_size;
-
-       /* Copy AP supported rates */
-       memcpy(out_rates, bss_desc->supported_rates, MWIFIEX_SUPPORTED_RATES);
-       /* Get the STA supported rates */
-       card_rates_size = mwifiex_get_active_data_rates(priv, card_rates);
-       /* Get the common rates between AP and STA supported rates */
-       if (mwifiex_get_common_rates(priv, out_rates, MWIFIEX_SUPPORTED_RATES,
-                                    card_rates, card_rates_size)) {
-               *out_rates_size = 0;
-               mwifiex_dbg(priv->adapter, ERROR,
-                           "%s: cannot get common rates\n",
-                           __func__);
-               return -1;
-       }
-
-       *out_rates_size =
-               min_t(size_t, strlen(out_rates), MWIFIEX_SUPPORTED_RATES);
-
-       return 0;
-}
-
-/*
- * This function appends a WPS IE. It is called from the network join command
- * preparation routine.
- *
- * If the IE buffer has been setup by the application, this routine appends
- * the buffer as a WPS TLV type to the request.
- */
-static int
-mwifiex_cmd_append_wps_ie(struct mwifiex_private *priv, u8 **buffer)
-{
-       int retLen = 0;
-       struct mwifiex_ie_types_header ie_header;
-
-       if (!buffer || !*buffer)
-               return 0;
-
-       /*
-        * If there is a wps ie buffer setup, append it to the return
-        * parameter buffer pointer.
-        */
-       if (priv->wps_ie_len) {
-               mwifiex_dbg(priv->adapter, CMD,
-                           "cmd: append wps ie %d to %p\n",
-                           priv->wps_ie_len, *buffer);
-
-               /* Wrap the generic IE buffer with a pass through TLV type */
-               ie_header.type = cpu_to_le16(TLV_TYPE_MGMT_IE);
-               ie_header.len = cpu_to_le16(priv->wps_ie_len);
-               memcpy(*buffer, &ie_header, sizeof(ie_header));
-               *buffer += sizeof(ie_header);
-               retLen += sizeof(ie_header);
-
-               memcpy(*buffer, priv->wps_ie, priv->wps_ie_len);
-               *buffer += priv->wps_ie_len;
-               retLen += priv->wps_ie_len;
-
-       }
-
-       kfree(priv->wps_ie);
-       priv->wps_ie_len = 0;
-       return retLen;
-}
-
-/*
- * This function appends a WAPI IE.
- *
- * This function is called from the network join command preparation routine.
- *
- * If the IE buffer has been setup by the application, this routine appends
- * the buffer as a WAPI TLV type to the request.
- */
-static int
-mwifiex_cmd_append_wapi_ie(struct mwifiex_private *priv, u8 **buffer)
-{
-       int retLen = 0;
-       struct mwifiex_ie_types_header ie_header;
-
-       /* Null Checks */
-       if (buffer == NULL)
-               return 0;
-       if (*buffer == NULL)
-               return 0;
-
-       /*
-        * If there is a wapi ie buffer setup, append it to the return
-        *   parameter buffer pointer.
-        */
-       if (priv->wapi_ie_len) {
-               mwifiex_dbg(priv->adapter, CMD,
-                           "cmd: append wapi ie %d to %p\n",
-                           priv->wapi_ie_len, *buffer);
-
-               /* Wrap the generic IE buffer with a pass through TLV type */
-               ie_header.type = cpu_to_le16(TLV_TYPE_WAPI_IE);
-               ie_header.len = cpu_to_le16(priv->wapi_ie_len);
-               memcpy(*buffer, &ie_header, sizeof(ie_header));
-
-               /* Increment the return size and the return buffer pointer
-                  param */
-               *buffer += sizeof(ie_header);
-               retLen += sizeof(ie_header);
-
-               /* Copy the wapi IE buffer to the output buffer, advance
-                  pointer */
-               memcpy(*buffer, priv->wapi_ie, priv->wapi_ie_len);
-
-               /* Increment the return size and the return buffer pointer
-                  param */
-               *buffer += priv->wapi_ie_len;
-               retLen += priv->wapi_ie_len;
-
-       }
-       /* return the length appended to the buffer */
-       return retLen;
-}
-
-/*
- * This function appends rsn ie tlv for wpa/wpa2 security modes.
- * It is called from the network join command preparation routine.
- */
-static int mwifiex_append_rsn_ie_wpa_wpa2(struct mwifiex_private *priv,
-                                         u8 **buffer)
-{
-       struct mwifiex_ie_types_rsn_param_set *rsn_ie_tlv;
-       int rsn_ie_len;
-
-       if (!buffer || !(*buffer))
-               return 0;
-
-       rsn_ie_tlv = (struct mwifiex_ie_types_rsn_param_set *) (*buffer);
-       rsn_ie_tlv->header.type = cpu_to_le16((u16) priv->wpa_ie[0]);
-       rsn_ie_tlv->header.type = cpu_to_le16(
-                                le16_to_cpu(rsn_ie_tlv->header.type) & 0x00FF);
-       rsn_ie_tlv->header.len = cpu_to_le16((u16) priv->wpa_ie[1]);
-       rsn_ie_tlv->header.len = cpu_to_le16(le16_to_cpu(rsn_ie_tlv->header.len)
-                                                        & 0x00FF);
-       if (le16_to_cpu(rsn_ie_tlv->header.len) <= (sizeof(priv->wpa_ie) - 2))
-               memcpy(rsn_ie_tlv->rsn_ie, &priv->wpa_ie[2],
-                      le16_to_cpu(rsn_ie_tlv->header.len));
-       else
-               return -1;
-
-       rsn_ie_len = sizeof(rsn_ie_tlv->header) +
-                                       le16_to_cpu(rsn_ie_tlv->header.len);
-       *buffer += rsn_ie_len;
-
-       return rsn_ie_len;
-}
-
-/*
- * This function prepares command for association.
- *
- * This sets the following parameters -
- *      - Peer MAC address
- *      - Listen interval
- *      - Beacon interval
- *      - Capability information
- *
- * ...and the following TLVs, as required -
- *      - SSID TLV
- *      - PHY TLV
- *      - SS TLV
- *      - Rates TLV
- *      - Authentication TLV
- *      - Channel TLV
- *      - WPA/WPA2 IE
- *      - 11n TLV
- *      - Vendor specific TLV
- *      - WMM TLV
- *      - WAPI IE
- *      - Generic IE
- *      - TSF TLV
- *
- * Preparation also includes -
- *      - Setting command ID and proper size
- *      - Ensuring correct endian-ness
- */
-int mwifiex_cmd_802_11_associate(struct mwifiex_private *priv,
-                                struct host_cmd_ds_command *cmd,
-                                struct mwifiex_bssdescriptor *bss_desc)
-{
-       struct host_cmd_ds_802_11_associate *assoc = &cmd->params.associate;
-       struct mwifiex_ie_types_ssid_param_set *ssid_tlv;
-       struct mwifiex_ie_types_phy_param_set *phy_tlv;
-       struct mwifiex_ie_types_ss_param_set *ss_tlv;
-       struct mwifiex_ie_types_rates_param_set *rates_tlv;
-       struct mwifiex_ie_types_auth_type *auth_tlv;
-       struct mwifiex_ie_types_chan_list_param_set *chan_tlv;
-       u8 rates[MWIFIEX_SUPPORTED_RATES];
-       u32 rates_size;
-       u16 tmp_cap;
-       u8 *pos;
-       int rsn_ie_len = 0;
-
-       pos = (u8 *) assoc;
-
-       cmd->command = cpu_to_le16(HostCmd_CMD_802_11_ASSOCIATE);
-
-       /* Save so we know which BSS Desc to use in the response handler */
-       priv->attempted_bss_desc = bss_desc;
-
-       memcpy(assoc->peer_sta_addr,
-              bss_desc->mac_address, sizeof(assoc->peer_sta_addr));
-       pos += sizeof(assoc->peer_sta_addr);
-
-       /* Set the listen interval */
-       assoc->listen_interval = cpu_to_le16(priv->listen_interval);
-       /* Set the beacon period */
-       assoc->beacon_period = cpu_to_le16(bss_desc->beacon_period);
-
-       pos += sizeof(assoc->cap_info_bitmap);
-       pos += sizeof(assoc->listen_interval);
-       pos += sizeof(assoc->beacon_period);
-       pos += sizeof(assoc->dtim_period);
-
-       ssid_tlv = (struct mwifiex_ie_types_ssid_param_set *) pos;
-       ssid_tlv->header.type = cpu_to_le16(WLAN_EID_SSID);
-       ssid_tlv->header.len = cpu_to_le16((u16) bss_desc->ssid.ssid_len);
-       memcpy(ssid_tlv->ssid, bss_desc->ssid.ssid,
-              le16_to_cpu(ssid_tlv->header.len));
-       pos += sizeof(ssid_tlv->header) + le16_to_cpu(ssid_tlv->header.len);
-
-       phy_tlv = (struct mwifiex_ie_types_phy_param_set *) pos;
-       phy_tlv->header.type = cpu_to_le16(WLAN_EID_DS_PARAMS);
-       phy_tlv->header.len = cpu_to_le16(sizeof(phy_tlv->fh_ds.ds_param_set));
-       memcpy(&phy_tlv->fh_ds.ds_param_set,
-              &bss_desc->phy_param_set.ds_param_set.current_chan,
-              sizeof(phy_tlv->fh_ds.ds_param_set));
-       pos += sizeof(phy_tlv->header) + le16_to_cpu(phy_tlv->header.len);
-
-       ss_tlv = (struct mwifiex_ie_types_ss_param_set *) pos;
-       ss_tlv->header.type = cpu_to_le16(WLAN_EID_CF_PARAMS);
-       ss_tlv->header.len = cpu_to_le16(sizeof(ss_tlv->cf_ibss.cf_param_set));
-       pos += sizeof(ss_tlv->header) + le16_to_cpu(ss_tlv->header.len);
-
-       /* Get the common rates supported between the driver and the BSS Desc */
-       if (mwifiex_setup_rates_from_bssdesc
-           (priv, bss_desc, rates, &rates_size))
-               return -1;
-
-       /* Save the data rates into Current BSS state structure */
-       priv->curr_bss_params.num_of_rates = rates_size;
-       memcpy(&priv->curr_bss_params.data_rates, rates, rates_size);
-
-       /* Setup the Rates TLV in the association command */
-       rates_tlv = (struct mwifiex_ie_types_rates_param_set *) pos;
-       rates_tlv->header.type = cpu_to_le16(WLAN_EID_SUPP_RATES);
-       rates_tlv->header.len = cpu_to_le16((u16) rates_size);
-       memcpy(rates_tlv->rates, rates, rates_size);
-       pos += sizeof(rates_tlv->header) + rates_size;
-       mwifiex_dbg(priv->adapter, INFO, "info: ASSOC_CMD: rates size = %d\n",
-                   rates_size);
-
-       /* Add the Authentication type to be used for Auth frames */
-       auth_tlv = (struct mwifiex_ie_types_auth_type *) pos;
-       auth_tlv->header.type = cpu_to_le16(TLV_TYPE_AUTH_TYPE);
-       auth_tlv->header.len = cpu_to_le16(sizeof(auth_tlv->auth_type));
-       if (priv->sec_info.wep_enabled)
-               auth_tlv->auth_type = cpu_to_le16(
-                               (u16) priv->sec_info.authentication_mode);
-       else
-               auth_tlv->auth_type = cpu_to_le16(NL80211_AUTHTYPE_OPEN_SYSTEM);
-
-       pos += sizeof(auth_tlv->header) + le16_to_cpu(auth_tlv->header.len);
-
-       if (IS_SUPPORT_MULTI_BANDS(priv->adapter) &&
-           !(ISSUPP_11NENABLED(priv->adapter->fw_cap_info) &&
-           (!bss_desc->disable_11n) &&
-           (priv->adapter->config_bands & BAND_GN ||
-            priv->adapter->config_bands & BAND_AN) &&
-           (bss_desc->bcn_ht_cap)
-           )
-               ) {
-               /* Append a channel TLV for the channel the attempted AP was
-                  found on */
-               chan_tlv = (struct mwifiex_ie_types_chan_list_param_set *) pos;
-               chan_tlv->header.type = cpu_to_le16(TLV_TYPE_CHANLIST);
-               chan_tlv->header.len =
-                       cpu_to_le16(sizeof(struct mwifiex_chan_scan_param_set));
-
-               memset(chan_tlv->chan_scan_param, 0x00,
-                      sizeof(struct mwifiex_chan_scan_param_set));
-               chan_tlv->chan_scan_param[0].chan_number =
-                       (bss_desc->phy_param_set.ds_param_set.current_chan);
-               mwifiex_dbg(priv->adapter, INFO, "info: Assoc: TLV Chan = %d\n",
-                           chan_tlv->chan_scan_param[0].chan_number);
-
-               chan_tlv->chan_scan_param[0].radio_type =
-                       mwifiex_band_to_radio_type((u8) bss_desc->bss_band);
-
-               mwifiex_dbg(priv->adapter, INFO, "info: Assoc: TLV Band = %d\n",
-                           chan_tlv->chan_scan_param[0].radio_type);
-               pos += sizeof(chan_tlv->header) +
-                       sizeof(struct mwifiex_chan_scan_param_set);
-       }
-
-       if (!priv->wps.session_enable) {
-               if (priv->sec_info.wpa_enabled || priv->sec_info.wpa2_enabled)
-                       rsn_ie_len = mwifiex_append_rsn_ie_wpa_wpa2(priv, &pos);
-
-               if (rsn_ie_len == -1)
-                       return -1;
-       }
-
-       if (ISSUPP_11NENABLED(priv->adapter->fw_cap_info) &&
-           (!bss_desc->disable_11n) &&
-           (priv->adapter->config_bands & BAND_GN ||
-            priv->adapter->config_bands & BAND_AN))
-               mwifiex_cmd_append_11n_tlv(priv, bss_desc, &pos);
-
-       if (ISSUPP_11ACENABLED(priv->adapter->fw_cap_info) &&
-           !bss_desc->disable_11n && !bss_desc->disable_11ac &&
-           priv->adapter->config_bands & BAND_AAC)
-               mwifiex_cmd_append_11ac_tlv(priv, bss_desc, &pos);
-
-       /* Append vendor specific IE TLV */
-       mwifiex_cmd_append_vsie_tlv(priv, MWIFIEX_VSIE_MASK_ASSOC, &pos);
-
-       mwifiex_wmm_process_association_req(priv, &pos, &bss_desc->wmm_ie,
-                                           bss_desc->bcn_ht_cap);
-       if (priv->sec_info.wapi_enabled && priv->wapi_ie_len)
-               mwifiex_cmd_append_wapi_ie(priv, &pos);
-
-       if (priv->wps.session_enable && priv->wps_ie_len)
-               mwifiex_cmd_append_wps_ie(priv, &pos);
-
-       mwifiex_cmd_append_generic_ie(priv, &pos);
-
-       mwifiex_cmd_append_tsf_tlv(priv, &pos, bss_desc);
-
-       mwifiex_11h_process_join(priv, &pos, bss_desc);
-
-       cmd->size = cpu_to_le16((u16) (pos - (u8 *) assoc) + S_DS_GEN);
-
-       /* Set the Capability info at last */
-       tmp_cap = bss_desc->cap_info_bitmap;
-
-       if (priv->adapter->config_bands == BAND_B)
-               tmp_cap &= ~WLAN_CAPABILITY_SHORT_SLOT_TIME;
-
-       tmp_cap &= CAPINFO_MASK;
-       mwifiex_dbg(priv->adapter, INFO,
-                   "info: ASSOC_CMD: tmp_cap=%4X CAPINFO_MASK=%4lX\n",
-                   tmp_cap, CAPINFO_MASK);
-       assoc->cap_info_bitmap = cpu_to_le16(tmp_cap);
-
-       return 0;
-}
-
-static const char *assoc_failure_reason_to_str(u16 cap_info)
-{
-       switch (cap_info) {
-       case CONNECT_ERR_AUTH_ERR_STA_FAILURE:
-               return "CONNECT_ERR_AUTH_ERR_STA_FAILURE";
-       case CONNECT_ERR_AUTH_MSG_UNHANDLED:
-               return "CONNECT_ERR_AUTH_MSG_UNHANDLED";
-       case CONNECT_ERR_ASSOC_ERR_TIMEOUT:
-               return "CONNECT_ERR_ASSOC_ERR_TIMEOUT";
-       case CONNECT_ERR_ASSOC_ERR_AUTH_REFUSED:
-               return "CONNECT_ERR_ASSOC_ERR_AUTH_REFUSED";
-       case CONNECT_ERR_STA_FAILURE:
-               return "CONNECT_ERR_STA_FAILURE";
-       }
-
-       return "Unknown connect failure";
-}
-/*
- * Association firmware command response handler
- *
- * The response buffer for the association command has the following
- * memory layout.
- *
- * For cases where an association response was not received (indicated
- * by the CapInfo and AId field):
- *
- *     .------------------------------------------------------------.
- *     |  Header(4 * sizeof(t_u16)):  Standard command response hdr |
- *     .------------------------------------------------------------.
- *     |  cap_info/Error Return(t_u16):                             |
- *     |           0xFFFF(-1): Internal error                       |
- *     |           0xFFFE(-2): Authentication unhandled message     |
- *     |           0xFFFD(-3): Authentication refused               |
- *     |           0xFFFC(-4): Timeout waiting for AP response      |
- *     .------------------------------------------------------------.
- *     |  status_code(t_u16):                                       |
- *     |        If cap_info is -1:                                  |
- *     |           An internal firmware failure prevented the       |
- *     |           command from being processed.  The status_code   |
- *     |           will be set to 1.                                |
- *     |                                                            |
- *     |        If cap_info is -2:                                  |
- *     |           An authentication frame was received but was     |
- *     |           not handled by the firmware.  IEEE Status        |
- *     |           code for the failure is returned.                |
- *     |                                                            |
- *     |        If cap_info is -3:                                  |
- *     |           An authentication frame was received and the     |
- *     |           status_code is the IEEE Status reported in the   |
- *     |           response.                                        |
- *     |                                                            |
- *     |        If cap_info is -4:                                  |
- *     |           (1) Association response timeout                 |
- *     |           (2) Authentication response timeout              |
- *     .------------------------------------------------------------.
- *     |  a_id(t_u16): 0xFFFF                                       |
- *     .------------------------------------------------------------.
- *
- *
- * For cases where an association response was received, the IEEE
- * standard association response frame is returned:
- *
- *     .------------------------------------------------------------.
- *     |  Header(4 * sizeof(t_u16)):  Standard command response hdr |
- *     .------------------------------------------------------------.
- *     |  cap_info(t_u16): IEEE Capability                          |
- *     .------------------------------------------------------------.
- *     |  status_code(t_u16): IEEE Status Code                      |
- *     .------------------------------------------------------------.
- *     |  a_id(t_u16): IEEE Association ID                          |
- *     .------------------------------------------------------------.
- *     |  IEEE IEs(variable): Any received IEs comprising the       |
- *     |                      remaining portion of a received       |
- *     |                      association response frame.           |
- *     .------------------------------------------------------------.
- *
- * For simplistic handling, the status_code field can be used to determine
- * an association success (0) or failure (non-zero).
- */
-int mwifiex_ret_802_11_associate(struct mwifiex_private *priv,
-                            struct host_cmd_ds_command *resp)
-{
-       struct mwifiex_adapter *adapter = priv->adapter;
-       int ret = 0;
-       struct ieee_types_assoc_rsp *assoc_rsp;
-       struct mwifiex_bssdescriptor *bss_desc;
-       bool enable_data = true;
-       u16 cap_info, status_code, aid;
-
-       assoc_rsp = (struct ieee_types_assoc_rsp *) &resp->params;
-
-       cap_info = le16_to_cpu(assoc_rsp->cap_info_bitmap);
-       status_code = le16_to_cpu(assoc_rsp->status_code);
-       aid = le16_to_cpu(assoc_rsp->a_id);
-
-       if ((aid & (BIT(15) | BIT(14))) != (BIT(15) | BIT(14)))
-               dev_err(priv->adapter->dev,
-                       "invalid AID value 0x%x; bits 15:14 not set\n",
-                       aid);
-
-       aid &= ~(BIT(15) | BIT(14));
-
-       priv->assoc_rsp_size = min(le16_to_cpu(resp->size) - S_DS_GEN,
-                                  sizeof(priv->assoc_rsp_buf));
-
-       memcpy(priv->assoc_rsp_buf, &resp->params, priv->assoc_rsp_size);
-
-       assoc_rsp->a_id = cpu_to_le16(aid);
-
-       if (status_code) {
-               priv->adapter->dbg.num_cmd_assoc_failure++;
-               mwifiex_dbg(priv->adapter, ERROR,
-                           "ASSOC_RESP: failed,\t"
-                           "status code=%d err=%#x a_id=%#x\n",
-                           status_code, cap_info,
-                           le16_to_cpu(assoc_rsp->a_id));
-
-               mwifiex_dbg(priv->adapter, ERROR, "assoc failure: reason %s\n",
-                           assoc_failure_reason_to_str(cap_info));
-               if (cap_info == CONNECT_ERR_ASSOC_ERR_TIMEOUT) {
-                       if (status_code == MWIFIEX_ASSOC_CMD_FAILURE_AUTH) {
-                               ret = WLAN_STATUS_AUTH_TIMEOUT;
-                               mwifiex_dbg(priv->adapter, ERROR,
-                                           "ASSOC_RESP: AUTH timeout\n");
-                       } else {
-                               ret = WLAN_STATUS_UNSPECIFIED_FAILURE;
-                               mwifiex_dbg(priv->adapter, ERROR,
-                                           "ASSOC_RESP: UNSPECIFIED failure\n");
-                       }
-               } else {
-                       ret = status_code;
-               }
-
-               goto done;
-       }
-
-       /* Send a Media Connected event, according to the Spec */
-       priv->media_connected = true;
-
-       priv->adapter->ps_state = PS_STATE_AWAKE;
-       priv->adapter->pps_uapsd_mode = false;
-       priv->adapter->tx_lock_flag = false;
-
-       /* Set the attempted BSSID Index to current */
-       bss_desc = priv->attempted_bss_desc;
-
-       mwifiex_dbg(priv->adapter, INFO, "info: ASSOC_RESP: %s\n",
-                   bss_desc->ssid.ssid);
-
-       /* Make a copy of current BSSID descriptor */
-       memcpy(&priv->curr_bss_params.bss_descriptor,
-              bss_desc, sizeof(struct mwifiex_bssdescriptor));
-
-       /* Update curr_bss_params */
-       priv->curr_bss_params.bss_descriptor.channel
-               = bss_desc->phy_param_set.ds_param_set.current_chan;
-
-       priv->curr_bss_params.band = (u8) bss_desc->bss_band;
-
-       if (bss_desc->wmm_ie.vend_hdr.element_id == WLAN_EID_VENDOR_SPECIFIC)
-               priv->curr_bss_params.wmm_enabled = true;
-       else
-               priv->curr_bss_params.wmm_enabled = false;
-
-       if ((priv->wmm_required || bss_desc->bcn_ht_cap) &&
-           priv->curr_bss_params.wmm_enabled)
-               priv->wmm_enabled = true;
-       else
-               priv->wmm_enabled = false;
-
-       priv->curr_bss_params.wmm_uapsd_enabled = false;
-
-       if (priv->wmm_enabled)
-               priv->curr_bss_params.wmm_uapsd_enabled
-                       = ((bss_desc->wmm_ie.qos_info_bitmap &
-                               IEEE80211_WMM_IE_AP_QOSINFO_UAPSD) ? 1 : 0);
-
-       mwifiex_dbg(priv->adapter, INFO,
-                   "info: ASSOC_RESP: curr_pkt_filter is %#x\n",
-                   priv->curr_pkt_filter);
-       if (priv->sec_info.wpa_enabled || priv->sec_info.wpa2_enabled)
-               priv->wpa_is_gtk_set = false;
-
-       if (priv->wmm_enabled) {
-               /* Don't re-enable carrier until we get the WMM_GET_STATUS
-                  event */
-               enable_data = false;
-       } else {
-               /* Since WMM is not enabled, setup the queues with the
-                  defaults */
-               mwifiex_wmm_setup_queue_priorities(priv, NULL);
-               mwifiex_wmm_setup_ac_downgrade(priv);
-       }
-
-       if (enable_data)
-               mwifiex_dbg(priv->adapter, INFO,
-                           "info: post association, re-enabling data flow\n");
-
-       /* Reset SNR/NF/RSSI values */
-       priv->data_rssi_last = 0;
-       priv->data_nf_last = 0;
-       priv->data_rssi_avg = 0;
-       priv->data_nf_avg = 0;
-       priv->bcn_rssi_last = 0;
-       priv->bcn_nf_last = 0;
-       priv->bcn_rssi_avg = 0;
-       priv->bcn_nf_avg = 0;
-       priv->rxpd_rate = 0;
-       priv->rxpd_htinfo = 0;
-
-       mwifiex_save_curr_bcn(priv);
-
-       priv->adapter->dbg.num_cmd_assoc_success++;
-
-       mwifiex_dbg(priv->adapter, INFO, "info: ASSOC_RESP: associated\n");
-
-       /* Add the ra_list here for infra mode as there will be only 1 ra
-          always */
-       mwifiex_ralist_add(priv,
-                          priv->curr_bss_params.bss_descriptor.mac_address);
-
-       if (!netif_carrier_ok(priv->netdev))
-               netif_carrier_on(priv->netdev);
-       mwifiex_wake_up_net_dev_queue(priv->netdev, adapter);
-
-       if (priv->sec_info.wpa_enabled || priv->sec_info.wpa2_enabled)
-               priv->scan_block = true;
-       else
-               priv->port_open = true;
-
-done:
-       /* Need to indicate IOCTL complete */
-       if (adapter->curr_cmd->wait_q_enabled) {
-               if (ret)
-                       adapter->cmd_wait_q.status = -1;
-               else
-                       adapter->cmd_wait_q.status = 0;
-       }
-
-       return ret;
-}
-
-/*
- * This function prepares command for ad-hoc start.
- *
- * Driver will fill up SSID, BSS mode, IBSS parameters, physical
- * parameters, probe delay, and capability information. Firmware
- * will fill up beacon period, basic rates and operational rates.
- *
- * In addition, the following TLVs are added -
- *      - Channel TLV
- *      - Vendor specific IE
- *      - WPA/WPA2 IE
- *      - HT Capabilities IE
- *      - HT Information IE
- *
- * Preparation also includes -
- *      - Setting command ID and proper size
- *      - Ensuring correct endian-ness
- */
-int
-mwifiex_cmd_802_11_ad_hoc_start(struct mwifiex_private *priv,
-                               struct host_cmd_ds_command *cmd,
-                               struct cfg80211_ssid *req_ssid)
-{
-       int rsn_ie_len = 0;
-       struct mwifiex_adapter *adapter = priv->adapter;
-       struct host_cmd_ds_802_11_ad_hoc_start *adhoc_start =
-               &cmd->params.adhoc_start;
-       struct mwifiex_bssdescriptor *bss_desc;
-       u32 cmd_append_size = 0;
-       u32 i;
-       u16 tmp_cap;
-       struct mwifiex_ie_types_chan_list_param_set *chan_tlv;
-       u8 radio_type;
-
-       struct mwifiex_ie_types_htcap *ht_cap;
-       struct mwifiex_ie_types_htinfo *ht_info;
-       u8 *pos = (u8 *) adhoc_start +
-                       sizeof(struct host_cmd_ds_802_11_ad_hoc_start);
-
-       if (!adapter)
-               return -1;
-
-       cmd->command = cpu_to_le16(HostCmd_CMD_802_11_AD_HOC_START);
-
-       bss_desc = &priv->curr_bss_params.bss_descriptor;
-       priv->attempted_bss_desc = bss_desc;
-
-       /*
-        * Fill in the parameters for 2 data structures:
-        *   1. struct host_cmd_ds_802_11_ad_hoc_start command
-        *   2. bss_desc
-        * Driver will fill up SSID, bss_mode,IBSS param, Physical Param,
-        * probe delay, and Cap info.
-        * Firmware will fill up beacon period, Basic rates
-        * and operational rates.
-        */
-
-       memset(adhoc_start->ssid, 0, IEEE80211_MAX_SSID_LEN);
-
-       memcpy(adhoc_start->ssid, req_ssid->ssid, req_ssid->ssid_len);
-
-       mwifiex_dbg(adapter, INFO, "info: ADHOC_S_CMD: SSID = %s\n",
-                   adhoc_start->ssid);
-
-       memset(bss_desc->ssid.ssid, 0, IEEE80211_MAX_SSID_LEN);
-       memcpy(bss_desc->ssid.ssid, req_ssid->ssid, req_ssid->ssid_len);
-
-       bss_desc->ssid.ssid_len = req_ssid->ssid_len;
-
-       /* Set the BSS mode */
-       adhoc_start->bss_mode = HostCmd_BSS_MODE_IBSS;
-       bss_desc->bss_mode = NL80211_IFTYPE_ADHOC;
-       adhoc_start->beacon_period = cpu_to_le16(priv->beacon_period);
-       bss_desc->beacon_period = priv->beacon_period;
-
-       /* Set Physical param set */
-/* Parameter IE Id */
-#define DS_PARA_IE_ID   3
-/* Parameter IE length */
-#define DS_PARA_IE_LEN  1
-
-       adhoc_start->phy_param_set.ds_param_set.element_id = DS_PARA_IE_ID;
-       adhoc_start->phy_param_set.ds_param_set.len = DS_PARA_IE_LEN;
-
-       if (!mwifiex_get_cfp(priv, adapter->adhoc_start_band,
-                            (u16) priv->adhoc_channel, 0)) {
-               struct mwifiex_chan_freq_power *cfp;
-               cfp = mwifiex_get_cfp(priv, adapter->adhoc_start_band,
-                                     FIRST_VALID_CHANNEL, 0);
-               if (cfp)
-                       priv->adhoc_channel = (u8) cfp->channel;
-       }
-
-       if (!priv->adhoc_channel) {
-               mwifiex_dbg(adapter, ERROR,
-                           "ADHOC_S_CMD: adhoc_channel cannot be 0\n");
-               return -1;
-       }
-
-       mwifiex_dbg(adapter, INFO,
-                   "info: ADHOC_S_CMD: creating ADHOC on channel %d\n",
-                   priv->adhoc_channel);
-
-       priv->curr_bss_params.bss_descriptor.channel = priv->adhoc_channel;
-       priv->curr_bss_params.band = adapter->adhoc_start_band;
-
-       bss_desc->channel = priv->adhoc_channel;
-       adhoc_start->phy_param_set.ds_param_set.current_chan =
-               priv->adhoc_channel;
-
-       memcpy(&bss_desc->phy_param_set, &adhoc_start->phy_param_set,
-              sizeof(union ieee_types_phy_param_set));
-
-       /* Set IBSS param set */
-/* IBSS parameter IE Id */
-#define IBSS_PARA_IE_ID   6
-/* IBSS parameter IE length */
-#define IBSS_PARA_IE_LEN  2
-
-       adhoc_start->ss_param_set.ibss_param_set.element_id = IBSS_PARA_IE_ID;
-       adhoc_start->ss_param_set.ibss_param_set.len = IBSS_PARA_IE_LEN;
-       adhoc_start->ss_param_set.ibss_param_set.atim_window
-                                       = cpu_to_le16(priv->atim_window);
-       memcpy(&bss_desc->ss_param_set, &adhoc_start->ss_param_set,
-              sizeof(union ieee_types_ss_param_set));
-
-       /* Set Capability info */
-       bss_desc->cap_info_bitmap |= WLAN_CAPABILITY_IBSS;
-       tmp_cap = WLAN_CAPABILITY_IBSS;
-
-       /* Set up privacy in bss_desc */
-       if (priv->sec_info.encryption_mode) {
-               /* Ad-Hoc capability privacy on */
-               mwifiex_dbg(adapter, INFO,
-                           "info: ADHOC_S_CMD: wep_status set privacy to WEP\n");
-               bss_desc->privacy = MWIFIEX_802_11_PRIV_FILTER_8021X_WEP;
-               tmp_cap |= WLAN_CAPABILITY_PRIVACY;
-       } else {
-               mwifiex_dbg(adapter, INFO,
-                           "info: ADHOC_S_CMD: wep_status NOT set,\t"
-                           "setting privacy to ACCEPT ALL\n");
-               bss_desc->privacy = MWIFIEX_802_11_PRIV_FILTER_ACCEPT_ALL;
-       }
-
-       memset(adhoc_start->data_rate, 0, sizeof(adhoc_start->data_rate));
-       mwifiex_get_active_data_rates(priv, adhoc_start->data_rate);
-       if ((adapter->adhoc_start_band & BAND_G) &&
-           (priv->curr_pkt_filter & HostCmd_ACT_MAC_ADHOC_G_PROTECTION_ON)) {
-               if (mwifiex_send_cmd(priv, HostCmd_CMD_MAC_CONTROL,
-                                    HostCmd_ACT_GEN_SET, 0,
-                                    &priv->curr_pkt_filter, false)) {
-                       mwifiex_dbg(adapter, ERROR,
-                                   "ADHOC_S_CMD: G Protection config failed\n");
-                       return -1;
-               }
-       }
-       /* Find the last non zero */
-       for (i = 0; i < sizeof(adhoc_start->data_rate); i++)
-               if (!adhoc_start->data_rate[i])
-                       break;
-
-       priv->curr_bss_params.num_of_rates = i;
-
-       /* Copy the ad-hoc creating rates into Current BSS rate structure */
-       memcpy(&priv->curr_bss_params.data_rates,
-              &adhoc_start->data_rate, priv->curr_bss_params.num_of_rates);
-
-       mwifiex_dbg(adapter, INFO, "info: ADHOC_S_CMD: rates=%4ph\n",
-                   adhoc_start->data_rate);
-
-       mwifiex_dbg(adapter, INFO, "info: ADHOC_S_CMD: AD-HOC Start command is ready\n");
-
-       if (IS_SUPPORT_MULTI_BANDS(adapter)) {
-               /* Append a channel TLV */
-               chan_tlv = (struct mwifiex_ie_types_chan_list_param_set *) pos;
-               chan_tlv->header.type = cpu_to_le16(TLV_TYPE_CHANLIST);
-               chan_tlv->header.len =
-                       cpu_to_le16(sizeof(struct mwifiex_chan_scan_param_set));
-
-               memset(chan_tlv->chan_scan_param, 0x00,
-                      sizeof(struct mwifiex_chan_scan_param_set));
-               chan_tlv->chan_scan_param[0].chan_number =
-                       (u8) priv->curr_bss_params.bss_descriptor.channel;
-
-               mwifiex_dbg(adapter, INFO, "info: ADHOC_S_CMD: TLV Chan = %d\n",
-                           chan_tlv->chan_scan_param[0].chan_number);
-
-               chan_tlv->chan_scan_param[0].radio_type
-                      = mwifiex_band_to_radio_type(priv->curr_bss_params.band);
-               if (adapter->adhoc_start_band & BAND_GN ||
-                   adapter->adhoc_start_band & BAND_AN) {
-                       if (adapter->sec_chan_offset ==
-                                           IEEE80211_HT_PARAM_CHA_SEC_ABOVE)
-                               chan_tlv->chan_scan_param[0].radio_type |=
-                                       (IEEE80211_HT_PARAM_CHA_SEC_ABOVE << 4);
-                       else if (adapter->sec_chan_offset ==
-                                           IEEE80211_HT_PARAM_CHA_SEC_BELOW)
-                               chan_tlv->chan_scan_param[0].radio_type |=
-                                       (IEEE80211_HT_PARAM_CHA_SEC_BELOW << 4);
-               }
-               mwifiex_dbg(adapter, INFO, "info: ADHOC_S_CMD: TLV Band = %d\n",
-                           chan_tlv->chan_scan_param[0].radio_type);
-               pos += sizeof(chan_tlv->header) +
-                       sizeof(struct mwifiex_chan_scan_param_set);
-               cmd_append_size +=
-                       sizeof(chan_tlv->header) +
-                       sizeof(struct mwifiex_chan_scan_param_set);
-       }
-
-       /* Append vendor specific IE TLV */
-       cmd_append_size += mwifiex_cmd_append_vsie_tlv(priv,
-                               MWIFIEX_VSIE_MASK_ADHOC, &pos);
-
-       if (priv->sec_info.wpa_enabled) {
-               rsn_ie_len = mwifiex_append_rsn_ie_wpa_wpa2(priv, &pos);
-               if (rsn_ie_len == -1)
-                       return -1;
-               cmd_append_size += rsn_ie_len;
-       }
-
-       if (adapter->adhoc_11n_enabled) {
-               /* Fill HT CAPABILITY */
-               ht_cap = (struct mwifiex_ie_types_htcap *) pos;
-               memset(ht_cap, 0, sizeof(struct mwifiex_ie_types_htcap));
-               ht_cap->header.type = cpu_to_le16(WLAN_EID_HT_CAPABILITY);
-               ht_cap->header.len =
-                      cpu_to_le16(sizeof(struct ieee80211_ht_cap));
-               radio_type = mwifiex_band_to_radio_type(
-                                       priv->adapter->config_bands);
-               mwifiex_fill_cap_info(priv, radio_type, &ht_cap->ht_cap);
-
-               if (adapter->sec_chan_offset ==
-                                       IEEE80211_HT_PARAM_CHA_SEC_NONE) {
-                       u16 tmp_ht_cap;
-
-                       tmp_ht_cap = le16_to_cpu(ht_cap->ht_cap.cap_info);
-                       tmp_ht_cap &= ~IEEE80211_HT_CAP_SUP_WIDTH_20_40;
-                       tmp_ht_cap &= ~IEEE80211_HT_CAP_SGI_40;
-                       ht_cap->ht_cap.cap_info = cpu_to_le16(tmp_ht_cap);
-               }
-
-               pos += sizeof(struct mwifiex_ie_types_htcap);
-               cmd_append_size += sizeof(struct mwifiex_ie_types_htcap);
-
-               /* Fill HT INFORMATION */
-               ht_info = (struct mwifiex_ie_types_htinfo *) pos;
-               memset(ht_info, 0, sizeof(struct mwifiex_ie_types_htinfo));
-               ht_info->header.type = cpu_to_le16(WLAN_EID_HT_OPERATION);
-               ht_info->header.len =
-                       cpu_to_le16(sizeof(struct ieee80211_ht_operation));
-
-               ht_info->ht_oper.primary_chan =
-                       (u8) priv->curr_bss_params.bss_descriptor.channel;
-               if (adapter->sec_chan_offset) {
-                       ht_info->ht_oper.ht_param = adapter->sec_chan_offset;
-                       ht_info->ht_oper.ht_param |=
-                                       IEEE80211_HT_PARAM_CHAN_WIDTH_ANY;
-               }
-               ht_info->ht_oper.operation_mode =
-                    cpu_to_le16(IEEE80211_HT_OP_MODE_NON_GF_STA_PRSNT);
-               ht_info->ht_oper.basic_set[0] = 0xff;
-               pos += sizeof(struct mwifiex_ie_types_htinfo);
-               cmd_append_size +=
-                               sizeof(struct mwifiex_ie_types_htinfo);
-       }
-
-       cmd->size =
-               cpu_to_le16((u16)(sizeof(struct host_cmd_ds_802_11_ad_hoc_start)
-                                 + S_DS_GEN + cmd_append_size));
-
-       if (adapter->adhoc_start_band == BAND_B)
-               tmp_cap &= ~WLAN_CAPABILITY_SHORT_SLOT_TIME;
-       else
-               tmp_cap |= WLAN_CAPABILITY_SHORT_SLOT_TIME;
-
-       adhoc_start->cap_info_bitmap = cpu_to_le16(tmp_cap);
-
-       return 0;
-}
-
-/*
- * This function prepares command for ad-hoc join.
- *
- * Most of the parameters are set up by copying from the target BSS descriptor
- * from the scan response.
- *
- * In addition, the following TLVs are added -
- *      - Channel TLV
- *      - Vendor specific IE
- *      - WPA/WPA2 IE
- *      - 11n IE
- *
- * Preparation also includes -
- *      - Setting command ID and proper size
- *      - Ensuring correct endian-ness
- */
-int
-mwifiex_cmd_802_11_ad_hoc_join(struct mwifiex_private *priv,
-                              struct host_cmd_ds_command *cmd,
-                              struct mwifiex_bssdescriptor *bss_desc)
-{
-       int rsn_ie_len = 0;
-       struct host_cmd_ds_802_11_ad_hoc_join *adhoc_join =
-               &cmd->params.adhoc_join;
-       struct mwifiex_ie_types_chan_list_param_set *chan_tlv;
-       u32 cmd_append_size = 0;
-       u16 tmp_cap;
-       u32 i, rates_size = 0;
-       u16 curr_pkt_filter;
-       u8 *pos =
-               (u8 *) adhoc_join +
-               sizeof(struct host_cmd_ds_802_11_ad_hoc_join);
-
-/* Use G protection */
-#define USE_G_PROTECTION        0x02
-       if (bss_desc->erp_flags & USE_G_PROTECTION) {
-               curr_pkt_filter =
-                       priv->
-                       curr_pkt_filter | HostCmd_ACT_MAC_ADHOC_G_PROTECTION_ON;
-
-               if (mwifiex_send_cmd(priv, HostCmd_CMD_MAC_CONTROL,
-                                    HostCmd_ACT_GEN_SET, 0,
-                                    &curr_pkt_filter, false)) {
-                       mwifiex_dbg(priv->adapter, ERROR,
-                                   "ADHOC_J_CMD: G Protection config failed\n");
-                       return -1;
-               }
-       }
-
-       priv->attempted_bss_desc = bss_desc;
-
-       cmd->command = cpu_to_le16(HostCmd_CMD_802_11_AD_HOC_JOIN);
-
-       adhoc_join->bss_descriptor.bss_mode = HostCmd_BSS_MODE_IBSS;
-
-       adhoc_join->bss_descriptor.beacon_period
-               = cpu_to_le16(bss_desc->beacon_period);
-
-       memcpy(&adhoc_join->bss_descriptor.bssid,
-              &bss_desc->mac_address, ETH_ALEN);
-
-       memcpy(&adhoc_join->bss_descriptor.ssid,
-              &bss_desc->ssid.ssid, bss_desc->ssid.ssid_len);
-
-       memcpy(&adhoc_join->bss_descriptor.phy_param_set,
-              &bss_desc->phy_param_set,
-              sizeof(union ieee_types_phy_param_set));
-
-       memcpy(&adhoc_join->bss_descriptor.ss_param_set,
-              &bss_desc->ss_param_set, sizeof(union ieee_types_ss_param_set));
-
-       tmp_cap = bss_desc->cap_info_bitmap;
-
-       tmp_cap &= CAPINFO_MASK;
-
-       mwifiex_dbg(priv->adapter, INFO,
-                   "info: ADHOC_J_CMD: tmp_cap=%4X CAPINFO_MASK=%4lX\n",
-                   tmp_cap, CAPINFO_MASK);
-
-       /* Information on BSSID descriptor passed to FW */
-       mwifiex_dbg(priv->adapter, INFO,
-                   "info: ADHOC_J_CMD: BSSID=%pM, SSID='%s'\n",
-                   adhoc_join->bss_descriptor.bssid,
-                   adhoc_join->bss_descriptor.ssid);
-
-       for (i = 0; i < MWIFIEX_SUPPORTED_RATES &&
-                   bss_desc->supported_rates[i]; i++)
-               ;
-       rates_size = i;
-
-       /* Copy Data Rates from the Rates recorded in scan response */
-       memset(adhoc_join->bss_descriptor.data_rates, 0,
-              sizeof(adhoc_join->bss_descriptor.data_rates));
-       memcpy(adhoc_join->bss_descriptor.data_rates,
-              bss_desc->supported_rates, rates_size);
-
-       /* Copy the adhoc join rates into Current BSS state structure */
-       priv->curr_bss_params.num_of_rates = rates_size;
-       memcpy(&priv->curr_bss_params.data_rates, bss_desc->supported_rates,
-              rates_size);
-
-       /* Copy the channel information */
-       priv->curr_bss_params.bss_descriptor.channel = bss_desc->channel;
-       priv->curr_bss_params.band = (u8) bss_desc->bss_band;
-
-       if (priv->sec_info.wep_enabled || priv->sec_info.wpa_enabled)
-               tmp_cap |= WLAN_CAPABILITY_PRIVACY;
-
-       if (IS_SUPPORT_MULTI_BANDS(priv->adapter)) {
-               /* Append a channel TLV */
-               chan_tlv = (struct mwifiex_ie_types_chan_list_param_set *) pos;
-               chan_tlv->header.type = cpu_to_le16(TLV_TYPE_CHANLIST);
-               chan_tlv->header.len =
-                       cpu_to_le16(sizeof(struct mwifiex_chan_scan_param_set));
-
-               memset(chan_tlv->chan_scan_param, 0x00,
-                      sizeof(struct mwifiex_chan_scan_param_set));
-               chan_tlv->chan_scan_param[0].chan_number =
-                       (bss_desc->phy_param_set.ds_param_set.current_chan);
-               mwifiex_dbg(priv->adapter, INFO, "info: ADHOC_J_CMD: TLV Chan=%d\n",
-                           chan_tlv->chan_scan_param[0].chan_number);
-
-               chan_tlv->chan_scan_param[0].radio_type =
-                       mwifiex_band_to_radio_type((u8) bss_desc->bss_band);
-
-               mwifiex_dbg(priv->adapter, INFO, "info: ADHOC_J_CMD: TLV Band=%d\n",
-                           chan_tlv->chan_scan_param[0].radio_type);
-               pos += sizeof(chan_tlv->header) +
-                               sizeof(struct mwifiex_chan_scan_param_set);
-               cmd_append_size += sizeof(chan_tlv->header) +
-                               sizeof(struct mwifiex_chan_scan_param_set);
-       }
-
-       if (priv->sec_info.wpa_enabled)
-               rsn_ie_len = mwifiex_append_rsn_ie_wpa_wpa2(priv, &pos);
-       if (rsn_ie_len == -1)
-               return -1;
-       cmd_append_size += rsn_ie_len;
-
-       if (ISSUPP_11NENABLED(priv->adapter->fw_cap_info))
-               cmd_append_size += mwifiex_cmd_append_11n_tlv(priv,
-                       bss_desc, &pos);
-
-       /* Append vendor specific IE TLV */
-       cmd_append_size += mwifiex_cmd_append_vsie_tlv(priv,
-                       MWIFIEX_VSIE_MASK_ADHOC, &pos);
-
-       cmd->size = cpu_to_le16
-               ((u16) (sizeof(struct host_cmd_ds_802_11_ad_hoc_join)
-                       + S_DS_GEN + cmd_append_size));
-
-       adhoc_join->bss_descriptor.cap_info_bitmap = cpu_to_le16(tmp_cap);
-
-       return 0;
-}
-
-/*
- * This function handles the command response of ad-hoc start and
- * ad-hoc join.
- *
- * The function generates a device-connected event to notify
- * the applications, in case of successful ad-hoc start/join, and
- * saves the beacon buffer.
- */
-int mwifiex_ret_802_11_ad_hoc(struct mwifiex_private *priv,
-                             struct host_cmd_ds_command *resp)
-{
-       int ret = 0;
-       struct mwifiex_adapter *adapter = priv->adapter;
-       struct host_cmd_ds_802_11_ad_hoc_result *adhoc_result;
-       struct mwifiex_bssdescriptor *bss_desc;
-       u16 reason_code;
-
-       adhoc_result = &resp->params.adhoc_result;
-
-       bss_desc = priv->attempted_bss_desc;
-
-       /* Join result code 0 --> SUCCESS */
-       reason_code = le16_to_cpu(resp->result);
-       if (reason_code) {
-               mwifiex_dbg(priv->adapter, ERROR, "ADHOC_RESP: failed\n");
-               if (priv->media_connected)
-                       mwifiex_reset_connect_state(priv, reason_code);
-
-               memset(&priv->curr_bss_params.bss_descriptor,
-                      0x00, sizeof(struct mwifiex_bssdescriptor));
-
-               ret = -1;
-               goto done;
-       }
-
-       /* Send a Media Connected event, according to the Spec */
-       priv->media_connected = true;
-
-       if (le16_to_cpu(resp->command) == HostCmd_CMD_802_11_AD_HOC_START) {
-               mwifiex_dbg(priv->adapter, INFO, "info: ADHOC_S_RESP %s\n",
-                           bss_desc->ssid.ssid);
-
-               /* Update the created network descriptor with the new BSSID */
-               memcpy(bss_desc->mac_address,
-                      adhoc_result->bssid, ETH_ALEN);
-
-               priv->adhoc_state = ADHOC_STARTED;
-       } else {
-               /*
-                * Now the join cmd should be successful.
-                * If BSSID has changed use SSID to compare instead of BSSID
-                */
-               mwifiex_dbg(priv->adapter, INFO,
-                           "info: ADHOC_J_RESP %s\n",
-                           bss_desc->ssid.ssid);
-
-               /*
-                * Make a copy of current BSSID descriptor, only needed for
-                * join since the current descriptor is already being used
-                * for adhoc start
-                */
-               memcpy(&priv->curr_bss_params.bss_descriptor,
-                      bss_desc, sizeof(struct mwifiex_bssdescriptor));
-
-               priv->adhoc_state = ADHOC_JOINED;
-       }
-
-       mwifiex_dbg(priv->adapter, INFO, "info: ADHOC_RESP: channel = %d\n",
-                   priv->adhoc_channel);
-       mwifiex_dbg(priv->adapter, INFO, "info: ADHOC_RESP: BSSID = %pM\n",
-                   priv->curr_bss_params.bss_descriptor.mac_address);
-
-       if (!netif_carrier_ok(priv->netdev))
-               netif_carrier_on(priv->netdev);
-       mwifiex_wake_up_net_dev_queue(priv->netdev, adapter);
-
-       mwifiex_save_curr_bcn(priv);
-
-done:
-       /* Need to indicate IOCTL complete */
-       if (adapter->curr_cmd->wait_q_enabled) {
-               if (ret)
-                       adapter->cmd_wait_q.status = -1;
-               else
-                       adapter->cmd_wait_q.status = 0;
-
-       }
-
-       return ret;
-}
-
-/*
- * This function associates to a specific BSS discovered in a scan.
- *
- * It clears any past association response stored for application
- * retrieval and calls the command preparation routine to send the
- * command to firmware.
- */
-int mwifiex_associate(struct mwifiex_private *priv,
-                     struct mwifiex_bssdescriptor *bss_desc)
-{
-       /* Return error if the adapter is not STA role or table entry
-        * is not marked as infra.
-        */
-       if ((GET_BSS_ROLE(priv) != MWIFIEX_BSS_ROLE_STA) ||
-           (bss_desc->bss_mode != NL80211_IFTYPE_STATION))
-               return -1;
-
-       if (ISSUPP_11ACENABLED(priv->adapter->fw_cap_info) &&
-           !bss_desc->disable_11n && !bss_desc->disable_11ac &&
-           priv->adapter->config_bands & BAND_AAC)
-               mwifiex_set_11ac_ba_params(priv);
-       else
-               mwifiex_set_ba_params(priv);
-
-       /* Clear any past association response stored for application
-          retrieval */
-       priv->assoc_rsp_size = 0;
-
-       return mwifiex_send_cmd(priv, HostCmd_CMD_802_11_ASSOCIATE,
-                               HostCmd_ACT_GEN_SET, 0, bss_desc, true);
-}
-
-/*
- * This function starts an ad-hoc network.
- *
- * It calls the command preparation routine to send the command to firmware.
- */
-int
-mwifiex_adhoc_start(struct mwifiex_private *priv,
-                   struct cfg80211_ssid *adhoc_ssid)
-{
-       mwifiex_dbg(priv->adapter, INFO, "info: Adhoc Channel = %d\n",
-                   priv->adhoc_channel);
-       mwifiex_dbg(priv->adapter, INFO, "info: curr_bss_params.channel = %d\n",
-                   priv->curr_bss_params.bss_descriptor.channel);
-       mwifiex_dbg(priv->adapter, INFO, "info: curr_bss_params.band = %d\n",
-                   priv->curr_bss_params.band);
-
-       if (ISSUPP_11ACENABLED(priv->adapter->fw_cap_info) &&
-           priv->adapter->config_bands & BAND_AAC)
-               mwifiex_set_11ac_ba_params(priv);
-       else
-               mwifiex_set_ba_params(priv);
-
-       return mwifiex_send_cmd(priv, HostCmd_CMD_802_11_AD_HOC_START,
-                               HostCmd_ACT_GEN_SET, 0, adhoc_ssid, true);
-}
-
-/*
- * This function joins an ad-hoc network found in a previous scan.
- *
- * It calls the command preparation routine to send the command to firmware,
- * if already not connected to the requested SSID.
- */
-int mwifiex_adhoc_join(struct mwifiex_private *priv,
-                      struct mwifiex_bssdescriptor *bss_desc)
-{
-       mwifiex_dbg(priv->adapter, INFO,
-                   "info: adhoc join: curr_bss ssid =%s\n",
-                   priv->curr_bss_params.bss_descriptor.ssid.ssid);
-       mwifiex_dbg(priv->adapter, INFO,
-                   "info: adhoc join: curr_bss ssid_len =%u\n",
-                   priv->curr_bss_params.bss_descriptor.ssid.ssid_len);
-       mwifiex_dbg(priv->adapter, INFO, "info: adhoc join: ssid =%s\n",
-                   bss_desc->ssid.ssid);
-       mwifiex_dbg(priv->adapter, INFO, "info: adhoc join: ssid_len =%u\n",
-                   bss_desc->ssid.ssid_len);
-
-       /* Check if the requested SSID is already joined */
-       if (priv->curr_bss_params.bss_descriptor.ssid.ssid_len &&
-           !mwifiex_ssid_cmp(&bss_desc->ssid,
-                             &priv->curr_bss_params.bss_descriptor.ssid) &&
-           (priv->curr_bss_params.bss_descriptor.bss_mode ==
-                                                       NL80211_IFTYPE_ADHOC)) {
-               mwifiex_dbg(priv->adapter, INFO,
-                           "info: ADHOC_J_CMD: new ad-hoc SSID\t"
-                           "is the same as current; not attempting to re-join\n");
-               return -1;
-       }
-
-       if (ISSUPP_11ACENABLED(priv->adapter->fw_cap_info) &&
-           !bss_desc->disable_11n && !bss_desc->disable_11ac &&
-           priv->adapter->config_bands & BAND_AAC)
-               mwifiex_set_11ac_ba_params(priv);
-       else
-               mwifiex_set_ba_params(priv);
-
-       mwifiex_dbg(priv->adapter, INFO,
-                   "info: curr_bss_params.channel = %d\n",
-                   priv->curr_bss_params.bss_descriptor.channel);
-       mwifiex_dbg(priv->adapter, INFO,
-                   "info: curr_bss_params.band = %c\n",
-                   priv->curr_bss_params.band);
-
-       return mwifiex_send_cmd(priv, HostCmd_CMD_802_11_AD_HOC_JOIN,
-                               HostCmd_ACT_GEN_SET, 0, bss_desc, true);
-}
-
-/*
- * This function deauthenticates/disconnects from infra network by sending
- * deauthentication request.
- */
-static int mwifiex_deauthenticate_infra(struct mwifiex_private *priv, u8 *mac)
-{
-       u8 mac_address[ETH_ALEN];
-       int ret;
-
-       if (!mac || is_zero_ether_addr(mac))
-               memcpy(mac_address,
-                      priv->curr_bss_params.bss_descriptor.mac_address,
-                      ETH_ALEN);
-       else
-               memcpy(mac_address, mac, ETH_ALEN);
-
-       ret = mwifiex_send_cmd(priv, HostCmd_CMD_802_11_DEAUTHENTICATE,
-                              HostCmd_ACT_GEN_SET, 0, mac_address, true);
-
-       return ret;
-}
-
-/*
- * This function deauthenticates/disconnects from a BSS.
- *
- * In case of infra made, it sends deauthentication request, and
- * in case of ad-hoc mode, a stop network request is sent to the firmware.
- * In AP mode, a command to stop bss is sent to firmware.
- */
-int mwifiex_deauthenticate(struct mwifiex_private *priv, u8 *mac)
-{
-       int ret = 0;
-
-       if (!priv->media_connected)
-               return 0;
-
-       switch (priv->bss_mode) {
-       case NL80211_IFTYPE_STATION:
-       case NL80211_IFTYPE_P2P_CLIENT:
-               ret = mwifiex_deauthenticate_infra(priv, mac);
-               if (ret)
-                       cfg80211_disconnected(priv->netdev, 0, NULL, 0,
-                                             true, GFP_KERNEL);
-               break;
-       case NL80211_IFTYPE_ADHOC:
-               return mwifiex_send_cmd(priv, HostCmd_CMD_802_11_AD_HOC_STOP,
-                                       HostCmd_ACT_GEN_SET, 0, NULL, true);
-       case NL80211_IFTYPE_AP:
-               return mwifiex_send_cmd(priv, HostCmd_CMD_UAP_BSS_STOP,
-                                       HostCmd_ACT_GEN_SET, 0, NULL, true);
-       default:
-               break;
-       }
-
-       return ret;
-}
-
-/* This function deauthenticates/disconnects from all BSS. */
-void mwifiex_deauthenticate_all(struct mwifiex_adapter *adapter)
-{
-       struct mwifiex_private *priv;
-       int i;
-
-       for (i = 0; i < adapter->priv_num; i++) {
-               priv = adapter->priv[i];
-               if (priv)
-                       mwifiex_deauthenticate(priv, NULL);
-       }
-}
-EXPORT_SYMBOL_GPL(mwifiex_deauthenticate_all);
-
-/*
- * This function converts band to radio type used in channel TLV.
- */
-u8
-mwifiex_band_to_radio_type(u8 band)
-{
-       switch (band) {
-       case BAND_A:
-       case BAND_AN:
-       case BAND_A | BAND_AN:
-       case BAND_A | BAND_AN | BAND_AAC:
-               return HostCmd_SCAN_RADIO_TYPE_A;
-       case BAND_B:
-       case BAND_G:
-       case BAND_B | BAND_G:
-       default:
-               return HostCmd_SCAN_RADIO_TYPE_BG;
-       }
-}
diff --git a/drivers/net/wireless/mwifiex/main.c b/drivers/net/wireless/mwifiex/main.c
deleted file mode 100644 (file)
index 969ca1e..0000000
+++ /dev/null
@@ -1,1552 +0,0 @@
-/*
- * Marvell Wireless LAN device driver: major functions
- *
- * Copyright (C) 2011-2014, Marvell International Ltd.
- *
- * This software file (the "File") is distributed by Marvell International
- * Ltd. under the terms of the GNU General Public License Version 2, June 1991
- * (the "License").  You may use, redistribute and/or modify this File in
- * accordance with the terms and conditions of the License, a copy of which
- * is available by writing to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the
- * worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
- *
- * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
- * ARE EXPRESSLY DISCLAIMED.  The License provides additional details about
- * this warranty disclaimer.
- */
-
-#include "main.h"
-#include "wmm.h"
-#include "cfg80211.h"
-#include "11n.h"
-
-#define VERSION        "1.0"
-
-static unsigned int debug_mask = MWIFIEX_DEFAULT_DEBUG_MASK;
-module_param(debug_mask, uint, 0);
-MODULE_PARM_DESC(debug_mask, "bitmap for debug flags");
-
-const char driver_version[] = "mwifiex " VERSION " (%s) ";
-static char *cal_data_cfg;
-module_param(cal_data_cfg, charp, 0);
-
-static unsigned short driver_mode;
-module_param(driver_mode, ushort, 0);
-MODULE_PARM_DESC(driver_mode,
-                "station=0x1(default), ap-sta=0x3, station-p2p=0x5, ap-sta-p2p=0x7");
-
-/*
- * This function registers the device and performs all the necessary
- * initializations.
- *
- * The following initialization operations are performed -
- *      - Allocate adapter structure
- *      - Save interface specific operations table in adapter
- *      - Call interface specific initialization routine
- *      - Allocate private structures
- *      - Set default adapter structure parameters
- *      - Initialize locks
- *
- * In case of any errors during inittialization, this function also ensures
- * proper cleanup before exiting.
- */
-static int mwifiex_register(void *card, struct mwifiex_if_ops *if_ops,
-                           void **padapter)
-{
-       struct mwifiex_adapter *adapter;
-       int i;
-
-       adapter = kzalloc(sizeof(struct mwifiex_adapter), GFP_KERNEL);
-       if (!adapter)
-               return -ENOMEM;
-
-       *padapter = adapter;
-       adapter->card = card;
-
-       /* Save interface specific operations in adapter */
-       memmove(&adapter->if_ops, if_ops, sizeof(struct mwifiex_if_ops));
-       adapter->debug_mask = debug_mask;
-
-       /* card specific initialization has been deferred until now .. */
-       if (adapter->if_ops.init_if)
-               if (adapter->if_ops.init_if(adapter))
-                       goto error;
-
-       adapter->priv_num = 0;
-
-       for (i = 0; i < MWIFIEX_MAX_BSS_NUM; i++) {
-               /* Allocate memory for private structure */
-               adapter->priv[i] =
-                       kzalloc(sizeof(struct mwifiex_private), GFP_KERNEL);
-               if (!adapter->priv[i])
-                       goto error;
-
-               adapter->priv[i]->adapter = adapter;
-               adapter->priv_num++;
-       }
-       mwifiex_init_lock_list(adapter);
-
-       setup_timer(&adapter->cmd_timer, mwifiex_cmd_timeout_func,
-                   (unsigned long)adapter);
-
-       return 0;
-
-error:
-       mwifiex_dbg(adapter, ERROR,
-                   "info: leave mwifiex_register with error\n");
-
-       for (i = 0; i < adapter->priv_num; i++)
-               kfree(adapter->priv[i]);
-
-       kfree(adapter);
-
-       return -1;
-}
-
-/*
- * This function unregisters the device and performs all the necessary
- * cleanups.
- *
- * The following cleanup operations are performed -
- *      - Free the timers
- *      - Free beacon buffers
- *      - Free private structures
- *      - Free adapter structure
- */
-static int mwifiex_unregister(struct mwifiex_adapter *adapter)
-{
-       s32 i;
-
-       if (adapter->if_ops.cleanup_if)
-               adapter->if_ops.cleanup_if(adapter);
-
-       del_timer_sync(&adapter->cmd_timer);
-
-       /* Free private structures */
-       for (i = 0; i < adapter->priv_num; i++) {
-               if (adapter->priv[i]) {
-                       mwifiex_free_curr_bcn(adapter->priv[i]);
-                       kfree(adapter->priv[i]);
-               }
-       }
-
-       vfree(adapter->chan_stats);
-       kfree(adapter);
-       return 0;
-}
-
-void mwifiex_queue_main_work(struct mwifiex_adapter *adapter)
-{
-       unsigned long flags;
-
-       spin_lock_irqsave(&adapter->main_proc_lock, flags);
-       if (adapter->mwifiex_processing) {
-               adapter->more_task_flag = true;
-               spin_unlock_irqrestore(&adapter->main_proc_lock, flags);
-       } else {
-               spin_unlock_irqrestore(&adapter->main_proc_lock, flags);
-               queue_work(adapter->workqueue, &adapter->main_work);
-       }
-}
-EXPORT_SYMBOL_GPL(mwifiex_queue_main_work);
-
-static void mwifiex_queue_rx_work(struct mwifiex_adapter *adapter)
-{
-       unsigned long flags;
-
-       spin_lock_irqsave(&adapter->rx_proc_lock, flags);
-       if (adapter->rx_processing) {
-               spin_unlock_irqrestore(&adapter->rx_proc_lock, flags);
-       } else {
-               spin_unlock_irqrestore(&adapter->rx_proc_lock, flags);
-               queue_work(adapter->rx_workqueue, &adapter->rx_work);
-       }
-}
-
-static int mwifiex_process_rx(struct mwifiex_adapter *adapter)
-{
-       unsigned long flags;
-       struct sk_buff *skb;
-       struct mwifiex_rxinfo *rx_info;
-
-       spin_lock_irqsave(&adapter->rx_proc_lock, flags);
-       if (adapter->rx_processing || adapter->rx_locked) {
-               spin_unlock_irqrestore(&adapter->rx_proc_lock, flags);
-               goto exit_rx_proc;
-       } else {
-               adapter->rx_processing = true;
-               spin_unlock_irqrestore(&adapter->rx_proc_lock, flags);
-       }
-
-       /* Check for Rx data */
-       while ((skb = skb_dequeue(&adapter->rx_data_q))) {
-               atomic_dec(&adapter->rx_pending);
-               if ((adapter->delay_main_work ||
-                    adapter->iface_type == MWIFIEX_USB) &&
-                   (atomic_read(&adapter->rx_pending) < LOW_RX_PENDING)) {
-                       if (adapter->if_ops.submit_rem_rx_urbs)
-                               adapter->if_ops.submit_rem_rx_urbs(adapter);
-                       adapter->delay_main_work = false;
-                       mwifiex_queue_main_work(adapter);
-               }
-               rx_info = MWIFIEX_SKB_RXCB(skb);
-               if (rx_info->buf_type == MWIFIEX_TYPE_AGGR_DATA) {
-                       if (adapter->if_ops.deaggr_pkt)
-                               adapter->if_ops.deaggr_pkt(adapter, skb);
-                       dev_kfree_skb_any(skb);
-               } else {
-                       mwifiex_handle_rx_packet(adapter, skb);
-               }
-       }
-       spin_lock_irqsave(&adapter->rx_proc_lock, flags);
-       adapter->rx_processing = false;
-       spin_unlock_irqrestore(&adapter->rx_proc_lock, flags);
-
-exit_rx_proc:
-       return 0;
-}
-
-/*
- * The main process.
- *
- * This function is the main procedure of the driver and handles various driver
- * operations. It runs in a loop and provides the core functionalities.
- *
- * The main responsibilities of this function are -
- *      - Ensure concurrency control
- *      - Handle pending interrupts and call interrupt handlers
- *      - Wake up the card if required
- *      - Handle command responses and call response handlers
- *      - Handle events and call event handlers
- *      - Execute pending commands
- *      - Transmit pending data packets
- */
-int mwifiex_main_process(struct mwifiex_adapter *adapter)
-{
-       int ret = 0;
-       unsigned long flags;
-
-       spin_lock_irqsave(&adapter->main_proc_lock, flags);
-
-       /* Check if already processing */
-       if (adapter->mwifiex_processing || adapter->main_locked) {
-               adapter->more_task_flag = true;
-               spin_unlock_irqrestore(&adapter->main_proc_lock, flags);
-               goto exit_main_proc;
-       } else {
-               adapter->mwifiex_processing = true;
-               spin_unlock_irqrestore(&adapter->main_proc_lock, flags);
-       }
-process_start:
-       do {
-               if ((adapter->hw_status == MWIFIEX_HW_STATUS_CLOSING) ||
-                   (adapter->hw_status == MWIFIEX_HW_STATUS_NOT_READY))
-                       break;
-
-               /* For non-USB interfaces, If we process interrupts first, it
-                * would increase RX pending even further. Avoid this by
-                * checking if rx_pending has crossed high threshold and
-                * schedule rx work queue and then process interrupts.
-                * For USB interface, there are no interrupts. We already have
-                * HIGH_RX_PENDING check in usb.c
-                */
-               if (atomic_read(&adapter->rx_pending) >= HIGH_RX_PENDING &&
-                   adapter->iface_type != MWIFIEX_USB) {
-                       adapter->delay_main_work = true;
-                       mwifiex_queue_rx_work(adapter);
-                       break;
-               }
-
-               /* Handle pending interrupt if any */
-               if (adapter->int_status) {
-                       if (adapter->hs_activated)
-                               mwifiex_process_hs_config(adapter);
-                       if (adapter->if_ops.process_int_status)
-                               adapter->if_ops.process_int_status(adapter);
-               }
-
-               if (adapter->rx_work_enabled && adapter->data_received)
-                       mwifiex_queue_rx_work(adapter);
-
-               /* Need to wake up the card ? */
-               if ((adapter->ps_state == PS_STATE_SLEEP) &&
-                   (adapter->pm_wakeup_card_req &&
-                    !adapter->pm_wakeup_fw_try) &&
-                   (is_command_pending(adapter) ||
-                    !skb_queue_empty(&adapter->tx_data_q) ||
-                    !mwifiex_bypass_txlist_empty(adapter) ||
-                    !mwifiex_wmm_lists_empty(adapter))) {
-                       adapter->pm_wakeup_fw_try = true;
-                       mod_timer(&adapter->wakeup_timer, jiffies + (HZ*3));
-                       adapter->if_ops.wakeup(adapter);
-                       continue;
-               }
-
-               if (IS_CARD_RX_RCVD(adapter)) {
-                       adapter->data_received = false;
-                       adapter->pm_wakeup_fw_try = false;
-                       del_timer(&adapter->wakeup_timer);
-                       if (adapter->ps_state == PS_STATE_SLEEP)
-                               adapter->ps_state = PS_STATE_AWAKE;
-               } else {
-                       /* We have tried to wakeup the card already */
-                       if (adapter->pm_wakeup_fw_try)
-                               break;
-                       if (adapter->ps_state != PS_STATE_AWAKE)
-                               break;
-                       if (adapter->tx_lock_flag) {
-                               if (adapter->iface_type == MWIFIEX_USB) {
-                                       if (!adapter->usb_mc_setup)
-                                               break;
-                               } else
-                                       break;
-                       }
-
-                       if ((!adapter->scan_chan_gap_enabled &&
-                            adapter->scan_processing) || adapter->data_sent ||
-                            mwifiex_is_tdls_chan_switching
-                            (mwifiex_get_priv(adapter,
-                                              MWIFIEX_BSS_ROLE_STA)) ||
-                           (mwifiex_wmm_lists_empty(adapter) &&
-                            mwifiex_bypass_txlist_empty(adapter) &&
-                            skb_queue_empty(&adapter->tx_data_q))) {
-                               if (adapter->cmd_sent || adapter->curr_cmd ||
-                                       !mwifiex_is_send_cmd_allowed
-                                               (mwifiex_get_priv(adapter,
-                                               MWIFIEX_BSS_ROLE_STA)) ||
-                                   (!is_command_pending(adapter)))
-                                       break;
-                       }
-               }
-
-               /* Check for event */
-               if (adapter->event_received) {
-                       adapter->event_received = false;
-                       mwifiex_process_event(adapter);
-               }
-
-               /* Check for Cmd Resp */
-               if (adapter->cmd_resp_received) {
-                       adapter->cmd_resp_received = false;
-                       mwifiex_process_cmdresp(adapter);
-
-                       /* call mwifiex back when init_fw is done */
-                       if (adapter->hw_status == MWIFIEX_HW_STATUS_INIT_DONE) {
-                               adapter->hw_status = MWIFIEX_HW_STATUS_READY;
-                               mwifiex_init_fw_complete(adapter);
-                       }
-               }
-
-               /* Check if we need to confirm Sleep Request
-                  received previously */
-               if (adapter->ps_state == PS_STATE_PRE_SLEEP) {
-                       if (!adapter->cmd_sent && !adapter->curr_cmd)
-                               mwifiex_check_ps_cond(adapter);
-               }
-
-               /* * The ps_state may have been changed during processing of
-                * Sleep Request event.
-                */
-               if ((adapter->ps_state == PS_STATE_SLEEP) ||
-                   (adapter->ps_state == PS_STATE_PRE_SLEEP) ||
-                   (adapter->ps_state == PS_STATE_SLEEP_CFM)) {
-                       continue;
-               }
-
-               if (adapter->tx_lock_flag) {
-                       if (adapter->iface_type == MWIFIEX_USB) {
-                               if (!adapter->usb_mc_setup)
-                                       continue;
-                       } else
-                               continue;
-               }
-
-               if (!adapter->cmd_sent && !adapter->curr_cmd &&
-                   mwifiex_is_send_cmd_allowed
-                   (mwifiex_get_priv(adapter, MWIFIEX_BSS_ROLE_STA))) {
-                       if (mwifiex_exec_next_cmd(adapter) == -1) {
-                               ret = -1;
-                               break;
-                       }
-               }
-
-               /** If USB Multi channel setup ongoing,
-                *  wait for ready to tx data.
-                */
-               if (adapter->iface_type == MWIFIEX_USB &&
-                   adapter->usb_mc_setup)
-                       continue;
-
-               if ((adapter->scan_chan_gap_enabled ||
-                    !adapter->scan_processing) &&
-                   !adapter->data_sent &&
-                   !skb_queue_empty(&adapter->tx_data_q)) {
-                       mwifiex_process_tx_queue(adapter);
-                       if (adapter->hs_activated) {
-                               adapter->is_hs_configured = false;
-                               mwifiex_hs_activated_event
-                                       (mwifiex_get_priv
-                                       (adapter, MWIFIEX_BSS_ROLE_ANY),
-                                       false);
-                       }
-               }
-
-               if ((adapter->scan_chan_gap_enabled ||
-                    !adapter->scan_processing) &&
-                   !adapter->data_sent &&
-                   !mwifiex_bypass_txlist_empty(adapter) &&
-                   !mwifiex_is_tdls_chan_switching
-                       (mwifiex_get_priv(adapter, MWIFIEX_BSS_ROLE_STA))) {
-                       mwifiex_process_bypass_tx(adapter);
-                       if (adapter->hs_activated) {
-                               adapter->is_hs_configured = false;
-                               mwifiex_hs_activated_event
-                                       (mwifiex_get_priv
-                                        (adapter, MWIFIEX_BSS_ROLE_ANY),
-                                        false);
-                       }
-               }
-
-               if ((adapter->scan_chan_gap_enabled ||
-                    !adapter->scan_processing) &&
-                   !adapter->data_sent && !mwifiex_wmm_lists_empty(adapter) &&
-                   !mwifiex_is_tdls_chan_switching
-                       (mwifiex_get_priv(adapter, MWIFIEX_BSS_ROLE_STA))) {
-                       mwifiex_wmm_process_tx(adapter);
-                       if (adapter->hs_activated) {
-                               adapter->is_hs_configured = false;
-                               mwifiex_hs_activated_event
-                                       (mwifiex_get_priv
-                                        (adapter, MWIFIEX_BSS_ROLE_ANY),
-                                        false);
-                       }
-               }
-
-               if (adapter->delay_null_pkt && !adapter->cmd_sent &&
-                   !adapter->curr_cmd && !is_command_pending(adapter) &&
-                   (mwifiex_wmm_lists_empty(adapter) &&
-                    mwifiex_bypass_txlist_empty(adapter) &&
-                    skb_queue_empty(&adapter->tx_data_q))) {
-                       if (!mwifiex_send_null_packet
-                           (mwifiex_get_priv(adapter, MWIFIEX_BSS_ROLE_STA),
-                            MWIFIEX_TxPD_POWER_MGMT_NULL_PACKET |
-                            MWIFIEX_TxPD_POWER_MGMT_LAST_PACKET)) {
-                               adapter->delay_null_pkt = false;
-                               adapter->ps_state = PS_STATE_SLEEP;
-                       }
-                       break;
-               }
-       } while (true);
-
-       spin_lock_irqsave(&adapter->main_proc_lock, flags);
-       if (adapter->more_task_flag) {
-               adapter->more_task_flag = false;
-               spin_unlock_irqrestore(&adapter->main_proc_lock, flags);
-               goto process_start;
-       }
-       adapter->mwifiex_processing = false;
-       spin_unlock_irqrestore(&adapter->main_proc_lock, flags);
-
-exit_main_proc:
-       if (adapter->hw_status == MWIFIEX_HW_STATUS_CLOSING)
-               mwifiex_shutdown_drv(adapter);
-       return ret;
-}
-EXPORT_SYMBOL_GPL(mwifiex_main_process);
-
-/*
- * This function frees the adapter structure.
- *
- * Additionally, this closes the netlink socket, frees the timers
- * and private structures.
- */
-static void mwifiex_free_adapter(struct mwifiex_adapter *adapter)
-{
-       if (!adapter) {
-               pr_err("%s: adapter is NULL\n", __func__);
-               return;
-       }
-
-       mwifiex_unregister(adapter);
-       pr_debug("info: %s: free adapter\n", __func__);
-}
-
-/*
- * This function cancels all works in the queue and destroys
- * the main workqueue.
- */
-static void mwifiex_terminate_workqueue(struct mwifiex_adapter *adapter)
-{
-       flush_workqueue(adapter->workqueue);
-       destroy_workqueue(adapter->workqueue);
-       adapter->workqueue = NULL;
-
-       if (adapter->rx_workqueue) {
-               flush_workqueue(adapter->rx_workqueue);
-               destroy_workqueue(adapter->rx_workqueue);
-               adapter->rx_workqueue = NULL;
-       }
-}
-
-/*
- * This function gets firmware and initializes it.
- *
- * The main initialization steps followed are -
- *      - Download the correct firmware to card
- *      - Issue the init commands to firmware
- */
-static void mwifiex_fw_dpc(const struct firmware *firmware, void *context)
-{
-       int ret;
-       char fmt[64];
-       struct mwifiex_private *priv;
-       struct mwifiex_adapter *adapter = context;
-       struct mwifiex_fw_image fw;
-       struct semaphore *sem = adapter->card_sem;
-       bool init_failed = false;
-       struct wireless_dev *wdev;
-
-       if (!firmware) {
-               mwifiex_dbg(adapter, ERROR,
-                           "Failed to get firmware %s\n", adapter->fw_name);
-               goto err_dnld_fw;
-       }
-
-       memset(&fw, 0, sizeof(struct mwifiex_fw_image));
-       adapter->firmware = firmware;
-       fw.fw_buf = (u8 *) adapter->firmware->data;
-       fw.fw_len = adapter->firmware->size;
-
-       if (adapter->if_ops.dnld_fw)
-               ret = adapter->if_ops.dnld_fw(adapter, &fw);
-       else
-               ret = mwifiex_dnld_fw(adapter, &fw);
-       if (ret == -1)
-               goto err_dnld_fw;
-
-       mwifiex_dbg(adapter, MSG, "WLAN FW is active\n");
-
-       if (cal_data_cfg) {
-               if ((request_firmware(&adapter->cal_data, cal_data_cfg,
-                                     adapter->dev)) < 0)
-                       mwifiex_dbg(adapter, ERROR,
-                                   "Cal data request_firmware() failed\n");
-       }
-
-       /* enable host interrupt after fw dnld is successful */
-       if (adapter->if_ops.enable_int) {
-               if (adapter->if_ops.enable_int(adapter))
-                       goto err_dnld_fw;
-       }
-
-       adapter->init_wait_q_woken = false;
-       ret = mwifiex_init_fw(adapter);
-       if (ret == -1) {
-               goto err_init_fw;
-       } else if (!ret) {
-               adapter->hw_status = MWIFIEX_HW_STATUS_READY;
-               goto done;
-       }
-       /* Wait for mwifiex_init to complete */
-       wait_event_interruptible(adapter->init_wait_q,
-                                adapter->init_wait_q_woken);
-       if (adapter->hw_status != MWIFIEX_HW_STATUS_READY)
-               goto err_init_fw;
-
-       priv = adapter->priv[MWIFIEX_BSS_ROLE_STA];
-       if (mwifiex_register_cfg80211(adapter)) {
-               mwifiex_dbg(adapter, ERROR,
-                           "cannot register with cfg80211\n");
-               goto err_init_fw;
-       }
-
-       if (mwifiex_init_channel_scan_gap(adapter)) {
-               mwifiex_dbg(adapter, ERROR,
-                           "could not init channel stats table\n");
-               goto err_init_fw;
-       }
-
-       if (driver_mode) {
-               driver_mode &= MWIFIEX_DRIVER_MODE_BITMASK;
-               driver_mode |= MWIFIEX_DRIVER_MODE_STA;
-       }
-
-       rtnl_lock();
-       /* Create station interface by default */
-       wdev = mwifiex_add_virtual_intf(adapter->wiphy, "mlan%d", NET_NAME_ENUM,
-                                       NL80211_IFTYPE_STATION, NULL, NULL);
-       if (IS_ERR(wdev)) {
-               mwifiex_dbg(adapter, ERROR,
-                           "cannot create default STA interface\n");
-               rtnl_unlock();
-               goto err_add_intf;
-       }
-
-       if (driver_mode & MWIFIEX_DRIVER_MODE_UAP) {
-               wdev = mwifiex_add_virtual_intf(adapter->wiphy, "uap%d", NET_NAME_ENUM,
-                                               NL80211_IFTYPE_AP, NULL, NULL);
-               if (IS_ERR(wdev)) {
-                       mwifiex_dbg(adapter, ERROR,
-                                   "cannot create AP interface\n");
-                       rtnl_unlock();
-                       goto err_add_intf;
-               }
-       }
-
-       if (driver_mode & MWIFIEX_DRIVER_MODE_P2P) {
-               wdev = mwifiex_add_virtual_intf(adapter->wiphy, "p2p%d", NET_NAME_ENUM,
-                                               NL80211_IFTYPE_P2P_CLIENT, NULL,
-                                               NULL);
-               if (IS_ERR(wdev)) {
-                       mwifiex_dbg(adapter, ERROR,
-                                   "cannot create p2p client interface\n");
-                       rtnl_unlock();
-                       goto err_add_intf;
-               }
-       }
-       rtnl_unlock();
-
-       mwifiex_drv_get_driver_version(adapter, fmt, sizeof(fmt) - 1);
-       mwifiex_dbg(adapter, MSG, "driver_version = %s\n", fmt);
-       goto done;
-
-err_add_intf:
-       wiphy_unregister(adapter->wiphy);
-       wiphy_free(adapter->wiphy);
-err_init_fw:
-       if (adapter->if_ops.disable_int)
-               adapter->if_ops.disable_int(adapter);
-err_dnld_fw:
-       mwifiex_dbg(adapter, ERROR,
-                   "info: %s: unregister device\n", __func__);
-       if (adapter->if_ops.unregister_dev)
-               adapter->if_ops.unregister_dev(adapter);
-
-       if (adapter->hw_status == MWIFIEX_HW_STATUS_READY) {
-               pr_debug("info: %s: shutdown mwifiex\n", __func__);
-               adapter->init_wait_q_woken = false;
-
-               if (mwifiex_shutdown_drv(adapter) == -EINPROGRESS)
-                       wait_event_interruptible(adapter->init_wait_q,
-                                                adapter->init_wait_q_woken);
-       }
-       adapter->surprise_removed = true;
-       mwifiex_terminate_workqueue(adapter);
-       init_failed = true;
-done:
-       if (adapter->cal_data) {
-               release_firmware(adapter->cal_data);
-               adapter->cal_data = NULL;
-       }
-       if (adapter->firmware) {
-               release_firmware(adapter->firmware);
-               adapter->firmware = NULL;
-       }
-       if (init_failed)
-               mwifiex_free_adapter(adapter);
-       up(sem);
-       return;
-}
-
-/*
- * This function initializes the hardware and gets firmware.
- */
-static int mwifiex_init_hw_fw(struct mwifiex_adapter *adapter)
-{
-       int ret;
-
-       ret = request_firmware_nowait(THIS_MODULE, 1, adapter->fw_name,
-                                     adapter->dev, GFP_KERNEL, adapter,
-                                     mwifiex_fw_dpc);
-       if (ret < 0)
-               mwifiex_dbg(adapter, ERROR,
-                           "request_firmware_nowait error %d\n", ret);
-       return ret;
-}
-
-/*
- * CFG802.11 network device handler for open.
- *
- * Starts the data queue.
- */
-static int
-mwifiex_open(struct net_device *dev)
-{
-       netif_carrier_off(dev);
-
-       return 0;
-}
-
-/*
- * CFG802.11 network device handler for close.
- */
-static int
-mwifiex_close(struct net_device *dev)
-{
-       struct mwifiex_private *priv = mwifiex_netdev_get_priv(dev);
-
-       if (priv->scan_request) {
-               mwifiex_dbg(priv->adapter, INFO,
-                           "aborting scan on ndo_stop\n");
-               cfg80211_scan_done(priv->scan_request, 1);
-               priv->scan_request = NULL;
-               priv->scan_aborting = true;
-       }
-
-       return 0;
-}
-
-static bool
-mwifiex_bypass_tx_queue(struct mwifiex_private *priv,
-                       struct sk_buff *skb)
-{
-       struct ethhdr *eth_hdr = (struct ethhdr *)skb->data;
-
-       if (ntohs(eth_hdr->h_proto) == ETH_P_PAE ||
-           mwifiex_is_skb_mgmt_frame(skb) ||
-           (GET_BSS_ROLE(priv) == MWIFIEX_BSS_ROLE_STA &&
-            ISSUPP_TDLS_ENABLED(priv->adapter->fw_cap_info) &&
-            (ntohs(eth_hdr->h_proto) == ETH_P_TDLS))) {
-               mwifiex_dbg(priv->adapter, DATA,
-                           "bypass txqueue; eth type %#x, mgmt %d\n",
-                            ntohs(eth_hdr->h_proto),
-                            mwifiex_is_skb_mgmt_frame(skb));
-               return true;
-       }
-
-       return false;
-}
-/*
- * Add buffer into wmm tx queue and queue work to transmit it.
- */
-int mwifiex_queue_tx_pkt(struct mwifiex_private *priv, struct sk_buff *skb)
-{
-       struct netdev_queue *txq;
-       int index = mwifiex_1d_to_wmm_queue[skb->priority];
-
-       if (atomic_inc_return(&priv->wmm_tx_pending[index]) >= MAX_TX_PENDING) {
-               txq = netdev_get_tx_queue(priv->netdev, index);
-               if (!netif_tx_queue_stopped(txq)) {
-                       netif_tx_stop_queue(txq);
-                       mwifiex_dbg(priv->adapter, DATA,
-                                   "stop queue: %d\n", index);
-               }
-       }
-
-       if (mwifiex_bypass_tx_queue(priv, skb)) {
-               atomic_inc(&priv->adapter->tx_pending);
-               atomic_inc(&priv->adapter->bypass_tx_pending);
-               mwifiex_wmm_add_buf_bypass_txqueue(priv, skb);
-        } else {
-               atomic_inc(&priv->adapter->tx_pending);
-               mwifiex_wmm_add_buf_txqueue(priv, skb);
-        }
-
-       mwifiex_queue_main_work(priv->adapter);
-
-       return 0;
-}
-
-struct sk_buff *
-mwifiex_clone_skb_for_tx_status(struct mwifiex_private *priv,
-                               struct sk_buff *skb, u8 flag, u64 *cookie)
-{
-       struct sk_buff *orig_skb = skb;
-       struct mwifiex_txinfo *tx_info, *orig_tx_info;
-
-       skb = skb_clone(skb, GFP_ATOMIC);
-       if (skb) {
-               unsigned long flags;
-               int id;
-
-               spin_lock_irqsave(&priv->ack_status_lock, flags);
-               id = idr_alloc(&priv->ack_status_frames, orig_skb,
-                              1, 0xff, GFP_ATOMIC);
-               spin_unlock_irqrestore(&priv->ack_status_lock, flags);
-
-               if (id >= 0) {
-                       tx_info = MWIFIEX_SKB_TXCB(skb);
-                       tx_info->ack_frame_id = id;
-                       tx_info->flags |= flag;
-                       orig_tx_info = MWIFIEX_SKB_TXCB(orig_skb);
-                       orig_tx_info->ack_frame_id = id;
-                       orig_tx_info->flags |= flag;
-
-                       if (flag == MWIFIEX_BUF_FLAG_ACTION_TX_STATUS && cookie)
-                               orig_tx_info->cookie = *cookie;
-
-               } else if (skb_shared(skb)) {
-                       kfree_skb(orig_skb);
-               } else {
-                       kfree_skb(skb);
-                       skb = orig_skb;
-               }
-       } else {
-               /* couldn't clone -- lose tx status ... */
-               skb = orig_skb;
-       }
-
-       return skb;
-}
-
-/*
- * CFG802.11 network device handler for data transmission.
- */
-static int
-mwifiex_hard_start_xmit(struct sk_buff *skb, struct net_device *dev)
-{
-       struct mwifiex_private *priv = mwifiex_netdev_get_priv(dev);
-       struct sk_buff *new_skb;
-       struct mwifiex_txinfo *tx_info;
-       bool multicast;
-
-       mwifiex_dbg(priv->adapter, DATA,
-                   "data: %lu BSS(%d-%d): Data <= kernel\n",
-                   jiffies, priv->bss_type, priv->bss_num);
-
-       if (priv->adapter->surprise_removed) {
-               kfree_skb(skb);
-               priv->stats.tx_dropped++;
-               return 0;
-       }
-       if (!skb->len || (skb->len > ETH_FRAME_LEN)) {
-               mwifiex_dbg(priv->adapter, ERROR,
-                           "Tx: bad skb len %d\n", skb->len);
-               kfree_skb(skb);
-               priv->stats.tx_dropped++;
-               return 0;
-       }
-       if (skb_headroom(skb) < MWIFIEX_MIN_DATA_HEADER_LEN) {
-               mwifiex_dbg(priv->adapter, DATA,
-                           "data: Tx: insufficient skb headroom %d\n",
-                           skb_headroom(skb));
-               /* Insufficient skb headroom - allocate a new skb */
-               new_skb =
-                       skb_realloc_headroom(skb, MWIFIEX_MIN_DATA_HEADER_LEN);
-               if (unlikely(!new_skb)) {
-                       mwifiex_dbg(priv->adapter, ERROR,
-                                   "Tx: cannot alloca new_skb\n");
-                       kfree_skb(skb);
-                       priv->stats.tx_dropped++;
-                       return 0;
-               }
-               kfree_skb(skb);
-               skb = new_skb;
-               mwifiex_dbg(priv->adapter, INFO,
-                           "info: new skb headroomd %d\n",
-                           skb_headroom(skb));
-       }
-
-       tx_info = MWIFIEX_SKB_TXCB(skb);
-       memset(tx_info, 0, sizeof(*tx_info));
-       tx_info->bss_num = priv->bss_num;
-       tx_info->bss_type = priv->bss_type;
-       tx_info->pkt_len = skb->len;
-
-       multicast = is_multicast_ether_addr(skb->data);
-
-       if (unlikely(!multicast && skb->sk &&
-                    skb_shinfo(skb)->tx_flags & SKBTX_WIFI_STATUS &&
-                    priv->adapter->fw_api_ver == MWIFIEX_FW_V15))
-               skb = mwifiex_clone_skb_for_tx_status(priv,
-                                                     skb,
-                                       MWIFIEX_BUF_FLAG_EAPOL_TX_STATUS, NULL);
-
-       /* Record the current time the packet was queued; used to
-        * determine the amount of time the packet was queued in
-        * the driver before it was sent to the firmware.
-        * The delay is then sent along with the packet to the
-        * firmware for aggregate delay calculation for stats and
-        * MSDU lifetime expiry.
-        */
-       __net_timestamp(skb);
-
-       if (ISSUPP_TDLS_ENABLED(priv->adapter->fw_cap_info) &&
-           priv->bss_type == MWIFIEX_BSS_TYPE_STA &&
-           !ether_addr_equal_unaligned(priv->cfg_bssid, skb->data)) {
-               if (priv->adapter->auto_tdls && priv->check_tdls_tx)
-                       mwifiex_tdls_check_tx(priv, skb);
-       }
-
-       mwifiex_queue_tx_pkt(priv, skb);
-
-       return 0;
-}
-
-/*
- * CFG802.11 network device handler for setting MAC address.
- */
-static int
-mwifiex_set_mac_address(struct net_device *dev, void *addr)
-{
-       struct mwifiex_private *priv = mwifiex_netdev_get_priv(dev);
-       struct sockaddr *hw_addr = addr;
-       int ret;
-
-       memcpy(priv->curr_addr, hw_addr->sa_data, ETH_ALEN);
-
-       /* Send request to firmware */
-       ret = mwifiex_send_cmd(priv, HostCmd_CMD_802_11_MAC_ADDRESS,
-                              HostCmd_ACT_GEN_SET, 0, NULL, true);
-
-       if (!ret)
-               memcpy(priv->netdev->dev_addr, priv->curr_addr, ETH_ALEN);
-       else
-               mwifiex_dbg(priv->adapter, ERROR,
-                           "set mac address failed: ret=%d\n", ret);
-
-       memcpy(dev->dev_addr, priv->curr_addr, ETH_ALEN);
-
-       return ret;
-}
-
-/*
- * CFG802.11 network device handler for setting multicast list.
- */
-static void mwifiex_set_multicast_list(struct net_device *dev)
-{
-       struct mwifiex_private *priv = mwifiex_netdev_get_priv(dev);
-       struct mwifiex_multicast_list mcast_list;
-
-       if (dev->flags & IFF_PROMISC) {
-               mcast_list.mode = MWIFIEX_PROMISC_MODE;
-       } else if (dev->flags & IFF_ALLMULTI ||
-                  netdev_mc_count(dev) > MWIFIEX_MAX_MULTICAST_LIST_SIZE) {
-               mcast_list.mode = MWIFIEX_ALL_MULTI_MODE;
-       } else {
-               mcast_list.mode = MWIFIEX_MULTICAST_MODE;
-               mcast_list.num_multicast_addr =
-                       mwifiex_copy_mcast_addr(&mcast_list, dev);
-       }
-       mwifiex_request_set_multicast_list(priv, &mcast_list);
-}
-
-/*
- * CFG802.11 network device handler for transmission timeout.
- */
-static void
-mwifiex_tx_timeout(struct net_device *dev)
-{
-       struct mwifiex_private *priv = mwifiex_netdev_get_priv(dev);
-
-       priv->num_tx_timeout++;
-       priv->tx_timeout_cnt++;
-       mwifiex_dbg(priv->adapter, ERROR,
-                   "%lu : Tx timeout(#%d), bss_type-num = %d-%d\n",
-                   jiffies, priv->tx_timeout_cnt, priv->bss_type,
-                   priv->bss_num);
-       mwifiex_set_trans_start(dev);
-
-       if (priv->tx_timeout_cnt > TX_TIMEOUT_THRESHOLD &&
-           priv->adapter->if_ops.card_reset) {
-               mwifiex_dbg(priv->adapter, ERROR,
-                           "tx_timeout_cnt exceeds threshold.\t"
-                           "Triggering card reset!\n");
-               priv->adapter->if_ops.card_reset(priv->adapter);
-       }
-}
-
-void mwifiex_multi_chan_resync(struct mwifiex_adapter *adapter)
-{
-       struct usb_card_rec *card = adapter->card;
-       struct mwifiex_private *priv;
-       u16 tx_buf_size;
-       int i, ret;
-
-       card->mc_resync_flag = true;
-       for (i = 0; i < MWIFIEX_TX_DATA_PORT; i++) {
-               if (atomic_read(&card->port[i].tx_data_urb_pending)) {
-                       mwifiex_dbg(adapter, WARN, "pending data urb in sys\n");
-                       return;
-               }
-       }
-
-       card->mc_resync_flag = false;
-       tx_buf_size = 0xffff;
-       priv = mwifiex_get_priv(adapter, MWIFIEX_BSS_ROLE_ANY);
-       ret = mwifiex_send_cmd(priv, HostCmd_CMD_RECONFIGURE_TX_BUFF,
-                              HostCmd_ACT_GEN_SET, 0, &tx_buf_size, false);
-       if (ret)
-               mwifiex_dbg(adapter, ERROR,
-                           "send reconfig tx buf size cmd err\n");
-}
-EXPORT_SYMBOL_GPL(mwifiex_multi_chan_resync);
-
-void mwifiex_drv_info_dump(struct mwifiex_adapter *adapter)
-{
-       void *p;
-       char drv_version[64];
-       struct usb_card_rec *cardp;
-       struct sdio_mmc_card *sdio_card;
-       struct mwifiex_private *priv;
-       int i, idx;
-       struct netdev_queue *txq;
-       struct mwifiex_debug_info *debug_info;
-
-       if (adapter->drv_info_dump) {
-               vfree(adapter->drv_info_dump);
-               adapter->drv_info_dump = NULL;
-               adapter->drv_info_size = 0;
-       }
-
-       mwifiex_dbg(adapter, MSG, "===mwifiex driverinfo dump start===\n");
-
-       adapter->drv_info_dump = vzalloc(MWIFIEX_DRV_INFO_SIZE_MAX);
-
-       if (!adapter->drv_info_dump)
-               return;
-
-       p = (char *)(adapter->drv_info_dump);
-       p += sprintf(p, "driver_name = " "\"mwifiex\"\n");
-
-       mwifiex_drv_get_driver_version(adapter, drv_version,
-                                      sizeof(drv_version) - 1);
-       p += sprintf(p, "driver_version = %s\n", drv_version);
-
-       if (adapter->iface_type == MWIFIEX_USB) {
-               cardp = (struct usb_card_rec *)adapter->card;
-               p += sprintf(p, "tx_cmd_urb_pending = %d\n",
-                            atomic_read(&cardp->tx_cmd_urb_pending));
-               p += sprintf(p, "tx_data_urb_pending_port_0 = %d\n",
-                            atomic_read(&cardp->port[0].tx_data_urb_pending));
-               p += sprintf(p, "tx_data_urb_pending_port_1 = %d\n",
-                            atomic_read(&cardp->port[1].tx_data_urb_pending));
-               p += sprintf(p, "rx_cmd_urb_pending = %d\n",
-                            atomic_read(&cardp->rx_cmd_urb_pending));
-               p += sprintf(p, "rx_data_urb_pending = %d\n",
-                            atomic_read(&cardp->rx_data_urb_pending));
-       }
-
-       p += sprintf(p, "tx_pending = %d\n",
-                    atomic_read(&adapter->tx_pending));
-       p += sprintf(p, "rx_pending = %d\n",
-                    atomic_read(&adapter->rx_pending));
-
-       if (adapter->iface_type == MWIFIEX_SDIO) {
-               sdio_card = (struct sdio_mmc_card *)adapter->card;
-               p += sprintf(p, "\nmp_rd_bitmap=0x%x curr_rd_port=0x%x\n",
-                            sdio_card->mp_rd_bitmap, sdio_card->curr_rd_port);
-               p += sprintf(p, "mp_wr_bitmap=0x%x curr_wr_port=0x%x\n",
-                            sdio_card->mp_wr_bitmap, sdio_card->curr_wr_port);
-       }
-
-       for (i = 0; i < adapter->priv_num; i++) {
-               if (!adapter->priv[i] || !adapter->priv[i]->netdev)
-                       continue;
-               priv = adapter->priv[i];
-               p += sprintf(p, "\n[interface  : \"%s\"]\n",
-                            priv->netdev->name);
-               p += sprintf(p, "wmm_tx_pending[0] = %d\n",
-                            atomic_read(&priv->wmm_tx_pending[0]));
-               p += sprintf(p, "wmm_tx_pending[1] = %d\n",
-                            atomic_read(&priv->wmm_tx_pending[1]));
-               p += sprintf(p, "wmm_tx_pending[2] = %d\n",
-                            atomic_read(&priv->wmm_tx_pending[2]));
-               p += sprintf(p, "wmm_tx_pending[3] = %d\n",
-                            atomic_read(&priv->wmm_tx_pending[3]));
-               p += sprintf(p, "media_state=\"%s\"\n", !priv->media_connected ?
-                            "Disconnected" : "Connected");
-               p += sprintf(p, "carrier %s\n", (netif_carrier_ok(priv->netdev)
-                            ? "on" : "off"));
-               for (idx = 0; idx < priv->netdev->num_tx_queues; idx++) {
-                       txq = netdev_get_tx_queue(priv->netdev, idx);
-                       p += sprintf(p, "tx queue %d:%s  ", idx,
-                                    netif_tx_queue_stopped(txq) ?
-                                    "stopped" : "started");
-               }
-               p += sprintf(p, "\n%s: num_tx_timeout = %d\n",
-                            priv->netdev->name, priv->num_tx_timeout);
-       }
-
-       if (adapter->iface_type == MWIFIEX_SDIO) {
-               p += sprintf(p, "\n=== SDIO register dump===\n");
-               if (adapter->if_ops.reg_dump)
-                       p += adapter->if_ops.reg_dump(adapter, p);
-       }
-
-       p += sprintf(p, "\n=== more debug information\n");
-       debug_info = kzalloc(sizeof(*debug_info), GFP_KERNEL);
-       if (debug_info) {
-               for (i = 0; i < adapter->priv_num; i++) {
-                       if (!adapter->priv[i] || !adapter->priv[i]->netdev)
-                               continue;
-                       priv = adapter->priv[i];
-                       mwifiex_get_debug_info(priv, debug_info);
-                       p += mwifiex_debug_info_to_buffer(priv, p, debug_info);
-                       break;
-               }
-               kfree(debug_info);
-       }
-
-       adapter->drv_info_size = p - adapter->drv_info_dump;
-       mwifiex_dbg(adapter, MSG, "===mwifiex driverinfo dump end===\n");
-}
-EXPORT_SYMBOL_GPL(mwifiex_drv_info_dump);
-
-void mwifiex_upload_device_dump(struct mwifiex_adapter *adapter)
-{
-       u8 idx, *dump_data, *fw_dump_ptr;
-       u32 dump_len;
-
-       dump_len = (strlen("========Start dump driverinfo========\n") +
-                      adapter->drv_info_size +
-                      strlen("\n========End dump========\n"));
-
-       for (idx = 0; idx < adapter->num_mem_types; idx++) {
-               struct memory_type_mapping *entry =
-                               &adapter->mem_type_mapping_tbl[idx];
-
-               if (entry->mem_ptr) {
-                       dump_len += (strlen("========Start dump ") +
-                                       strlen(entry->mem_name) +
-                                       strlen("========\n") +
-                                       (entry->mem_size + 1) +
-                                       strlen("\n========End dump========\n"));
-               }
-       }
-
-       dump_data = vzalloc(dump_len + 1);
-       if (!dump_data)
-               goto done;
-
-       fw_dump_ptr = dump_data;
-
-       /* Dump all the memory data into single file, a userspace script will
-        * be used to split all the memory data to multiple files
-        */
-       mwifiex_dbg(adapter, MSG,
-                   "== mwifiex dump information to /sys/class/devcoredump start");
-
-       strcpy(fw_dump_ptr, "========Start dump driverinfo========\n");
-       fw_dump_ptr += strlen("========Start dump driverinfo========\n");
-       memcpy(fw_dump_ptr, adapter->drv_info_dump, adapter->drv_info_size);
-       fw_dump_ptr += adapter->drv_info_size;
-       strcpy(fw_dump_ptr, "\n========End dump========\n");
-       fw_dump_ptr += strlen("\n========End dump========\n");
-
-       for (idx = 0; idx < adapter->num_mem_types; idx++) {
-               struct memory_type_mapping *entry =
-                                       &adapter->mem_type_mapping_tbl[idx];
-
-               if (entry->mem_ptr) {
-                       strcpy(fw_dump_ptr, "========Start dump ");
-                       fw_dump_ptr += strlen("========Start dump ");
-
-                       strcpy(fw_dump_ptr, entry->mem_name);
-                       fw_dump_ptr += strlen(entry->mem_name);
-
-                       strcpy(fw_dump_ptr, "========\n");
-                       fw_dump_ptr += strlen("========\n");
-
-                       memcpy(fw_dump_ptr, entry->mem_ptr, entry->mem_size);
-                       fw_dump_ptr += entry->mem_size;
-
-                       strcpy(fw_dump_ptr, "\n========End dump========\n");
-                       fw_dump_ptr += strlen("\n========End dump========\n");
-               }
-       }
-
-       /* device dump data will be free in device coredump release function
-        * after 5 min
-        */
-       dev_coredumpv(adapter->dev, dump_data, dump_len, GFP_KERNEL);
-       mwifiex_dbg(adapter, MSG,
-                   "== mwifiex dump information to /sys/class/devcoredump end");
-
-done:
-       for (idx = 0; idx < adapter->num_mem_types; idx++) {
-               struct memory_type_mapping *entry =
-                       &adapter->mem_type_mapping_tbl[idx];
-
-               if (entry->mem_ptr) {
-                       vfree(entry->mem_ptr);
-                       entry->mem_ptr = NULL;
-               }
-               entry->mem_size = 0;
-       }
-
-       if (adapter->drv_info_dump) {
-               vfree(adapter->drv_info_dump);
-               adapter->drv_info_dump = NULL;
-               adapter->drv_info_size = 0;
-       }
-}
-EXPORT_SYMBOL_GPL(mwifiex_upload_device_dump);
-
-/*
- * CFG802.11 network device handler for statistics retrieval.
- */
-static struct net_device_stats *mwifiex_get_stats(struct net_device *dev)
-{
-       struct mwifiex_private *priv = mwifiex_netdev_get_priv(dev);
-
-       return &priv->stats;
-}
-
-static u16
-mwifiex_netdev_select_wmm_queue(struct net_device *dev, struct sk_buff *skb,
-                               void *accel_priv, select_queue_fallback_t fallback)
-{
-       skb->priority = cfg80211_classify8021d(skb, NULL);
-       return mwifiex_1d_to_wmm_queue[skb->priority];
-}
-
-/* Network device handlers */
-static const struct net_device_ops mwifiex_netdev_ops = {
-       .ndo_open = mwifiex_open,
-       .ndo_stop = mwifiex_close,
-       .ndo_start_xmit = mwifiex_hard_start_xmit,
-       .ndo_set_mac_address = mwifiex_set_mac_address,
-       .ndo_validate_addr = eth_validate_addr,
-       .ndo_tx_timeout = mwifiex_tx_timeout,
-       .ndo_get_stats = mwifiex_get_stats,
-       .ndo_set_rx_mode = mwifiex_set_multicast_list,
-       .ndo_select_queue = mwifiex_netdev_select_wmm_queue,
-};
-
-/*
- * This function initializes the private structure parameters.
- *
- * The following wait queues are initialized -
- *      - IOCTL wait queue
- *      - Command wait queue
- *      - Statistics wait queue
- *
- * ...and the following default parameters are set -
- *      - Current key index     : Set to 0
- *      - Rate index            : Set to auto
- *      - Media connected       : Set to disconnected
- *      - Adhoc link sensed     : Set to false
- *      - Nick name             : Set to null
- *      - Number of Tx timeout  : Set to 0
- *      - Device address        : Set to current address
- *      - Rx histogram statistc : Set to 0
- *
- * In addition, the CFG80211 work queue is also created.
- */
-void mwifiex_init_priv_params(struct mwifiex_private *priv,
-                             struct net_device *dev)
-{
-       dev->netdev_ops = &mwifiex_netdev_ops;
-       dev->destructor = free_netdev;
-       /* Initialize private structure */
-       priv->current_key_index = 0;
-       priv->media_connected = false;
-       memset(priv->mgmt_ie, 0,
-              sizeof(struct mwifiex_ie) * MAX_MGMT_IE_INDEX);
-       priv->beacon_idx = MWIFIEX_AUTO_IDX_MASK;
-       priv->proberesp_idx = MWIFIEX_AUTO_IDX_MASK;
-       priv->assocresp_idx = MWIFIEX_AUTO_IDX_MASK;
-       priv->gen_idx = MWIFIEX_AUTO_IDX_MASK;
-       priv->num_tx_timeout = 0;
-       ether_addr_copy(priv->curr_addr, priv->adapter->perm_addr);
-       memcpy(dev->dev_addr, priv->curr_addr, ETH_ALEN);
-
-       if (GET_BSS_ROLE(priv) == MWIFIEX_BSS_ROLE_STA ||
-           GET_BSS_ROLE(priv) == MWIFIEX_BSS_ROLE_UAP) {
-               priv->hist_data = kmalloc(sizeof(*priv->hist_data), GFP_KERNEL);
-               if (priv->hist_data)
-                       mwifiex_hist_data_reset(priv);
-       }
-}
-
-/*
- * This function check if command is pending.
- */
-int is_command_pending(struct mwifiex_adapter *adapter)
-{
-       unsigned long flags;
-       int is_cmd_pend_q_empty;
-
-       spin_lock_irqsave(&adapter->cmd_pending_q_lock, flags);
-       is_cmd_pend_q_empty = list_empty(&adapter->cmd_pending_q);
-       spin_unlock_irqrestore(&adapter->cmd_pending_q_lock, flags);
-
-       return !is_cmd_pend_q_empty;
-}
-
-/*
- * This is the RX work queue function.
- *
- * It handles the RX operations.
- */
-static void mwifiex_rx_work_queue(struct work_struct *work)
-{
-       struct mwifiex_adapter *adapter =
-               container_of(work, struct mwifiex_adapter, rx_work);
-
-       if (adapter->surprise_removed)
-               return;
-       mwifiex_process_rx(adapter);
-}
-
-/*
- * This is the main work queue function.
- *
- * It handles the main process, which in turn handles the complete
- * driver operations.
- */
-static void mwifiex_main_work_queue(struct work_struct *work)
-{
-       struct mwifiex_adapter *adapter =
-               container_of(work, struct mwifiex_adapter, main_work);
-
-       if (adapter->surprise_removed)
-               return;
-       mwifiex_main_process(adapter);
-}
-
-/*
- * This function adds the card.
- *
- * This function follows the following major steps to set up the device -
- *      - Initialize software. This includes probing the card, registering
- *        the interface operations table, and allocating/initializing the
- *        adapter structure
- *      - Set up the netlink socket
- *      - Create and start the main work queue
- *      - Register the device
- *      - Initialize firmware and hardware
- *      - Add logical interfaces
- */
-int
-mwifiex_add_card(void *card, struct semaphore *sem,
-                struct mwifiex_if_ops *if_ops, u8 iface_type)
-{
-       struct mwifiex_adapter *adapter;
-
-       if (down_interruptible(sem))
-               goto exit_sem_err;
-
-       if (mwifiex_register(card, if_ops, (void **)&adapter)) {
-               pr_err("%s: software init failed\n", __func__);
-               goto err_init_sw;
-       }
-
-       adapter->iface_type = iface_type;
-       adapter->card_sem = sem;
-
-       adapter->hw_status = MWIFIEX_HW_STATUS_INITIALIZING;
-       adapter->surprise_removed = false;
-       init_waitqueue_head(&adapter->init_wait_q);
-       adapter->is_suspended = false;
-       adapter->hs_activated = false;
-       init_waitqueue_head(&adapter->hs_activate_wait_q);
-       init_waitqueue_head(&adapter->cmd_wait_q.wait);
-       adapter->cmd_wait_q.status = 0;
-       adapter->scan_wait_q_woken = false;
-
-       if ((num_possible_cpus() > 1) || adapter->iface_type == MWIFIEX_USB) {
-               adapter->rx_work_enabled = true;
-               pr_notice("rx work enabled, cpus %d\n", num_possible_cpus());
-       }
-
-       adapter->workqueue =
-               alloc_workqueue("MWIFIEX_WORK_QUEUE",
-                               WQ_HIGHPRI | WQ_MEM_RECLAIM | WQ_UNBOUND, 1);
-       if (!adapter->workqueue)
-               goto err_kmalloc;
-
-       INIT_WORK(&adapter->main_work, mwifiex_main_work_queue);
-
-       if (adapter->rx_work_enabled) {
-               adapter->rx_workqueue = alloc_workqueue("MWIFIEX_RX_WORK_QUEUE",
-                                                       WQ_HIGHPRI |
-                                                       WQ_MEM_RECLAIM |
-                                                       WQ_UNBOUND, 1);
-               if (!adapter->rx_workqueue)
-                       goto err_kmalloc;
-
-               INIT_WORK(&adapter->rx_work, mwifiex_rx_work_queue);
-       }
-
-       /* Register the device. Fill up the private data structure with relevant
-          information from the card. */
-       if (adapter->if_ops.register_dev(adapter)) {
-               pr_err("%s: failed to register mwifiex device\n", __func__);
-               goto err_registerdev;
-       }
-
-       if (mwifiex_init_hw_fw(adapter)) {
-               pr_err("%s: firmware init failed\n", __func__);
-               goto err_init_fw;
-       }
-
-       return 0;
-
-err_init_fw:
-       pr_debug("info: %s: unregister device\n", __func__);
-       if (adapter->if_ops.unregister_dev)
-               adapter->if_ops.unregister_dev(adapter);
-       if (adapter->hw_status == MWIFIEX_HW_STATUS_READY) {
-               pr_debug("info: %s: shutdown mwifiex\n", __func__);
-               adapter->init_wait_q_woken = false;
-
-               if (mwifiex_shutdown_drv(adapter) == -EINPROGRESS)
-                       wait_event_interruptible(adapter->init_wait_q,
-                                                adapter->init_wait_q_woken);
-       }
-err_registerdev:
-       adapter->surprise_removed = true;
-       mwifiex_terminate_workqueue(adapter);
-err_kmalloc:
-       mwifiex_free_adapter(adapter);
-
-err_init_sw:
-       up(sem);
-
-exit_sem_err:
-       return -1;
-}
-EXPORT_SYMBOL_GPL(mwifiex_add_card);
-
-/*
- * This function removes the card.
- *
- * This function follows the following major steps to remove the device -
- *      - Stop data traffic
- *      - Shutdown firmware
- *      - Remove the logical interfaces
- *      - Terminate the work queue
- *      - Unregister the device
- *      - Free the adapter structure
- */
-int mwifiex_remove_card(struct mwifiex_adapter *adapter, struct semaphore *sem)
-{
-       struct mwifiex_private *priv = NULL;
-       int i;
-
-       if (down_interruptible(sem))
-               goto exit_sem_err;
-
-       if (!adapter)
-               goto exit_remove;
-
-       /* We can no longer handle interrupts once we start doing the teardown
-        * below. */
-       if (adapter->if_ops.disable_int)
-               adapter->if_ops.disable_int(adapter);
-
-       adapter->surprise_removed = true;
-
-       mwifiex_terminate_workqueue(adapter);
-
-       /* Stop data */
-       for (i = 0; i < adapter->priv_num; i++) {
-               priv = adapter->priv[i];
-               if (priv && priv->netdev) {
-                       mwifiex_stop_net_dev_queue(priv->netdev, adapter);
-                       if (netif_carrier_ok(priv->netdev))
-                               netif_carrier_off(priv->netdev);
-               }
-       }
-
-       mwifiex_dbg(adapter, CMD,
-                   "cmd: calling mwifiex_shutdown_drv...\n");
-       adapter->init_wait_q_woken = false;
-
-       if (mwifiex_shutdown_drv(adapter) == -EINPROGRESS)
-               wait_event_interruptible(adapter->init_wait_q,
-                                        adapter->init_wait_q_woken);
-       mwifiex_dbg(adapter, CMD,
-                   "cmd: mwifiex_shutdown_drv done\n");
-       if (atomic_read(&adapter->rx_pending) ||
-           atomic_read(&adapter->tx_pending) ||
-           atomic_read(&adapter->cmd_pending)) {
-               mwifiex_dbg(adapter, ERROR,
-                           "rx_pending=%d, tx_pending=%d,\t"
-                           "cmd_pending=%d\n",
-                           atomic_read(&adapter->rx_pending),
-                           atomic_read(&adapter->tx_pending),
-                           atomic_read(&adapter->cmd_pending));
-       }
-
-       for (i = 0; i < adapter->priv_num; i++) {
-               priv = adapter->priv[i];
-
-               if (!priv)
-                       continue;
-
-               rtnl_lock();
-               if (priv->netdev &&
-                   priv->wdev.iftype != NL80211_IFTYPE_UNSPECIFIED)
-                       mwifiex_del_virtual_intf(adapter->wiphy, &priv->wdev);
-               rtnl_unlock();
-       }
-
-       wiphy_unregister(adapter->wiphy);
-       wiphy_free(adapter->wiphy);
-
-       /* Unregister device */
-       mwifiex_dbg(adapter, INFO,
-                   "info: unregister device\n");
-       if (adapter->if_ops.unregister_dev)
-               adapter->if_ops.unregister_dev(adapter);
-       /* Free adapter structure */
-       mwifiex_dbg(adapter, INFO,
-                   "info: free adapter\n");
-       mwifiex_free_adapter(adapter);
-
-exit_remove:
-       up(sem);
-exit_sem_err:
-       return 0;
-}
-EXPORT_SYMBOL_GPL(mwifiex_remove_card);
-
-void _mwifiex_dbg(const struct mwifiex_adapter *adapter, int mask,
-                 const char *fmt, ...)
-{
-       struct va_format vaf;
-       va_list args;
-
-       if (!adapter->dev || !(adapter->debug_mask & mask))
-               return;
-
-       va_start(args, fmt);
-
-       vaf.fmt = fmt;
-       vaf.va = &args;
-
-       dev_info(adapter->dev, "%pV", &vaf);
-
-       va_end(args);
-}
-EXPORT_SYMBOL_GPL(_mwifiex_dbg);
-
-/*
- * This function initializes the module.
- *
- * The debug FS is also initialized if configured.
- */
-static int
-mwifiex_init_module(void)
-{
-#ifdef CONFIG_DEBUG_FS
-       mwifiex_debugfs_init();
-#endif
-       return 0;
-}
-
-/*
- * This function cleans up the module.
- *
- * The debug FS is removed if available.
- */
-static void
-mwifiex_cleanup_module(void)
-{
-#ifdef CONFIG_DEBUG_FS
-       mwifiex_debugfs_remove();
-#endif
-}
-
-module_init(mwifiex_init_module);
-module_exit(mwifiex_cleanup_module);
-
-MODULE_AUTHOR("Marvell International Ltd.");
-MODULE_DESCRIPTION("Marvell WiFi-Ex Driver version " VERSION);
-MODULE_VERSION(VERSION);
-MODULE_LICENSE("GPL v2");
diff --git a/drivers/net/wireless/mwifiex/main.h b/drivers/net/wireless/mwifiex/main.h
deleted file mode 100644 (file)
index 3959f1c..0000000
+++ /dev/null
@@ -1,1579 +0,0 @@
-/*
- * Marvell Wireless LAN device driver: major data structures and prototypes
- *
- * Copyright (C) 2011-2014, Marvell International Ltd.
- *
- * This software file (the "File") is distributed by Marvell International
- * Ltd. under the terms of the GNU General Public License Version 2, June 1991
- * (the "License").  You may use, redistribute and/or modify this File in
- * accordance with the terms and conditions of the License, a copy of which
- * is available by writing to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the
- * worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
- *
- * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
- * ARE EXPRESSLY DISCLAIMED.  The License provides additional details about
- * this warranty disclaimer.
- */
-
-#ifndef _MWIFIEX_MAIN_H_
-#define _MWIFIEX_MAIN_H_
-
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/sched.h>
-#include <linux/semaphore.h>
-#include <linux/ip.h>
-#include <linux/skbuff.h>
-#include <linux/if_arp.h>
-#include <linux/etherdevice.h>
-#include <net/sock.h>
-#include <net/lib80211.h>
-#include <linux/vmalloc.h>
-#include <linux/firmware.h>
-#include <linux/ctype.h>
-#include <linux/of.h>
-#include <linux/idr.h>
-#include <linux/inetdevice.h>
-#include <linux/devcoredump.h>
-
-#include "decl.h"
-#include "ioctl.h"
-#include "util.h"
-#include "fw.h"
-#include "pcie.h"
-#include "usb.h"
-#include "sdio.h"
-
-extern const char driver_version[];
-
-struct mwifiex_adapter;
-struct mwifiex_private;
-
-enum {
-       MWIFIEX_ASYNC_CMD,
-       MWIFIEX_SYNC_CMD
-};
-
-#define MWIFIEX_DRIVER_MODE_STA                        BIT(0)
-#define MWIFIEX_DRIVER_MODE_UAP                        BIT(1)
-#define MWIFIEX_DRIVER_MODE_P2P                        BIT(2)
-#define MWIFIEX_DRIVER_MODE_BITMASK            (BIT(0) | BIT(1) | BIT(2))
-
-#define MWIFIEX_MAX_AP                         64
-
-#define MWIFIEX_MAX_PKTS_TXQ                   16
-
-#define MWIFIEX_DEFAULT_WATCHDOG_TIMEOUT       (5 * HZ)
-
-#define MWIFIEX_TIMER_10S                      10000
-#define MWIFIEX_TIMER_1S                       1000
-
-#define MAX_TX_PENDING      100
-#define LOW_TX_PENDING      80
-
-#define HIGH_RX_PENDING     50
-#define LOW_RX_PENDING      20
-
-#define MWIFIEX_UPLD_SIZE               (2312)
-
-#define MAX_EVENT_SIZE                  2048
-
-#define ARP_FILTER_MAX_BUF_SIZE         68
-
-#define MWIFIEX_KEY_BUFFER_SIZE                        16
-#define MWIFIEX_DEFAULT_LISTEN_INTERVAL 10
-#define MWIFIEX_MAX_REGION_CODE         7
-
-#define DEFAULT_BCN_AVG_FACTOR          8
-#define DEFAULT_DATA_AVG_FACTOR         8
-
-#define FIRST_VALID_CHANNEL                            0xff
-#define DEFAULT_AD_HOC_CHANNEL                 6
-#define DEFAULT_AD_HOC_CHANNEL_A               36
-
-#define DEFAULT_BCN_MISS_TIMEOUT               5
-
-#define MAX_SCAN_BEACON_BUFFER                 8000
-
-#define SCAN_BEACON_ENTRY_PAD                  6
-
-#define MWIFIEX_PASSIVE_SCAN_CHAN_TIME 110
-#define MWIFIEX_ACTIVE_SCAN_CHAN_TIME  30
-#define MWIFIEX_SPECIFIC_SCAN_CHAN_TIME        30
-#define MWIFIEX_DEF_SCAN_CHAN_GAP_TIME  50
-
-#define SCAN_RSSI(RSSI)                                        (0x100 - ((u8)(RSSI)))
-
-#define MWIFIEX_MAX_TOTAL_SCAN_TIME    (MWIFIEX_TIMER_10S - MWIFIEX_TIMER_1S)
-
-#define RSN_GTK_OUI_OFFSET                             2
-
-#define MWIFIEX_OUI_NOT_PRESENT                        0
-#define MWIFIEX_OUI_PRESENT                            1
-
-#define PKT_TYPE_MGMT  0xE5
-
-/*
- * Do not check for data_received for USB, as data_received
- * is handled in mwifiex_usb_recv for USB
- */
-#define IS_CARD_RX_RCVD(adapter) (adapter->cmd_resp_received || \
-                               adapter->event_received || \
-                               adapter->data_received)
-
-#define MWIFIEX_TYPE_CMD                               1
-#define MWIFIEX_TYPE_DATA                              0
-#define MWIFIEX_TYPE_AGGR_DATA                         10
-#define MWIFIEX_TYPE_EVENT                             3
-
-#define MAX_BITMAP_RATES_SIZE                  18
-
-#define MAX_CHANNEL_BAND_BG     14
-#define MAX_CHANNEL_BAND_A      165
-
-#define MAX_FREQUENCY_BAND_BG   2484
-
-#define MWIFIEX_EVENT_HEADER_LEN           4
-#define MWIFIEX_UAP_EVENT_EXTRA_HEADER    2
-
-#define MWIFIEX_TYPE_LEN                       4
-#define MWIFIEX_USB_TYPE_CMD                   0xF00DFACE
-#define MWIFIEX_USB_TYPE_DATA                  0xBEADC0DE
-#define MWIFIEX_USB_TYPE_EVENT                 0xBEEFFACE
-
-/* Threshold for tx_timeout_cnt before we trigger a card reset */
-#define TX_TIMEOUT_THRESHOLD   6
-
-#define MWIFIEX_DRV_INFO_SIZE_MAX 0x40000
-
-/* Address alignment */
-#define MWIFIEX_ALIGN_ADDR(p, a) (((long)(p) + (a) - 1) & ~((a) - 1))
-
-/**
- *enum mwifiex_debug_level  -  marvell wifi debug level
- */
-enum MWIFIEX_DEBUG_LEVEL {
-       MWIFIEX_DBG_MSG         = 0x00000001,
-       MWIFIEX_DBG_FATAL       = 0x00000002,
-       MWIFIEX_DBG_ERROR       = 0x00000004,
-       MWIFIEX_DBG_DATA        = 0x00000008,
-       MWIFIEX_DBG_CMD         = 0x00000010,
-       MWIFIEX_DBG_EVENT       = 0x00000020,
-       MWIFIEX_DBG_INTR        = 0x00000040,
-       MWIFIEX_DBG_IOCTL       = 0x00000080,
-
-       MWIFIEX_DBG_MPA_D       = 0x00008000,
-       MWIFIEX_DBG_DAT_D       = 0x00010000,
-       MWIFIEX_DBG_CMD_D       = 0x00020000,
-       MWIFIEX_DBG_EVT_D       = 0x00040000,
-       MWIFIEX_DBG_FW_D        = 0x00080000,
-       MWIFIEX_DBG_IF_D        = 0x00100000,
-
-       MWIFIEX_DBG_ENTRY       = 0x10000000,
-       MWIFIEX_DBG_WARN        = 0x20000000,
-       MWIFIEX_DBG_INFO        = 0x40000000,
-       MWIFIEX_DBG_DUMP        = 0x80000000,
-
-       MWIFIEX_DBG_ANY         = 0xffffffff
-};
-
-#define MWIFIEX_DEFAULT_DEBUG_MASK     (MWIFIEX_DBG_MSG | \
-                                       MWIFIEX_DBG_FATAL | \
-                                       MWIFIEX_DBG_ERROR)
-
-__printf(3, 4)
-void _mwifiex_dbg(const struct mwifiex_adapter *adapter, int mask,
-                 const char *fmt, ...);
-#define mwifiex_dbg(adapter, mask, fmt, ...)                           \
-       _mwifiex_dbg(adapter, MWIFIEX_DBG_##mask, fmt, ##__VA_ARGS__)
-
-#define DEBUG_DUMP_DATA_MAX_LEN                128
-#define mwifiex_dbg_dump(adapter, dbg_mask, str, buf, len)     \
-do {                                                           \
-       if ((adapter)->debug_mask & MWIFIEX_DBG_##dbg_mask)     \
-               print_hex_dump(KERN_DEBUG, str,                 \
-                              DUMP_PREFIX_OFFSET, 16, 1,       \
-                              buf, len, false);                \
-} while (0)
-
-struct mwifiex_dbg {
-       u32 num_cmd_host_to_card_failure;
-       u32 num_cmd_sleep_cfm_host_to_card_failure;
-       u32 num_tx_host_to_card_failure;
-       u32 num_event_deauth;
-       u32 num_event_disassoc;
-       u32 num_event_link_lost;
-       u32 num_cmd_deauth;
-       u32 num_cmd_assoc_success;
-       u32 num_cmd_assoc_failure;
-       u32 num_tx_timeout;
-       u16 timeout_cmd_id;
-       u16 timeout_cmd_act;
-       u16 last_cmd_id[DBG_CMD_NUM];
-       u16 last_cmd_act[DBG_CMD_NUM];
-       u16 last_cmd_index;
-       u16 last_cmd_resp_id[DBG_CMD_NUM];
-       u16 last_cmd_resp_index;
-       u16 last_event[DBG_CMD_NUM];
-       u16 last_event_index;
-};
-
-enum MWIFIEX_HARDWARE_STATUS {
-       MWIFIEX_HW_STATUS_READY,
-       MWIFIEX_HW_STATUS_INITIALIZING,
-       MWIFIEX_HW_STATUS_INIT_DONE,
-       MWIFIEX_HW_STATUS_RESET,
-       MWIFIEX_HW_STATUS_CLOSING,
-       MWIFIEX_HW_STATUS_NOT_READY
-};
-
-enum MWIFIEX_802_11_POWER_MODE {
-       MWIFIEX_802_11_POWER_MODE_CAM,
-       MWIFIEX_802_11_POWER_MODE_PSP
-};
-
-struct mwifiex_tx_param {
-       u32 next_pkt_len;
-};
-
-enum MWIFIEX_PS_STATE {
-       PS_STATE_AWAKE,
-       PS_STATE_PRE_SLEEP,
-       PS_STATE_SLEEP_CFM,
-       PS_STATE_SLEEP
-};
-
-enum mwifiex_iface_type {
-       MWIFIEX_SDIO,
-       MWIFIEX_PCIE,
-       MWIFIEX_USB
-};
-
-struct mwifiex_add_ba_param {
-       u32 tx_win_size;
-       u32 rx_win_size;
-       u32 timeout;
-       u8 tx_amsdu;
-       u8 rx_amsdu;
-};
-
-struct mwifiex_tx_aggr {
-       u8 ampdu_user;
-       u8 ampdu_ap;
-       u8 amsdu;
-};
-
-enum mwifiex_ba_status {
-       BA_SETUP_NONE = 0,
-       BA_SETUP_INPROGRESS,
-       BA_SETUP_COMPLETE
-};
-
-struct mwifiex_ra_list_tbl {
-       struct list_head list;
-       struct sk_buff_head skb_head;
-       u8 ra[ETH_ALEN];
-       u32 is_11n_enabled;
-       u16 max_amsdu;
-       u16 ba_pkt_count;
-       u8 ba_packet_thr;
-       enum mwifiex_ba_status ba_status;
-       u8 amsdu_in_ampdu;
-       u16 total_pkt_count;
-       bool tdls_link;
-       bool tx_paused;
-};
-
-struct mwifiex_tid_tbl {
-       struct list_head ra_list;
-};
-
-#define WMM_HIGHEST_PRIORITY           7
-#define HIGH_PRIO_TID                          7
-#define LOW_PRIO_TID                           0
-
-struct mwifiex_wmm_desc {
-       struct mwifiex_tid_tbl tid_tbl_ptr[MAX_NUM_TID];
-       u32 packets_out[MAX_NUM_TID];
-       u32 pkts_paused[MAX_NUM_TID];
-       /* spin lock to protect ra_list */
-       spinlock_t ra_list_spinlock;
-       struct mwifiex_wmm_ac_status ac_status[IEEE80211_NUM_ACS];
-       enum mwifiex_wmm_ac_e ac_down_graded_vals[IEEE80211_NUM_ACS];
-       u32 drv_pkt_delay_max;
-       u8 queue_priority[IEEE80211_NUM_ACS];
-       u32 user_pri_pkt_tx_ctrl[WMM_HIGHEST_PRIORITY + 1];     /* UP: 0 to 7 */
-       /* Number of transmit packets queued */
-       atomic_t tx_pkts_queued;
-       /* Tracks highest priority with a packet queued */
-       atomic_t highest_queued_prio;
-};
-
-struct mwifiex_802_11_security {
-       u8 wpa_enabled;
-       u8 wpa2_enabled;
-       u8 wapi_enabled;
-       u8 wapi_key_on;
-       u8 wep_enabled;
-       u32 authentication_mode;
-       u8 is_authtype_auto;
-       u32 encryption_mode;
-};
-
-struct ieee_types_header {
-       u8 element_id;
-       u8 len;
-} __packed;
-
-struct ieee_types_vendor_specific {
-       struct ieee_types_vendor_header vend_hdr;
-       u8 data[IEEE_MAX_IE_SIZE - sizeof(struct ieee_types_vendor_header)];
-} __packed;
-
-struct ieee_types_generic {
-       struct ieee_types_header ieee_hdr;
-       u8 data[IEEE_MAX_IE_SIZE - sizeof(struct ieee_types_header)];
-} __packed;
-
-struct ieee_types_bss_co_2040 {
-       struct ieee_types_header ieee_hdr;
-       u8 bss_2040co;
-} __packed;
-
-struct ieee_types_extcap {
-       struct ieee_types_header ieee_hdr;
-       u8 ext_capab[8];
-} __packed;
-
-struct ieee_types_vht_cap {
-       struct ieee_types_header ieee_hdr;
-       struct ieee80211_vht_cap vhtcap;
-} __packed;
-
-struct ieee_types_vht_oper {
-       struct ieee_types_header ieee_hdr;
-       struct ieee80211_vht_operation vhtoper;
-} __packed;
-
-struct ieee_types_aid {
-       struct ieee_types_header ieee_hdr;
-       u16 aid;
-} __packed;
-
-struct mwifiex_bssdescriptor {
-       u8 mac_address[ETH_ALEN];
-       struct cfg80211_ssid ssid;
-       u32 privacy;
-       s32 rssi;
-       u32 channel;
-       u32 freq;
-       u16 beacon_period;
-       u8 erp_flags;
-       u32 bss_mode;
-       u8 supported_rates[MWIFIEX_SUPPORTED_RATES];
-       u8 data_rates[MWIFIEX_SUPPORTED_RATES];
-       /* Network band.
-        * BAND_B(0x01): 'b' band
-        * BAND_G(0x02): 'g' band
-        * BAND_A(0X04): 'a' band
-        */
-       u16 bss_band;
-       u64 fw_tsf;
-       u64 timestamp;
-       union ieee_types_phy_param_set phy_param_set;
-       union ieee_types_ss_param_set ss_param_set;
-       u16 cap_info_bitmap;
-       struct ieee_types_wmm_parameter wmm_ie;
-       u8  disable_11n;
-       struct ieee80211_ht_cap *bcn_ht_cap;
-       u16 ht_cap_offset;
-       struct ieee80211_ht_operation *bcn_ht_oper;
-       u16 ht_info_offset;
-       u8 *bcn_bss_co_2040;
-       u16 bss_co_2040_offset;
-       u8 *bcn_ext_cap;
-       u16 ext_cap_offset;
-       struct ieee80211_vht_cap *bcn_vht_cap;
-       u16 vht_cap_offset;
-       struct ieee80211_vht_operation *bcn_vht_oper;
-       u16 vht_info_offset;
-       struct ieee_types_oper_mode_ntf *oper_mode;
-       u16 oper_mode_offset;
-       u8 disable_11ac;
-       struct ieee_types_vendor_specific *bcn_wpa_ie;
-       u16 wpa_offset;
-       struct ieee_types_generic *bcn_rsn_ie;
-       u16 rsn_offset;
-       struct ieee_types_generic *bcn_wapi_ie;
-       u16 wapi_offset;
-       u8 *beacon_buf;
-       u32 beacon_buf_size;
-       u8 sensed_11h;
-       u8 local_constraint;
-       u8 chan_sw_ie_present;
-};
-
-struct mwifiex_current_bss_params {
-       struct mwifiex_bssdescriptor bss_descriptor;
-       u8 wmm_enabled;
-       u8 wmm_uapsd_enabled;
-       u8 band;
-       u32 num_of_rates;
-       u8 data_rates[MWIFIEX_SUPPORTED_RATES];
-};
-
-struct mwifiex_sleep_params {
-       u16 sp_error;
-       u16 sp_offset;
-       u16 sp_stable_time;
-       u8 sp_cal_control;
-       u8 sp_ext_sleep_clk;
-       u16 sp_reserved;
-};
-
-struct mwifiex_sleep_period {
-       u16 period;
-       u16 reserved;
-};
-
-struct mwifiex_wep_key {
-       u32 length;
-       u32 key_index;
-       u32 key_length;
-       u8 key_material[MWIFIEX_KEY_BUFFER_SIZE];
-};
-
-#define MAX_REGION_CHANNEL_NUM  2
-
-struct mwifiex_chan_freq_power {
-       u16 channel;
-       u32 freq;
-       u16 max_tx_power;
-       u8 unsupported;
-};
-
-enum state_11d_t {
-       DISABLE_11D = 0,
-       ENABLE_11D = 1,
-};
-
-#define MWIFIEX_MAX_TRIPLET_802_11D            83
-
-struct mwifiex_802_11d_domain_reg {
-       u8 country_code[IEEE80211_COUNTRY_STRING_LEN];
-       u8 no_of_triplet;
-       struct ieee80211_country_ie_triplet
-               triplet[MWIFIEX_MAX_TRIPLET_802_11D];
-};
-
-struct mwifiex_vendor_spec_cfg_ie {
-       u16 mask;
-       u16 flag;
-       u8 ie[MWIFIEX_MAX_VSIE_LEN];
-};
-
-struct wps {
-       u8 session_enable;
-};
-
-struct mwifiex_roc_cfg {
-       u64 cookie;
-       struct ieee80211_channel chan;
-};
-
-#define MWIFIEX_FW_DUMP_IDX            0xff
-#define MWIFIEX_DRV_INFO_IDX           20
-#define FW_DUMP_MAX_NAME_LEN           8
-#define FW_DUMP_HOST_READY             0xEE
-#define FW_DUMP_DONE                   0xFF
-#define FW_DUMP_READ_DONE              0xFE
-
-struct memory_type_mapping {
-       u8 mem_name[FW_DUMP_MAX_NAME_LEN];
-       u8 *mem_ptr;
-       u32 mem_size;
-       u8 done_flag;
-};
-
-enum rdwr_status {
-       RDWR_STATUS_SUCCESS = 0,
-       RDWR_STATUS_FAILURE = 1,
-       RDWR_STATUS_DONE = 2
-};
-
-enum mwifiex_iface_work_flags {
-       MWIFIEX_IFACE_WORK_DEVICE_DUMP,
-       MWIFIEX_IFACE_WORK_CARD_RESET,
-};
-
-struct mwifiex_private {
-       struct mwifiex_adapter *adapter;
-       u8 bss_type;
-       u8 bss_role;
-       u8 bss_priority;
-       u8 bss_num;
-       u8 bss_started;
-       u8 frame_type;
-       u8 curr_addr[ETH_ALEN];
-       u8 media_connected;
-       u8 port_open;
-       u8 usb_port;
-       u32 num_tx_timeout;
-       /* track consecutive timeout */
-       u8 tx_timeout_cnt;
-       struct net_device *netdev;
-       struct net_device_stats stats;
-       u16 curr_pkt_filter;
-       u32 bss_mode;
-       u32 pkt_tx_ctrl;
-       u16 tx_power_level;
-       u8 max_tx_power_level;
-       u8 min_tx_power_level;
-       u8 tx_rate;
-       u8 tx_htinfo;
-       u8 rxpd_htinfo;
-       u8 rxpd_rate;
-       u16 rate_bitmap;
-       u16 bitmap_rates[MAX_BITMAP_RATES_SIZE];
-       u32 data_rate;
-       u8 is_data_rate_auto;
-       u16 bcn_avg_factor;
-       u16 data_avg_factor;
-       s16 data_rssi_last;
-       s16 data_nf_last;
-       s16 data_rssi_avg;
-       s16 data_nf_avg;
-       s16 bcn_rssi_last;
-       s16 bcn_nf_last;
-       s16 bcn_rssi_avg;
-       s16 bcn_nf_avg;
-       struct mwifiex_bssdescriptor *attempted_bss_desc;
-       struct cfg80211_ssid prev_ssid;
-       u8 prev_bssid[ETH_ALEN];
-       struct mwifiex_current_bss_params curr_bss_params;
-       u16 beacon_period;
-       u8 dtim_period;
-       u16 listen_interval;
-       u16 atim_window;
-       u8 adhoc_channel;
-       u8 adhoc_is_link_sensed;
-       u8 adhoc_state;
-       struct mwifiex_802_11_security sec_info;
-       struct mwifiex_wep_key wep_key[NUM_WEP_KEYS];
-       u16 wep_key_curr_index;
-       u8 wpa_ie[256];
-       u8 wpa_ie_len;
-       u8 wpa_is_gtk_set;
-       struct host_cmd_ds_802_11_key_material aes_key;
-       struct host_cmd_ds_802_11_key_material_v2 aes_key_v2;
-       u8 wapi_ie[256];
-       u8 wapi_ie_len;
-       u8 *wps_ie;
-       u8 wps_ie_len;
-       u8 wmm_required;
-       u8 wmm_enabled;
-       u8 wmm_qosinfo;
-       struct mwifiex_wmm_desc wmm;
-       atomic_t wmm_tx_pending[IEEE80211_NUM_ACS];
-       struct list_head sta_list;
-       /* spin lock for associated station/TDLS peers list */
-       spinlock_t sta_list_spinlock;
-       struct list_head auto_tdls_list;
-       /* spin lock for auto TDLS peer list */
-       spinlock_t auto_tdls_lock;
-       struct list_head tx_ba_stream_tbl_ptr;
-       /* spin lock for tx_ba_stream_tbl_ptr queue */
-       spinlock_t tx_ba_stream_tbl_lock;
-       struct mwifiex_tx_aggr aggr_prio_tbl[MAX_NUM_TID];
-       struct mwifiex_add_ba_param add_ba_param;
-       u16 rx_seq[MAX_NUM_TID];
-       u8 tos_to_tid_inv[MAX_NUM_TID];
-       struct list_head rx_reorder_tbl_ptr;
-       /* spin lock for rx_reorder_tbl_ptr queue */
-       spinlock_t rx_reorder_tbl_lock;
-       /* spin lock for Rx packets */
-       spinlock_t rx_pkt_lock;
-
-#define MWIFIEX_ASSOC_RSP_BUF_SIZE  500
-       u8 assoc_rsp_buf[MWIFIEX_ASSOC_RSP_BUF_SIZE];
-       u32 assoc_rsp_size;
-
-#define MWIFIEX_GENIE_BUF_SIZE      256
-       u8 gen_ie_buf[MWIFIEX_GENIE_BUF_SIZE];
-       u8 gen_ie_buf_len;
-
-       struct mwifiex_vendor_spec_cfg_ie vs_ie[MWIFIEX_MAX_VSIE_NUM];
-
-#define MWIFIEX_ASSOC_TLV_BUF_SIZE  256
-       u8 assoc_tlv_buf[MWIFIEX_ASSOC_TLV_BUF_SIZE];
-       u8 assoc_tlv_buf_len;
-
-       u8 *curr_bcn_buf;
-       u32 curr_bcn_size;
-       /* spin lock for beacon buffer */
-       spinlock_t curr_bcn_buf_lock;
-       struct wireless_dev wdev;
-       struct mwifiex_chan_freq_power cfp;
-       char version_str[128];
-#ifdef CONFIG_DEBUG_FS
-       struct dentry *dfs_dev_dir;
-#endif
-       u16 current_key_index;
-       struct semaphore async_sem;
-       struct cfg80211_scan_request *scan_request;
-       u8 cfg_bssid[6];
-       struct wps wps;
-       u8 scan_block;
-       s32 cqm_rssi_thold;
-       u32 cqm_rssi_hyst;
-       u8 subsc_evt_rssi_state;
-       struct mwifiex_ds_misc_subsc_evt async_subsc_evt_storage;
-       struct mwifiex_ie mgmt_ie[MAX_MGMT_IE_INDEX];
-       u16 beacon_idx;
-       u16 proberesp_idx;
-       u16 assocresp_idx;
-       u16 gen_idx;
-       u8 ap_11n_enabled;
-       u8 ap_11ac_enabled;
-       u32 mgmt_frame_mask;
-       struct mwifiex_roc_cfg roc_cfg;
-       bool scan_aborting;
-       u8 csa_chan;
-       unsigned long csa_expire_time;
-       u8 del_list_idx;
-       bool hs2_enabled;
-       struct mwifiex_uap_bss_param bss_cfg;
-       struct cfg80211_chan_def bss_chandef;
-       struct station_parameters *sta_params;
-       struct sk_buff_head tdls_txq;
-       u8 check_tdls_tx;
-       struct timer_list auto_tdls_timer;
-       bool auto_tdls_timer_active;
-       struct idr ack_status_frames;
-       /* spin lock for ack status */
-       spinlock_t ack_status_lock;
-       /** rx histogram data */
-       struct mwifiex_histogram_data *hist_data;
-       struct cfg80211_chan_def dfs_chandef;
-       struct workqueue_struct *dfs_cac_workqueue;
-       struct delayed_work dfs_cac_work;
-       struct timer_list dfs_chan_switch_timer;
-       struct workqueue_struct *dfs_chan_sw_workqueue;
-       struct delayed_work dfs_chan_sw_work;
-       struct cfg80211_beacon_data beacon_after;
-       struct mwifiex_11h_intf_state state_11h;
-       struct mwifiex_ds_mem_rw mem_rw;
-       struct sk_buff_head bypass_txq;
-       struct mwifiex_user_scan_chan hidden_chan[MWIFIEX_USER_SCAN_CHAN_MAX];
-};
-
-
-struct mwifiex_tx_ba_stream_tbl {
-       struct list_head list;
-       int tid;
-       u8 ra[ETH_ALEN];
-       enum mwifiex_ba_status ba_status;
-       u8 amsdu;
-};
-
-struct mwifiex_rx_reorder_tbl;
-
-struct reorder_tmr_cnxt {
-       struct timer_list timer;
-       struct mwifiex_rx_reorder_tbl *ptr;
-       struct mwifiex_private *priv;
-       u8 timer_is_set;
-};
-
-struct mwifiex_rx_reorder_tbl {
-       struct list_head list;
-       int tid;
-       u8 ta[ETH_ALEN];
-       int init_win;
-       int start_win;
-       int win_size;
-       void **rx_reorder_ptr;
-       struct reorder_tmr_cnxt timer_context;
-       u8 amsdu;
-       u8 flags;
-};
-
-struct mwifiex_bss_prio_node {
-       struct list_head list;
-       struct mwifiex_private *priv;
-};
-
-struct mwifiex_bss_prio_tbl {
-       struct list_head bss_prio_head;
-       /* spin lock for bss priority  */
-       spinlock_t bss_prio_lock;
-       struct mwifiex_bss_prio_node *bss_prio_cur;
-};
-
-struct cmd_ctrl_node {
-       struct list_head list;
-       struct mwifiex_private *priv;
-       u32 cmd_oid;
-       u32 cmd_flag;
-       struct sk_buff *cmd_skb;
-       struct sk_buff *resp_skb;
-       void *data_buf;
-       u32 wait_q_enabled;
-       struct sk_buff *skb;
-       u8 *condition;
-       u8 cmd_wait_q_woken;
-};
-
-struct mwifiex_bss_priv {
-       u8 band;
-       u64 fw_tsf;
-};
-
-struct mwifiex_tdls_capab {
-       __le16 capab;
-       u8 rates[32];
-       u8 rates_len;
-       u8 qos_info;
-       u8 coex_2040;
-       u16 aid;
-       struct ieee80211_ht_cap ht_capb;
-       struct ieee80211_ht_operation ht_oper;
-       struct ieee_types_extcap extcap;
-       struct ieee_types_generic rsn_ie;
-       struct ieee80211_vht_cap vhtcap;
-       struct ieee80211_vht_operation vhtoper;
-};
-
-struct mwifiex_station_stats {
-       u64 last_rx;
-       s8 rssi;
-       u64 rx_bytes;
-       u64 tx_bytes;
-       u32 rx_packets;
-       u32 tx_packets;
-       u32 tx_failed;
-       u8 last_tx_rate;
-       u8 last_tx_htinfo;
-};
-
-/* This is AP/TDLS specific structure which stores information
- * about associated/peer STA
- */
-struct mwifiex_sta_node {
-       struct list_head list;
-       u8 mac_addr[ETH_ALEN];
-       u8 is_wmm_enabled;
-       u8 is_11n_enabled;
-       u8 is_11ac_enabled;
-       u8 ampdu_sta[MAX_NUM_TID];
-       u16 rx_seq[MAX_NUM_TID];
-       u16 max_amsdu;
-       u8 tdls_status;
-       struct mwifiex_tdls_capab tdls_cap;
-       struct mwifiex_station_stats stats;
-       u8 tx_pause;
-};
-
-struct mwifiex_auto_tdls_peer {
-       struct list_head list;
-       u8 mac_addr[ETH_ALEN];
-       u8 tdls_status;
-       int rssi;
-       long rssi_jiffies;
-       u8 failure_count;
-       u8 do_discover;
-       u8 do_setup;
-};
-
-struct mwifiex_if_ops {
-       int (*init_if) (struct mwifiex_adapter *);
-       void (*cleanup_if) (struct mwifiex_adapter *);
-       int (*check_fw_status) (struct mwifiex_adapter *, u32);
-       int (*prog_fw) (struct mwifiex_adapter *, struct mwifiex_fw_image *);
-       int (*register_dev) (struct mwifiex_adapter *);
-       void (*unregister_dev) (struct mwifiex_adapter *);
-       int (*enable_int) (struct mwifiex_adapter *);
-       void (*disable_int) (struct mwifiex_adapter *);
-       int (*process_int_status) (struct mwifiex_adapter *);
-       int (*host_to_card) (struct mwifiex_adapter *, u8, struct sk_buff *,
-                            struct mwifiex_tx_param *);
-       int (*wakeup) (struct mwifiex_adapter *);
-       int (*wakeup_complete) (struct mwifiex_adapter *);
-
-       /* Interface specific functions */
-       void (*update_mp_end_port) (struct mwifiex_adapter *, u16);
-       void (*cleanup_mpa_buf) (struct mwifiex_adapter *);
-       int (*cmdrsp_complete) (struct mwifiex_adapter *, struct sk_buff *);
-       int (*event_complete) (struct mwifiex_adapter *, struct sk_buff *);
-       int (*init_fw_port) (struct mwifiex_adapter *);
-       int (*dnld_fw) (struct mwifiex_adapter *, struct mwifiex_fw_image *);
-       void (*card_reset) (struct mwifiex_adapter *);
-       int (*reg_dump)(struct mwifiex_adapter *, char *);
-       void (*device_dump)(struct mwifiex_adapter *);
-       int (*clean_pcie_ring) (struct mwifiex_adapter *adapter);
-       void (*iface_work)(struct work_struct *work);
-       void (*submit_rem_rx_urbs)(struct mwifiex_adapter *adapter);
-       void (*deaggr_pkt)(struct mwifiex_adapter *, struct sk_buff *);
-       void (*multi_port_resync)(struct mwifiex_adapter *);
-       bool (*is_port_ready)(struct mwifiex_private *);
-};
-
-struct mwifiex_adapter {
-       u8 iface_type;
-       unsigned int debug_mask;
-       struct mwifiex_iface_comb iface_limit;
-       struct mwifiex_iface_comb curr_iface_comb;
-       struct mwifiex_private *priv[MWIFIEX_MAX_BSS_NUM];
-       u8 priv_num;
-       const struct firmware *firmware;
-       char fw_name[32];
-       int winner;
-       struct device *dev;
-       struct wiphy *wiphy;
-       u8 perm_addr[ETH_ALEN];
-       bool surprise_removed;
-       u32 fw_release_number;
-       u16 init_wait_q_woken;
-       wait_queue_head_t init_wait_q;
-       void *card;
-       struct mwifiex_if_ops if_ops;
-       atomic_t bypass_tx_pending;
-       atomic_t rx_pending;
-       atomic_t tx_pending;
-       atomic_t cmd_pending;
-       struct workqueue_struct *workqueue;
-       struct work_struct main_work;
-       struct workqueue_struct *rx_workqueue;
-       struct work_struct rx_work;
-       struct workqueue_struct *dfs_workqueue;
-       struct work_struct dfs_work;
-       bool rx_work_enabled;
-       bool rx_processing;
-       bool delay_main_work;
-       bool rx_locked;
-       bool main_locked;
-       struct mwifiex_bss_prio_tbl bss_prio_tbl[MWIFIEX_MAX_BSS_NUM];
-       /* spin lock for init/shutdown */
-       spinlock_t mwifiex_lock;
-       /* spin lock for main process */
-       spinlock_t main_proc_lock;
-       u32 mwifiex_processing;
-       u8 more_task_flag;
-       u16 tx_buf_size;
-       u16 curr_tx_buf_size;
-       /* sdio single port rx aggregation capability */
-       bool host_disable_sdio_rx_aggr;
-       bool sdio_rx_aggr_enable;
-       u16 sdio_rx_block_size;
-       u32 ioport;
-       enum MWIFIEX_HARDWARE_STATUS hw_status;
-       u16 number_of_antenna;
-       u32 fw_cap_info;
-       /* spin lock for interrupt handling */
-       spinlock_t int_lock;
-       u8 int_status;
-       u32 event_cause;
-       struct sk_buff *event_skb;
-       u8 upld_buf[MWIFIEX_UPLD_SIZE];
-       u8 data_sent;
-       u8 cmd_sent;
-       u8 cmd_resp_received;
-       u8 event_received;
-       u8 data_received;
-       u16 seq_num;
-       struct cmd_ctrl_node *cmd_pool;
-       struct cmd_ctrl_node *curr_cmd;
-       /* spin lock for command */
-       spinlock_t mwifiex_cmd_lock;
-       u8 is_cmd_timedout;
-       u16 last_init_cmd;
-       struct timer_list cmd_timer;
-       struct list_head cmd_free_q;
-       /* spin lock for cmd_free_q */
-       spinlock_t cmd_free_q_lock;
-       struct list_head cmd_pending_q;
-       /* spin lock for cmd_pending_q */
-       spinlock_t cmd_pending_q_lock;
-       struct list_head scan_pending_q;
-       /* spin lock for scan_pending_q */
-       spinlock_t scan_pending_q_lock;
-       /* spin lock for RX processing routine */
-       spinlock_t rx_proc_lock;
-       struct sk_buff_head tx_data_q;
-       atomic_t tx_queued;
-       u32 scan_processing;
-       u16 region_code;
-       struct mwifiex_802_11d_domain_reg domain_reg;
-       u16 scan_probes;
-       u32 scan_mode;
-       u16 specific_scan_time;
-       u16 active_scan_time;
-       u16 passive_scan_time;
-       u16 scan_chan_gap_time;
-       u8 fw_bands;
-       u8 adhoc_start_band;
-       u8 config_bands;
-       struct mwifiex_chan_scan_param_set *scan_channels;
-       u8 tx_lock_flag;
-       struct mwifiex_sleep_params sleep_params;
-       struct mwifiex_sleep_period sleep_period;
-       u16 ps_mode;
-       u32 ps_state;
-       u8 need_to_wakeup;
-       u16 multiple_dtim;
-       u16 local_listen_interval;
-       u16 null_pkt_interval;
-       struct sk_buff *sleep_cfm;
-       u16 bcn_miss_time_out;
-       u16 adhoc_awake_period;
-       u8 is_deep_sleep;
-       u8 delay_null_pkt;
-       u16 delay_to_ps;
-       u16 enhanced_ps_mode;
-       u8 pm_wakeup_card_req;
-       u16 gen_null_pkt;
-       u16 pps_uapsd_mode;
-       u32 pm_wakeup_fw_try;
-       struct timer_list wakeup_timer;
-       u8 is_hs_configured;
-       struct mwifiex_hs_config_param hs_cfg;
-       u8 hs_activated;
-       u16 hs_activate_wait_q_woken;
-       wait_queue_head_t hs_activate_wait_q;
-       bool is_suspended;
-       bool hs_enabling;
-       u8 event_body[MAX_EVENT_SIZE];
-       u32 hw_dot_11n_dev_cap;
-       u8 hw_dev_mcs_support;
-       u8 user_dev_mcs_support;
-       u8 adhoc_11n_enabled;
-       u8 sec_chan_offset;
-       struct mwifiex_dbg dbg;
-       u8 arp_filter[ARP_FILTER_MAX_BUF_SIZE];
-       u32 arp_filter_size;
-       struct mwifiex_wait_queue cmd_wait_q;
-       u8 scan_wait_q_woken;
-       spinlock_t queue_lock;          /* lock for tx queues */
-       u8 country_code[IEEE80211_COUNTRY_STRING_LEN];
-       u16 max_mgmt_ie_index;
-       const struct firmware *cal_data;
-       struct device_node *dt_node;
-
-       /* 11AC */
-       u32 is_hw_11ac_capable;
-       u32 hw_dot_11ac_dev_cap;
-       u32 hw_dot_11ac_mcs_support;
-       u32 usr_dot_11ac_dev_cap_bg;
-       u32 usr_dot_11ac_dev_cap_a;
-       u32 usr_dot_11ac_mcs_support;
-
-       atomic_t pending_bridged_pkts;
-       struct semaphore *card_sem;
-       bool ext_scan;
-       u8 fw_api_ver;
-       u8 key_api_major_ver, key_api_minor_ver;
-       struct memory_type_mapping *mem_type_mapping_tbl;
-       u8 num_mem_types;
-       void *drv_info_dump;
-       u32 drv_info_size;
-       bool scan_chan_gap_enabled;
-       struct sk_buff_head rx_data_q;
-       struct mwifiex_chan_stats *chan_stats;
-       u32 num_in_chan_stats;
-       int survey_idx;
-       bool auto_tdls;
-       u8 coex_scan;
-       u8 coex_min_scan_time;
-       u8 coex_max_scan_time;
-       u8 coex_win_size;
-       u8 coex_tx_win_size;
-       u8 coex_rx_win_size;
-       bool drcs_enabled;
-       u8 active_scan_triggered;
-       bool usb_mc_status;
-       bool usb_mc_setup;
-};
-
-void mwifiex_process_tx_queue(struct mwifiex_adapter *adapter);
-
-int mwifiex_init_lock_list(struct mwifiex_adapter *adapter);
-
-void mwifiex_set_trans_start(struct net_device *dev);
-
-void mwifiex_stop_net_dev_queue(struct net_device *netdev,
-               struct mwifiex_adapter *adapter);
-
-void mwifiex_wake_up_net_dev_queue(struct net_device *netdev,
-               struct mwifiex_adapter *adapter);
-
-int mwifiex_init_priv(struct mwifiex_private *priv);
-void mwifiex_free_priv(struct mwifiex_private *priv);
-
-int mwifiex_init_fw(struct mwifiex_adapter *adapter);
-
-int mwifiex_init_fw_complete(struct mwifiex_adapter *adapter);
-
-int mwifiex_shutdown_drv(struct mwifiex_adapter *adapter);
-
-int mwifiex_shutdown_fw_complete(struct mwifiex_adapter *adapter);
-
-int mwifiex_dnld_fw(struct mwifiex_adapter *, struct mwifiex_fw_image *);
-
-int mwifiex_recv_packet(struct mwifiex_private *priv, struct sk_buff *skb);
-
-int mwifiex_process_mgmt_packet(struct mwifiex_private *priv,
-                               struct sk_buff *skb);
-
-int mwifiex_process_event(struct mwifiex_adapter *adapter);
-
-int mwifiex_complete_cmd(struct mwifiex_adapter *adapter,
-                        struct cmd_ctrl_node *cmd_node);
-
-int mwifiex_send_cmd(struct mwifiex_private *priv, u16 cmd_no,
-                    u16 cmd_action, u32 cmd_oid, void *data_buf, bool sync);
-
-void mwifiex_cmd_timeout_func(unsigned long function_context);
-
-int mwifiex_get_debug_info(struct mwifiex_private *,
-                          struct mwifiex_debug_info *);
-
-int mwifiex_alloc_cmd_buffer(struct mwifiex_adapter *adapter);
-int mwifiex_free_cmd_buffer(struct mwifiex_adapter *adapter);
-void mwifiex_cancel_all_pending_cmd(struct mwifiex_adapter *adapter);
-void mwifiex_cancel_pending_ioctl(struct mwifiex_adapter *adapter);
-
-void mwifiex_insert_cmd_to_free_q(struct mwifiex_adapter *adapter,
-                                 struct cmd_ctrl_node *cmd_node);
-void mwifiex_recycle_cmd_node(struct mwifiex_adapter *adapter,
-                             struct cmd_ctrl_node *cmd_node);
-
-void mwifiex_insert_cmd_to_pending_q(struct mwifiex_adapter *adapter,
-                                    struct cmd_ctrl_node *cmd_node,
-                                    u32 addtail);
-
-int mwifiex_exec_next_cmd(struct mwifiex_adapter *adapter);
-int mwifiex_process_cmdresp(struct mwifiex_adapter *adapter);
-int mwifiex_handle_rx_packet(struct mwifiex_adapter *adapter,
-                            struct sk_buff *skb);
-int mwifiex_process_tx(struct mwifiex_private *priv, struct sk_buff *skb,
-                      struct mwifiex_tx_param *tx_param);
-int mwifiex_send_null_packet(struct mwifiex_private *priv, u8 flags);
-int mwifiex_write_data_complete(struct mwifiex_adapter *adapter,
-                               struct sk_buff *skb, int aggr, int status);
-void mwifiex_clean_txrx(struct mwifiex_private *priv);
-u8 mwifiex_check_last_packet_indication(struct mwifiex_private *priv);
-void mwifiex_check_ps_cond(struct mwifiex_adapter *adapter);
-void mwifiex_process_sleep_confirm_resp(struct mwifiex_adapter *, u8 *,
-                                       u32);
-int mwifiex_cmd_enh_power_mode(struct mwifiex_private *priv,
-                              struct host_cmd_ds_command *cmd,
-                              u16 cmd_action, uint16_t ps_bitmap,
-                              struct mwifiex_ds_auto_ds *auto_ds);
-int mwifiex_ret_enh_power_mode(struct mwifiex_private *priv,
-                              struct host_cmd_ds_command *resp,
-                              struct mwifiex_ds_pm_cfg *pm_cfg);
-void mwifiex_process_hs_config(struct mwifiex_adapter *adapter);
-void mwifiex_hs_activated_event(struct mwifiex_private *priv,
-                                       u8 activated);
-int mwifiex_set_hs_params(struct mwifiex_private *priv, u16 action,
-                         int cmd_type, struct mwifiex_ds_hs_cfg *hs_cfg);
-int mwifiex_ret_802_11_hs_cfg(struct mwifiex_private *priv,
-                             struct host_cmd_ds_command *resp);
-int mwifiex_process_rx_packet(struct mwifiex_private *priv,
-                             struct sk_buff *skb);
-int mwifiex_sta_prepare_cmd(struct mwifiex_private *, uint16_t cmd_no,
-                           u16 cmd_action, u32 cmd_oid,
-                           void *data_buf, void *cmd_buf);
-int mwifiex_uap_prepare_cmd(struct mwifiex_private *priv, uint16_t cmd_no,
-                           u16 cmd_action, u32 cmd_oid,
-                           void *data_buf, void *cmd_buf);
-int mwifiex_process_sta_cmdresp(struct mwifiex_private *, u16 cmdresp_no,
-                               struct host_cmd_ds_command *resp);
-int mwifiex_process_sta_rx_packet(struct mwifiex_private *,
-                                 struct sk_buff *skb);
-int mwifiex_process_uap_rx_packet(struct mwifiex_private *priv,
-                                 struct sk_buff *skb);
-int mwifiex_handle_uap_rx_forward(struct mwifiex_private *priv,
-                                 struct sk_buff *skb);
-int mwifiex_process_sta_event(struct mwifiex_private *);
-int mwifiex_process_uap_event(struct mwifiex_private *);
-void mwifiex_delete_all_station_list(struct mwifiex_private *priv);
-void mwifiex_wmm_del_peer_ra_list(struct mwifiex_private *priv,
-                                 const u8 *ra_addr);
-void *mwifiex_process_sta_txpd(struct mwifiex_private *, struct sk_buff *skb);
-void *mwifiex_process_uap_txpd(struct mwifiex_private *, struct sk_buff *skb);
-int mwifiex_sta_init_cmd(struct mwifiex_private *, u8 first_sta, bool init);
-int mwifiex_cmd_802_11_scan(struct host_cmd_ds_command *cmd,
-                           struct mwifiex_scan_cmd_config *scan_cfg);
-void mwifiex_queue_scan_cmd(struct mwifiex_private *priv,
-                           struct cmd_ctrl_node *cmd_node);
-int mwifiex_ret_802_11_scan(struct mwifiex_private *priv,
-                           struct host_cmd_ds_command *resp);
-s32 mwifiex_ssid_cmp(struct cfg80211_ssid *ssid1, struct cfg80211_ssid *ssid2);
-int mwifiex_associate(struct mwifiex_private *priv,
-                     struct mwifiex_bssdescriptor *bss_desc);
-int mwifiex_cmd_802_11_associate(struct mwifiex_private *priv,
-                                struct host_cmd_ds_command *cmd,
-                                struct mwifiex_bssdescriptor *bss_desc);
-int mwifiex_ret_802_11_associate(struct mwifiex_private *priv,
-                                struct host_cmd_ds_command *resp);
-void mwifiex_reset_connect_state(struct mwifiex_private *priv, u16 reason);
-u8 mwifiex_band_to_radio_type(u8 band);
-int mwifiex_deauthenticate(struct mwifiex_private *priv, u8 *mac);
-void mwifiex_deauthenticate_all(struct mwifiex_adapter *adapter);
-int mwifiex_adhoc_start(struct mwifiex_private *priv,
-                       struct cfg80211_ssid *adhoc_ssid);
-int mwifiex_adhoc_join(struct mwifiex_private *priv,
-                      struct mwifiex_bssdescriptor *bss_desc);
-int mwifiex_cmd_802_11_ad_hoc_start(struct mwifiex_private *priv,
-                                   struct host_cmd_ds_command *cmd,
-                                   struct cfg80211_ssid *req_ssid);
-int mwifiex_cmd_802_11_ad_hoc_join(struct mwifiex_private *priv,
-                                  struct host_cmd_ds_command *cmd,
-                                  struct mwifiex_bssdescriptor *bss_desc);
-int mwifiex_ret_802_11_ad_hoc(struct mwifiex_private *priv,
-                             struct host_cmd_ds_command *resp);
-int mwifiex_cmd_802_11_bg_scan_query(struct host_cmd_ds_command *cmd);
-struct mwifiex_chan_freq_power *mwifiex_get_cfp(struct mwifiex_private *priv,
-                                               u8 band, u16 channel, u32 freq);
-u32 mwifiex_index_to_data_rate(struct mwifiex_private *priv,
-                              u8 index, u8 ht_info);
-u32 mwifiex_index_to_acs_data_rate(struct mwifiex_private *priv,
-                                  u8 index, u8 ht_info);
-u32 mwifiex_find_freq_from_band_chan(u8, u8);
-int mwifiex_cmd_append_vsie_tlv(struct mwifiex_private *priv, u16 vsie_mask,
-                               u8 **buffer);
-u32 mwifiex_get_active_data_rates(struct mwifiex_private *priv,
-                                   u8 *rates);
-u32 mwifiex_get_supported_rates(struct mwifiex_private *priv, u8 *rates);
-u32 mwifiex_get_rates_from_cfg80211(struct mwifiex_private *priv,
-                                   u8 *rates, u8 radio_type);
-u8 mwifiex_is_rate_auto(struct mwifiex_private *priv);
-extern u16 region_code_index[MWIFIEX_MAX_REGION_CODE];
-void mwifiex_save_curr_bcn(struct mwifiex_private *priv);
-void mwifiex_free_curr_bcn(struct mwifiex_private *priv);
-int mwifiex_cmd_get_hw_spec(struct mwifiex_private *priv,
-                           struct host_cmd_ds_command *cmd);
-int mwifiex_ret_get_hw_spec(struct mwifiex_private *priv,
-                           struct host_cmd_ds_command *resp);
-int is_command_pending(struct mwifiex_adapter *adapter);
-void mwifiex_init_priv_params(struct mwifiex_private *priv,
-                                               struct net_device *dev);
-int mwifiex_set_secure_params(struct mwifiex_private *priv,
-                             struct mwifiex_uap_bss_param *bss_config,
-                             struct cfg80211_ap_settings *params);
-void mwifiex_set_ht_params(struct mwifiex_private *priv,
-                          struct mwifiex_uap_bss_param *bss_cfg,
-                          struct cfg80211_ap_settings *params);
-void mwifiex_set_vht_params(struct mwifiex_private *priv,
-                           struct mwifiex_uap_bss_param *bss_cfg,
-                           struct cfg80211_ap_settings *params);
-void mwifiex_set_tpc_params(struct mwifiex_private *priv,
-                           struct mwifiex_uap_bss_param *bss_cfg,
-                           struct cfg80211_ap_settings *params);
-void mwifiex_set_uap_rates(struct mwifiex_uap_bss_param *bss_cfg,
-                          struct cfg80211_ap_settings *params);
-void mwifiex_set_vht_width(struct mwifiex_private *priv,
-                          enum nl80211_chan_width width,
-                          bool ap_11ac_disable);
-void
-mwifiex_set_wmm_params(struct mwifiex_private *priv,
-                      struct mwifiex_uap_bss_param *bss_cfg,
-                      struct cfg80211_ap_settings *params);
-void mwifiex_set_ba_params(struct mwifiex_private *priv);
-
-void mwifiex_update_ampdu_txwinsize(struct mwifiex_adapter *pmadapter);
-void mwifiex_bt_coex_wlan_param_update_event(struct mwifiex_private *priv,
-                                            struct sk_buff *event_skb);
-
-void mwifiex_set_11ac_ba_params(struct mwifiex_private *priv);
-int mwifiex_cmd_802_11_scan_ext(struct mwifiex_private *priv,
-                               struct host_cmd_ds_command *cmd,
-                               void *data_buf);
-int mwifiex_ret_802_11_scan_ext(struct mwifiex_private *priv,
-                               struct host_cmd_ds_command *resp);
-int mwifiex_handle_event_ext_scan_report(struct mwifiex_private *priv,
-                                        void *buf);
-
-/*
- * This function checks if the queuing is RA based or not.
- */
-static inline u8
-mwifiex_queuing_ra_based(struct mwifiex_private *priv)
-{
-       /*
-        * Currently we assume if we are in Infra, then DA=RA. This might not be
-        * true in the future
-        */
-       if ((priv->bss_mode == NL80211_IFTYPE_STATION) &&
-           (GET_BSS_ROLE(priv) == MWIFIEX_BSS_ROLE_STA))
-               return false;
-
-       return true;
-}
-
-/*
- * This function copies rates.
- */
-static inline u32
-mwifiex_copy_rates(u8 *dest, u32 pos, u8 *src, int len)
-{
-       int i;
-
-       for (i = 0; i < len && src[i]; i++, pos++) {
-               if (pos >= MWIFIEX_SUPPORTED_RATES)
-                       break;
-               dest[pos] = src[i];
-       }
-
-       return pos;
-}
-
-/*
- * This function returns the correct private structure pointer based
- * upon the BSS type and BSS number.
- */
-static inline struct mwifiex_private *
-mwifiex_get_priv_by_id(struct mwifiex_adapter *adapter,
-                      u8 bss_num, u8 bss_type)
-{
-       int i;
-
-       for (i = 0; i < adapter->priv_num; i++) {
-               if (adapter->priv[i]) {
-                       if ((adapter->priv[i]->bss_num == bss_num) &&
-                           (adapter->priv[i]->bss_type == bss_type))
-                               break;
-               }
-       }
-       return ((i < adapter->priv_num) ? adapter->priv[i] : NULL);
-}
-
-/*
- * This function returns the first available private structure pointer
- * based upon the BSS role.
- */
-static inline struct mwifiex_private *
-mwifiex_get_priv(struct mwifiex_adapter *adapter,
-                enum mwifiex_bss_role bss_role)
-{
-       int i;
-
-       for (i = 0; i < adapter->priv_num; i++) {
-               if (adapter->priv[i]) {
-                       if (bss_role == MWIFIEX_BSS_ROLE_ANY ||
-                           GET_BSS_ROLE(adapter->priv[i]) == bss_role)
-                               break;
-               }
-       }
-
-       return ((i < adapter->priv_num) ? adapter->priv[i] : NULL);
-}
-
-/*
- * This function returns the first available unused private structure pointer.
- */
-static inline struct mwifiex_private *
-mwifiex_get_unused_priv(struct mwifiex_adapter *adapter)
-{
-       int i;
-
-       for (i = 0; i < adapter->priv_num; i++) {
-               if (adapter->priv[i]) {
-                       if (adapter->priv[i]->bss_mode ==
-                           NL80211_IFTYPE_UNSPECIFIED)
-                               break;
-               }
-       }
-
-       return ((i < adapter->priv_num) ? adapter->priv[i] : NULL);
-}
-
-/*
- * This function returns the driver private structure of a network device.
- */
-static inline struct mwifiex_private *
-mwifiex_netdev_get_priv(struct net_device *dev)
-{
-       return (struct mwifiex_private *) (*(unsigned long *) netdev_priv(dev));
-}
-
-/*
- * This function checks if a skb holds a management frame.
- */
-static inline bool mwifiex_is_skb_mgmt_frame(struct sk_buff *skb)
-{
-       return (le32_to_cpu(*(__le32 *)skb->data) == PKT_TYPE_MGMT);
-}
-
-/* This function retrieves channel closed for operation by Channel
- * Switch Announcement.
- */
-static inline u8
-mwifiex_11h_get_csa_closed_channel(struct mwifiex_private *priv)
-{
-       if (!priv->csa_chan)
-               return 0;
-
-       /* Clear csa channel, if DFS channel move time has passed */
-       if (time_after(jiffies, priv->csa_expire_time)) {
-               priv->csa_chan = 0;
-               priv->csa_expire_time = 0;
-       }
-
-       return priv->csa_chan;
-}
-
-static inline u8 mwifiex_is_any_intf_active(struct mwifiex_private *priv)
-{
-       struct mwifiex_private *priv_num;
-       int i;
-
-       for (i = 0; i < priv->adapter->priv_num; i++) {
-               priv_num = priv->adapter->priv[i];
-               if (priv_num) {
-                       if ((GET_BSS_ROLE(priv_num) == MWIFIEX_BSS_ROLE_UAP &&
-                            priv_num->bss_started) ||
-                           (GET_BSS_ROLE(priv_num) == MWIFIEX_BSS_ROLE_STA &&
-                            priv_num->media_connected))
-                               return 1;
-               }
-       }
-
-       return 0;
-}
-
-static inline u8 mwifiex_is_tdls_link_setup(u8 status)
-{
-       switch (status) {
-       case TDLS_SETUP_COMPLETE:
-       case TDLS_CHAN_SWITCHING:
-       case TDLS_IN_BASE_CHAN:
-       case TDLS_IN_OFF_CHAN:
-               return true;
-       default:
-               break;
-       }
-
-       return false;
-}
-
-int mwifiex_init_shutdown_fw(struct mwifiex_private *priv,
-                            u32 func_init_shutdown);
-int mwifiex_add_card(void *, struct semaphore *, struct mwifiex_if_ops *, u8);
-int mwifiex_remove_card(struct mwifiex_adapter *, struct semaphore *);
-
-void mwifiex_get_version(struct mwifiex_adapter *adapter, char *version,
-                        int maxlen);
-int mwifiex_request_set_multicast_list(struct mwifiex_private *priv,
-                       struct mwifiex_multicast_list *mcast_list);
-int mwifiex_copy_mcast_addr(struct mwifiex_multicast_list *mlist,
-                           struct net_device *dev);
-int mwifiex_wait_queue_complete(struct mwifiex_adapter *adapter,
-                               struct cmd_ctrl_node *cmd_queued);
-int mwifiex_bss_start(struct mwifiex_private *priv, struct cfg80211_bss *bss,
-                     struct cfg80211_ssid *req_ssid);
-int mwifiex_cancel_hs(struct mwifiex_private *priv, int cmd_type);
-int mwifiex_enable_hs(struct mwifiex_adapter *adapter);
-int mwifiex_disable_auto_ds(struct mwifiex_private *priv);
-int mwifiex_drv_get_data_rate(struct mwifiex_private *priv, u32 *rate);
-int mwifiex_request_scan(struct mwifiex_private *priv,
-                        struct cfg80211_ssid *req_ssid);
-int mwifiex_scan_networks(struct mwifiex_private *priv,
-                         const struct mwifiex_user_scan_cfg *user_scan_in);
-int mwifiex_set_radio(struct mwifiex_private *priv, u8 option);
-
-int mwifiex_set_encode(struct mwifiex_private *priv, struct key_params *kp,
-                      const u8 *key, int key_len, u8 key_index,
-                      const u8 *mac_addr, int disable);
-
-int mwifiex_set_gen_ie(struct mwifiex_private *priv, const u8 *ie, int ie_len);
-
-int mwifiex_get_ver_ext(struct mwifiex_private *priv);
-
-int mwifiex_remain_on_chan_cfg(struct mwifiex_private *priv, u16 action,
-                              struct ieee80211_channel *chan,
-                              unsigned int duration);
-
-int mwifiex_get_stats_info(struct mwifiex_private *priv,
-                          struct mwifiex_ds_get_stats *log);
-
-int mwifiex_reg_write(struct mwifiex_private *priv, u32 reg_type,
-                     u32 reg_offset, u32 reg_value);
-
-int mwifiex_reg_read(struct mwifiex_private *priv, u32 reg_type,
-                    u32 reg_offset, u32 *value);
-
-int mwifiex_eeprom_read(struct mwifiex_private *priv, u16 offset, u16 bytes,
-                       u8 *value);
-
-int mwifiex_set_11n_httx_cfg(struct mwifiex_private *priv, int data);
-
-int mwifiex_get_11n_httx_cfg(struct mwifiex_private *priv, int *data);
-
-int mwifiex_set_tx_rate_cfg(struct mwifiex_private *priv, int tx_rate_index);
-
-int mwifiex_get_tx_rate_cfg(struct mwifiex_private *priv, int *tx_rate_index);
-
-int mwifiex_drv_set_power(struct mwifiex_private *priv, u32 *ps_mode);
-
-int mwifiex_drv_get_driver_version(struct mwifiex_adapter *adapter,
-                                  char *version, int max_len);
-
-int mwifiex_set_tx_power(struct mwifiex_private *priv,
-                        struct mwifiex_power_cfg *power_cfg);
-
-int mwifiex_main_process(struct mwifiex_adapter *);
-
-int mwifiex_queue_tx_pkt(struct mwifiex_private *priv, struct sk_buff *skb);
-
-int mwifiex_get_bss_info(struct mwifiex_private *,
-                        struct mwifiex_bss_info *);
-int mwifiex_fill_new_bss_desc(struct mwifiex_private *priv,
-                             struct cfg80211_bss *bss,
-                             struct mwifiex_bssdescriptor *bss_desc);
-int mwifiex_update_bss_desc_with_ie(struct mwifiex_adapter *adapter,
-                                   struct mwifiex_bssdescriptor *bss_entry);
-int mwifiex_check_network_compatibility(struct mwifiex_private *priv,
-                                       struct mwifiex_bssdescriptor *bss_desc);
-
-u8 mwifiex_chan_type_to_sec_chan_offset(enum nl80211_channel_type chan_type);
-u8 mwifiex_sec_chan_offset_to_chan_type(u8 second_chan_offset);
-
-struct wireless_dev *mwifiex_add_virtual_intf(struct wiphy *wiphy,
-                                             const char *name,
-                                             unsigned char name_assign_type,
-                                             enum nl80211_iftype type,
-                                             u32 *flags,
-                                             struct vif_params *params);
-int mwifiex_del_virtual_intf(struct wiphy *wiphy, struct wireless_dev *wdev);
-
-void mwifiex_set_sys_config_invalid_data(struct mwifiex_uap_bss_param *config);
-
-int mwifiex_add_wowlan_magic_pkt_filter(struct mwifiex_adapter *adapter);
-
-int mwifiex_set_mgmt_ies(struct mwifiex_private *priv,
-                        struct cfg80211_beacon_data *data);
-int mwifiex_del_mgmt_ies(struct mwifiex_private *priv);
-u8 *mwifiex_11d_code_2_region(u8 code);
-void mwifiex_uap_set_channel(struct mwifiex_private *priv,
-                            struct mwifiex_uap_bss_param *bss_cfg,
-                            struct cfg80211_chan_def chandef);
-int mwifiex_config_start_uap(struct mwifiex_private *priv,
-                            struct mwifiex_uap_bss_param *bss_cfg);
-void mwifiex_uap_del_sta_data(struct mwifiex_private *priv,
-                             struct mwifiex_sta_node *node);
-
-void mwifiex_init_11h_params(struct mwifiex_private *priv);
-int mwifiex_is_11h_active(struct mwifiex_private *priv);
-int mwifiex_11h_activate(struct mwifiex_private *priv, bool flag);
-
-void mwifiex_11h_process_join(struct mwifiex_private *priv, u8 **buffer,
-                             struct mwifiex_bssdescriptor *bss_desc);
-int mwifiex_11h_handle_event_chanswann(struct mwifiex_private *priv);
-int mwifiex_dnld_dt_cfgdata(struct mwifiex_private *priv,
-                           struct device_node *node, const char *prefix);
-void mwifiex_dnld_txpwr_table(struct mwifiex_private *priv);
-
-extern const struct ethtool_ops mwifiex_ethtool_ops;
-
-void mwifiex_del_all_sta_list(struct mwifiex_private *priv);
-void mwifiex_del_sta_entry(struct mwifiex_private *priv, const u8 *mac);
-void
-mwifiex_set_sta_ht_cap(struct mwifiex_private *priv, const u8 *ies,
-                      int ies_len, struct mwifiex_sta_node *node);
-struct mwifiex_sta_node *
-mwifiex_add_sta_entry(struct mwifiex_private *priv, const u8 *mac);
-struct mwifiex_sta_node *
-mwifiex_get_sta_entry(struct mwifiex_private *priv, const u8 *mac);
-u8 mwifiex_is_tdls_chan_switching(struct mwifiex_private *priv);
-u8 mwifiex_is_tdls_off_chan(struct mwifiex_private *priv);
-u8 mwifiex_is_send_cmd_allowed(struct mwifiex_private *priv);
-int mwifiex_send_tdls_data_frame(struct mwifiex_private *priv, const u8 *peer,
-                                u8 action_code, u8 dialog_token,
-                                u16 status_code, const u8 *extra_ies,
-                                size_t extra_ies_len);
-int mwifiex_send_tdls_action_frame(struct mwifiex_private *priv, const u8 *peer,
-                                  u8 action_code, u8 dialog_token,
-                                  u16 status_code, const u8 *extra_ies,
-                                  size_t extra_ies_len);
-void mwifiex_process_tdls_action_frame(struct mwifiex_private *priv,
-                                      u8 *buf, int len);
-int mwifiex_tdls_oper(struct mwifiex_private *priv, const u8 *peer, u8 action);
-int mwifiex_get_tdls_link_status(struct mwifiex_private *priv, const u8 *mac);
-int mwifiex_get_tdls_list(struct mwifiex_private *priv,
-                         struct tdls_peer_info *buf);
-void mwifiex_disable_all_tdls_links(struct mwifiex_private *priv);
-bool mwifiex_is_bss_in_11ac_mode(struct mwifiex_private *priv);
-u8 mwifiex_get_center_freq_index(struct mwifiex_private *priv, u8 band,
-                                u32 pri_chan, u8 chan_bw);
-int mwifiex_init_channel_scan_gap(struct mwifiex_adapter *adapter);
-
-int mwifiex_tdls_check_tx(struct mwifiex_private *priv, struct sk_buff *skb);
-void mwifiex_flush_auto_tdls_list(struct mwifiex_private *priv);
-void mwifiex_auto_tdls_update_peer_status(struct mwifiex_private *priv,
-                                         const u8 *mac, u8 link_status);
-void mwifiex_auto_tdls_update_peer_signal(struct mwifiex_private *priv,
-                                         u8 *mac, s8 snr, s8 nflr);
-void mwifiex_check_auto_tdls(unsigned long context);
-void mwifiex_add_auto_tdls_peer(struct mwifiex_private *priv, const u8 *mac);
-void mwifiex_setup_auto_tdls_timer(struct mwifiex_private *priv);
-void mwifiex_clean_auto_tdls(struct mwifiex_private *priv);
-int mwifiex_config_tdls_enable(struct mwifiex_private *priv);
-int mwifiex_config_tdls_disable(struct mwifiex_private *priv);
-int mwifiex_config_tdls_cs_params(struct mwifiex_private *priv);
-int mwifiex_stop_tdls_cs(struct mwifiex_private *priv, const u8 *peer_mac);
-int mwifiex_start_tdls_cs(struct mwifiex_private *priv, const u8 *peer_mac,
-                         u8 primary_chan, u8 second_chan_offset, u8 band);
-
-int mwifiex_cmd_issue_chan_report_request(struct mwifiex_private *priv,
-                                         struct host_cmd_ds_command *cmd,
-                                         void *data_buf);
-int mwifiex_11h_handle_chanrpt_ready(struct mwifiex_private *priv,
-                                    struct sk_buff *skb);
-
-void mwifiex_parse_tx_status_event(struct mwifiex_private *priv,
-                                  void *event_body);
-
-struct sk_buff *
-mwifiex_clone_skb_for_tx_status(struct mwifiex_private *priv,
-                               struct sk_buff *skb, u8 flag, u64 *cookie);
-void mwifiex_dfs_cac_work_queue(struct work_struct *work);
-void mwifiex_dfs_chan_sw_work_queue(struct work_struct *work);
-void mwifiex_abort_cac(struct mwifiex_private *priv);
-int mwifiex_stop_radar_detection(struct mwifiex_private *priv,
-                                struct cfg80211_chan_def *chandef);
-int mwifiex_11h_handle_radar_detected(struct mwifiex_private *priv,
-                                     struct sk_buff *skb);
-
-void mwifiex_hist_data_set(struct mwifiex_private *priv, u8 rx_rate, s8 snr,
-                          s8 nflr);
-void mwifiex_hist_data_reset(struct mwifiex_private *priv);
-void mwifiex_hist_data_add(struct mwifiex_private *priv,
-                          u8 rx_rate, s8 snr, s8 nflr);
-u8 mwifiex_adjust_data_rate(struct mwifiex_private *priv,
-                           u8 rx_rate, u8 ht_info);
-
-void mwifiex_drv_info_dump(struct mwifiex_adapter *adapter);
-void mwifiex_upload_device_dump(struct mwifiex_adapter *adapter);
-void *mwifiex_alloc_dma_align_buf(int rx_len, gfp_t flags);
-void mwifiex_queue_main_work(struct mwifiex_adapter *adapter);
-void mwifiex_coex_ampdu_rxwinsize(struct mwifiex_adapter *adapter);
-void mwifiex_11n_delba(struct mwifiex_private *priv, int tid);
-int mwifiex_send_domain_info_cmd_fw(struct wiphy *wiphy);
-void mwifiex_process_tx_pause_event(struct mwifiex_private *priv,
-                                   struct sk_buff *event);
-void mwifiex_process_multi_chan_event(struct mwifiex_private *priv,
-                                     struct sk_buff *event_skb);
-void mwifiex_multi_chan_resync(struct mwifiex_adapter *adapter);
-
-#ifdef CONFIG_DEBUG_FS
-void mwifiex_debugfs_init(void);
-void mwifiex_debugfs_remove(void);
-
-void mwifiex_dev_debugfs_init(struct mwifiex_private *priv);
-void mwifiex_dev_debugfs_remove(struct mwifiex_private *priv);
-#endif
-#endif /* !_MWIFIEX_MAIN_H_ */
diff --git a/drivers/net/wireless/mwifiex/pcie.c b/drivers/net/wireless/mwifiex/pcie.c
deleted file mode 100644 (file)
index 21192b6..0000000
+++ /dev/null
@@ -1,2742 +0,0 @@
-/*
- * Marvell Wireless LAN device driver: PCIE specific handling
- *
- * Copyright (C) 2011-2014, Marvell International Ltd.
- *
- * This software file (the "File") is distributed by Marvell International
- * Ltd. under the terms of the GNU General Public License Version 2, June 1991
- * (the "License").  You may use, redistribute and/or modify this File in
- * accordance with the terms and conditions of the License, a copy of which
- * is available by writing to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the
- * worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
- *
- * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
- * ARE EXPRESSLY DISCLAIMED.  The License provides additional details about
- * this warranty disclaimer.
- */
-
-#include <linux/firmware.h>
-
-#include "decl.h"
-#include "ioctl.h"
-#include "util.h"
-#include "fw.h"
-#include "main.h"
-#include "wmm.h"
-#include "11n.h"
-#include "pcie.h"
-
-#define PCIE_VERSION   "1.0"
-#define DRV_NAME        "Marvell mwifiex PCIe"
-
-static u8 user_rmmod;
-
-static struct mwifiex_if_ops pcie_ops;
-
-static struct semaphore add_remove_card_sem;
-
-static struct memory_type_mapping mem_type_mapping_tbl[] = {
-       {"ITCM", NULL, 0, 0xF0},
-       {"DTCM", NULL, 0, 0xF1},
-       {"SQRAM", NULL, 0, 0xF2},
-       {"IRAM", NULL, 0, 0xF3},
-       {"APU", NULL, 0, 0xF4},
-       {"CIU", NULL, 0, 0xF5},
-       {"ICU", NULL, 0, 0xF6},
-       {"MAC", NULL, 0, 0xF7},
-};
-
-static int
-mwifiex_map_pci_memory(struct mwifiex_adapter *adapter, struct sk_buff *skb,
-                      size_t size, int flags)
-{
-       struct pcie_service_card *card = adapter->card;
-       struct mwifiex_dma_mapping mapping;
-
-       mapping.addr = pci_map_single(card->dev, skb->data, size, flags);
-       if (pci_dma_mapping_error(card->dev, mapping.addr)) {
-               mwifiex_dbg(adapter, ERROR, "failed to map pci memory!\n");
-               return -1;
-       }
-       mapping.len = size;
-       mwifiex_store_mapping(skb, &mapping);
-       return 0;
-}
-
-static void mwifiex_unmap_pci_memory(struct mwifiex_adapter *adapter,
-                                    struct sk_buff *skb, int flags)
-{
-       struct pcie_service_card *card = adapter->card;
-       struct mwifiex_dma_mapping mapping;
-
-       mwifiex_get_mapping(skb, &mapping);
-       pci_unmap_single(card->dev, mapping.addr, mapping.len, flags);
-}
-
-/*
- * This function reads sleep cookie and checks if FW is ready
- */
-static bool mwifiex_pcie_ok_to_access_hw(struct mwifiex_adapter *adapter)
-{
-       u32 *cookie_addr;
-       struct pcie_service_card *card = adapter->card;
-       const struct mwifiex_pcie_card_reg *reg = card->pcie.reg;
-
-       if (!reg->sleep_cookie)
-               return true;
-
-       if (card->sleep_cookie_vbase) {
-               cookie_addr = (u32 *)card->sleep_cookie_vbase;
-               mwifiex_dbg(adapter, INFO,
-                           "info: ACCESS_HW: sleep cookie=0x%x\n",
-                           *cookie_addr);
-               if (*cookie_addr == FW_AWAKE_COOKIE)
-                       return true;
-       }
-
-       return false;
-}
-
-#ifdef CONFIG_PM_SLEEP
-/*
- * Kernel needs to suspend all functions separately. Therefore all
- * registered functions must have drivers with suspend and resume
- * methods. Failing that the kernel simply removes the whole card.
- *
- * If already not suspended, this function allocates and sends a host
- * sleep activate request to the firmware and turns off the traffic.
- */
-static int mwifiex_pcie_suspend(struct device *dev)
-{
-       struct mwifiex_adapter *adapter;
-       struct pcie_service_card *card;
-       int hs_actived;
-       struct pci_dev *pdev = to_pci_dev(dev);
-
-       if (pdev) {
-               card = pci_get_drvdata(pdev);
-               if (!card || !card->adapter) {
-                       pr_err("Card or adapter structure is not valid\n");
-                       return 0;
-               }
-       } else {
-               pr_err("PCIE device is not specified\n");
-               return 0;
-       }
-
-       adapter = card->adapter;
-
-       hs_actived = mwifiex_enable_hs(adapter);
-
-       /* Indicate device suspended */
-       adapter->is_suspended = true;
-       adapter->hs_enabling = false;
-
-       return 0;
-}
-
-/*
- * Kernel needs to suspend all functions separately. Therefore all
- * registered functions must have drivers with suspend and resume
- * methods. Failing that the kernel simply removes the whole card.
- *
- * If already not resumed, this function turns on the traffic and
- * sends a host sleep cancel request to the firmware.
- */
-static int mwifiex_pcie_resume(struct device *dev)
-{
-       struct mwifiex_adapter *adapter;
-       struct pcie_service_card *card;
-       struct pci_dev *pdev = to_pci_dev(dev);
-
-       if (pdev) {
-               card = pci_get_drvdata(pdev);
-               if (!card || !card->adapter) {
-                       pr_err("Card or adapter structure is not valid\n");
-                       return 0;
-               }
-       } else {
-               pr_err("PCIE device is not specified\n");
-               return 0;
-       }
-
-       adapter = card->adapter;
-
-       if (!adapter->is_suspended) {
-               mwifiex_dbg(adapter, WARN,
-                           "Device already resumed\n");
-               return 0;
-       }
-
-       adapter->is_suspended = false;
-
-       mwifiex_cancel_hs(mwifiex_get_priv(adapter, MWIFIEX_BSS_ROLE_STA),
-                         MWIFIEX_ASYNC_CMD);
-
-       return 0;
-}
-#endif
-
-/*
- * This function probes an mwifiex device and registers it. It allocates
- * the card structure, enables PCIE function number and initiates the
- * device registration and initialization procedure by adding a logical
- * interface.
- */
-static int mwifiex_pcie_probe(struct pci_dev *pdev,
-                                       const struct pci_device_id *ent)
-{
-       struct pcie_service_card *card;
-
-       pr_debug("info: vendor=0x%4.04X device=0x%4.04X rev=%d\n",
-                pdev->vendor, pdev->device, pdev->revision);
-
-       card = kzalloc(sizeof(struct pcie_service_card), GFP_KERNEL);
-       if (!card)
-               return -ENOMEM;
-
-       card->dev = pdev;
-
-       if (ent->driver_data) {
-               struct mwifiex_pcie_device *data = (void *)ent->driver_data;
-               card->pcie.firmware = data->firmware;
-               card->pcie.reg = data->reg;
-               card->pcie.blksz_fw_dl = data->blksz_fw_dl;
-               card->pcie.tx_buf_size = data->tx_buf_size;
-               card->pcie.can_dump_fw = data->can_dump_fw;
-               card->pcie.can_ext_scan = data->can_ext_scan;
-       }
-
-       if (mwifiex_add_card(card, &add_remove_card_sem, &pcie_ops,
-                            MWIFIEX_PCIE)) {
-               pr_err("%s failed\n", __func__);
-               kfree(card);
-               return -1;
-       }
-
-       return 0;
-}
-
-/*
- * This function removes the interface and frees up the card structure.
- */
-static void mwifiex_pcie_remove(struct pci_dev *pdev)
-{
-       struct pcie_service_card *card;
-       struct mwifiex_adapter *adapter;
-       struct mwifiex_private *priv;
-
-       card = pci_get_drvdata(pdev);
-       if (!card)
-               return;
-
-       adapter = card->adapter;
-       if (!adapter || !adapter->priv_num)
-               return;
-
-       if (user_rmmod) {
-#ifdef CONFIG_PM_SLEEP
-               if (adapter->is_suspended)
-                       mwifiex_pcie_resume(&pdev->dev);
-#endif
-
-               mwifiex_deauthenticate_all(adapter);
-
-               priv = mwifiex_get_priv(adapter, MWIFIEX_BSS_ROLE_ANY);
-
-               mwifiex_disable_auto_ds(priv);
-
-               mwifiex_init_shutdown_fw(priv, MWIFIEX_FUNC_SHUTDOWN);
-       }
-
-       mwifiex_remove_card(card->adapter, &add_remove_card_sem);
-}
-
-static void mwifiex_pcie_shutdown(struct pci_dev *pdev)
-{
-       user_rmmod = 1;
-       mwifiex_pcie_remove(pdev);
-
-       return;
-}
-
-static const struct pci_device_id mwifiex_ids[] = {
-       {
-               PCIE_VENDOR_ID_MARVELL, PCIE_DEVICE_ID_MARVELL_88W8766P,
-               PCI_ANY_ID, PCI_ANY_ID, 0, 0,
-               .driver_data = (unsigned long)&mwifiex_pcie8766,
-       },
-       {
-               PCIE_VENDOR_ID_MARVELL, PCIE_DEVICE_ID_MARVELL_88W8897,
-               PCI_ANY_ID, PCI_ANY_ID, 0, 0,
-               .driver_data = (unsigned long)&mwifiex_pcie8897,
-       },
-       {
-               PCIE_VENDOR_ID_MARVELL, PCIE_DEVICE_ID_MARVELL_88W8997,
-               PCI_ANY_ID, PCI_ANY_ID, 0, 0,
-               .driver_data = (unsigned long)&mwifiex_pcie8997,
-       },
-       {},
-};
-
-MODULE_DEVICE_TABLE(pci, mwifiex_ids);
-
-#ifdef CONFIG_PM_SLEEP
-/* Power Management Hooks */
-static SIMPLE_DEV_PM_OPS(mwifiex_pcie_pm_ops, mwifiex_pcie_suspend,
-                               mwifiex_pcie_resume);
-#endif
-
-/* PCI Device Driver */
-static struct pci_driver __refdata mwifiex_pcie = {
-       .name     = "mwifiex_pcie",
-       .id_table = mwifiex_ids,
-       .probe    = mwifiex_pcie_probe,
-       .remove   = mwifiex_pcie_remove,
-#ifdef CONFIG_PM_SLEEP
-       .driver   = {
-               .pm = &mwifiex_pcie_pm_ops,
-       },
-#endif
-       .shutdown = mwifiex_pcie_shutdown,
-};
-
-/*
- * This function writes data into PCIE card register.
- */
-static int mwifiex_write_reg(struct mwifiex_adapter *adapter, int reg, u32 data)
-{
-       struct pcie_service_card *card = adapter->card;
-
-       iowrite32(data, card->pci_mmap1 + reg);
-
-       return 0;
-}
-
-/*
- * This function reads data from PCIE card register.
- */
-static int mwifiex_read_reg(struct mwifiex_adapter *adapter, int reg, u32 *data)
-{
-       struct pcie_service_card *card = adapter->card;
-
-       *data = ioread32(card->pci_mmap1 + reg);
-
-       return 0;
-}
-
-/* This function reads u8 data from PCIE card register. */
-static int mwifiex_read_reg_byte(struct mwifiex_adapter *adapter,
-                                int reg, u8 *data)
-{
-       struct pcie_service_card *card = adapter->card;
-
-       *data = ioread8(card->pci_mmap1 + reg);
-
-       return 0;
-}
-
-/*
- * This function adds delay loop to ensure FW is awake before proceeding.
- */
-static void mwifiex_pcie_dev_wakeup_delay(struct mwifiex_adapter *adapter)
-{
-       int i = 0;
-
-       while (mwifiex_pcie_ok_to_access_hw(adapter)) {
-               i++;
-               usleep_range(10, 20);
-               /* 50ms max wait */
-               if (i == 5000)
-                       break;
-       }
-
-       return;
-}
-
-static void mwifiex_delay_for_sleep_cookie(struct mwifiex_adapter *adapter,
-                                          u32 max_delay_loop_cnt)
-{
-       struct pcie_service_card *card = adapter->card;
-       u8 *buffer;
-       u32 sleep_cookie, count;
-
-       for (count = 0; count < max_delay_loop_cnt; count++) {
-               buffer = card->cmdrsp_buf->data - INTF_HEADER_LEN;
-               sleep_cookie = *(u32 *)buffer;
-
-               if (sleep_cookie == MWIFIEX_DEF_SLEEP_COOKIE) {
-                       mwifiex_dbg(adapter, INFO,
-                                   "sleep cookie found at count %d\n", count);
-                       break;
-               }
-               usleep_range(20, 30);
-       }
-
-       if (count >= max_delay_loop_cnt)
-               mwifiex_dbg(adapter, INFO,
-                           "max count reached while accessing sleep cookie\n");
-}
-
-/* This function wakes up the card by reading fw_status register. */
-static int mwifiex_pm_wakeup_card(struct mwifiex_adapter *adapter)
-{
-       u32 fw_status;
-       struct pcie_service_card *card = adapter->card;
-       const struct mwifiex_pcie_card_reg *reg = card->pcie.reg;
-
-       mwifiex_dbg(adapter, EVENT,
-                   "event: Wakeup device...\n");
-
-       if (reg->sleep_cookie)
-               mwifiex_pcie_dev_wakeup_delay(adapter);
-
-       /* Reading fw_status register will wakeup device */
-       if (mwifiex_read_reg(adapter, reg->fw_status, &fw_status)) {
-               mwifiex_dbg(adapter, ERROR,
-                           "Reading fw_status register failed\n");
-               return -1;
-       }
-
-       if (reg->sleep_cookie) {
-               mwifiex_pcie_dev_wakeup_delay(adapter);
-               mwifiex_dbg(adapter, INFO,
-                           "PCIE wakeup: Setting PS_STATE_AWAKE\n");
-               adapter->ps_state = PS_STATE_AWAKE;
-       }
-
-       return 0;
-}
-
-/*
- * This function is called after the card has woken up.
- *
- * The card configuration register is reset.
- */
-static int mwifiex_pm_wakeup_card_complete(struct mwifiex_adapter *adapter)
-{
-       mwifiex_dbg(adapter, CMD,
-                   "cmd: Wakeup device completed\n");
-
-       return 0;
-}
-
-/*
- * This function disables the host interrupt.
- *
- * The host interrupt mask is read, the disable bit is reset and
- * written back to the card host interrupt mask register.
- */
-static int mwifiex_pcie_disable_host_int(struct mwifiex_adapter *adapter)
-{
-       if (mwifiex_pcie_ok_to_access_hw(adapter)) {
-               if (mwifiex_write_reg(adapter, PCIE_HOST_INT_MASK,
-                                     0x00000000)) {
-                       mwifiex_dbg(adapter, ERROR,
-                                   "Disable host interrupt failed\n");
-                       return -1;
-               }
-       }
-
-       return 0;
-}
-
-/*
- * This function enables the host interrupt.
- *
- * The host interrupt enable mask is written to the card
- * host interrupt mask register.
- */
-static int mwifiex_pcie_enable_host_int(struct mwifiex_adapter *adapter)
-{
-       if (mwifiex_pcie_ok_to_access_hw(adapter)) {
-               /* Simply write the mask to the register */
-               if (mwifiex_write_reg(adapter, PCIE_HOST_INT_MASK,
-                                     HOST_INTR_MASK)) {
-                       mwifiex_dbg(adapter, ERROR,
-                                   "Enable host interrupt failed\n");
-                       return -1;
-               }
-       }
-
-       return 0;
-}
-
-/*
- * This function initializes TX buffer ring descriptors
- */
-static int mwifiex_init_txq_ring(struct mwifiex_adapter *adapter)
-{
-       struct pcie_service_card *card = adapter->card;
-       const struct mwifiex_pcie_card_reg *reg = card->pcie.reg;
-       struct mwifiex_pcie_buf_desc *desc;
-       struct mwifiex_pfu_buf_desc *desc2;
-       int i;
-
-       for (i = 0; i < MWIFIEX_MAX_TXRX_BD; i++) {
-               card->tx_buf_list[i] = NULL;
-               if (reg->pfu_enabled) {
-                       card->txbd_ring[i] = (void *)card->txbd_ring_vbase +
-                                            (sizeof(*desc2) * i);
-                       desc2 = card->txbd_ring[i];
-                       memset(desc2, 0, sizeof(*desc2));
-               } else {
-                       card->txbd_ring[i] = (void *)card->txbd_ring_vbase +
-                                            (sizeof(*desc) * i);
-                       desc = card->txbd_ring[i];
-                       memset(desc, 0, sizeof(*desc));
-               }
-       }
-
-       return 0;
-}
-
-/* This function initializes RX buffer ring descriptors. Each SKB is allocated
- * here and after mapping PCI memory, its physical address is assigned to
- * PCIE Rx buffer descriptor's physical address.
- */
-static int mwifiex_init_rxq_ring(struct mwifiex_adapter *adapter)
-{
-       struct pcie_service_card *card = adapter->card;
-       const struct mwifiex_pcie_card_reg *reg = card->pcie.reg;
-       struct sk_buff *skb;
-       struct mwifiex_pcie_buf_desc *desc;
-       struct mwifiex_pfu_buf_desc *desc2;
-       dma_addr_t buf_pa;
-       int i;
-
-       for (i = 0; i < MWIFIEX_MAX_TXRX_BD; i++) {
-               /* Allocate skb here so that firmware can DMA data from it */
-               skb = mwifiex_alloc_dma_align_buf(MWIFIEX_RX_DATA_BUF_SIZE,
-                                                 GFP_KERNEL | GFP_DMA);
-               if (!skb) {
-                       mwifiex_dbg(adapter, ERROR,
-                                   "Unable to allocate skb for RX ring.\n");
-                       kfree(card->rxbd_ring_vbase);
-                       return -ENOMEM;
-               }
-
-               if (mwifiex_map_pci_memory(adapter, skb,
-                                          MWIFIEX_RX_DATA_BUF_SIZE,
-                                          PCI_DMA_FROMDEVICE))
-                       return -1;
-
-               buf_pa = MWIFIEX_SKB_DMA_ADDR(skb);
-
-               mwifiex_dbg(adapter, INFO,
-                           "info: RX ring: skb=%p len=%d data=%p buf_pa=%#x:%x\n",
-                           skb, skb->len, skb->data, (u32)buf_pa,
-                           (u32)((u64)buf_pa >> 32));
-
-               card->rx_buf_list[i] = skb;
-               if (reg->pfu_enabled) {
-                       card->rxbd_ring[i] = (void *)card->rxbd_ring_vbase +
-                                            (sizeof(*desc2) * i);
-                       desc2 = card->rxbd_ring[i];
-                       desc2->paddr = buf_pa;
-                       desc2->len = (u16)skb->len;
-                       desc2->frag_len = (u16)skb->len;
-                       desc2->flags = reg->ring_flag_eop | reg->ring_flag_sop;
-                       desc2->offset = 0;
-               } else {
-                       card->rxbd_ring[i] = (void *)(card->rxbd_ring_vbase +
-                                            (sizeof(*desc) * i));
-                       desc = card->rxbd_ring[i];
-                       desc->paddr = buf_pa;
-                       desc->len = (u16)skb->len;
-                       desc->flags = 0;
-               }
-       }
-
-       return 0;
-}
-
-/* This function initializes event buffer ring descriptors. Each SKB is
- * allocated here and after mapping PCI memory, its physical address is assigned
- * to PCIE Rx buffer descriptor's physical address
- */
-static int mwifiex_pcie_init_evt_ring(struct mwifiex_adapter *adapter)
-{
-       struct pcie_service_card *card = adapter->card;
-       struct mwifiex_evt_buf_desc *desc;
-       struct sk_buff *skb;
-       dma_addr_t buf_pa;
-       int i;
-
-       for (i = 0; i < MWIFIEX_MAX_EVT_BD; i++) {
-               /* Allocate skb here so that firmware can DMA data from it */
-               skb = dev_alloc_skb(MAX_EVENT_SIZE);
-               if (!skb) {
-                       mwifiex_dbg(adapter, ERROR,
-                                   "Unable to allocate skb for EVENT buf.\n");
-                       kfree(card->evtbd_ring_vbase);
-                       return -ENOMEM;
-               }
-               skb_put(skb, MAX_EVENT_SIZE);
-
-               if (mwifiex_map_pci_memory(adapter, skb, MAX_EVENT_SIZE,
-                                          PCI_DMA_FROMDEVICE))
-                       return -1;
-
-               buf_pa = MWIFIEX_SKB_DMA_ADDR(skb);
-
-               mwifiex_dbg(adapter, EVENT,
-                           "info: EVT ring: skb=%p len=%d data=%p buf_pa=%#x:%x\n",
-                           skb, skb->len, skb->data, (u32)buf_pa,
-                           (u32)((u64)buf_pa >> 32));
-
-               card->evt_buf_list[i] = skb;
-               card->evtbd_ring[i] = (void *)(card->evtbd_ring_vbase +
-                                     (sizeof(*desc) * i));
-               desc = card->evtbd_ring[i];
-               desc->paddr = buf_pa;
-               desc->len = (u16)skb->len;
-               desc->flags = 0;
-       }
-
-       return 0;
-}
-
-/* This function cleans up TX buffer rings. If any of the buffer list has valid
- * SKB address, associated SKB is freed.
- */
-static void mwifiex_cleanup_txq_ring(struct mwifiex_adapter *adapter)
-{
-       struct pcie_service_card *card = adapter->card;
-       const struct mwifiex_pcie_card_reg *reg = card->pcie.reg;
-       struct sk_buff *skb;
-       struct mwifiex_pcie_buf_desc *desc;
-       struct mwifiex_pfu_buf_desc *desc2;
-       int i;
-
-       for (i = 0; i < MWIFIEX_MAX_TXRX_BD; i++) {
-               if (reg->pfu_enabled) {
-                       desc2 = card->txbd_ring[i];
-                       if (card->tx_buf_list[i]) {
-                               skb = card->tx_buf_list[i];
-                               mwifiex_unmap_pci_memory(adapter, skb,
-                                                        PCI_DMA_TODEVICE);
-                               dev_kfree_skb_any(skb);
-                       }
-                       memset(desc2, 0, sizeof(*desc2));
-               } else {
-                       desc = card->txbd_ring[i];
-                       if (card->tx_buf_list[i]) {
-                               skb = card->tx_buf_list[i];
-                               mwifiex_unmap_pci_memory(adapter, skb,
-                                                        PCI_DMA_TODEVICE);
-                               dev_kfree_skb_any(skb);
-                       }
-                       memset(desc, 0, sizeof(*desc));
-               }
-               card->tx_buf_list[i] = NULL;
-       }
-
-       return;
-}
-
-/* This function cleans up RX buffer rings. If any of the buffer list has valid
- * SKB address, associated SKB is freed.
- */
-static void mwifiex_cleanup_rxq_ring(struct mwifiex_adapter *adapter)
-{
-       struct pcie_service_card *card = adapter->card;
-       const struct mwifiex_pcie_card_reg *reg = card->pcie.reg;
-       struct mwifiex_pcie_buf_desc *desc;
-       struct mwifiex_pfu_buf_desc *desc2;
-       struct sk_buff *skb;
-       int i;
-
-       for (i = 0; i < MWIFIEX_MAX_TXRX_BD; i++) {
-               if (reg->pfu_enabled) {
-                       desc2 = card->rxbd_ring[i];
-                       if (card->rx_buf_list[i]) {
-                               skb = card->rx_buf_list[i];
-                               mwifiex_unmap_pci_memory(adapter, skb,
-                                                        PCI_DMA_FROMDEVICE);
-                               dev_kfree_skb_any(skb);
-                       }
-                       memset(desc2, 0, sizeof(*desc2));
-               } else {
-                       desc = card->rxbd_ring[i];
-                       if (card->rx_buf_list[i]) {
-                               skb = card->rx_buf_list[i];
-                               mwifiex_unmap_pci_memory(adapter, skb,
-                                                        PCI_DMA_FROMDEVICE);
-                               dev_kfree_skb_any(skb);
-                       }
-                       memset(desc, 0, sizeof(*desc));
-               }
-               card->rx_buf_list[i] = NULL;
-       }
-
-       return;
-}
-
-/* This function cleans up event buffer rings. If any of the buffer list has
- * valid SKB address, associated SKB is freed.
- */
-static void mwifiex_cleanup_evt_ring(struct mwifiex_adapter *adapter)
-{
-       struct pcie_service_card *card = adapter->card;
-       struct mwifiex_evt_buf_desc *desc;
-       struct sk_buff *skb;
-       int i;
-
-       for (i = 0; i < MWIFIEX_MAX_EVT_BD; i++) {
-               desc = card->evtbd_ring[i];
-               if (card->evt_buf_list[i]) {
-                       skb = card->evt_buf_list[i];
-                       mwifiex_unmap_pci_memory(adapter, skb,
-                                                PCI_DMA_FROMDEVICE);
-                       dev_kfree_skb_any(skb);
-               }
-               card->evt_buf_list[i] = NULL;
-               memset(desc, 0, sizeof(*desc));
-       }
-
-       return;
-}
-
-/* This function creates buffer descriptor ring for TX
- */
-static int mwifiex_pcie_create_txbd_ring(struct mwifiex_adapter *adapter)
-{
-       struct pcie_service_card *card = adapter->card;
-       const struct mwifiex_pcie_card_reg *reg = card->pcie.reg;
-
-       /*
-        * driver maintaines the write pointer and firmware maintaines the read
-        * pointer. The write pointer starts at 0 (zero) while the read pointer
-        * starts at zero with rollover bit set
-        */
-       card->txbd_wrptr = 0;
-
-       if (reg->pfu_enabled)
-               card->txbd_rdptr = 0;
-       else
-               card->txbd_rdptr |= reg->tx_rollover_ind;
-
-       /* allocate shared memory for the BD ring and divide the same in to
-          several descriptors */
-       if (reg->pfu_enabled)
-               card->txbd_ring_size = sizeof(struct mwifiex_pfu_buf_desc) *
-                                      MWIFIEX_MAX_TXRX_BD;
-       else
-               card->txbd_ring_size = sizeof(struct mwifiex_pcie_buf_desc) *
-                                      MWIFIEX_MAX_TXRX_BD;
-
-       mwifiex_dbg(adapter, INFO,
-                   "info: txbd_ring: Allocating %d bytes\n",
-                   card->txbd_ring_size);
-       card->txbd_ring_vbase = pci_alloc_consistent(card->dev,
-                                                    card->txbd_ring_size,
-                                                    &card->txbd_ring_pbase);
-       if (!card->txbd_ring_vbase) {
-               mwifiex_dbg(adapter, ERROR,
-                           "allocate consistent memory (%d bytes) failed!\n",
-                           card->txbd_ring_size);
-               return -ENOMEM;
-       }
-       mwifiex_dbg(adapter, DATA,
-                   "info: txbd_ring - base: %p, pbase: %#x:%x, len: %x\n",
-                   card->txbd_ring_vbase, (unsigned int)card->txbd_ring_pbase,
-                   (u32)((u64)card->txbd_ring_pbase >> 32),
-                   card->txbd_ring_size);
-
-       return mwifiex_init_txq_ring(adapter);
-}
-
-static int mwifiex_pcie_delete_txbd_ring(struct mwifiex_adapter *adapter)
-{
-       struct pcie_service_card *card = adapter->card;
-       const struct mwifiex_pcie_card_reg *reg = card->pcie.reg;
-
-       mwifiex_cleanup_txq_ring(adapter);
-
-       if (card->txbd_ring_vbase)
-               pci_free_consistent(card->dev, card->txbd_ring_size,
-                                   card->txbd_ring_vbase,
-                                   card->txbd_ring_pbase);
-       card->txbd_ring_size = 0;
-       card->txbd_wrptr = 0;
-       card->txbd_rdptr = 0 | reg->tx_rollover_ind;
-       card->txbd_ring_vbase = NULL;
-       card->txbd_ring_pbase = 0;
-
-       return 0;
-}
-
-/*
- * This function creates buffer descriptor ring for RX
- */
-static int mwifiex_pcie_create_rxbd_ring(struct mwifiex_adapter *adapter)
-{
-       struct pcie_service_card *card = adapter->card;
-       const struct mwifiex_pcie_card_reg *reg = card->pcie.reg;
-
-       /*
-        * driver maintaines the read pointer and firmware maintaines the write
-        * pointer. The write pointer starts at 0 (zero) while the read pointer
-        * starts at zero with rollover bit set
-        */
-       card->rxbd_wrptr = 0;
-       card->rxbd_rdptr = reg->rx_rollover_ind;
-
-       if (reg->pfu_enabled)
-               card->rxbd_ring_size = sizeof(struct mwifiex_pfu_buf_desc) *
-                                      MWIFIEX_MAX_TXRX_BD;
-       else
-               card->rxbd_ring_size = sizeof(struct mwifiex_pcie_buf_desc) *
-                                      MWIFIEX_MAX_TXRX_BD;
-
-       mwifiex_dbg(adapter, INFO,
-                   "info: rxbd_ring: Allocating %d bytes\n",
-                   card->rxbd_ring_size);
-       card->rxbd_ring_vbase = pci_alloc_consistent(card->dev,
-                                                    card->rxbd_ring_size,
-                                                    &card->rxbd_ring_pbase);
-       if (!card->rxbd_ring_vbase) {
-               mwifiex_dbg(adapter, ERROR,
-                           "allocate consistent memory (%d bytes) failed!\n",
-                           card->rxbd_ring_size);
-               return -ENOMEM;
-       }
-
-       mwifiex_dbg(adapter, DATA,
-                   "info: rxbd_ring - base: %p, pbase: %#x:%x, len: %#x\n",
-                   card->rxbd_ring_vbase, (u32)card->rxbd_ring_pbase,
-                   (u32)((u64)card->rxbd_ring_pbase >> 32),
-                   card->rxbd_ring_size);
-
-       return mwifiex_init_rxq_ring(adapter);
-}
-
-/*
- * This function deletes Buffer descriptor ring for RX
- */
-static int mwifiex_pcie_delete_rxbd_ring(struct mwifiex_adapter *adapter)
-{
-       struct pcie_service_card *card = adapter->card;
-       const struct mwifiex_pcie_card_reg *reg = card->pcie.reg;
-
-       mwifiex_cleanup_rxq_ring(adapter);
-
-       if (card->rxbd_ring_vbase)
-               pci_free_consistent(card->dev, card->rxbd_ring_size,
-                                   card->rxbd_ring_vbase,
-                                   card->rxbd_ring_pbase);
-       card->rxbd_ring_size = 0;
-       card->rxbd_wrptr = 0;
-       card->rxbd_rdptr = 0 | reg->rx_rollover_ind;
-       card->rxbd_ring_vbase = NULL;
-       card->rxbd_ring_pbase = 0;
-
-       return 0;
-}
-
-/*
- * This function creates buffer descriptor ring for Events
- */
-static int mwifiex_pcie_create_evtbd_ring(struct mwifiex_adapter *adapter)
-{
-       struct pcie_service_card *card = adapter->card;
-       const struct mwifiex_pcie_card_reg *reg = card->pcie.reg;
-
-       /*
-        * driver maintaines the read pointer and firmware maintaines the write
-        * pointer. The write pointer starts at 0 (zero) while the read pointer
-        * starts at zero with rollover bit set
-        */
-       card->evtbd_wrptr = 0;
-       card->evtbd_rdptr = reg->evt_rollover_ind;
-
-       card->evtbd_ring_size = sizeof(struct mwifiex_evt_buf_desc) *
-                               MWIFIEX_MAX_EVT_BD;
-
-       mwifiex_dbg(adapter, INFO,
-                   "info: evtbd_ring: Allocating %d bytes\n",
-               card->evtbd_ring_size);
-       card->evtbd_ring_vbase = pci_alloc_consistent(card->dev,
-                                                     card->evtbd_ring_size,
-                                                     &card->evtbd_ring_pbase);
-       if (!card->evtbd_ring_vbase) {
-               mwifiex_dbg(adapter, ERROR,
-                           "allocate consistent memory (%d bytes) failed!\n",
-                           card->evtbd_ring_size);
-               return -ENOMEM;
-       }
-
-       mwifiex_dbg(adapter, EVENT,
-                   "info: CMDRSP/EVT bd_ring - base: %p pbase: %#x:%x len: %#x\n",
-                   card->evtbd_ring_vbase, (u32)card->evtbd_ring_pbase,
-                   (u32)((u64)card->evtbd_ring_pbase >> 32),
-                   card->evtbd_ring_size);
-
-       return mwifiex_pcie_init_evt_ring(adapter);
-}
-
-/*
- * This function deletes Buffer descriptor ring for Events
- */
-static int mwifiex_pcie_delete_evtbd_ring(struct mwifiex_adapter *adapter)
-{
-       struct pcie_service_card *card = adapter->card;
-       const struct mwifiex_pcie_card_reg *reg = card->pcie.reg;
-
-       mwifiex_cleanup_evt_ring(adapter);
-
-       if (card->evtbd_ring_vbase)
-               pci_free_consistent(card->dev, card->evtbd_ring_size,
-                                   card->evtbd_ring_vbase,
-                                   card->evtbd_ring_pbase);
-       card->evtbd_wrptr = 0;
-       card->evtbd_rdptr = 0 | reg->evt_rollover_ind;
-       card->evtbd_ring_size = 0;
-       card->evtbd_ring_vbase = NULL;
-       card->evtbd_ring_pbase = 0;
-
-       return 0;
-}
-
-/*
- * This function allocates a buffer for CMDRSP
- */
-static int mwifiex_pcie_alloc_cmdrsp_buf(struct mwifiex_adapter *adapter)
-{
-       struct pcie_service_card *card = adapter->card;
-       struct sk_buff *skb;
-
-       /* Allocate memory for receiving command response data */
-       skb = dev_alloc_skb(MWIFIEX_UPLD_SIZE);
-       if (!skb) {
-               mwifiex_dbg(adapter, ERROR,
-                           "Unable to allocate skb for command response data.\n");
-               return -ENOMEM;
-       }
-       skb_put(skb, MWIFIEX_UPLD_SIZE);
-       if (mwifiex_map_pci_memory(adapter, skb, MWIFIEX_UPLD_SIZE,
-                                  PCI_DMA_FROMDEVICE))
-               return -1;
-
-       card->cmdrsp_buf = skb;
-
-       return 0;
-}
-
-/*
- * This function deletes a buffer for CMDRSP
- */
-static int mwifiex_pcie_delete_cmdrsp_buf(struct mwifiex_adapter *adapter)
-{
-       struct pcie_service_card *card;
-
-       if (!adapter)
-               return 0;
-
-       card = adapter->card;
-
-       if (card && card->cmdrsp_buf) {
-               mwifiex_unmap_pci_memory(adapter, card->cmdrsp_buf,
-                                        PCI_DMA_FROMDEVICE);
-               dev_kfree_skb_any(card->cmdrsp_buf);
-       }
-
-       if (card && card->cmd_buf) {
-               mwifiex_unmap_pci_memory(adapter, card->cmd_buf,
-                                        PCI_DMA_TODEVICE);
-       }
-       return 0;
-}
-
-/*
- * This function allocates a buffer for sleep cookie
- */
-static int mwifiex_pcie_alloc_sleep_cookie_buf(struct mwifiex_adapter *adapter)
-{
-       struct pcie_service_card *card = adapter->card;
-
-       card->sleep_cookie_vbase = pci_alloc_consistent(card->dev, sizeof(u32),
-                                                    &card->sleep_cookie_pbase);
-       if (!card->sleep_cookie_vbase) {
-               mwifiex_dbg(adapter, ERROR,
-                           "pci_alloc_consistent failed!\n");
-               return -ENOMEM;
-       }
-       /* Init val of Sleep Cookie */
-       *(u32 *)card->sleep_cookie_vbase = FW_AWAKE_COOKIE;
-
-       mwifiex_dbg(adapter, INFO,
-                   "alloc_scook: sleep cookie=0x%x\n",
-                   *((u32 *)card->sleep_cookie_vbase));
-
-       return 0;
-}
-
-/*
- * This function deletes buffer for sleep cookie
- */
-static int mwifiex_pcie_delete_sleep_cookie_buf(struct mwifiex_adapter *adapter)
-{
-       struct pcie_service_card *card;
-
-       if (!adapter)
-               return 0;
-
-       card = adapter->card;
-
-       if (card && card->sleep_cookie_vbase) {
-               pci_free_consistent(card->dev, sizeof(u32),
-                                   card->sleep_cookie_vbase,
-                                   card->sleep_cookie_pbase);
-               card->sleep_cookie_vbase = NULL;
-       }
-
-       return 0;
-}
-
-/* This function flushes the TX buffer descriptor ring
- * This function defined as handler is also called while cleaning TXRX
- * during disconnect/ bss stop.
- */
-static int mwifiex_clean_pcie_ring_buf(struct mwifiex_adapter *adapter)
-{
-       struct pcie_service_card *card = adapter->card;
-
-       if (!mwifiex_pcie_txbd_empty(card, card->txbd_rdptr)) {
-               card->txbd_flush = 1;
-               /* write pointer already set at last send
-                * send dnld-rdy intr again, wait for completion.
-                */
-               if (mwifiex_write_reg(adapter, PCIE_CPU_INT_EVENT,
-                                     CPU_INTR_DNLD_RDY)) {
-                       mwifiex_dbg(adapter, ERROR,
-                                   "failed to assert dnld-rdy interrupt.\n");
-                       return -1;
-               }
-       }
-       return 0;
-}
-
-/*
- * This function unmaps and frees downloaded data buffer
- */
-static int mwifiex_pcie_send_data_complete(struct mwifiex_adapter *adapter)
-{
-       struct sk_buff *skb;
-       u32 wrdoneidx, rdptr, num_tx_buffs, unmap_count = 0;
-       struct mwifiex_pcie_buf_desc *desc;
-       struct mwifiex_pfu_buf_desc *desc2;
-       struct pcie_service_card *card = adapter->card;
-       const struct mwifiex_pcie_card_reg *reg = card->pcie.reg;
-
-       if (!mwifiex_pcie_ok_to_access_hw(adapter))
-               mwifiex_pm_wakeup_card(adapter);
-
-       /* Read the TX ring read pointer set by firmware */
-       if (mwifiex_read_reg(adapter, reg->tx_rdptr, &rdptr)) {
-               mwifiex_dbg(adapter, ERROR,
-                           "SEND COMP: failed to read reg->tx_rdptr\n");
-               return -1;
-       }
-
-       mwifiex_dbg(adapter, DATA,
-                   "SEND COMP: rdptr_prev=0x%x, rdptr=0x%x\n",
-                   card->txbd_rdptr, rdptr);
-
-       num_tx_buffs = MWIFIEX_MAX_TXRX_BD << reg->tx_start_ptr;
-       /* free from previous txbd_rdptr to current txbd_rdptr */
-       while (((card->txbd_rdptr & reg->tx_mask) !=
-               (rdptr & reg->tx_mask)) ||
-              ((card->txbd_rdptr & reg->tx_rollover_ind) !=
-               (rdptr & reg->tx_rollover_ind))) {
-               wrdoneidx = (card->txbd_rdptr & reg->tx_mask) >>
-                           reg->tx_start_ptr;
-
-               skb = card->tx_buf_list[wrdoneidx];
-
-               if (skb) {
-                       mwifiex_dbg(adapter, DATA,
-                                   "SEND COMP: Detach skb %p at txbd_rdidx=%d\n",
-                                   skb, wrdoneidx);
-                       mwifiex_unmap_pci_memory(adapter, skb,
-                                                PCI_DMA_TODEVICE);
-
-                       unmap_count++;
-
-                       if (card->txbd_flush)
-                               mwifiex_write_data_complete(adapter, skb, 0,
-                                                           -1);
-                       else
-                               mwifiex_write_data_complete(adapter, skb, 0, 0);
-               }
-
-               card->tx_buf_list[wrdoneidx] = NULL;
-
-               if (reg->pfu_enabled) {
-                       desc2 = card->txbd_ring[wrdoneidx];
-                       memset(desc2, 0, sizeof(*desc2));
-               } else {
-                       desc = card->txbd_ring[wrdoneidx];
-                       memset(desc, 0, sizeof(*desc));
-               }
-               switch (card->dev->device) {
-               case PCIE_DEVICE_ID_MARVELL_88W8766P:
-                       card->txbd_rdptr++;
-                       break;
-               case PCIE_DEVICE_ID_MARVELL_88W8897:
-               case PCIE_DEVICE_ID_MARVELL_88W8997:
-                       card->txbd_rdptr += reg->ring_tx_start_ptr;
-                       break;
-               }
-
-
-               if ((card->txbd_rdptr & reg->tx_mask) == num_tx_buffs)
-                       card->txbd_rdptr = ((card->txbd_rdptr &
-                                            reg->tx_rollover_ind) ^
-                                            reg->tx_rollover_ind);
-       }
-
-       if (unmap_count)
-               adapter->data_sent = false;
-
-       if (card->txbd_flush) {
-               if (mwifiex_pcie_txbd_empty(card, card->txbd_rdptr))
-                       card->txbd_flush = 0;
-               else
-                       mwifiex_clean_pcie_ring_buf(adapter);
-       }
-
-       return 0;
-}
-
-/* This function sends data buffer to device. First 4 bytes of payload
- * are filled with payload length and payload type. Then this payload
- * is mapped to PCI device memory. Tx ring pointers are advanced accordingly.
- * Download ready interrupt to FW is deffered if Tx ring is not full and
- * additional payload can be accomodated.
- * Caller must ensure tx_param parameter to this function is not NULL.
- */
-static int
-mwifiex_pcie_send_data(struct mwifiex_adapter *adapter, struct sk_buff *skb,
-                      struct mwifiex_tx_param *tx_param)
-{
-       struct pcie_service_card *card = adapter->card;
-       const struct mwifiex_pcie_card_reg *reg = card->pcie.reg;
-       u32 wrindx, num_tx_buffs, rx_val;
-       int ret;
-       dma_addr_t buf_pa;
-       struct mwifiex_pcie_buf_desc *desc = NULL;
-       struct mwifiex_pfu_buf_desc *desc2 = NULL;
-       __le16 *tmp;
-
-       if (!(skb->data && skb->len)) {
-               mwifiex_dbg(adapter, ERROR,
-                           "%s(): invalid parameter <%p, %#x>\n",
-                           __func__, skb->data, skb->len);
-               return -1;
-       }
-
-       if (!mwifiex_pcie_ok_to_access_hw(adapter))
-               mwifiex_pm_wakeup_card(adapter);
-
-       num_tx_buffs = MWIFIEX_MAX_TXRX_BD << reg->tx_start_ptr;
-       mwifiex_dbg(adapter, DATA,
-                   "info: SEND DATA: <Rd: %#x, Wr: %#x>\n",
-               card->txbd_rdptr, card->txbd_wrptr);
-       if (mwifiex_pcie_txbd_not_full(card)) {
-               u8 *payload;
-
-               adapter->data_sent = true;
-               payload = skb->data;
-               tmp = (__le16 *)&payload[0];
-               *tmp = cpu_to_le16((u16)skb->len);
-               tmp = (__le16 *)&payload[2];
-               *tmp = cpu_to_le16(MWIFIEX_TYPE_DATA);
-
-               if (mwifiex_map_pci_memory(adapter, skb, skb->len,
-                                          PCI_DMA_TODEVICE))
-                       return -1;
-
-               wrindx = (card->txbd_wrptr & reg->tx_mask) >> reg->tx_start_ptr;
-               buf_pa = MWIFIEX_SKB_DMA_ADDR(skb);
-               card->tx_buf_list[wrindx] = skb;
-
-               if (reg->pfu_enabled) {
-                       desc2 = card->txbd_ring[wrindx];
-                       desc2->paddr = buf_pa;
-                       desc2->len = (u16)skb->len;
-                       desc2->frag_len = (u16)skb->len;
-                       desc2->offset = 0;
-                       desc2->flags = MWIFIEX_BD_FLAG_FIRST_DESC |
-                                        MWIFIEX_BD_FLAG_LAST_DESC;
-               } else {
-                       desc = card->txbd_ring[wrindx];
-                       desc->paddr = buf_pa;
-                       desc->len = (u16)skb->len;
-                       desc->flags = MWIFIEX_BD_FLAG_FIRST_DESC |
-                                     MWIFIEX_BD_FLAG_LAST_DESC;
-               }
-
-               switch (card->dev->device) {
-               case PCIE_DEVICE_ID_MARVELL_88W8766P:
-                       card->txbd_wrptr++;
-                       break;
-               case PCIE_DEVICE_ID_MARVELL_88W8897:
-               case PCIE_DEVICE_ID_MARVELL_88W8997:
-                       card->txbd_wrptr += reg->ring_tx_start_ptr;
-                       break;
-               }
-
-               if ((card->txbd_wrptr & reg->tx_mask) == num_tx_buffs)
-                       card->txbd_wrptr = ((card->txbd_wrptr &
-                                               reg->tx_rollover_ind) ^
-                                               reg->tx_rollover_ind);
-
-               rx_val = card->rxbd_rdptr & reg->rx_wrap_mask;
-               /* Write the TX ring write pointer in to reg->tx_wrptr */
-               if (mwifiex_write_reg(adapter, reg->tx_wrptr,
-                                     card->txbd_wrptr | rx_val)) {
-                       mwifiex_dbg(adapter, ERROR,
-                                   "SEND DATA: failed to write reg->tx_wrptr\n");
-                       ret = -1;
-                       goto done_unmap;
-               }
-               if ((mwifiex_pcie_txbd_not_full(card)) &&
-                   tx_param->next_pkt_len) {
-                       /* have more packets and TxBD still can hold more */
-                       mwifiex_dbg(adapter, DATA,
-                                   "SEND DATA: delay dnld-rdy interrupt.\n");
-                       adapter->data_sent = false;
-               } else {
-                       /* Send the TX ready interrupt */
-                       if (mwifiex_write_reg(adapter, PCIE_CPU_INT_EVENT,
-                                             CPU_INTR_DNLD_RDY)) {
-                               mwifiex_dbg(adapter, ERROR,
-                                           "SEND DATA: failed to assert dnld-rdy interrupt.\n");
-                               ret = -1;
-                               goto done_unmap;
-                       }
-               }
-               mwifiex_dbg(adapter, DATA,
-                           "info: SEND DATA: Updated <Rd: %#x, Wr:\t"
-                           "%#x> and sent packet to firmware successfully\n",
-                           card->txbd_rdptr, card->txbd_wrptr);
-       } else {
-               mwifiex_dbg(adapter, DATA,
-                           "info: TX Ring full, can't send packets to fw\n");
-               adapter->data_sent = true;
-               /* Send the TX ready interrupt */
-               if (mwifiex_write_reg(adapter, PCIE_CPU_INT_EVENT,
-                                     CPU_INTR_DNLD_RDY))
-                       mwifiex_dbg(adapter, ERROR,
-                                   "SEND DATA: failed to assert door-bell intr\n");
-               return -EBUSY;
-       }
-
-       return -EINPROGRESS;
-done_unmap:
-       mwifiex_unmap_pci_memory(adapter, skb, PCI_DMA_TODEVICE);
-       card->tx_buf_list[wrindx] = NULL;
-       if (reg->pfu_enabled)
-               memset(desc2, 0, sizeof(*desc2));
-       else
-               memset(desc, 0, sizeof(*desc));
-
-       return ret;
-}
-
-/*
- * This function handles received buffer ring and
- * dispatches packets to upper
- */
-static int mwifiex_pcie_process_recv_data(struct mwifiex_adapter *adapter)
-{
-       struct pcie_service_card *card = adapter->card;
-       const struct mwifiex_pcie_card_reg *reg = card->pcie.reg;
-       u32 wrptr, rd_index, tx_val;
-       dma_addr_t buf_pa;
-       int ret = 0;
-       struct sk_buff *skb_tmp = NULL;
-       struct mwifiex_pcie_buf_desc *desc;
-       struct mwifiex_pfu_buf_desc *desc2;
-
-       if (!mwifiex_pcie_ok_to_access_hw(adapter))
-               mwifiex_pm_wakeup_card(adapter);
-
-       /* Read the RX ring Write pointer set by firmware */
-       if (mwifiex_read_reg(adapter, reg->rx_wrptr, &wrptr)) {
-               mwifiex_dbg(adapter, ERROR,
-                           "RECV DATA: failed to read reg->rx_wrptr\n");
-               ret = -1;
-               goto done;
-       }
-       card->rxbd_wrptr = wrptr;
-
-       while (((wrptr & reg->rx_mask) !=
-               (card->rxbd_rdptr & reg->rx_mask)) ||
-              ((wrptr & reg->rx_rollover_ind) ==
-               (card->rxbd_rdptr & reg->rx_rollover_ind))) {
-               struct sk_buff *skb_data;
-               u16 rx_len;
-               __le16 pkt_len;
-
-               rd_index = card->rxbd_rdptr & reg->rx_mask;
-               skb_data = card->rx_buf_list[rd_index];
-
-               /* If skb allocation was failed earlier for Rx packet,
-                * rx_buf_list[rd_index] would have been left with a NULL.
-                */
-               if (!skb_data)
-                       return -ENOMEM;
-
-               mwifiex_unmap_pci_memory(adapter, skb_data, PCI_DMA_FROMDEVICE);
-               card->rx_buf_list[rd_index] = NULL;
-
-               /* Get data length from interface header -
-                * first 2 bytes for len, next 2 bytes is for type
-                */
-               pkt_len = *((__le16 *)skb_data->data);
-               rx_len = le16_to_cpu(pkt_len);
-               if (WARN_ON(rx_len <= INTF_HEADER_LEN ||
-                           rx_len > MWIFIEX_RX_DATA_BUF_SIZE)) {
-                       mwifiex_dbg(adapter, ERROR,
-                                   "Invalid RX len %d, Rd=%#x, Wr=%#x\n",
-                                   rx_len, card->rxbd_rdptr, wrptr);
-                       dev_kfree_skb_any(skb_data);
-               } else {
-                       skb_put(skb_data, rx_len);
-                       mwifiex_dbg(adapter, DATA,
-                                   "info: RECV DATA: Rd=%#x, Wr=%#x, Len=%d\n",
-                                   card->rxbd_rdptr, wrptr, rx_len);
-                       skb_pull(skb_data, INTF_HEADER_LEN);
-                       if (adapter->rx_work_enabled) {
-                               skb_queue_tail(&adapter->rx_data_q, skb_data);
-                               adapter->data_received = true;
-                               atomic_inc(&adapter->rx_pending);
-                       } else {
-                               mwifiex_handle_rx_packet(adapter, skb_data);
-                       }
-               }
-
-               skb_tmp = mwifiex_alloc_dma_align_buf(MWIFIEX_RX_DATA_BUF_SIZE,
-                                                     GFP_KERNEL | GFP_DMA);
-               if (!skb_tmp) {
-                       mwifiex_dbg(adapter, ERROR,
-                                   "Unable to allocate skb.\n");
-                       return -ENOMEM;
-               }
-
-               if (mwifiex_map_pci_memory(adapter, skb_tmp,
-                                          MWIFIEX_RX_DATA_BUF_SIZE,
-                                          PCI_DMA_FROMDEVICE))
-                       return -1;
-
-               buf_pa = MWIFIEX_SKB_DMA_ADDR(skb_tmp);
-
-               mwifiex_dbg(adapter, INFO,
-                           "RECV DATA: Attach new sk_buff %p at rxbd_rdidx=%d\n",
-                           skb_tmp, rd_index);
-               card->rx_buf_list[rd_index] = skb_tmp;
-
-               if (reg->pfu_enabled) {
-                       desc2 = card->rxbd_ring[rd_index];
-                       desc2->paddr = buf_pa;
-                       desc2->len = skb_tmp->len;
-                       desc2->frag_len = skb_tmp->len;
-                       desc2->offset = 0;
-                       desc2->flags = reg->ring_flag_sop | reg->ring_flag_eop;
-               } else {
-                       desc = card->rxbd_ring[rd_index];
-                       desc->paddr = buf_pa;
-                       desc->len = skb_tmp->len;
-                       desc->flags = 0;
-               }
-
-               if ((++card->rxbd_rdptr & reg->rx_mask) ==
-                                                       MWIFIEX_MAX_TXRX_BD) {
-                       card->rxbd_rdptr = ((card->rxbd_rdptr &
-                                            reg->rx_rollover_ind) ^
-                                            reg->rx_rollover_ind);
-               }
-               mwifiex_dbg(adapter, DATA,
-                           "info: RECV DATA: <Rd: %#x, Wr: %#x>\n",
-                           card->rxbd_rdptr, wrptr);
-
-               tx_val = card->txbd_wrptr & reg->tx_wrap_mask;
-               /* Write the RX ring read pointer in to reg->rx_rdptr */
-               if (mwifiex_write_reg(adapter, reg->rx_rdptr,
-                                     card->rxbd_rdptr | tx_val)) {
-                       mwifiex_dbg(adapter, DATA,
-                                   "RECV DATA: failed to write reg->rx_rdptr\n");
-                       ret = -1;
-                       goto done;
-               }
-
-               /* Read the RX ring Write pointer set by firmware */
-               if (mwifiex_read_reg(adapter, reg->rx_wrptr, &wrptr)) {
-                       mwifiex_dbg(adapter, ERROR,
-                                   "RECV DATA: failed to read reg->rx_wrptr\n");
-                       ret = -1;
-                       goto done;
-               }
-               mwifiex_dbg(adapter, DATA,
-                           "info: RECV DATA: Rcvd packet from fw successfully\n");
-               card->rxbd_wrptr = wrptr;
-       }
-
-done:
-       return ret;
-}
-
-/*
- * This function downloads the boot command to device
- */
-static int
-mwifiex_pcie_send_boot_cmd(struct mwifiex_adapter *adapter, struct sk_buff *skb)
-{
-       dma_addr_t buf_pa;
-       struct pcie_service_card *card = adapter->card;
-       const struct mwifiex_pcie_card_reg *reg = card->pcie.reg;
-
-       if (!(skb->data && skb->len)) {
-               mwifiex_dbg(adapter, ERROR,
-                           "Invalid parameter in %s <%p. len %d>\n",
-                           __func__, skb->data, skb->len);
-               return -1;
-       }
-
-       if (mwifiex_map_pci_memory(adapter, skb, skb->len , PCI_DMA_TODEVICE))
-               return -1;
-
-       buf_pa = MWIFIEX_SKB_DMA_ADDR(skb);
-
-       /* Write the lower 32bits of the physical address to low command
-        * address scratch register
-        */
-       if (mwifiex_write_reg(adapter, reg->cmd_addr_lo, (u32)buf_pa)) {
-               mwifiex_dbg(adapter, ERROR,
-                           "%s: failed to write download command to boot code.\n",
-                           __func__);
-               mwifiex_unmap_pci_memory(adapter, skb, PCI_DMA_TODEVICE);
-               return -1;
-       }
-
-       /* Write the upper 32bits of the physical address to high command
-        * address scratch register
-        */
-       if (mwifiex_write_reg(adapter, reg->cmd_addr_hi,
-                             (u32)((u64)buf_pa >> 32))) {
-               mwifiex_dbg(adapter, ERROR,
-                           "%s: failed to write download command to boot code.\n",
-                           __func__);
-               mwifiex_unmap_pci_memory(adapter, skb, PCI_DMA_TODEVICE);
-               return -1;
-       }
-
-       /* Write the command length to cmd_size scratch register */
-       if (mwifiex_write_reg(adapter, reg->cmd_size, skb->len)) {
-               mwifiex_dbg(adapter, ERROR,
-                           "%s: failed to write command len to cmd_size scratch reg\n",
-                           __func__);
-               mwifiex_unmap_pci_memory(adapter, skb, PCI_DMA_TODEVICE);
-               return -1;
-       }
-
-       /* Ring the door bell */
-       if (mwifiex_write_reg(adapter, PCIE_CPU_INT_EVENT,
-                             CPU_INTR_DOOR_BELL)) {
-               mwifiex_dbg(adapter, ERROR,
-                           "%s: failed to assert door-bell intr\n", __func__);
-               mwifiex_unmap_pci_memory(adapter, skb, PCI_DMA_TODEVICE);
-               return -1;
-       }
-
-       return 0;
-}
-
-/* This function init rx port in firmware which in turn enables to receive data
- * from device before transmitting any packet.
- */
-static int mwifiex_pcie_init_fw_port(struct mwifiex_adapter *adapter)
-{
-       struct pcie_service_card *card = adapter->card;
-       const struct mwifiex_pcie_card_reg *reg = card->pcie.reg;
-       int tx_wrap = card->txbd_wrptr & reg->tx_wrap_mask;
-
-       /* Write the RX ring read pointer in to reg->rx_rdptr */
-       if (mwifiex_write_reg(adapter, reg->rx_rdptr, card->rxbd_rdptr |
-                             tx_wrap)) {
-               mwifiex_dbg(adapter, ERROR,
-                           "RECV DATA: failed to write reg->rx_rdptr\n");
-               return -1;
-       }
-       return 0;
-}
-
-/* This function downloads commands to the device
- */
-static int
-mwifiex_pcie_send_cmd(struct mwifiex_adapter *adapter, struct sk_buff *skb)
-{
-       struct pcie_service_card *card = adapter->card;
-       const struct mwifiex_pcie_card_reg *reg = card->pcie.reg;
-       int ret = 0;
-       dma_addr_t cmd_buf_pa, cmdrsp_buf_pa;
-       u8 *payload = (u8 *)skb->data;
-
-       if (!(skb->data && skb->len)) {
-               mwifiex_dbg(adapter, ERROR,
-                           "Invalid parameter in %s <%p, %#x>\n",
-                           __func__, skb->data, skb->len);
-               return -1;
-       }
-
-       /* Make sure a command response buffer is available */
-       if (!card->cmdrsp_buf) {
-               mwifiex_dbg(adapter, ERROR,
-                           "No response buffer available, send command failed\n");
-               return -EBUSY;
-       }
-
-       if (!mwifiex_pcie_ok_to_access_hw(adapter))
-               mwifiex_pm_wakeup_card(adapter);
-
-       adapter->cmd_sent = true;
-
-       *(__le16 *)&payload[0] = cpu_to_le16((u16)skb->len);
-       *(__le16 *)&payload[2] = cpu_to_le16(MWIFIEX_TYPE_CMD);
-
-       if (mwifiex_map_pci_memory(adapter, skb, skb->len, PCI_DMA_TODEVICE))
-               return -1;
-
-       card->cmd_buf = skb;
-
-       /* To send a command, the driver will:
-               1. Write the 64bit physical address of the data buffer to
-                  cmd response address low  + cmd response address high
-               2. Ring the door bell (i.e. set the door bell interrupt)
-
-               In response to door bell interrupt, the firmware will perform
-               the DMA of the command packet (first header to obtain the total
-               length and then rest of the command).
-       */
-
-       if (card->cmdrsp_buf) {
-               cmdrsp_buf_pa = MWIFIEX_SKB_DMA_ADDR(card->cmdrsp_buf);
-               /* Write the lower 32bits of the cmdrsp buffer physical
-                  address */
-               if (mwifiex_write_reg(adapter, reg->cmdrsp_addr_lo,
-                                     (u32)cmdrsp_buf_pa)) {
-                       mwifiex_dbg(adapter, ERROR,
-                                   "Failed to write download cmd to boot code.\n");
-                       ret = -1;
-                       goto done;
-               }
-               /* Write the upper 32bits of the cmdrsp buffer physical
-                  address */
-               if (mwifiex_write_reg(adapter, reg->cmdrsp_addr_hi,
-                                     (u32)((u64)cmdrsp_buf_pa >> 32))) {
-                       mwifiex_dbg(adapter, ERROR,
-                                   "Failed to write download cmd to boot code.\n");
-                       ret = -1;
-                       goto done;
-               }
-       }
-
-       cmd_buf_pa = MWIFIEX_SKB_DMA_ADDR(card->cmd_buf);
-       /* Write the lower 32bits of the physical address to reg->cmd_addr_lo */
-       if (mwifiex_write_reg(adapter, reg->cmd_addr_lo,
-                             (u32)cmd_buf_pa)) {
-               mwifiex_dbg(adapter, ERROR,
-                           "Failed to write download cmd to boot code.\n");
-               ret = -1;
-               goto done;
-       }
-       /* Write the upper 32bits of the physical address to reg->cmd_addr_hi */
-       if (mwifiex_write_reg(adapter, reg->cmd_addr_hi,
-                             (u32)((u64)cmd_buf_pa >> 32))) {
-               mwifiex_dbg(adapter, ERROR,
-                           "Failed to write download cmd to boot code.\n");
-               ret = -1;
-               goto done;
-       }
-
-       /* Write the command length to reg->cmd_size */
-       if (mwifiex_write_reg(adapter, reg->cmd_size,
-                             card->cmd_buf->len)) {
-               mwifiex_dbg(adapter, ERROR,
-                           "Failed to write cmd len to reg->cmd_size\n");
-               ret = -1;
-               goto done;
-       }
-
-       /* Ring the door bell */
-       if (mwifiex_write_reg(adapter, PCIE_CPU_INT_EVENT,
-                             CPU_INTR_DOOR_BELL)) {
-               mwifiex_dbg(adapter, ERROR,
-                           "Failed to assert door-bell intr\n");
-               ret = -1;
-               goto done;
-       }
-
-done:
-       if (ret)
-               adapter->cmd_sent = false;
-
-       return 0;
-}
-
-/*
- * This function handles command complete interrupt
- */
-static int mwifiex_pcie_process_cmd_complete(struct mwifiex_adapter *adapter)
-{
-       struct pcie_service_card *card = adapter->card;
-       const struct mwifiex_pcie_card_reg *reg = card->pcie.reg;
-       struct sk_buff *skb = card->cmdrsp_buf;
-       int count = 0;
-       u16 rx_len;
-       __le16 pkt_len;
-
-       mwifiex_dbg(adapter, CMD,
-                   "info: Rx CMD Response\n");
-
-       mwifiex_unmap_pci_memory(adapter, skb, PCI_DMA_FROMDEVICE);
-
-       /* Unmap the command as a response has been received. */
-       if (card->cmd_buf) {
-               mwifiex_unmap_pci_memory(adapter, card->cmd_buf,
-                                        PCI_DMA_TODEVICE);
-               card->cmd_buf = NULL;
-       }
-
-       pkt_len = *((__le16 *)skb->data);
-       rx_len = le16_to_cpu(pkt_len);
-       skb_trim(skb, rx_len);
-       skb_pull(skb, INTF_HEADER_LEN);
-
-       if (!adapter->curr_cmd) {
-               if (adapter->ps_state == PS_STATE_SLEEP_CFM) {
-                       mwifiex_process_sleep_confirm_resp(adapter, skb->data,
-                                                          skb->len);
-                       mwifiex_pcie_enable_host_int(adapter);
-                       if (mwifiex_write_reg(adapter,
-                                             PCIE_CPU_INT_EVENT,
-                                             CPU_INTR_SLEEP_CFM_DONE)) {
-                               mwifiex_dbg(adapter, ERROR,
-                                           "Write register failed\n");
-                               return -1;
-                       }
-                       mwifiex_delay_for_sleep_cookie(adapter,
-                                                      MWIFIEX_MAX_DELAY_COUNT);
-                       while (reg->sleep_cookie && (count++ < 10) &&
-                              mwifiex_pcie_ok_to_access_hw(adapter))
-                               usleep_range(50, 60);
-               } else {
-                       mwifiex_dbg(adapter, ERROR,
-                                   "There is no command but got cmdrsp\n");
-               }
-               memcpy(adapter->upld_buf, skb->data,
-                      min_t(u32, MWIFIEX_SIZE_OF_CMD_BUFFER, skb->len));
-               skb_push(skb, INTF_HEADER_LEN);
-               if (mwifiex_map_pci_memory(adapter, skb, MWIFIEX_UPLD_SIZE,
-                                          PCI_DMA_FROMDEVICE))
-                       return -1;
-       } else if (mwifiex_pcie_ok_to_access_hw(adapter)) {
-               adapter->curr_cmd->resp_skb = skb;
-               adapter->cmd_resp_received = true;
-               /* Take the pointer and set it to CMD node and will
-                  return in the response complete callback */
-               card->cmdrsp_buf = NULL;
-
-               /* Clear the cmd-rsp buffer address in scratch registers. This
-                  will prevent firmware from writing to the same response
-                  buffer again. */
-               if (mwifiex_write_reg(adapter, reg->cmdrsp_addr_lo, 0)) {
-                       mwifiex_dbg(adapter, ERROR,
-                                   "cmd_done: failed to clear cmd_rsp_addr_lo\n");
-                       return -1;
-               }
-               /* Write the upper 32bits of the cmdrsp buffer physical
-                  address */
-               if (mwifiex_write_reg(adapter, reg->cmdrsp_addr_hi, 0)) {
-                       mwifiex_dbg(adapter, ERROR,
-                                   "cmd_done: failed to clear cmd_rsp_addr_hi\n");
-                       return -1;
-               }
-       }
-
-       return 0;
-}
-
-/*
- * Command Response processing complete handler
- */
-static int mwifiex_pcie_cmdrsp_complete(struct mwifiex_adapter *adapter,
-                                       struct sk_buff *skb)
-{
-       struct pcie_service_card *card = adapter->card;
-
-       if (skb) {
-               card->cmdrsp_buf = skb;
-               skb_push(card->cmdrsp_buf, INTF_HEADER_LEN);
-               if (mwifiex_map_pci_memory(adapter, skb, MWIFIEX_UPLD_SIZE,
-                                          PCI_DMA_FROMDEVICE))
-                       return -1;
-       }
-
-       return 0;
-}
-
-/*
- * This function handles firmware event ready interrupt
- */
-static int mwifiex_pcie_process_event_ready(struct mwifiex_adapter *adapter)
-{
-       struct pcie_service_card *card = adapter->card;
-       const struct mwifiex_pcie_card_reg *reg = card->pcie.reg;
-       u32 rdptr = card->evtbd_rdptr & MWIFIEX_EVTBD_MASK;
-       u32 wrptr, event;
-       struct mwifiex_evt_buf_desc *desc;
-
-       if (!mwifiex_pcie_ok_to_access_hw(adapter))
-               mwifiex_pm_wakeup_card(adapter);
-
-       if (adapter->event_received) {
-               mwifiex_dbg(adapter, EVENT,
-                           "info: Event being processed,\t"
-                           "do not process this interrupt just yet\n");
-               return 0;
-       }
-
-       if (rdptr >= MWIFIEX_MAX_EVT_BD) {
-               mwifiex_dbg(adapter, ERROR,
-                           "info: Invalid read pointer...\n");
-               return -1;
-       }
-
-       /* Read the event ring write pointer set by firmware */
-       if (mwifiex_read_reg(adapter, reg->evt_wrptr, &wrptr)) {
-               mwifiex_dbg(adapter, ERROR,
-                           "EventReady: failed to read reg->evt_wrptr\n");
-               return -1;
-       }
-
-       mwifiex_dbg(adapter, EVENT,
-                   "info: EventReady: Initial <Rd: 0x%x, Wr: 0x%x>",
-                   card->evtbd_rdptr, wrptr);
-       if (((wrptr & MWIFIEX_EVTBD_MASK) != (card->evtbd_rdptr
-                                             & MWIFIEX_EVTBD_MASK)) ||
-           ((wrptr & reg->evt_rollover_ind) ==
-            (card->evtbd_rdptr & reg->evt_rollover_ind))) {
-               struct sk_buff *skb_cmd;
-               __le16 data_len = 0;
-               u16 evt_len;
-
-               mwifiex_dbg(adapter, INFO,
-                           "info: Read Index: %d\n", rdptr);
-               skb_cmd = card->evt_buf_list[rdptr];
-               mwifiex_unmap_pci_memory(adapter, skb_cmd, PCI_DMA_FROMDEVICE);
-
-               /* Take the pointer and set it to event pointer in adapter
-                  and will return back after event handling callback */
-               card->evt_buf_list[rdptr] = NULL;
-               desc = card->evtbd_ring[rdptr];
-               memset(desc, 0, sizeof(*desc));
-
-               event = *(u32 *) &skb_cmd->data[INTF_HEADER_LEN];
-               adapter->event_cause = event;
-               /* The first 4bytes will be the event transfer header
-                  len is 2 bytes followed by type which is 2 bytes */
-               memcpy(&data_len, skb_cmd->data, sizeof(__le16));
-               evt_len = le16_to_cpu(data_len);
-               skb_trim(skb_cmd, evt_len);
-               skb_pull(skb_cmd, INTF_HEADER_LEN);
-               mwifiex_dbg(adapter, EVENT,
-                           "info: Event length: %d\n", evt_len);
-
-               if ((evt_len > 0) && (evt_len  < MAX_EVENT_SIZE))
-                       memcpy(adapter->event_body, skb_cmd->data +
-                              MWIFIEX_EVENT_HEADER_LEN, evt_len -
-                              MWIFIEX_EVENT_HEADER_LEN);
-
-               adapter->event_received = true;
-               adapter->event_skb = skb_cmd;
-
-               /* Do not update the event read pointer here, wait till the
-                  buffer is released. This is just to make things simpler,
-                  we need to find a better method of managing these buffers.
-               */
-       } else {
-               if (mwifiex_write_reg(adapter, PCIE_CPU_INT_EVENT,
-                                     CPU_INTR_EVENT_DONE)) {
-                       mwifiex_dbg(adapter, ERROR,
-                                   "Write register failed\n");
-                       return -1;
-               }
-       }
-
-       return 0;
-}
-
-/*
- * Event processing complete handler
- */
-static int mwifiex_pcie_event_complete(struct mwifiex_adapter *adapter,
-                                      struct sk_buff *skb)
-{
-       struct pcie_service_card *card = adapter->card;
-       const struct mwifiex_pcie_card_reg *reg = card->pcie.reg;
-       int ret = 0;
-       u32 rdptr = card->evtbd_rdptr & MWIFIEX_EVTBD_MASK;
-       u32 wrptr;
-       struct mwifiex_evt_buf_desc *desc;
-
-       if (!skb)
-               return 0;
-
-       if (rdptr >= MWIFIEX_MAX_EVT_BD) {
-               mwifiex_dbg(adapter, ERROR,
-                           "event_complete: Invalid rdptr 0x%x\n",
-                           rdptr);
-               return -EINVAL;
-       }
-
-       /* Read the event ring write pointer set by firmware */
-       if (mwifiex_read_reg(adapter, reg->evt_wrptr, &wrptr)) {
-               mwifiex_dbg(adapter, ERROR,
-                           "event_complete: failed to read reg->evt_wrptr\n");
-               return -1;
-       }
-
-       if (!card->evt_buf_list[rdptr]) {
-               skb_push(skb, INTF_HEADER_LEN);
-               skb_put(skb, MAX_EVENT_SIZE - skb->len);
-               if (mwifiex_map_pci_memory(adapter, skb,
-                                          MAX_EVENT_SIZE,
-                                          PCI_DMA_FROMDEVICE))
-                       return -1;
-               card->evt_buf_list[rdptr] = skb;
-               desc = card->evtbd_ring[rdptr];
-               desc->paddr = MWIFIEX_SKB_DMA_ADDR(skb);
-               desc->len = (u16)skb->len;
-               desc->flags = 0;
-               skb = NULL;
-       } else {
-               mwifiex_dbg(adapter, ERROR,
-                           "info: ERROR: buf still valid at index %d, <%p, %p>\n",
-                           rdptr, card->evt_buf_list[rdptr], skb);
-       }
-
-       if ((++card->evtbd_rdptr & MWIFIEX_EVTBD_MASK) == MWIFIEX_MAX_EVT_BD) {
-               card->evtbd_rdptr = ((card->evtbd_rdptr &
-                                       reg->evt_rollover_ind) ^
-                                       reg->evt_rollover_ind);
-       }
-
-       mwifiex_dbg(adapter, EVENT,
-                   "info: Updated <Rd: 0x%x, Wr: 0x%x>",
-                   card->evtbd_rdptr, wrptr);
-
-       /* Write the event ring read pointer in to reg->evt_rdptr */
-       if (mwifiex_write_reg(adapter, reg->evt_rdptr,
-                             card->evtbd_rdptr)) {
-               mwifiex_dbg(adapter, ERROR,
-                           "event_complete: failed to read reg->evt_rdptr\n");
-               return -1;
-       }
-
-       mwifiex_dbg(adapter, EVENT,
-                   "info: Check Events Again\n");
-       ret = mwifiex_pcie_process_event_ready(adapter);
-
-       return ret;
-}
-
-/*
- * This function downloads the firmware to the card.
- *
- * Firmware is downloaded to the card in blocks. Every block download
- * is tested for CRC errors, and retried a number of times before
- * returning failure.
- */
-static int mwifiex_prog_fw_w_helper(struct mwifiex_adapter *adapter,
-                                   struct mwifiex_fw_image *fw)
-{
-       int ret;
-       u8 *firmware = fw->fw_buf;
-       u32 firmware_len = fw->fw_len;
-       u32 offset = 0;
-       struct sk_buff *skb;
-       u32 txlen, tx_blocks = 0, tries, len;
-       u32 block_retry_cnt = 0;
-       struct pcie_service_card *card = adapter->card;
-       const struct mwifiex_pcie_card_reg *reg = card->pcie.reg;
-
-       if (!firmware || !firmware_len) {
-               mwifiex_dbg(adapter, ERROR,
-                           "No firmware image found! Terminating download\n");
-               return -1;
-       }
-
-       mwifiex_dbg(adapter, INFO,
-                   "info: Downloading FW image (%d bytes)\n",
-                   firmware_len);
-
-       if (mwifiex_pcie_disable_host_int(adapter)) {
-               mwifiex_dbg(adapter, ERROR,
-                           "%s: Disabling interrupts failed.\n", __func__);
-               return -1;
-       }
-
-       skb = dev_alloc_skb(MWIFIEX_UPLD_SIZE);
-       if (!skb) {
-               ret = -ENOMEM;
-               goto done;
-       }
-
-       /* Perform firmware data transfer */
-       do {
-               u32 ireg_intr = 0;
-
-               /* More data? */
-               if (offset >= firmware_len)
-                       break;
-
-               for (tries = 0; tries < MAX_POLL_TRIES; tries++) {
-                       ret = mwifiex_read_reg(adapter, reg->cmd_size,
-                                              &len);
-                       if (ret) {
-                               mwifiex_dbg(adapter, FATAL,
-                                           "Failed reading len from boot code\n");
-                               goto done;
-                       }
-                       if (len)
-                               break;
-                       usleep_range(10, 20);
-               }
-
-               if (!len) {
-                       break;
-               } else if (len > MWIFIEX_UPLD_SIZE) {
-                       mwifiex_dbg(adapter, ERROR,
-                                   "FW download failure @ %d, invalid length %d\n",
-                                   offset, len);
-                       ret = -1;
-                       goto done;
-               }
-
-               txlen = len;
-
-               if (len & BIT(0)) {
-                       block_retry_cnt++;
-                       if (block_retry_cnt > MAX_WRITE_IOMEM_RETRY) {
-                               mwifiex_dbg(adapter, ERROR,
-                                           "FW download failure @ %d, over max\t"
-                                           "retry count\n", offset);
-                               ret = -1;
-                               goto done;
-                       }
-                       mwifiex_dbg(adapter, ERROR,
-                                   "FW CRC error indicated by the\t"
-                                   "helper: len = 0x%04X, txlen = %d\n",
-                                   len, txlen);
-                       len &= ~BIT(0);
-                       /* Setting this to 0 to resend from same offset */
-                       txlen = 0;
-               } else {
-                       block_retry_cnt = 0;
-                       /* Set blocksize to transfer - checking for
-                          last block */
-                       if (firmware_len - offset < txlen)
-                               txlen = firmware_len - offset;
-
-                       mwifiex_dbg(adapter, INFO, ".");
-
-                       tx_blocks = (txlen + card->pcie.blksz_fw_dl - 1) /
-                                   card->pcie.blksz_fw_dl;
-
-                       /* Copy payload to buffer */
-                       memmove(skb->data, &firmware[offset], txlen);
-               }
-
-               skb_put(skb, MWIFIEX_UPLD_SIZE - skb->len);
-               skb_trim(skb, tx_blocks * card->pcie.blksz_fw_dl);
-
-               /* Send the boot command to device */
-               if (mwifiex_pcie_send_boot_cmd(adapter, skb)) {
-                       mwifiex_dbg(adapter, ERROR,
-                                   "Failed to send firmware download command\n");
-                       ret = -1;
-                       goto done;
-               }
-
-               /* Wait for the command done interrupt */
-               do {
-                       if (mwifiex_read_reg(adapter, PCIE_CPU_INT_STATUS,
-                                            &ireg_intr)) {
-                               mwifiex_dbg(adapter, ERROR,
-                                           "%s: Failed to read\t"
-                                           "interrupt status during fw dnld.\n",
-                                           __func__);
-                               mwifiex_unmap_pci_memory(adapter, skb,
-                                                        PCI_DMA_TODEVICE);
-                               ret = -1;
-                               goto done;
-                       }
-               } while ((ireg_intr & CPU_INTR_DOOR_BELL) ==
-                        CPU_INTR_DOOR_BELL);
-
-               mwifiex_unmap_pci_memory(adapter, skb, PCI_DMA_TODEVICE);
-
-               offset += txlen;
-       } while (true);
-
-       mwifiex_dbg(adapter, MSG,
-                   "info: FW download over, size %d bytes\n", offset);
-
-       ret = 0;
-
-done:
-       dev_kfree_skb_any(skb);
-       return ret;
-}
-
-/*
- * This function checks the firmware status in card.
- *
- * The winner interface is also determined by this function.
- */
-static int
-mwifiex_check_fw_status(struct mwifiex_adapter *adapter, u32 poll_num)
-{
-       int ret = 0;
-       u32 firmware_stat, winner_status;
-       struct pcie_service_card *card = adapter->card;
-       const struct mwifiex_pcie_card_reg *reg = card->pcie.reg;
-       u32 tries;
-
-       /* Mask spurios interrupts */
-       if (mwifiex_write_reg(adapter, PCIE_HOST_INT_STATUS_MASK,
-                             HOST_INTR_MASK)) {
-               mwifiex_dbg(adapter, ERROR,
-                           "Write register failed\n");
-               return -1;
-       }
-
-       mwifiex_dbg(adapter, INFO,
-                   "Setting driver ready signature\n");
-       if (mwifiex_write_reg(adapter, reg->drv_rdy,
-                             FIRMWARE_READY_PCIE)) {
-               mwifiex_dbg(adapter, ERROR,
-                           "Failed to write driver ready signature\n");
-               return -1;
-       }
-
-       /* Wait for firmware initialization event */
-       for (tries = 0; tries < poll_num; tries++) {
-               if (mwifiex_read_reg(adapter, reg->fw_status,
-                                    &firmware_stat))
-                       ret = -1;
-               else
-                       ret = 0;
-               if (ret)
-                       continue;
-               if (firmware_stat == FIRMWARE_READY_PCIE) {
-                       ret = 0;
-                       break;
-               } else {
-                       msleep(100);
-                       ret = -1;
-               }
-       }
-
-       if (ret) {
-               if (mwifiex_read_reg(adapter, reg->fw_status,
-                                    &winner_status))
-                       ret = -1;
-               else if (!winner_status) {
-                       mwifiex_dbg(adapter, INFO,
-                                   "PCI-E is the winner\n");
-                       adapter->winner = 1;
-               } else {
-                       mwifiex_dbg(adapter, ERROR,
-                                   "PCI-E is not the winner <%#x,%d>, exit dnld\n",
-                                   ret, adapter->winner);
-               }
-       }
-
-       return ret;
-}
-
-/*
- * This function reads the interrupt status from card.
- */
-static void mwifiex_interrupt_status(struct mwifiex_adapter *adapter)
-{
-       u32 pcie_ireg;
-       unsigned long flags;
-
-       if (!mwifiex_pcie_ok_to_access_hw(adapter))
-               return;
-
-       if (mwifiex_read_reg(adapter, PCIE_HOST_INT_STATUS, &pcie_ireg)) {
-               mwifiex_dbg(adapter, ERROR, "Read register failed\n");
-               return;
-       }
-
-       if ((pcie_ireg != 0xFFFFFFFF) && (pcie_ireg)) {
-
-               mwifiex_pcie_disable_host_int(adapter);
-
-               /* Clear the pending interrupts */
-               if (mwifiex_write_reg(adapter, PCIE_HOST_INT_STATUS,
-                                     ~pcie_ireg)) {
-                       mwifiex_dbg(adapter, ERROR,
-                                   "Write register failed\n");
-                       return;
-               }
-               spin_lock_irqsave(&adapter->int_lock, flags);
-               adapter->int_status |= pcie_ireg;
-               spin_unlock_irqrestore(&adapter->int_lock, flags);
-
-               if (!adapter->pps_uapsd_mode &&
-                   adapter->ps_state == PS_STATE_SLEEP &&
-                   mwifiex_pcie_ok_to_access_hw(adapter)) {
-                               /* Potentially for PCIe we could get other
-                                * interrupts like shared. Don't change power
-                                * state until cookie is set */
-                               adapter->ps_state = PS_STATE_AWAKE;
-                               adapter->pm_wakeup_fw_try = false;
-                               del_timer(&adapter->wakeup_timer);
-               }
-       }
-}
-
-/*
- * Interrupt handler for PCIe root port
- *
- * This function reads the interrupt status from firmware and assigns
- * the main process in workqueue which will handle the interrupt.
- */
-static irqreturn_t mwifiex_pcie_interrupt(int irq, void *context)
-{
-       struct pci_dev *pdev = (struct pci_dev *)context;
-       struct pcie_service_card *card;
-       struct mwifiex_adapter *adapter;
-
-       if (!pdev) {
-               pr_debug("info: %s: pdev is NULL\n", (u8 *)pdev);
-               goto exit;
-       }
-
-       card = pci_get_drvdata(pdev);
-       if (!card || !card->adapter) {
-               pr_debug("info: %s: card=%p adapter=%p\n", __func__, card,
-                        card ? card->adapter : NULL);
-               goto exit;
-       }
-       adapter = card->adapter;
-
-       if (adapter->surprise_removed)
-               goto exit;
-
-       mwifiex_interrupt_status(adapter);
-       mwifiex_queue_main_work(adapter);
-
-exit:
-       return IRQ_HANDLED;
-}
-
-/*
- * This function checks the current interrupt status.
- *
- * The following interrupts are checked and handled by this function -
- *      - Data sent
- *      - Command sent
- *      - Command received
- *      - Packets received
- *      - Events received
- *
- * In case of Rx packets received, the packets are uploaded from card to
- * host and processed accordingly.
- */
-static int mwifiex_process_int_status(struct mwifiex_adapter *adapter)
-{
-       int ret;
-       u32 pcie_ireg;
-       unsigned long flags;
-
-       spin_lock_irqsave(&adapter->int_lock, flags);
-       /* Clear out unused interrupts */
-       pcie_ireg = adapter->int_status;
-       adapter->int_status = 0;
-       spin_unlock_irqrestore(&adapter->int_lock, flags);
-
-       while (pcie_ireg & HOST_INTR_MASK) {
-               if (pcie_ireg & HOST_INTR_DNLD_DONE) {
-                       pcie_ireg &= ~HOST_INTR_DNLD_DONE;
-                       mwifiex_dbg(adapter, INTR,
-                                   "info: TX DNLD Done\n");
-                       ret = mwifiex_pcie_send_data_complete(adapter);
-                       if (ret)
-                               return ret;
-               }
-               if (pcie_ireg & HOST_INTR_UPLD_RDY) {
-                       pcie_ireg &= ~HOST_INTR_UPLD_RDY;
-                       mwifiex_dbg(adapter, INTR,
-                                   "info: Rx DATA\n");
-                       ret = mwifiex_pcie_process_recv_data(adapter);
-                       if (ret)
-                               return ret;
-               }
-               if (pcie_ireg & HOST_INTR_EVENT_RDY) {
-                       pcie_ireg &= ~HOST_INTR_EVENT_RDY;
-                       mwifiex_dbg(adapter, INTR,
-                                   "info: Rx EVENT\n");
-                       ret = mwifiex_pcie_process_event_ready(adapter);
-                       if (ret)
-                               return ret;
-               }
-
-               if (pcie_ireg & HOST_INTR_CMD_DONE) {
-                       pcie_ireg &= ~HOST_INTR_CMD_DONE;
-                       if (adapter->cmd_sent) {
-                               mwifiex_dbg(adapter, INTR,
-                                           "info: CMD sent Interrupt\n");
-                               adapter->cmd_sent = false;
-                       }
-                       /* Handle command response */
-                       ret = mwifiex_pcie_process_cmd_complete(adapter);
-                       if (ret)
-                               return ret;
-               }
-
-               if (mwifiex_pcie_ok_to_access_hw(adapter)) {
-                       if (mwifiex_read_reg(adapter, PCIE_HOST_INT_STATUS,
-                                            &pcie_ireg)) {
-                               mwifiex_dbg(adapter, ERROR,
-                                           "Read register failed\n");
-                               return -1;
-                       }
-
-                       if ((pcie_ireg != 0xFFFFFFFF) && (pcie_ireg)) {
-                               if (mwifiex_write_reg(adapter,
-                                                     PCIE_HOST_INT_STATUS,
-                                                     ~pcie_ireg)) {
-                                       mwifiex_dbg(adapter, ERROR,
-                                                   "Write register failed\n");
-                                       return -1;
-                               }
-                       }
-
-               }
-       }
-       mwifiex_dbg(adapter, INTR,
-                   "info: cmd_sent=%d data_sent=%d\n",
-                   adapter->cmd_sent, adapter->data_sent);
-       if (adapter->ps_state != PS_STATE_SLEEP)
-               mwifiex_pcie_enable_host_int(adapter);
-
-       return 0;
-}
-
-/*
- * This function downloads data from driver to card.
- *
- * Both commands and data packets are transferred to the card by this
- * function.
- *
- * This function adds the PCIE specific header to the front of the buffer
- * before transferring. The header contains the length of the packet and
- * the type. The firmware handles the packets based upon this set type.
- */
-static int mwifiex_pcie_host_to_card(struct mwifiex_adapter *adapter, u8 type,
-                                    struct sk_buff *skb,
-                                    struct mwifiex_tx_param *tx_param)
-{
-       if (!skb) {
-               mwifiex_dbg(adapter, ERROR,
-                           "Passed NULL skb to %s\n", __func__);
-               return -1;
-       }
-
-       if (type == MWIFIEX_TYPE_DATA)
-               return mwifiex_pcie_send_data(adapter, skb, tx_param);
-       else if (type == MWIFIEX_TYPE_CMD)
-               return mwifiex_pcie_send_cmd(adapter, skb);
-
-       return 0;
-}
-
-/* This function read/write firmware */
-static enum rdwr_status
-mwifiex_pcie_rdwr_firmware(struct mwifiex_adapter *adapter, u8 doneflag)
-{
-       int ret, tries;
-       u8 ctrl_data;
-       struct pcie_service_card *card = adapter->card;
-       const struct mwifiex_pcie_card_reg *reg = card->pcie.reg;
-
-       ret = mwifiex_write_reg(adapter, reg->fw_dump_ctrl, FW_DUMP_HOST_READY);
-       if (ret) {
-               mwifiex_dbg(adapter, ERROR,
-                           "PCIE write err\n");
-               return RDWR_STATUS_FAILURE;
-       }
-
-       for (tries = 0; tries < MAX_POLL_TRIES; tries++) {
-               mwifiex_read_reg_byte(adapter, reg->fw_dump_ctrl, &ctrl_data);
-               if (ctrl_data == FW_DUMP_DONE)
-                       return RDWR_STATUS_SUCCESS;
-               if (doneflag && ctrl_data == doneflag)
-                       return RDWR_STATUS_DONE;
-               if (ctrl_data != FW_DUMP_HOST_READY) {
-                       mwifiex_dbg(adapter, WARN,
-                                   "The ctrl reg was changed, re-try again!\n");
-                       ret = mwifiex_write_reg(adapter, reg->fw_dump_ctrl,
-                                               FW_DUMP_HOST_READY);
-                       if (ret) {
-                               mwifiex_dbg(adapter, ERROR,
-                                           "PCIE write err\n");
-                               return RDWR_STATUS_FAILURE;
-                       }
-               }
-               usleep_range(100, 200);
-       }
-
-       mwifiex_dbg(adapter, ERROR, "Fail to pull ctrl_data\n");
-       return RDWR_STATUS_FAILURE;
-}
-
-/* This function dump firmware memory to file */
-static void mwifiex_pcie_fw_dump(struct mwifiex_adapter *adapter)
-{
-       struct pcie_service_card *card = adapter->card;
-       const struct mwifiex_pcie_card_reg *creg = card->pcie.reg;
-       unsigned int reg, reg_start, reg_end;
-       u8 *dbg_ptr, *end_ptr, dump_num, idx, i, read_reg, doneflag = 0;
-       enum rdwr_status stat;
-       u32 memory_size;
-       int ret;
-
-       if (!card->pcie.can_dump_fw)
-               return;
-
-       for (idx = 0; idx < ARRAY_SIZE(mem_type_mapping_tbl); idx++) {
-               struct memory_type_mapping *entry = &mem_type_mapping_tbl[idx];
-
-               if (entry->mem_ptr) {
-                       vfree(entry->mem_ptr);
-                       entry->mem_ptr = NULL;
-               }
-               entry->mem_size = 0;
-       }
-
-       mwifiex_dbg(adapter, DUMP, "== mwifiex firmware dump start ==\n");
-
-       /* Read the number of the memories which will dump */
-       stat = mwifiex_pcie_rdwr_firmware(adapter, doneflag);
-       if (stat == RDWR_STATUS_FAILURE)
-               return;
-
-       reg = creg->fw_dump_start;
-       mwifiex_read_reg_byte(adapter, reg, &dump_num);
-
-       /* Read the length of every memory which will dump */
-       for (idx = 0; idx < dump_num; idx++) {
-               struct memory_type_mapping *entry = &mem_type_mapping_tbl[idx];
-
-               stat = mwifiex_pcie_rdwr_firmware(adapter, doneflag);
-               if (stat == RDWR_STATUS_FAILURE)
-                       return;
-
-               memory_size = 0;
-               reg = creg->fw_dump_start;
-               for (i = 0; i < 4; i++) {
-                       mwifiex_read_reg_byte(adapter, reg, &read_reg);
-                       memory_size |= (read_reg << (i * 8));
-                       reg++;
-               }
-
-               if (memory_size == 0) {
-                       mwifiex_dbg(adapter, MSG, "Firmware dump Finished!\n");
-                       ret = mwifiex_write_reg(adapter, creg->fw_dump_ctrl,
-                                               FW_DUMP_READ_DONE);
-                       if (ret) {
-                               mwifiex_dbg(adapter, ERROR, "PCIE write err\n");
-                               return;
-                       }
-                       break;
-               }
-
-               mwifiex_dbg(adapter, DUMP,
-                           "%s_SIZE=0x%x\n", entry->mem_name, memory_size);
-               entry->mem_ptr = vmalloc(memory_size + 1);
-               entry->mem_size = memory_size;
-               if (!entry->mem_ptr) {
-                       mwifiex_dbg(adapter, ERROR,
-                                   "Vmalloc %s failed\n", entry->mem_name);
-                       return;
-               }
-               dbg_ptr = entry->mem_ptr;
-               end_ptr = dbg_ptr + memory_size;
-
-               doneflag = entry->done_flag;
-               mwifiex_dbg(adapter, DUMP, "Start %s output, please wait...\n",
-                           entry->mem_name);
-
-               do {
-                       stat = mwifiex_pcie_rdwr_firmware(adapter, doneflag);
-                       if (RDWR_STATUS_FAILURE == stat)
-                               return;
-
-                       reg_start = creg->fw_dump_start;
-                       reg_end = creg->fw_dump_end;
-                       for (reg = reg_start; reg <= reg_end; reg++) {
-                               mwifiex_read_reg_byte(adapter, reg, dbg_ptr);
-                               if (dbg_ptr < end_ptr) {
-                                       dbg_ptr++;
-                               } else {
-                                       mwifiex_dbg(adapter, ERROR,
-                                                   "Allocated buf not enough\n");
-                                       return;
-                               }
-                       }
-
-                       if (stat != RDWR_STATUS_DONE)
-                               continue;
-
-                       mwifiex_dbg(adapter, DUMP,
-                                   "%s done: size=0x%tx\n",
-                                   entry->mem_name, dbg_ptr - entry->mem_ptr);
-                       break;
-               } while (true);
-       }
-       mwifiex_dbg(adapter, DUMP, "== mwifiex firmware dump end ==\n");
-}
-
-static void mwifiex_pcie_device_dump_work(struct mwifiex_adapter *adapter)
-{
-       mwifiex_drv_info_dump(adapter);
-       mwifiex_pcie_fw_dump(adapter);
-       mwifiex_upload_device_dump(adapter);
-}
-
-static unsigned long iface_work_flags;
-static struct mwifiex_adapter *save_adapter;
-static void mwifiex_pcie_work(struct work_struct *work)
-{
-       if (test_and_clear_bit(MWIFIEX_IFACE_WORK_DEVICE_DUMP,
-                              &iface_work_flags))
-               mwifiex_pcie_device_dump_work(save_adapter);
-}
-
-static DECLARE_WORK(pcie_work, mwifiex_pcie_work);
-/* This function dumps FW information */
-static void mwifiex_pcie_device_dump(struct mwifiex_adapter *adapter)
-{
-       save_adapter = adapter;
-       if (test_bit(MWIFIEX_IFACE_WORK_DEVICE_DUMP, &iface_work_flags))
-               return;
-
-       set_bit(MWIFIEX_IFACE_WORK_DEVICE_DUMP, &iface_work_flags);
-
-       schedule_work(&pcie_work);
-}
-
-/*
- * This function initializes the PCI-E host memory space, WCB rings, etc.
- *
- * The following initializations steps are followed -
- *      - Allocate TXBD ring buffers
- *      - Allocate RXBD ring buffers
- *      - Allocate event BD ring buffers
- *      - Allocate command response ring buffer
- *      - Allocate sleep cookie buffer
- */
-static int mwifiex_pcie_init(struct mwifiex_adapter *adapter)
-{
-       struct pcie_service_card *card = adapter->card;
-       int ret;
-       struct pci_dev *pdev = card->dev;
-       const struct mwifiex_pcie_card_reg *reg = card->pcie.reg;
-
-       pci_set_drvdata(pdev, card);
-
-       ret = pci_enable_device(pdev);
-       if (ret)
-               goto err_enable_dev;
-
-       pci_set_master(pdev);
-
-       mwifiex_dbg(adapter, INFO,
-                   "try set_consistent_dma_mask(32)\n");
-       ret = pci_set_dma_mask(pdev, DMA_BIT_MASK(32));
-       if (ret) {
-               mwifiex_dbg(adapter, ERROR,
-                           "set_dma_mask(32) failed\n");
-               goto err_set_dma_mask;
-       }
-
-       ret = pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(32));
-       if (ret) {
-               mwifiex_dbg(adapter, ERROR,
-                           "set_consistent_dma_mask(64) failed\n");
-               goto err_set_dma_mask;
-       }
-
-       ret = pci_request_region(pdev, 0, DRV_NAME);
-       if (ret) {
-               mwifiex_dbg(adapter, ERROR,
-                           "req_reg(0) error\n");
-               goto err_req_region0;
-       }
-       card->pci_mmap = pci_iomap(pdev, 0, 0);
-       if (!card->pci_mmap) {
-               mwifiex_dbg(adapter, ERROR, "iomap(0) error\n");
-               ret = -EIO;
-               goto err_iomap0;
-       }
-       ret = pci_request_region(pdev, 2, DRV_NAME);
-       if (ret) {
-               mwifiex_dbg(adapter, ERROR, "req_reg(2) error\n");
-               goto err_req_region2;
-       }
-       card->pci_mmap1 = pci_iomap(pdev, 2, 0);
-       if (!card->pci_mmap1) {
-               mwifiex_dbg(adapter, ERROR,
-                           "iomap(2) error\n");
-               ret = -EIO;
-               goto err_iomap2;
-       }
-
-       mwifiex_dbg(adapter, INFO,
-                   "PCI memory map Virt0: %p PCI memory map Virt2: %p\n",
-                   card->pci_mmap, card->pci_mmap1);
-
-       card->cmdrsp_buf = NULL;
-       ret = mwifiex_pcie_create_txbd_ring(adapter);
-       if (ret)
-               goto err_cre_txbd;
-       ret = mwifiex_pcie_create_rxbd_ring(adapter);
-       if (ret)
-               goto err_cre_rxbd;
-       ret = mwifiex_pcie_create_evtbd_ring(adapter);
-       if (ret)
-               goto err_cre_evtbd;
-       ret = mwifiex_pcie_alloc_cmdrsp_buf(adapter);
-       if (ret)
-               goto err_alloc_cmdbuf;
-       if (reg->sleep_cookie) {
-               ret = mwifiex_pcie_alloc_sleep_cookie_buf(adapter);
-               if (ret)
-                       goto err_alloc_cookie;
-       } else {
-               card->sleep_cookie_vbase = NULL;
-       }
-       return ret;
-
-err_alloc_cookie:
-       mwifiex_pcie_delete_cmdrsp_buf(adapter);
-err_alloc_cmdbuf:
-       mwifiex_pcie_delete_evtbd_ring(adapter);
-err_cre_evtbd:
-       mwifiex_pcie_delete_rxbd_ring(adapter);
-err_cre_rxbd:
-       mwifiex_pcie_delete_txbd_ring(adapter);
-err_cre_txbd:
-       pci_iounmap(pdev, card->pci_mmap1);
-err_iomap2:
-       pci_release_region(pdev, 2);
-err_req_region2:
-       pci_iounmap(pdev, card->pci_mmap);
-err_iomap0:
-       pci_release_region(pdev, 0);
-err_req_region0:
-err_set_dma_mask:
-       pci_disable_device(pdev);
-err_enable_dev:
-       pci_set_drvdata(pdev, NULL);
-       return ret;
-}
-
-/*
- * This function cleans up the allocated card buffers.
- *
- * The following are freed by this function -
- *      - TXBD ring buffers
- *      - RXBD ring buffers
- *      - Event BD ring buffers
- *      - Command response ring buffer
- *      - Sleep cookie buffer
- */
-static void mwifiex_pcie_cleanup(struct mwifiex_adapter *adapter)
-{
-       struct pcie_service_card *card = adapter->card;
-       struct pci_dev *pdev = card->dev;
-       const struct mwifiex_pcie_card_reg *reg = card->pcie.reg;
-
-       if (user_rmmod) {
-               mwifiex_dbg(adapter, INFO,
-                           "Clearing driver ready signature\n");
-               if (mwifiex_write_reg(adapter, reg->drv_rdy, 0x00000000))
-                       mwifiex_dbg(adapter, ERROR,
-                                   "Failed to write driver not-ready signature\n");
-       }
-
-       if (pdev) {
-               pci_iounmap(pdev, card->pci_mmap);
-               pci_iounmap(pdev, card->pci_mmap1);
-               pci_disable_device(pdev);
-               pci_release_region(pdev, 2);
-               pci_release_region(pdev, 0);
-               pci_set_drvdata(pdev, NULL);
-       }
-       kfree(card);
-}
-
-/*
- * This function registers the PCIE device.
- *
- * PCIE IRQ is claimed, block size is set and driver data is initialized.
- */
-static int mwifiex_register_dev(struct mwifiex_adapter *adapter)
-{
-       int ret;
-       struct pcie_service_card *card = adapter->card;
-       struct pci_dev *pdev = card->dev;
-
-       /* save adapter pointer in card */
-       card->adapter = adapter;
-
-       ret = request_irq(pdev->irq, mwifiex_pcie_interrupt, IRQF_SHARED,
-                         "MRVL_PCIE", pdev);
-       if (ret) {
-               mwifiex_dbg(adapter, ERROR,
-                           "request_irq failed: ret=%d\n", ret);
-               adapter->card = NULL;
-               return -1;
-       }
-
-       adapter->dev = &pdev->dev;
-       adapter->tx_buf_size = card->pcie.tx_buf_size;
-       adapter->mem_type_mapping_tbl = mem_type_mapping_tbl;
-       adapter->num_mem_types = ARRAY_SIZE(mem_type_mapping_tbl);
-       strcpy(adapter->fw_name, card->pcie.firmware);
-       adapter->ext_scan = card->pcie.can_ext_scan;
-
-       return 0;
-}
-
-/*
- * This function unregisters the PCIE device.
- *
- * The PCIE IRQ is released, the function is disabled and driver
- * data is set to null.
- */
-static void mwifiex_unregister_dev(struct mwifiex_adapter *adapter)
-{
-       struct pcie_service_card *card = adapter->card;
-       const struct mwifiex_pcie_card_reg *reg;
-
-       if (card) {
-               mwifiex_dbg(adapter, INFO,
-                           "%s(): calling free_irq()\n", __func__);
-               free_irq(card->dev->irq, card->dev);
-
-               reg = card->pcie.reg;
-               if (reg->sleep_cookie)
-                       mwifiex_pcie_delete_sleep_cookie_buf(adapter);
-
-               mwifiex_pcie_delete_cmdrsp_buf(adapter);
-               mwifiex_pcie_delete_evtbd_ring(adapter);
-               mwifiex_pcie_delete_rxbd_ring(adapter);
-               mwifiex_pcie_delete_txbd_ring(adapter);
-               card->cmdrsp_buf = NULL;
-       }
-}
-
-static struct mwifiex_if_ops pcie_ops = {
-       .init_if =                      mwifiex_pcie_init,
-       .cleanup_if =                   mwifiex_pcie_cleanup,
-       .check_fw_status =              mwifiex_check_fw_status,
-       .prog_fw =                      mwifiex_prog_fw_w_helper,
-       .register_dev =                 mwifiex_register_dev,
-       .unregister_dev =               mwifiex_unregister_dev,
-       .enable_int =                   mwifiex_pcie_enable_host_int,
-       .process_int_status =           mwifiex_process_int_status,
-       .host_to_card =                 mwifiex_pcie_host_to_card,
-       .wakeup =                       mwifiex_pm_wakeup_card,
-       .wakeup_complete =              mwifiex_pm_wakeup_card_complete,
-
-       /* PCIE specific */
-       .cmdrsp_complete =              mwifiex_pcie_cmdrsp_complete,
-       .event_complete =               mwifiex_pcie_event_complete,
-       .update_mp_end_port =           NULL,
-       .cleanup_mpa_buf =              NULL,
-       .init_fw_port =                 mwifiex_pcie_init_fw_port,
-       .clean_pcie_ring =              mwifiex_clean_pcie_ring_buf,
-       .device_dump =                  mwifiex_pcie_device_dump,
-};
-
-/*
- * This function initializes the PCIE driver module.
- *
- * This initiates the semaphore and registers the device with
- * PCIE bus.
- */
-static int mwifiex_pcie_init_module(void)
-{
-       int ret;
-
-       pr_debug("Marvell PCIe Driver\n");
-
-       sema_init(&add_remove_card_sem, 1);
-
-       /* Clear the flag in case user removes the card. */
-       user_rmmod = 0;
-
-       ret = pci_register_driver(&mwifiex_pcie);
-       if (ret)
-               pr_err("Driver register failed!\n");
-       else
-               pr_debug("info: Driver registered successfully!\n");
-
-       return ret;
-}
-
-/*
- * This function cleans up the PCIE driver.
- *
- * The following major steps are followed for cleanup -
- *      - Resume the device if its suspended
- *      - Disconnect the device if connected
- *      - Shutdown the firmware
- *      - Unregister the device from PCIE bus.
- */
-static void mwifiex_pcie_cleanup_module(void)
-{
-       if (!down_interruptible(&add_remove_card_sem))
-               up(&add_remove_card_sem);
-
-       /* Set the flag as user is removing this module. */
-       user_rmmod = 1;
-
-       cancel_work_sync(&pcie_work);
-       pci_unregister_driver(&mwifiex_pcie);
-}
-
-module_init(mwifiex_pcie_init_module);
-module_exit(mwifiex_pcie_cleanup_module);
-
-MODULE_AUTHOR("Marvell International Ltd.");
-MODULE_DESCRIPTION("Marvell WiFi-Ex PCI-Express Driver version " PCIE_VERSION);
-MODULE_VERSION(PCIE_VERSION);
-MODULE_LICENSE("GPL v2");
-MODULE_FIRMWARE(PCIE8766_DEFAULT_FW_NAME);
-MODULE_FIRMWARE(PCIE8897_DEFAULT_FW_NAME);
-MODULE_FIRMWARE(PCIE8997_DEFAULT_FW_NAME);
diff --git a/drivers/net/wireless/mwifiex/pcie.h b/drivers/net/wireless/mwifiex/pcie.h
deleted file mode 100644 (file)
index 48e549c..0000000
+++ /dev/null
@@ -1,382 +0,0 @@
-/* @file mwifiex_pcie.h
- *
- * @brief This file contains definitions for PCI-E interface.
- * driver.
- *
- * Copyright (C) 2011-2014, Marvell International Ltd.
- *
- * This software file (the "File") is distributed by Marvell International
- * Ltd. under the terms of the GNU General Public License Version 2, June 1991
- * (the "License").  You may use, redistribute and/or modify this File in
- * accordance with the terms and conditions of the License, a copy of which
- * is available by writing to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the
- * worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
- *
- * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
- * ARE EXPRESSLY DISCLAIMED.  The License provides additional details about
- * this warranty disclaimer.
- */
-
-#ifndef        _MWIFIEX_PCIE_H
-#define        _MWIFIEX_PCIE_H
-
-#include    <linux/pci.h>
-#include    <linux/pcieport_if.h>
-#include    <linux/interrupt.h>
-
-#include    "main.h"
-
-#define PCIE8766_DEFAULT_FW_NAME "mrvl/pcie8766_uapsta.bin"
-#define PCIE8897_DEFAULT_FW_NAME "mrvl/pcie8897_uapsta.bin"
-#define PCIE8997_DEFAULT_FW_NAME "mrvl/pcie8997_uapsta.bin"
-
-#define PCIE_VENDOR_ID_MARVELL              (0x11ab)
-#define PCIE_DEVICE_ID_MARVELL_88W8766P                (0x2b30)
-#define PCIE_DEVICE_ID_MARVELL_88W8897         (0x2b38)
-#define PCIE_DEVICE_ID_MARVELL_88W8997         (0x2b42)
-
-/* Constants for Buffer Descriptor (BD) rings */
-#define MWIFIEX_MAX_TXRX_BD                    0x20
-#define MWIFIEX_TXBD_MASK                      0x3F
-#define MWIFIEX_RXBD_MASK                      0x3F
-
-#define MWIFIEX_MAX_EVT_BD                     0x08
-#define MWIFIEX_EVTBD_MASK                     0x0f
-
-/* PCIE INTERNAL REGISTERS */
-#define PCIE_SCRATCH_0_REG                             0xC10
-#define PCIE_SCRATCH_1_REG                             0xC14
-#define PCIE_CPU_INT_EVENT                             0xC18
-#define PCIE_CPU_INT_STATUS                            0xC1C
-#define PCIE_HOST_INT_STATUS                           0xC30
-#define PCIE_HOST_INT_MASK                             0xC34
-#define PCIE_HOST_INT_STATUS_MASK                      0xC3C
-#define PCIE_SCRATCH_2_REG                             0xC40
-#define PCIE_SCRATCH_3_REG                             0xC44
-#define PCIE_SCRATCH_4_REG                             0xCD0
-#define PCIE_SCRATCH_5_REG                             0xCD4
-#define PCIE_SCRATCH_6_REG                             0xCD8
-#define PCIE_SCRATCH_7_REG                             0xCDC
-#define PCIE_SCRATCH_8_REG                             0xCE0
-#define PCIE_SCRATCH_9_REG                             0xCE4
-#define PCIE_SCRATCH_10_REG                            0xCE8
-#define PCIE_SCRATCH_11_REG                            0xCEC
-#define PCIE_SCRATCH_12_REG                            0xCF0
-#define PCIE_RD_DATA_PTR_Q0_Q1                          0xC08C
-#define PCIE_WR_DATA_PTR_Q0_Q1                          0xC05C
-
-#define CPU_INTR_DNLD_RDY                              BIT(0)
-#define CPU_INTR_DOOR_BELL                             BIT(1)
-#define CPU_INTR_SLEEP_CFM_DONE                        BIT(2)
-#define CPU_INTR_RESET                                 BIT(3)
-#define CPU_INTR_EVENT_DONE                            BIT(5)
-
-#define HOST_INTR_DNLD_DONE                            BIT(0)
-#define HOST_INTR_UPLD_RDY                             BIT(1)
-#define HOST_INTR_CMD_DONE                             BIT(2)
-#define HOST_INTR_EVENT_RDY                            BIT(3)
-#define HOST_INTR_MASK                                 (HOST_INTR_DNLD_DONE | \
-                                                        HOST_INTR_UPLD_RDY  | \
-                                                        HOST_INTR_CMD_DONE  | \
-                                                        HOST_INTR_EVENT_RDY)
-
-#define MWIFIEX_BD_FLAG_ROLLOVER_IND                   BIT(7)
-#define MWIFIEX_BD_FLAG_FIRST_DESC                     BIT(0)
-#define MWIFIEX_BD_FLAG_LAST_DESC                      BIT(1)
-#define MWIFIEX_BD_FLAG_SOP                            BIT(0)
-#define MWIFIEX_BD_FLAG_EOP                            BIT(1)
-#define MWIFIEX_BD_FLAG_XS_SOP                         BIT(2)
-#define MWIFIEX_BD_FLAG_XS_EOP                         BIT(3)
-#define MWIFIEX_BD_FLAG_EVT_ROLLOVER_IND               BIT(7)
-#define MWIFIEX_BD_FLAG_RX_ROLLOVER_IND                        BIT(10)
-#define MWIFIEX_BD_FLAG_TX_START_PTR                   BIT(16)
-#define MWIFIEX_BD_FLAG_TX_ROLLOVER_IND                        BIT(26)
-
-/* Max retry number of command write */
-#define MAX_WRITE_IOMEM_RETRY                          2
-/* Define PCIE block size for firmware download */
-#define MWIFIEX_PCIE_BLOCK_SIZE_FW_DNLD                256
-/* FW awake cookie after FW ready */
-#define FW_AWAKE_COOKIE                                                (0xAA55AA55)
-#define MWIFIEX_DEF_SLEEP_COOKIE                       0xBEEFBEEF
-#define MWIFIEX_MAX_DELAY_COUNT                                5
-
-struct mwifiex_pcie_card_reg {
-       u16 cmd_addr_lo;
-       u16 cmd_addr_hi;
-       u16 fw_status;
-       u16 cmd_size;
-       u16 cmdrsp_addr_lo;
-       u16 cmdrsp_addr_hi;
-       u16 tx_rdptr;
-       u16 tx_wrptr;
-       u16 rx_rdptr;
-       u16 rx_wrptr;
-       u16 evt_rdptr;
-       u16 evt_wrptr;
-       u16 drv_rdy;
-       u16 tx_start_ptr;
-       u32 tx_mask;
-       u32 tx_wrap_mask;
-       u32 rx_mask;
-       u32 rx_wrap_mask;
-       u32 tx_rollover_ind;
-       u32 rx_rollover_ind;
-       u32 evt_rollover_ind;
-       u8 ring_flag_sop;
-       u8 ring_flag_eop;
-       u8 ring_flag_xs_sop;
-       u8 ring_flag_xs_eop;
-       u32 ring_tx_start_ptr;
-       u8 pfu_enabled;
-       u8 sleep_cookie;
-       u16 fw_dump_ctrl;
-       u16 fw_dump_start;
-       u16 fw_dump_end;
-};
-
-static const struct mwifiex_pcie_card_reg mwifiex_reg_8766 = {
-       .cmd_addr_lo = PCIE_SCRATCH_0_REG,
-       .cmd_addr_hi = PCIE_SCRATCH_1_REG,
-       .cmd_size = PCIE_SCRATCH_2_REG,
-       .fw_status = PCIE_SCRATCH_3_REG,
-       .cmdrsp_addr_lo = PCIE_SCRATCH_4_REG,
-       .cmdrsp_addr_hi = PCIE_SCRATCH_5_REG,
-       .tx_rdptr = PCIE_SCRATCH_6_REG,
-       .tx_wrptr = PCIE_SCRATCH_7_REG,
-       .rx_rdptr = PCIE_SCRATCH_8_REG,
-       .rx_wrptr = PCIE_SCRATCH_9_REG,
-       .evt_rdptr = PCIE_SCRATCH_10_REG,
-       .evt_wrptr = PCIE_SCRATCH_11_REG,
-       .drv_rdy = PCIE_SCRATCH_12_REG,
-       .tx_start_ptr = 0,
-       .tx_mask = MWIFIEX_TXBD_MASK,
-       .tx_wrap_mask = 0,
-       .rx_mask = MWIFIEX_RXBD_MASK,
-       .rx_wrap_mask = 0,
-       .tx_rollover_ind = MWIFIEX_BD_FLAG_ROLLOVER_IND,
-       .rx_rollover_ind = MWIFIEX_BD_FLAG_ROLLOVER_IND,
-       .evt_rollover_ind = MWIFIEX_BD_FLAG_ROLLOVER_IND,
-       .ring_flag_sop = 0,
-       .ring_flag_eop = 0,
-       .ring_flag_xs_sop = 0,
-       .ring_flag_xs_eop = 0,
-       .ring_tx_start_ptr = 0,
-       .pfu_enabled = 0,
-       .sleep_cookie = 1,
-};
-
-static const struct mwifiex_pcie_card_reg mwifiex_reg_8897 = {
-       .cmd_addr_lo = PCIE_SCRATCH_0_REG,
-       .cmd_addr_hi = PCIE_SCRATCH_1_REG,
-       .cmd_size = PCIE_SCRATCH_2_REG,
-       .fw_status = PCIE_SCRATCH_3_REG,
-       .cmdrsp_addr_lo = PCIE_SCRATCH_4_REG,
-       .cmdrsp_addr_hi = PCIE_SCRATCH_5_REG,
-       .tx_rdptr = PCIE_RD_DATA_PTR_Q0_Q1,
-       .tx_wrptr = PCIE_WR_DATA_PTR_Q0_Q1,
-       .rx_rdptr = PCIE_WR_DATA_PTR_Q0_Q1,
-       .rx_wrptr = PCIE_RD_DATA_PTR_Q0_Q1,
-       .evt_rdptr = PCIE_SCRATCH_10_REG,
-       .evt_wrptr = PCIE_SCRATCH_11_REG,
-       .drv_rdy = PCIE_SCRATCH_12_REG,
-       .tx_start_ptr = 16,
-       .tx_mask = 0x03FF0000,
-       .tx_wrap_mask = 0x07FF0000,
-       .rx_mask = 0x000003FF,
-       .rx_wrap_mask = 0x000007FF,
-       .tx_rollover_ind = MWIFIEX_BD_FLAG_TX_ROLLOVER_IND,
-       .rx_rollover_ind = MWIFIEX_BD_FLAG_RX_ROLLOVER_IND,
-       .evt_rollover_ind = MWIFIEX_BD_FLAG_EVT_ROLLOVER_IND,
-       .ring_flag_sop = MWIFIEX_BD_FLAG_SOP,
-       .ring_flag_eop = MWIFIEX_BD_FLAG_EOP,
-       .ring_flag_xs_sop = MWIFIEX_BD_FLAG_XS_SOP,
-       .ring_flag_xs_eop = MWIFIEX_BD_FLAG_XS_EOP,
-       .ring_tx_start_ptr = MWIFIEX_BD_FLAG_TX_START_PTR,
-       .pfu_enabled = 1,
-       .sleep_cookie = 0,
-       .fw_dump_ctrl = 0xcf4,
-       .fw_dump_start = 0xcf8,
-       .fw_dump_end = 0xcff,
-};
-
-static const struct mwifiex_pcie_card_reg mwifiex_reg_8997 = {
-       .cmd_addr_lo = PCIE_SCRATCH_0_REG,
-       .cmd_addr_hi = PCIE_SCRATCH_1_REG,
-       .cmd_size = PCIE_SCRATCH_2_REG,
-       .fw_status = PCIE_SCRATCH_3_REG,
-       .cmdrsp_addr_lo = PCIE_SCRATCH_4_REG,
-       .cmdrsp_addr_hi = PCIE_SCRATCH_5_REG,
-       .tx_rdptr = 0xC1A4,
-       .tx_wrptr = 0xC1A8,
-       .rx_rdptr = 0xC1A8,
-       .rx_wrptr = 0xC1A4,
-       .evt_rdptr = PCIE_SCRATCH_10_REG,
-       .evt_wrptr = PCIE_SCRATCH_11_REG,
-       .drv_rdy = PCIE_SCRATCH_12_REG,
-       .tx_start_ptr = 16,
-       .tx_mask = 0x0FFF0000,
-       .tx_wrap_mask = 0x01FF0000,
-       .rx_mask = 0x00000FFF,
-       .rx_wrap_mask = 0x000001FF,
-       .tx_rollover_ind = BIT(28),
-       .rx_rollover_ind = BIT(12),
-       .evt_rollover_ind = MWIFIEX_BD_FLAG_EVT_ROLLOVER_IND,
-       .ring_flag_sop = MWIFIEX_BD_FLAG_SOP,
-       .ring_flag_eop = MWIFIEX_BD_FLAG_EOP,
-       .ring_flag_xs_sop = MWIFIEX_BD_FLAG_XS_SOP,
-       .ring_flag_xs_eop = MWIFIEX_BD_FLAG_XS_EOP,
-       .ring_tx_start_ptr = MWIFIEX_BD_FLAG_TX_START_PTR,
-       .pfu_enabled = 1,
-       .sleep_cookie = 0,
-};
-
-struct mwifiex_pcie_device {
-       const char *firmware;
-       const struct mwifiex_pcie_card_reg *reg;
-       u16 blksz_fw_dl;
-       u16 tx_buf_size;
-       bool can_dump_fw;
-       bool can_ext_scan;
-};
-
-static const struct mwifiex_pcie_device mwifiex_pcie8766 = {
-       .firmware       = PCIE8766_DEFAULT_FW_NAME,
-       .reg            = &mwifiex_reg_8766,
-       .blksz_fw_dl = MWIFIEX_PCIE_BLOCK_SIZE_FW_DNLD,
-       .tx_buf_size = MWIFIEX_TX_DATA_BUF_SIZE_2K,
-       .can_dump_fw = false,
-       .can_ext_scan = true,
-};
-
-static const struct mwifiex_pcie_device mwifiex_pcie8897 = {
-       .firmware       = PCIE8897_DEFAULT_FW_NAME,
-       .reg            = &mwifiex_reg_8897,
-       .blksz_fw_dl = MWIFIEX_PCIE_BLOCK_SIZE_FW_DNLD,
-       .tx_buf_size = MWIFIEX_TX_DATA_BUF_SIZE_4K,
-       .can_dump_fw = true,
-       .can_ext_scan = true,
-};
-
-static const struct mwifiex_pcie_device mwifiex_pcie8997 = {
-       .firmware       = PCIE8997_DEFAULT_FW_NAME,
-       .reg            = &mwifiex_reg_8997,
-       .blksz_fw_dl = MWIFIEX_PCIE_BLOCK_SIZE_FW_DNLD,
-       .tx_buf_size = MWIFIEX_TX_DATA_BUF_SIZE_4K,
-       .can_dump_fw = false,
-       .can_ext_scan = true,
-};
-
-struct mwifiex_evt_buf_desc {
-       u64 paddr;
-       u16 len;
-       u16 flags;
-} __packed;
-
-struct mwifiex_pcie_buf_desc {
-       u64 paddr;
-       u16 len;
-       u16 flags;
-} __packed;
-
-struct mwifiex_pfu_buf_desc {
-       u16 flags;
-       u16 offset;
-       u16 frag_len;
-       u16 len;
-       u64 paddr;
-       u32 reserved;
-} __packed;
-
-struct pcie_service_card {
-       struct pci_dev *dev;
-       struct mwifiex_adapter *adapter;
-       struct mwifiex_pcie_device pcie;
-
-       u8 txbd_flush;
-       u32 txbd_wrptr;
-       u32 txbd_rdptr;
-       u32 txbd_ring_size;
-       u8 *txbd_ring_vbase;
-       dma_addr_t txbd_ring_pbase;
-       void *txbd_ring[MWIFIEX_MAX_TXRX_BD];
-       struct sk_buff *tx_buf_list[MWIFIEX_MAX_TXRX_BD];
-
-       u32 rxbd_wrptr;
-       u32 rxbd_rdptr;
-       u32 rxbd_ring_size;
-       u8 *rxbd_ring_vbase;
-       dma_addr_t rxbd_ring_pbase;
-       void *rxbd_ring[MWIFIEX_MAX_TXRX_BD];
-       struct sk_buff *rx_buf_list[MWIFIEX_MAX_TXRX_BD];
-
-       u32 evtbd_wrptr;
-       u32 evtbd_rdptr;
-       u32 evtbd_ring_size;
-       u8 *evtbd_ring_vbase;
-       dma_addr_t evtbd_ring_pbase;
-       void *evtbd_ring[MWIFIEX_MAX_EVT_BD];
-       struct sk_buff *evt_buf_list[MWIFIEX_MAX_EVT_BD];
-
-       struct sk_buff *cmd_buf;
-       struct sk_buff *cmdrsp_buf;
-       u8 *sleep_cookie_vbase;
-       dma_addr_t sleep_cookie_pbase;
-       void __iomem *pci_mmap;
-       void __iomem *pci_mmap1;
-};
-
-static inline int
-mwifiex_pcie_txbd_empty(struct pcie_service_card *card, u32 rdptr)
-{
-       const struct mwifiex_pcie_card_reg *reg = card->pcie.reg;
-
-       switch (card->dev->device) {
-       case PCIE_DEVICE_ID_MARVELL_88W8766P:
-               if (((card->txbd_wrptr & reg->tx_mask) ==
-                    (rdptr & reg->tx_mask)) &&
-                   ((card->txbd_wrptr & reg->tx_rollover_ind) !=
-                    (rdptr & reg->tx_rollover_ind)))
-                       return 1;
-               break;
-       case PCIE_DEVICE_ID_MARVELL_88W8897:
-               if (((card->txbd_wrptr & reg->tx_mask) ==
-                    (rdptr & reg->tx_mask)) &&
-                   ((card->txbd_wrptr & reg->tx_rollover_ind) ==
-                       (rdptr & reg->tx_rollover_ind)))
-                       return 1;
-               break;
-       }
-
-       return 0;
-}
-
-static inline int
-mwifiex_pcie_txbd_not_full(struct pcie_service_card *card)
-{
-       const struct mwifiex_pcie_card_reg *reg = card->pcie.reg;
-
-       switch (card->dev->device) {
-       case PCIE_DEVICE_ID_MARVELL_88W8766P:
-               if (((card->txbd_wrptr & reg->tx_mask) !=
-                    (card->txbd_rdptr & reg->tx_mask)) ||
-                   ((card->txbd_wrptr & reg->tx_rollover_ind) !=
-                    (card->txbd_rdptr & reg->tx_rollover_ind)))
-                       return 1;
-               break;
-       case PCIE_DEVICE_ID_MARVELL_88W8897:
-       case PCIE_DEVICE_ID_MARVELL_88W8997:
-               if (((card->txbd_wrptr & reg->tx_mask) !=
-                    (card->txbd_rdptr & reg->tx_mask)) ||
-                   ((card->txbd_wrptr & reg->tx_rollover_ind) ==
-                    (card->txbd_rdptr & reg->tx_rollover_ind)))
-                       return 1;
-               break;
-       }
-
-       return 0;
-}
-
-#endif /* _MWIFIEX_PCIE_H */
diff --git a/drivers/net/wireless/mwifiex/scan.c b/drivers/net/wireless/mwifiex/scan.c
deleted file mode 100644 (file)
index c20017c..0000000
+++ /dev/null
@@ -1,2639 +0,0 @@
-/*
- * Marvell Wireless LAN device driver: scan ioctl and command handling
- *
- * Copyright (C) 2011-2014, Marvell International Ltd.
- *
- * This software file (the "File") is distributed by Marvell International
- * Ltd. under the terms of the GNU General Public License Version 2, June 1991
- * (the "License").  You may use, redistribute and/or modify this File in
- * accordance with the terms and conditions of the License, a copy of which
- * is available by writing to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the
- * worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
- *
- * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
- * ARE EXPRESSLY DISCLAIMED.  The License provides additional details about
- * this warranty disclaimer.
- */
-
-#include "decl.h"
-#include "ioctl.h"
-#include "util.h"
-#include "fw.h"
-#include "main.h"
-#include "11n.h"
-#include "cfg80211.h"
-
-/* The maximum number of channels the firmware can scan per command */
-#define MWIFIEX_MAX_CHANNELS_PER_SPECIFIC_SCAN   14
-
-#define MWIFIEX_DEF_CHANNELS_PER_SCAN_CMD      4
-
-/* Memory needed to store a max sized Channel List TLV for a firmware scan */
-#define CHAN_TLV_MAX_SIZE  (sizeof(struct mwifiex_ie_types_header)         \
-                               + (MWIFIEX_MAX_CHANNELS_PER_SPECIFIC_SCAN     \
-                               *sizeof(struct mwifiex_chan_scan_param_set)))
-
-/* Memory needed to store supported rate */
-#define RATE_TLV_MAX_SIZE   (sizeof(struct mwifiex_ie_types_rates_param_set) \
-                               + HOSTCMD_SUPPORTED_RATES)
-
-/* Memory needed to store a max number/size WildCard SSID TLV for a firmware
-       scan */
-#define WILDCARD_SSID_TLV_MAX_SIZE  \
-       (MWIFIEX_MAX_SSID_LIST_LENGTH *                                 \
-               (sizeof(struct mwifiex_ie_types_wildcard_ssid_params)   \
-                       + IEEE80211_MAX_SSID_LEN))
-
-/* Maximum memory needed for a mwifiex_scan_cmd_config with all TLVs at max */
-#define MAX_SCAN_CFG_ALLOC (sizeof(struct mwifiex_scan_cmd_config)        \
-                               + sizeof(struct mwifiex_ie_types_num_probes)   \
-                               + sizeof(struct mwifiex_ie_types_htcap)       \
-                               + CHAN_TLV_MAX_SIZE                 \
-                               + RATE_TLV_MAX_SIZE                 \
-                               + WILDCARD_SSID_TLV_MAX_SIZE)
-
-
-union mwifiex_scan_cmd_config_tlv {
-       /* Scan configuration (variable length) */
-       struct mwifiex_scan_cmd_config config;
-       /* Max allocated block */
-       u8 config_alloc_buf[MAX_SCAN_CFG_ALLOC];
-};
-
-enum cipher_suite {
-       CIPHER_SUITE_TKIP,
-       CIPHER_SUITE_CCMP,
-       CIPHER_SUITE_MAX
-};
-static u8 mwifiex_wpa_oui[CIPHER_SUITE_MAX][4] = {
-       { 0x00, 0x50, 0xf2, 0x02 },     /* TKIP */
-       { 0x00, 0x50, 0xf2, 0x04 },     /* AES  */
-};
-static u8 mwifiex_rsn_oui[CIPHER_SUITE_MAX][4] = {
-       { 0x00, 0x0f, 0xac, 0x02 },     /* TKIP */
-       { 0x00, 0x0f, 0xac, 0x04 },     /* AES  */
-};
-
-/*
- * This function parses a given IE for a given OUI.
- *
- * This is used to parse a WPA/RSN IE to find if it has
- * a given oui in PTK.
- */
-static u8
-mwifiex_search_oui_in_ie(struct ie_body *iebody, u8 *oui)
-{
-       u8 count;
-
-       count = iebody->ptk_cnt[0];
-
-       /* There could be multiple OUIs for PTK hence
-          1) Take the length.
-          2) Check all the OUIs for AES.
-          3) If one of them is AES then pass success. */
-       while (count) {
-               if (!memcmp(iebody->ptk_body, oui, sizeof(iebody->ptk_body)))
-                       return MWIFIEX_OUI_PRESENT;
-
-               --count;
-               if (count)
-                       iebody = (struct ie_body *) ((u8 *) iebody +
-                                               sizeof(iebody->ptk_body));
-       }
-
-       pr_debug("info: %s: OUI is not found in PTK\n", __func__);
-       return MWIFIEX_OUI_NOT_PRESENT;
-}
-
-/*
- * This function checks if a given OUI is present in a RSN IE.
- *
- * The function first checks if a RSN IE is present or not in the
- * BSS descriptor. It tries to locate the OUI only if such an IE is
- * present.
- */
-static u8
-mwifiex_is_rsn_oui_present(struct mwifiex_bssdescriptor *bss_desc, u32 cipher)
-{
-       u8 *oui;
-       struct ie_body *iebody;
-       u8 ret = MWIFIEX_OUI_NOT_PRESENT;
-
-       if (((bss_desc->bcn_rsn_ie) && ((*(bss_desc->bcn_rsn_ie)).
-                                       ieee_hdr.element_id == WLAN_EID_RSN))) {
-               iebody = (struct ie_body *)
-                        (((u8 *) bss_desc->bcn_rsn_ie->data) +
-                         RSN_GTK_OUI_OFFSET);
-               oui = &mwifiex_rsn_oui[cipher][0];
-               ret = mwifiex_search_oui_in_ie(iebody, oui);
-               if (ret)
-                       return ret;
-       }
-       return ret;
-}
-
-/*
- * This function checks if a given OUI is present in a WPA IE.
- *
- * The function first checks if a WPA IE is present or not in the
- * BSS descriptor. It tries to locate the OUI only if such an IE is
- * present.
- */
-static u8
-mwifiex_is_wpa_oui_present(struct mwifiex_bssdescriptor *bss_desc, u32 cipher)
-{
-       u8 *oui;
-       struct ie_body *iebody;
-       u8 ret = MWIFIEX_OUI_NOT_PRESENT;
-
-       if (((bss_desc->bcn_wpa_ie) &&
-            ((*(bss_desc->bcn_wpa_ie)).vend_hdr.element_id ==
-             WLAN_EID_VENDOR_SPECIFIC))) {
-               iebody = (struct ie_body *) bss_desc->bcn_wpa_ie->data;
-               oui = &mwifiex_wpa_oui[cipher][0];
-               ret = mwifiex_search_oui_in_ie(iebody, oui);
-               if (ret)
-                       return ret;
-       }
-       return ret;
-}
-
-/*
- * This function compares two SSIDs and checks if they match.
- */
-s32
-mwifiex_ssid_cmp(struct cfg80211_ssid *ssid1, struct cfg80211_ssid *ssid2)
-{
-       if (!ssid1 || !ssid2 || (ssid1->ssid_len != ssid2->ssid_len))
-               return -1;
-       return memcmp(ssid1->ssid, ssid2->ssid, ssid1->ssid_len);
-}
-
-/*
- * This function checks if wapi is enabled in driver and scanned network is
- * compatible with it.
- */
-static bool
-mwifiex_is_bss_wapi(struct mwifiex_private *priv,
-                   struct mwifiex_bssdescriptor *bss_desc)
-{
-       if (priv->sec_info.wapi_enabled &&
-           (bss_desc->bcn_wapi_ie &&
-            ((*(bss_desc->bcn_wapi_ie)).ieee_hdr.element_id ==
-                       WLAN_EID_BSS_AC_ACCESS_DELAY))) {
-               return true;
-       }
-       return false;
-}
-
-/*
- * This function checks if driver is configured with no security mode and
- * scanned network is compatible with it.
- */
-static bool
-mwifiex_is_bss_no_sec(struct mwifiex_private *priv,
-                     struct mwifiex_bssdescriptor *bss_desc)
-{
-       if (!priv->sec_info.wep_enabled && !priv->sec_info.wpa_enabled &&
-           !priv->sec_info.wpa2_enabled && ((!bss_desc->bcn_wpa_ie) ||
-               ((*(bss_desc->bcn_wpa_ie)).vend_hdr.element_id !=
-                WLAN_EID_VENDOR_SPECIFIC)) &&
-           ((!bss_desc->bcn_rsn_ie) ||
-               ((*(bss_desc->bcn_rsn_ie)).ieee_hdr.element_id !=
-                WLAN_EID_RSN)) &&
-           !priv->sec_info.encryption_mode && !bss_desc->privacy) {
-               return true;
-       }
-       return false;
-}
-
-/*
- * This function checks if static WEP is enabled in driver and scanned network
- * is compatible with it.
- */
-static bool
-mwifiex_is_bss_static_wep(struct mwifiex_private *priv,
-                         struct mwifiex_bssdescriptor *bss_desc)
-{
-       if (priv->sec_info.wep_enabled && !priv->sec_info.wpa_enabled &&
-           !priv->sec_info.wpa2_enabled && bss_desc->privacy) {
-               return true;
-       }
-       return false;
-}
-
-/*
- * This function checks if wpa is enabled in driver and scanned network is
- * compatible with it.
- */
-static bool
-mwifiex_is_bss_wpa(struct mwifiex_private *priv,
-                  struct mwifiex_bssdescriptor *bss_desc)
-{
-       if (!priv->sec_info.wep_enabled && priv->sec_info.wpa_enabled &&
-           !priv->sec_info.wpa2_enabled && ((bss_desc->bcn_wpa_ie) &&
-           ((*(bss_desc->bcn_wpa_ie)).
-            vend_hdr.element_id == WLAN_EID_VENDOR_SPECIFIC))
-          /*
-           * Privacy bit may NOT be set in some APs like
-           * LinkSys WRT54G && bss_desc->privacy
-           */
-        ) {
-               mwifiex_dbg(priv->adapter, INFO,
-                           "info: %s: WPA:\t"
-                           "wpa_ie=%#x wpa2_ie=%#x WEP=%s WPA=%s WPA2=%s\t"
-                           "EncMode=%#x privacy=%#x\n", __func__,
-                           (bss_desc->bcn_wpa_ie) ?
-                           (*bss_desc->bcn_wpa_ie).
-                           vend_hdr.element_id : 0,
-                           (bss_desc->bcn_rsn_ie) ?
-                           (*bss_desc->bcn_rsn_ie).
-                           ieee_hdr.element_id : 0,
-                           (priv->sec_info.wep_enabled) ? "e" : "d",
-                           (priv->sec_info.wpa_enabled) ? "e" : "d",
-                           (priv->sec_info.wpa2_enabled) ? "e" : "d",
-                           priv->sec_info.encryption_mode,
-                           bss_desc->privacy);
-               return true;
-       }
-       return false;
-}
-
-/*
- * This function checks if wpa2 is enabled in driver and scanned network is
- * compatible with it.
- */
-static bool
-mwifiex_is_bss_wpa2(struct mwifiex_private *priv,
-                   struct mwifiex_bssdescriptor *bss_desc)
-{
-       if (!priv->sec_info.wep_enabled &&
-           !priv->sec_info.wpa_enabled &&
-           priv->sec_info.wpa2_enabled &&
-           ((bss_desc->bcn_rsn_ie) &&
-            ((*(bss_desc->bcn_rsn_ie)).ieee_hdr.element_id == WLAN_EID_RSN))) {
-               /*
-                * Privacy bit may NOT be set in some APs like
-                * LinkSys WRT54G && bss_desc->privacy
-                */
-               mwifiex_dbg(priv->adapter, INFO,
-                           "info: %s: WPA2:\t"
-                           "wpa_ie=%#x wpa2_ie=%#x WEP=%s WPA=%s WPA2=%s\t"
-                           "EncMode=%#x privacy=%#x\n", __func__,
-                           (bss_desc->bcn_wpa_ie) ?
-                           (*bss_desc->bcn_wpa_ie).
-                           vend_hdr.element_id : 0,
-                           (bss_desc->bcn_rsn_ie) ?
-                           (*bss_desc->bcn_rsn_ie).
-                           ieee_hdr.element_id : 0,
-                           (priv->sec_info.wep_enabled) ? "e" : "d",
-                           (priv->sec_info.wpa_enabled) ? "e" : "d",
-                           (priv->sec_info.wpa2_enabled) ? "e" : "d",
-                           priv->sec_info.encryption_mode,
-                           bss_desc->privacy);
-               return true;
-       }
-       return false;
-}
-
-/*
- * This function checks if adhoc AES is enabled in driver and scanned network is
- * compatible with it.
- */
-static bool
-mwifiex_is_bss_adhoc_aes(struct mwifiex_private *priv,
-                        struct mwifiex_bssdescriptor *bss_desc)
-{
-       if (!priv->sec_info.wep_enabled && !priv->sec_info.wpa_enabled &&
-           !priv->sec_info.wpa2_enabled &&
-           ((!bss_desc->bcn_wpa_ie) ||
-            ((*(bss_desc->bcn_wpa_ie)).
-             vend_hdr.element_id != WLAN_EID_VENDOR_SPECIFIC)) &&
-           ((!bss_desc->bcn_rsn_ie) ||
-            ((*(bss_desc->bcn_rsn_ie)).ieee_hdr.element_id != WLAN_EID_RSN)) &&
-           !priv->sec_info.encryption_mode && bss_desc->privacy) {
-               return true;
-       }
-       return false;
-}
-
-/*
- * This function checks if dynamic WEP is enabled in driver and scanned network
- * is compatible with it.
- */
-static bool
-mwifiex_is_bss_dynamic_wep(struct mwifiex_private *priv,
-                          struct mwifiex_bssdescriptor *bss_desc)
-{
-       if (!priv->sec_info.wep_enabled && !priv->sec_info.wpa_enabled &&
-           !priv->sec_info.wpa2_enabled &&
-           ((!bss_desc->bcn_wpa_ie) ||
-            ((*(bss_desc->bcn_wpa_ie)).
-             vend_hdr.element_id != WLAN_EID_VENDOR_SPECIFIC)) &&
-           ((!bss_desc->bcn_rsn_ie) ||
-            ((*(bss_desc->bcn_rsn_ie)).ieee_hdr.element_id != WLAN_EID_RSN)) &&
-           priv->sec_info.encryption_mode && bss_desc->privacy) {
-               mwifiex_dbg(priv->adapter, INFO,
-                           "info: %s: dynamic\t"
-                           "WEP: wpa_ie=%#x wpa2_ie=%#x\t"
-                           "EncMode=%#x privacy=%#x\n",
-                           __func__,
-                           (bss_desc->bcn_wpa_ie) ?
-                           (*bss_desc->bcn_wpa_ie).
-                           vend_hdr.element_id : 0,
-                           (bss_desc->bcn_rsn_ie) ?
-                           (*bss_desc->bcn_rsn_ie).
-                           ieee_hdr.element_id : 0,
-                           priv->sec_info.encryption_mode,
-                           bss_desc->privacy);
-               return true;
-       }
-       return false;
-}
-
-/*
- * This function checks if a scanned network is compatible with the driver
- * settings.
- *
- *   WEP     WPA    WPA2   ad-hoc encrypt                  Network
- * enabled enabled enabled  AES    mode   Privacy WPA WPA2 Compatible
- *    0       0       0      0     NONE      0     0   0   yes No security
- *    0       1       0      0      x        1x    1   x   yes WPA (disable
- *                                                         HT if no AES)
- *    0       0       1      0      x        1x    x   1   yes WPA2 (disable
- *                                                         HT if no AES)
- *    0       0       0      1     NONE      1     0   0   yes Ad-hoc AES
- *    1       0       0      0     NONE      1     0   0   yes Static WEP
- *                                                         (disable HT)
- *    0       0       0      0    !=NONE     1     0   0   yes Dynamic WEP
- *
- * Compatibility is not matched while roaming, except for mode.
- */
-static s32
-mwifiex_is_network_compatible(struct mwifiex_private *priv,
-                             struct mwifiex_bssdescriptor *bss_desc, u32 mode)
-{
-       struct mwifiex_adapter *adapter = priv->adapter;
-
-       bss_desc->disable_11n = false;
-
-       /* Don't check for compatibility if roaming */
-       if (priv->media_connected &&
-           (priv->bss_mode == NL80211_IFTYPE_STATION) &&
-           (bss_desc->bss_mode == NL80211_IFTYPE_STATION))
-               return 0;
-
-       if (priv->wps.session_enable) {
-               mwifiex_dbg(adapter, IOCTL,
-                           "info: return success directly in WPS period\n");
-               return 0;
-       }
-
-       if (bss_desc->chan_sw_ie_present) {
-               mwifiex_dbg(adapter, INFO,
-                           "Don't connect to AP with WLAN_EID_CHANNEL_SWITCH\n");
-               return -1;
-       }
-
-       if (mwifiex_is_bss_wapi(priv, bss_desc)) {
-               mwifiex_dbg(adapter, INFO,
-                           "info: return success for WAPI AP\n");
-               return 0;
-       }
-
-       if (bss_desc->bss_mode == mode) {
-               if (mwifiex_is_bss_no_sec(priv, bss_desc)) {
-                       /* No security */
-                       return 0;
-               } else if (mwifiex_is_bss_static_wep(priv, bss_desc)) {
-                       /* Static WEP enabled */
-                       mwifiex_dbg(adapter, INFO,
-                                   "info: Disable 11n in WEP mode.\n");
-                       bss_desc->disable_11n = true;
-                       return 0;
-               } else if (mwifiex_is_bss_wpa(priv, bss_desc)) {
-                       /* WPA enabled */
-                       if (((priv->adapter->config_bands & BAND_GN ||
-                             priv->adapter->config_bands & BAND_AN) &&
-                            bss_desc->bcn_ht_cap) &&
-                           !mwifiex_is_wpa_oui_present(bss_desc,
-                                                        CIPHER_SUITE_CCMP)) {
-
-                               if (mwifiex_is_wpa_oui_present
-                                               (bss_desc, CIPHER_SUITE_TKIP)) {
-                                       mwifiex_dbg(adapter, INFO,
-                                                   "info: Disable 11n if AES\t"
-                                                   "is not supported by AP\n");
-                                       bss_desc->disable_11n = true;
-                               } else {
-                                       return -1;
-                               }
-                       }
-                       return 0;
-               } else if (mwifiex_is_bss_wpa2(priv, bss_desc)) {
-                       /* WPA2 enabled */
-                       if (((priv->adapter->config_bands & BAND_GN ||
-                             priv->adapter->config_bands & BAND_AN) &&
-                            bss_desc->bcn_ht_cap) &&
-                           !mwifiex_is_rsn_oui_present(bss_desc,
-                                                       CIPHER_SUITE_CCMP)) {
-
-                               if (mwifiex_is_rsn_oui_present
-                                               (bss_desc, CIPHER_SUITE_TKIP)) {
-                                       mwifiex_dbg(adapter, INFO,
-                                                   "info: Disable 11n if AES\t"
-                                                   "is not supported by AP\n");
-                                       bss_desc->disable_11n = true;
-                               } else {
-                                       return -1;
-                               }
-                       }
-                       return 0;
-               } else if (mwifiex_is_bss_adhoc_aes(priv, bss_desc)) {
-                       /* Ad-hoc AES enabled */
-                       return 0;
-               } else if (mwifiex_is_bss_dynamic_wep(priv, bss_desc)) {
-                       /* Dynamic WEP enabled */
-                       return 0;
-               }
-
-               /* Security doesn't match */
-               mwifiex_dbg(adapter, ERROR,
-                           "info: %s: failed: wpa_ie=%#x wpa2_ie=%#x WEP=%s\t"
-                           "WPA=%s WPA2=%s EncMode=%#x privacy=%#x\n",
-                           __func__,
-                           (bss_desc->bcn_wpa_ie) ?
-                           (*bss_desc->bcn_wpa_ie).vend_hdr.element_id : 0,
-                           (bss_desc->bcn_rsn_ie) ?
-                           (*bss_desc->bcn_rsn_ie).ieee_hdr.element_id : 0,
-                           (priv->sec_info.wep_enabled) ? "e" : "d",
-                           (priv->sec_info.wpa_enabled) ? "e" : "d",
-                           (priv->sec_info.wpa2_enabled) ? "e" : "d",
-                           priv->sec_info.encryption_mode, bss_desc->privacy);
-               return -1;
-       }
-
-       /* Mode doesn't match */
-       return -1;
-}
-
-/*
- * This function creates a channel list for the driver to scan, based
- * on region/band information.
- *
- * This routine is used for any scan that is not provided with a
- * specific channel list to scan.
- */
-static int
-mwifiex_scan_create_channel_list(struct mwifiex_private *priv,
-                                const struct mwifiex_user_scan_cfg
-                                                       *user_scan_in,
-                                struct mwifiex_chan_scan_param_set
-                                                       *scan_chan_list,
-                                u8 filtered_scan)
-{
-       enum ieee80211_band band;
-       struct ieee80211_supported_band *sband;
-       struct ieee80211_channel *ch;
-       struct mwifiex_adapter *adapter = priv->adapter;
-       int chan_idx = 0, i;
-
-       for (band = 0; (band < IEEE80211_NUM_BANDS) ; band++) {
-
-               if (!priv->wdev.wiphy->bands[band])
-                       continue;
-
-               sband = priv->wdev.wiphy->bands[band];
-
-               for (i = 0; (i < sband->n_channels) ; i++) {
-                       ch = &sband->channels[i];
-                       if (ch->flags & IEEE80211_CHAN_DISABLED)
-                               continue;
-                       scan_chan_list[chan_idx].radio_type = band;
-
-                       if (user_scan_in &&
-                           user_scan_in->chan_list[0].scan_time)
-                               scan_chan_list[chan_idx].max_scan_time =
-                                       cpu_to_le16((u16) user_scan_in->
-                                       chan_list[0].scan_time);
-                       else if (ch->flags & IEEE80211_CHAN_NO_IR)
-                               scan_chan_list[chan_idx].max_scan_time =
-                                       cpu_to_le16(adapter->passive_scan_time);
-                       else
-                               scan_chan_list[chan_idx].max_scan_time =
-                                       cpu_to_le16(adapter->active_scan_time);
-
-                       if (ch->flags & IEEE80211_CHAN_NO_IR)
-                               scan_chan_list[chan_idx].chan_scan_mode_bitmap
-                                       |= (MWIFIEX_PASSIVE_SCAN |
-                                           MWIFIEX_HIDDEN_SSID_REPORT);
-                       else
-                               scan_chan_list[chan_idx].chan_scan_mode_bitmap
-                                       &= ~MWIFIEX_PASSIVE_SCAN;
-                       scan_chan_list[chan_idx].chan_number =
-                                                       (u32) ch->hw_value;
-                       if (filtered_scan) {
-                               scan_chan_list[chan_idx].max_scan_time =
-                               cpu_to_le16(adapter->specific_scan_time);
-                               scan_chan_list[chan_idx].chan_scan_mode_bitmap
-                                       |= MWIFIEX_DISABLE_CHAN_FILT;
-                       }
-                       chan_idx++;
-               }
-
-       }
-       return chan_idx;
-}
-
-/* This function appends rate TLV to scan config command. */
-static int
-mwifiex_append_rate_tlv(struct mwifiex_private *priv,
-                       struct mwifiex_scan_cmd_config *scan_cfg_out,
-                       u8 radio)
-{
-       struct mwifiex_ie_types_rates_param_set *rates_tlv;
-       u8 rates[MWIFIEX_SUPPORTED_RATES], *tlv_pos;
-       u32 rates_size;
-
-       memset(rates, 0, sizeof(rates));
-
-       tlv_pos = (u8 *)scan_cfg_out->tlv_buf + scan_cfg_out->tlv_buf_len;
-
-       if (priv->scan_request)
-               rates_size = mwifiex_get_rates_from_cfg80211(priv, rates,
-                                                            radio);
-       else
-               rates_size = mwifiex_get_supported_rates(priv, rates);
-
-       mwifiex_dbg(priv->adapter, CMD,
-                   "info: SCAN_CMD: Rates size = %d\n",
-               rates_size);
-       rates_tlv = (struct mwifiex_ie_types_rates_param_set *)tlv_pos;
-       rates_tlv->header.type = cpu_to_le16(WLAN_EID_SUPP_RATES);
-       rates_tlv->header.len = cpu_to_le16((u16) rates_size);
-       memcpy(rates_tlv->rates, rates, rates_size);
-       scan_cfg_out->tlv_buf_len += sizeof(rates_tlv->header) + rates_size;
-
-       return rates_size;
-}
-
-/*
- * This function constructs and sends multiple scan config commands to
- * the firmware.
- *
- * Previous routines in the code flow have created a scan command configuration
- * with any requested TLVs.  This function splits the channel TLV into maximum
- * channels supported per scan lists and sends the portion of the channel TLV,
- * along with the other TLVs, to the firmware.
- */
-static int
-mwifiex_scan_channel_list(struct mwifiex_private *priv,
-                         u32 max_chan_per_scan, u8 filtered_scan,
-                         struct mwifiex_scan_cmd_config *scan_cfg_out,
-                         struct mwifiex_ie_types_chan_list_param_set
-                         *chan_tlv_out,
-                         struct mwifiex_chan_scan_param_set *scan_chan_list)
-{
-       struct mwifiex_adapter *adapter = priv->adapter;
-       int ret = 0;
-       struct mwifiex_chan_scan_param_set *tmp_chan_list;
-       struct mwifiex_chan_scan_param_set *start_chan;
-       struct cmd_ctrl_node *cmd_node, *tmp_node;
-       unsigned long flags;
-       u32 tlv_idx, rates_size, cmd_no;
-       u32 total_scan_time;
-       u32 done_early;
-       u8 radio_type;
-
-       if (!scan_cfg_out || !chan_tlv_out || !scan_chan_list) {
-               mwifiex_dbg(priv->adapter, ERROR,
-                           "info: Scan: Null detect: %p, %p, %p\n",
-                           scan_cfg_out, chan_tlv_out, scan_chan_list);
-               return -1;
-       }
-
-       /* Check csa channel expiry before preparing scan list */
-       mwifiex_11h_get_csa_closed_channel(priv);
-
-       chan_tlv_out->header.type = cpu_to_le16(TLV_TYPE_CHANLIST);
-
-       /* Set the temp channel struct pointer to the start of the desired
-          list */
-       tmp_chan_list = scan_chan_list;
-
-       /* Loop through the desired channel list, sending a new firmware scan
-          commands for each max_chan_per_scan channels (or for 1,6,11
-          individually if configured accordingly) */
-       while (tmp_chan_list->chan_number) {
-
-               tlv_idx = 0;
-               total_scan_time = 0;
-               radio_type = 0;
-               chan_tlv_out->header.len = 0;
-               start_chan = tmp_chan_list;
-               done_early = false;
-
-               /*
-                * Construct the Channel TLV for the scan command.  Continue to
-                * insert channel TLVs until:
-                *   - the tlv_idx hits the maximum configured per scan command
-                *   - the next channel to insert is 0 (end of desired channel
-                *     list)
-                *   - done_early is set (controlling individual scanning of
-                *     1,6,11)
-                */
-               while (tlv_idx < max_chan_per_scan &&
-                      tmp_chan_list->chan_number && !done_early) {
-
-                       if (tmp_chan_list->chan_number == priv->csa_chan) {
-                               tmp_chan_list++;
-                               continue;
-                       }
-
-                       radio_type = tmp_chan_list->radio_type;
-                       mwifiex_dbg(priv->adapter, INFO,
-                                   "info: Scan: Chan(%3d), Radio(%d),\t"
-                                   "Mode(%d, %d), Dur(%d)\n",
-                                   tmp_chan_list->chan_number,
-                                   tmp_chan_list->radio_type,
-                                   tmp_chan_list->chan_scan_mode_bitmap
-                                   & MWIFIEX_PASSIVE_SCAN,
-                                   (tmp_chan_list->chan_scan_mode_bitmap
-                                   & MWIFIEX_DISABLE_CHAN_FILT) >> 1,
-                                   le16_to_cpu(tmp_chan_list->max_scan_time));
-
-                       /* Copy the current channel TLV to the command being
-                          prepared */
-                       memcpy(chan_tlv_out->chan_scan_param + tlv_idx,
-                              tmp_chan_list,
-                              sizeof(chan_tlv_out->chan_scan_param));
-
-                       /* Increment the TLV header length by the size
-                          appended */
-                       le16_add_cpu(&chan_tlv_out->header.len,
-                                    sizeof(chan_tlv_out->chan_scan_param));
-
-                       /*
-                        * The tlv buffer length is set to the number of bytes
-                        * of the between the channel tlv pointer and the start
-                        * of the tlv buffer.  This compensates for any TLVs
-                        * that were appended before the channel list.
-                        */
-                       scan_cfg_out->tlv_buf_len = (u32) ((u8 *) chan_tlv_out -
-                                                       scan_cfg_out->tlv_buf);
-
-                       /* Add the size of the channel tlv header and the data
-                          length */
-                       scan_cfg_out->tlv_buf_len +=
-                               (sizeof(chan_tlv_out->header)
-                                + le16_to_cpu(chan_tlv_out->header.len));
-
-                       /* Increment the index to the channel tlv we are
-                          constructing */
-                       tlv_idx++;
-
-                       /* Count the total scan time per command */
-                       total_scan_time +=
-                               le16_to_cpu(tmp_chan_list->max_scan_time);
-
-                       done_early = false;
-
-                       /* Stop the loop if the *current* channel is in the
-                          1,6,11 set and we are not filtering on a BSSID
-                          or SSID. */
-                       if (!filtered_scan &&
-                           (tmp_chan_list->chan_number == 1 ||
-                            tmp_chan_list->chan_number == 6 ||
-                            tmp_chan_list->chan_number == 11))
-                               done_early = true;
-
-                       /* Increment the tmp pointer to the next channel to
-                          be scanned */
-                       tmp_chan_list++;
-
-                       /* Stop the loop if the *next* channel is in the 1,6,11
-                          set.  This will cause it to be the only channel
-                          scanned on the next interation */
-                       if (!filtered_scan &&
-                           (tmp_chan_list->chan_number == 1 ||
-                            tmp_chan_list->chan_number == 6 ||
-                            tmp_chan_list->chan_number == 11))
-                               done_early = true;
-               }
-
-               /* The total scan time should be less than scan command timeout
-                  value */
-               if (total_scan_time > MWIFIEX_MAX_TOTAL_SCAN_TIME) {
-                       mwifiex_dbg(priv->adapter, ERROR,
-                                   "total scan time %dms\t"
-                                   "is over limit (%dms), scan skipped\n",
-                                   total_scan_time,
-                                   MWIFIEX_MAX_TOTAL_SCAN_TIME);
-                       ret = -1;
-                       break;
-               }
-
-               rates_size = mwifiex_append_rate_tlv(priv, scan_cfg_out,
-                                                    radio_type);
-
-               priv->adapter->scan_channels = start_chan;
-
-               /* Send the scan command to the firmware with the specified
-                  cfg */
-               if (priv->adapter->ext_scan)
-                       cmd_no = HostCmd_CMD_802_11_SCAN_EXT;
-               else
-                       cmd_no = HostCmd_CMD_802_11_SCAN;
-
-               ret = mwifiex_send_cmd(priv, cmd_no, HostCmd_ACT_GEN_SET,
-                                      0, scan_cfg_out, false);
-
-               /* rate IE is updated per scan command but same starting
-                * pointer is used each time so that rate IE from earlier
-                * scan_cfg_out->buf is overwritten with new one.
-                */
-               scan_cfg_out->tlv_buf_len -=
-                           sizeof(struct mwifiex_ie_types_header) + rates_size;
-
-               if (ret) {
-                       spin_lock_irqsave(&adapter->scan_pending_q_lock, flags);
-                       list_for_each_entry_safe(cmd_node, tmp_node,
-                                                &adapter->scan_pending_q,
-                                                list) {
-                               list_del(&cmd_node->list);
-                               cmd_node->wait_q_enabled = false;
-                               mwifiex_insert_cmd_to_free_q(adapter, cmd_node);
-                       }
-                       spin_unlock_irqrestore(&adapter->scan_pending_q_lock,
-                                              flags);
-                       break;
-               }
-       }
-
-       if (ret)
-               return -1;
-
-       return 0;
-}
-
-/*
- * This function constructs a scan command configuration structure to use
- * in scan commands.
- *
- * Application layer or other functions can invoke network scanning
- * with a scan configuration supplied in a user scan configuration structure.
- * This structure is used as the basis of one or many scan command configuration
- * commands that are sent to the command processing module and eventually to the
- * firmware.
- *
- * This function creates a scan command configuration structure  based on the
- * following user supplied parameters (if present):
- *      - SSID filter
- *      - BSSID filter
- *      - Number of Probes to be sent
- *      - Channel list
- *
- * If the SSID or BSSID filter is not present, the filter is disabled/cleared.
- * If the number of probes is not set, adapter default setting is used.
- */
-static void
-mwifiex_config_scan(struct mwifiex_private *priv,
-                   const struct mwifiex_user_scan_cfg *user_scan_in,
-                   struct mwifiex_scan_cmd_config *scan_cfg_out,
-                   struct mwifiex_ie_types_chan_list_param_set **chan_list_out,
-                   struct mwifiex_chan_scan_param_set *scan_chan_list,
-                   u8 *max_chan_per_scan, u8 *filtered_scan,
-                   u8 *scan_current_only)
-{
-       struct mwifiex_adapter *adapter = priv->adapter;
-       struct mwifiex_ie_types_num_probes *num_probes_tlv;
-       struct mwifiex_ie_types_scan_chan_gap *chan_gap_tlv;
-       struct mwifiex_ie_types_wildcard_ssid_params *wildcard_ssid_tlv;
-       struct mwifiex_ie_types_bssid_list *bssid_tlv;
-       u8 *tlv_pos;
-       u32 num_probes;
-       u32 ssid_len;
-       u32 chan_idx;
-       u32 chan_num;
-       u32 scan_type;
-       u16 scan_dur;
-       u8 channel;
-       u8 radio_type;
-       int i;
-       u8 ssid_filter;
-       struct mwifiex_ie_types_htcap *ht_cap;
-       struct mwifiex_ie_types_bss_mode *bss_mode;
-
-       /* The tlv_buf_len is calculated for each scan command.  The TLVs added
-          in this routine will be preserved since the routine that sends the
-          command will append channelTLVs at *chan_list_out.  The difference
-          between the *chan_list_out and the tlv_buf start will be used to
-          calculate the size of anything we add in this routine. */
-       scan_cfg_out->tlv_buf_len = 0;
-
-       /* Running tlv pointer.  Assigned to chan_list_out at end of function
-          so later routines know where channels can be added to the command
-          buf */
-       tlv_pos = scan_cfg_out->tlv_buf;
-
-       /* Initialize the scan as un-filtered; the flag is later set to TRUE
-          below if a SSID or BSSID filter is sent in the command */
-       *filtered_scan = false;
-
-       /* Initialize the scan as not being only on the current channel.  If
-          the channel list is customized, only contains one channel, and is
-          the active channel, this is set true and data flow is not halted. */
-       *scan_current_only = false;
-
-       if (user_scan_in) {
-
-               /* Default the ssid_filter flag to TRUE, set false under
-                  certain wildcard conditions and qualified by the existence
-                  of an SSID list before marking the scan as filtered */
-               ssid_filter = true;
-
-               /* Set the BSS type scan filter, use Adapter setting if
-                  unset */
-               scan_cfg_out->bss_mode =
-                       (user_scan_in->bss_mode ? (u8) user_scan_in->
-                        bss_mode : (u8) adapter->scan_mode);
-
-               /* Set the number of probes to send, use Adapter setting
-                  if unset */
-               num_probes =
-                       (user_scan_in->num_probes ? user_scan_in->
-                        num_probes : adapter->scan_probes);
-
-               /*
-                * Set the BSSID filter to the incoming configuration,
-                * if non-zero.  If not set, it will remain disabled
-                * (all zeros).
-                */
-               memcpy(scan_cfg_out->specific_bssid,
-                      user_scan_in->specific_bssid,
-                      sizeof(scan_cfg_out->specific_bssid));
-
-               if (adapter->ext_scan &&
-                   !is_zero_ether_addr(scan_cfg_out->specific_bssid)) {
-                       bssid_tlv =
-                               (struct mwifiex_ie_types_bssid_list *)tlv_pos;
-                       bssid_tlv->header.type = cpu_to_le16(TLV_TYPE_BSSID);
-                       bssid_tlv->header.len = cpu_to_le16(ETH_ALEN);
-                       memcpy(bssid_tlv->bssid, user_scan_in->specific_bssid,
-                              ETH_ALEN);
-                       tlv_pos += sizeof(struct mwifiex_ie_types_bssid_list);
-               }
-
-               for (i = 0; i < user_scan_in->num_ssids; i++) {
-                       ssid_len = user_scan_in->ssid_list[i].ssid_len;
-
-                       wildcard_ssid_tlv =
-                               (struct mwifiex_ie_types_wildcard_ssid_params *)
-                               tlv_pos;
-                       wildcard_ssid_tlv->header.type =
-                               cpu_to_le16(TLV_TYPE_WILDCARDSSID);
-                       wildcard_ssid_tlv->header.len = cpu_to_le16(
-                               (u16) (ssid_len + sizeof(wildcard_ssid_tlv->
-                                                        max_ssid_length)));
-
-                       /*
-                        * max_ssid_length = 0 tells firmware to perform
-                        * specific scan for the SSID filled, whereas
-                        * max_ssid_length = IEEE80211_MAX_SSID_LEN is for
-                        * wildcard scan.
-                        */
-                       if (ssid_len)
-                               wildcard_ssid_tlv->max_ssid_length = 0;
-                       else
-                               wildcard_ssid_tlv->max_ssid_length =
-                                                       IEEE80211_MAX_SSID_LEN;
-
-                       if (!memcmp(user_scan_in->ssid_list[i].ssid,
-                                   "DIRECT-", 7))
-                               wildcard_ssid_tlv->max_ssid_length = 0xfe;
-
-                       memcpy(wildcard_ssid_tlv->ssid,
-                              user_scan_in->ssid_list[i].ssid, ssid_len);
-
-                       tlv_pos += (sizeof(wildcard_ssid_tlv->header)
-                               + le16_to_cpu(wildcard_ssid_tlv->header.len));
-
-                       mwifiex_dbg(adapter, INFO,
-                                   "info: scan: ssid[%d]: %s, %d\n",
-                                   i, wildcard_ssid_tlv->ssid,
-                                   wildcard_ssid_tlv->max_ssid_length);
-
-                       /* Empty wildcard ssid with a maxlen will match many or
-                          potentially all SSIDs (maxlen == 32), therefore do
-                          not treat the scan as
-                          filtered. */
-                       if (!ssid_len && wildcard_ssid_tlv->max_ssid_length)
-                               ssid_filter = false;
-               }
-
-               /*
-                *  The default number of channels sent in the command is low to
-                *  ensure the response buffer from the firmware does not
-                *  truncate scan results.  That is not an issue with an SSID
-                *  or BSSID filter applied to the scan results in the firmware.
-                */
-               if ((i && ssid_filter) ||
-                   !is_zero_ether_addr(scan_cfg_out->specific_bssid))
-                       *filtered_scan = true;
-
-               if (user_scan_in->scan_chan_gap) {
-                       mwifiex_dbg(adapter, INFO,
-                                   "info: scan: channel gap = %d\n",
-                                   user_scan_in->scan_chan_gap);
-                       *max_chan_per_scan =
-                                       MWIFIEX_MAX_CHANNELS_PER_SPECIFIC_SCAN;
-
-                       chan_gap_tlv = (void *)tlv_pos;
-                       chan_gap_tlv->header.type =
-                                        cpu_to_le16(TLV_TYPE_SCAN_CHANNEL_GAP);
-                       chan_gap_tlv->header.len =
-                                   cpu_to_le16(sizeof(chan_gap_tlv->chan_gap));
-                       chan_gap_tlv->chan_gap =
-                                    cpu_to_le16((user_scan_in->scan_chan_gap));
-                       tlv_pos +=
-                                 sizeof(struct mwifiex_ie_types_scan_chan_gap);
-               }
-       } else {
-               scan_cfg_out->bss_mode = (u8) adapter->scan_mode;
-               num_probes = adapter->scan_probes;
-       }
-
-       /*
-        *  If a specific BSSID or SSID is used, the number of channels in the
-        *  scan command will be increased to the absolute maximum.
-        */
-       if (*filtered_scan)
-               *max_chan_per_scan = MWIFIEX_MAX_CHANNELS_PER_SPECIFIC_SCAN;
-       else
-               *max_chan_per_scan = MWIFIEX_DEF_CHANNELS_PER_SCAN_CMD;
-
-       if (adapter->ext_scan) {
-               bss_mode = (struct mwifiex_ie_types_bss_mode *)tlv_pos;
-               bss_mode->header.type = cpu_to_le16(TLV_TYPE_BSS_MODE);
-               bss_mode->header.len = cpu_to_le16(sizeof(bss_mode->bss_mode));
-               bss_mode->bss_mode = scan_cfg_out->bss_mode;
-               tlv_pos += sizeof(bss_mode->header) +
-                          le16_to_cpu(bss_mode->header.len);
-       }
-
-       /* If the input config or adapter has the number of Probes set,
-          add tlv */
-       if (num_probes) {
-
-               mwifiex_dbg(adapter, INFO,
-                           "info: scan: num_probes = %d\n",
-                           num_probes);
-
-               num_probes_tlv = (struct mwifiex_ie_types_num_probes *) tlv_pos;
-               num_probes_tlv->header.type = cpu_to_le16(TLV_TYPE_NUMPROBES);
-               num_probes_tlv->header.len =
-                       cpu_to_le16(sizeof(num_probes_tlv->num_probes));
-               num_probes_tlv->num_probes = cpu_to_le16((u16) num_probes);
-
-               tlv_pos += sizeof(num_probes_tlv->header) +
-                       le16_to_cpu(num_probes_tlv->header.len);
-
-       }
-
-       if (ISSUPP_11NENABLED(priv->adapter->fw_cap_info) &&
-           (priv->adapter->config_bands & BAND_GN ||
-            priv->adapter->config_bands & BAND_AN)) {
-               ht_cap = (struct mwifiex_ie_types_htcap *) tlv_pos;
-               memset(ht_cap, 0, sizeof(struct mwifiex_ie_types_htcap));
-               ht_cap->header.type = cpu_to_le16(WLAN_EID_HT_CAPABILITY);
-               ht_cap->header.len =
-                               cpu_to_le16(sizeof(struct ieee80211_ht_cap));
-               radio_type =
-                       mwifiex_band_to_radio_type(priv->adapter->config_bands);
-               mwifiex_fill_cap_info(priv, radio_type, &ht_cap->ht_cap);
-               tlv_pos += sizeof(struct mwifiex_ie_types_htcap);
-       }
-
-       /* Append vendor specific IE TLV */
-       mwifiex_cmd_append_vsie_tlv(priv, MWIFIEX_VSIE_MASK_SCAN, &tlv_pos);
-
-       /*
-        * Set the output for the channel TLV to the address in the tlv buffer
-        *   past any TLVs that were added in this function (SSID, num_probes).
-        *   Channel TLVs will be added past this for each scan command,
-        *   preserving the TLVs that were previously added.
-        */
-       *chan_list_out =
-               (struct mwifiex_ie_types_chan_list_param_set *) tlv_pos;
-
-       if (user_scan_in && user_scan_in->chan_list[0].chan_number) {
-
-               mwifiex_dbg(adapter, INFO,
-                           "info: Scan: Using supplied channel list\n");
-
-               for (chan_idx = 0;
-                    chan_idx < MWIFIEX_USER_SCAN_CHAN_MAX &&
-                    user_scan_in->chan_list[chan_idx].chan_number;
-                    chan_idx++) {
-
-                       channel = user_scan_in->chan_list[chan_idx].chan_number;
-                       (scan_chan_list + chan_idx)->chan_number = channel;
-
-                       radio_type =
-                               user_scan_in->chan_list[chan_idx].radio_type;
-                       (scan_chan_list + chan_idx)->radio_type = radio_type;
-
-                       scan_type = user_scan_in->chan_list[chan_idx].scan_type;
-
-                       if (scan_type == MWIFIEX_SCAN_TYPE_PASSIVE)
-                               (scan_chan_list +
-                                chan_idx)->chan_scan_mode_bitmap
-                                       |= (MWIFIEX_PASSIVE_SCAN |
-                                           MWIFIEX_HIDDEN_SSID_REPORT);
-                       else
-                               (scan_chan_list +
-                                chan_idx)->chan_scan_mode_bitmap
-                                       &= ~MWIFIEX_PASSIVE_SCAN;
-
-                       if (*filtered_scan)
-                               (scan_chan_list +
-                                chan_idx)->chan_scan_mode_bitmap
-                                       |= MWIFIEX_DISABLE_CHAN_FILT;
-
-                       if (user_scan_in->chan_list[chan_idx].scan_time) {
-                               scan_dur = (u16) user_scan_in->
-                                       chan_list[chan_idx].scan_time;
-                       } else {
-                               if (scan_type == MWIFIEX_SCAN_TYPE_PASSIVE)
-                                       scan_dur = adapter->passive_scan_time;
-                               else if (*filtered_scan)
-                                       scan_dur = adapter->specific_scan_time;
-                               else
-                                       scan_dur = adapter->active_scan_time;
-                       }
-
-                       (scan_chan_list + chan_idx)->min_scan_time =
-                               cpu_to_le16(scan_dur);
-                       (scan_chan_list + chan_idx)->max_scan_time =
-                               cpu_to_le16(scan_dur);
-               }
-
-               /* Check if we are only scanning the current channel */
-               if ((chan_idx == 1) &&
-                   (user_scan_in->chan_list[0].chan_number ==
-                    priv->curr_bss_params.bss_descriptor.channel)) {
-                       *scan_current_only = true;
-                       mwifiex_dbg(adapter, INFO,
-                                   "info: Scan: Scanning current channel only\n");
-               }
-               chan_num = chan_idx;
-       } else {
-               mwifiex_dbg(adapter, INFO,
-                           "info: Scan: Creating full region channel list\n");
-               chan_num = mwifiex_scan_create_channel_list(priv, user_scan_in,
-                                                           scan_chan_list,
-                                                           *filtered_scan);
-       }
-
-}
-
-/*
- * This function inspects the scan response buffer for pointers to
- * expected TLVs.
- *
- * TLVs can be included at the end of the scan response BSS information.
- *
- * Data in the buffer is parsed pointers to TLVs that can potentially
- * be passed back in the response.
- */
-static void
-mwifiex_ret_802_11_scan_get_tlv_ptrs(struct mwifiex_adapter *adapter,
-                                    struct mwifiex_ie_types_data *tlv,
-                                    u32 tlv_buf_size, u32 req_tlv_type,
-                                    struct mwifiex_ie_types_data **tlv_data)
-{
-       struct mwifiex_ie_types_data *current_tlv;
-       u32 tlv_buf_left;
-       u32 tlv_type;
-       u32 tlv_len;
-
-       current_tlv = tlv;
-       tlv_buf_left = tlv_buf_size;
-       *tlv_data = NULL;
-
-       mwifiex_dbg(adapter, INFO,
-                   "info: SCAN_RESP: tlv_buf_size = %d\n",
-                   tlv_buf_size);
-
-       while (tlv_buf_left >= sizeof(struct mwifiex_ie_types_header)) {
-
-               tlv_type = le16_to_cpu(current_tlv->header.type);
-               tlv_len = le16_to_cpu(current_tlv->header.len);
-
-               if (sizeof(tlv->header) + tlv_len > tlv_buf_left) {
-                       mwifiex_dbg(adapter, ERROR,
-                                   "SCAN_RESP: TLV buffer corrupt\n");
-                       break;
-               }
-
-               if (req_tlv_type == tlv_type) {
-                       switch (tlv_type) {
-                       case TLV_TYPE_TSFTIMESTAMP:
-                               mwifiex_dbg(adapter, INFO,
-                                           "info: SCAN_RESP: TSF\t"
-                                           "timestamp TLV, len = %d\n",
-                                           tlv_len);
-                               *tlv_data = current_tlv;
-                               break;
-                       case TLV_TYPE_CHANNELBANDLIST:
-                               mwifiex_dbg(adapter, INFO,
-                                           "info: SCAN_RESP: channel\t"
-                                           "band list TLV, len = %d\n",
-                                           tlv_len);
-                               *tlv_data = current_tlv;
-                               break;
-                       default:
-                               mwifiex_dbg(adapter, ERROR,
-                                           "SCAN_RESP: unhandled TLV = %d\n",
-                                           tlv_type);
-                               /* Give up, this seems corrupted */
-                               return;
-                       }
-               }
-
-               if (*tlv_data)
-                       break;
-
-
-               tlv_buf_left -= (sizeof(tlv->header) + tlv_len);
-               current_tlv =
-                       (struct mwifiex_ie_types_data *) (current_tlv->data +
-                                                         tlv_len);
-
-       }                       /* while */
-}
-
-/*
- * This function parses provided beacon buffer and updates
- * respective fields in bss descriptor structure.
- */
-int mwifiex_update_bss_desc_with_ie(struct mwifiex_adapter *adapter,
-                                   struct mwifiex_bssdescriptor *bss_entry)
-{
-       int ret = 0;
-       u8 element_id;
-       struct ieee_types_fh_param_set *fh_param_set;
-       struct ieee_types_ds_param_set *ds_param_set;
-       struct ieee_types_cf_param_set *cf_param_set;
-       struct ieee_types_ibss_param_set *ibss_param_set;
-       u8 *current_ptr;
-       u8 *rate;
-       u8 element_len;
-       u16 total_ie_len;
-       u8 bytes_to_copy;
-       u8 rate_size;
-       u8 found_data_rate_ie;
-       u32 bytes_left;
-       struct ieee_types_vendor_specific *vendor_ie;
-       const u8 wpa_oui[4] = { 0x00, 0x50, 0xf2, 0x01 };
-       const u8 wmm_oui[4] = { 0x00, 0x50, 0xf2, 0x02 };
-
-       found_data_rate_ie = false;
-       rate_size = 0;
-       current_ptr = bss_entry->beacon_buf;
-       bytes_left = bss_entry->beacon_buf_size;
-
-       /* Process variable IE */
-       while (bytes_left >= 2) {
-               element_id = *current_ptr;
-               element_len = *(current_ptr + 1);
-               total_ie_len = element_len + sizeof(struct ieee_types_header);
-
-               if (bytes_left < total_ie_len) {
-                       mwifiex_dbg(adapter, ERROR,
-                                   "err: InterpretIE: in processing\t"
-                                   "IE, bytes left < IE length\n");
-                       return -1;
-               }
-               switch (element_id) {
-               case WLAN_EID_SSID:
-                       bss_entry->ssid.ssid_len = element_len;
-                       memcpy(bss_entry->ssid.ssid, (current_ptr + 2),
-                              element_len);
-                       mwifiex_dbg(adapter, INFO,
-                                   "info: InterpretIE: ssid: %-32s\n",
-                                   bss_entry->ssid.ssid);
-                       break;
-
-               case WLAN_EID_SUPP_RATES:
-                       memcpy(bss_entry->data_rates, current_ptr + 2,
-                              element_len);
-                       memcpy(bss_entry->supported_rates, current_ptr + 2,
-                              element_len);
-                       rate_size = element_len;
-                       found_data_rate_ie = true;
-                       break;
-
-               case WLAN_EID_FH_PARAMS:
-                       fh_param_set =
-                               (struct ieee_types_fh_param_set *) current_ptr;
-                       memcpy(&bss_entry->phy_param_set.fh_param_set,
-                              fh_param_set,
-                              sizeof(struct ieee_types_fh_param_set));
-                       break;
-
-               case WLAN_EID_DS_PARAMS:
-                       ds_param_set =
-                               (struct ieee_types_ds_param_set *) current_ptr;
-
-                       bss_entry->channel = ds_param_set->current_chan;
-
-                       memcpy(&bss_entry->phy_param_set.ds_param_set,
-                              ds_param_set,
-                              sizeof(struct ieee_types_ds_param_set));
-                       break;
-
-               case WLAN_EID_CF_PARAMS:
-                       cf_param_set =
-                               (struct ieee_types_cf_param_set *) current_ptr;
-                       memcpy(&bss_entry->ss_param_set.cf_param_set,
-                              cf_param_set,
-                              sizeof(struct ieee_types_cf_param_set));
-                       break;
-
-               case WLAN_EID_IBSS_PARAMS:
-                       ibss_param_set =
-                               (struct ieee_types_ibss_param_set *)
-                               current_ptr;
-                       memcpy(&bss_entry->ss_param_set.ibss_param_set,
-                              ibss_param_set,
-                              sizeof(struct ieee_types_ibss_param_set));
-                       break;
-
-               case WLAN_EID_ERP_INFO:
-                       bss_entry->erp_flags = *(current_ptr + 2);
-                       break;
-
-               case WLAN_EID_PWR_CONSTRAINT:
-                       bss_entry->local_constraint = *(current_ptr + 2);
-                       bss_entry->sensed_11h = true;
-                       break;
-
-               case WLAN_EID_CHANNEL_SWITCH:
-                       bss_entry->chan_sw_ie_present = true;
-               case WLAN_EID_PWR_CAPABILITY:
-               case WLAN_EID_TPC_REPORT:
-               case WLAN_EID_QUIET:
-                       bss_entry->sensed_11h = true;
-                   break;
-
-               case WLAN_EID_EXT_SUPP_RATES:
-                       /*
-                        * Only process extended supported rate
-                        * if data rate is already found.
-                        * Data rate IE should come before
-                        * extended supported rate IE
-                        */
-                       if (found_data_rate_ie) {
-                               if ((element_len + rate_size) >
-                                   MWIFIEX_SUPPORTED_RATES)
-                                       bytes_to_copy =
-                                               (MWIFIEX_SUPPORTED_RATES -
-                                                rate_size);
-                               else
-                                       bytes_to_copy = element_len;
-
-                               rate = (u8 *) bss_entry->data_rates;
-                               rate += rate_size;
-                               memcpy(rate, current_ptr + 2, bytes_to_copy);
-
-                               rate = (u8 *) bss_entry->supported_rates;
-                               rate += rate_size;
-                               memcpy(rate, current_ptr + 2, bytes_to_copy);
-                       }
-                       break;
-
-               case WLAN_EID_VENDOR_SPECIFIC:
-                       vendor_ie = (struct ieee_types_vendor_specific *)
-                                       current_ptr;
-
-                       if (!memcmp
-                           (vendor_ie->vend_hdr.oui, wpa_oui,
-                            sizeof(wpa_oui))) {
-                               bss_entry->bcn_wpa_ie =
-                                       (struct ieee_types_vendor_specific *)
-                                       current_ptr;
-                               bss_entry->wpa_offset = (u16)
-                                       (current_ptr - bss_entry->beacon_buf);
-                       } else if (!memcmp(vendor_ie->vend_hdr.oui, wmm_oui,
-                                   sizeof(wmm_oui))) {
-                               if (total_ie_len ==
-                                   sizeof(struct ieee_types_wmm_parameter) ||
-                                   total_ie_len ==
-                                   sizeof(struct ieee_types_wmm_info))
-                                       /*
-                                        * Only accept and copy the WMM IE if
-                                        * it matches the size expected for the
-                                        * WMM Info IE or the WMM Parameter IE.
-                                        */
-                                       memcpy((u8 *) &bss_entry->wmm_ie,
-                                              current_ptr, total_ie_len);
-                       }
-                       break;
-               case WLAN_EID_RSN:
-                       bss_entry->bcn_rsn_ie =
-                               (struct ieee_types_generic *) current_ptr;
-                       bss_entry->rsn_offset = (u16) (current_ptr -
-                                                       bss_entry->beacon_buf);
-                       break;
-               case WLAN_EID_BSS_AC_ACCESS_DELAY:
-                       bss_entry->bcn_wapi_ie =
-                               (struct ieee_types_generic *) current_ptr;
-                       bss_entry->wapi_offset = (u16) (current_ptr -
-                                                       bss_entry->beacon_buf);
-                       break;
-               case WLAN_EID_HT_CAPABILITY:
-                       bss_entry->bcn_ht_cap = (struct ieee80211_ht_cap *)
-                                       (current_ptr +
-                                       sizeof(struct ieee_types_header));
-                       bss_entry->ht_cap_offset = (u16) (current_ptr +
-                                       sizeof(struct ieee_types_header) -
-                                       bss_entry->beacon_buf);
-                       break;
-               case WLAN_EID_HT_OPERATION:
-                       bss_entry->bcn_ht_oper =
-                               (struct ieee80211_ht_operation *)(current_ptr +
-                                       sizeof(struct ieee_types_header));
-                       bss_entry->ht_info_offset = (u16) (current_ptr +
-                                       sizeof(struct ieee_types_header) -
-                                       bss_entry->beacon_buf);
-                       break;
-               case WLAN_EID_VHT_CAPABILITY:
-                       bss_entry->disable_11ac = false;
-                       bss_entry->bcn_vht_cap =
-                               (void *)(current_ptr +
-                                        sizeof(struct ieee_types_header));
-                       bss_entry->vht_cap_offset =
-                                       (u16)((u8 *)bss_entry->bcn_vht_cap -
-                                             bss_entry->beacon_buf);
-                       break;
-               case WLAN_EID_VHT_OPERATION:
-                       bss_entry->bcn_vht_oper =
-                               (void *)(current_ptr +
-                                        sizeof(struct ieee_types_header));
-                       bss_entry->vht_info_offset =
-                                       (u16)((u8 *)bss_entry->bcn_vht_oper -
-                                             bss_entry->beacon_buf);
-                       break;
-               case WLAN_EID_BSS_COEX_2040:
-                       bss_entry->bcn_bss_co_2040 = current_ptr;
-                       bss_entry->bss_co_2040_offset =
-                               (u16) (current_ptr - bss_entry->beacon_buf);
-                       break;
-               case WLAN_EID_EXT_CAPABILITY:
-                       bss_entry->bcn_ext_cap = current_ptr;
-                       bss_entry->ext_cap_offset =
-                               (u16) (current_ptr - bss_entry->beacon_buf);
-                       break;
-               case WLAN_EID_OPMODE_NOTIF:
-                       bss_entry->oper_mode = (void *)current_ptr;
-                       bss_entry->oper_mode_offset =
-                                       (u16)((u8 *)bss_entry->oper_mode -
-                                             bss_entry->beacon_buf);
-                       break;
-               default:
-                       break;
-               }
-
-               current_ptr += element_len + 2;
-
-               /* Need to account for IE ID and IE Len */
-               bytes_left -= (element_len + 2);
-
-       }       /* while (bytes_left > 2) */
-       return ret;
-}
-
-/*
- * This function converts radio type scan parameter to a band configuration
- * to be used in join command.
- */
-static u8
-mwifiex_radio_type_to_band(u8 radio_type)
-{
-       switch (radio_type) {
-       case HostCmd_SCAN_RADIO_TYPE_A:
-               return BAND_A;
-       case HostCmd_SCAN_RADIO_TYPE_BG:
-       default:
-               return BAND_G;
-       }
-}
-
-/*
- * This is an internal function used to start a scan based on an input
- * configuration.
- *
- * This uses the input user scan configuration information when provided in
- * order to send the appropriate scan commands to firmware to populate or
- * update the internal driver scan table.
- */
-int mwifiex_scan_networks(struct mwifiex_private *priv,
-                         const struct mwifiex_user_scan_cfg *user_scan_in)
-{
-       int ret;
-       struct mwifiex_adapter *adapter = priv->adapter;
-       struct cmd_ctrl_node *cmd_node;
-       union mwifiex_scan_cmd_config_tlv *scan_cfg_out;
-       struct mwifiex_ie_types_chan_list_param_set *chan_list_out;
-       struct mwifiex_chan_scan_param_set *scan_chan_list;
-       u8 filtered_scan;
-       u8 scan_current_chan_only;
-       u8 max_chan_per_scan;
-       unsigned long flags;
-
-       if (adapter->scan_processing) {
-               mwifiex_dbg(adapter, WARN,
-                           "cmd: Scan already in process...\n");
-               return -EBUSY;
-       }
-
-       if (priv->scan_block) {
-               mwifiex_dbg(adapter, WARN,
-                           "cmd: Scan is blocked during association...\n");
-               return -EBUSY;
-       }
-
-       if (adapter->surprise_removed || adapter->is_cmd_timedout) {
-               mwifiex_dbg(adapter, ERROR,
-                           "Ignore scan. Card removed or firmware in bad state\n");
-               return -EFAULT;
-       }
-
-       spin_lock_irqsave(&adapter->mwifiex_cmd_lock, flags);
-       adapter->scan_processing = true;
-       spin_unlock_irqrestore(&adapter->mwifiex_cmd_lock, flags);
-
-       scan_cfg_out = kzalloc(sizeof(union mwifiex_scan_cmd_config_tlv),
-                              GFP_KERNEL);
-       if (!scan_cfg_out) {
-               ret = -ENOMEM;
-               goto done;
-       }
-
-       scan_chan_list = kcalloc(MWIFIEX_USER_SCAN_CHAN_MAX,
-                                sizeof(struct mwifiex_chan_scan_param_set),
-                                GFP_KERNEL);
-       if (!scan_chan_list) {
-               kfree(scan_cfg_out);
-               ret = -ENOMEM;
-               goto done;
-       }
-
-       mwifiex_config_scan(priv, user_scan_in, &scan_cfg_out->config,
-                           &chan_list_out, scan_chan_list, &max_chan_per_scan,
-                           &filtered_scan, &scan_current_chan_only);
-
-       ret = mwifiex_scan_channel_list(priv, max_chan_per_scan, filtered_scan,
-                                       &scan_cfg_out->config, chan_list_out,
-                                       scan_chan_list);
-
-       /* Get scan command from scan_pending_q and put to cmd_pending_q */
-       if (!ret) {
-               spin_lock_irqsave(&adapter->scan_pending_q_lock, flags);
-               if (!list_empty(&adapter->scan_pending_q)) {
-                       cmd_node = list_first_entry(&adapter->scan_pending_q,
-                                                   struct cmd_ctrl_node, list);
-                       list_del(&cmd_node->list);
-                       spin_unlock_irqrestore(&adapter->scan_pending_q_lock,
-                                              flags);
-                       mwifiex_insert_cmd_to_pending_q(adapter, cmd_node,
-                                                       true);
-                       queue_work(adapter->workqueue, &adapter->main_work);
-
-                       /* Perform internal scan synchronously */
-                       if (!priv->scan_request) {
-                               mwifiex_dbg(adapter, INFO,
-                                           "wait internal scan\n");
-                               mwifiex_wait_queue_complete(adapter, cmd_node);
-                       }
-               } else {
-                       spin_unlock_irqrestore(&adapter->scan_pending_q_lock,
-                                              flags);
-               }
-       }
-
-       kfree(scan_cfg_out);
-       kfree(scan_chan_list);
-done:
-       if (ret) {
-               spin_lock_irqsave(&adapter->mwifiex_cmd_lock, flags);
-               adapter->scan_processing = false;
-               spin_unlock_irqrestore(&adapter->mwifiex_cmd_lock, flags);
-       }
-       return ret;
-}
-
-/*
- * This function prepares a scan command to be sent to the firmware.
- *
- * This uses the scan command configuration sent to the command processing
- * module in command preparation stage to configure a scan command structure
- * to send to firmware.
- *
- * The fixed fields specifying the BSS type and BSSID filters as well as a
- * variable number/length of TLVs are sent in the command to firmware.
- *
- * Preparation also includes -
- *      - Setting command ID, and proper size
- *      - Ensuring correct endian-ness
- */
-int mwifiex_cmd_802_11_scan(struct host_cmd_ds_command *cmd,
-                           struct mwifiex_scan_cmd_config *scan_cfg)
-{
-       struct host_cmd_ds_802_11_scan *scan_cmd = &cmd->params.scan;
-
-       /* Set fixed field variables in scan command */
-       scan_cmd->bss_mode = scan_cfg->bss_mode;
-       memcpy(scan_cmd->bssid, scan_cfg->specific_bssid,
-              sizeof(scan_cmd->bssid));
-       memcpy(scan_cmd->tlv_buffer, scan_cfg->tlv_buf, scan_cfg->tlv_buf_len);
-
-       cmd->command = cpu_to_le16(HostCmd_CMD_802_11_SCAN);
-
-       /* Size is equal to the sizeof(fixed portions) + the TLV len + header */
-       cmd->size = cpu_to_le16((u16) (sizeof(scan_cmd->bss_mode)
-                                         + sizeof(scan_cmd->bssid)
-                                         + scan_cfg->tlv_buf_len + S_DS_GEN));
-
-       return 0;
-}
-
-/*
- * This function checks compatibility of requested network with current
- * driver settings.
- */
-int mwifiex_check_network_compatibility(struct mwifiex_private *priv,
-                                       struct mwifiex_bssdescriptor *bss_desc)
-{
-       int ret = -1;
-
-       if (!bss_desc)
-               return -1;
-
-       if ((mwifiex_get_cfp(priv, (u8) bss_desc->bss_band,
-                            (u16) bss_desc->channel, 0))) {
-               switch (priv->bss_mode) {
-               case NL80211_IFTYPE_STATION:
-               case NL80211_IFTYPE_ADHOC:
-                       ret = mwifiex_is_network_compatible(priv, bss_desc,
-                                                           priv->bss_mode);
-                       if (ret)
-                               mwifiex_dbg(priv->adapter, ERROR,
-                                           "Incompatible network settings\n");
-                       break;
-               default:
-                       ret = 0;
-               }
-       }
-
-       return ret;
-}
-
-/* This function checks if SSID string contains all zeroes or length is zero */
-static bool mwifiex_is_hidden_ssid(struct cfg80211_ssid *ssid)
-{
-       int idx;
-
-       for (idx = 0; idx < ssid->ssid_len; idx++) {
-               if (ssid->ssid[idx])
-                       return false;
-       }
-
-       return true;
-}
-
-/* This function checks if any hidden SSID found in passive scan channels
- * and save those channels for specific SSID active scan
- */
-static int mwifiex_save_hidden_ssid_channels(struct mwifiex_private *priv,
-                                            struct cfg80211_bss *bss)
-{
-       struct mwifiex_bssdescriptor *bss_desc;
-       int ret;
-       int chid;
-
-       /* Allocate and fill new bss descriptor */
-       bss_desc = kzalloc(sizeof(*bss_desc), GFP_KERNEL);
-       if (!bss_desc)
-               return -ENOMEM;
-
-       ret = mwifiex_fill_new_bss_desc(priv, bss, bss_desc);
-       if (ret)
-               goto done;
-
-       if (mwifiex_is_hidden_ssid(&bss_desc->ssid)) {
-               mwifiex_dbg(priv->adapter, INFO, "found hidden SSID\n");
-               for (chid = 0 ; chid < MWIFIEX_USER_SCAN_CHAN_MAX; chid++) {
-                       if (priv->hidden_chan[chid].chan_number ==
-                           bss->channel->hw_value)
-                               break;
-
-                       if (!priv->hidden_chan[chid].chan_number) {
-                               priv->hidden_chan[chid].chan_number =
-                                       bss->channel->hw_value;
-                               priv->hidden_chan[chid].radio_type =
-                                       bss->channel->band;
-                               priv->hidden_chan[chid].scan_type =
-                                       MWIFIEX_SCAN_TYPE_ACTIVE;
-                               break;
-                       }
-               }
-       }
-
-done:
-       kfree(bss_desc);
-       return 0;
-}
-
-static int mwifiex_update_curr_bss_params(struct mwifiex_private *priv,
-                                         struct cfg80211_bss *bss)
-{
-       struct mwifiex_bssdescriptor *bss_desc;
-       int ret;
-       unsigned long flags;
-
-       /* Allocate and fill new bss descriptor */
-       bss_desc = kzalloc(sizeof(struct mwifiex_bssdescriptor), GFP_KERNEL);
-       if (!bss_desc)
-               return -ENOMEM;
-
-       ret = mwifiex_fill_new_bss_desc(priv, bss, bss_desc);
-       if (ret)
-               goto done;
-
-       ret = mwifiex_check_network_compatibility(priv, bss_desc);
-       if (ret)
-               goto done;
-
-       spin_lock_irqsave(&priv->curr_bcn_buf_lock, flags);
-       /* Make a copy of current BSSID descriptor */
-       memcpy(&priv->curr_bss_params.bss_descriptor, bss_desc,
-              sizeof(priv->curr_bss_params.bss_descriptor));
-
-       /* The contents of beacon_ie will be copied to its own buffer
-        * in mwifiex_save_curr_bcn()
-        */
-       mwifiex_save_curr_bcn(priv);
-       spin_unlock_irqrestore(&priv->curr_bcn_buf_lock, flags);
-
-done:
-       /* beacon_ie buffer was allocated in function
-        * mwifiex_fill_new_bss_desc(). Free it now.
-        */
-       kfree(bss_desc->beacon_buf);
-       kfree(bss_desc);
-       return 0;
-}
-
-static int
-mwifiex_parse_single_response_buf(struct mwifiex_private *priv, u8 **bss_info,
-                                 u32 *bytes_left, u64 fw_tsf, u8 *radio_type,
-                                 bool ext_scan, s32 rssi_val)
-{
-       struct mwifiex_adapter *adapter = priv->adapter;
-       struct mwifiex_chan_freq_power *cfp;
-       struct cfg80211_bss *bss;
-       u8 bssid[ETH_ALEN];
-       s32 rssi;
-       const u8 *ie_buf;
-       size_t ie_len;
-       u16 channel = 0;
-       u16 beacon_size = 0;
-       u32 curr_bcn_bytes;
-       u32 freq;
-       u16 beacon_period;
-       u16 cap_info_bitmap;
-       u8 *current_ptr;
-       u64 timestamp;
-       struct mwifiex_fixed_bcn_param *bcn_param;
-       struct mwifiex_bss_priv *bss_priv;
-
-       if (*bytes_left >= sizeof(beacon_size)) {
-               /* Extract & convert beacon size from command buffer */
-               beacon_size = le16_to_cpu(*(__le16 *)(*bss_info));
-               *bytes_left -= sizeof(beacon_size);
-               *bss_info += sizeof(beacon_size);
-       }
-
-       if (!beacon_size || beacon_size > *bytes_left) {
-               *bss_info += *bytes_left;
-               *bytes_left = 0;
-               return -EFAULT;
-       }
-
-       /* Initialize the current working beacon pointer for this BSS
-        * iteration
-        */
-       current_ptr = *bss_info;
-
-       /* Advance the return beacon pointer past the current beacon */
-       *bss_info += beacon_size;
-       *bytes_left -= beacon_size;
-
-       curr_bcn_bytes = beacon_size;
-
-       /* First 5 fields are bssid, RSSI(for legacy scan only),
-        * time stamp, beacon interval, and capability information
-        */
-       if (curr_bcn_bytes < ETH_ALEN + sizeof(u8) +
-           sizeof(struct mwifiex_fixed_bcn_param)) {
-               mwifiex_dbg(adapter, ERROR,
-                           "InterpretIE: not enough bytes left\n");
-               return -EFAULT;
-       }
-
-       memcpy(bssid, current_ptr, ETH_ALEN);
-       current_ptr += ETH_ALEN;
-       curr_bcn_bytes -= ETH_ALEN;
-
-       if (!ext_scan) {
-               rssi = (s32) *current_ptr;
-               rssi = (-rssi) * 100;           /* Convert dBm to mBm */
-               current_ptr += sizeof(u8);
-               curr_bcn_bytes -= sizeof(u8);
-               mwifiex_dbg(adapter, INFO,
-                           "info: InterpretIE: RSSI=%d\n", rssi);
-       } else {
-               rssi = rssi_val;
-       }
-
-       bcn_param = (struct mwifiex_fixed_bcn_param *)current_ptr;
-       current_ptr += sizeof(*bcn_param);
-       curr_bcn_bytes -= sizeof(*bcn_param);
-
-       timestamp = le64_to_cpu(bcn_param->timestamp);
-       beacon_period = le16_to_cpu(bcn_param->beacon_period);
-
-       cap_info_bitmap = le16_to_cpu(bcn_param->cap_info_bitmap);
-       mwifiex_dbg(adapter, INFO,
-                   "info: InterpretIE: capabilities=0x%X\n",
-                   cap_info_bitmap);
-
-       /* Rest of the current buffer are IE's */
-       ie_buf = current_ptr;
-       ie_len = curr_bcn_bytes;
-       mwifiex_dbg(adapter, INFO,
-                   "info: InterpretIE: IELength for this AP = %d\n",
-                   curr_bcn_bytes);
-
-       while (curr_bcn_bytes >= sizeof(struct ieee_types_header)) {
-               u8 element_id, element_len;
-
-               element_id = *current_ptr;
-               element_len = *(current_ptr + 1);
-               if (curr_bcn_bytes < element_len +
-                               sizeof(struct ieee_types_header)) {
-                       mwifiex_dbg(adapter, ERROR,
-                                   "%s: bytes left < IE length\n", __func__);
-                       return -EFAULT;
-               }
-               if (element_id == WLAN_EID_DS_PARAMS) {
-                       channel = *(current_ptr +
-                                   sizeof(struct ieee_types_header));
-                       break;
-               }
-
-               current_ptr += element_len + sizeof(struct ieee_types_header);
-               curr_bcn_bytes -= element_len +
-                                       sizeof(struct ieee_types_header);
-       }
-
-       if (channel) {
-               struct ieee80211_channel *chan;
-               u8 band;
-
-               /* Skip entry if on csa closed channel */
-               if (channel == priv->csa_chan) {
-                       mwifiex_dbg(adapter, WARN,
-                                   "Dropping entry on csa closed channel\n");
-                       return 0;
-               }
-
-               band = BAND_G;
-               if (radio_type)
-                       band = mwifiex_radio_type_to_band(*radio_type &
-                                                         (BIT(0) | BIT(1)));
-
-               cfp = mwifiex_get_cfp(priv, band, channel, 0);
-
-               freq = cfp ? cfp->freq : 0;
-
-               chan = ieee80211_get_channel(priv->wdev.wiphy, freq);
-
-               if (chan && !(chan->flags & IEEE80211_CHAN_DISABLED)) {
-                       bss = cfg80211_inform_bss(priv->wdev.wiphy,
-                                           chan, CFG80211_BSS_FTYPE_UNKNOWN,
-                                           bssid, timestamp,
-                                           cap_info_bitmap, beacon_period,
-                                           ie_buf, ie_len, rssi, GFP_KERNEL);
-                       if (bss) {
-                               bss_priv = (struct mwifiex_bss_priv *)bss->priv;
-                               bss_priv->band = band;
-                               bss_priv->fw_tsf = fw_tsf;
-                               if (priv->media_connected &&
-                                   !memcmp(bssid, priv->curr_bss_params.
-                                           bss_descriptor.mac_address,
-                                           ETH_ALEN))
-                                       mwifiex_update_curr_bss_params(priv,
-                                                                      bss);
-                               cfg80211_put_bss(priv->wdev.wiphy, bss);
-                       }
-
-                       if ((chan->flags & IEEE80211_CHAN_RADAR) ||
-                           (chan->flags & IEEE80211_CHAN_NO_IR)) {
-                               mwifiex_dbg(adapter, INFO,
-                                           "radar or passive channel %d\n",
-                                           channel);
-                               mwifiex_save_hidden_ssid_channels(priv, bss);
-                       }
-               }
-       } else {
-               mwifiex_dbg(adapter, WARN, "missing BSS channel IE\n");
-       }
-
-       return 0;
-}
-
-static void mwifiex_complete_scan(struct mwifiex_private *priv)
-{
-       struct mwifiex_adapter *adapter = priv->adapter;
-
-       adapter->survey_idx = 0;
-       if (adapter->curr_cmd->wait_q_enabled) {
-               adapter->cmd_wait_q.status = 0;
-               if (!priv->scan_request) {
-                       mwifiex_dbg(adapter, INFO,
-                                   "complete internal scan\n");
-                       mwifiex_complete_cmd(adapter, adapter->curr_cmd);
-               }
-       }
-}
-
-/* This function checks if any hidden SSID found in passive scan channels
- * and do specific SSID active scan for those channels
- */
-static int
-mwifiex_active_scan_req_for_passive_chan(struct mwifiex_private *priv)
-{
-       int ret;
-       struct mwifiex_adapter *adapter = priv->adapter;
-       u8 id = 0;
-       struct mwifiex_user_scan_cfg  *user_scan_cfg;
-
-       if (adapter->active_scan_triggered || !priv->scan_request) {
-               adapter->active_scan_triggered = false;
-               return 0;
-       }
-
-       if (!priv->hidden_chan[0].chan_number) {
-               mwifiex_dbg(adapter, INFO, "No BSS with hidden SSID found on DFS channels\n");
-               return 0;
-       }
-       user_scan_cfg = kzalloc(sizeof(*user_scan_cfg), GFP_KERNEL);
-
-       if (!user_scan_cfg)
-               return -ENOMEM;
-
-       memset(user_scan_cfg, 0, sizeof(*user_scan_cfg));
-
-       for (id = 0; id < MWIFIEX_USER_SCAN_CHAN_MAX; id++) {
-               if (!priv->hidden_chan[id].chan_number)
-                       break;
-               memcpy(&user_scan_cfg->chan_list[id],
-                      &priv->hidden_chan[id],
-                      sizeof(struct mwifiex_user_scan_chan));
-       }
-
-       adapter->active_scan_triggered = true;
-       user_scan_cfg->num_ssids = priv->scan_request->n_ssids;
-       user_scan_cfg->ssid_list = priv->scan_request->ssids;
-
-       ret = mwifiex_scan_networks(priv, user_scan_cfg);
-       kfree(user_scan_cfg);
-
-       memset(&priv->hidden_chan, 0, sizeof(priv->hidden_chan));
-
-       if (ret) {
-               dev_err(priv->adapter->dev, "scan failed: %d\n", ret);
-               return ret;
-       }
-
-       return 0;
-}
-static void mwifiex_check_next_scan_command(struct mwifiex_private *priv)
-{
-       struct mwifiex_adapter *adapter = priv->adapter;
-       struct cmd_ctrl_node *cmd_node, *tmp_node;
-       unsigned long flags;
-
-       spin_lock_irqsave(&adapter->scan_pending_q_lock, flags);
-       if (list_empty(&adapter->scan_pending_q)) {
-               spin_unlock_irqrestore(&adapter->scan_pending_q_lock, flags);
-               spin_lock_irqsave(&adapter->mwifiex_cmd_lock, flags);
-               adapter->scan_processing = false;
-               spin_unlock_irqrestore(&adapter->mwifiex_cmd_lock, flags);
-
-               mwifiex_active_scan_req_for_passive_chan(priv);
-
-               if (!adapter->ext_scan)
-                       mwifiex_complete_scan(priv);
-
-               if (priv->scan_request) {
-                       mwifiex_dbg(adapter, INFO,
-                                   "info: notifying scan done\n");
-                       cfg80211_scan_done(priv->scan_request, 0);
-                       priv->scan_request = NULL;
-               } else {
-                       priv->scan_aborting = false;
-                       mwifiex_dbg(adapter, INFO,
-                                   "info: scan already aborted\n");
-               }
-       } else if ((priv->scan_aborting && !priv->scan_request) ||
-                  priv->scan_block) {
-               list_for_each_entry_safe(cmd_node, tmp_node,
-                                        &adapter->scan_pending_q, list) {
-                       list_del(&cmd_node->list);
-                       mwifiex_insert_cmd_to_free_q(adapter, cmd_node);
-               }
-               spin_unlock_irqrestore(&adapter->scan_pending_q_lock, flags);
-
-               spin_lock_irqsave(&adapter->mwifiex_cmd_lock, flags);
-               adapter->scan_processing = false;
-               spin_unlock_irqrestore(&adapter->mwifiex_cmd_lock, flags);
-
-               if (!adapter->active_scan_triggered) {
-                       if (priv->scan_request) {
-                               mwifiex_dbg(adapter, INFO,
-                                           "info: aborting scan\n");
-                               cfg80211_scan_done(priv->scan_request, 1);
-                               priv->scan_request = NULL;
-                       } else {
-                               priv->scan_aborting = false;
-                               mwifiex_dbg(adapter, INFO,
-                                           "info: scan already aborted\n");
-                       }
-               }
-       } else {
-               /* Get scan command from scan_pending_q and put to
-                * cmd_pending_q
-                */
-               cmd_node = list_first_entry(&adapter->scan_pending_q,
-                                           struct cmd_ctrl_node, list);
-               list_del(&cmd_node->list);
-               spin_unlock_irqrestore(&adapter->scan_pending_q_lock, flags);
-               mwifiex_insert_cmd_to_pending_q(adapter, cmd_node, true);
-       }
-
-       return;
-}
-
-/*
- * This function handles the command response of scan.
- *
- * The response buffer for the scan command has the following
- * memory layout:
- *
- *      .-------------------------------------------------------------.
- *      |  Header (4 * sizeof(t_u16)):  Standard command response hdr |
- *      .-------------------------------------------------------------.
- *      |  BufSize (t_u16) : sizeof the BSS Description data          |
- *      .-------------------------------------------------------------.
- *      |  NumOfSet (t_u8) : Number of BSS Descs returned             |
- *      .-------------------------------------------------------------.
- *      |  BSSDescription data (variable, size given in BufSize)      |
- *      .-------------------------------------------------------------.
- *      |  TLV data (variable, size calculated using Header->Size,    |
- *      |            BufSize and sizeof the fixed fields above)       |
- *      .-------------------------------------------------------------.
- */
-int mwifiex_ret_802_11_scan(struct mwifiex_private *priv,
-                           struct host_cmd_ds_command *resp)
-{
-       int ret = 0;
-       struct mwifiex_adapter *adapter = priv->adapter;
-       struct host_cmd_ds_802_11_scan_rsp *scan_rsp;
-       struct mwifiex_ie_types_data *tlv_data;
-       struct mwifiex_ie_types_tsf_timestamp *tsf_tlv;
-       u8 *bss_info;
-       u32 scan_resp_size;
-       u32 bytes_left;
-       u32 idx;
-       u32 tlv_buf_size;
-       struct mwifiex_ie_types_chan_band_list_param_set *chan_band_tlv;
-       struct chan_band_param_set *chan_band;
-       u8 is_bgscan_resp;
-       __le64 fw_tsf = 0;
-       u8 *radio_type;
-
-       is_bgscan_resp = (le16_to_cpu(resp->command)
-                         == HostCmd_CMD_802_11_BG_SCAN_QUERY);
-       if (is_bgscan_resp)
-               scan_rsp = &resp->params.bg_scan_query_resp.scan_resp;
-       else
-               scan_rsp = &resp->params.scan_resp;
-
-
-       if (scan_rsp->number_of_sets > MWIFIEX_MAX_AP) {
-               mwifiex_dbg(adapter, ERROR,
-                           "SCAN_RESP: too many AP returned (%d)\n",
-                           scan_rsp->number_of_sets);
-               ret = -1;
-               goto check_next_scan;
-       }
-
-       /* Check csa channel expiry before parsing scan response */
-       mwifiex_11h_get_csa_closed_channel(priv);
-
-       bytes_left = le16_to_cpu(scan_rsp->bss_descript_size);
-       mwifiex_dbg(adapter, INFO,
-                   "info: SCAN_RESP: bss_descript_size %d\n",
-                   bytes_left);
-
-       scan_resp_size = le16_to_cpu(resp->size);
-
-       mwifiex_dbg(adapter, INFO,
-                   "info: SCAN_RESP: returned %d APs before parsing\n",
-                   scan_rsp->number_of_sets);
-
-       bss_info = scan_rsp->bss_desc_and_tlv_buffer;
-
-       /*
-        * The size of the TLV buffer is equal to the entire command response
-        *   size (scan_resp_size) minus the fixed fields (sizeof()'s), the
-        *   BSS Descriptions (bss_descript_size as bytesLef) and the command
-        *   response header (S_DS_GEN)
-        */
-       tlv_buf_size = scan_resp_size - (bytes_left
-                                        + sizeof(scan_rsp->bss_descript_size)
-                                        + sizeof(scan_rsp->number_of_sets)
-                                        + S_DS_GEN);
-
-       tlv_data = (struct mwifiex_ie_types_data *) (scan_rsp->
-                                                bss_desc_and_tlv_buffer +
-                                                bytes_left);
-
-       /* Search the TLV buffer space in the scan response for any valid
-          TLVs */
-       mwifiex_ret_802_11_scan_get_tlv_ptrs(adapter, tlv_data, tlv_buf_size,
-                                            TLV_TYPE_TSFTIMESTAMP,
-                                            (struct mwifiex_ie_types_data **)
-                                            &tsf_tlv);
-
-       /* Search the TLV buffer space in the scan response for any valid
-          TLVs */
-       mwifiex_ret_802_11_scan_get_tlv_ptrs(adapter, tlv_data, tlv_buf_size,
-                                            TLV_TYPE_CHANNELBANDLIST,
-                                            (struct mwifiex_ie_types_data **)
-                                            &chan_band_tlv);
-
-       for (idx = 0; idx < scan_rsp->number_of_sets && bytes_left; idx++) {
-               /*
-                * If the TSF TLV was appended to the scan results, save this
-                * entry's TSF value in the fw_tsf field. It is the firmware's
-                * TSF value at the time the beacon or probe response was
-                * received.
-                */
-               if (tsf_tlv)
-                       memcpy(&fw_tsf, &tsf_tlv->tsf_data[idx * TSF_DATA_SIZE],
-                              sizeof(fw_tsf));
-
-               if (chan_band_tlv) {
-                       chan_band = &chan_band_tlv->chan_band_param[idx];
-                       radio_type = &chan_band->radio_type;
-               } else {
-                       radio_type = NULL;
-               }
-
-               ret = mwifiex_parse_single_response_buf(priv, &bss_info,
-                                                       &bytes_left,
-                                                       le64_to_cpu(fw_tsf),
-                                                       radio_type, false, 0);
-               if (ret)
-                       goto check_next_scan;
-       }
-
-check_next_scan:
-       mwifiex_check_next_scan_command(priv);
-       return ret;
-}
-
-/*
- * This function prepares an extended scan command to be sent to the firmware
- *
- * This uses the scan command configuration sent to the command processing
- * module in command preparation stage to configure a extended scan command
- * structure to send to firmware.
- */
-int mwifiex_cmd_802_11_scan_ext(struct mwifiex_private *priv,
-                               struct host_cmd_ds_command *cmd,
-                               void *data_buf)
-{
-       struct host_cmd_ds_802_11_scan_ext *ext_scan = &cmd->params.ext_scan;
-       struct mwifiex_scan_cmd_config *scan_cfg = data_buf;
-
-       memcpy(ext_scan->tlv_buffer, scan_cfg->tlv_buf, scan_cfg->tlv_buf_len);
-
-       cmd->command = cpu_to_le16(HostCmd_CMD_802_11_SCAN_EXT);
-
-       /* Size is equal to the sizeof(fixed portions) + the TLV len + header */
-       cmd->size = cpu_to_le16((u16)(sizeof(ext_scan->reserved)
-                                     + scan_cfg->tlv_buf_len + S_DS_GEN));
-
-       return 0;
-}
-
-static void
-mwifiex_update_chan_statistics(struct mwifiex_private *priv,
-                              struct mwifiex_ietypes_chanstats *tlv_stat)
-{
-       struct mwifiex_adapter *adapter = priv->adapter;
-       u8 i, num_chan;
-       struct mwifiex_fw_chan_stats *fw_chan_stats;
-       struct mwifiex_chan_stats chan_stats;
-
-       fw_chan_stats = (void *)((u8 *)tlv_stat +
-                             sizeof(struct mwifiex_ie_types_header));
-       num_chan = le16_to_cpu(tlv_stat->header.len) /
-                                             sizeof(struct mwifiex_chan_stats);
-
-       for (i = 0 ; i < num_chan; i++) {
-               chan_stats.chan_num = fw_chan_stats->chan_num;
-               chan_stats.bandcfg = fw_chan_stats->bandcfg;
-               chan_stats.flags = fw_chan_stats->flags;
-               chan_stats.noise = fw_chan_stats->noise;
-               chan_stats.total_bss = le16_to_cpu(fw_chan_stats->total_bss);
-               chan_stats.cca_scan_dur =
-                                      le16_to_cpu(fw_chan_stats->cca_scan_dur);
-               chan_stats.cca_busy_dur =
-                                      le16_to_cpu(fw_chan_stats->cca_busy_dur);
-               mwifiex_dbg(adapter, INFO,
-                           "chan=%d, noise=%d, total_network=%d scan_duration=%d, busy_duration=%d\n",
-                           chan_stats.chan_num,
-                           chan_stats.noise,
-                           chan_stats.total_bss,
-                           chan_stats.cca_scan_dur,
-                           chan_stats.cca_busy_dur);
-               memcpy(&adapter->chan_stats[adapter->survey_idx++], &chan_stats,
-                      sizeof(struct mwifiex_chan_stats));
-               fw_chan_stats++;
-       }
-}
-
-/* This function handles the command response of extended scan */
-int mwifiex_ret_802_11_scan_ext(struct mwifiex_private *priv,
-                               struct host_cmd_ds_command *resp)
-{
-       struct mwifiex_adapter *adapter = priv->adapter;
-       struct host_cmd_ds_802_11_scan_ext *ext_scan_resp;
-       struct mwifiex_ie_types_header *tlv;
-       struct mwifiex_ietypes_chanstats *tlv_stat;
-       u16 buf_left, type, len;
-
-       struct host_cmd_ds_command *cmd_ptr;
-       struct cmd_ctrl_node *cmd_node;
-       unsigned long cmd_flags, scan_flags;
-       bool complete_scan = false;
-
-       mwifiex_dbg(adapter, INFO, "info: EXT scan returns successfully\n");
-
-       ext_scan_resp = &resp->params.ext_scan;
-
-       tlv = (void *)ext_scan_resp->tlv_buffer;
-       buf_left = le16_to_cpu(resp->size) - (sizeof(*ext_scan_resp) + S_DS_GEN
-                                             - 1);
-
-       while (buf_left >= sizeof(struct mwifiex_ie_types_header)) {
-               type = le16_to_cpu(tlv->type);
-               len = le16_to_cpu(tlv->len);
-
-               if (buf_left < (sizeof(struct mwifiex_ie_types_header) + len)) {
-                       mwifiex_dbg(adapter, ERROR,
-                                   "error processing scan response TLVs");
-                       break;
-               }
-
-               switch (type) {
-               case TLV_TYPE_CHANNEL_STATS:
-                       tlv_stat = (void *)tlv;
-                       mwifiex_update_chan_statistics(priv, tlv_stat);
-                       break;
-               default:
-                       break;
-               }
-
-               buf_left -= len + sizeof(struct mwifiex_ie_types_header);
-               tlv = (void *)((u8 *)tlv + len +
-                              sizeof(struct mwifiex_ie_types_header));
-       }
-
-       spin_lock_irqsave(&adapter->cmd_pending_q_lock, cmd_flags);
-       spin_lock_irqsave(&adapter->scan_pending_q_lock, scan_flags);
-       if (list_empty(&adapter->scan_pending_q)) {
-               complete_scan = true;
-               list_for_each_entry(cmd_node, &adapter->cmd_pending_q, list) {
-                       cmd_ptr = (void *)cmd_node->cmd_skb->data;
-                       if (le16_to_cpu(cmd_ptr->command) ==
-                           HostCmd_CMD_802_11_SCAN_EXT) {
-                               mwifiex_dbg(adapter, INFO,
-                                           "Scan pending in command pending list");
-                               complete_scan = false;
-                               break;
-                       }
-               }
-       }
-       spin_unlock_irqrestore(&adapter->scan_pending_q_lock, scan_flags);
-       spin_unlock_irqrestore(&adapter->cmd_pending_q_lock, cmd_flags);
-
-       if (complete_scan)
-               mwifiex_complete_scan(priv);
-
-       return 0;
-}
-
-/* This function This function handles the event extended scan report. It
- * parses extended scan results and informs to cfg80211 stack.
- */
-int mwifiex_handle_event_ext_scan_report(struct mwifiex_private *priv,
-                                        void *buf)
-{
-       int ret = 0;
-       struct mwifiex_adapter *adapter = priv->adapter;
-       u8 *bss_info;
-       u32 bytes_left, bytes_left_for_tlv, idx;
-       u16 type, len;
-       struct mwifiex_ie_types_data *tlv;
-       struct mwifiex_ie_types_bss_scan_rsp *scan_rsp_tlv;
-       struct mwifiex_ie_types_bss_scan_info *scan_info_tlv;
-       u8 *radio_type;
-       u64 fw_tsf = 0;
-       s32 rssi = 0;
-       struct mwifiex_event_scan_result *event_scan = buf;
-       u8 num_of_set = event_scan->num_of_set;
-       u8 *scan_resp = buf + sizeof(struct mwifiex_event_scan_result);
-       u16 scan_resp_size = le16_to_cpu(event_scan->buf_size);
-
-       if (num_of_set > MWIFIEX_MAX_AP) {
-               mwifiex_dbg(adapter, ERROR,
-                           "EXT_SCAN: Invalid number of AP returned (%d)!!\n",
-                           num_of_set);
-               ret = -1;
-               goto check_next_scan;
-       }
-
-       bytes_left = scan_resp_size;
-       mwifiex_dbg(adapter, INFO,
-                   "EXT_SCAN: size %d, returned %d APs...",
-                   scan_resp_size, num_of_set);
-       mwifiex_dbg_dump(adapter, CMD_D, "EXT_SCAN buffer:", buf,
-                        scan_resp_size +
-                        sizeof(struct mwifiex_event_scan_result));
-
-       tlv = (struct mwifiex_ie_types_data *)scan_resp;
-
-       for (idx = 0; idx < num_of_set && bytes_left; idx++) {
-               type = le16_to_cpu(tlv->header.type);
-               len = le16_to_cpu(tlv->header.len);
-               if (bytes_left < sizeof(struct mwifiex_ie_types_header) + len) {
-                       mwifiex_dbg(adapter, ERROR,
-                                   "EXT_SCAN: Error bytes left < TLV length\n");
-                       break;
-               }
-               scan_rsp_tlv = NULL;
-               scan_info_tlv = NULL;
-               bytes_left_for_tlv = bytes_left;
-
-               /* BSS response TLV with beacon or probe response buffer
-                * at the initial position of each descriptor
-                */
-               if (type != TLV_TYPE_BSS_SCAN_RSP)
-                       break;
-
-               bss_info = (u8 *)tlv;
-               scan_rsp_tlv = (struct mwifiex_ie_types_bss_scan_rsp *)tlv;
-               tlv = (struct mwifiex_ie_types_data *)(tlv->data + len);
-               bytes_left_for_tlv -=
-                               (len + sizeof(struct mwifiex_ie_types_header));
-
-               while (bytes_left_for_tlv >=
-                      sizeof(struct mwifiex_ie_types_header) &&
-                      le16_to_cpu(tlv->header.type) != TLV_TYPE_BSS_SCAN_RSP) {
-                       type = le16_to_cpu(tlv->header.type);
-                       len = le16_to_cpu(tlv->header.len);
-                       if (bytes_left_for_tlv <
-                           sizeof(struct mwifiex_ie_types_header) + len) {
-                               mwifiex_dbg(adapter, ERROR,
-                                           "EXT_SCAN: Error in processing TLV,\t"
-                                           "bytes left < TLV length\n");
-                               scan_rsp_tlv = NULL;
-                               bytes_left_for_tlv = 0;
-                               continue;
-                       }
-                       switch (type) {
-                       case TLV_TYPE_BSS_SCAN_INFO:
-                               scan_info_tlv =
-                                 (struct mwifiex_ie_types_bss_scan_info *)tlv;
-                               if (len !=
-                                sizeof(struct mwifiex_ie_types_bss_scan_info) -
-                                sizeof(struct mwifiex_ie_types_header)) {
-                                       bytes_left_for_tlv = 0;
-                                       continue;
-                               }
-                               break;
-                       default:
-                               break;
-                       }
-                       tlv = (struct mwifiex_ie_types_data *)(tlv->data + len);
-                       bytes_left -=
-                               (len + sizeof(struct mwifiex_ie_types_header));
-                       bytes_left_for_tlv -=
-                               (len + sizeof(struct mwifiex_ie_types_header));
-               }
-
-               if (!scan_rsp_tlv)
-                       break;
-
-               /* Advance pointer to the beacon buffer length and
-                * update the bytes count so that the function
-                * wlan_interpret_bss_desc_with_ie() can handle the
-                * scan buffer withut any change
-                */
-               bss_info += sizeof(u16);
-               bytes_left -= sizeof(u16);
-
-               if (scan_info_tlv) {
-                       rssi = (s32)(s16)(le16_to_cpu(scan_info_tlv->rssi));
-                       rssi *= 100;           /* Convert dBm to mBm */
-                       mwifiex_dbg(adapter, INFO,
-                                   "info: InterpretIE: RSSI=%d\n", rssi);
-                       fw_tsf = le64_to_cpu(scan_info_tlv->tsf);
-                       radio_type = &scan_info_tlv->radio_type;
-               } else {
-                       radio_type = NULL;
-               }
-               ret = mwifiex_parse_single_response_buf(priv, &bss_info,
-                                                       &bytes_left, fw_tsf,
-                                                       radio_type, true, rssi);
-               if (ret)
-                       goto check_next_scan;
-       }
-
-check_next_scan:
-       if (!event_scan->more_event)
-               mwifiex_check_next_scan_command(priv);
-
-       return ret;
-}
-
-/*
- * This function prepares command for background scan query.
- *
- * Preparation includes -
- *      - Setting command ID and proper size
- *      - Setting background scan flush parameter
- *      - Ensuring correct endian-ness
- */
-int mwifiex_cmd_802_11_bg_scan_query(struct host_cmd_ds_command *cmd)
-{
-       struct host_cmd_ds_802_11_bg_scan_query *bg_query =
-               &cmd->params.bg_scan_query;
-
-       cmd->command = cpu_to_le16(HostCmd_CMD_802_11_BG_SCAN_QUERY);
-       cmd->size = cpu_to_le16(sizeof(struct host_cmd_ds_802_11_bg_scan_query)
-                               + S_DS_GEN);
-
-       bg_query->flush = 1;
-
-       return 0;
-}
-
-/*
- * This function inserts scan command node to the scan pending queue.
- */
-void
-mwifiex_queue_scan_cmd(struct mwifiex_private *priv,
-                      struct cmd_ctrl_node *cmd_node)
-{
-       struct mwifiex_adapter *adapter = priv->adapter;
-       unsigned long flags;
-
-       cmd_node->wait_q_enabled = true;
-       cmd_node->condition = &adapter->scan_wait_q_woken;
-       spin_lock_irqsave(&adapter->scan_pending_q_lock, flags);
-       list_add_tail(&cmd_node->list, &adapter->scan_pending_q);
-       spin_unlock_irqrestore(&adapter->scan_pending_q_lock, flags);
-}
-
-/*
- * This function sends a scan command for all available channels to the
- * firmware, filtered on a specific SSID.
- */
-static int mwifiex_scan_specific_ssid(struct mwifiex_private *priv,
-                                     struct cfg80211_ssid *req_ssid)
-{
-       struct mwifiex_adapter *adapter = priv->adapter;
-       int ret;
-       struct mwifiex_user_scan_cfg *scan_cfg;
-
-       if (adapter->scan_processing) {
-               mwifiex_dbg(adapter, WARN,
-                           "cmd: Scan already in process...\n");
-               return -EBUSY;
-       }
-
-       if (priv->scan_block) {
-               mwifiex_dbg(adapter, WARN,
-                           "cmd: Scan is blocked during association...\n");
-               return -EBUSY;
-       }
-
-       scan_cfg = kzalloc(sizeof(struct mwifiex_user_scan_cfg), GFP_KERNEL);
-       if (!scan_cfg)
-               return -ENOMEM;
-
-       scan_cfg->ssid_list = req_ssid;
-       scan_cfg->num_ssids = 1;
-
-       ret = mwifiex_scan_networks(priv, scan_cfg);
-
-       kfree(scan_cfg);
-       return ret;
-}
-
-/*
- * Sends IOCTL request to start a scan.
- *
- * This function allocates the IOCTL request buffer, fills it
- * with requisite parameters and calls the IOCTL handler.
- *
- * Scan command can be issued for both normal scan and specific SSID
- * scan, depending upon whether an SSID is provided or not.
- */
-int mwifiex_request_scan(struct mwifiex_private *priv,
-                        struct cfg80211_ssid *req_ssid)
-{
-       int ret;
-
-       if (down_interruptible(&priv->async_sem)) {
-               mwifiex_dbg(priv->adapter, ERROR,
-                           "%s: acquire semaphore fail\n",
-                           __func__);
-               return -1;
-       }
-
-       priv->adapter->scan_wait_q_woken = false;
-
-       if (req_ssid && req_ssid->ssid_len != 0)
-               /* Specific SSID scan */
-               ret = mwifiex_scan_specific_ssid(priv, req_ssid);
-       else
-               /* Normal scan */
-               ret = mwifiex_scan_networks(priv, NULL);
-
-       up(&priv->async_sem);
-
-       return ret;
-}
-
-/*
- * This function appends the vendor specific IE TLV to a buffer.
- */
-int
-mwifiex_cmd_append_vsie_tlv(struct mwifiex_private *priv,
-                           u16 vsie_mask, u8 **buffer)
-{
-       int id, ret_len = 0;
-       struct mwifiex_ie_types_vendor_param_set *vs_param_set;
-
-       if (!buffer)
-               return 0;
-       if (!(*buffer))
-               return 0;
-
-       /*
-        * Traverse through the saved vendor specific IE array and append
-        * the selected(scan/assoc/adhoc) IE as TLV to the command
-        */
-       for (id = 0; id < MWIFIEX_MAX_VSIE_NUM; id++) {
-               if (priv->vs_ie[id].mask & vsie_mask) {
-                       vs_param_set =
-                               (struct mwifiex_ie_types_vendor_param_set *)
-                               *buffer;
-                       vs_param_set->header.type =
-                               cpu_to_le16(TLV_TYPE_PASSTHROUGH);
-                       vs_param_set->header.len =
-                               cpu_to_le16((((u16) priv->vs_ie[id].ie[1])
-                               & 0x00FF) + 2);
-                       memcpy(vs_param_set->ie, priv->vs_ie[id].ie,
-                              le16_to_cpu(vs_param_set->header.len));
-                       *buffer += le16_to_cpu(vs_param_set->header.len) +
-                                  sizeof(struct mwifiex_ie_types_header);
-                       ret_len += le16_to_cpu(vs_param_set->header.len) +
-                                  sizeof(struct mwifiex_ie_types_header);
-               }
-       }
-       return ret_len;
-}
-
-/*
- * This function saves a beacon buffer of the current BSS descriptor.
- *
- * The current beacon buffer is saved so that it can be restored in the
- * following cases that makes the beacon buffer not to contain the current
- * ssid's beacon buffer.
- *      - The current ssid was not found somehow in the last scan.
- *      - The current ssid was the last entry of the scan table and overloaded.
- */
-void
-mwifiex_save_curr_bcn(struct mwifiex_private *priv)
-{
-       struct mwifiex_bssdescriptor *curr_bss =
-               &priv->curr_bss_params.bss_descriptor;
-
-       if (!curr_bss->beacon_buf_size)
-               return;
-
-       /* allocate beacon buffer at 1st time; or if it's size has changed */
-       if (!priv->curr_bcn_buf ||
-           priv->curr_bcn_size != curr_bss->beacon_buf_size) {
-               priv->curr_bcn_size = curr_bss->beacon_buf_size;
-
-               kfree(priv->curr_bcn_buf);
-               priv->curr_bcn_buf = kmalloc(curr_bss->beacon_buf_size,
-                                            GFP_ATOMIC);
-               if (!priv->curr_bcn_buf)
-                       return;
-       }
-
-       memcpy(priv->curr_bcn_buf, curr_bss->beacon_buf,
-              curr_bss->beacon_buf_size);
-       mwifiex_dbg(priv->adapter, INFO,
-                   "info: current beacon saved %d\n",
-                   priv->curr_bcn_size);
-
-       curr_bss->beacon_buf = priv->curr_bcn_buf;
-
-       /* adjust the pointers in the current BSS descriptor */
-       if (curr_bss->bcn_wpa_ie)
-               curr_bss->bcn_wpa_ie =
-                       (struct ieee_types_vendor_specific *)
-                       (curr_bss->beacon_buf +
-                        curr_bss->wpa_offset);
-
-       if (curr_bss->bcn_rsn_ie)
-               curr_bss->bcn_rsn_ie = (struct ieee_types_generic *)
-                       (curr_bss->beacon_buf +
-                        curr_bss->rsn_offset);
-
-       if (curr_bss->bcn_ht_cap)
-               curr_bss->bcn_ht_cap = (struct ieee80211_ht_cap *)
-                       (curr_bss->beacon_buf +
-                        curr_bss->ht_cap_offset);
-
-       if (curr_bss->bcn_ht_oper)
-               curr_bss->bcn_ht_oper = (struct ieee80211_ht_operation *)
-                       (curr_bss->beacon_buf +
-                        curr_bss->ht_info_offset);
-
-       if (curr_bss->bcn_vht_cap)
-               curr_bss->bcn_vht_cap = (void *)(curr_bss->beacon_buf +
-                                                curr_bss->vht_cap_offset);
-
-       if (curr_bss->bcn_vht_oper)
-               curr_bss->bcn_vht_oper = (void *)(curr_bss->beacon_buf +
-                                                 curr_bss->vht_info_offset);
-
-       if (curr_bss->bcn_bss_co_2040)
-               curr_bss->bcn_bss_co_2040 =
-                       (curr_bss->beacon_buf + curr_bss->bss_co_2040_offset);
-
-       if (curr_bss->bcn_ext_cap)
-               curr_bss->bcn_ext_cap = curr_bss->beacon_buf +
-                       curr_bss->ext_cap_offset;
-
-       if (curr_bss->oper_mode)
-               curr_bss->oper_mode = (void *)(curr_bss->beacon_buf +
-                                              curr_bss->oper_mode_offset);
-}
-
-/*
- * This function frees the current BSS descriptor beacon buffer.
- */
-void
-mwifiex_free_curr_bcn(struct mwifiex_private *priv)
-{
-       kfree(priv->curr_bcn_buf);
-       priv->curr_bcn_buf = NULL;
-}
diff --git a/drivers/net/wireless/mwifiex/sdio.c b/drivers/net/wireless/mwifiex/sdio.c
deleted file mode 100644 (file)
index 78a8474..0000000
+++ /dev/null
@@ -1,2684 +0,0 @@
-/*
- * Marvell Wireless LAN device driver: SDIO specific handling
- *
- * Copyright (C) 2011-2014, Marvell International Ltd.
- *
- * This software file (the "File") is distributed by Marvell International
- * Ltd. under the terms of the GNU General Public License Version 2, June 1991
- * (the "License").  You may use, redistribute and/or modify this File in
- * accordance with the terms and conditions of the License, a copy of which
- * is available by writing to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the
- * worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
- *
- * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
- * ARE EXPRESSLY DISCLAIMED.  The License provides additional details about
- * this warranty disclaimer.
- */
-
-#include <linux/firmware.h>
-
-#include "decl.h"
-#include "ioctl.h"
-#include "util.h"
-#include "fw.h"
-#include "main.h"
-#include "wmm.h"
-#include "11n.h"
-#include "sdio.h"
-
-
-#define SDIO_VERSION   "1.0"
-
-/* The mwifiex_sdio_remove() callback function is called when
- * user removes this module from kernel space or ejects
- * the card from the slot. The driver handles these 2 cases
- * differently.
- * If the user is removing the module, the few commands (FUNC_SHUTDOWN,
- * HS_CANCEL etc.) are sent to the firmware.
- * If the card is removed, there is no need to send these command.
- *
- * The variable 'user_rmmod' is used to distinguish these two
- * scenarios. This flag is initialized as FALSE in case the card
- * is removed, and will be set to TRUE for module removal when
- * module_exit function is called.
- */
-static u8 user_rmmod;
-
-static struct mwifiex_if_ops sdio_ops;
-static unsigned long iface_work_flags;
-
-static struct semaphore add_remove_card_sem;
-
-static struct memory_type_mapping generic_mem_type_map[] = {
-       {"DUMP", NULL, 0, 0xDD},
-};
-
-static struct memory_type_mapping mem_type_mapping_tbl[] = {
-       {"ITCM", NULL, 0, 0xF0},
-       {"DTCM", NULL, 0, 0xF1},
-       {"SQRAM", NULL, 0, 0xF2},
-       {"APU", NULL, 0, 0xF3},
-       {"CIU", NULL, 0, 0xF4},
-       {"ICU", NULL, 0, 0xF5},
-       {"MAC", NULL, 0, 0xF6},
-       {"EXT7", NULL, 0, 0xF7},
-       {"EXT8", NULL, 0, 0xF8},
-       {"EXT9", NULL, 0, 0xF9},
-       {"EXT10", NULL, 0, 0xFA},
-       {"EXT11", NULL, 0, 0xFB},
-       {"EXT12", NULL, 0, 0xFC},
-       {"EXT13", NULL, 0, 0xFD},
-       {"EXTLAST", NULL, 0, 0xFE},
-};
-
-/*
- * SDIO probe.
- *
- * This function probes an mwifiex device and registers it. It allocates
- * the card structure, enables SDIO function number and initiates the
- * device registration and initialization procedure by adding a logical
- * interface.
- */
-static int
-mwifiex_sdio_probe(struct sdio_func *func, const struct sdio_device_id *id)
-{
-       int ret;
-       struct sdio_mmc_card *card = NULL;
-
-       pr_debug("info: vendor=0x%4.04X device=0x%4.04X class=%d function=%d\n",
-                func->vendor, func->device, func->class, func->num);
-
-       card = kzalloc(sizeof(struct sdio_mmc_card), GFP_KERNEL);
-       if (!card)
-               return -ENOMEM;
-
-       card->func = func;
-       card->device_id = id;
-
-       func->card->quirks |= MMC_QUIRK_BLKSZ_FOR_BYTE_MODE;
-
-       if (id->driver_data) {
-               struct mwifiex_sdio_device *data = (void *)id->driver_data;
-
-               card->firmware = data->firmware;
-               card->reg = data->reg;
-               card->max_ports = data->max_ports;
-               card->mp_agg_pkt_limit = data->mp_agg_pkt_limit;
-               card->supports_sdio_new_mode = data->supports_sdio_new_mode;
-               card->has_control_mask = data->has_control_mask;
-               card->tx_buf_size = data->tx_buf_size;
-               card->mp_tx_agg_buf_size = data->mp_tx_agg_buf_size;
-               card->mp_rx_agg_buf_size = data->mp_rx_agg_buf_size;
-               card->can_dump_fw = data->can_dump_fw;
-               card->fw_dump_enh = data->fw_dump_enh;
-               card->can_auto_tdls = data->can_auto_tdls;
-               card->can_ext_scan = data->can_ext_scan;
-       }
-
-       sdio_claim_host(func);
-       ret = sdio_enable_func(func);
-       sdio_release_host(func);
-
-       if (ret) {
-               pr_err("%s: failed to enable function\n", __func__);
-               kfree(card);
-               return -EIO;
-       }
-
-       if (mwifiex_add_card(card, &add_remove_card_sem, &sdio_ops,
-                            MWIFIEX_SDIO)) {
-               pr_err("%s: add card failed\n", __func__);
-               kfree(card);
-               sdio_claim_host(func);
-               ret = sdio_disable_func(func);
-               sdio_release_host(func);
-               ret = -1;
-       }
-
-       return ret;
-}
-
-/*
- * SDIO resume.
- *
- * Kernel needs to suspend all functions separately. Therefore all
- * registered functions must have drivers with suspend and resume
- * methods. Failing that the kernel simply removes the whole card.
- *
- * If already not resumed, this function turns on the traffic and
- * sends a host sleep cancel request to the firmware.
- */
-static int mwifiex_sdio_resume(struct device *dev)
-{
-       struct sdio_func *func = dev_to_sdio_func(dev);
-       struct sdio_mmc_card *card;
-       struct mwifiex_adapter *adapter;
-       mmc_pm_flag_t pm_flag = 0;
-
-       if (func) {
-               pm_flag = sdio_get_host_pm_caps(func);
-               card = sdio_get_drvdata(func);
-               if (!card || !card->adapter) {
-                       pr_err("resume: invalid card or adapter\n");
-                       return 0;
-               }
-       } else {
-               pr_err("resume: sdio_func is not specified\n");
-               return 0;
-       }
-
-       adapter = card->adapter;
-
-       if (!adapter->is_suspended) {
-               mwifiex_dbg(adapter, WARN,
-                           "device already resumed\n");
-               return 0;
-       }
-
-       adapter->is_suspended = false;
-
-       /* Disable Host Sleep */
-       mwifiex_cancel_hs(mwifiex_get_priv(adapter, MWIFIEX_BSS_ROLE_STA),
-                         MWIFIEX_ASYNC_CMD);
-
-       return 0;
-}
-
-/*
- * SDIO remove.
- *
- * This function removes the interface and frees up the card structure.
- */
-static void
-mwifiex_sdio_remove(struct sdio_func *func)
-{
-       struct sdio_mmc_card *card;
-       struct mwifiex_adapter *adapter;
-       struct mwifiex_private *priv;
-
-       card = sdio_get_drvdata(func);
-       if (!card)
-               return;
-
-       adapter = card->adapter;
-       if (!adapter || !adapter->priv_num)
-               return;
-
-       mwifiex_dbg(adapter, INFO, "info: SDIO func num=%d\n", func->num);
-
-       if (user_rmmod) {
-               if (adapter->is_suspended)
-                       mwifiex_sdio_resume(adapter->dev);
-
-               mwifiex_deauthenticate_all(adapter);
-
-               priv = mwifiex_get_priv(adapter, MWIFIEX_BSS_ROLE_ANY);
-               mwifiex_disable_auto_ds(priv);
-               mwifiex_init_shutdown_fw(priv, MWIFIEX_FUNC_SHUTDOWN);
-       }
-
-       mwifiex_remove_card(card->adapter, &add_remove_card_sem);
-}
-
-/*
- * SDIO suspend.
- *
- * Kernel needs to suspend all functions separately. Therefore all
- * registered functions must have drivers with suspend and resume
- * methods. Failing that the kernel simply removes the whole card.
- *
- * If already not suspended, this function allocates and sends a host
- * sleep activate request to the firmware and turns off the traffic.
- */
-static int mwifiex_sdio_suspend(struct device *dev)
-{
-       struct sdio_func *func = dev_to_sdio_func(dev);
-       struct sdio_mmc_card *card;
-       struct mwifiex_adapter *adapter;
-       mmc_pm_flag_t pm_flag = 0;
-       int ret = 0;
-
-       if (func) {
-               pm_flag = sdio_get_host_pm_caps(func);
-               pr_debug("cmd: %s: suspend: PM flag = 0x%x\n",
-                        sdio_func_id(func), pm_flag);
-               if (!(pm_flag & MMC_PM_KEEP_POWER)) {
-                       pr_err("%s: cannot remain alive while host is"
-                               " suspended\n", sdio_func_id(func));
-                       return -ENOSYS;
-               }
-
-               card = sdio_get_drvdata(func);
-               if (!card || !card->adapter) {
-                       pr_err("suspend: invalid card or adapter\n");
-                       return 0;
-               }
-       } else {
-               pr_err("suspend: sdio_func is not specified\n");
-               return 0;
-       }
-
-       adapter = card->adapter;
-
-       /* Enable the Host Sleep */
-       if (!mwifiex_enable_hs(adapter)) {
-               mwifiex_dbg(adapter, ERROR,
-                           "cmd: failed to suspend\n");
-               adapter->hs_enabling = false;
-               return -EFAULT;
-       }
-
-       mwifiex_dbg(adapter, INFO,
-                   "cmd: suspend with MMC_PM_KEEP_POWER\n");
-       ret = sdio_set_host_pm_flags(func, MMC_PM_KEEP_POWER);
-
-       /* Indicate device suspended */
-       adapter->is_suspended = true;
-       adapter->hs_enabling = false;
-
-       return ret;
-}
-
-/* Device ID for SD8786 */
-#define SDIO_DEVICE_ID_MARVELL_8786   (0x9116)
-/* Device ID for SD8787 */
-#define SDIO_DEVICE_ID_MARVELL_8787   (0x9119)
-/* Device ID for SD8797 */
-#define SDIO_DEVICE_ID_MARVELL_8797   (0x9129)
-/* Device ID for SD8897 */
-#define SDIO_DEVICE_ID_MARVELL_8897   (0x912d)
-/* Device ID for SD8887 */
-#define SDIO_DEVICE_ID_MARVELL_8887   (0x9135)
-/* Device ID for SD8801 */
-#define SDIO_DEVICE_ID_MARVELL_8801   (0x9139)
-/* Device ID for SD8997 */
-#define SDIO_DEVICE_ID_MARVELL_8997   (0x9141)
-
-
-/* WLAN IDs */
-static const struct sdio_device_id mwifiex_ids[] = {
-       {SDIO_DEVICE(SDIO_VENDOR_ID_MARVELL, SDIO_DEVICE_ID_MARVELL_8786),
-               .driver_data = (unsigned long) &mwifiex_sdio_sd8786},
-       {SDIO_DEVICE(SDIO_VENDOR_ID_MARVELL, SDIO_DEVICE_ID_MARVELL_8787),
-               .driver_data = (unsigned long) &mwifiex_sdio_sd8787},
-       {SDIO_DEVICE(SDIO_VENDOR_ID_MARVELL, SDIO_DEVICE_ID_MARVELL_8797),
-               .driver_data = (unsigned long) &mwifiex_sdio_sd8797},
-       {SDIO_DEVICE(SDIO_VENDOR_ID_MARVELL, SDIO_DEVICE_ID_MARVELL_8897),
-               .driver_data = (unsigned long) &mwifiex_sdio_sd8897},
-       {SDIO_DEVICE(SDIO_VENDOR_ID_MARVELL, SDIO_DEVICE_ID_MARVELL_8887),
-               .driver_data = (unsigned long)&mwifiex_sdio_sd8887},
-       {SDIO_DEVICE(SDIO_VENDOR_ID_MARVELL, SDIO_DEVICE_ID_MARVELL_8801),
-               .driver_data = (unsigned long)&mwifiex_sdio_sd8801},
-       {SDIO_DEVICE(SDIO_VENDOR_ID_MARVELL, SDIO_DEVICE_ID_MARVELL_8997),
-               .driver_data = (unsigned long)&mwifiex_sdio_sd8997},
-       {},
-};
-
-MODULE_DEVICE_TABLE(sdio, mwifiex_ids);
-
-static const struct dev_pm_ops mwifiex_sdio_pm_ops = {
-       .suspend = mwifiex_sdio_suspend,
-       .resume = mwifiex_sdio_resume,
-};
-
-static struct sdio_driver mwifiex_sdio = {
-       .name = "mwifiex_sdio",
-       .id_table = mwifiex_ids,
-       .probe = mwifiex_sdio_probe,
-       .remove = mwifiex_sdio_remove,
-       .drv = {
-               .owner = THIS_MODULE,
-               .pm = &mwifiex_sdio_pm_ops,
-       }
-};
-
-/* Write data into SDIO card register. Caller claims SDIO device. */
-static int
-mwifiex_write_reg_locked(struct sdio_func *func, u32 reg, u8 data)
-{
-       int ret = -1;
-       sdio_writeb(func, data, reg, &ret);
-       return ret;
-}
-
-/*
- * This function writes data into SDIO card register.
- */
-static int
-mwifiex_write_reg(struct mwifiex_adapter *adapter, u32 reg, u8 data)
-{
-       struct sdio_mmc_card *card = adapter->card;
-       int ret;
-
-       sdio_claim_host(card->func);
-       ret = mwifiex_write_reg_locked(card->func, reg, data);
-       sdio_release_host(card->func);
-
-       return ret;
-}
-
-/*
- * This function reads data from SDIO card register.
- */
-static int
-mwifiex_read_reg(struct mwifiex_adapter *adapter, u32 reg, u8 *data)
-{
-       struct sdio_mmc_card *card = adapter->card;
-       int ret = -1;
-       u8 val;
-
-       sdio_claim_host(card->func);
-       val = sdio_readb(card->func, reg, &ret);
-       sdio_release_host(card->func);
-
-       *data = val;
-
-       return ret;
-}
-
-/*
- * This function writes multiple data into SDIO card memory.
- *
- * This does not work in suspended mode.
- */
-static int
-mwifiex_write_data_sync(struct mwifiex_adapter *adapter,
-                       u8 *buffer, u32 pkt_len, u32 port)
-{
-       struct sdio_mmc_card *card = adapter->card;
-       int ret;
-       u8 blk_mode =
-               (port & MWIFIEX_SDIO_BYTE_MODE_MASK) ? BYTE_MODE : BLOCK_MODE;
-       u32 blk_size = (blk_mode == BLOCK_MODE) ? MWIFIEX_SDIO_BLOCK_SIZE : 1;
-       u32 blk_cnt =
-               (blk_mode ==
-                BLOCK_MODE) ? (pkt_len /
-                               MWIFIEX_SDIO_BLOCK_SIZE) : pkt_len;
-       u32 ioport = (port & MWIFIEX_SDIO_IO_PORT_MASK);
-
-       if (adapter->is_suspended) {
-               mwifiex_dbg(adapter, ERROR,
-                           "%s: not allowed while suspended\n", __func__);
-               return -1;
-       }
-
-       sdio_claim_host(card->func);
-
-       ret = sdio_writesb(card->func, ioport, buffer, blk_cnt * blk_size);
-
-       sdio_release_host(card->func);
-
-       return ret;
-}
-
-/*
- * This function reads multiple data from SDIO card memory.
- */
-static int mwifiex_read_data_sync(struct mwifiex_adapter *adapter, u8 *buffer,
-                                 u32 len, u32 port, u8 claim)
-{
-       struct sdio_mmc_card *card = adapter->card;
-       int ret;
-       u8 blk_mode = (port & MWIFIEX_SDIO_BYTE_MODE_MASK) ? BYTE_MODE
-                      : BLOCK_MODE;
-       u32 blk_size = (blk_mode == BLOCK_MODE) ? MWIFIEX_SDIO_BLOCK_SIZE : 1;
-       u32 blk_cnt = (blk_mode == BLOCK_MODE) ? (len / MWIFIEX_SDIO_BLOCK_SIZE)
-                       : len;
-       u32 ioport = (port & MWIFIEX_SDIO_IO_PORT_MASK);
-
-       if (claim)
-               sdio_claim_host(card->func);
-
-       ret = sdio_readsb(card->func, buffer, ioport, blk_cnt * blk_size);
-
-       if (claim)
-               sdio_release_host(card->func);
-
-       return ret;
-}
-
-/*
- * This function wakes up the card.
- *
- * A host power up command is written to the card configuration
- * register to wake up the card.
- */
-static int mwifiex_pm_wakeup_card(struct mwifiex_adapter *adapter)
-{
-       mwifiex_dbg(adapter, EVENT,
-                   "event: wakeup device...\n");
-
-       return mwifiex_write_reg(adapter, CONFIGURATION_REG, HOST_POWER_UP);
-}
-
-/*
- * This function is called after the card has woken up.
- *
- * The card configuration register is reset.
- */
-static int mwifiex_pm_wakeup_card_complete(struct mwifiex_adapter *adapter)
-{
-       mwifiex_dbg(adapter, EVENT,
-                   "cmd: wakeup device completed\n");
-
-       return mwifiex_write_reg(adapter, CONFIGURATION_REG, 0);
-}
-
-/*
- * This function is used to initialize IO ports for the
- * chipsets supporting SDIO new mode eg SD8897.
- */
-static int mwifiex_init_sdio_new_mode(struct mwifiex_adapter *adapter)
-{
-       u8 reg;
-       struct sdio_mmc_card *card = adapter->card;
-
-       adapter->ioport = MEM_PORT;
-
-       /* enable sdio new mode */
-       if (mwifiex_read_reg(adapter, card->reg->card_cfg_2_1_reg, &reg))
-               return -1;
-       if (mwifiex_write_reg(adapter, card->reg->card_cfg_2_1_reg,
-                             reg | CMD53_NEW_MODE))
-               return -1;
-
-       /* Configure cmd port and enable reading rx length from the register */
-       if (mwifiex_read_reg(adapter, card->reg->cmd_cfg_0, &reg))
-               return -1;
-       if (mwifiex_write_reg(adapter, card->reg->cmd_cfg_0,
-                             reg | CMD_PORT_RD_LEN_EN))
-               return -1;
-
-       /* Enable Dnld/Upld ready auto reset for cmd port after cmd53 is
-        * completed
-        */
-       if (mwifiex_read_reg(adapter, card->reg->cmd_cfg_1, &reg))
-               return -1;
-       if (mwifiex_write_reg(adapter, card->reg->cmd_cfg_1,
-                             reg | CMD_PORT_AUTO_EN))
-               return -1;
-
-       return 0;
-}
-
-/* This function initializes the IO ports.
- *
- * The following operations are performed -
- *      - Read the IO ports (0, 1 and 2)
- *      - Set host interrupt Reset-To-Read to clear
- *      - Set auto re-enable interrupt
- */
-static int mwifiex_init_sdio_ioport(struct mwifiex_adapter *adapter)
-{
-       u8 reg;
-       struct sdio_mmc_card *card = adapter->card;
-
-       adapter->ioport = 0;
-
-       if (card->supports_sdio_new_mode) {
-               if (mwifiex_init_sdio_new_mode(adapter))
-                       return -1;
-               goto cont;
-       }
-
-       /* Read the IO port */
-       if (!mwifiex_read_reg(adapter, card->reg->io_port_0_reg, &reg))
-               adapter->ioport |= (reg & 0xff);
-       else
-               return -1;
-
-       if (!mwifiex_read_reg(adapter, card->reg->io_port_1_reg, &reg))
-               adapter->ioport |= ((reg & 0xff) << 8);
-       else
-               return -1;
-
-       if (!mwifiex_read_reg(adapter, card->reg->io_port_2_reg, &reg))
-               adapter->ioport |= ((reg & 0xff) << 16);
-       else
-               return -1;
-cont:
-       mwifiex_dbg(adapter, INFO,
-                   "info: SDIO FUNC1 IO port: %#x\n", adapter->ioport);
-
-       /* Set Host interrupt reset to read to clear */
-       if (!mwifiex_read_reg(adapter, card->reg->host_int_rsr_reg, &reg))
-               mwifiex_write_reg(adapter, card->reg->host_int_rsr_reg,
-                                 reg | card->reg->sdio_int_mask);
-       else
-               return -1;
-
-       /* Dnld/Upld ready set to auto reset */
-       if (!mwifiex_read_reg(adapter, card->reg->card_misc_cfg_reg, &reg))
-               mwifiex_write_reg(adapter, card->reg->card_misc_cfg_reg,
-                                 reg | AUTO_RE_ENABLE_INT);
-       else
-               return -1;
-
-       return 0;
-}
-
-/*
- * This function sends data to the card.
- */
-static int mwifiex_write_data_to_card(struct mwifiex_adapter *adapter,
-                                     u8 *payload, u32 pkt_len, u32 port)
-{
-       u32 i = 0;
-       int ret;
-
-       do {
-               ret = mwifiex_write_data_sync(adapter, payload, pkt_len, port);
-               if (ret) {
-                       i++;
-                       mwifiex_dbg(adapter, ERROR,
-                                   "host_to_card, write iomem\t"
-                                   "(%d) failed: %d\n", i, ret);
-                       if (mwifiex_write_reg(adapter, CONFIGURATION_REG, 0x04))
-                               mwifiex_dbg(adapter, ERROR,
-                                           "write CFG reg failed\n");
-
-                       ret = -1;
-                       if (i > MAX_WRITE_IOMEM_RETRY)
-                               return ret;
-               }
-       } while (ret == -1);
-
-       return ret;
-}
-
-/*
- * This function gets the read port.
- *
- * If control port bit is set in MP read bitmap, the control port
- * is returned, otherwise the current read port is returned and
- * the value is increased (provided it does not reach the maximum
- * limit, in which case it is reset to 1)
- */
-static int mwifiex_get_rd_port(struct mwifiex_adapter *adapter, u8 *port)
-{
-       struct sdio_mmc_card *card = adapter->card;
-       const struct mwifiex_sdio_card_reg *reg = card->reg;
-       u32 rd_bitmap = card->mp_rd_bitmap;
-
-       mwifiex_dbg(adapter, DATA,
-                   "data: mp_rd_bitmap=0x%08x\n", rd_bitmap);
-
-       if (card->supports_sdio_new_mode) {
-               if (!(rd_bitmap & reg->data_port_mask))
-                       return -1;
-       } else {
-               if (!(rd_bitmap & (CTRL_PORT_MASK | reg->data_port_mask)))
-                       return -1;
-       }
-
-       if ((card->has_control_mask) &&
-           (card->mp_rd_bitmap & CTRL_PORT_MASK)) {
-               card->mp_rd_bitmap &= (u32) (~CTRL_PORT_MASK);
-               *port = CTRL_PORT;
-               mwifiex_dbg(adapter, DATA,
-                           "data: port=%d mp_rd_bitmap=0x%08x\n",
-                           *port, card->mp_rd_bitmap);
-               return 0;
-       }
-
-       if (!(card->mp_rd_bitmap & (1 << card->curr_rd_port)))
-               return -1;
-
-       /* We are now handling the SDIO data ports */
-       card->mp_rd_bitmap &= (u32)(~(1 << card->curr_rd_port));
-       *port = card->curr_rd_port;
-
-       if (++card->curr_rd_port == card->max_ports)
-               card->curr_rd_port = reg->start_rd_port;
-
-       mwifiex_dbg(adapter, DATA,
-                   "data: port=%d mp_rd_bitmap=0x%08x -> 0x%08x\n",
-                   *port, rd_bitmap, card->mp_rd_bitmap);
-
-       return 0;
-}
-
-/*
- * This function gets the write port for data.
- *
- * The current write port is returned if available and the value is
- * increased (provided it does not reach the maximum limit, in which
- * case it is reset to 1)
- */
-static int mwifiex_get_wr_port_data(struct mwifiex_adapter *adapter, u32 *port)
-{
-       struct sdio_mmc_card *card = adapter->card;
-       const struct mwifiex_sdio_card_reg *reg = card->reg;
-       u32 wr_bitmap = card->mp_wr_bitmap;
-
-       mwifiex_dbg(adapter, DATA,
-                   "data: mp_wr_bitmap=0x%08x\n", wr_bitmap);
-
-       if (!(wr_bitmap & card->mp_data_port_mask)) {
-               adapter->data_sent = true;
-               return -EBUSY;
-       }
-
-       if (card->mp_wr_bitmap & (1 << card->curr_wr_port)) {
-               card->mp_wr_bitmap &= (u32) (~(1 << card->curr_wr_port));
-               *port = card->curr_wr_port;
-               if (++card->curr_wr_port == card->mp_end_port)
-                       card->curr_wr_port = reg->start_wr_port;
-       } else {
-               adapter->data_sent = true;
-               return -EBUSY;
-       }
-
-       if ((card->has_control_mask) && (*port == CTRL_PORT)) {
-               mwifiex_dbg(adapter, ERROR,
-                           "invalid data port=%d cur port=%d mp_wr_bitmap=0x%08x -> 0x%08x\n",
-                           *port, card->curr_wr_port, wr_bitmap,
-                           card->mp_wr_bitmap);
-               return -1;
-       }
-
-       mwifiex_dbg(adapter, DATA,
-                   "data: port=%d mp_wr_bitmap=0x%08x -> 0x%08x\n",
-                   *port, wr_bitmap, card->mp_wr_bitmap);
-
-       return 0;
-}
-
-/*
- * This function polls the card status.
- */
-static int
-mwifiex_sdio_poll_card_status(struct mwifiex_adapter *adapter, u8 bits)
-{
-       struct sdio_mmc_card *card = adapter->card;
-       u32 tries;
-       u8 cs;
-
-       for (tries = 0; tries < MAX_POLL_TRIES; tries++) {
-               if (mwifiex_read_reg(adapter, card->reg->poll_reg, &cs))
-                       break;
-               else if ((cs & bits) == bits)
-                       return 0;
-
-               usleep_range(10, 20);
-       }
-
-       mwifiex_dbg(adapter, ERROR,
-                   "poll card status failed, tries = %d\n", tries);
-
-       return -1;
-}
-
-/*
- * This function reads the firmware status.
- */
-static int
-mwifiex_sdio_read_fw_status(struct mwifiex_adapter *adapter, u16 *dat)
-{
-       struct sdio_mmc_card *card = adapter->card;
-       const struct mwifiex_sdio_card_reg *reg = card->reg;
-       u8 fws0, fws1;
-
-       if (mwifiex_read_reg(adapter, reg->status_reg_0, &fws0))
-               return -1;
-
-       if (mwifiex_read_reg(adapter, reg->status_reg_1, &fws1))
-               return -1;
-
-       *dat = (u16) ((fws1 << 8) | fws0);
-
-       return 0;
-}
-
-/*
- * This function disables the host interrupt.
- *
- * The host interrupt mask is read, the disable bit is reset and
- * written back to the card host interrupt mask register.
- */
-static void mwifiex_sdio_disable_host_int(struct mwifiex_adapter *adapter)
-{
-       struct sdio_mmc_card *card = adapter->card;
-       struct sdio_func *func = card->func;
-
-       sdio_claim_host(func);
-       mwifiex_write_reg_locked(func, card->reg->host_int_mask_reg, 0);
-       sdio_release_irq(func);
-       sdio_release_host(func);
-}
-
-/*
- * This function reads the interrupt status from card.
- */
-static void mwifiex_interrupt_status(struct mwifiex_adapter *adapter)
-{
-       struct sdio_mmc_card *card = adapter->card;
-       u8 sdio_ireg;
-       unsigned long flags;
-
-       if (mwifiex_read_data_sync(adapter, card->mp_regs,
-                                  card->reg->max_mp_regs,
-                                  REG_PORT | MWIFIEX_SDIO_BYTE_MODE_MASK, 0)) {
-               mwifiex_dbg(adapter, ERROR, "read mp_regs failed\n");
-               return;
-       }
-
-       sdio_ireg = card->mp_regs[card->reg->host_int_status_reg];
-       if (sdio_ireg) {
-               /*
-                * DN_LD_HOST_INT_STATUS and/or UP_LD_HOST_INT_STATUS
-                * For SDIO new mode CMD port interrupts
-                *      DN_LD_CMD_PORT_HOST_INT_STATUS and/or
-                *      UP_LD_CMD_PORT_HOST_INT_STATUS
-                * Clear the interrupt status register
-                */
-               mwifiex_dbg(adapter, INTR,
-                           "int: sdio_ireg = %#x\n", sdio_ireg);
-               spin_lock_irqsave(&adapter->int_lock, flags);
-               adapter->int_status |= sdio_ireg;
-               spin_unlock_irqrestore(&adapter->int_lock, flags);
-       }
-}
-
-/*
- * SDIO interrupt handler.
- *
- * This function reads the interrupt status from firmware and handles
- * the interrupt in current thread (ksdioirqd) right away.
- */
-static void
-mwifiex_sdio_interrupt(struct sdio_func *func)
-{
-       struct mwifiex_adapter *adapter;
-       struct sdio_mmc_card *card;
-
-       card = sdio_get_drvdata(func);
-       if (!card || !card->adapter) {
-               pr_debug("int: func=%p card=%p adapter=%p\n",
-                        func, card, card ? card->adapter : NULL);
-               return;
-       }
-       adapter = card->adapter;
-
-       if (!adapter->pps_uapsd_mode && adapter->ps_state == PS_STATE_SLEEP)
-               adapter->ps_state = PS_STATE_AWAKE;
-
-       mwifiex_interrupt_status(adapter);
-       mwifiex_main_process(adapter);
-}
-
-/*
- * This function enables the host interrupt.
- *
- * The host interrupt enable mask is written to the card
- * host interrupt mask register.
- */
-static int mwifiex_sdio_enable_host_int(struct mwifiex_adapter *adapter)
-{
-       struct sdio_mmc_card *card = adapter->card;
-       struct sdio_func *func = card->func;
-       int ret;
-
-       sdio_claim_host(func);
-
-       /* Request the SDIO IRQ */
-       ret = sdio_claim_irq(func, mwifiex_sdio_interrupt);
-       if (ret) {
-               mwifiex_dbg(adapter, ERROR,
-                           "claim irq failed: ret=%d\n", ret);
-               goto out;
-       }
-
-       /* Simply write the mask to the register */
-       ret = mwifiex_write_reg_locked(func, card->reg->host_int_mask_reg,
-                                      card->reg->host_int_enable);
-       if (ret) {
-               mwifiex_dbg(adapter, ERROR,
-                           "enable host interrupt failed\n");
-               sdio_release_irq(func);
-       }
-
-out:
-       sdio_release_host(func);
-       return ret;
-}
-
-/*
- * This function sends a data buffer to the card.
- */
-static int mwifiex_sdio_card_to_host(struct mwifiex_adapter *adapter,
-                                    u32 *type, u8 *buffer,
-                                    u32 npayload, u32 ioport)
-{
-       int ret;
-       u32 nb;
-
-       if (!buffer) {
-               mwifiex_dbg(adapter, ERROR,
-                           "%s: buffer is NULL\n", __func__);
-               return -1;
-       }
-
-       ret = mwifiex_read_data_sync(adapter, buffer, npayload, ioport, 1);
-
-       if (ret) {
-               mwifiex_dbg(adapter, ERROR,
-                           "%s: read iomem failed: %d\n", __func__,
-                       ret);
-               return -1;
-       }
-
-       nb = le16_to_cpu(*(__le16 *) (buffer));
-       if (nb > npayload) {
-               mwifiex_dbg(adapter, ERROR,
-                           "%s: invalid packet, nb=%d npayload=%d\n",
-                           __func__, nb, npayload);
-               return -1;
-       }
-
-       *type = le16_to_cpu(*(__le16 *) (buffer + 2));
-
-       return ret;
-}
-
-/*
- * This function downloads the firmware to the card.
- *
- * Firmware is downloaded to the card in blocks. Every block download
- * is tested for CRC errors, and retried a number of times before
- * returning failure.
- */
-static int mwifiex_prog_fw_w_helper(struct mwifiex_adapter *adapter,
-                                   struct mwifiex_fw_image *fw)
-{
-       struct sdio_mmc_card *card = adapter->card;
-       const struct mwifiex_sdio_card_reg *reg = card->reg;
-       int ret;
-       u8 *firmware = fw->fw_buf;
-       u32 firmware_len = fw->fw_len;
-       u32 offset = 0;
-       u8 base0, base1;
-       u8 *fwbuf;
-       u16 len = 0;
-       u32 txlen, tx_blocks = 0, tries;
-       u32 i = 0;
-
-       if (!firmware_len) {
-               mwifiex_dbg(adapter, ERROR,
-                           "firmware image not found! Terminating download\n");
-               return -1;
-       }
-
-       mwifiex_dbg(adapter, INFO,
-                   "info: downloading FW image (%d bytes)\n",
-                   firmware_len);
-
-       /* Assume that the allocated buffer is 8-byte aligned */
-       fwbuf = kzalloc(MWIFIEX_UPLD_SIZE, GFP_KERNEL);
-       if (!fwbuf)
-               return -ENOMEM;
-
-       sdio_claim_host(card->func);
-
-       /* Perform firmware data transfer */
-       do {
-               /* The host polls for the DN_LD_CARD_RDY and CARD_IO_READY
-                  bits */
-               ret = mwifiex_sdio_poll_card_status(adapter, CARD_IO_READY |
-                                                   DN_LD_CARD_RDY);
-               if (ret) {
-                       mwifiex_dbg(adapter, ERROR,
-                                   "FW download with helper:\t"
-                                   "poll status timeout @ %d\n", offset);
-                       goto done;
-               }
-
-               /* More data? */
-               if (offset >= firmware_len)
-                       break;
-
-               for (tries = 0; tries < MAX_POLL_TRIES; tries++) {
-                       ret = mwifiex_read_reg(adapter, reg->base_0_reg,
-                                              &base0);
-                       if (ret) {
-                               mwifiex_dbg(adapter, ERROR,
-                                           "dev BASE0 register read failed:\t"
-                                           "base0=%#04X(%d). Terminating dnld\n",
-                                           base0, base0);
-                               goto done;
-                       }
-                       ret = mwifiex_read_reg(adapter, reg->base_1_reg,
-                                              &base1);
-                       if (ret) {
-                               mwifiex_dbg(adapter, ERROR,
-                                           "dev BASE1 register read failed:\t"
-                                           "base1=%#04X(%d). Terminating dnld\n",
-                                           base1, base1);
-                               goto done;
-                       }
-                       len = (u16) (((base1 & 0xff) << 8) | (base0 & 0xff));
-
-                       if (len)
-                               break;
-
-                       usleep_range(10, 20);
-               }
-
-               if (!len) {
-                       break;
-               } else if (len > MWIFIEX_UPLD_SIZE) {
-                       mwifiex_dbg(adapter, ERROR,
-                                   "FW dnld failed @ %d, invalid length %d\n",
-                                   offset, len);
-                       ret = -1;
-                       goto done;
-               }
-
-               txlen = len;
-
-               if (len & BIT(0)) {
-                       i++;
-                       if (i > MAX_WRITE_IOMEM_RETRY) {
-                               mwifiex_dbg(adapter, ERROR,
-                                           "FW dnld failed @ %d, over max retry\n",
-                                           offset);
-                               ret = -1;
-                               goto done;
-                       }
-                       mwifiex_dbg(adapter, ERROR,
-                                   "CRC indicated by the helper:\t"
-                                   "len = 0x%04X, txlen = %d\n", len, txlen);
-                       len &= ~BIT(0);
-                       /* Setting this to 0 to resend from same offset */
-                       txlen = 0;
-               } else {
-                       i = 0;
-
-                       /* Set blocksize to transfer - checking for last
-                          block */
-                       if (firmware_len - offset < txlen)
-                               txlen = firmware_len - offset;
-
-                       tx_blocks = (txlen + MWIFIEX_SDIO_BLOCK_SIZE - 1)
-                                   / MWIFIEX_SDIO_BLOCK_SIZE;
-
-                       /* Copy payload to buffer */
-                       memmove(fwbuf, &firmware[offset], txlen);
-               }
-
-               ret = mwifiex_write_data_sync(adapter, fwbuf, tx_blocks *
-                                             MWIFIEX_SDIO_BLOCK_SIZE,
-                                             adapter->ioport);
-               if (ret) {
-                       mwifiex_dbg(adapter, ERROR,
-                                   "FW download, write iomem (%d) failed @ %d\n",
-                                   i, offset);
-                       if (mwifiex_write_reg(adapter, CONFIGURATION_REG, 0x04))
-                               mwifiex_dbg(adapter, ERROR,
-                                           "write CFG reg failed\n");
-
-                       ret = -1;
-                       goto done;
-               }
-
-               offset += txlen;
-       } while (true);
-
-       sdio_release_host(card->func);
-
-       mwifiex_dbg(adapter, MSG,
-                   "info: FW download over, size %d bytes\n", offset);
-
-       ret = 0;
-done:
-       kfree(fwbuf);
-       return ret;
-}
-
-/*
- * This function checks the firmware status in card.
- *
- * The winner interface is also determined by this function.
- */
-static int mwifiex_check_fw_status(struct mwifiex_adapter *adapter,
-                                  u32 poll_num)
-{
-       struct sdio_mmc_card *card = adapter->card;
-       int ret = 0;
-       u16 firmware_stat;
-       u32 tries;
-       u8 winner_status;
-
-       /* Wait for firmware initialization event */
-       for (tries = 0; tries < poll_num; tries++) {
-               ret = mwifiex_sdio_read_fw_status(adapter, &firmware_stat);
-               if (ret)
-                       continue;
-               if (firmware_stat == FIRMWARE_READY_SDIO) {
-                       ret = 0;
-                       break;
-               } else {
-                       msleep(100);
-                       ret = -1;
-               }
-       }
-
-       if (ret) {
-               if (mwifiex_read_reg
-                   (adapter, card->reg->status_reg_0, &winner_status))
-                       winner_status = 0;
-
-               if (winner_status)
-                       adapter->winner = 0;
-               else
-                       adapter->winner = 1;
-       }
-       return ret;
-}
-
-/*
- * This function decode sdio aggreation pkt.
- *
- * Based on the the data block size and pkt_len,
- * skb data will be decoded to few packets.
- */
-static void mwifiex_deaggr_sdio_pkt(struct mwifiex_adapter *adapter,
-                                   struct sk_buff *skb)
-{
-       u32 total_pkt_len, pkt_len;
-       struct sk_buff *skb_deaggr;
-       u32 pkt_type;
-       u16 blk_size;
-       u8 blk_num;
-       u8 *data;
-
-       data = skb->data;
-       total_pkt_len = skb->len;
-
-       while (total_pkt_len >= (SDIO_HEADER_OFFSET + INTF_HEADER_LEN)) {
-               if (total_pkt_len < adapter->sdio_rx_block_size)
-                       break;
-               blk_num = *(data + BLOCK_NUMBER_OFFSET);
-               blk_size = adapter->sdio_rx_block_size * blk_num;
-               if (blk_size > total_pkt_len) {
-                       mwifiex_dbg(adapter, ERROR,
-                                   "%s: error in blk_size,\t"
-                                   "blk_num=%d, blk_size=%d, total_pkt_len=%d\n",
-                                   __func__, blk_num, blk_size, total_pkt_len);
-                       break;
-               }
-               pkt_len = le16_to_cpu(*(__le16 *)(data + SDIO_HEADER_OFFSET));
-               pkt_type = le16_to_cpu(*(__le16 *)(data + SDIO_HEADER_OFFSET +
-                                        2));
-               if ((pkt_len + SDIO_HEADER_OFFSET) > blk_size) {
-                       mwifiex_dbg(adapter, ERROR,
-                                   "%s: error in pkt_len,\t"
-                                   "pkt_len=%d, blk_size=%d\n",
-                                   __func__, pkt_len, blk_size);
-                       break;
-               }
-               skb_deaggr = mwifiex_alloc_dma_align_buf(pkt_len,
-                                                        GFP_KERNEL | GFP_DMA);
-               if (!skb_deaggr)
-                       break;
-               skb_put(skb_deaggr, pkt_len);
-               memcpy(skb_deaggr->data, data + SDIO_HEADER_OFFSET, pkt_len);
-               skb_pull(skb_deaggr, INTF_HEADER_LEN);
-
-               mwifiex_handle_rx_packet(adapter, skb_deaggr);
-               data += blk_size;
-               total_pkt_len -= blk_size;
-       }
-}
-
-/*
- * This function decodes a received packet.
- *
- * Based on the type, the packet is treated as either a data, or
- * a command response, or an event, and the correct handler
- * function is invoked.
- */
-static int mwifiex_decode_rx_packet(struct mwifiex_adapter *adapter,
-                                   struct sk_buff *skb, u32 upld_typ)
-{
-       u8 *cmd_buf;
-       __le16 *curr_ptr = (__le16 *)skb->data;
-       u16 pkt_len = le16_to_cpu(*curr_ptr);
-       struct mwifiex_rxinfo *rx_info;
-
-       if (upld_typ != MWIFIEX_TYPE_AGGR_DATA) {
-               skb_trim(skb, pkt_len);
-               skb_pull(skb, INTF_HEADER_LEN);
-       }
-
-       switch (upld_typ) {
-       case MWIFIEX_TYPE_AGGR_DATA:
-               mwifiex_dbg(adapter, INFO,
-                           "info: --- Rx: Aggr Data packet ---\n");
-               rx_info = MWIFIEX_SKB_RXCB(skb);
-               rx_info->buf_type = MWIFIEX_TYPE_AGGR_DATA;
-               if (adapter->rx_work_enabled) {
-                       skb_queue_tail(&adapter->rx_data_q, skb);
-                       atomic_inc(&adapter->rx_pending);
-                       adapter->data_received = true;
-               } else {
-                       mwifiex_deaggr_sdio_pkt(adapter, skb);
-                       dev_kfree_skb_any(skb);
-               }
-               break;
-
-       case MWIFIEX_TYPE_DATA:
-               mwifiex_dbg(adapter, DATA,
-                           "info: --- Rx: Data packet ---\n");
-               if (adapter->rx_work_enabled) {
-                       skb_queue_tail(&adapter->rx_data_q, skb);
-                       adapter->data_received = true;
-                       atomic_inc(&adapter->rx_pending);
-               } else {
-                       mwifiex_handle_rx_packet(adapter, skb);
-               }
-               break;
-
-       case MWIFIEX_TYPE_CMD:
-               mwifiex_dbg(adapter, CMD,
-                           "info: --- Rx: Cmd Response ---\n");
-               /* take care of curr_cmd = NULL case */
-               if (!adapter->curr_cmd) {
-                       cmd_buf = adapter->upld_buf;
-
-                       if (adapter->ps_state == PS_STATE_SLEEP_CFM)
-                               mwifiex_process_sleep_confirm_resp(adapter,
-                                                                  skb->data,
-                                                                  skb->len);
-
-                       memcpy(cmd_buf, skb->data,
-                              min_t(u32, MWIFIEX_SIZE_OF_CMD_BUFFER,
-                                    skb->len));
-
-                       dev_kfree_skb_any(skb);
-               } else {
-                       adapter->cmd_resp_received = true;
-                       adapter->curr_cmd->resp_skb = skb;
-               }
-               break;
-
-       case MWIFIEX_TYPE_EVENT:
-               mwifiex_dbg(adapter, EVENT,
-                           "info: --- Rx: Event ---\n");
-               adapter->event_cause = le32_to_cpu(*(__le32 *) skb->data);
-
-               if ((skb->len > 0) && (skb->len  < MAX_EVENT_SIZE))
-                       memcpy(adapter->event_body,
-                              skb->data + MWIFIEX_EVENT_HEADER_LEN,
-                              skb->len);
-
-               /* event cause has been saved to adapter->event_cause */
-               adapter->event_received = true;
-               adapter->event_skb = skb;
-
-               break;
-
-       default:
-               mwifiex_dbg(adapter, ERROR,
-                           "unknown upload type %#x\n", upld_typ);
-               dev_kfree_skb_any(skb);
-               break;
-       }
-
-       return 0;
-}
-
-/*
- * This function transfers received packets from card to driver, performing
- * aggregation if required.
- *
- * For data received on control port, or if aggregation is disabled, the
- * received buffers are uploaded as separate packets. However, if aggregation
- * is enabled and required, the buffers are copied onto an aggregation buffer,
- * provided there is space left, processed and finally uploaded.
- */
-static int mwifiex_sdio_card_to_host_mp_aggr(struct mwifiex_adapter *adapter,
-                                            u16 rx_len, u8 port)
-{
-       struct sdio_mmc_card *card = adapter->card;
-       s32 f_do_rx_aggr = 0;
-       s32 f_do_rx_cur = 0;
-       s32 f_aggr_cur = 0;
-       s32 f_post_aggr_cur = 0;
-       struct sk_buff *skb_deaggr;
-       struct sk_buff *skb = NULL;
-       u32 pkt_len, pkt_type, mport, pind;
-       u8 *curr_ptr;
-
-       if ((card->has_control_mask) && (port == CTRL_PORT)) {
-               /* Read the command Resp without aggr */
-               mwifiex_dbg(adapter, CMD,
-                           "info: %s: no aggregation for cmd\t"
-                           "response\n", __func__);
-
-               f_do_rx_cur = 1;
-               goto rx_curr_single;
-       }
-
-       if (!card->mpa_rx.enabled) {
-               mwifiex_dbg(adapter, WARN,
-                           "info: %s: rx aggregation disabled\n",
-                           __func__);
-
-               f_do_rx_cur = 1;
-               goto rx_curr_single;
-       }
-
-       if ((!card->has_control_mask && (card->mp_rd_bitmap &
-                                        card->reg->data_port_mask)) ||
-           (card->has_control_mask && (card->mp_rd_bitmap &
-                                       (~((u32) CTRL_PORT_MASK))))) {
-               /* Some more data RX pending */
-               mwifiex_dbg(adapter, INFO,
-                           "info: %s: not last packet\n", __func__);
-
-               if (MP_RX_AGGR_IN_PROGRESS(card)) {
-                       if (MP_RX_AGGR_BUF_HAS_ROOM(card, rx_len)) {
-                               f_aggr_cur = 1;
-                       } else {
-                               /* No room in Aggr buf, do rx aggr now */
-                               f_do_rx_aggr = 1;
-                               f_post_aggr_cur = 1;
-                       }
-               } else {
-                       /* Rx aggr not in progress */
-                       f_aggr_cur = 1;
-               }
-
-       } else {
-               /* No more data RX pending */
-               mwifiex_dbg(adapter, INFO,
-                           "info: %s: last packet\n", __func__);
-
-               if (MP_RX_AGGR_IN_PROGRESS(card)) {
-                       f_do_rx_aggr = 1;
-                       if (MP_RX_AGGR_BUF_HAS_ROOM(card, rx_len))
-                               f_aggr_cur = 1;
-                       else
-                               /* No room in Aggr buf, do rx aggr now */
-                               f_do_rx_cur = 1;
-               } else {
-                       f_do_rx_cur = 1;
-               }
-       }
-
-       if (f_aggr_cur) {
-               mwifiex_dbg(adapter, INFO,
-                           "info: current packet aggregation\n");
-               /* Curr pkt can be aggregated */
-               mp_rx_aggr_setup(card, rx_len, port);
-
-               if (MP_RX_AGGR_PKT_LIMIT_REACHED(card) ||
-                   mp_rx_aggr_port_limit_reached(card)) {
-                       mwifiex_dbg(adapter, INFO,
-                                   "info: %s: aggregated packet\t"
-                                   "limit reached\n", __func__);
-                       /* No more pkts allowed in Aggr buf, rx it */
-                       f_do_rx_aggr = 1;
-               }
-       }
-
-       if (f_do_rx_aggr) {
-               /* do aggr RX now */
-               mwifiex_dbg(adapter, DATA,
-                           "info: do_rx_aggr: num of packets: %d\n",
-                           card->mpa_rx.pkt_cnt);
-
-               if (card->supports_sdio_new_mode) {
-                       int i;
-                       u32 port_count;
-
-                       for (i = 0, port_count = 0; i < card->max_ports; i++)
-                               if (card->mpa_rx.ports & BIT(i))
-                                       port_count++;
-
-                       /* Reading data from "start_port + 0" to "start_port +
-                        * port_count -1", so decrease the count by 1
-                        */
-                       port_count--;
-                       mport = (adapter->ioport | SDIO_MPA_ADDR_BASE |
-                                (port_count << 8)) + card->mpa_rx.start_port;
-               } else {
-                       mport = (adapter->ioport | SDIO_MPA_ADDR_BASE |
-                                (card->mpa_rx.ports << 4)) +
-                                card->mpa_rx.start_port;
-               }
-
-               if (mwifiex_read_data_sync(adapter, card->mpa_rx.buf,
-                                          card->mpa_rx.buf_len, mport, 1))
-                       goto error;
-
-               curr_ptr = card->mpa_rx.buf;
-
-               for (pind = 0; pind < card->mpa_rx.pkt_cnt; pind++) {
-                       u32 *len_arr = card->mpa_rx.len_arr;
-
-                       /* get curr PKT len & type */
-                       pkt_len = le16_to_cpu(*(__le16 *) &curr_ptr[0]);
-                       pkt_type = le16_to_cpu(*(__le16 *) &curr_ptr[2]);
-
-                       /* copy pkt to deaggr buf */
-                       skb_deaggr = mwifiex_alloc_dma_align_buf(len_arr[pind],
-                                                                GFP_KERNEL |
-                                                                GFP_DMA);
-                       if (!skb_deaggr) {
-                               mwifiex_dbg(adapter, ERROR, "skb allocation failure\t"
-                                           "drop pkt len=%d type=%d\n",
-                                           pkt_len, pkt_type);
-                               curr_ptr += len_arr[pind];
-                               continue;
-                       }
-
-                       skb_put(skb_deaggr, len_arr[pind]);
-
-                       if ((pkt_type == MWIFIEX_TYPE_DATA ||
-                            (pkt_type == MWIFIEX_TYPE_AGGR_DATA &&
-                             adapter->sdio_rx_aggr_enable)) &&
-                           (pkt_len <= len_arr[pind])) {
-
-                               memcpy(skb_deaggr->data, curr_ptr, pkt_len);
-
-                               skb_trim(skb_deaggr, pkt_len);
-
-                               /* Process de-aggr packet */
-                               mwifiex_decode_rx_packet(adapter, skb_deaggr,
-                                                        pkt_type);
-                       } else {
-                               mwifiex_dbg(adapter, ERROR,
-                                           "drop wrong aggr pkt:\t"
-                                           "sdio_single_port_rx_aggr=%d\t"
-                                           "type=%d len=%d max_len=%d\n",
-                                           adapter->sdio_rx_aggr_enable,
-                                           pkt_type, pkt_len, len_arr[pind]);
-                               dev_kfree_skb_any(skb_deaggr);
-                       }
-                       curr_ptr += len_arr[pind];
-               }
-               MP_RX_AGGR_BUF_RESET(card);
-       }
-
-rx_curr_single:
-       if (f_do_rx_cur) {
-               mwifiex_dbg(adapter, INFO, "info: RX: port: %d, rx_len: %d\n",
-                           port, rx_len);
-
-               skb = mwifiex_alloc_dma_align_buf(rx_len, GFP_KERNEL | GFP_DMA);
-               if (!skb) {
-                       mwifiex_dbg(adapter, ERROR,
-                                   "single skb allocated fail,\t"
-                                   "drop pkt port=%d len=%d\n", port, rx_len);
-                       if (mwifiex_sdio_card_to_host(adapter, &pkt_type,
-                                                     card->mpa_rx.buf, rx_len,
-                                                     adapter->ioport + port))
-                               goto error;
-                       return 0;
-               }
-
-               skb_put(skb, rx_len);
-
-               if (mwifiex_sdio_card_to_host(adapter, &pkt_type,
-                                             skb->data, skb->len,
-                                             adapter->ioport + port))
-                       goto error;
-               if (!adapter->sdio_rx_aggr_enable &&
-                   pkt_type == MWIFIEX_TYPE_AGGR_DATA) {
-                       mwifiex_dbg(adapter, ERROR, "drop wrong pkt type %d\t"
-                                   "current SDIO RX Aggr not enabled\n",
-                                   pkt_type);
-                       dev_kfree_skb_any(skb);
-                       return 0;
-               }
-
-               mwifiex_decode_rx_packet(adapter, skb, pkt_type);
-       }
-       if (f_post_aggr_cur) {
-               mwifiex_dbg(adapter, INFO,
-                           "info: current packet aggregation\n");
-               /* Curr pkt can be aggregated */
-               mp_rx_aggr_setup(card, rx_len, port);
-       }
-
-       return 0;
-error:
-       if (MP_RX_AGGR_IN_PROGRESS(card))
-               MP_RX_AGGR_BUF_RESET(card);
-
-       if (f_do_rx_cur && skb)
-               /* Single transfer pending. Free curr buff also */
-               dev_kfree_skb_any(skb);
-
-       return -1;
-}
-
-/*
- * This function checks the current interrupt status.
- *
- * The following interrupts are checked and handled by this function -
- *      - Data sent
- *      - Command sent
- *      - Packets received
- *
- * Since the firmware does not generate download ready interrupt if the
- * port updated is command port only, command sent interrupt checking
- * should be done manually, and for every SDIO interrupt.
- *
- * In case of Rx packets received, the packets are uploaded from card to
- * host and processed accordingly.
- */
-static int mwifiex_process_int_status(struct mwifiex_adapter *adapter)
-{
-       struct sdio_mmc_card *card = adapter->card;
-       const struct mwifiex_sdio_card_reg *reg = card->reg;
-       int ret = 0;
-       u8 sdio_ireg;
-       struct sk_buff *skb;
-       u8 port = CTRL_PORT;
-       u32 len_reg_l, len_reg_u;
-       u32 rx_blocks;
-       u16 rx_len;
-       unsigned long flags;
-       u32 bitmap;
-       u8 cr;
-
-       spin_lock_irqsave(&adapter->int_lock, flags);
-       sdio_ireg = adapter->int_status;
-       adapter->int_status = 0;
-       spin_unlock_irqrestore(&adapter->int_lock, flags);
-
-       if (!sdio_ireg)
-               return ret;
-
-       /* Following interrupt is only for SDIO new mode */
-       if (sdio_ireg & DN_LD_CMD_PORT_HOST_INT_STATUS && adapter->cmd_sent)
-               adapter->cmd_sent = false;
-
-       /* Following interrupt is only for SDIO new mode */
-       if (sdio_ireg & UP_LD_CMD_PORT_HOST_INT_STATUS) {
-               u32 pkt_type;
-
-               /* read the len of control packet */
-               rx_len = card->mp_regs[reg->cmd_rd_len_1] << 8;
-               rx_len |= (u16)card->mp_regs[reg->cmd_rd_len_0];
-               rx_blocks = DIV_ROUND_UP(rx_len, MWIFIEX_SDIO_BLOCK_SIZE);
-               if (rx_len <= INTF_HEADER_LEN ||
-                   (rx_blocks * MWIFIEX_SDIO_BLOCK_SIZE) >
-                    MWIFIEX_RX_DATA_BUF_SIZE)
-                       return -1;
-               rx_len = (u16) (rx_blocks * MWIFIEX_SDIO_BLOCK_SIZE);
-               mwifiex_dbg(adapter, INFO, "info: rx_len = %d\n", rx_len);
-
-               skb = mwifiex_alloc_dma_align_buf(rx_len, GFP_KERNEL | GFP_DMA);
-               if (!skb)
-                       return -1;
-
-               skb_put(skb, rx_len);
-
-               if (mwifiex_sdio_card_to_host(adapter, &pkt_type, skb->data,
-                                             skb->len, adapter->ioport |
-                                                       CMD_PORT_SLCT)) {
-                       mwifiex_dbg(adapter, ERROR,
-                                   "%s: failed to card_to_host", __func__);
-                       dev_kfree_skb_any(skb);
-                       goto term_cmd;
-               }
-
-               if ((pkt_type != MWIFIEX_TYPE_CMD) &&
-                   (pkt_type != MWIFIEX_TYPE_EVENT))
-                       mwifiex_dbg(adapter, ERROR,
-                                   "%s:Received wrong packet on cmd port",
-                                   __func__);
-
-               mwifiex_decode_rx_packet(adapter, skb, pkt_type);
-       }
-
-       if (sdio_ireg & DN_LD_HOST_INT_STATUS) {
-               bitmap = (u32) card->mp_regs[reg->wr_bitmap_l];
-               bitmap |= ((u32) card->mp_regs[reg->wr_bitmap_u]) << 8;
-               if (card->supports_sdio_new_mode) {
-                       bitmap |=
-                               ((u32) card->mp_regs[reg->wr_bitmap_1l]) << 16;
-                       bitmap |=
-                               ((u32) card->mp_regs[reg->wr_bitmap_1u]) << 24;
-               }
-               card->mp_wr_bitmap = bitmap;
-
-               mwifiex_dbg(adapter, INTR,
-                           "int: DNLD: wr_bitmap=0x%x\n",
-                           card->mp_wr_bitmap);
-               if (adapter->data_sent &&
-                   (card->mp_wr_bitmap & card->mp_data_port_mask)) {
-                       mwifiex_dbg(adapter, INTR,
-                                   "info:  <--- Tx DONE Interrupt --->\n");
-                       adapter->data_sent = false;
-               }
-       }
-
-       /* As firmware will not generate download ready interrupt if the port
-          updated is command port only, cmd_sent should be done for any SDIO
-          interrupt. */
-       if (card->has_control_mask && adapter->cmd_sent) {
-               /* Check if firmware has attach buffer at command port and
-                  update just that in wr_bit_map. */
-               card->mp_wr_bitmap |=
-                       (u32) card->mp_regs[reg->wr_bitmap_l] & CTRL_PORT_MASK;
-               if (card->mp_wr_bitmap & CTRL_PORT_MASK)
-                       adapter->cmd_sent = false;
-       }
-
-       mwifiex_dbg(adapter, INTR, "info: cmd_sent=%d data_sent=%d\n",
-                   adapter->cmd_sent, adapter->data_sent);
-       if (sdio_ireg & UP_LD_HOST_INT_STATUS) {
-               bitmap = (u32) card->mp_regs[reg->rd_bitmap_l];
-               bitmap |= ((u32) card->mp_regs[reg->rd_bitmap_u]) << 8;
-               if (card->supports_sdio_new_mode) {
-                       bitmap |=
-                               ((u32) card->mp_regs[reg->rd_bitmap_1l]) << 16;
-                       bitmap |=
-                               ((u32) card->mp_regs[reg->rd_bitmap_1u]) << 24;
-               }
-               card->mp_rd_bitmap = bitmap;
-               mwifiex_dbg(adapter, INTR,
-                           "int: UPLD: rd_bitmap=0x%x\n",
-                           card->mp_rd_bitmap);
-
-               while (true) {
-                       ret = mwifiex_get_rd_port(adapter, &port);
-                       if (ret) {
-                               mwifiex_dbg(adapter, INFO,
-                                           "info: no more rd_port available\n");
-                               break;
-                       }
-                       len_reg_l = reg->rd_len_p0_l + (port << 1);
-                       len_reg_u = reg->rd_len_p0_u + (port << 1);
-                       rx_len = ((u16) card->mp_regs[len_reg_u]) << 8;
-                       rx_len |= (u16) card->mp_regs[len_reg_l];
-                       mwifiex_dbg(adapter, INFO,
-                                   "info: RX: port=%d rx_len=%u\n",
-                                   port, rx_len);
-                       rx_blocks =
-                               (rx_len + MWIFIEX_SDIO_BLOCK_SIZE -
-                                1) / MWIFIEX_SDIO_BLOCK_SIZE;
-                       if (rx_len <= INTF_HEADER_LEN ||
-                           (card->mpa_rx.enabled &&
-                            ((rx_blocks * MWIFIEX_SDIO_BLOCK_SIZE) >
-                             card->mpa_rx.buf_size))) {
-                               mwifiex_dbg(adapter, ERROR,
-                                           "invalid rx_len=%d\n",
-                                           rx_len);
-                               return -1;
-                       }
-
-                       rx_len = (u16) (rx_blocks * MWIFIEX_SDIO_BLOCK_SIZE);
-                       mwifiex_dbg(adapter, INFO, "info: rx_len = %d\n",
-                                   rx_len);
-
-                       if (mwifiex_sdio_card_to_host_mp_aggr(adapter, rx_len,
-                                                             port)) {
-                               mwifiex_dbg(adapter, ERROR,
-                                           "card_to_host_mpa failed: int status=%#x\n",
-                                           sdio_ireg);
-                               goto term_cmd;
-                       }
-               }
-       }
-
-       return 0;
-
-term_cmd:
-       /* terminate cmd */
-       if (mwifiex_read_reg(adapter, CONFIGURATION_REG, &cr))
-               mwifiex_dbg(adapter, ERROR, "read CFG reg failed\n");
-       else
-               mwifiex_dbg(adapter, INFO,
-                           "info: CFG reg val = %d\n", cr);
-
-       if (mwifiex_write_reg(adapter, CONFIGURATION_REG, (cr | 0x04)))
-               mwifiex_dbg(adapter, ERROR,
-                           "write CFG reg failed\n");
-       else
-               mwifiex_dbg(adapter, INFO, "info: write success\n");
-
-       if (mwifiex_read_reg(adapter, CONFIGURATION_REG, &cr))
-               mwifiex_dbg(adapter, ERROR,
-                           "read CFG reg failed\n");
-       else
-               mwifiex_dbg(adapter, INFO,
-                           "info: CFG reg val =%x\n", cr);
-
-       return -1;
-}
-
-/*
- * This function aggregates transmission buffers in driver and downloads
- * the aggregated packet to card.
- *
- * The individual packets are aggregated by copying into an aggregation
- * buffer and then downloaded to the card. Previous unsent packets in the
- * aggregation buffer are pre-copied first before new packets are added.
- * Aggregation is done till there is space left in the aggregation buffer,
- * or till new packets are available.
- *
- * The function will only download the packet to the card when aggregation
- * stops, otherwise it will just aggregate the packet in aggregation buffer
- * and return.
- */
-static int mwifiex_host_to_card_mp_aggr(struct mwifiex_adapter *adapter,
-                                       u8 *payload, u32 pkt_len, u32 port,
-                                       u32 next_pkt_len)
-{
-       struct sdio_mmc_card *card = adapter->card;
-       int ret = 0;
-       s32 f_send_aggr_buf = 0;
-       s32 f_send_cur_buf = 0;
-       s32 f_precopy_cur_buf = 0;
-       s32 f_postcopy_cur_buf = 0;
-       u32 mport;
-
-       if (!card->mpa_tx.enabled ||
-           (card->has_control_mask && (port == CTRL_PORT)) ||
-           (card->supports_sdio_new_mode && (port == CMD_PORT_SLCT))) {
-               mwifiex_dbg(adapter, WARN,
-                           "info: %s: tx aggregation disabled\n",
-                           __func__);
-
-               f_send_cur_buf = 1;
-               goto tx_curr_single;
-       }
-
-       if (next_pkt_len) {
-               /* More pkt in TX queue */
-               mwifiex_dbg(adapter, INFO,
-                           "info: %s: more packets in queue.\n",
-                           __func__);
-
-               if (MP_TX_AGGR_IN_PROGRESS(card)) {
-                       if (MP_TX_AGGR_BUF_HAS_ROOM(card, pkt_len)) {
-                               f_precopy_cur_buf = 1;
-
-                               if (!(card->mp_wr_bitmap &
-                                     (1 << card->curr_wr_port)) ||
-                                   !MP_TX_AGGR_BUF_HAS_ROOM(
-                                           card, pkt_len + next_pkt_len))
-                                       f_send_aggr_buf = 1;
-                       } else {
-                               /* No room in Aggr buf, send it */
-                               f_send_aggr_buf = 1;
-
-                               if (!(card->mp_wr_bitmap &
-                                     (1 << card->curr_wr_port)))
-                                       f_send_cur_buf = 1;
-                               else
-                                       f_postcopy_cur_buf = 1;
-                       }
-               } else {
-                       if (MP_TX_AGGR_BUF_HAS_ROOM(card, pkt_len) &&
-                           (card->mp_wr_bitmap & (1 << card->curr_wr_port)))
-                               f_precopy_cur_buf = 1;
-                       else
-                               f_send_cur_buf = 1;
-               }
-       } else {
-               /* Last pkt in TX queue */
-               mwifiex_dbg(adapter, INFO,
-                           "info: %s: Last packet in Tx Queue.\n",
-                           __func__);
-
-               if (MP_TX_AGGR_IN_PROGRESS(card)) {
-                       /* some packs in Aggr buf already */
-                       f_send_aggr_buf = 1;
-
-                       if (MP_TX_AGGR_BUF_HAS_ROOM(card, pkt_len))
-                               f_precopy_cur_buf = 1;
-                       else
-                               /* No room in Aggr buf, send it */
-                               f_send_cur_buf = 1;
-               } else {
-                       f_send_cur_buf = 1;
-               }
-       }
-
-       if (f_precopy_cur_buf) {
-               mwifiex_dbg(adapter, DATA,
-                           "data: %s: precopy current buffer\n",
-                           __func__);
-               MP_TX_AGGR_BUF_PUT(card, payload, pkt_len, port);
-
-               if (MP_TX_AGGR_PKT_LIMIT_REACHED(card) ||
-                   mp_tx_aggr_port_limit_reached(card))
-                       /* No more pkts allowed in Aggr buf, send it */
-                       f_send_aggr_buf = 1;
-       }
-
-       if (f_send_aggr_buf) {
-               mwifiex_dbg(adapter, DATA,
-                           "data: %s: send aggr buffer: %d %d\n",
-                           __func__, card->mpa_tx.start_port,
-                           card->mpa_tx.ports);
-               if (card->supports_sdio_new_mode) {
-                       u32 port_count;
-                       int i;
-
-                       for (i = 0, port_count = 0; i < card->max_ports; i++)
-                               if (card->mpa_tx.ports & BIT(i))
-                                       port_count++;
-
-                       /* Writing data from "start_port + 0" to "start_port +
-                        * port_count -1", so decrease the count by 1
-                        */
-                       port_count--;
-                       mport = (adapter->ioport | SDIO_MPA_ADDR_BASE |
-                                (port_count << 8)) + card->mpa_tx.start_port;
-               } else {
-                       mport = (adapter->ioport | SDIO_MPA_ADDR_BASE |
-                                (card->mpa_tx.ports << 4)) +
-                                card->mpa_tx.start_port;
-               }
-
-               ret = mwifiex_write_data_to_card(adapter, card->mpa_tx.buf,
-                                                card->mpa_tx.buf_len, mport);
-
-               MP_TX_AGGR_BUF_RESET(card);
-       }
-
-tx_curr_single:
-       if (f_send_cur_buf) {
-               mwifiex_dbg(adapter, DATA,
-                           "data: %s: send current buffer %d\n",
-                           __func__, port);
-               ret = mwifiex_write_data_to_card(adapter, payload, pkt_len,
-                                                adapter->ioport + port);
-       }
-
-       if (f_postcopy_cur_buf) {
-               mwifiex_dbg(adapter, DATA,
-                           "data: %s: postcopy current buffer\n",
-                           __func__);
-               MP_TX_AGGR_BUF_PUT(card, payload, pkt_len, port);
-       }
-
-       return ret;
-}
-
-/*
- * This function downloads data from driver to card.
- *
- * Both commands and data packets are transferred to the card by this
- * function.
- *
- * This function adds the SDIO specific header to the front of the buffer
- * before transferring. The header contains the length of the packet and
- * the type. The firmware handles the packets based upon this set type.
- */
-static int mwifiex_sdio_host_to_card(struct mwifiex_adapter *adapter,
-                                    u8 type, struct sk_buff *skb,
-                                    struct mwifiex_tx_param *tx_param)
-{
-       struct sdio_mmc_card *card = adapter->card;
-       int ret;
-       u32 buf_block_len;
-       u32 blk_size;
-       u32 port = CTRL_PORT;
-       u8 *payload = (u8 *)skb->data;
-       u32 pkt_len = skb->len;
-
-       /* Allocate buffer and copy payload */
-       blk_size = MWIFIEX_SDIO_BLOCK_SIZE;
-       buf_block_len = (pkt_len + blk_size - 1) / blk_size;
-       *(__le16 *)&payload[0] = cpu_to_le16((u16)pkt_len);
-       *(__le16 *)&payload[2] = cpu_to_le16(type);
-
-       /*
-        * This is SDIO specific header
-        *  u16 length,
-        *  u16 type (MWIFIEX_TYPE_DATA = 0, MWIFIEX_TYPE_CMD = 1,
-        *  MWIFIEX_TYPE_EVENT = 3)
-        */
-       if (type == MWIFIEX_TYPE_DATA) {
-               ret = mwifiex_get_wr_port_data(adapter, &port);
-               if (ret) {
-                       mwifiex_dbg(adapter, ERROR,
-                                   "%s: no wr_port available\n",
-                                   __func__);
-                       return ret;
-               }
-       } else {
-               adapter->cmd_sent = true;
-               /* Type must be MWIFIEX_TYPE_CMD */
-
-               if (pkt_len <= INTF_HEADER_LEN ||
-                   pkt_len > MWIFIEX_UPLD_SIZE)
-                       mwifiex_dbg(adapter, ERROR,
-                                   "%s: payload=%p, nb=%d\n",
-                                   __func__, payload, pkt_len);
-
-               if (card->supports_sdio_new_mode)
-                       port = CMD_PORT_SLCT;
-       }
-
-       /* Transfer data to card */
-       pkt_len = buf_block_len * blk_size;
-
-       if (tx_param)
-               ret = mwifiex_host_to_card_mp_aggr(adapter, payload, pkt_len,
-                                                  port, tx_param->next_pkt_len
-                                                  );
-       else
-               ret = mwifiex_host_to_card_mp_aggr(adapter, payload, pkt_len,
-                                                  port, 0);
-
-       if (ret) {
-               if (type == MWIFIEX_TYPE_CMD)
-                       adapter->cmd_sent = false;
-               if (type == MWIFIEX_TYPE_DATA) {
-                       adapter->data_sent = false;
-                       /* restore curr_wr_port in error cases */
-                       card->curr_wr_port = port;
-                       card->mp_wr_bitmap |= (u32)(1 << card->curr_wr_port);
-               }
-       } else {
-               if (type == MWIFIEX_TYPE_DATA) {
-                       if (!(card->mp_wr_bitmap & (1 << card->curr_wr_port)))
-                               adapter->data_sent = true;
-                       else
-                               adapter->data_sent = false;
-               }
-       }
-
-       return ret;
-}
-
-/*
- * This function allocates the MPA Tx and Rx buffers.
- */
-static int mwifiex_alloc_sdio_mpa_buffers(struct mwifiex_adapter *adapter,
-                                  u32 mpa_tx_buf_size, u32 mpa_rx_buf_size)
-{
-       struct sdio_mmc_card *card = adapter->card;
-       u32 rx_buf_size;
-       int ret = 0;
-
-       card->mpa_tx.buf = kzalloc(mpa_tx_buf_size, GFP_KERNEL);
-       if (!card->mpa_tx.buf) {
-               ret = -1;
-               goto error;
-       }
-
-       card->mpa_tx.buf_size = mpa_tx_buf_size;
-
-       rx_buf_size = max_t(u32, mpa_rx_buf_size,
-                           (u32)SDIO_MAX_AGGR_BUF_SIZE);
-       card->mpa_rx.buf = kzalloc(rx_buf_size, GFP_KERNEL);
-       if (!card->mpa_rx.buf) {
-               ret = -1;
-               goto error;
-       }
-
-       card->mpa_rx.buf_size = rx_buf_size;
-
-error:
-       if (ret) {
-               kfree(card->mpa_tx.buf);
-               kfree(card->mpa_rx.buf);
-               card->mpa_tx.buf_size = 0;
-               card->mpa_rx.buf_size = 0;
-       }
-
-       return ret;
-}
-
-/*
- * This function unregisters the SDIO device.
- *
- * The SDIO IRQ is released, the function is disabled and driver
- * data is set to null.
- */
-static void
-mwifiex_unregister_dev(struct mwifiex_adapter *adapter)
-{
-       struct sdio_mmc_card *card = adapter->card;
-
-       if (adapter->card) {
-               sdio_claim_host(card->func);
-               sdio_disable_func(card->func);
-               sdio_release_host(card->func);
-       }
-}
-
-/*
- * This function registers the SDIO device.
- *
- * SDIO IRQ is claimed, block size is set and driver data is initialized.
- */
-static int mwifiex_register_dev(struct mwifiex_adapter *adapter)
-{
-       int ret;
-       struct sdio_mmc_card *card = adapter->card;
-       struct sdio_func *func = card->func;
-
-       /* save adapter pointer in card */
-       card->adapter = adapter;
-       adapter->tx_buf_size = card->tx_buf_size;
-
-       sdio_claim_host(func);
-
-       /* Set block size */
-       ret = sdio_set_block_size(card->func, MWIFIEX_SDIO_BLOCK_SIZE);
-       sdio_release_host(func);
-       if (ret) {
-               mwifiex_dbg(adapter, ERROR,
-                           "cannot set SDIO block size\n");
-               return ret;
-       }
-
-
-       adapter->dev = &func->dev;
-
-       strcpy(adapter->fw_name, card->firmware);
-       if (card->fw_dump_enh) {
-               adapter->mem_type_mapping_tbl = generic_mem_type_map;
-               adapter->num_mem_types = 1;
-       } else {
-               adapter->mem_type_mapping_tbl = mem_type_mapping_tbl;
-               adapter->num_mem_types = ARRAY_SIZE(mem_type_mapping_tbl);
-       }
-
-       return 0;
-}
-
-/*
- * This function initializes the SDIO driver.
- *
- * The following initializations steps are followed -
- *      - Read the Host interrupt status register to acknowledge
- *        the first interrupt got from bootloader
- *      - Disable host interrupt mask register
- *      - Get SDIO port
- *      - Initialize SDIO variables in card
- *      - Allocate MP registers
- *      - Allocate MPA Tx and Rx buffers
- */
-static int mwifiex_init_sdio(struct mwifiex_adapter *adapter)
-{
-       struct sdio_mmc_card *card = adapter->card;
-       const struct mwifiex_sdio_card_reg *reg = card->reg;
-       int ret;
-       u8 sdio_ireg;
-
-       sdio_set_drvdata(card->func, card);
-
-       /*
-        * Read the host_int_status_reg for ACK the first interrupt got
-        * from the bootloader. If we don't do this we get a interrupt
-        * as soon as we register the irq.
-        */
-       mwifiex_read_reg(adapter, card->reg->host_int_status_reg, &sdio_ireg);
-
-       /* Get SDIO ioport */
-       mwifiex_init_sdio_ioport(adapter);
-
-       /* Initialize SDIO variables in card */
-       card->mp_rd_bitmap = 0;
-       card->mp_wr_bitmap = 0;
-       card->curr_rd_port = reg->start_rd_port;
-       card->curr_wr_port = reg->start_wr_port;
-
-       card->mp_data_port_mask = reg->data_port_mask;
-
-       card->mpa_tx.buf_len = 0;
-       card->mpa_tx.pkt_cnt = 0;
-       card->mpa_tx.start_port = 0;
-
-       card->mpa_tx.enabled = 1;
-       card->mpa_tx.pkt_aggr_limit = card->mp_agg_pkt_limit;
-
-       card->mpa_rx.buf_len = 0;
-       card->mpa_rx.pkt_cnt = 0;
-       card->mpa_rx.start_port = 0;
-
-       card->mpa_rx.enabled = 1;
-       card->mpa_rx.pkt_aggr_limit = card->mp_agg_pkt_limit;
-
-       /* Allocate buffers for SDIO MP-A */
-       card->mp_regs = kzalloc(reg->max_mp_regs, GFP_KERNEL);
-       if (!card->mp_regs)
-               return -ENOMEM;
-
-       /* Allocate skb pointer buffers */
-       card->mpa_rx.skb_arr = kzalloc((sizeof(void *)) *
-                                      card->mp_agg_pkt_limit, GFP_KERNEL);
-       card->mpa_rx.len_arr = kzalloc(sizeof(*card->mpa_rx.len_arr) *
-                                      card->mp_agg_pkt_limit, GFP_KERNEL);
-       ret = mwifiex_alloc_sdio_mpa_buffers(adapter,
-                                            card->mp_tx_agg_buf_size,
-                                            card->mp_rx_agg_buf_size);
-
-       /* Allocate 32k MPA Tx/Rx buffers if 64k memory allocation fails */
-       if (ret && (card->mp_tx_agg_buf_size == MWIFIEX_MP_AGGR_BUF_SIZE_MAX ||
-                   card->mp_rx_agg_buf_size == MWIFIEX_MP_AGGR_BUF_SIZE_MAX)) {
-               /* Disable rx single port aggregation */
-               adapter->host_disable_sdio_rx_aggr = true;
-
-               ret = mwifiex_alloc_sdio_mpa_buffers
-                       (adapter, MWIFIEX_MP_AGGR_BUF_SIZE_32K,
-                        MWIFIEX_MP_AGGR_BUF_SIZE_32K);
-               if (ret) {
-                       /* Disable multi port aggregation */
-                       card->mpa_tx.enabled = 0;
-                       card->mpa_rx.enabled = 0;
-               }
-       }
-
-       adapter->auto_tdls = card->can_auto_tdls;
-       adapter->ext_scan = card->can_ext_scan;
-       return 0;
-}
-
-/*
- * This function resets the MPA Tx and Rx buffers.
- */
-static void mwifiex_cleanup_mpa_buf(struct mwifiex_adapter *adapter)
-{
-       struct sdio_mmc_card *card = adapter->card;
-
-       MP_TX_AGGR_BUF_RESET(card);
-       MP_RX_AGGR_BUF_RESET(card);
-}
-
-/*
- * This function cleans up the allocated card buffers.
- *
- * The following are freed by this function -
- *      - MP registers
- *      - MPA Tx buffer
- *      - MPA Rx buffer
- */
-static void mwifiex_cleanup_sdio(struct mwifiex_adapter *adapter)
-{
-       struct sdio_mmc_card *card = adapter->card;
-
-       kfree(card->mp_regs);
-       kfree(card->mpa_rx.skb_arr);
-       kfree(card->mpa_rx.len_arr);
-       kfree(card->mpa_tx.buf);
-       kfree(card->mpa_rx.buf);
-       sdio_set_drvdata(card->func, NULL);
-       kfree(card);
-}
-
-/*
- * This function updates the MP end port in card.
- */
-static void
-mwifiex_update_mp_end_port(struct mwifiex_adapter *adapter, u16 port)
-{
-       struct sdio_mmc_card *card = adapter->card;
-       const struct mwifiex_sdio_card_reg *reg = card->reg;
-       int i;
-
-       card->mp_end_port = port;
-
-       card->mp_data_port_mask = reg->data_port_mask;
-
-       if (reg->start_wr_port) {
-               for (i = 1; i <= card->max_ports - card->mp_end_port; i++)
-                       card->mp_data_port_mask &=
-                                       ~(1 << (card->max_ports - i));
-       }
-
-       card->curr_wr_port = reg->start_wr_port;
-
-       mwifiex_dbg(adapter, CMD,
-                   "cmd: mp_end_port %d, data port mask 0x%x\n",
-                   port, card->mp_data_port_mask);
-}
-
-static void mwifiex_recreate_adapter(struct sdio_mmc_card *card)
-{
-       struct sdio_func *func = card->func;
-       const struct sdio_device_id *device_id = card->device_id;
-
-       /* TODO mmc_hw_reset does not require destroying and re-probing the
-        * whole adapter. Hence there was no need to for this rube-goldberg
-        * design to reload the fw from an external workqueue. If we don't
-        * destroy the adapter we could reload the fw from
-        * mwifiex_main_work_queue directly.
-        * The real difficulty with fw reset is to restore all the user
-        * settings applied through ioctl. By destroying and recreating the
-        * adapter, we take the easy way out, since we rely on user space to
-        * restore them. We assume that user space will treat the new
-        * incarnation of the adapter(interfaces) as if they had been just
-        * discovered and initializes them from scratch.
-        */
-
-       mwifiex_sdio_remove(func);
-
-       /* power cycle the adapter */
-       sdio_claim_host(func);
-       mmc_hw_reset(func->card->host);
-       sdio_release_host(func);
-
-       mwifiex_sdio_probe(func, device_id);
-}
-
-static struct mwifiex_adapter *save_adapter;
-static void mwifiex_sdio_card_reset_work(struct mwifiex_adapter *adapter)
-{
-       struct sdio_mmc_card *card = adapter->card;
-
-       /* TODO card pointer is unprotected. If the adapter is removed
-        * physically, sdio core might trigger mwifiex_sdio_remove, before this
-        * workqueue is run, which will destroy the adapter struct. When this
-        * workqueue eventually exceutes it will dereference an invalid adapter
-        * pointer
-        */
-       mwifiex_recreate_adapter(card);
-}
-
-/* This function read/write firmware */
-static enum
-rdwr_status mwifiex_sdio_rdwr_firmware(struct mwifiex_adapter *adapter,
-                                      u8 doneflag)
-{
-       struct sdio_mmc_card *card = adapter->card;
-       int ret, tries;
-       u8 ctrl_data = 0;
-
-       sdio_writeb(card->func, card->reg->fw_dump_host_ready,
-                   card->reg->fw_dump_ctrl, &ret);
-       if (ret) {
-               mwifiex_dbg(adapter, ERROR, "SDIO Write ERR\n");
-               return RDWR_STATUS_FAILURE;
-       }
-       for (tries = 0; tries < MAX_POLL_TRIES; tries++) {
-               ctrl_data = sdio_readb(card->func, card->reg->fw_dump_ctrl,
-                                      &ret);
-               if (ret) {
-                       mwifiex_dbg(adapter, ERROR, "SDIO read err\n");
-                       return RDWR_STATUS_FAILURE;
-               }
-               if (ctrl_data == FW_DUMP_DONE)
-                       break;
-               if (doneflag && ctrl_data == doneflag)
-                       return RDWR_STATUS_DONE;
-               if (ctrl_data != card->reg->fw_dump_host_ready) {
-                       mwifiex_dbg(adapter, WARN,
-                                   "The ctrl reg was changed, re-try again\n");
-                       sdio_writeb(card->func, card->reg->fw_dump_host_ready,
-                                   card->reg->fw_dump_ctrl, &ret);
-                       if (ret) {
-                               mwifiex_dbg(adapter, ERROR, "SDIO write err\n");
-                               return RDWR_STATUS_FAILURE;
-                       }
-               }
-               usleep_range(100, 200);
-       }
-       if (ctrl_data == card->reg->fw_dump_host_ready) {
-               mwifiex_dbg(adapter, ERROR,
-                           "Fail to pull ctrl_data\n");
-               return RDWR_STATUS_FAILURE;
-       }
-
-       return RDWR_STATUS_SUCCESS;
-}
-
-/* This function dump firmware memory to file */
-static void mwifiex_sdio_fw_dump(struct mwifiex_adapter *adapter)
-{
-       struct sdio_mmc_card *card = adapter->card;
-       int ret = 0;
-       unsigned int reg, reg_start, reg_end;
-       u8 *dbg_ptr, *end_ptr, dump_num, idx, i, read_reg, doneflag = 0;
-       enum rdwr_status stat;
-       u32 memory_size;
-
-       if (!card->can_dump_fw)
-               return;
-
-       for (idx = 0; idx < ARRAY_SIZE(mem_type_mapping_tbl); idx++) {
-               struct memory_type_mapping *entry = &mem_type_mapping_tbl[idx];
-
-               if (entry->mem_ptr) {
-                       vfree(entry->mem_ptr);
-                       entry->mem_ptr = NULL;
-               }
-               entry->mem_size = 0;
-       }
-
-       mwifiex_pm_wakeup_card(adapter);
-       sdio_claim_host(card->func);
-
-       mwifiex_dbg(adapter, MSG, "== mwifiex firmware dump start ==\n");
-
-       stat = mwifiex_sdio_rdwr_firmware(adapter, doneflag);
-       if (stat == RDWR_STATUS_FAILURE)
-               goto done;
-
-       reg = card->reg->fw_dump_start;
-       /* Read the number of the memories which will dump */
-       dump_num = sdio_readb(card->func, reg, &ret);
-       if (ret) {
-               mwifiex_dbg(adapter, ERROR, "SDIO read memory length err\n");
-               goto done;
-       }
-
-       /* Read the length of every memory which will dump */
-       for (idx = 0; idx < dump_num; idx++) {
-               struct memory_type_mapping *entry = &mem_type_mapping_tbl[idx];
-
-               stat = mwifiex_sdio_rdwr_firmware(adapter, doneflag);
-               if (stat == RDWR_STATUS_FAILURE)
-                       goto done;
-
-               memory_size = 0;
-               reg = card->reg->fw_dump_start;
-               for (i = 0; i < 4; i++) {
-                       read_reg = sdio_readb(card->func, reg, &ret);
-                       if (ret) {
-                               mwifiex_dbg(adapter, ERROR, "SDIO read err\n");
-                               goto done;
-                       }
-                       memory_size |= (read_reg << i*8);
-                       reg++;
-               }
-
-               if (memory_size == 0) {
-                       mwifiex_dbg(adapter, DUMP, "Firmware dump Finished!\n");
-                       ret = mwifiex_write_reg(adapter,
-                                               card->reg->fw_dump_ctrl,
-                                               FW_DUMP_READ_DONE);
-                       if (ret) {
-                               mwifiex_dbg(adapter, ERROR, "SDIO write err\n");
-                               return;
-                       }
-                       break;
-               }
-
-               mwifiex_dbg(adapter, DUMP,
-                           "%s_SIZE=0x%x\n", entry->mem_name, memory_size);
-               entry->mem_ptr = vmalloc(memory_size + 1);
-               entry->mem_size = memory_size;
-               if (!entry->mem_ptr) {
-                       mwifiex_dbg(adapter, ERROR, "Vmalloc %s failed\n",
-                                   entry->mem_name);
-                       goto done;
-               }
-               dbg_ptr = entry->mem_ptr;
-               end_ptr = dbg_ptr + memory_size;
-
-               doneflag = entry->done_flag;
-               mwifiex_dbg(adapter, DUMP,
-                           "Start %s output, please wait...\n",
-                           entry->mem_name);
-
-               do {
-                       stat = mwifiex_sdio_rdwr_firmware(adapter, doneflag);
-                       if (stat == RDWR_STATUS_FAILURE)
-                               goto done;
-
-                       reg_start = card->reg->fw_dump_start;
-                       reg_end = card->reg->fw_dump_end;
-                       for (reg = reg_start; reg <= reg_end; reg++) {
-                               *dbg_ptr = sdio_readb(card->func, reg, &ret);
-                               if (ret) {
-                                       mwifiex_dbg(adapter, ERROR,
-                                                   "SDIO read err\n");
-                                       goto done;
-                               }
-                               if (dbg_ptr < end_ptr)
-                                       dbg_ptr++;
-                               else
-                                       mwifiex_dbg(adapter, ERROR,
-                                                   "Allocated buf not enough\n");
-                       }
-
-                       if (stat != RDWR_STATUS_DONE)
-                               continue;
-
-                       mwifiex_dbg(adapter, DUMP, "%s done: size=0x%tx\n",
-                                   entry->mem_name, dbg_ptr - entry->mem_ptr);
-                       break;
-               } while (1);
-       }
-       mwifiex_dbg(adapter, MSG, "== mwifiex firmware dump end ==\n");
-
-done:
-       sdio_release_host(card->func);
-}
-
-static void mwifiex_sdio_generic_fw_dump(struct mwifiex_adapter *adapter)
-{
-       struct sdio_mmc_card *card = adapter->card;
-       struct memory_type_mapping *entry = &generic_mem_type_map[0];
-       unsigned int reg, reg_start, reg_end;
-       u8 start_flag = 0, done_flag = 0;
-       u8 *dbg_ptr, *end_ptr;
-       enum rdwr_status stat;
-       int ret = -1, tries;
-
-       if (!card->fw_dump_enh)
-               return;
-
-       if (entry->mem_ptr) {
-               vfree(entry->mem_ptr);
-               entry->mem_ptr = NULL;
-       }
-       entry->mem_size = 0;
-
-       mwifiex_pm_wakeup_card(adapter);
-       sdio_claim_host(card->func);
-
-       mwifiex_dbg(adapter, MSG, "== mwifiex firmware dump start ==\n");
-
-       stat = mwifiex_sdio_rdwr_firmware(adapter, done_flag);
-       if (stat == RDWR_STATUS_FAILURE)
-               goto done;
-
-       reg_start = card->reg->fw_dump_start;
-       reg_end = card->reg->fw_dump_end;
-       for (reg = reg_start; reg <= reg_end; reg++) {
-               for (tries = 0; tries < MAX_POLL_TRIES; tries++) {
-                       start_flag = sdio_readb(card->func, reg, &ret);
-                       if (ret) {
-                               mwifiex_dbg(adapter, ERROR,
-                                           "SDIO read err\n");
-                               goto done;
-                       }
-                       if (start_flag == 0)
-                               break;
-                       if (tries == MAX_POLL_TRIES) {
-                               mwifiex_dbg(adapter, ERROR,
-                                           "FW not ready to dump\n");
-                               ret = -1;
-                               goto done;
-                       }
-               }
-               usleep_range(100, 200);
-       }
-
-       entry->mem_ptr = vmalloc(0xf0000 + 1);
-       if (!entry->mem_ptr) {
-               ret = -1;
-               goto done;
-       }
-       dbg_ptr = entry->mem_ptr;
-       entry->mem_size = 0xf0000;
-       end_ptr = dbg_ptr + entry->mem_size;
-
-       done_flag = entry->done_flag;
-       mwifiex_dbg(adapter, DUMP,
-                   "Start %s output, please wait...\n", entry->mem_name);
-
-       while (true) {
-               stat = mwifiex_sdio_rdwr_firmware(adapter, done_flag);
-               if (stat == RDWR_STATUS_FAILURE)
-                       goto done;
-               for (reg = reg_start; reg <= reg_end; reg++) {
-                       *dbg_ptr = sdio_readb(card->func, reg, &ret);
-                       if (ret) {
-                               mwifiex_dbg(adapter, ERROR,
-                                           "SDIO read err\n");
-                               goto done;
-                       }
-                       dbg_ptr++;
-                       if (dbg_ptr >= end_ptr) {
-                               u8 *tmp_ptr;
-
-                               tmp_ptr = vmalloc(entry->mem_size + 0x4000 + 1);
-                               if (!tmp_ptr)
-                                       goto done;
-
-                               memcpy(tmp_ptr, entry->mem_ptr,
-                                      entry->mem_size);
-                               vfree(entry->mem_ptr);
-                               entry->mem_ptr = tmp_ptr;
-                               tmp_ptr = NULL;
-                               dbg_ptr = entry->mem_ptr + entry->mem_size;
-                               entry->mem_size += 0x4000;
-                               end_ptr = entry->mem_ptr + entry->mem_size;
-                       }
-               }
-               if (stat == RDWR_STATUS_DONE) {
-                       entry->mem_size = dbg_ptr - entry->mem_ptr;
-                       mwifiex_dbg(adapter, DUMP, "dump %s done size=0x%x\n",
-                                   entry->mem_name, entry->mem_size);
-                       ret = 0;
-                       break;
-               }
-       }
-       mwifiex_dbg(adapter, MSG, "== mwifiex firmware dump end ==\n");
-
-done:
-       if (ret) {
-               mwifiex_dbg(adapter, ERROR, "firmware dump failed\n");
-               if (entry->mem_ptr) {
-                       vfree(entry->mem_ptr);
-                       entry->mem_ptr = NULL;
-               }
-               entry->mem_size = 0;
-       }
-       sdio_release_host(card->func);
-}
-
-static void mwifiex_sdio_device_dump_work(struct mwifiex_adapter *adapter)
-{
-       struct sdio_mmc_card *card = adapter->card;
-
-       mwifiex_drv_info_dump(adapter);
-       if (card->fw_dump_enh)
-               mwifiex_sdio_generic_fw_dump(adapter);
-       else
-               mwifiex_sdio_fw_dump(adapter);
-       mwifiex_upload_device_dump(adapter);
-}
-
-static void mwifiex_sdio_work(struct work_struct *work)
-{
-       if (test_and_clear_bit(MWIFIEX_IFACE_WORK_DEVICE_DUMP,
-                              &iface_work_flags))
-               mwifiex_sdio_device_dump_work(save_adapter);
-       if (test_and_clear_bit(MWIFIEX_IFACE_WORK_CARD_RESET,
-                              &iface_work_flags))
-               mwifiex_sdio_card_reset_work(save_adapter);
-}
-
-static DECLARE_WORK(sdio_work, mwifiex_sdio_work);
-/* This function resets the card */
-static void mwifiex_sdio_card_reset(struct mwifiex_adapter *adapter)
-{
-       save_adapter = adapter;
-       if (test_bit(MWIFIEX_IFACE_WORK_CARD_RESET, &iface_work_flags))
-               return;
-
-       set_bit(MWIFIEX_IFACE_WORK_CARD_RESET, &iface_work_flags);
-
-       schedule_work(&sdio_work);
-}
-
-/* This function dumps FW information */
-static void mwifiex_sdio_device_dump(struct mwifiex_adapter *adapter)
-{
-       save_adapter = adapter;
-       if (test_bit(MWIFIEX_IFACE_WORK_DEVICE_DUMP, &iface_work_flags))
-               return;
-
-       set_bit(MWIFIEX_IFACE_WORK_DEVICE_DUMP, &iface_work_flags);
-       schedule_work(&sdio_work);
-}
-
-/* Function to dump SDIO function registers and SDIO scratch registers in case
- * of FW crash
- */
-static int
-mwifiex_sdio_reg_dump(struct mwifiex_adapter *adapter, char *drv_buf)
-{
-       char *p = drv_buf;
-       struct sdio_mmc_card *cardp = adapter->card;
-       int ret = 0;
-       u8 count, func, data, index = 0, size = 0;
-       u8 reg, reg_start, reg_end;
-       char buf[256], *ptr;
-
-       if (!p)
-               return 0;
-
-       mwifiex_dbg(adapter, MSG, "SDIO register dump start\n");
-
-       mwifiex_pm_wakeup_card(adapter);
-
-       sdio_claim_host(cardp->func);
-
-       for (count = 0; count < 5; count++) {
-               memset(buf, 0, sizeof(buf));
-               ptr = buf;
-
-               switch (count) {
-               case 0:
-                       /* Read the registers of SDIO function0 */
-                       func = count;
-                       reg_start = 0;
-                       reg_end = 9;
-                       break;
-               case 1:
-                       /* Read the registers of SDIO function1 */
-                       func = count;
-                       reg_start = cardp->reg->func1_dump_reg_start;
-                       reg_end = cardp->reg->func1_dump_reg_end;
-                       break;
-               case 2:
-                       index = 0;
-                       func = 1;
-                       reg_start = cardp->reg->func1_spec_reg_table[index++];
-                       size = cardp->reg->func1_spec_reg_num;
-                       reg_end = cardp->reg->func1_spec_reg_table[size-1];
-                       break;
-               default:
-                       /* Read the scratch registers of SDIO function1 */
-                       if (count == 4)
-                               mdelay(100);
-                       func = 1;
-                       reg_start = cardp->reg->func1_scratch_reg;
-                       reg_end = reg_start + MWIFIEX_SDIO_SCRATCH_SIZE;
-               }
-
-               if (count != 2)
-                       ptr += sprintf(ptr, "SDIO Func%d (%#x-%#x): ",
-                                      func, reg_start, reg_end);
-               else
-                       ptr += sprintf(ptr, "SDIO Func%d: ", func);
-
-               for (reg = reg_start; reg <= reg_end;) {
-                       if (func == 0)
-                               data = sdio_f0_readb(cardp->func, reg, &ret);
-                       else
-                               data = sdio_readb(cardp->func, reg, &ret);
-
-                       if (count == 2)
-                               ptr += sprintf(ptr, "(%#x) ", reg);
-                       if (!ret) {
-                               ptr += sprintf(ptr, "%02x ", data);
-                       } else {
-                               ptr += sprintf(ptr, "ERR");
-                               break;
-                       }
-
-                       if (count == 2 && reg < reg_end)
-                               reg = cardp->reg->func1_spec_reg_table[index++];
-                       else
-                               reg++;
-               }
-
-               mwifiex_dbg(adapter, MSG, "%s\n", buf);
-               p += sprintf(p, "%s\n", buf);
-       }
-
-       sdio_release_host(cardp->func);
-
-       mwifiex_dbg(adapter, MSG, "SDIO register dump end\n");
-
-       return p - drv_buf;
-}
-
-static struct mwifiex_if_ops sdio_ops = {
-       .init_if = mwifiex_init_sdio,
-       .cleanup_if = mwifiex_cleanup_sdio,
-       .check_fw_status = mwifiex_check_fw_status,
-       .prog_fw = mwifiex_prog_fw_w_helper,
-       .register_dev = mwifiex_register_dev,
-       .unregister_dev = mwifiex_unregister_dev,
-       .enable_int = mwifiex_sdio_enable_host_int,
-       .disable_int = mwifiex_sdio_disable_host_int,
-       .process_int_status = mwifiex_process_int_status,
-       .host_to_card = mwifiex_sdio_host_to_card,
-       .wakeup = mwifiex_pm_wakeup_card,
-       .wakeup_complete = mwifiex_pm_wakeup_card_complete,
-
-       /* SDIO specific */
-       .update_mp_end_port = mwifiex_update_mp_end_port,
-       .cleanup_mpa_buf = mwifiex_cleanup_mpa_buf,
-       .cmdrsp_complete = mwifiex_sdio_cmdrsp_complete,
-       .event_complete = mwifiex_sdio_event_complete,
-       .card_reset = mwifiex_sdio_card_reset,
-       .reg_dump = mwifiex_sdio_reg_dump,
-       .device_dump = mwifiex_sdio_device_dump,
-       .deaggr_pkt = mwifiex_deaggr_sdio_pkt,
-};
-
-/*
- * This function initializes the SDIO driver.
- *
- * This initiates the semaphore and registers the device with
- * SDIO bus.
- */
-static int
-mwifiex_sdio_init_module(void)
-{
-       sema_init(&add_remove_card_sem, 1);
-
-       /* Clear the flag in case user removes the card. */
-       user_rmmod = 0;
-
-       return sdio_register_driver(&mwifiex_sdio);
-}
-
-/*
- * This function cleans up the SDIO driver.
- *
- * The following major steps are followed for cleanup -
- *      - Resume the device if its suspended
- *      - Disconnect the device if connected
- *      - Shutdown the firmware
- *      - Unregister the device from SDIO bus.
- */
-static void
-mwifiex_sdio_cleanup_module(void)
-{
-       if (!down_interruptible(&add_remove_card_sem))
-               up(&add_remove_card_sem);
-
-       /* Set the flag as user is removing this module. */
-       user_rmmod = 1;
-       cancel_work_sync(&sdio_work);
-
-       sdio_unregister_driver(&mwifiex_sdio);
-}
-
-module_init(mwifiex_sdio_init_module);
-module_exit(mwifiex_sdio_cleanup_module);
-
-MODULE_AUTHOR("Marvell International Ltd.");
-MODULE_DESCRIPTION("Marvell WiFi-Ex SDIO Driver version " SDIO_VERSION);
-MODULE_VERSION(SDIO_VERSION);
-MODULE_LICENSE("GPL v2");
-MODULE_FIRMWARE(SD8786_DEFAULT_FW_NAME);
-MODULE_FIRMWARE(SD8787_DEFAULT_FW_NAME);
-MODULE_FIRMWARE(SD8797_DEFAULT_FW_NAME);
-MODULE_FIRMWARE(SD8897_DEFAULT_FW_NAME);
-MODULE_FIRMWARE(SD8887_DEFAULT_FW_NAME);
-MODULE_FIRMWARE(SD8997_DEFAULT_FW_NAME);
diff --git a/drivers/net/wireless/mwifiex/sdio.h b/drivers/net/wireless/mwifiex/sdio.h
deleted file mode 100644 (file)
index b9fbc5c..0000000
+++ /dev/null
@@ -1,672 +0,0 @@
-/*
- * Marvell Wireless LAN device driver: SDIO specific definitions
- *
- * Copyright (C) 2011-2014, Marvell International Ltd.
- *
- * This software file (the "File") is distributed by Marvell International
- * Ltd. under the terms of the GNU General Public License Version 2, June 1991
- * (the "License").  You may use, redistribute and/or modify this File in
- * accordance with the terms and conditions of the License, a copy of which
- * is available by writing to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the
- * worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
- *
- * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
- * ARE EXPRESSLY DISCLAIMED.  The License provides additional details about
- * this warranty disclaimer.
- */
-
-#ifndef        _MWIFIEX_SDIO_H
-#define        _MWIFIEX_SDIO_H
-
-
-#include <linux/mmc/sdio.h>
-#include <linux/mmc/sdio_ids.h>
-#include <linux/mmc/sdio_func.h>
-#include <linux/mmc/card.h>
-#include <linux/mmc/host.h>
-
-#include "main.h"
-
-#define SD8786_DEFAULT_FW_NAME "mrvl/sd8786_uapsta.bin"
-#define SD8787_DEFAULT_FW_NAME "mrvl/sd8787_uapsta.bin"
-#define SD8797_DEFAULT_FW_NAME "mrvl/sd8797_uapsta.bin"
-#define SD8897_DEFAULT_FW_NAME "mrvl/sd8897_uapsta.bin"
-#define SD8887_DEFAULT_FW_NAME "mrvl/sd8887_uapsta.bin"
-#define SD8801_DEFAULT_FW_NAME "mrvl/sd8801_uapsta.bin"
-#define SD8997_DEFAULT_FW_NAME "mrvl/sd8997_uapsta.bin"
-
-#define BLOCK_MODE     1
-#define BYTE_MODE      0
-
-#define REG_PORT                       0
-
-#define MWIFIEX_SDIO_IO_PORT_MASK              0xfffff
-
-#define MWIFIEX_SDIO_BYTE_MODE_MASK    0x80000000
-
-#define MWIFIEX_MAX_FUNC2_REG_NUM      13
-#define MWIFIEX_SDIO_SCRATCH_SIZE      10
-
-#define SDIO_MPA_ADDR_BASE             0x1000
-#define CTRL_PORT                      0
-#define CTRL_PORT_MASK                 0x0001
-
-#define CMD_PORT_UPLD_INT_MASK         (0x1U<<6)
-#define CMD_PORT_DNLD_INT_MASK         (0x1U<<7)
-#define HOST_TERM_CMD53                        (0x1U << 2)
-#define REG_PORT                       0
-#define MEM_PORT                       0x10000
-
-#define CMD53_NEW_MODE                 (0x1U << 0)
-#define CMD_PORT_RD_LEN_EN             (0x1U << 2)
-#define CMD_PORT_AUTO_EN               (0x1U << 0)
-#define CMD_PORT_SLCT                  0x8000
-#define UP_LD_CMD_PORT_HOST_INT_STATUS (0x40U)
-#define DN_LD_CMD_PORT_HOST_INT_STATUS (0x80U)
-
-#define MWIFIEX_MP_AGGR_BUF_SIZE_16K   (16384)
-#define MWIFIEX_MP_AGGR_BUF_SIZE_32K   (32768)
-/* we leave one block of 256 bytes for DMA alignment*/
-#define MWIFIEX_MP_AGGR_BUF_SIZE_MAX    (65280)
-
-/* Misc. Config Register : Auto Re-enable interrupts */
-#define AUTO_RE_ENABLE_INT              BIT(4)
-
-/* Host Control Registers : Configuration */
-#define CONFIGURATION_REG              0x00
-/* Host Control Registers : Host power up */
-#define HOST_POWER_UP                  (0x1U << 1)
-
-/* Host Control Registers : Upload host interrupt mask */
-#define UP_LD_HOST_INT_MASK            (0x1U)
-/* Host Control Registers : Download host interrupt mask */
-#define DN_LD_HOST_INT_MASK            (0x2U)
-
-/* Host Control Registers : Upload host interrupt status */
-#define UP_LD_HOST_INT_STATUS          (0x1U)
-/* Host Control Registers : Download host interrupt status */
-#define DN_LD_HOST_INT_STATUS          (0x2U)
-
-/* Host Control Registers : Host interrupt status */
-#define CARD_INT_STATUS_REG            0x28
-
-/* Card Control Registers : Card I/O ready */
-#define CARD_IO_READY                   (0x1U << 3)
-/* Card Control Registers : Download card ready */
-#define DN_LD_CARD_RDY                  (0x1U << 0)
-
-/* Max retry number of CMD53 write */
-#define MAX_WRITE_IOMEM_RETRY          2
-
-/* SDIO Tx aggregation in progress ? */
-#define MP_TX_AGGR_IN_PROGRESS(a) (a->mpa_tx.pkt_cnt > 0)
-
-/* SDIO Tx aggregation buffer room for next packet ? */
-#define MP_TX_AGGR_BUF_HAS_ROOM(a, len) ((a->mpa_tx.buf_len+len)       \
-                                               <= a->mpa_tx.buf_size)
-
-/* Copy current packet (SDIO Tx aggregation buffer) to SDIO buffer */
-#define MP_TX_AGGR_BUF_PUT(a, payload, pkt_len, port) do {             \
-       memmove(&a->mpa_tx.buf[a->mpa_tx.buf_len],                      \
-                       payload, pkt_len);                              \
-       a->mpa_tx.buf_len += pkt_len;                                   \
-       if (!a->mpa_tx.pkt_cnt)                                         \
-               a->mpa_tx.start_port = port;                            \
-       if (a->mpa_tx.start_port <= port)                               \
-               a->mpa_tx.ports |= (1<<(a->mpa_tx.pkt_cnt));            \
-       else                                                            \
-               a->mpa_tx.ports |= (1<<(a->mpa_tx.pkt_cnt+1+            \
-                                               (a->max_ports - \
-                                               a->mp_end_port)));      \
-       a->mpa_tx.pkt_cnt++;                                            \
-} while (0)
-
-/* SDIO Tx aggregation limit ? */
-#define MP_TX_AGGR_PKT_LIMIT_REACHED(a)                                        \
-                       (a->mpa_tx.pkt_cnt == a->mpa_tx.pkt_aggr_limit)
-
-/* Reset SDIO Tx aggregation buffer parameters */
-#define MP_TX_AGGR_BUF_RESET(a) do {                                   \
-       a->mpa_tx.pkt_cnt = 0;                                          \
-       a->mpa_tx.buf_len = 0;                                          \
-       a->mpa_tx.ports = 0;                                            \
-       a->mpa_tx.start_port = 0;                                       \
-} while (0)
-
-/* SDIO Rx aggregation limit ? */
-#define MP_RX_AGGR_PKT_LIMIT_REACHED(a)                                        \
-                       (a->mpa_rx.pkt_cnt == a->mpa_rx.pkt_aggr_limit)
-
-/* SDIO Rx aggregation in progress ? */
-#define MP_RX_AGGR_IN_PROGRESS(a) (a->mpa_rx.pkt_cnt > 0)
-
-/* SDIO Rx aggregation buffer room for next packet ? */
-#define MP_RX_AGGR_BUF_HAS_ROOM(a, rx_len)                             \
-                       ((a->mpa_rx.buf_len+rx_len) <= a->mpa_rx.buf_size)
-
-/* Reset SDIO Rx aggregation buffer parameters */
-#define MP_RX_AGGR_BUF_RESET(a) do {                                   \
-       a->mpa_rx.pkt_cnt = 0;                                          \
-       a->mpa_rx.buf_len = 0;                                          \
-       a->mpa_rx.ports = 0;                                            \
-       a->mpa_rx.start_port = 0;                                       \
-} while (0)
-
-/* data structure for SDIO MPA TX */
-struct mwifiex_sdio_mpa_tx {
-       /* multiport tx aggregation buffer pointer */
-       u8 *buf;
-       u32 buf_len;
-       u32 pkt_cnt;
-       u32 ports;
-       u16 start_port;
-       u8 enabled;
-       u32 buf_size;
-       u32 pkt_aggr_limit;
-};
-
-struct mwifiex_sdio_mpa_rx {
-       u8 *buf;
-       u32 buf_len;
-       u32 pkt_cnt;
-       u32 ports;
-       u16 start_port;
-
-       struct sk_buff **skb_arr;
-       u32 *len_arr;
-
-       u8 enabled;
-       u32 buf_size;
-       u32 pkt_aggr_limit;
-};
-
-int mwifiex_bus_register(void);
-void mwifiex_bus_unregister(void);
-
-struct mwifiex_sdio_card_reg {
-       u8 start_rd_port;
-       u8 start_wr_port;
-       u8 base_0_reg;
-       u8 base_1_reg;
-       u8 poll_reg;
-       u8 host_int_enable;
-       u8 host_int_rsr_reg;
-       u8 host_int_status_reg;
-       u8 host_int_mask_reg;
-       u8 status_reg_0;
-       u8 status_reg_1;
-       u8 sdio_int_mask;
-       u32 data_port_mask;
-       u8 io_port_0_reg;
-       u8 io_port_1_reg;
-       u8 io_port_2_reg;
-       u8 max_mp_regs;
-       u8 rd_bitmap_l;
-       u8 rd_bitmap_u;
-       u8 rd_bitmap_1l;
-       u8 rd_bitmap_1u;
-       u8 wr_bitmap_l;
-       u8 wr_bitmap_u;
-       u8 wr_bitmap_1l;
-       u8 wr_bitmap_1u;
-       u8 rd_len_p0_l;
-       u8 rd_len_p0_u;
-       u8 card_misc_cfg_reg;
-       u8 card_cfg_2_1_reg;
-       u8 cmd_rd_len_0;
-       u8 cmd_rd_len_1;
-       u8 cmd_rd_len_2;
-       u8 cmd_rd_len_3;
-       u8 cmd_cfg_0;
-       u8 cmd_cfg_1;
-       u8 cmd_cfg_2;
-       u8 cmd_cfg_3;
-       u8 fw_dump_host_ready;
-       u8 fw_dump_ctrl;
-       u8 fw_dump_start;
-       u8 fw_dump_end;
-       u8 func1_dump_reg_start;
-       u8 func1_dump_reg_end;
-       u8 func1_scratch_reg;
-       u8 func1_spec_reg_num;
-       u8 func1_spec_reg_table[MWIFIEX_MAX_FUNC2_REG_NUM];
-};
-
-struct sdio_mmc_card {
-       struct sdio_func *func;
-       struct mwifiex_adapter *adapter;
-
-       const char *firmware;
-       const struct mwifiex_sdio_card_reg *reg;
-       u8 max_ports;
-       u8 mp_agg_pkt_limit;
-       u16 tx_buf_size;
-       u32 mp_tx_agg_buf_size;
-       u32 mp_rx_agg_buf_size;
-
-       u32 mp_rd_bitmap;
-       u32 mp_wr_bitmap;
-
-       u16 mp_end_port;
-       u32 mp_data_port_mask;
-
-       u8 curr_rd_port;
-       u8 curr_wr_port;
-
-       u8 *mp_regs;
-       bool supports_sdio_new_mode;
-       bool has_control_mask;
-       bool can_dump_fw;
-       bool fw_dump_enh;
-       bool can_auto_tdls;
-       bool can_ext_scan;
-
-       struct mwifiex_sdio_mpa_tx mpa_tx;
-       struct mwifiex_sdio_mpa_rx mpa_rx;
-
-       /* needed for card reset */
-       const struct sdio_device_id *device_id;
-};
-
-struct mwifiex_sdio_device {
-       const char *firmware;
-       const struct mwifiex_sdio_card_reg *reg;
-       u8 max_ports;
-       u8 mp_agg_pkt_limit;
-       u16 tx_buf_size;
-       u32 mp_tx_agg_buf_size;
-       u32 mp_rx_agg_buf_size;
-       bool supports_sdio_new_mode;
-       bool has_control_mask;
-       bool can_dump_fw;
-       bool fw_dump_enh;
-       bool can_auto_tdls;
-       bool can_ext_scan;
-};
-
-static const struct mwifiex_sdio_card_reg mwifiex_reg_sd87xx = {
-       .start_rd_port = 1,
-       .start_wr_port = 1,
-       .base_0_reg = 0x0040,
-       .base_1_reg = 0x0041,
-       .poll_reg = 0x30,
-       .host_int_enable = UP_LD_HOST_INT_MASK | DN_LD_HOST_INT_MASK,
-       .host_int_rsr_reg = 0x1,
-       .host_int_mask_reg = 0x02,
-       .host_int_status_reg = 0x03,
-       .status_reg_0 = 0x60,
-       .status_reg_1 = 0x61,
-       .sdio_int_mask = 0x3f,
-       .data_port_mask = 0x0000fffe,
-       .io_port_0_reg = 0x78,
-       .io_port_1_reg = 0x79,
-       .io_port_2_reg = 0x7A,
-       .max_mp_regs = 64,
-       .rd_bitmap_l = 0x04,
-       .rd_bitmap_u = 0x05,
-       .wr_bitmap_l = 0x06,
-       .wr_bitmap_u = 0x07,
-       .rd_len_p0_l = 0x08,
-       .rd_len_p0_u = 0x09,
-       .card_misc_cfg_reg = 0x6c,
-       .func1_dump_reg_start = 0x0,
-       .func1_dump_reg_end = 0x9,
-       .func1_scratch_reg = 0x60,
-       .func1_spec_reg_num = 5,
-       .func1_spec_reg_table = {0x28, 0x30, 0x34, 0x38, 0x3c},
-};
-
-static const struct mwifiex_sdio_card_reg mwifiex_reg_sd8897 = {
-       .start_rd_port = 0,
-       .start_wr_port = 0,
-       .base_0_reg = 0x60,
-       .base_1_reg = 0x61,
-       .poll_reg = 0x50,
-       .host_int_enable = UP_LD_HOST_INT_MASK | DN_LD_HOST_INT_MASK |
-                       CMD_PORT_UPLD_INT_MASK | CMD_PORT_DNLD_INT_MASK,
-       .host_int_rsr_reg = 0x1,
-       .host_int_status_reg = 0x03,
-       .host_int_mask_reg = 0x02,
-       .status_reg_0 = 0xc0,
-       .status_reg_1 = 0xc1,
-       .sdio_int_mask = 0xff,
-       .data_port_mask = 0xffffffff,
-       .io_port_0_reg = 0xD8,
-       .io_port_1_reg = 0xD9,
-       .io_port_2_reg = 0xDA,
-       .max_mp_regs = 184,
-       .rd_bitmap_l = 0x04,
-       .rd_bitmap_u = 0x05,
-       .rd_bitmap_1l = 0x06,
-       .rd_bitmap_1u = 0x07,
-       .wr_bitmap_l = 0x08,
-       .wr_bitmap_u = 0x09,
-       .wr_bitmap_1l = 0x0a,
-       .wr_bitmap_1u = 0x0b,
-       .rd_len_p0_l = 0x0c,
-       .rd_len_p0_u = 0x0d,
-       .card_misc_cfg_reg = 0xcc,
-       .card_cfg_2_1_reg = 0xcd,
-       .cmd_rd_len_0 = 0xb4,
-       .cmd_rd_len_1 = 0xb5,
-       .cmd_rd_len_2 = 0xb6,
-       .cmd_rd_len_3 = 0xb7,
-       .cmd_cfg_0 = 0xb8,
-       .cmd_cfg_1 = 0xb9,
-       .cmd_cfg_2 = 0xba,
-       .cmd_cfg_3 = 0xbb,
-       .fw_dump_host_ready = 0xee,
-       .fw_dump_ctrl = 0xe2,
-       .fw_dump_start = 0xe3,
-       .fw_dump_end = 0xea,
-       .func1_dump_reg_start = 0x0,
-       .func1_dump_reg_end = 0xb,
-       .func1_scratch_reg = 0xc0,
-       .func1_spec_reg_num = 8,
-       .func1_spec_reg_table = {0x4C, 0x50, 0x54, 0x55, 0x58,
-                                0x59, 0x5c, 0x5d},
-};
-
-static const struct mwifiex_sdio_card_reg mwifiex_reg_sd8997 = {
-       .start_rd_port = 0,
-       .start_wr_port = 0,
-       .base_0_reg = 0xF8,
-       .base_1_reg = 0xF9,
-       .poll_reg = 0x5C,
-       .host_int_enable = UP_LD_HOST_INT_MASK | DN_LD_HOST_INT_MASK |
-                       CMD_PORT_UPLD_INT_MASK | CMD_PORT_DNLD_INT_MASK,
-       .host_int_rsr_reg = 0x4,
-       .host_int_status_reg = 0x0C,
-       .host_int_mask_reg = 0x08,
-       .status_reg_0 = 0xE8,
-       .status_reg_1 = 0xE9,
-       .sdio_int_mask = 0xff,
-       .data_port_mask = 0xffffffff,
-       .io_port_0_reg = 0xE4,
-       .io_port_1_reg = 0xE5,
-       .io_port_2_reg = 0xE6,
-       .max_mp_regs = 196,
-       .rd_bitmap_l = 0x10,
-       .rd_bitmap_u = 0x11,
-       .rd_bitmap_1l = 0x12,
-       .rd_bitmap_1u = 0x13,
-       .wr_bitmap_l = 0x14,
-       .wr_bitmap_u = 0x15,
-       .wr_bitmap_1l = 0x16,
-       .wr_bitmap_1u = 0x17,
-       .rd_len_p0_l = 0x18,
-       .rd_len_p0_u = 0x19,
-       .card_misc_cfg_reg = 0xd8,
-       .card_cfg_2_1_reg = 0xd9,
-       .cmd_rd_len_0 = 0xc0,
-       .cmd_rd_len_1 = 0xc1,
-       .cmd_rd_len_2 = 0xc2,
-       .cmd_rd_len_3 = 0xc3,
-       .cmd_cfg_0 = 0xc4,
-       .cmd_cfg_1 = 0xc5,
-       .cmd_cfg_2 = 0xc6,
-       .cmd_cfg_3 = 0xc7,
-       .fw_dump_host_ready = 0xcc,
-       .fw_dump_ctrl = 0xf0,
-       .fw_dump_start = 0xf1,
-       .fw_dump_end = 0xf8,
-       .func1_dump_reg_start = 0x10,
-       .func1_dump_reg_end = 0x17,
-       .func1_scratch_reg = 0xe8,
-       .func1_spec_reg_num = 13,
-       .func1_spec_reg_table = {0x08, 0x58, 0x5C, 0x5D,
-                                0x60, 0x61, 0x62, 0x64,
-                                0x65, 0x66, 0x68, 0x69,
-                                0x6a},
-};
-
-static const struct mwifiex_sdio_card_reg mwifiex_reg_sd8887 = {
-       .start_rd_port = 0,
-       .start_wr_port = 0,
-       .base_0_reg = 0x6C,
-       .base_1_reg = 0x6D,
-       .poll_reg = 0x5C,
-       .host_int_enable = UP_LD_HOST_INT_MASK | DN_LD_HOST_INT_MASK |
-                       CMD_PORT_UPLD_INT_MASK | CMD_PORT_DNLD_INT_MASK,
-       .host_int_rsr_reg = 0x4,
-       .host_int_status_reg = 0x0C,
-       .host_int_mask_reg = 0x08,
-       .status_reg_0 = 0x90,
-       .status_reg_1 = 0x91,
-       .sdio_int_mask = 0xff,
-       .data_port_mask = 0xffffffff,
-       .io_port_0_reg = 0xE4,
-       .io_port_1_reg = 0xE5,
-       .io_port_2_reg = 0xE6,
-       .max_mp_regs = 196,
-       .rd_bitmap_l = 0x10,
-       .rd_bitmap_u = 0x11,
-       .rd_bitmap_1l = 0x12,
-       .rd_bitmap_1u = 0x13,
-       .wr_bitmap_l = 0x14,
-       .wr_bitmap_u = 0x15,
-       .wr_bitmap_1l = 0x16,
-       .wr_bitmap_1u = 0x17,
-       .rd_len_p0_l = 0x18,
-       .rd_len_p0_u = 0x19,
-       .card_misc_cfg_reg = 0xd8,
-       .card_cfg_2_1_reg = 0xd9,
-       .cmd_rd_len_0 = 0xc0,
-       .cmd_rd_len_1 = 0xc1,
-       .cmd_rd_len_2 = 0xc2,
-       .cmd_rd_len_3 = 0xc3,
-       .cmd_cfg_0 = 0xc4,
-       .cmd_cfg_1 = 0xc5,
-       .cmd_cfg_2 = 0xc6,
-       .cmd_cfg_3 = 0xc7,
-       .func1_dump_reg_start = 0x10,
-       .func1_dump_reg_end = 0x17,
-       .func1_scratch_reg = 0x90,
-       .func1_spec_reg_num = 13,
-       .func1_spec_reg_table = {0x08, 0x58, 0x5C, 0x5D, 0x60,
-                                0x61, 0x62, 0x64, 0x65, 0x66,
-                                0x68, 0x69, 0x6a},
-};
-
-static const struct mwifiex_sdio_device mwifiex_sdio_sd8786 = {
-       .firmware = SD8786_DEFAULT_FW_NAME,
-       .reg = &mwifiex_reg_sd87xx,
-       .max_ports = 16,
-       .mp_agg_pkt_limit = 8,
-       .tx_buf_size = MWIFIEX_TX_DATA_BUF_SIZE_2K,
-       .mp_tx_agg_buf_size = MWIFIEX_MP_AGGR_BUF_SIZE_16K,
-       .mp_rx_agg_buf_size = MWIFIEX_MP_AGGR_BUF_SIZE_16K,
-       .supports_sdio_new_mode = false,
-       .has_control_mask = true,
-       .can_dump_fw = false,
-       .can_auto_tdls = false,
-       .can_ext_scan = false,
-};
-
-static const struct mwifiex_sdio_device mwifiex_sdio_sd8787 = {
-       .firmware = SD8787_DEFAULT_FW_NAME,
-       .reg = &mwifiex_reg_sd87xx,
-       .max_ports = 16,
-       .mp_agg_pkt_limit = 8,
-       .tx_buf_size = MWIFIEX_TX_DATA_BUF_SIZE_2K,
-       .mp_tx_agg_buf_size = MWIFIEX_MP_AGGR_BUF_SIZE_16K,
-       .mp_rx_agg_buf_size = MWIFIEX_MP_AGGR_BUF_SIZE_16K,
-       .supports_sdio_new_mode = false,
-       .has_control_mask = true,
-       .can_dump_fw = false,
-       .can_auto_tdls = false,
-       .can_ext_scan = true,
-};
-
-static const struct mwifiex_sdio_device mwifiex_sdio_sd8797 = {
-       .firmware = SD8797_DEFAULT_FW_NAME,
-       .reg = &mwifiex_reg_sd87xx,
-       .max_ports = 16,
-       .mp_agg_pkt_limit = 8,
-       .tx_buf_size = MWIFIEX_TX_DATA_BUF_SIZE_2K,
-       .mp_tx_agg_buf_size = MWIFIEX_MP_AGGR_BUF_SIZE_16K,
-       .mp_rx_agg_buf_size = MWIFIEX_MP_AGGR_BUF_SIZE_16K,
-       .supports_sdio_new_mode = false,
-       .has_control_mask = true,
-       .can_dump_fw = false,
-       .can_auto_tdls = false,
-       .can_ext_scan = true,
-};
-
-static const struct mwifiex_sdio_device mwifiex_sdio_sd8897 = {
-       .firmware = SD8897_DEFAULT_FW_NAME,
-       .reg = &mwifiex_reg_sd8897,
-       .max_ports = 32,
-       .mp_agg_pkt_limit = 16,
-       .tx_buf_size = MWIFIEX_TX_DATA_BUF_SIZE_4K,
-       .mp_tx_agg_buf_size = MWIFIEX_MP_AGGR_BUF_SIZE_MAX,
-       .mp_rx_agg_buf_size = MWIFIEX_MP_AGGR_BUF_SIZE_MAX,
-       .supports_sdio_new_mode = true,
-       .has_control_mask = false,
-       .can_dump_fw = true,
-       .can_auto_tdls = false,
-       .can_ext_scan = true,
-};
-
-static const struct mwifiex_sdio_device mwifiex_sdio_sd8997 = {
-       .firmware = SD8997_DEFAULT_FW_NAME,
-       .reg = &mwifiex_reg_sd8997,
-       .max_ports = 32,
-       .mp_agg_pkt_limit = 16,
-       .tx_buf_size = MWIFIEX_TX_DATA_BUF_SIZE_4K,
-       .mp_tx_agg_buf_size = MWIFIEX_MP_AGGR_BUF_SIZE_MAX,
-       .mp_rx_agg_buf_size = MWIFIEX_MP_AGGR_BUF_SIZE_MAX,
-       .supports_sdio_new_mode = true,
-       .has_control_mask = false,
-       .can_dump_fw = true,
-       .fw_dump_enh = true,
-       .can_auto_tdls = false,
-       .can_ext_scan = true,
-};
-
-static const struct mwifiex_sdio_device mwifiex_sdio_sd8887 = {
-       .firmware = SD8887_DEFAULT_FW_NAME,
-       .reg = &mwifiex_reg_sd8887,
-       .max_ports = 32,
-       .mp_agg_pkt_limit = 16,
-       .tx_buf_size = MWIFIEX_TX_DATA_BUF_SIZE_2K,
-       .mp_tx_agg_buf_size = MWIFIEX_MP_AGGR_BUF_SIZE_32K,
-       .mp_rx_agg_buf_size = MWIFIEX_MP_AGGR_BUF_SIZE_32K,
-       .supports_sdio_new_mode = true,
-       .has_control_mask = false,
-       .can_dump_fw = false,
-       .can_auto_tdls = true,
-       .can_ext_scan = true,
-};
-
-static const struct mwifiex_sdio_device mwifiex_sdio_sd8801 = {
-       .firmware = SD8801_DEFAULT_FW_NAME,
-       .reg = &mwifiex_reg_sd87xx,
-       .max_ports = 16,
-       .mp_agg_pkt_limit = 8,
-       .supports_sdio_new_mode = false,
-       .has_control_mask = true,
-       .tx_buf_size = MWIFIEX_TX_DATA_BUF_SIZE_2K,
-       .mp_tx_agg_buf_size = MWIFIEX_MP_AGGR_BUF_SIZE_16K,
-       .mp_rx_agg_buf_size = MWIFIEX_MP_AGGR_BUF_SIZE_16K,
-       .can_dump_fw = false,
-       .can_auto_tdls = false,
-       .can_ext_scan = true,
-};
-
-/*
- * .cmdrsp_complete handler
- */
-static inline int mwifiex_sdio_cmdrsp_complete(struct mwifiex_adapter *adapter,
-                                              struct sk_buff *skb)
-{
-       dev_kfree_skb_any(skb);
-       return 0;
-}
-
-/*
- * .event_complete handler
- */
-static inline int mwifiex_sdio_event_complete(struct mwifiex_adapter *adapter,
-                                             struct sk_buff *skb)
-{
-       dev_kfree_skb_any(skb);
-       return 0;
-}
-
-static inline bool
-mp_rx_aggr_port_limit_reached(struct sdio_mmc_card *card)
-{
-       u8 tmp;
-
-       if (card->curr_rd_port < card->mpa_rx.start_port) {
-               if (card->supports_sdio_new_mode)
-                       tmp = card->mp_end_port >> 1;
-               else
-                       tmp = card->mp_agg_pkt_limit;
-
-               if (((card->max_ports - card->mpa_rx.start_port) +
-                   card->curr_rd_port) >= tmp)
-                       return true;
-       }
-
-       if (!card->supports_sdio_new_mode)
-               return false;
-
-       if ((card->curr_rd_port - card->mpa_rx.start_port) >=
-           (card->mp_end_port >> 1))
-               return true;
-
-       return false;
-}
-
-static inline bool
-mp_tx_aggr_port_limit_reached(struct sdio_mmc_card *card)
-{
-       u16 tmp;
-
-       if (card->curr_wr_port < card->mpa_tx.start_port) {
-               if (card->supports_sdio_new_mode)
-                       tmp = card->mp_end_port >> 1;
-               else
-                       tmp = card->mp_agg_pkt_limit;
-
-               if (((card->max_ports - card->mpa_tx.start_port) +
-                   card->curr_wr_port) >= tmp)
-                       return true;
-       }
-
-       if (!card->supports_sdio_new_mode)
-               return false;
-
-       if ((card->curr_wr_port - card->mpa_tx.start_port) >=
-           (card->mp_end_port >> 1))
-               return true;
-
-       return false;
-}
-
-/* Prepare to copy current packet from card to SDIO Rx aggregation buffer */
-static inline void mp_rx_aggr_setup(struct sdio_mmc_card *card,
-                                   u16 rx_len, u8 port)
-{
-       card->mpa_rx.buf_len += rx_len;
-
-       if (!card->mpa_rx.pkt_cnt)
-               card->mpa_rx.start_port = port;
-
-       if (card->supports_sdio_new_mode) {
-               card->mpa_rx.ports |= (1 << port);
-       } else {
-               if (card->mpa_rx.start_port <= port)
-                       card->mpa_rx.ports |= 1 << (card->mpa_rx.pkt_cnt);
-               else
-                       card->mpa_rx.ports |= 1 << (card->mpa_rx.pkt_cnt + 1);
-       }
-       card->mpa_rx.skb_arr[card->mpa_rx.pkt_cnt] = NULL;
-       card->mpa_rx.len_arr[card->mpa_rx.pkt_cnt] = rx_len;
-       card->mpa_rx.pkt_cnt++;
-}
-#endif /* _MWIFIEX_SDIO_H */
diff --git a/drivers/net/wireless/mwifiex/sta_cmd.c b/drivers/net/wireless/mwifiex/sta_cmd.c
deleted file mode 100644 (file)
index e486867..0000000
+++ /dev/null
@@ -1,2282 +0,0 @@
-/*
- * Marvell Wireless LAN device driver: station command handling
- *
- * Copyright (C) 2011-2014, Marvell International Ltd.
- *
- * This software file (the "File") is distributed by Marvell International
- * Ltd. under the terms of the GNU General Public License Version 2, June 1991
- * (the "License").  You may use, redistribute and/or modify this File in
- * accordance with the terms and conditions of the License, a copy of which
- * is available by writing to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the
- * worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
- *
- * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
- * ARE EXPRESSLY DISCLAIMED.  The License provides additional details about
- * this warranty disclaimer.
- */
-
-#include "decl.h"
-#include "ioctl.h"
-#include "util.h"
-#include "fw.h"
-#include "main.h"
-#include "wmm.h"
-#include "11n.h"
-#include "11ac.h"
-
-static bool drcs;
-module_param(drcs, bool, 0644);
-MODULE_PARM_DESC(drcs, "multi-channel operation:1, single-channel operation:0");
-
-static bool disable_auto_ds;
-module_param(disable_auto_ds, bool, 0);
-MODULE_PARM_DESC(disable_auto_ds,
-                "deepsleep enabled=0(default), deepsleep disabled=1");
-/*
- * This function prepares command to set/get RSSI information.
- *
- * Preparation includes -
- *      - Setting command ID, action and proper size
- *      - Setting data/beacon average factors
- *      - Resetting SNR/NF/RSSI values in private structure
- *      - Ensuring correct endian-ness
- */
-static int
-mwifiex_cmd_802_11_rssi_info(struct mwifiex_private *priv,
-                            struct host_cmd_ds_command *cmd, u16 cmd_action)
-{
-       cmd->command = cpu_to_le16(HostCmd_CMD_RSSI_INFO);
-       cmd->size = cpu_to_le16(sizeof(struct host_cmd_ds_802_11_rssi_info) +
-                               S_DS_GEN);
-       cmd->params.rssi_info.action = cpu_to_le16(cmd_action);
-       cmd->params.rssi_info.ndata = cpu_to_le16(priv->data_avg_factor);
-       cmd->params.rssi_info.nbcn = cpu_to_le16(priv->bcn_avg_factor);
-
-       /* Reset SNR/NF/RSSI values in private structure */
-       priv->data_rssi_last = 0;
-       priv->data_nf_last = 0;
-       priv->data_rssi_avg = 0;
-       priv->data_nf_avg = 0;
-       priv->bcn_rssi_last = 0;
-       priv->bcn_nf_last = 0;
-       priv->bcn_rssi_avg = 0;
-       priv->bcn_nf_avg = 0;
-
-       return 0;
-}
-
-/*
- * This function prepares command to set MAC control.
- *
- * Preparation includes -
- *      - Setting command ID, action and proper size
- *      - Ensuring correct endian-ness
- */
-static int mwifiex_cmd_mac_control(struct mwifiex_private *priv,
-                                  struct host_cmd_ds_command *cmd,
-                                  u16 cmd_action, u16 *action)
-{
-       struct host_cmd_ds_mac_control *mac_ctrl = &cmd->params.mac_ctrl;
-
-       if (cmd_action != HostCmd_ACT_GEN_SET) {
-               mwifiex_dbg(priv->adapter, ERROR,
-                           "mac_control: only support set cmd\n");
-               return -1;
-       }
-
-       cmd->command = cpu_to_le16(HostCmd_CMD_MAC_CONTROL);
-       cmd->size =
-               cpu_to_le16(sizeof(struct host_cmd_ds_mac_control) + S_DS_GEN);
-       mac_ctrl->action = cpu_to_le16(*action);
-
-       return 0;
-}
-
-/*
- * This function prepares command to set/get SNMP MIB.
- *
- * Preparation includes -
- *      - Setting command ID, action and proper size
- *      - Setting SNMP MIB OID number and value
- *        (as required)
- *      - Ensuring correct endian-ness
- *
- * The following SNMP MIB OIDs are supported -
- *      - FRAG_THRESH_I     : Fragmentation threshold
- *      - RTS_THRESH_I      : RTS threshold
- *      - SHORT_RETRY_LIM_I : Short retry limit
- *      - DOT11D_I          : 11d support
- */
-static int mwifiex_cmd_802_11_snmp_mib(struct mwifiex_private *priv,
-                                      struct host_cmd_ds_command *cmd,
-                                      u16 cmd_action, u32 cmd_oid,
-                                      u16 *ul_temp)
-{
-       struct host_cmd_ds_802_11_snmp_mib *snmp_mib = &cmd->params.smib;
-
-       mwifiex_dbg(priv->adapter, CMD,
-                   "cmd: SNMP_CMD: cmd_oid = 0x%x\n", cmd_oid);
-       cmd->command = cpu_to_le16(HostCmd_CMD_802_11_SNMP_MIB);
-       cmd->size = cpu_to_le16(sizeof(struct host_cmd_ds_802_11_snmp_mib)
-                               - 1 + S_DS_GEN);
-
-       snmp_mib->oid = cpu_to_le16((u16)cmd_oid);
-       if (cmd_action == HostCmd_ACT_GEN_GET) {
-               snmp_mib->query_type = cpu_to_le16(HostCmd_ACT_GEN_GET);
-               snmp_mib->buf_size = cpu_to_le16(MAX_SNMP_BUF_SIZE);
-               le16_add_cpu(&cmd->size, MAX_SNMP_BUF_SIZE);
-       } else if (cmd_action == HostCmd_ACT_GEN_SET) {
-               snmp_mib->query_type = cpu_to_le16(HostCmd_ACT_GEN_SET);
-               snmp_mib->buf_size = cpu_to_le16(sizeof(u16));
-               *((__le16 *) (snmp_mib->value)) = cpu_to_le16(*ul_temp);
-               le16_add_cpu(&cmd->size, sizeof(u16));
-       }
-
-       mwifiex_dbg(priv->adapter, CMD,
-                   "cmd: SNMP_CMD: Action=0x%x, OID=0x%x,\t"
-                   "OIDSize=0x%x, Value=0x%x\n",
-                   cmd_action, cmd_oid, le16_to_cpu(snmp_mib->buf_size),
-                   le16_to_cpu(*(__le16 *)snmp_mib->value));
-       return 0;
-}
-
-/*
- * This function prepares command to get log.
- *
- * Preparation includes -
- *      - Setting command ID and proper size
- *      - Ensuring correct endian-ness
- */
-static int
-mwifiex_cmd_802_11_get_log(struct host_cmd_ds_command *cmd)
-{
-       cmd->command = cpu_to_le16(HostCmd_CMD_802_11_GET_LOG);
-       cmd->size = cpu_to_le16(sizeof(struct host_cmd_ds_802_11_get_log) +
-                               S_DS_GEN);
-       return 0;
-}
-
-/*
- * This function prepares command to set/get Tx data rate configuration.
- *
- * Preparation includes -
- *      - Setting command ID, action and proper size
- *      - Setting configuration index, rate scope and rate drop pattern
- *        parameters (as required)
- *      - Ensuring correct endian-ness
- */
-static int mwifiex_cmd_tx_rate_cfg(struct mwifiex_private *priv,
-                                  struct host_cmd_ds_command *cmd,
-                                  u16 cmd_action, u16 *pbitmap_rates)
-{
-       struct host_cmd_ds_tx_rate_cfg *rate_cfg = &cmd->params.tx_rate_cfg;
-       struct mwifiex_rate_scope *rate_scope;
-       struct mwifiex_rate_drop_pattern *rate_drop;
-       u32 i;
-
-       cmd->command = cpu_to_le16(HostCmd_CMD_TX_RATE_CFG);
-
-       rate_cfg->action = cpu_to_le16(cmd_action);
-       rate_cfg->cfg_index = 0;
-
-       rate_scope = (struct mwifiex_rate_scope *) ((u8 *) rate_cfg +
-                     sizeof(struct host_cmd_ds_tx_rate_cfg));
-       rate_scope->type = cpu_to_le16(TLV_TYPE_RATE_SCOPE);
-       rate_scope->length = cpu_to_le16
-               (sizeof(*rate_scope) - sizeof(struct mwifiex_ie_types_header));
-       if (pbitmap_rates != NULL) {
-               rate_scope->hr_dsss_rate_bitmap = cpu_to_le16(pbitmap_rates[0]);
-               rate_scope->ofdm_rate_bitmap = cpu_to_le16(pbitmap_rates[1]);
-               for (i = 0;
-                    i < sizeof(rate_scope->ht_mcs_rate_bitmap) / sizeof(u16);
-                    i++)
-                       rate_scope->ht_mcs_rate_bitmap[i] =
-                               cpu_to_le16(pbitmap_rates[2 + i]);
-               if (priv->adapter->fw_api_ver == MWIFIEX_FW_V15) {
-                       for (i = 0;
-                            i < ARRAY_SIZE(rate_scope->vht_mcs_rate_bitmap);
-                            i++)
-                               rate_scope->vht_mcs_rate_bitmap[i] =
-                                       cpu_to_le16(pbitmap_rates[10 + i]);
-               }
-       } else {
-               rate_scope->hr_dsss_rate_bitmap =
-                       cpu_to_le16(priv->bitmap_rates[0]);
-               rate_scope->ofdm_rate_bitmap =
-                       cpu_to_le16(priv->bitmap_rates[1]);
-               for (i = 0;
-                    i < sizeof(rate_scope->ht_mcs_rate_bitmap) / sizeof(u16);
-                    i++)
-                       rate_scope->ht_mcs_rate_bitmap[i] =
-                               cpu_to_le16(priv->bitmap_rates[2 + i]);
-               if (priv->adapter->fw_api_ver == MWIFIEX_FW_V15) {
-                       for (i = 0;
-                            i < ARRAY_SIZE(rate_scope->vht_mcs_rate_bitmap);
-                            i++)
-                               rate_scope->vht_mcs_rate_bitmap[i] =
-                                       cpu_to_le16(priv->bitmap_rates[10 + i]);
-               }
-       }
-
-       rate_drop = (struct mwifiex_rate_drop_pattern *) ((u8 *) rate_scope +
-                                            sizeof(struct mwifiex_rate_scope));
-       rate_drop->type = cpu_to_le16(TLV_TYPE_RATE_DROP_CONTROL);
-       rate_drop->length = cpu_to_le16(sizeof(rate_drop->rate_drop_mode));
-       rate_drop->rate_drop_mode = 0;
-
-       cmd->size =
-               cpu_to_le16(S_DS_GEN + sizeof(struct host_cmd_ds_tx_rate_cfg) +
-                           sizeof(struct mwifiex_rate_scope) +
-                           sizeof(struct mwifiex_rate_drop_pattern));
-
-       return 0;
-}
-
-/*
- * This function prepares command to set/get Tx power configuration.
- *
- * Preparation includes -
- *      - Setting command ID, action and proper size
- *      - Setting Tx power mode, power group TLV
- *        (as required)
- *      - Ensuring correct endian-ness
- */
-static int mwifiex_cmd_tx_power_cfg(struct host_cmd_ds_command *cmd,
-                                   u16 cmd_action,
-                                   struct host_cmd_ds_txpwr_cfg *txp)
-{
-       struct mwifiex_types_power_group *pg_tlv;
-       struct host_cmd_ds_txpwr_cfg *cmd_txp_cfg = &cmd->params.txp_cfg;
-
-       cmd->command = cpu_to_le16(HostCmd_CMD_TXPWR_CFG);
-       cmd->size =
-               cpu_to_le16(S_DS_GEN + sizeof(struct host_cmd_ds_txpwr_cfg));
-       switch (cmd_action) {
-       case HostCmd_ACT_GEN_SET:
-               if (txp->mode) {
-                       pg_tlv = (struct mwifiex_types_power_group
-                                 *) ((unsigned long) txp +
-                                    sizeof(struct host_cmd_ds_txpwr_cfg));
-                       memmove(cmd_txp_cfg, txp,
-                               sizeof(struct host_cmd_ds_txpwr_cfg) +
-                               sizeof(struct mwifiex_types_power_group) +
-                               le16_to_cpu(pg_tlv->length));
-
-                       pg_tlv = (struct mwifiex_types_power_group *) ((u8 *)
-                                 cmd_txp_cfg +
-                                 sizeof(struct host_cmd_ds_txpwr_cfg));
-                       cmd->size = cpu_to_le16(le16_to_cpu(cmd->size) +
-                                 sizeof(struct mwifiex_types_power_group) +
-                                 le16_to_cpu(pg_tlv->length));
-               } else {
-                       memmove(cmd_txp_cfg, txp, sizeof(*txp));
-               }
-               cmd_txp_cfg->action = cpu_to_le16(cmd_action);
-               break;
-       case HostCmd_ACT_GEN_GET:
-               cmd_txp_cfg->action = cpu_to_le16(cmd_action);
-               break;
-       }
-
-       return 0;
-}
-
-/*
- * This function prepares command to get RF Tx power.
- */
-static int mwifiex_cmd_rf_tx_power(struct mwifiex_private *priv,
-                                  struct host_cmd_ds_command *cmd,
-                                  u16 cmd_action, void *data_buf)
-{
-       struct host_cmd_ds_rf_tx_pwr *txp = &cmd->params.txp;
-
-       cmd->size = cpu_to_le16(sizeof(struct host_cmd_ds_rf_tx_pwr)
-                               + S_DS_GEN);
-       cmd->command = cpu_to_le16(HostCmd_CMD_RF_TX_PWR);
-       txp->action = cpu_to_le16(cmd_action);
-
-       return 0;
-}
-
-/*
- * This function prepares command to set rf antenna.
- */
-static int mwifiex_cmd_rf_antenna(struct mwifiex_private *priv,
-                                 struct host_cmd_ds_command *cmd,
-                                 u16 cmd_action,
-                                 struct mwifiex_ds_ant_cfg *ant_cfg)
-{
-       struct host_cmd_ds_rf_ant_mimo *ant_mimo = &cmd->params.ant_mimo;
-       struct host_cmd_ds_rf_ant_siso *ant_siso = &cmd->params.ant_siso;
-
-       cmd->command = cpu_to_le16(HostCmd_CMD_RF_ANTENNA);
-
-       if (cmd_action != HostCmd_ACT_GEN_SET)
-               return 0;
-
-       if (priv->adapter->hw_dev_mcs_support == HT_STREAM_2X2) {
-               cmd->size = cpu_to_le16(sizeof(struct host_cmd_ds_rf_ant_mimo) +
-                                       S_DS_GEN);
-               ant_mimo->action_tx = cpu_to_le16(HostCmd_ACT_SET_TX);
-               ant_mimo->tx_ant_mode = cpu_to_le16((u16)ant_cfg->tx_ant);
-               ant_mimo->action_rx = cpu_to_le16(HostCmd_ACT_SET_RX);
-               ant_mimo->rx_ant_mode = cpu_to_le16((u16)ant_cfg->rx_ant);
-       } else {
-               cmd->size = cpu_to_le16(sizeof(struct host_cmd_ds_rf_ant_siso) +
-                                       S_DS_GEN);
-               ant_siso->action = cpu_to_le16(HostCmd_ACT_SET_BOTH);
-               ant_siso->ant_mode = cpu_to_le16((u16)ant_cfg->tx_ant);
-       }
-
-       return 0;
-}
-
-/*
- * This function prepares command to set Host Sleep configuration.
- *
- * Preparation includes -
- *      - Setting command ID and proper size
- *      - Setting Host Sleep action, conditions, ARP filters
- *        (as required)
- *      - Ensuring correct endian-ness
- */
-static int
-mwifiex_cmd_802_11_hs_cfg(struct mwifiex_private *priv,
-                         struct host_cmd_ds_command *cmd,
-                         u16 cmd_action,
-                         struct mwifiex_hs_config_param *hscfg_param)
-{
-       struct mwifiex_adapter *adapter = priv->adapter;
-       struct host_cmd_ds_802_11_hs_cfg_enh *hs_cfg = &cmd->params.opt_hs_cfg;
-       bool hs_activate = false;
-
-       if (!hscfg_param)
-               /* New Activate command */
-               hs_activate = true;
-       cmd->command = cpu_to_le16(HostCmd_CMD_802_11_HS_CFG_ENH);
-
-       if (!hs_activate &&
-           (hscfg_param->conditions != cpu_to_le32(HS_CFG_CANCEL)) &&
-           ((adapter->arp_filter_size > 0) &&
-            (adapter->arp_filter_size <= ARP_FILTER_MAX_BUF_SIZE))) {
-               mwifiex_dbg(adapter, CMD,
-                           "cmd: Attach %d bytes ArpFilter to HSCfg cmd\n",
-                           adapter->arp_filter_size);
-               memcpy(((u8 *) hs_cfg) +
-                      sizeof(struct host_cmd_ds_802_11_hs_cfg_enh),
-                      adapter->arp_filter, adapter->arp_filter_size);
-               cmd->size = cpu_to_le16
-                               (adapter->arp_filter_size +
-                                sizeof(struct host_cmd_ds_802_11_hs_cfg_enh)
-                               + S_DS_GEN);
-       } else {
-               cmd->size = cpu_to_le16(S_DS_GEN + sizeof(struct
-                                               host_cmd_ds_802_11_hs_cfg_enh));
-       }
-       if (hs_activate) {
-               hs_cfg->action = cpu_to_le16(HS_ACTIVATE);
-               hs_cfg->params.hs_activate.resp_ctrl = cpu_to_le16(RESP_NEEDED);
-       } else {
-               hs_cfg->action = cpu_to_le16(HS_CONFIGURE);
-               hs_cfg->params.hs_config.conditions = hscfg_param->conditions;
-               hs_cfg->params.hs_config.gpio = hscfg_param->gpio;
-               hs_cfg->params.hs_config.gap = hscfg_param->gap;
-               mwifiex_dbg(adapter, CMD,
-                           "cmd: HS_CFG_CMD: condition:0x%x gpio:0x%x gap:0x%x\n",
-                           hs_cfg->params.hs_config.conditions,
-                           hs_cfg->params.hs_config.gpio,
-                           hs_cfg->params.hs_config.gap);
-       }
-
-       return 0;
-}
-
-/*
- * This function prepares command to set/get MAC address.
- *
- * Preparation includes -
- *      - Setting command ID, action and proper size
- *      - Setting MAC address (for SET only)
- *      - Ensuring correct endian-ness
- */
-static int mwifiex_cmd_802_11_mac_address(struct mwifiex_private *priv,
-                                         struct host_cmd_ds_command *cmd,
-                                         u16 cmd_action)
-{
-       cmd->command = cpu_to_le16(HostCmd_CMD_802_11_MAC_ADDRESS);
-       cmd->size = cpu_to_le16(sizeof(struct host_cmd_ds_802_11_mac_address) +
-                               S_DS_GEN);
-       cmd->result = 0;
-
-       cmd->params.mac_addr.action = cpu_to_le16(cmd_action);
-
-       if (cmd_action == HostCmd_ACT_GEN_SET)
-               memcpy(cmd->params.mac_addr.mac_addr, priv->curr_addr,
-                      ETH_ALEN);
-       return 0;
-}
-
-/*
- * This function prepares command to set MAC multicast address.
- *
- * Preparation includes -
- *      - Setting command ID, action and proper size
- *      - Setting MAC multicast address
- *      - Ensuring correct endian-ness
- */
-static int
-mwifiex_cmd_mac_multicast_adr(struct host_cmd_ds_command *cmd,
-                             u16 cmd_action,
-                             struct mwifiex_multicast_list *mcast_list)
-{
-       struct host_cmd_ds_mac_multicast_adr *mcast_addr = &cmd->params.mc_addr;
-
-       cmd->size = cpu_to_le16(sizeof(struct host_cmd_ds_mac_multicast_adr) +
-                               S_DS_GEN);
-       cmd->command = cpu_to_le16(HostCmd_CMD_MAC_MULTICAST_ADR);
-
-       mcast_addr->action = cpu_to_le16(cmd_action);
-       mcast_addr->num_of_adrs =
-               cpu_to_le16((u16) mcast_list->num_multicast_addr);
-       memcpy(mcast_addr->mac_list, mcast_list->mac_list,
-              mcast_list->num_multicast_addr * ETH_ALEN);
-
-       return 0;
-}
-
-/*
- * This function prepares command to deauthenticate.
- *
- * Preparation includes -
- *      - Setting command ID and proper size
- *      - Setting AP MAC address and reason code
- *      - Ensuring correct endian-ness
- */
-static int mwifiex_cmd_802_11_deauthenticate(struct mwifiex_private *priv,
-                                            struct host_cmd_ds_command *cmd,
-                                            u8 *mac)
-{
-       struct host_cmd_ds_802_11_deauthenticate *deauth = &cmd->params.deauth;
-
-       cmd->command = cpu_to_le16(HostCmd_CMD_802_11_DEAUTHENTICATE);
-       cmd->size = cpu_to_le16(sizeof(struct host_cmd_ds_802_11_deauthenticate)
-                               + S_DS_GEN);
-
-       /* Set AP MAC address */
-       memcpy(deauth->mac_addr, mac, ETH_ALEN);
-
-       mwifiex_dbg(priv->adapter, CMD, "cmd: Deauth: %pM\n", deauth->mac_addr);
-
-       deauth->reason_code = cpu_to_le16(WLAN_REASON_DEAUTH_LEAVING);
-
-       return 0;
-}
-
-/*
- * This function prepares command to stop Ad-Hoc network.
- *
- * Preparation includes -
- *      - Setting command ID and proper size
- *      - Ensuring correct endian-ness
- */
-static int mwifiex_cmd_802_11_ad_hoc_stop(struct host_cmd_ds_command *cmd)
-{
-       cmd->command = cpu_to_le16(HostCmd_CMD_802_11_AD_HOC_STOP);
-       cmd->size = cpu_to_le16(S_DS_GEN);
-       return 0;
-}
-
-/*
- * This function sets WEP key(s) to key parameter TLV(s).
- *
- * Multi-key parameter TLVs are supported, so we can send multiple
- * WEP keys in a single buffer.
- */
-static int
-mwifiex_set_keyparamset_wep(struct mwifiex_private *priv,
-                           struct mwifiex_ie_type_key_param_set *key_param_set,
-                           u16 *key_param_len)
-{
-       int cur_key_param_len;
-       u8 i;
-
-       /* Multi-key_param_set TLV is supported */
-       for (i = 0; i < NUM_WEP_KEYS; i++) {
-               if ((priv->wep_key[i].key_length == WLAN_KEY_LEN_WEP40) ||
-                   (priv->wep_key[i].key_length == WLAN_KEY_LEN_WEP104)) {
-                       key_param_set->type =
-                               cpu_to_le16(TLV_TYPE_KEY_MATERIAL);
-/* Key_param_set WEP fixed length */
-#define KEYPARAMSET_WEP_FIXED_LEN 8
-                       key_param_set->length = cpu_to_le16((u16)
-                                       (priv->wep_key[i].
-                                        key_length +
-                                        KEYPARAMSET_WEP_FIXED_LEN));
-                       key_param_set->key_type_id =
-                               cpu_to_le16(KEY_TYPE_ID_WEP);
-                       key_param_set->key_info =
-                               cpu_to_le16(KEY_ENABLED | KEY_UNICAST |
-                                           KEY_MCAST);
-                       key_param_set->key_len =
-                               cpu_to_le16(priv->wep_key[i].key_length);
-                       /* Set WEP key index */
-                       key_param_set->key[0] = i;
-                       /* Set default Tx key flag */
-                       if (i ==
-                           (priv->
-                            wep_key_curr_index & HostCmd_WEP_KEY_INDEX_MASK))
-                               key_param_set->key[1] = 1;
-                       else
-                               key_param_set->key[1] = 0;
-                       memmove(&key_param_set->key[2],
-                               priv->wep_key[i].key_material,
-                               priv->wep_key[i].key_length);
-
-                       cur_key_param_len = priv->wep_key[i].key_length +
-                               KEYPARAMSET_WEP_FIXED_LEN +
-                               sizeof(struct mwifiex_ie_types_header);
-                       *key_param_len += (u16) cur_key_param_len;
-                       key_param_set =
-                               (struct mwifiex_ie_type_key_param_set *)
-                                               ((u8 *)key_param_set +
-                                                cur_key_param_len);
-               } else if (!priv->wep_key[i].key_length) {
-                       continue;
-               } else {
-                       mwifiex_dbg(priv->adapter, ERROR,
-                                   "key%d Length = %d is incorrect\n",
-                                   (i + 1), priv->wep_key[i].key_length);
-                       return -1;
-               }
-       }
-
-       return 0;
-}
-
-/* This function populates key material v2 command
- * to set network key for AES & CMAC AES.
- */
-static int mwifiex_set_aes_key_v2(struct mwifiex_private *priv,
-                                 struct host_cmd_ds_command *cmd,
-                                 struct mwifiex_ds_encrypt_key *enc_key,
-                                 struct host_cmd_ds_802_11_key_material_v2 *km)
-{
-       struct mwifiex_adapter *adapter = priv->adapter;
-       u16 size, len = KEY_PARAMS_FIXED_LEN;
-
-       if (enc_key->is_igtk_key) {
-               mwifiex_dbg(adapter, INFO,
-                           "%s: Set CMAC AES Key\n", __func__);
-               if (enc_key->is_rx_seq_valid)
-                       memcpy(km->key_param_set.key_params.cmac_aes.ipn,
-                              enc_key->pn, enc_key->pn_len);
-               km->key_param_set.key_info &= cpu_to_le16(~KEY_MCAST);
-               km->key_param_set.key_info |= cpu_to_le16(KEY_IGTK);
-               km->key_param_set.key_type = KEY_TYPE_ID_AES_CMAC;
-               km->key_param_set.key_params.cmac_aes.key_len =
-                                         cpu_to_le16(enc_key->key_len);
-               memcpy(km->key_param_set.key_params.cmac_aes.key,
-                      enc_key->key_material, enc_key->key_len);
-               len += sizeof(struct mwifiex_cmac_aes_param);
-       } else {
-               mwifiex_dbg(adapter, INFO,
-                           "%s: Set AES Key\n", __func__);
-               if (enc_key->is_rx_seq_valid)
-                       memcpy(km->key_param_set.key_params.aes.pn,
-                              enc_key->pn, enc_key->pn_len);
-               km->key_param_set.key_type = KEY_TYPE_ID_AES;
-               km->key_param_set.key_params.aes.key_len =
-                                         cpu_to_le16(enc_key->key_len);
-               memcpy(km->key_param_set.key_params.aes.key,
-                      enc_key->key_material, enc_key->key_len);
-               len += sizeof(struct mwifiex_aes_param);
-       }
-
-       km->key_param_set.len = cpu_to_le16(len);
-       size = len + sizeof(struct mwifiex_ie_types_header) +
-              sizeof(km->action) + S_DS_GEN;
-       cmd->size = cpu_to_le16(size);
-
-       return 0;
-}
-
-/* This function prepares command to set/get/reset network key(s).
- * This function prepares key material command for V2 format.
- * Preparation includes -
- *      - Setting command ID, action and proper size
- *      - Setting WEP keys, WAPI keys or WPA keys along with required
- *        encryption (TKIP, AES) (as required)
- *      - Ensuring correct endian-ness
- */
-static int
-mwifiex_cmd_802_11_key_material_v2(struct mwifiex_private *priv,
-                                  struct host_cmd_ds_command *cmd,
-                                  u16 cmd_action, u32 cmd_oid,
-                                  struct mwifiex_ds_encrypt_key *enc_key)
-{
-       struct mwifiex_adapter *adapter = priv->adapter;
-       u8 *mac = enc_key->mac_addr;
-       u16 key_info, len = KEY_PARAMS_FIXED_LEN;
-       struct host_cmd_ds_802_11_key_material_v2 *km =
-                                               &cmd->params.key_material_v2;
-
-       cmd->command = cpu_to_le16(HostCmd_CMD_802_11_KEY_MATERIAL);
-       km->action = cpu_to_le16(cmd_action);
-
-       if (cmd_action == HostCmd_ACT_GEN_GET) {
-               mwifiex_dbg(adapter, INFO, "%s: Get key\n", __func__);
-               km->key_param_set.key_idx =
-                                       enc_key->key_index & KEY_INDEX_MASK;
-               km->key_param_set.type = cpu_to_le16(TLV_TYPE_KEY_PARAM_V2);
-               km->key_param_set.len = cpu_to_le16(KEY_PARAMS_FIXED_LEN);
-               memcpy(km->key_param_set.mac_addr, mac, ETH_ALEN);
-
-               if (enc_key->key_index & MWIFIEX_KEY_INDEX_UNICAST)
-                       key_info = KEY_UNICAST;
-               else
-                       key_info = KEY_MCAST;
-
-               if (enc_key->is_igtk_key)
-                       key_info |= KEY_IGTK;
-
-               km->key_param_set.key_info = cpu_to_le16(key_info);
-
-               cmd->size = cpu_to_le16(sizeof(struct mwifiex_ie_types_header) +
-                                       S_DS_GEN + KEY_PARAMS_FIXED_LEN +
-                                       sizeof(km->action));
-               return 0;
-       }
-
-       memset(&km->key_param_set, 0,
-              sizeof(struct mwifiex_ie_type_key_param_set_v2));
-
-       if (enc_key->key_disable) {
-               mwifiex_dbg(adapter, INFO, "%s: Remove key\n", __func__);
-               km->action = cpu_to_le16(HostCmd_ACT_GEN_REMOVE);
-               km->key_param_set.type = cpu_to_le16(TLV_TYPE_KEY_PARAM_V2);
-               km->key_param_set.len = cpu_to_le16(KEY_PARAMS_FIXED_LEN);
-               km->key_param_set.key_idx = enc_key->key_index & KEY_INDEX_MASK;
-               key_info = KEY_MCAST | KEY_UNICAST;
-               km->key_param_set.key_info = cpu_to_le16(key_info);
-               memcpy(km->key_param_set.mac_addr, mac, ETH_ALEN);
-               cmd->size = cpu_to_le16(sizeof(struct mwifiex_ie_types_header) +
-                                       S_DS_GEN + KEY_PARAMS_FIXED_LEN +
-                                       sizeof(km->action));
-               return 0;
-       }
-
-       km->action = cpu_to_le16(HostCmd_ACT_GEN_SET);
-       km->key_param_set.key_idx = enc_key->key_index & KEY_INDEX_MASK;
-       km->key_param_set.type = cpu_to_le16(TLV_TYPE_KEY_PARAM_V2);
-       key_info = KEY_ENABLED;
-       memcpy(km->key_param_set.mac_addr, mac, ETH_ALEN);
-
-       if (enc_key->key_len <= WLAN_KEY_LEN_WEP104) {
-               mwifiex_dbg(adapter, INFO, "%s: Set WEP Key\n", __func__);
-               len += sizeof(struct mwifiex_wep_param);
-               km->key_param_set.len = cpu_to_le16(len);
-               km->key_param_set.key_type = KEY_TYPE_ID_WEP;
-
-               if (GET_BSS_ROLE(priv) == MWIFIEX_BSS_ROLE_UAP) {
-                               key_info |= KEY_MCAST | KEY_UNICAST;
-               } else {
-                       if (enc_key->is_current_wep_key) {
-                               key_info |= KEY_MCAST | KEY_UNICAST;
-                               if (km->key_param_set.key_idx ==
-                                   (priv->wep_key_curr_index & KEY_INDEX_MASK))
-                                       key_info |= KEY_DEFAULT;
-                       } else {
-                               if (mac) {
-                                       if (is_broadcast_ether_addr(mac))
-                                               key_info |= KEY_MCAST;
-                                       else
-                                               key_info |= KEY_UNICAST |
-                                                           KEY_DEFAULT;
-                               } else {
-                                       key_info |= KEY_MCAST;
-                               }
-                       }
-               }
-               km->key_param_set.key_info = cpu_to_le16(key_info);
-
-               km->key_param_set.key_params.wep.key_len =
-                                                 cpu_to_le16(enc_key->key_len);
-               memcpy(km->key_param_set.key_params.wep.key,
-                      enc_key->key_material, enc_key->key_len);
-
-               cmd->size = cpu_to_le16(sizeof(struct mwifiex_ie_types_header) +
-                                       len + sizeof(km->action) + S_DS_GEN);
-               return 0;
-       }
-
-       if (is_broadcast_ether_addr(mac))
-               key_info |= KEY_MCAST | KEY_RX_KEY;
-       else
-               key_info |= KEY_UNICAST | KEY_TX_KEY | KEY_RX_KEY;
-
-       if (enc_key->is_wapi_key) {
-               mwifiex_dbg(adapter, INFO, "%s: Set WAPI Key\n", __func__);
-               km->key_param_set.key_type = KEY_TYPE_ID_WAPI;
-               memcpy(km->key_param_set.key_params.wapi.pn, enc_key->pn,
-                      PN_LEN);
-               km->key_param_set.key_params.wapi.key_len =
-                                               cpu_to_le16(enc_key->key_len);
-               memcpy(km->key_param_set.key_params.wapi.key,
-                      enc_key->key_material, enc_key->key_len);
-               if (is_broadcast_ether_addr(mac))
-                       priv->sec_info.wapi_key_on = true;
-
-               if (!priv->sec_info.wapi_key_on)
-                       key_info |= KEY_DEFAULT;
-               km->key_param_set.key_info = cpu_to_le16(key_info);
-
-               len += sizeof(struct mwifiex_wapi_param);
-               km->key_param_set.len = cpu_to_le16(len);
-               cmd->size = cpu_to_le16(sizeof(struct mwifiex_ie_types_header) +
-                                       len + sizeof(km->action) + S_DS_GEN);
-               return 0;
-       }
-
-       if (priv->bss_mode == NL80211_IFTYPE_ADHOC) {
-               key_info |= KEY_DEFAULT;
-               /* Enable unicast bit for WPA-NONE/ADHOC_AES */
-               if (!priv->sec_info.wpa2_enabled &&
-                   !is_broadcast_ether_addr(mac))
-                       key_info |= KEY_UNICAST;
-       } else {
-               /* Enable default key for WPA/WPA2 */
-               if (!priv->wpa_is_gtk_set)
-                       key_info |= KEY_DEFAULT;
-       }
-
-       km->key_param_set.key_info = cpu_to_le16(key_info);
-
-       if (enc_key->key_len == WLAN_KEY_LEN_CCMP)
-               return mwifiex_set_aes_key_v2(priv, cmd, enc_key, km);
-
-       if (enc_key->key_len == WLAN_KEY_LEN_TKIP) {
-               mwifiex_dbg(adapter, INFO,
-                           "%s: Set TKIP Key\n", __func__);
-               if (enc_key->is_rx_seq_valid)
-                       memcpy(km->key_param_set.key_params.tkip.pn,
-                              enc_key->pn, enc_key->pn_len);
-               km->key_param_set.key_type = KEY_TYPE_ID_TKIP;
-               km->key_param_set.key_params.tkip.key_len =
-                                               cpu_to_le16(enc_key->key_len);
-               memcpy(km->key_param_set.key_params.tkip.key,
-                      enc_key->key_material, enc_key->key_len);
-
-               len += sizeof(struct mwifiex_tkip_param);
-               km->key_param_set.len = cpu_to_le16(len);
-               cmd->size = cpu_to_le16(sizeof(struct mwifiex_ie_types_header) +
-                                       len + sizeof(km->action) + S_DS_GEN);
-       }
-
-       return 0;
-}
-
-/*
- * This function prepares command to set/get/reset network key(s).
- * This function prepares key material command for V1 format.
- *
- * Preparation includes -
- *      - Setting command ID, action and proper size
- *      - Setting WEP keys, WAPI keys or WPA keys along with required
- *        encryption (TKIP, AES) (as required)
- *      - Ensuring correct endian-ness
- */
-static int
-mwifiex_cmd_802_11_key_material_v1(struct mwifiex_private *priv,
-                                  struct host_cmd_ds_command *cmd,
-                                  u16 cmd_action, u32 cmd_oid,
-                                  struct mwifiex_ds_encrypt_key *enc_key)
-{
-       struct host_cmd_ds_802_11_key_material *key_material =
-               &cmd->params.key_material;
-       struct host_cmd_tlv_mac_addr *tlv_mac;
-       u16 key_param_len = 0, cmd_size;
-       int ret = 0;
-
-       cmd->command = cpu_to_le16(HostCmd_CMD_802_11_KEY_MATERIAL);
-       key_material->action = cpu_to_le16(cmd_action);
-
-       if (cmd_action == HostCmd_ACT_GEN_GET) {
-               cmd->size =
-                       cpu_to_le16(sizeof(key_material->action) + S_DS_GEN);
-               return ret;
-       }
-
-       if (!enc_key) {
-               memset(&key_material->key_param_set, 0,
-                      (NUM_WEP_KEYS *
-                       sizeof(struct mwifiex_ie_type_key_param_set)));
-               ret = mwifiex_set_keyparamset_wep(priv,
-                                                 &key_material->key_param_set,
-                                                 &key_param_len);
-               cmd->size = cpu_to_le16(key_param_len +
-                                   sizeof(key_material->action) + S_DS_GEN);
-               return ret;
-       } else
-               memset(&key_material->key_param_set, 0,
-                      sizeof(struct mwifiex_ie_type_key_param_set));
-       if (enc_key->is_wapi_key) {
-               mwifiex_dbg(priv->adapter, INFO, "info: Set WAPI Key\n");
-               key_material->key_param_set.key_type_id =
-                                               cpu_to_le16(KEY_TYPE_ID_WAPI);
-               if (cmd_oid == KEY_INFO_ENABLED)
-                       key_material->key_param_set.key_info =
-                                               cpu_to_le16(KEY_ENABLED);
-               else
-                       key_material->key_param_set.key_info =
-                                               cpu_to_le16(!KEY_ENABLED);
-
-               key_material->key_param_set.key[0] = enc_key->key_index;
-               if (!priv->sec_info.wapi_key_on)
-                       key_material->key_param_set.key[1] = 1;
-               else
-                       /* set 0 when re-key */
-                       key_material->key_param_set.key[1] = 0;
-
-               if (!is_broadcast_ether_addr(enc_key->mac_addr)) {
-                       /* WAPI pairwise key: unicast */
-                       key_material->key_param_set.key_info |=
-                               cpu_to_le16(KEY_UNICAST);
-               } else {        /* WAPI group key: multicast */
-                       key_material->key_param_set.key_info |=
-                               cpu_to_le16(KEY_MCAST);
-                       priv->sec_info.wapi_key_on = true;
-               }
-
-               key_material->key_param_set.type =
-                                       cpu_to_le16(TLV_TYPE_KEY_MATERIAL);
-               key_material->key_param_set.key_len =
-                                               cpu_to_le16(WAPI_KEY_LEN);
-               memcpy(&key_material->key_param_set.key[2],
-                      enc_key->key_material, enc_key->key_len);
-               memcpy(&key_material->key_param_set.key[2 + enc_key->key_len],
-                      enc_key->pn, PN_LEN);
-               key_material->key_param_set.length =
-                       cpu_to_le16(WAPI_KEY_LEN + KEYPARAMSET_FIXED_LEN);
-
-               key_param_len = (WAPI_KEY_LEN + KEYPARAMSET_FIXED_LEN) +
-                                sizeof(struct mwifiex_ie_types_header);
-               cmd->size = cpu_to_le16(sizeof(key_material->action)
-                                       + S_DS_GEN +  key_param_len);
-               return ret;
-       }
-       if (enc_key->key_len == WLAN_KEY_LEN_CCMP) {
-               if (enc_key->is_igtk_key) {
-                       mwifiex_dbg(priv->adapter, CMD, "cmd: CMAC_AES\n");
-                       key_material->key_param_set.key_type_id =
-                                       cpu_to_le16(KEY_TYPE_ID_AES_CMAC);
-                       if (cmd_oid == KEY_INFO_ENABLED)
-                               key_material->key_param_set.key_info =
-                                               cpu_to_le16(KEY_ENABLED);
-                       else
-                               key_material->key_param_set.key_info =
-                                               cpu_to_le16(!KEY_ENABLED);
-
-                       key_material->key_param_set.key_info |=
-                                                       cpu_to_le16(KEY_IGTK);
-               } else {
-                       mwifiex_dbg(priv->adapter, CMD, "cmd: WPA_AES\n");
-                       key_material->key_param_set.key_type_id =
-                                               cpu_to_le16(KEY_TYPE_ID_AES);
-                       if (cmd_oid == KEY_INFO_ENABLED)
-                               key_material->key_param_set.key_info =
-                                               cpu_to_le16(KEY_ENABLED);
-                       else
-                               key_material->key_param_set.key_info =
-                                               cpu_to_le16(!KEY_ENABLED);
-
-                       if (enc_key->key_index & MWIFIEX_KEY_INDEX_UNICAST)
-                               /* AES pairwise key: unicast */
-                               key_material->key_param_set.key_info |=
-                                               cpu_to_le16(KEY_UNICAST);
-                       else    /* AES group key: multicast */
-                               key_material->key_param_set.key_info |=
-                                                       cpu_to_le16(KEY_MCAST);
-               }
-       } else if (enc_key->key_len == WLAN_KEY_LEN_TKIP) {
-               mwifiex_dbg(priv->adapter, CMD, "cmd: WPA_TKIP\n");
-               key_material->key_param_set.key_type_id =
-                                               cpu_to_le16(KEY_TYPE_ID_TKIP);
-               key_material->key_param_set.key_info =
-                                               cpu_to_le16(KEY_ENABLED);
-
-               if (enc_key->key_index & MWIFIEX_KEY_INDEX_UNICAST)
-                               /* TKIP pairwise key: unicast */
-                       key_material->key_param_set.key_info |=
-                                               cpu_to_le16(KEY_UNICAST);
-               else            /* TKIP group key: multicast */
-                       key_material->key_param_set.key_info |=
-                                                       cpu_to_le16(KEY_MCAST);
-       }
-
-       if (key_material->key_param_set.key_type_id) {
-               key_material->key_param_set.type =
-                                       cpu_to_le16(TLV_TYPE_KEY_MATERIAL);
-               key_material->key_param_set.key_len =
-                                       cpu_to_le16((u16) enc_key->key_len);
-               memcpy(key_material->key_param_set.key, enc_key->key_material,
-                      enc_key->key_len);
-               key_material->key_param_set.length =
-                       cpu_to_le16((u16) enc_key->key_len +
-                                   KEYPARAMSET_FIXED_LEN);
-
-               key_param_len = (u16)(enc_key->key_len + KEYPARAMSET_FIXED_LEN)
-                               + sizeof(struct mwifiex_ie_types_header);
-
-               if (le16_to_cpu(key_material->key_param_set.key_type_id) ==
-                                                       KEY_TYPE_ID_AES_CMAC) {
-                       struct mwifiex_cmac_param *param =
-                                       (void *)key_material->key_param_set.key;
-
-                       memcpy(param->ipn, enc_key->pn, IGTK_PN_LEN);
-                       memcpy(param->key, enc_key->key_material,
-                              WLAN_KEY_LEN_AES_CMAC);
-
-                       key_param_len = sizeof(struct mwifiex_cmac_param);
-                       key_material->key_param_set.key_len =
-                                               cpu_to_le16(key_param_len);
-                       key_param_len += KEYPARAMSET_FIXED_LEN;
-                       key_material->key_param_set.length =
-                                               cpu_to_le16(key_param_len);
-                       key_param_len += sizeof(struct mwifiex_ie_types_header);
-               }
-
-               cmd->size = cpu_to_le16(sizeof(key_material->action) + S_DS_GEN
-                                       + key_param_len);
-
-               if (GET_BSS_ROLE(priv) == MWIFIEX_BSS_ROLE_UAP) {
-                       tlv_mac = (void *)((u8 *)&key_material->key_param_set +
-                                          key_param_len);
-                       tlv_mac->header.type =
-                                       cpu_to_le16(TLV_TYPE_STA_MAC_ADDR);
-                       tlv_mac->header.len = cpu_to_le16(ETH_ALEN);
-                       memcpy(tlv_mac->mac_addr, enc_key->mac_addr, ETH_ALEN);
-                       cmd_size = key_param_len + S_DS_GEN +
-                                  sizeof(key_material->action) +
-                                  sizeof(struct host_cmd_tlv_mac_addr);
-               } else {
-                       cmd_size = key_param_len + S_DS_GEN +
-                                  sizeof(key_material->action);
-               }
-               cmd->size = cpu_to_le16(cmd_size);
-       }
-
-       return ret;
-}
-
-/* Wrapper function for setting network key depending upon FW KEY API version */
-static int
-mwifiex_cmd_802_11_key_material(struct mwifiex_private *priv,
-                               struct host_cmd_ds_command *cmd,
-                               u16 cmd_action, u32 cmd_oid,
-                               struct mwifiex_ds_encrypt_key *enc_key)
-{
-       if (priv->adapter->key_api_major_ver == KEY_API_VER_MAJOR_V2)
-               return mwifiex_cmd_802_11_key_material_v2(priv, cmd,
-                                                         cmd_action, cmd_oid,
-                                                         enc_key);
-
-       else
-               return mwifiex_cmd_802_11_key_material_v1(priv, cmd,
-                                                         cmd_action, cmd_oid,
-                                                         enc_key);
-}
-
-/*
- * This function prepares command to set/get 11d domain information.
- *
- * Preparation includes -
- *      - Setting command ID, action and proper size
- *      - Setting domain information fields (for SET only)
- *      - Ensuring correct endian-ness
- */
-static int mwifiex_cmd_802_11d_domain_info(struct mwifiex_private *priv,
-                                          struct host_cmd_ds_command *cmd,
-                                          u16 cmd_action)
-{
-       struct mwifiex_adapter *adapter = priv->adapter;
-       struct host_cmd_ds_802_11d_domain_info *domain_info =
-               &cmd->params.domain_info;
-       struct mwifiex_ietypes_domain_param_set *domain =
-               &domain_info->domain;
-       u8 no_of_triplet = adapter->domain_reg.no_of_triplet;
-
-       mwifiex_dbg(adapter, INFO,
-                   "info: 11D: no_of_triplet=0x%x\n", no_of_triplet);
-
-       cmd->command = cpu_to_le16(HostCmd_CMD_802_11D_DOMAIN_INFO);
-       domain_info->action = cpu_to_le16(cmd_action);
-       if (cmd_action == HostCmd_ACT_GEN_GET) {
-               cmd->size = cpu_to_le16(sizeof(domain_info->action) + S_DS_GEN);
-               return 0;
-       }
-
-       /* Set domain info fields */
-       domain->header.type = cpu_to_le16(WLAN_EID_COUNTRY);
-       memcpy(domain->country_code, adapter->domain_reg.country_code,
-              sizeof(domain->country_code));
-
-       domain->header.len =
-               cpu_to_le16((no_of_triplet *
-                            sizeof(struct ieee80211_country_ie_triplet))
-                           + sizeof(domain->country_code));
-
-       if (no_of_triplet) {
-               memcpy(domain->triplet, adapter->domain_reg.triplet,
-                      no_of_triplet * sizeof(struct
-                                             ieee80211_country_ie_triplet));
-
-               cmd->size = cpu_to_le16(sizeof(domain_info->action) +
-                                       le16_to_cpu(domain->header.len) +
-                                       sizeof(struct mwifiex_ie_types_header)
-                                       + S_DS_GEN);
-       } else {
-               cmd->size = cpu_to_le16(sizeof(domain_info->action) + S_DS_GEN);
-       }
-
-       return 0;
-}
-
-/*
- * This function prepares command to set/get IBSS coalescing status.
- *
- * Preparation includes -
- *      - Setting command ID, action and proper size
- *      - Setting status to enable or disable (for SET only)
- *      - Ensuring correct endian-ness
- */
-static int mwifiex_cmd_ibss_coalescing_status(struct host_cmd_ds_command *cmd,
-                                             u16 cmd_action, u16 *enable)
-{
-       struct host_cmd_ds_802_11_ibss_status *ibss_coal =
-               &(cmd->params.ibss_coalescing);
-
-       cmd->command = cpu_to_le16(HostCmd_CMD_802_11_IBSS_COALESCING_STATUS);
-       cmd->size = cpu_to_le16(sizeof(struct host_cmd_ds_802_11_ibss_status) +
-                               S_DS_GEN);
-       cmd->result = 0;
-       ibss_coal->action = cpu_to_le16(cmd_action);
-
-       switch (cmd_action) {
-       case HostCmd_ACT_GEN_SET:
-               if (enable)
-                       ibss_coal->enable = cpu_to_le16(*enable);
-               else
-                       ibss_coal->enable = 0;
-               break;
-
-               /* In other case.. Nothing to do */
-       case HostCmd_ACT_GEN_GET:
-       default:
-               break;
-       }
-
-       return 0;
-}
-
-/* This function prepares command buffer to get/set memory location value.
- */
-static int
-mwifiex_cmd_mem_access(struct host_cmd_ds_command *cmd, u16 cmd_action,
-                      void *pdata_buf)
-{
-       struct mwifiex_ds_mem_rw *mem_rw = (void *)pdata_buf;
-       struct host_cmd_ds_mem_access *mem_access = (void *)&cmd->params.mem;
-
-       cmd->command = cpu_to_le16(HostCmd_CMD_MEM_ACCESS);
-       cmd->size = cpu_to_le16(sizeof(struct host_cmd_ds_mem_access) +
-                               S_DS_GEN);
-
-       mem_access->action = cpu_to_le16(cmd_action);
-       mem_access->addr = cpu_to_le32(mem_rw->addr);
-       mem_access->value = cpu_to_le32(mem_rw->value);
-
-       return 0;
-}
-
-/*
- * This function prepares command to set/get register value.
- *
- * Preparation includes -
- *      - Setting command ID, action and proper size
- *      - Setting register offset (for both GET and SET) and
- *        register value (for SET only)
- *      - Ensuring correct endian-ness
- *
- * The following type of registers can be accessed with this function -
- *      - MAC register
- *      - BBP register
- *      - RF register
- *      - PMIC register
- *      - CAU register
- *      - EEPROM
- */
-static int mwifiex_cmd_reg_access(struct host_cmd_ds_command *cmd,
-                                 u16 cmd_action, void *data_buf)
-{
-       struct mwifiex_ds_reg_rw *reg_rw = data_buf;
-
-       switch (le16_to_cpu(cmd->command)) {
-       case HostCmd_CMD_MAC_REG_ACCESS:
-       {
-               struct host_cmd_ds_mac_reg_access *mac_reg;
-
-               cmd->size = cpu_to_le16(sizeof(*mac_reg) + S_DS_GEN);
-               mac_reg = &cmd->params.mac_reg;
-               mac_reg->action = cpu_to_le16(cmd_action);
-               mac_reg->offset =
-                       cpu_to_le16((u16) le32_to_cpu(reg_rw->offset));
-               mac_reg->value = reg_rw->value;
-               break;
-       }
-       case HostCmd_CMD_BBP_REG_ACCESS:
-       {
-               struct host_cmd_ds_bbp_reg_access *bbp_reg;
-
-               cmd->size = cpu_to_le16(sizeof(*bbp_reg) + S_DS_GEN);
-               bbp_reg = &cmd->params.bbp_reg;
-               bbp_reg->action = cpu_to_le16(cmd_action);
-               bbp_reg->offset =
-                       cpu_to_le16((u16) le32_to_cpu(reg_rw->offset));
-               bbp_reg->value = (u8) le32_to_cpu(reg_rw->value);
-               break;
-       }
-       case HostCmd_CMD_RF_REG_ACCESS:
-       {
-               struct host_cmd_ds_rf_reg_access *rf_reg;
-
-               cmd->size = cpu_to_le16(sizeof(*rf_reg) + S_DS_GEN);
-               rf_reg = &cmd->params.rf_reg;
-               rf_reg->action = cpu_to_le16(cmd_action);
-               rf_reg->offset = cpu_to_le16((u16) le32_to_cpu(reg_rw->offset));
-               rf_reg->value = (u8) le32_to_cpu(reg_rw->value);
-               break;
-       }
-       case HostCmd_CMD_PMIC_REG_ACCESS:
-       {
-               struct host_cmd_ds_pmic_reg_access *pmic_reg;
-
-               cmd->size = cpu_to_le16(sizeof(*pmic_reg) + S_DS_GEN);
-               pmic_reg = &cmd->params.pmic_reg;
-               pmic_reg->action = cpu_to_le16(cmd_action);
-               pmic_reg->offset =
-                               cpu_to_le16((u16) le32_to_cpu(reg_rw->offset));
-               pmic_reg->value = (u8) le32_to_cpu(reg_rw->value);
-               break;
-       }
-       case HostCmd_CMD_CAU_REG_ACCESS:
-       {
-               struct host_cmd_ds_rf_reg_access *cau_reg;
-
-               cmd->size = cpu_to_le16(sizeof(*cau_reg) + S_DS_GEN);
-               cau_reg = &cmd->params.rf_reg;
-               cau_reg->action = cpu_to_le16(cmd_action);
-               cau_reg->offset =
-                               cpu_to_le16((u16) le32_to_cpu(reg_rw->offset));
-               cau_reg->value = (u8) le32_to_cpu(reg_rw->value);
-               break;
-       }
-       case HostCmd_CMD_802_11_EEPROM_ACCESS:
-       {
-               struct mwifiex_ds_read_eeprom *rd_eeprom = data_buf;
-               struct host_cmd_ds_802_11_eeprom_access *cmd_eeprom =
-                       &cmd->params.eeprom;
-
-               cmd->size = cpu_to_le16(sizeof(*cmd_eeprom) + S_DS_GEN);
-               cmd_eeprom->action = cpu_to_le16(cmd_action);
-               cmd_eeprom->offset = rd_eeprom->offset;
-               cmd_eeprom->byte_count = rd_eeprom->byte_count;
-               cmd_eeprom->value = 0;
-               break;
-       }
-       default:
-               return -1;
-       }
-
-       return 0;
-}
-
-/*
- * This function prepares command to set PCI-Express
- * host buffer configuration
- *
- * Preparation includes -
- *      - Setting command ID, action and proper size
- *      - Setting host buffer configuration
- *      - Ensuring correct endian-ness
- */
-static int
-mwifiex_cmd_pcie_host_spec(struct mwifiex_private *priv,
-                          struct host_cmd_ds_command *cmd, u16 action)
-{
-       struct host_cmd_ds_pcie_details *host_spec =
-                                       &cmd->params.pcie_host_spec;
-       struct pcie_service_card *card = priv->adapter->card;
-
-       cmd->command = cpu_to_le16(HostCmd_CMD_PCIE_DESC_DETAILS);
-       cmd->size = cpu_to_le16(sizeof(struct
-                                       host_cmd_ds_pcie_details) + S_DS_GEN);
-       cmd->result = 0;
-
-       memset(host_spec, 0, sizeof(struct host_cmd_ds_pcie_details));
-
-       if (action != HostCmd_ACT_GEN_SET)
-               return 0;
-
-       /* Send the ring base addresses and count to firmware */
-       host_spec->txbd_addr_lo = (u32)(card->txbd_ring_pbase);
-       host_spec->txbd_addr_hi = (u32)(((u64)card->txbd_ring_pbase)>>32);
-       host_spec->txbd_count = MWIFIEX_MAX_TXRX_BD;
-       host_spec->rxbd_addr_lo = (u32)(card->rxbd_ring_pbase);
-       host_spec->rxbd_addr_hi = (u32)(((u64)card->rxbd_ring_pbase)>>32);
-       host_spec->rxbd_count = MWIFIEX_MAX_TXRX_BD;
-       host_spec->evtbd_addr_lo = (u32)(card->evtbd_ring_pbase);
-       host_spec->evtbd_addr_hi = (u32)(((u64)card->evtbd_ring_pbase)>>32);
-       host_spec->evtbd_count = MWIFIEX_MAX_EVT_BD;
-       if (card->sleep_cookie_vbase) {
-               host_spec->sleep_cookie_addr_lo =
-                                               (u32)(card->sleep_cookie_pbase);
-               host_spec->sleep_cookie_addr_hi =
-                                (u32)(((u64)(card->sleep_cookie_pbase)) >> 32);
-               mwifiex_dbg(priv->adapter, INFO,
-                           "sleep_cook_lo phy addr: 0x%x\n",
-                           host_spec->sleep_cookie_addr_lo);
-       }
-
-       return 0;
-}
-
-/*
- * This function prepares command for event subscription, configuration
- * and query. Events can be subscribed or unsubscribed. Current subscribed
- * events can be queried. Also, current subscribed events are reported in
- * every FW response.
- */
-static int
-mwifiex_cmd_802_11_subsc_evt(struct mwifiex_private *priv,
-                            struct host_cmd_ds_command *cmd,
-                            struct mwifiex_ds_misc_subsc_evt *subsc_evt_cfg)
-{
-       struct host_cmd_ds_802_11_subsc_evt *subsc_evt = &cmd->params.subsc_evt;
-       struct mwifiex_ie_types_rssi_threshold *rssi_tlv;
-       u16 event_bitmap;
-       u8 *pos;
-
-       cmd->command = cpu_to_le16(HostCmd_CMD_802_11_SUBSCRIBE_EVENT);
-       cmd->size = cpu_to_le16(sizeof(struct host_cmd_ds_802_11_subsc_evt) +
-                               S_DS_GEN);
-
-       subsc_evt->action = cpu_to_le16(subsc_evt_cfg->action);
-       mwifiex_dbg(priv->adapter, CMD,
-                   "cmd: action: %d\n", subsc_evt_cfg->action);
-
-       /*For query requests, no configuration TLV structures are to be added.*/
-       if (subsc_evt_cfg->action == HostCmd_ACT_GEN_GET)
-               return 0;
-
-       subsc_evt->events = cpu_to_le16(subsc_evt_cfg->events);
-
-       event_bitmap = subsc_evt_cfg->events;
-       mwifiex_dbg(priv->adapter, CMD, "cmd: event bitmap : %16x\n",
-                   event_bitmap);
-
-       if (((subsc_evt_cfg->action == HostCmd_ACT_BITWISE_CLR) ||
-            (subsc_evt_cfg->action == HostCmd_ACT_BITWISE_SET)) &&
-           (event_bitmap == 0)) {
-               mwifiex_dbg(priv->adapter, ERROR,
-                           "Error: No event specified\t"
-                           "for bitwise action type\n");
-               return -EINVAL;
-       }
-
-       /*
-        * Append TLV structures for each of the specified events for
-        * subscribing or re-configuring. This is not required for
-        * bitwise unsubscribing request.
-        */
-       if (subsc_evt_cfg->action == HostCmd_ACT_BITWISE_CLR)
-               return 0;
-
-       pos = ((u8 *)subsc_evt) +
-                       sizeof(struct host_cmd_ds_802_11_subsc_evt);
-
-       if (event_bitmap & BITMASK_BCN_RSSI_LOW) {
-               rssi_tlv = (struct mwifiex_ie_types_rssi_threshold *) pos;
-
-               rssi_tlv->header.type = cpu_to_le16(TLV_TYPE_RSSI_LOW);
-               rssi_tlv->header.len =
-                   cpu_to_le16(sizeof(struct mwifiex_ie_types_rssi_threshold) -
-                               sizeof(struct mwifiex_ie_types_header));
-               rssi_tlv->abs_value = subsc_evt_cfg->bcn_l_rssi_cfg.abs_value;
-               rssi_tlv->evt_freq = subsc_evt_cfg->bcn_l_rssi_cfg.evt_freq;
-
-               mwifiex_dbg(priv->adapter, EVENT,
-                           "Cfg Beacon Low Rssi event,\t"
-                           "RSSI:-%d dBm, Freq:%d\n",
-                           subsc_evt_cfg->bcn_l_rssi_cfg.abs_value,
-                           subsc_evt_cfg->bcn_l_rssi_cfg.evt_freq);
-
-               pos += sizeof(struct mwifiex_ie_types_rssi_threshold);
-               le16_add_cpu(&cmd->size,
-                            sizeof(struct mwifiex_ie_types_rssi_threshold));
-       }
-
-       if (event_bitmap & BITMASK_BCN_RSSI_HIGH) {
-               rssi_tlv = (struct mwifiex_ie_types_rssi_threshold *) pos;
-
-               rssi_tlv->header.type = cpu_to_le16(TLV_TYPE_RSSI_HIGH);
-               rssi_tlv->header.len =
-                   cpu_to_le16(sizeof(struct mwifiex_ie_types_rssi_threshold) -
-                               sizeof(struct mwifiex_ie_types_header));
-               rssi_tlv->abs_value = subsc_evt_cfg->bcn_h_rssi_cfg.abs_value;
-               rssi_tlv->evt_freq = subsc_evt_cfg->bcn_h_rssi_cfg.evt_freq;
-
-               mwifiex_dbg(priv->adapter, EVENT,
-                           "Cfg Beacon High Rssi event,\t"
-                           "RSSI:-%d dBm, Freq:%d\n",
-                           subsc_evt_cfg->bcn_h_rssi_cfg.abs_value,
-                           subsc_evt_cfg->bcn_h_rssi_cfg.evt_freq);
-
-               pos += sizeof(struct mwifiex_ie_types_rssi_threshold);
-               le16_add_cpu(&cmd->size,
-                            sizeof(struct mwifiex_ie_types_rssi_threshold));
-       }
-
-       return 0;
-}
-
-static int
-mwifiex_cmd_append_rpn_expression(struct mwifiex_private *priv,
-                                 struct mwifiex_mef_entry *mef_entry,
-                                 u8 **buffer)
-{
-       struct mwifiex_mef_filter *filter = mef_entry->filter;
-       int i, byte_len;
-       u8 *stack_ptr = *buffer;
-
-       for (i = 0; i < MWIFIEX_MEF_MAX_FILTERS; i++) {
-               filter = &mef_entry->filter[i];
-               if (!filter->filt_type)
-                       break;
-               *(__le32 *)stack_ptr = cpu_to_le32((u32)filter->repeat);
-               stack_ptr += 4;
-               *stack_ptr = TYPE_DNUM;
-               stack_ptr += 1;
-
-               byte_len = filter->byte_seq[MWIFIEX_MEF_MAX_BYTESEQ];
-               memcpy(stack_ptr, filter->byte_seq, byte_len);
-               stack_ptr += byte_len;
-               *stack_ptr = byte_len;
-               stack_ptr += 1;
-               *stack_ptr = TYPE_BYTESEQ;
-               stack_ptr += 1;
-
-               *(__le32 *)stack_ptr = cpu_to_le32((u32)filter->offset);
-               stack_ptr += 4;
-               *stack_ptr = TYPE_DNUM;
-               stack_ptr += 1;
-
-               *stack_ptr = filter->filt_type;
-               stack_ptr += 1;
-
-               if (filter->filt_action) {
-                       *stack_ptr = filter->filt_action;
-                       stack_ptr += 1;
-               }
-
-               if (stack_ptr - *buffer > STACK_NBYTES)
-                       return -1;
-       }
-
-       *buffer = stack_ptr;
-       return 0;
-}
-
-static int
-mwifiex_cmd_mef_cfg(struct mwifiex_private *priv,
-                   struct host_cmd_ds_command *cmd,
-                   struct mwifiex_ds_mef_cfg *mef)
-{
-       struct host_cmd_ds_mef_cfg *mef_cfg = &cmd->params.mef_cfg;
-       struct mwifiex_fw_mef_entry *mef_entry = NULL;
-       u8 *pos = (u8 *)mef_cfg;
-       u16 i;
-
-       cmd->command = cpu_to_le16(HostCmd_CMD_MEF_CFG);
-
-       mef_cfg->criteria = cpu_to_le32(mef->criteria);
-       mef_cfg->num_entries = cpu_to_le16(mef->num_entries);
-       pos += sizeof(*mef_cfg);
-
-       for (i = 0; i < mef->num_entries; i++) {
-               mef_entry = (struct mwifiex_fw_mef_entry *)pos;
-               mef_entry->mode = mef->mef_entry[i].mode;
-               mef_entry->action = mef->mef_entry[i].action;
-               pos += sizeof(*mef_cfg->mef_entry);
-
-               if (mwifiex_cmd_append_rpn_expression(priv,
-                                                     &mef->mef_entry[i], &pos))
-                       return -1;
-
-               mef_entry->exprsize =
-                       cpu_to_le16(pos - mef_entry->expr);
-       }
-       cmd->size = cpu_to_le16((u16) (pos - (u8 *)mef_cfg) + S_DS_GEN);
-
-       return 0;
-}
-
-/* This function parse cal data from ASCII to hex */
-static u32 mwifiex_parse_cal_cfg(u8 *src, size_t len, u8 *dst)
-{
-       u8 *s = src, *d = dst;
-
-       while (s - src < len) {
-               if (*s && (isspace(*s) || *s == '\t')) {
-                       s++;
-                       continue;
-               }
-               if (isxdigit(*s)) {
-                       *d++ = simple_strtol(s, NULL, 16);
-                       s += 2;
-               } else {
-                       s++;
-               }
-       }
-
-       return d - dst;
-}
-
-int mwifiex_dnld_dt_cfgdata(struct mwifiex_private *priv,
-                           struct device_node *node, const char *prefix)
-{
-#ifdef CONFIG_OF
-       struct property *prop;
-       size_t len = strlen(prefix);
-       int ret;
-
-       /* look for all matching property names */
-       for_each_property_of_node(node, prop) {
-               if (len > strlen(prop->name) ||
-                   strncmp(prop->name, prefix, len))
-                       continue;
-
-               /* property header is 6 bytes, data must fit in cmd buffer */
-               if (prop && prop->value && prop->length > 6 &&
-                   prop->length <= MWIFIEX_SIZE_OF_CMD_BUFFER - S_DS_GEN) {
-                       ret = mwifiex_send_cmd(priv, HostCmd_CMD_CFG_DATA,
-                                              HostCmd_ACT_GEN_SET, 0,
-                                              prop, true);
-                       if (ret)
-                               return ret;
-               }
-       }
-#endif
-       return 0;
-}
-
-/* This function prepares command of set_cfg_data. */
-static int mwifiex_cmd_cfg_data(struct mwifiex_private *priv,
-                               struct host_cmd_ds_command *cmd, void *data_buf)
-{
-       struct mwifiex_adapter *adapter = priv->adapter;
-       struct property *prop = data_buf;
-       u32 len;
-       u8 *data = (u8 *)cmd + S_DS_GEN;
-       int ret;
-
-       if (prop) {
-               len = prop->length;
-               ret = of_property_read_u8_array(adapter->dt_node, prop->name,
-                                               data, len);
-               if (ret)
-                       return ret;
-               mwifiex_dbg(adapter, INFO,
-                           "download cfg_data from device tree: %s\n",
-                           prop->name);
-       } else if (adapter->cal_data->data && adapter->cal_data->size > 0) {
-               len = mwifiex_parse_cal_cfg((u8 *)adapter->cal_data->data,
-                                           adapter->cal_data->size, data);
-               mwifiex_dbg(adapter, INFO,
-                           "download cfg_data from config file\n");
-       } else {
-               return -1;
-       }
-
-       cmd->command = cpu_to_le16(HostCmd_CMD_CFG_DATA);
-       cmd->size = cpu_to_le16(S_DS_GEN + len);
-
-       return 0;
-}
-
-static int
-mwifiex_cmd_set_mc_policy(struct mwifiex_private *priv,
-                         struct host_cmd_ds_command *cmd,
-                         u16 cmd_action, void *data_buf)
-{
-       struct host_cmd_ds_multi_chan_policy *mc_pol = &cmd->params.mc_policy;
-       const u16 *drcs_info = data_buf;
-
-       mc_pol->action = cpu_to_le16(cmd_action);
-       mc_pol->policy = cpu_to_le16(*drcs_info);
-       cmd->command = cpu_to_le16(HostCmd_CMD_MC_POLICY);
-       cmd->size = cpu_to_le16(sizeof(struct host_cmd_ds_multi_chan_policy) +
-                               S_DS_GEN);
-       return 0;
-}
-
-static int mwifiex_cmd_robust_coex(struct mwifiex_private *priv,
-                                  struct host_cmd_ds_command *cmd,
-                                  u16 cmd_action, bool *is_timeshare)
-{
-       struct host_cmd_ds_robust_coex *coex = &cmd->params.coex;
-       struct mwifiex_ie_types_robust_coex *coex_tlv;
-
-       cmd->command = cpu_to_le16(HostCmd_CMD_ROBUST_COEX);
-       cmd->size = cpu_to_le16(sizeof(*coex) + sizeof(*coex_tlv) + S_DS_GEN);
-
-       coex->action = cpu_to_le16(cmd_action);
-       coex_tlv = (struct mwifiex_ie_types_robust_coex *)
-                               ((u8 *)coex + sizeof(*coex));
-       coex_tlv->header.type = cpu_to_le16(TLV_TYPE_ROBUST_COEX);
-       coex_tlv->header.len = cpu_to_le16(sizeof(coex_tlv->mode));
-
-       if (coex->action == HostCmd_ACT_GEN_GET)
-               return 0;
-
-       if (*is_timeshare)
-               coex_tlv->mode = cpu_to_le32(MWIFIEX_COEX_MODE_TIMESHARE);
-       else
-               coex_tlv->mode = cpu_to_le32(MWIFIEX_COEX_MODE_SPATIAL);
-
-       return 0;
-}
-
-static int
-mwifiex_cmd_coalesce_cfg(struct mwifiex_private *priv,
-                        struct host_cmd_ds_command *cmd,
-                        u16 cmd_action, void *data_buf)
-{
-       struct host_cmd_ds_coalesce_cfg *coalesce_cfg =
-                                               &cmd->params.coalesce_cfg;
-       struct mwifiex_ds_coalesce_cfg *cfg = data_buf;
-       struct coalesce_filt_field_param *param;
-       u16 cnt, idx, length;
-       struct coalesce_receive_filt_rule *rule;
-
-       cmd->command = cpu_to_le16(HostCmd_CMD_COALESCE_CFG);
-       cmd->size = cpu_to_le16(S_DS_GEN);
-
-       coalesce_cfg->action = cpu_to_le16(cmd_action);
-       coalesce_cfg->num_of_rules = cpu_to_le16(cfg->num_of_rules);
-       rule = coalesce_cfg->rule;
-
-       for (cnt = 0; cnt < cfg->num_of_rules; cnt++) {
-               rule->header.type = cpu_to_le16(TLV_TYPE_COALESCE_RULE);
-               rule->max_coalescing_delay =
-                       cpu_to_le16(cfg->rule[cnt].max_coalescing_delay);
-               rule->pkt_type = cfg->rule[cnt].pkt_type;
-               rule->num_of_fields = cfg->rule[cnt].num_of_fields;
-
-               length = 0;
-
-               param = rule->params;
-               for (idx = 0; idx < cfg->rule[cnt].num_of_fields; idx++) {
-                       param->operation = cfg->rule[cnt].params[idx].operation;
-                       param->operand_len =
-                                       cfg->rule[cnt].params[idx].operand_len;
-                       param->offset =
-                               cpu_to_le16(cfg->rule[cnt].params[idx].offset);
-                       memcpy(param->operand_byte_stream,
-                              cfg->rule[cnt].params[idx].operand_byte_stream,
-                              param->operand_len);
-
-                       length += sizeof(struct coalesce_filt_field_param);
-
-                       param++;
-               }
-
-               /* Total rule length is sizeof max_coalescing_delay(u16),
-                * num_of_fields(u8), pkt_type(u8) and total length of the all
-                * params
-                */
-               rule->header.len = cpu_to_le16(length + sizeof(u16) +
-                                              sizeof(u8) + sizeof(u8));
-
-               /* Add the rule length to the command size*/
-               le16_add_cpu(&cmd->size, le16_to_cpu(rule->header.len) +
-                            sizeof(struct mwifiex_ie_types_header));
-
-               rule = (void *)((u8 *)rule->params + length);
-       }
-
-       /* Add sizeof action, num_of_rules to total command length */
-       le16_add_cpu(&cmd->size, sizeof(u16) + sizeof(u16));
-
-       return 0;
-}
-
-static int
-mwifiex_cmd_tdls_config(struct mwifiex_private *priv,
-                       struct host_cmd_ds_command *cmd,
-                       u16 cmd_action, void *data_buf)
-{
-       struct host_cmd_ds_tdls_config *tdls_config = &cmd->params.tdls_config;
-       struct mwifiex_tdls_init_cs_params *config;
-       struct mwifiex_tdls_config *init_config;
-       u16 len;
-
-       cmd->command = cpu_to_le16(HostCmd_CMD_TDLS_CONFIG);
-       cmd->size = cpu_to_le16(S_DS_GEN);
-       tdls_config->tdls_action = cpu_to_le16(cmd_action);
-       le16_add_cpu(&cmd->size, sizeof(tdls_config->tdls_action));
-
-       switch (cmd_action) {
-       case ACT_TDLS_CS_ENABLE_CONFIG:
-               init_config = data_buf;
-               len = sizeof(*init_config);
-               memcpy(tdls_config->tdls_data, init_config, len);
-               break;
-       case ACT_TDLS_CS_INIT:
-               config = data_buf;
-               len = sizeof(*config);
-               memcpy(tdls_config->tdls_data, config, len);
-               break;
-       case ACT_TDLS_CS_STOP:
-               len = sizeof(struct mwifiex_tdls_stop_cs_params);
-               memcpy(tdls_config->tdls_data, data_buf, len);
-               break;
-       case ACT_TDLS_CS_PARAMS:
-               len = sizeof(struct mwifiex_tdls_config_cs_params);
-               memcpy(tdls_config->tdls_data, data_buf, len);
-               break;
-       default:
-               mwifiex_dbg(priv->adapter, ERROR,
-                           "Unknown TDLS configuration\n");
-               return -ENOTSUPP;
-       }
-
-       le16_add_cpu(&cmd->size, len);
-       return 0;
-}
-
-static int
-mwifiex_cmd_tdls_oper(struct mwifiex_private *priv,
-                     struct host_cmd_ds_command *cmd,
-                     void *data_buf)
-{
-       struct host_cmd_ds_tdls_oper *tdls_oper = &cmd->params.tdls_oper;
-       struct mwifiex_ds_tdls_oper *oper = data_buf;
-       struct mwifiex_sta_node *sta_ptr;
-       struct host_cmd_tlv_rates *tlv_rates;
-       struct mwifiex_ie_types_htcap *ht_capab;
-       struct mwifiex_ie_types_qos_info *wmm_qos_info;
-       struct mwifiex_ie_types_extcap *extcap;
-       struct mwifiex_ie_types_vhtcap *vht_capab;
-       struct mwifiex_ie_types_aid *aid;
-       struct mwifiex_ie_types_tdls_idle_timeout *timeout;
-       u8 *pos, qos_info;
-       u16 config_len = 0;
-       struct station_parameters *params = priv->sta_params;
-
-       cmd->command = cpu_to_le16(HostCmd_CMD_TDLS_OPER);
-       cmd->size = cpu_to_le16(S_DS_GEN);
-       le16_add_cpu(&cmd->size, sizeof(struct host_cmd_ds_tdls_oper));
-
-       tdls_oper->reason = 0;
-       memcpy(tdls_oper->peer_mac, oper->peer_mac, ETH_ALEN);
-       sta_ptr = mwifiex_get_sta_entry(priv, oper->peer_mac);
-
-       pos = (u8 *)tdls_oper + sizeof(struct host_cmd_ds_tdls_oper);
-
-       switch (oper->tdls_action) {
-       case MWIFIEX_TDLS_DISABLE_LINK:
-               tdls_oper->tdls_action = cpu_to_le16(ACT_TDLS_DELETE);
-               break;
-       case MWIFIEX_TDLS_CREATE_LINK:
-               tdls_oper->tdls_action = cpu_to_le16(ACT_TDLS_CREATE);
-               break;
-       case MWIFIEX_TDLS_CONFIG_LINK:
-               tdls_oper->tdls_action = cpu_to_le16(ACT_TDLS_CONFIG);
-
-               if (!params) {
-                       mwifiex_dbg(priv->adapter, ERROR,
-                                   "TDLS config params not available for %pM\n",
-                                   oper->peer_mac);
-                       return -ENODATA;
-               }
-
-               *(__le16 *)pos = cpu_to_le16(params->capability);
-               config_len += sizeof(params->capability);
-
-               qos_info = params->uapsd_queues | (params->max_sp << 5);
-               wmm_qos_info = (struct mwifiex_ie_types_qos_info *)(pos +
-                                                                   config_len);
-               wmm_qos_info->header.type = cpu_to_le16(WLAN_EID_QOS_CAPA);
-               wmm_qos_info->header.len = cpu_to_le16(sizeof(qos_info));
-               wmm_qos_info->qos_info = qos_info;
-               config_len += sizeof(struct mwifiex_ie_types_qos_info);
-
-               if (params->ht_capa) {
-                       ht_capab = (struct mwifiex_ie_types_htcap *)(pos +
-                                                                   config_len);
-                       ht_capab->header.type =
-                                           cpu_to_le16(WLAN_EID_HT_CAPABILITY);
-                       ht_capab->header.len =
-                                  cpu_to_le16(sizeof(struct ieee80211_ht_cap));
-                       memcpy(&ht_capab->ht_cap, params->ht_capa,
-                              sizeof(struct ieee80211_ht_cap));
-                       config_len += sizeof(struct mwifiex_ie_types_htcap);
-               }
-
-               if (params->supported_rates && params->supported_rates_len) {
-                       tlv_rates = (struct host_cmd_tlv_rates *)(pos +
-                                                                 config_len);
-                       tlv_rates->header.type =
-                                              cpu_to_le16(WLAN_EID_SUPP_RATES);
-                       tlv_rates->header.len =
-                                      cpu_to_le16(params->supported_rates_len);
-                       memcpy(tlv_rates->rates, params->supported_rates,
-                              params->supported_rates_len);
-                       config_len += sizeof(struct host_cmd_tlv_rates) +
-                                     params->supported_rates_len;
-               }
-
-               if (params->ext_capab && params->ext_capab_len) {
-                       extcap = (struct mwifiex_ie_types_extcap *)(pos +
-                                                                   config_len);
-                       extcap->header.type =
-                                          cpu_to_le16(WLAN_EID_EXT_CAPABILITY);
-                       extcap->header.len = cpu_to_le16(params->ext_capab_len);
-                       memcpy(extcap->ext_capab, params->ext_capab,
-                              params->ext_capab_len);
-                       config_len += sizeof(struct mwifiex_ie_types_extcap) +
-                                     params->ext_capab_len;
-               }
-               if (params->vht_capa) {
-                       vht_capab = (struct mwifiex_ie_types_vhtcap *)(pos +
-                                                                   config_len);
-                       vht_capab->header.type =
-                                          cpu_to_le16(WLAN_EID_VHT_CAPABILITY);
-                       vht_capab->header.len =
-                                 cpu_to_le16(sizeof(struct ieee80211_vht_cap));
-                       memcpy(&vht_capab->vht_cap, params->vht_capa,
-                              sizeof(struct ieee80211_vht_cap));
-                       config_len += sizeof(struct mwifiex_ie_types_vhtcap);
-               }
-               if (params->aid) {
-                       aid = (struct mwifiex_ie_types_aid *)(pos + config_len);
-                       aid->header.type = cpu_to_le16(WLAN_EID_AID);
-                       aid->header.len = cpu_to_le16(sizeof(params->aid));
-                       aid->aid = cpu_to_le16(params->aid);
-                       config_len += sizeof(struct mwifiex_ie_types_aid);
-               }
-
-               timeout = (void *)(pos + config_len);
-               timeout->header.type = cpu_to_le16(TLV_TYPE_TDLS_IDLE_TIMEOUT);
-               timeout->header.len = cpu_to_le16(sizeof(timeout->value));
-               timeout->value = cpu_to_le16(MWIFIEX_TDLS_IDLE_TIMEOUT_IN_SEC);
-               config_len += sizeof(struct mwifiex_ie_types_tdls_idle_timeout);
-
-               break;
-       default:
-               mwifiex_dbg(priv->adapter, ERROR, "Unknown TDLS operation\n");
-               return -ENOTSUPP;
-       }
-
-       le16_add_cpu(&cmd->size, config_len);
-
-       return 0;
-}
-
-/* This function prepares command of sdio rx aggr info. */
-static int mwifiex_cmd_sdio_rx_aggr_cfg(struct host_cmd_ds_command *cmd,
-                                       u16 cmd_action, void *data_buf)
-{
-       struct host_cmd_sdio_sp_rx_aggr_cfg *cfg =
-                                       &cmd->params.sdio_rx_aggr_cfg;
-
-       cmd->command = cpu_to_le16(HostCmd_CMD_SDIO_SP_RX_AGGR_CFG);
-       cmd->size =
-               cpu_to_le16(sizeof(struct host_cmd_sdio_sp_rx_aggr_cfg) +
-                           S_DS_GEN);
-       cfg->action = cmd_action;
-       if (cmd_action == HostCmd_ACT_GEN_SET)
-               cfg->enable = *(u8 *)data_buf;
-
-       return 0;
-}
-
-/*
- * This function prepares the commands before sending them to the firmware.
- *
- * This is a generic function which calls specific command preparation
- * routines based upon the command number.
- */
-int mwifiex_sta_prepare_cmd(struct mwifiex_private *priv, uint16_t cmd_no,
-                           u16 cmd_action, u32 cmd_oid,
-                           void *data_buf, void *cmd_buf)
-{
-       struct host_cmd_ds_command *cmd_ptr = cmd_buf;
-       int ret = 0;
-
-       /* Prepare command */
-       switch (cmd_no) {
-       case HostCmd_CMD_GET_HW_SPEC:
-               ret = mwifiex_cmd_get_hw_spec(priv, cmd_ptr);
-               break;
-       case HostCmd_CMD_CFG_DATA:
-               ret = mwifiex_cmd_cfg_data(priv, cmd_ptr, data_buf);
-               break;
-       case HostCmd_CMD_MAC_CONTROL:
-               ret = mwifiex_cmd_mac_control(priv, cmd_ptr, cmd_action,
-                                             data_buf);
-               break;
-       case HostCmd_CMD_802_11_MAC_ADDRESS:
-               ret = mwifiex_cmd_802_11_mac_address(priv, cmd_ptr,
-                                                    cmd_action);
-               break;
-       case HostCmd_CMD_MAC_MULTICAST_ADR:
-               ret = mwifiex_cmd_mac_multicast_adr(cmd_ptr, cmd_action,
-                                                   data_buf);
-               break;
-       case HostCmd_CMD_TX_RATE_CFG:
-               ret = mwifiex_cmd_tx_rate_cfg(priv, cmd_ptr, cmd_action,
-                                             data_buf);
-               break;
-       case HostCmd_CMD_TXPWR_CFG:
-               ret = mwifiex_cmd_tx_power_cfg(cmd_ptr, cmd_action,
-                                              data_buf);
-               break;
-       case HostCmd_CMD_RF_TX_PWR:
-               ret = mwifiex_cmd_rf_tx_power(priv, cmd_ptr, cmd_action,
-                                             data_buf);
-               break;
-       case HostCmd_CMD_RF_ANTENNA:
-               ret = mwifiex_cmd_rf_antenna(priv, cmd_ptr, cmd_action,
-                                            data_buf);
-               break;
-       case HostCmd_CMD_802_11_PS_MODE_ENH:
-               ret = mwifiex_cmd_enh_power_mode(priv, cmd_ptr, cmd_action,
-                                                (uint16_t)cmd_oid, data_buf);
-               break;
-       case HostCmd_CMD_802_11_HS_CFG_ENH:
-               ret = mwifiex_cmd_802_11_hs_cfg(priv, cmd_ptr, cmd_action,
-                               (struct mwifiex_hs_config_param *) data_buf);
-               break;
-       case HostCmd_CMD_802_11_SCAN:
-               ret = mwifiex_cmd_802_11_scan(cmd_ptr, data_buf);
-               break;
-       case HostCmd_CMD_802_11_BG_SCAN_QUERY:
-               ret = mwifiex_cmd_802_11_bg_scan_query(cmd_ptr);
-               break;
-       case HostCmd_CMD_802_11_ASSOCIATE:
-               ret = mwifiex_cmd_802_11_associate(priv, cmd_ptr, data_buf);
-               break;
-       case HostCmd_CMD_802_11_DEAUTHENTICATE:
-               ret = mwifiex_cmd_802_11_deauthenticate(priv, cmd_ptr,
-                                                       data_buf);
-               break;
-       case HostCmd_CMD_802_11_AD_HOC_START:
-               ret = mwifiex_cmd_802_11_ad_hoc_start(priv, cmd_ptr,
-                                                     data_buf);
-               break;
-       case HostCmd_CMD_802_11_GET_LOG:
-               ret = mwifiex_cmd_802_11_get_log(cmd_ptr);
-               break;
-       case HostCmd_CMD_802_11_AD_HOC_JOIN:
-               ret = mwifiex_cmd_802_11_ad_hoc_join(priv, cmd_ptr,
-                                                    data_buf);
-               break;
-       case HostCmd_CMD_802_11_AD_HOC_STOP:
-               ret = mwifiex_cmd_802_11_ad_hoc_stop(cmd_ptr);
-               break;
-       case HostCmd_CMD_RSSI_INFO:
-               ret = mwifiex_cmd_802_11_rssi_info(priv, cmd_ptr, cmd_action);
-               break;
-       case HostCmd_CMD_802_11_SNMP_MIB:
-               ret = mwifiex_cmd_802_11_snmp_mib(priv, cmd_ptr, cmd_action,
-                                                 cmd_oid, data_buf);
-               break;
-       case HostCmd_CMD_802_11_TX_RATE_QUERY:
-               cmd_ptr->command =
-                       cpu_to_le16(HostCmd_CMD_802_11_TX_RATE_QUERY);
-               cmd_ptr->size =
-                       cpu_to_le16(sizeof(struct host_cmd_ds_tx_rate_query) +
-                                   S_DS_GEN);
-               priv->tx_rate = 0;
-               ret = 0;
-               break;
-       case HostCmd_CMD_VERSION_EXT:
-               cmd_ptr->command = cpu_to_le16(cmd_no);
-               cmd_ptr->params.verext.version_str_sel =
-                       (u8) (*((u32 *) data_buf));
-               memcpy(&cmd_ptr->params, data_buf,
-                      sizeof(struct host_cmd_ds_version_ext));
-               cmd_ptr->size =
-                       cpu_to_le16(sizeof(struct host_cmd_ds_version_ext) +
-                                   S_DS_GEN);
-               ret = 0;
-               break;
-       case HostCmd_CMD_MGMT_FRAME_REG:
-               cmd_ptr->command = cpu_to_le16(cmd_no);
-               cmd_ptr->params.reg_mask.action = cpu_to_le16(cmd_action);
-               cmd_ptr->params.reg_mask.mask = cpu_to_le32(*(u32 *)data_buf);
-               cmd_ptr->size =
-                       cpu_to_le16(sizeof(struct host_cmd_ds_mgmt_frame_reg) +
-                                   S_DS_GEN);
-               ret = 0;
-               break;
-       case HostCmd_CMD_REMAIN_ON_CHAN:
-               cmd_ptr->command = cpu_to_le16(cmd_no);
-               memcpy(&cmd_ptr->params, data_buf,
-                      sizeof(struct host_cmd_ds_remain_on_chan));
-               cmd_ptr->size =
-                     cpu_to_le16(sizeof(struct host_cmd_ds_remain_on_chan) +
-                                 S_DS_GEN);
-               break;
-       case HostCmd_CMD_11AC_CFG:
-               ret = mwifiex_cmd_11ac_cfg(priv, cmd_ptr, cmd_action, data_buf);
-               break;
-       case HostCmd_CMD_P2P_MODE_CFG:
-               cmd_ptr->command = cpu_to_le16(cmd_no);
-               cmd_ptr->params.mode_cfg.action = cpu_to_le16(cmd_action);
-               cmd_ptr->params.mode_cfg.mode = cpu_to_le16(*(u16 *)data_buf);
-               cmd_ptr->size =
-                       cpu_to_le16(sizeof(struct host_cmd_ds_p2p_mode_cfg) +
-                                   S_DS_GEN);
-               break;
-       case HostCmd_CMD_FUNC_INIT:
-               if (priv->adapter->hw_status == MWIFIEX_HW_STATUS_RESET)
-                       priv->adapter->hw_status = MWIFIEX_HW_STATUS_READY;
-               cmd_ptr->command = cpu_to_le16(cmd_no);
-               cmd_ptr->size = cpu_to_le16(S_DS_GEN);
-               break;
-       case HostCmd_CMD_FUNC_SHUTDOWN:
-               priv->adapter->hw_status = MWIFIEX_HW_STATUS_RESET;
-               cmd_ptr->command = cpu_to_le16(cmd_no);
-               cmd_ptr->size = cpu_to_le16(S_DS_GEN);
-               break;
-       case HostCmd_CMD_11N_ADDBA_REQ:
-               ret = mwifiex_cmd_11n_addba_req(cmd_ptr, data_buf);
-               break;
-       case HostCmd_CMD_11N_DELBA:
-               ret = mwifiex_cmd_11n_delba(cmd_ptr, data_buf);
-               break;
-       case HostCmd_CMD_11N_ADDBA_RSP:
-               ret = mwifiex_cmd_11n_addba_rsp_gen(priv, cmd_ptr, data_buf);
-               break;
-       case HostCmd_CMD_802_11_KEY_MATERIAL:
-               ret = mwifiex_cmd_802_11_key_material(priv, cmd_ptr,
-                                                     cmd_action, cmd_oid,
-                                                     data_buf);
-               break;
-       case HostCmd_CMD_802_11D_DOMAIN_INFO:
-               ret = mwifiex_cmd_802_11d_domain_info(priv, cmd_ptr,
-                                                     cmd_action);
-               break;
-       case HostCmd_CMD_RECONFIGURE_TX_BUFF:
-               ret = mwifiex_cmd_recfg_tx_buf(priv, cmd_ptr, cmd_action,
-                                              data_buf);
-               break;
-       case HostCmd_CMD_AMSDU_AGGR_CTRL:
-               ret = mwifiex_cmd_amsdu_aggr_ctrl(cmd_ptr, cmd_action,
-                                                 data_buf);
-               break;
-       case HostCmd_CMD_11N_CFG:
-               ret = mwifiex_cmd_11n_cfg(priv, cmd_ptr, cmd_action, data_buf);
-               break;
-       case HostCmd_CMD_WMM_GET_STATUS:
-               mwifiex_dbg(priv->adapter, CMD,
-                           "cmd: WMM: WMM_GET_STATUS cmd sent\n");
-               cmd_ptr->command = cpu_to_le16(HostCmd_CMD_WMM_GET_STATUS);
-               cmd_ptr->size =
-                       cpu_to_le16(sizeof(struct host_cmd_ds_wmm_get_status) +
-                                   S_DS_GEN);
-               ret = 0;
-               break;
-       case HostCmd_CMD_802_11_IBSS_COALESCING_STATUS:
-               ret = mwifiex_cmd_ibss_coalescing_status(cmd_ptr, cmd_action,
-                                                        data_buf);
-               break;
-       case HostCmd_CMD_802_11_SCAN_EXT:
-               ret = mwifiex_cmd_802_11_scan_ext(priv, cmd_ptr, data_buf);
-               break;
-       case HostCmd_CMD_MEM_ACCESS:
-               ret = mwifiex_cmd_mem_access(cmd_ptr, cmd_action, data_buf);
-               break;
-       case HostCmd_CMD_MAC_REG_ACCESS:
-       case HostCmd_CMD_BBP_REG_ACCESS:
-       case HostCmd_CMD_RF_REG_ACCESS:
-       case HostCmd_CMD_PMIC_REG_ACCESS:
-       case HostCmd_CMD_CAU_REG_ACCESS:
-       case HostCmd_CMD_802_11_EEPROM_ACCESS:
-               ret = mwifiex_cmd_reg_access(cmd_ptr, cmd_action, data_buf);
-               break;
-       case HostCmd_CMD_SET_BSS_MODE:
-               cmd_ptr->command = cpu_to_le16(cmd_no);
-               if (priv->bss_mode == NL80211_IFTYPE_ADHOC)
-                       cmd_ptr->params.bss_mode.con_type =
-                               CONNECTION_TYPE_ADHOC;
-               else if (priv->bss_mode == NL80211_IFTYPE_STATION ||
-                        priv->bss_mode == NL80211_IFTYPE_P2P_CLIENT)
-                       cmd_ptr->params.bss_mode.con_type =
-                               CONNECTION_TYPE_INFRA;
-               else if (priv->bss_mode == NL80211_IFTYPE_AP ||
-                        priv->bss_mode == NL80211_IFTYPE_P2P_GO)
-                       cmd_ptr->params.bss_mode.con_type = CONNECTION_TYPE_AP;
-               cmd_ptr->size = cpu_to_le16(sizeof(struct
-                               host_cmd_ds_set_bss_mode) + S_DS_GEN);
-               ret = 0;
-               break;
-       case HostCmd_CMD_PCIE_DESC_DETAILS:
-               ret = mwifiex_cmd_pcie_host_spec(priv, cmd_ptr, cmd_action);
-               break;
-       case HostCmd_CMD_802_11_SUBSCRIBE_EVENT:
-               ret = mwifiex_cmd_802_11_subsc_evt(priv, cmd_ptr, data_buf);
-               break;
-       case HostCmd_CMD_MEF_CFG:
-               ret = mwifiex_cmd_mef_cfg(priv, cmd_ptr, data_buf);
-               break;
-       case HostCmd_CMD_COALESCE_CFG:
-               ret = mwifiex_cmd_coalesce_cfg(priv, cmd_ptr, cmd_action,
-                                              data_buf);
-               break;
-       case HostCmd_CMD_TDLS_OPER:
-               ret = mwifiex_cmd_tdls_oper(priv, cmd_ptr, data_buf);
-               break;
-       case HostCmd_CMD_TDLS_CONFIG:
-               ret = mwifiex_cmd_tdls_config(priv, cmd_ptr, cmd_action,
-                                             data_buf);
-               break;
-       case HostCmd_CMD_CHAN_REPORT_REQUEST:
-               ret = mwifiex_cmd_issue_chan_report_request(priv, cmd_ptr,
-                                                           data_buf);
-               break;
-       case HostCmd_CMD_SDIO_SP_RX_AGGR_CFG:
-               ret = mwifiex_cmd_sdio_rx_aggr_cfg(cmd_ptr, cmd_action,
-                                                  data_buf);
-               break;
-       case HostCmd_CMD_MC_POLICY:
-               ret = mwifiex_cmd_set_mc_policy(priv, cmd_ptr, cmd_action,
-                                               data_buf);
-               break;
-       case HostCmd_CMD_ROBUST_COEX:
-               ret = mwifiex_cmd_robust_coex(priv, cmd_ptr, cmd_action,
-                                             data_buf);
-               break;
-       default:
-               mwifiex_dbg(priv->adapter, ERROR,
-                           "PREP_CMD: unknown cmd- %#x\n", cmd_no);
-               ret = -1;
-               break;
-       }
-       return ret;
-}
-
-/*
- * This function issues commands to initialize firmware.
- *
- * This is called after firmware download to bring the card to
- * working state.
- * Function is also called during reinitialization of virtual
- * interfaces.
- *
- * The following commands are issued sequentially -
- *      - Set PCI-Express host buffer configuration (PCIE only)
- *      - Function init (for first interface only)
- *      - Read MAC address (for first interface only)
- *      - Reconfigure Tx buffer size (for first interface only)
- *      - Enable auto deep sleep (for first interface only)
- *      - Get Tx rate
- *      - Get Tx power
- *      - Set IBSS coalescing status
- *      - Set AMSDU aggregation control
- *      - Set 11d control
- *      - Set MAC control (this must be the last command to initialize firmware)
- */
-int mwifiex_sta_init_cmd(struct mwifiex_private *priv, u8 first_sta, bool init)
-{
-       struct mwifiex_adapter *adapter = priv->adapter;
-       int ret;
-       u16 enable = true;
-       struct mwifiex_ds_11n_amsdu_aggr_ctrl amsdu_aggr_ctrl;
-       struct mwifiex_ds_auto_ds auto_ds;
-       enum state_11d_t state_11d;
-       struct mwifiex_ds_11n_tx_cfg tx_cfg;
-       u8 sdio_sp_rx_aggr_enable;
-
-       if (first_sta) {
-               if (priv->adapter->iface_type == MWIFIEX_PCIE) {
-                       ret = mwifiex_send_cmd(priv,
-                                              HostCmd_CMD_PCIE_DESC_DETAILS,
-                                              HostCmd_ACT_GEN_SET, 0, NULL,
-                                              true);
-                       if (ret)
-                               return -1;
-               }
-
-               ret = mwifiex_send_cmd(priv, HostCmd_CMD_FUNC_INIT,
-                                      HostCmd_ACT_GEN_SET, 0, NULL, true);
-               if (ret)
-                       return -1;
-
-               /* Download calibration data to firmware.
-                * The cal-data can be read from device tree and/or
-                * a configuration file and downloaded to firmware.
-                */
-               adapter->dt_node =
-                               of_find_node_by_name(NULL, "marvell_cfgdata");
-               if (adapter->dt_node) {
-                       ret = mwifiex_dnld_dt_cfgdata(priv, adapter->dt_node,
-                                                     "marvell,caldata");
-                       if (ret)
-                               return -1;
-               }
-
-               if (adapter->cal_data) {
-                       ret = mwifiex_send_cmd(priv, HostCmd_CMD_CFG_DATA,
-                                              HostCmd_ACT_GEN_SET, 0, NULL,
-                                              true);
-                       if (ret)
-                               return -1;
-               }
-
-               /* Read MAC address from HW */
-               ret = mwifiex_send_cmd(priv, HostCmd_CMD_GET_HW_SPEC,
-                                      HostCmd_ACT_GEN_GET, 0, NULL, true);
-               if (ret)
-                       return -1;
-
-               /** Set SDIO Single Port RX Aggr Info */
-               if (priv->adapter->iface_type == MWIFIEX_SDIO &&
-                   ISSUPP_SDIO_SPA_ENABLED(priv->adapter->fw_cap_info) &&
-                   !priv->adapter->host_disable_sdio_rx_aggr) {
-                       sdio_sp_rx_aggr_enable = true;
-                       ret = mwifiex_send_cmd(priv,
-                                              HostCmd_CMD_SDIO_SP_RX_AGGR_CFG,
-                                              HostCmd_ACT_GEN_SET, 0,
-                                              &sdio_sp_rx_aggr_enable,
-                                              true);
-                       if (ret) {
-                               mwifiex_dbg(priv->adapter, ERROR,
-                                           "error while enabling SP aggregation..disable it");
-                               adapter->sdio_rx_aggr_enable = false;
-                       }
-               }
-
-               /* Reconfigure tx buf size */
-               ret = mwifiex_send_cmd(priv, HostCmd_CMD_RECONFIGURE_TX_BUFF,
-                                      HostCmd_ACT_GEN_SET, 0,
-                                      &priv->adapter->tx_buf_size, true);
-               if (ret)
-                       return -1;
-
-               if (priv->bss_type != MWIFIEX_BSS_TYPE_UAP) {
-                       /* Enable IEEE PS by default */
-                       priv->adapter->ps_mode = MWIFIEX_802_11_POWER_MODE_PSP;
-                       ret = mwifiex_send_cmd(priv,
-                                              HostCmd_CMD_802_11_PS_MODE_ENH,
-                                              EN_AUTO_PS, BITMAP_STA_PS, NULL,
-                                              true);
-                       if (ret)
-                               return -1;
-               }
-
-               if (drcs) {
-                       adapter->drcs_enabled = true;
-                       if (ISSUPP_DRCS_ENABLED(adapter->fw_cap_info))
-                               ret = mwifiex_send_cmd(priv,
-                                                      HostCmd_CMD_MC_POLICY,
-                                                      HostCmd_ACT_GEN_SET, 0,
-                                                      &adapter->drcs_enabled,
-                                                      true);
-                       if (ret)
-                               return -1;
-               }
-       }
-
-       /* get tx rate */
-       ret = mwifiex_send_cmd(priv, HostCmd_CMD_TX_RATE_CFG,
-                              HostCmd_ACT_GEN_GET, 0, NULL, true);
-       if (ret)
-               return -1;
-       priv->data_rate = 0;
-
-       /* get tx power */
-       ret = mwifiex_send_cmd(priv, HostCmd_CMD_RF_TX_PWR,
-                              HostCmd_ACT_GEN_GET, 0, NULL, true);
-       if (ret)
-               return -1;
-
-       if (priv->bss_type == MWIFIEX_BSS_TYPE_STA) {
-               /* set ibss coalescing_status */
-               ret = mwifiex_send_cmd(
-                               priv,
-                               HostCmd_CMD_802_11_IBSS_COALESCING_STATUS,
-                               HostCmd_ACT_GEN_SET, 0, &enable, true);
-               if (ret)
-                       return -1;
-       }
-
-       memset(&amsdu_aggr_ctrl, 0, sizeof(amsdu_aggr_ctrl));
-       amsdu_aggr_ctrl.enable = true;
-       /* Send request to firmware */
-       ret = mwifiex_send_cmd(priv, HostCmd_CMD_AMSDU_AGGR_CTRL,
-                              HostCmd_ACT_GEN_SET, 0,
-                              &amsdu_aggr_ctrl, true);
-       if (ret)
-               return -1;
-       /* MAC Control must be the last command in init_fw */
-       /* set MAC Control */
-       ret = mwifiex_send_cmd(priv, HostCmd_CMD_MAC_CONTROL,
-                              HostCmd_ACT_GEN_SET, 0,
-                              &priv->curr_pkt_filter, true);
-       if (ret)
-               return -1;
-
-       if (!disable_auto_ds &&
-           first_sta && priv->adapter->iface_type != MWIFIEX_USB &&
-           priv->bss_type != MWIFIEX_BSS_TYPE_UAP) {
-               /* Enable auto deep sleep */
-               auto_ds.auto_ds = DEEP_SLEEP_ON;
-               auto_ds.idle_time = DEEP_SLEEP_IDLE_TIME;
-               ret = mwifiex_send_cmd(priv, HostCmd_CMD_802_11_PS_MODE_ENH,
-                                      EN_AUTO_PS, BITMAP_AUTO_DS,
-                                      &auto_ds, true);
-               if (ret)
-                       return -1;
-       }
-
-       if (priv->bss_type != MWIFIEX_BSS_TYPE_UAP) {
-               /* Send cmd to FW to enable/disable 11D function */
-               state_11d = ENABLE_11D;
-               ret = mwifiex_send_cmd(priv, HostCmd_CMD_802_11_SNMP_MIB,
-                                      HostCmd_ACT_GEN_SET, DOT11D_I,
-                                      &state_11d, true);
-               if (ret)
-                       mwifiex_dbg(priv->adapter, ERROR,
-                                   "11D: failed to enable 11D\n");
-       }
-
-       /* Send cmd to FW to configure 11n specific configuration
-        * (Short GI, Channel BW, Green field support etc.) for transmit
-        */
-       tx_cfg.tx_htcap = MWIFIEX_FW_DEF_HTTXCFG;
-       ret = mwifiex_send_cmd(priv, HostCmd_CMD_11N_CFG,
-                              HostCmd_ACT_GEN_SET, 0, &tx_cfg, true);
-
-       if (init) {
-               /* set last_init_cmd before sending the command */
-               priv->adapter->last_init_cmd = HostCmd_CMD_11N_CFG;
-               ret = -EINPROGRESS;
-       }
-
-       return ret;
-}
diff --git a/drivers/net/wireless/mwifiex/sta_cmdresp.c b/drivers/net/wireless/mwifiex/sta_cmdresp.c
deleted file mode 100644 (file)
index 9ac7aa2..0000000
+++ /dev/null
@@ -1,1249 +0,0 @@
-/*
- * Marvell Wireless LAN device driver: station command response handling
- *
- * Copyright (C) 2011-2014, Marvell International Ltd.
- *
- * This software file (the "File") is distributed by Marvell International
- * Ltd. under the terms of the GNU General Public License Version 2, June 1991
- * (the "License").  You may use, redistribute and/or modify this File in
- * accordance with the terms and conditions of the License, a copy of which
- * is available by writing to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the
- * worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
- *
- * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
- * ARE EXPRESSLY DISCLAIMED.  The License provides additional details about
- * this warranty disclaimer.
- */
-
-#include "decl.h"
-#include "ioctl.h"
-#include "util.h"
-#include "fw.h"
-#include "main.h"
-#include "wmm.h"
-#include "11n.h"
-#include "11ac.h"
-
-
-/*
- * This function handles the command response error case.
- *
- * For scan response error, the function cancels all the pending
- * scan commands and generates an event to inform the applications
- * of the scan completion.
- *
- * For Power Save command failure, we do not retry enter PS
- * command in case of Ad-hoc mode.
- *
- * For all other response errors, the current command buffer is freed
- * and returned to the free command queue.
- */
-static void
-mwifiex_process_cmdresp_error(struct mwifiex_private *priv,
-                             struct host_cmd_ds_command *resp)
-{
-       struct cmd_ctrl_node *cmd_node = NULL, *tmp_node;
-       struct mwifiex_adapter *adapter = priv->adapter;
-       struct host_cmd_ds_802_11_ps_mode_enh *pm;
-       unsigned long flags;
-
-       mwifiex_dbg(adapter, ERROR,
-                   "CMD_RESP: cmd %#x error, result=%#x\n",
-                   resp->command, resp->result);
-
-       if (adapter->curr_cmd->wait_q_enabled)
-               adapter->cmd_wait_q.status = -1;
-
-       switch (le16_to_cpu(resp->command)) {
-       case HostCmd_CMD_802_11_PS_MODE_ENH:
-               pm = &resp->params.psmode_enh;
-               mwifiex_dbg(adapter, ERROR,
-                           "PS_MODE_ENH cmd failed: result=0x%x action=0x%X\n",
-                           resp->result, le16_to_cpu(pm->action));
-               /* We do not re-try enter-ps command in ad-hoc mode. */
-               if (le16_to_cpu(pm->action) == EN_AUTO_PS &&
-                   (le16_to_cpu(pm->params.ps_bitmap) & BITMAP_STA_PS) &&
-                   priv->bss_mode == NL80211_IFTYPE_ADHOC)
-                       adapter->ps_mode = MWIFIEX_802_11_POWER_MODE_CAM;
-
-               break;
-       case HostCmd_CMD_802_11_SCAN:
-       case HostCmd_CMD_802_11_SCAN_EXT:
-               /* Cancel all pending scan command */
-               spin_lock_irqsave(&adapter->scan_pending_q_lock, flags);
-               list_for_each_entry_safe(cmd_node, tmp_node,
-                                        &adapter->scan_pending_q, list) {
-                       list_del(&cmd_node->list);
-                       spin_unlock_irqrestore(&adapter->scan_pending_q_lock,
-                                              flags);
-                       mwifiex_insert_cmd_to_free_q(adapter, cmd_node);
-                       spin_lock_irqsave(&adapter->scan_pending_q_lock, flags);
-               }
-               spin_unlock_irqrestore(&adapter->scan_pending_q_lock, flags);
-
-               spin_lock_irqsave(&adapter->mwifiex_cmd_lock, flags);
-               adapter->scan_processing = false;
-               spin_unlock_irqrestore(&adapter->mwifiex_cmd_lock, flags);
-               break;
-
-       case HostCmd_CMD_MAC_CONTROL:
-               break;
-
-       case HostCmd_CMD_SDIO_SP_RX_AGGR_CFG:
-               mwifiex_dbg(adapter, MSG,
-                           "SDIO RX single-port aggregation Not support\n");
-               break;
-
-       default:
-               break;
-       }
-       /* Handling errors here */
-       mwifiex_recycle_cmd_node(adapter, adapter->curr_cmd);
-
-       spin_lock_irqsave(&adapter->mwifiex_cmd_lock, flags);
-       adapter->curr_cmd = NULL;
-       spin_unlock_irqrestore(&adapter->mwifiex_cmd_lock, flags);
-}
-
-/*
- * This function handles the command response of get RSSI info.
- *
- * Handling includes changing the header fields into CPU format
- * and saving the following parameters in driver -
- *      - Last data and beacon RSSI value
- *      - Average data and beacon RSSI value
- *      - Last data and beacon NF value
- *      - Average data and beacon NF value
- *
- * The parameters are send to the application as well, along with
- * calculated SNR values.
- */
-static int mwifiex_ret_802_11_rssi_info(struct mwifiex_private *priv,
-                                       struct host_cmd_ds_command *resp)
-{
-       struct host_cmd_ds_802_11_rssi_info_rsp *rssi_info_rsp =
-                                               &resp->params.rssi_info_rsp;
-       struct mwifiex_ds_misc_subsc_evt *subsc_evt =
-                                               &priv->async_subsc_evt_storage;
-
-       priv->data_rssi_last = le16_to_cpu(rssi_info_rsp->data_rssi_last);
-       priv->data_nf_last = le16_to_cpu(rssi_info_rsp->data_nf_last);
-
-       priv->data_rssi_avg = le16_to_cpu(rssi_info_rsp->data_rssi_avg);
-       priv->data_nf_avg = le16_to_cpu(rssi_info_rsp->data_nf_avg);
-
-       priv->bcn_rssi_last = le16_to_cpu(rssi_info_rsp->bcn_rssi_last);
-       priv->bcn_nf_last = le16_to_cpu(rssi_info_rsp->bcn_nf_last);
-
-       priv->bcn_rssi_avg = le16_to_cpu(rssi_info_rsp->bcn_rssi_avg);
-       priv->bcn_nf_avg = le16_to_cpu(rssi_info_rsp->bcn_nf_avg);
-
-       if (priv->subsc_evt_rssi_state == EVENT_HANDLED)
-               return 0;
-
-       memset(subsc_evt, 0x00, sizeof(struct mwifiex_ds_misc_subsc_evt));
-
-       /* Resubscribe low and high rssi events with new thresholds */
-       subsc_evt->events = BITMASK_BCN_RSSI_LOW | BITMASK_BCN_RSSI_HIGH;
-       subsc_evt->action = HostCmd_ACT_BITWISE_SET;
-       if (priv->subsc_evt_rssi_state == RSSI_LOW_RECVD) {
-               subsc_evt->bcn_l_rssi_cfg.abs_value = abs(priv->bcn_rssi_avg -
-                               priv->cqm_rssi_hyst);
-               subsc_evt->bcn_h_rssi_cfg.abs_value = abs(priv->cqm_rssi_thold);
-       } else if (priv->subsc_evt_rssi_state == RSSI_HIGH_RECVD) {
-               subsc_evt->bcn_l_rssi_cfg.abs_value = abs(priv->cqm_rssi_thold);
-               subsc_evt->bcn_h_rssi_cfg.abs_value = abs(priv->bcn_rssi_avg +
-                               priv->cqm_rssi_hyst);
-       }
-       subsc_evt->bcn_l_rssi_cfg.evt_freq = 1;
-       subsc_evt->bcn_h_rssi_cfg.evt_freq = 1;
-
-       priv->subsc_evt_rssi_state = EVENT_HANDLED;
-
-       mwifiex_send_cmd(priv, HostCmd_CMD_802_11_SUBSCRIBE_EVENT,
-                        0, 0, subsc_evt, false);
-
-       return 0;
-}
-
-/*
- * This function handles the command response of set/get SNMP
- * MIB parameters.
- *
- * Handling includes changing the header fields into CPU format
- * and saving the parameter in driver.
- *
- * The following parameters are supported -
- *      - Fragmentation threshold
- *      - RTS threshold
- *      - Short retry limit
- */
-static int mwifiex_ret_802_11_snmp_mib(struct mwifiex_private *priv,
-                                      struct host_cmd_ds_command *resp,
-                                      u32 *data_buf)
-{
-       struct host_cmd_ds_802_11_snmp_mib *smib = &resp->params.smib;
-       u16 oid = le16_to_cpu(smib->oid);
-       u16 query_type = le16_to_cpu(smib->query_type);
-       u32 ul_temp;
-
-       mwifiex_dbg(priv->adapter, INFO,
-                   "info: SNMP_RESP: oid value = %#x,\t"
-                   "query_type = %#x, buf size = %#x\n",
-                   oid, query_type, le16_to_cpu(smib->buf_size));
-       if (query_type == HostCmd_ACT_GEN_GET) {
-               ul_temp = le16_to_cpu(*((__le16 *) (smib->value)));
-               if (data_buf)
-                       *data_buf = ul_temp;
-               switch (oid) {
-               case FRAG_THRESH_I:
-                       mwifiex_dbg(priv->adapter, INFO,
-                                   "info: SNMP_RESP: FragThsd =%u\n",
-                                   ul_temp);
-                       break;
-               case RTS_THRESH_I:
-                       mwifiex_dbg(priv->adapter, INFO,
-                                   "info: SNMP_RESP: RTSThsd =%u\n",
-                                   ul_temp);
-                       break;
-               case SHORT_RETRY_LIM_I:
-                       mwifiex_dbg(priv->adapter, INFO,
-                                   "info: SNMP_RESP: TxRetryCount=%u\n",
-                                   ul_temp);
-                       break;
-               case DTIM_PERIOD_I:
-                       mwifiex_dbg(priv->adapter, INFO,
-                                   "info: SNMP_RESP: DTIM period=%u\n",
-                                   ul_temp);
-               default:
-                       break;
-               }
-       }
-
-       return 0;
-}
-
-/*
- * This function handles the command response of get log request
- *
- * Handling includes changing the header fields into CPU format
- * and sending the received parameters to application.
- */
-static int mwifiex_ret_get_log(struct mwifiex_private *priv,
-                              struct host_cmd_ds_command *resp,
-                              struct mwifiex_ds_get_stats *stats)
-{
-       struct host_cmd_ds_802_11_get_log *get_log =
-               &resp->params.get_log;
-
-       if (stats) {
-               stats->mcast_tx_frame = le32_to_cpu(get_log->mcast_tx_frame);
-               stats->failed = le32_to_cpu(get_log->failed);
-               stats->retry = le32_to_cpu(get_log->retry);
-               stats->multi_retry = le32_to_cpu(get_log->multi_retry);
-               stats->frame_dup = le32_to_cpu(get_log->frame_dup);
-               stats->rts_success = le32_to_cpu(get_log->rts_success);
-               stats->rts_failure = le32_to_cpu(get_log->rts_failure);
-               stats->ack_failure = le32_to_cpu(get_log->ack_failure);
-               stats->rx_frag = le32_to_cpu(get_log->rx_frag);
-               stats->mcast_rx_frame = le32_to_cpu(get_log->mcast_rx_frame);
-               stats->fcs_error = le32_to_cpu(get_log->fcs_error);
-               stats->tx_frame = le32_to_cpu(get_log->tx_frame);
-               stats->wep_icv_error[0] =
-                       le32_to_cpu(get_log->wep_icv_err_cnt[0]);
-               stats->wep_icv_error[1] =
-                       le32_to_cpu(get_log->wep_icv_err_cnt[1]);
-               stats->wep_icv_error[2] =
-                       le32_to_cpu(get_log->wep_icv_err_cnt[2]);
-               stats->wep_icv_error[3] =
-                       le32_to_cpu(get_log->wep_icv_err_cnt[3]);
-               stats->bcn_rcv_cnt = le32_to_cpu(get_log->bcn_rcv_cnt);
-               stats->bcn_miss_cnt = le32_to_cpu(get_log->bcn_miss_cnt);
-       }
-
-       return 0;
-}
-
-/*
- * This function handles the command response of set/get Tx rate
- * configurations.
- *
- * Handling includes changing the header fields into CPU format
- * and saving the following parameters in driver -
- *      - DSSS rate bitmap
- *      - OFDM rate bitmap
- *      - HT MCS rate bitmaps
- *
- * Based on the new rate bitmaps, the function re-evaluates if
- * auto data rate has been activated. If not, it sends another
- * query to the firmware to get the current Tx data rate.
- */
-static int mwifiex_ret_tx_rate_cfg(struct mwifiex_private *priv,
-                                  struct host_cmd_ds_command *resp)
-{
-       struct host_cmd_ds_tx_rate_cfg *rate_cfg = &resp->params.tx_rate_cfg;
-       struct mwifiex_rate_scope *rate_scope;
-       struct mwifiex_ie_types_header *head;
-       u16 tlv, tlv_buf_len, tlv_buf_left;
-       u8 *tlv_buf;
-       u32 i;
-
-       tlv_buf = ((u8 *)rate_cfg) + sizeof(struct host_cmd_ds_tx_rate_cfg);
-       tlv_buf_left = le16_to_cpu(resp->size) - S_DS_GEN - sizeof(*rate_cfg);
-
-       while (tlv_buf_left >= sizeof(*head)) {
-               head = (struct mwifiex_ie_types_header *)tlv_buf;
-               tlv = le16_to_cpu(head->type);
-               tlv_buf_len = le16_to_cpu(head->len);
-
-               if (tlv_buf_left < (sizeof(*head) + tlv_buf_len))
-                       break;
-
-               switch (tlv) {
-               case TLV_TYPE_RATE_SCOPE:
-                       rate_scope = (struct mwifiex_rate_scope *) tlv_buf;
-                       priv->bitmap_rates[0] =
-                               le16_to_cpu(rate_scope->hr_dsss_rate_bitmap);
-                       priv->bitmap_rates[1] =
-                               le16_to_cpu(rate_scope->ofdm_rate_bitmap);
-                       for (i = 0;
-                            i <
-                            sizeof(rate_scope->ht_mcs_rate_bitmap) /
-                            sizeof(u16); i++)
-                               priv->bitmap_rates[2 + i] =
-                                       le16_to_cpu(rate_scope->
-                                                   ht_mcs_rate_bitmap[i]);
-
-                       if (priv->adapter->fw_api_ver == MWIFIEX_FW_V15) {
-                               for (i = 0; i < ARRAY_SIZE(rate_scope->
-                                                          vht_mcs_rate_bitmap);
-                                    i++)
-                                       priv->bitmap_rates[10 + i] =
-                                           le16_to_cpu(rate_scope->
-                                                       vht_mcs_rate_bitmap[i]);
-                       }
-                       break;
-                       /* Add RATE_DROP tlv here */
-               }
-
-               tlv_buf += (sizeof(*head) + tlv_buf_len);
-               tlv_buf_left -= (sizeof(*head) + tlv_buf_len);
-       }
-
-       priv->is_data_rate_auto = mwifiex_is_rate_auto(priv);
-
-       if (priv->is_data_rate_auto)
-               priv->data_rate = 0;
-       else
-               return mwifiex_send_cmd(priv, HostCmd_CMD_802_11_TX_RATE_QUERY,
-                                       HostCmd_ACT_GEN_GET, 0, NULL, false);
-
-       return 0;
-}
-
-/*
- * This function handles the command response of get Tx power level.
- *
- * Handling includes saving the maximum and minimum Tx power levels
- * in driver, as well as sending the values to user.
- */
-static int mwifiex_get_power_level(struct mwifiex_private *priv, void *data_buf)
-{
-       int length, max_power = -1, min_power = -1;
-       struct mwifiex_types_power_group *pg_tlv_hdr;
-       struct mwifiex_power_group *pg;
-
-       if (!data_buf)
-               return -1;
-
-       pg_tlv_hdr = (struct mwifiex_types_power_group *)((u8 *)data_buf);
-       pg = (struct mwifiex_power_group *)
-               ((u8 *) pg_tlv_hdr + sizeof(struct mwifiex_types_power_group));
-       length = le16_to_cpu(pg_tlv_hdr->length);
-
-       /* At least one structure required to update power */
-       if (length < sizeof(struct mwifiex_power_group))
-               return 0;
-
-       max_power = pg->power_max;
-       min_power = pg->power_min;
-       length -= sizeof(struct mwifiex_power_group);
-
-       while (length >= sizeof(struct mwifiex_power_group)) {
-               pg++;
-               if (max_power < pg->power_max)
-                       max_power = pg->power_max;
-
-               if (min_power > pg->power_min)
-                       min_power = pg->power_min;
-
-               length -= sizeof(struct mwifiex_power_group);
-       }
-       priv->min_tx_power_level = (u8) min_power;
-       priv->max_tx_power_level = (u8) max_power;
-
-       return 0;
-}
-
-/*
- * This function handles the command response of set/get Tx power
- * configurations.
- *
- * Handling includes changing the header fields into CPU format
- * and saving the current Tx power level in driver.
- */
-static int mwifiex_ret_tx_power_cfg(struct mwifiex_private *priv,
-                                   struct host_cmd_ds_command *resp)
-{
-       struct mwifiex_adapter *adapter = priv->adapter;
-       struct host_cmd_ds_txpwr_cfg *txp_cfg = &resp->params.txp_cfg;
-       struct mwifiex_types_power_group *pg_tlv_hdr;
-       struct mwifiex_power_group *pg;
-       u16 action = le16_to_cpu(txp_cfg->action);
-       u16 tlv_buf_left;
-
-       pg_tlv_hdr = (struct mwifiex_types_power_group *)
-               ((u8 *)txp_cfg +
-                sizeof(struct host_cmd_ds_txpwr_cfg));
-
-       pg = (struct mwifiex_power_group *)
-               ((u8 *)pg_tlv_hdr +
-                sizeof(struct mwifiex_types_power_group));
-
-       tlv_buf_left = le16_to_cpu(resp->size) - S_DS_GEN - sizeof(*txp_cfg);
-       if (tlv_buf_left <
-                       le16_to_cpu(pg_tlv_hdr->length) + sizeof(*pg_tlv_hdr))
-               return 0;
-
-       switch (action) {
-       case HostCmd_ACT_GEN_GET:
-               if (adapter->hw_status == MWIFIEX_HW_STATUS_INITIALIZING)
-                       mwifiex_get_power_level(priv, pg_tlv_hdr);
-
-               priv->tx_power_level = (u16) pg->power_min;
-               break;
-
-       case HostCmd_ACT_GEN_SET:
-               if (!le32_to_cpu(txp_cfg->mode))
-                       break;
-
-               if (pg->power_max == pg->power_min)
-                       priv->tx_power_level = (u16) pg->power_min;
-               break;
-       default:
-               mwifiex_dbg(adapter, ERROR,
-                           "CMD_RESP: unknown cmd action %d\n",
-                           action);
-               return 0;
-       }
-       mwifiex_dbg(adapter, INFO,
-                   "info: Current TxPower Level = %d, Max Power=%d, Min Power=%d\n",
-                   priv->tx_power_level, priv->max_tx_power_level,
-                   priv->min_tx_power_level);
-
-       return 0;
-}
-
-/*
- * This function handles the command response of get RF Tx power.
- */
-static int mwifiex_ret_rf_tx_power(struct mwifiex_private *priv,
-                                  struct host_cmd_ds_command *resp)
-{
-       struct host_cmd_ds_rf_tx_pwr *txp = &resp->params.txp;
-       u16 action = le16_to_cpu(txp->action);
-
-       priv->tx_power_level = le16_to_cpu(txp->cur_level);
-
-       if (action == HostCmd_ACT_GEN_GET) {
-               priv->max_tx_power_level = txp->max_power;
-               priv->min_tx_power_level = txp->min_power;
-       }
-
-       mwifiex_dbg(priv->adapter, INFO,
-                   "Current TxPower Level=%d, Max Power=%d, Min Power=%d\n",
-                   priv->tx_power_level, priv->max_tx_power_level,
-                   priv->min_tx_power_level);
-
-       return 0;
-}
-
-/*
- * This function handles the command response of set rf antenna
- */
-static int mwifiex_ret_rf_antenna(struct mwifiex_private *priv,
-                                 struct host_cmd_ds_command *resp)
-{
-       struct host_cmd_ds_rf_ant_mimo *ant_mimo = &resp->params.ant_mimo;
-       struct host_cmd_ds_rf_ant_siso *ant_siso = &resp->params.ant_siso;
-       struct mwifiex_adapter *adapter = priv->adapter;
-
-       if (adapter->hw_dev_mcs_support == HT_STREAM_2X2)
-               mwifiex_dbg(adapter, INFO,
-                           "RF_ANT_RESP: Tx action = 0x%x, Tx Mode = 0x%04x\t"
-                           "Rx action = 0x%x, Rx Mode = 0x%04x\n",
-                           le16_to_cpu(ant_mimo->action_tx),
-                           le16_to_cpu(ant_mimo->tx_ant_mode),
-                           le16_to_cpu(ant_mimo->action_rx),
-                           le16_to_cpu(ant_mimo->rx_ant_mode));
-       else
-               mwifiex_dbg(adapter, INFO,
-                           "RF_ANT_RESP: action = 0x%x, Mode = 0x%04x\n",
-                           le16_to_cpu(ant_siso->action),
-                           le16_to_cpu(ant_siso->ant_mode));
-
-       return 0;
-}
-
-/*
- * This function handles the command response of set/get MAC address.
- *
- * Handling includes saving the MAC address in driver.
- */
-static int mwifiex_ret_802_11_mac_address(struct mwifiex_private *priv,
-                                         struct host_cmd_ds_command *resp)
-{
-       struct host_cmd_ds_802_11_mac_address *cmd_mac_addr =
-                                                       &resp->params.mac_addr;
-
-       memcpy(priv->curr_addr, cmd_mac_addr->mac_addr, ETH_ALEN);
-
-       mwifiex_dbg(priv->adapter, INFO,
-                   "info: set mac address: %pM\n", priv->curr_addr);
-
-       return 0;
-}
-
-/*
- * This function handles the command response of set/get MAC multicast
- * address.
- */
-static int mwifiex_ret_mac_multicast_adr(struct mwifiex_private *priv,
-                                        struct host_cmd_ds_command *resp)
-{
-       return 0;
-}
-
-/*
- * This function handles the command response of get Tx rate query.
- *
- * Handling includes changing the header fields into CPU format
- * and saving the Tx rate and HT information parameters in driver.
- *
- * Both rate configuration and current data rate can be retrieved
- * with this request.
- */
-static int mwifiex_ret_802_11_tx_rate_query(struct mwifiex_private *priv,
-                                           struct host_cmd_ds_command *resp)
-{
-       priv->tx_rate = resp->params.tx_rate.tx_rate;
-       priv->tx_htinfo = resp->params.tx_rate.ht_info;
-       if (!priv->is_data_rate_auto)
-               priv->data_rate =
-                       mwifiex_index_to_data_rate(priv, priv->tx_rate,
-                                                  priv->tx_htinfo);
-
-       return 0;
-}
-
-/*
- * This function handles the command response of a deauthenticate
- * command.
- *
- * If the deauthenticated MAC matches the current BSS MAC, the connection
- * state is reset.
- */
-static int mwifiex_ret_802_11_deauthenticate(struct mwifiex_private *priv,
-                                            struct host_cmd_ds_command *resp)
-{
-       struct mwifiex_adapter *adapter = priv->adapter;
-
-       adapter->dbg.num_cmd_deauth++;
-       if (!memcmp(resp->params.deauth.mac_addr,
-                   &priv->curr_bss_params.bss_descriptor.mac_address,
-                   sizeof(resp->params.deauth.mac_addr)))
-               mwifiex_reset_connect_state(priv, WLAN_REASON_DEAUTH_LEAVING);
-
-       return 0;
-}
-
-/*
- * This function handles the command response of ad-hoc stop.
- *
- * The function resets the connection state in driver.
- */
-static int mwifiex_ret_802_11_ad_hoc_stop(struct mwifiex_private *priv,
-                                         struct host_cmd_ds_command *resp)
-{
-       mwifiex_reset_connect_state(priv, WLAN_REASON_DEAUTH_LEAVING);
-       return 0;
-}
-
-/*
- * This function handles the command response of set/get v1 key material.
- *
- * Handling includes updating the driver parameters to reflect the
- * changes.
- */
-static int mwifiex_ret_802_11_key_material_v1(struct mwifiex_private *priv,
-                                             struct host_cmd_ds_command *resp)
-{
-       struct host_cmd_ds_802_11_key_material *key =
-                                               &resp->params.key_material;
-
-       if (le16_to_cpu(key->action) == HostCmd_ACT_GEN_SET) {
-               if ((le16_to_cpu(key->key_param_set.key_info) & KEY_MCAST)) {
-                       mwifiex_dbg(priv->adapter, INFO,
-                                   "info: key: GTK is set\n");
-                       priv->wpa_is_gtk_set = true;
-                       priv->scan_block = false;
-                       priv->port_open = true;
-               }
-       }
-
-       memset(priv->aes_key.key_param_set.key, 0,
-              sizeof(key->key_param_set.key));
-       priv->aes_key.key_param_set.key_len = key->key_param_set.key_len;
-       memcpy(priv->aes_key.key_param_set.key, key->key_param_set.key,
-              le16_to_cpu(priv->aes_key.key_param_set.key_len));
-
-       return 0;
-}
-
-/*
- * This function handles the command response of set/get v2 key material.
- *
- * Handling includes updating the driver parameters to reflect the
- * changes.
- */
-static int mwifiex_ret_802_11_key_material_v2(struct mwifiex_private *priv,
-                                             struct host_cmd_ds_command *resp)
-{
-       struct host_cmd_ds_802_11_key_material_v2 *key_v2;
-       __le16 len;
-
-       key_v2 = &resp->params.key_material_v2;
-       if (le16_to_cpu(key_v2->action) == HostCmd_ACT_GEN_SET) {
-               if ((le16_to_cpu(key_v2->key_param_set.key_info) & KEY_MCAST)) {
-                       mwifiex_dbg(priv->adapter, INFO, "info: key: GTK is set\n");
-                       priv->wpa_is_gtk_set = true;
-                       priv->scan_block = false;
-                       priv->port_open = true;
-               }
-       }
-
-       if (key_v2->key_param_set.key_type != KEY_TYPE_ID_AES)
-               return 0;
-
-       memset(priv->aes_key_v2.key_param_set.key_params.aes.key, 0,
-              WLAN_KEY_LEN_CCMP);
-       priv->aes_key_v2.key_param_set.key_params.aes.key_len =
-                               key_v2->key_param_set.key_params.aes.key_len;
-       len = priv->aes_key_v2.key_param_set.key_params.aes.key_len;
-       memcpy(priv->aes_key_v2.key_param_set.key_params.aes.key,
-              key_v2->key_param_set.key_params.aes.key, le16_to_cpu(len));
-
-       return 0;
-}
-
-/* Wrapper function for processing response of key material command */
-static int mwifiex_ret_802_11_key_material(struct mwifiex_private *priv,
-                                          struct host_cmd_ds_command *resp)
-{
-       if (priv->adapter->key_api_major_ver == KEY_API_VER_MAJOR_V2)
-               return mwifiex_ret_802_11_key_material_v2(priv, resp);
-       else
-               return mwifiex_ret_802_11_key_material_v1(priv, resp);
-}
-
-/*
- * This function handles the command response of get 11d domain information.
- */
-static int mwifiex_ret_802_11d_domain_info(struct mwifiex_private *priv,
-                                          struct host_cmd_ds_command *resp)
-{
-       struct host_cmd_ds_802_11d_domain_info_rsp *domain_info =
-               &resp->params.domain_info_resp;
-       struct mwifiex_ietypes_domain_param_set *domain = &domain_info->domain;
-       u16 action = le16_to_cpu(domain_info->action);
-       u8 no_of_triplet;
-
-       no_of_triplet = (u8) ((le16_to_cpu(domain->header.len)
-                               - IEEE80211_COUNTRY_STRING_LEN)
-                             / sizeof(struct ieee80211_country_ie_triplet));
-
-       mwifiex_dbg(priv->adapter, INFO,
-                   "info: 11D Domain Info Resp: no_of_triplet=%d\n",
-                   no_of_triplet);
-
-       if (no_of_triplet > MWIFIEX_MAX_TRIPLET_802_11D) {
-               mwifiex_dbg(priv->adapter, FATAL,
-                           "11D: invalid number of triplets %d returned\n",
-                           no_of_triplet);
-               return -1;
-       }
-
-       switch (action) {
-       case HostCmd_ACT_GEN_SET:  /* Proc Set Action */
-               break;
-       case HostCmd_ACT_GEN_GET:
-               break;
-       default:
-               mwifiex_dbg(priv->adapter, ERROR,
-                           "11D: invalid action:%d\n", domain_info->action);
-               return -1;
-       }
-
-       return 0;
-}
-
-/*
- * This function handles the command response of get extended version.
- *
- * Handling includes forming the extended version string and sending it
- * to application.
- */
-static int mwifiex_ret_ver_ext(struct mwifiex_private *priv,
-                              struct host_cmd_ds_command *resp,
-                              struct host_cmd_ds_version_ext *version_ext)
-{
-       struct host_cmd_ds_version_ext *ver_ext = &resp->params.verext;
-
-       if (version_ext) {
-               version_ext->version_str_sel = ver_ext->version_str_sel;
-               memcpy(version_ext->version_str, ver_ext->version_str,
-                      sizeof(char) * 128);
-               memcpy(priv->version_str, ver_ext->version_str, 128);
-       }
-       return 0;
-}
-
-/*
- * This function handles the command response of remain on channel.
- */
-static int
-mwifiex_ret_remain_on_chan(struct mwifiex_private *priv,
-                          struct host_cmd_ds_command *resp,
-                          struct host_cmd_ds_remain_on_chan *roc_cfg)
-{
-       struct host_cmd_ds_remain_on_chan *resp_cfg = &resp->params.roc_cfg;
-
-       if (roc_cfg)
-               memcpy(roc_cfg, resp_cfg, sizeof(*roc_cfg));
-
-       return 0;
-}
-
-/*
- * This function handles the command response of P2P mode cfg.
- */
-static int
-mwifiex_ret_p2p_mode_cfg(struct mwifiex_private *priv,
-                        struct host_cmd_ds_command *resp,
-                        void *data_buf)
-{
-       struct host_cmd_ds_p2p_mode_cfg *mode_cfg = &resp->params.mode_cfg;
-
-       if (data_buf)
-               *((u16 *)data_buf) = le16_to_cpu(mode_cfg->mode);
-
-       return 0;
-}
-
-/* This function handles the command response of mem_access command
- */
-static int
-mwifiex_ret_mem_access(struct mwifiex_private *priv,
-                      struct host_cmd_ds_command *resp, void *pioctl_buf)
-{
-       struct host_cmd_ds_mem_access *mem = (void *)&resp->params.mem;
-
-       priv->mem_rw.addr = le32_to_cpu(mem->addr);
-       priv->mem_rw.value = le32_to_cpu(mem->value);
-
-       return 0;
-}
-/*
- * This function handles the command response of register access.
- *
- * The register value and offset are returned to the user. For EEPROM
- * access, the byte count is also returned.
- */
-static int mwifiex_ret_reg_access(u16 type, struct host_cmd_ds_command *resp,
-                                 void *data_buf)
-{
-       struct mwifiex_ds_reg_rw *reg_rw;
-       struct mwifiex_ds_read_eeprom *eeprom;
-       union reg {
-               struct host_cmd_ds_mac_reg_access *mac;
-               struct host_cmd_ds_bbp_reg_access *bbp;
-               struct host_cmd_ds_rf_reg_access *rf;
-               struct host_cmd_ds_pmic_reg_access *pmic;
-               struct host_cmd_ds_802_11_eeprom_access *eeprom;
-       } r;
-
-       if (!data_buf)
-               return 0;
-
-       reg_rw = data_buf;
-       eeprom = data_buf;
-       switch (type) {
-       case HostCmd_CMD_MAC_REG_ACCESS:
-               r.mac = &resp->params.mac_reg;
-               reg_rw->offset = cpu_to_le32((u32) le16_to_cpu(r.mac->offset));
-               reg_rw->value = r.mac->value;
-               break;
-       case HostCmd_CMD_BBP_REG_ACCESS:
-               r.bbp = &resp->params.bbp_reg;
-               reg_rw->offset = cpu_to_le32((u32) le16_to_cpu(r.bbp->offset));
-               reg_rw->value = cpu_to_le32((u32) r.bbp->value);
-               break;
-
-       case HostCmd_CMD_RF_REG_ACCESS:
-               r.rf = &resp->params.rf_reg;
-               reg_rw->offset = cpu_to_le32((u32) le16_to_cpu(r.rf->offset));
-               reg_rw->value = cpu_to_le32((u32) r.bbp->value);
-               break;
-       case HostCmd_CMD_PMIC_REG_ACCESS:
-               r.pmic = &resp->params.pmic_reg;
-               reg_rw->offset = cpu_to_le32((u32) le16_to_cpu(r.pmic->offset));
-               reg_rw->value = cpu_to_le32((u32) r.pmic->value);
-               break;
-       case HostCmd_CMD_CAU_REG_ACCESS:
-               r.rf = &resp->params.rf_reg;
-               reg_rw->offset = cpu_to_le32((u32) le16_to_cpu(r.rf->offset));
-               reg_rw->value = cpu_to_le32((u32) r.rf->value);
-               break;
-       case HostCmd_CMD_802_11_EEPROM_ACCESS:
-               r.eeprom = &resp->params.eeprom;
-               pr_debug("info: EEPROM read len=%x\n", r.eeprom->byte_count);
-               if (le16_to_cpu(eeprom->byte_count) <
-                   le16_to_cpu(r.eeprom->byte_count)) {
-                       eeprom->byte_count = cpu_to_le16(0);
-                       pr_debug("info: EEPROM read length is too big\n");
-                       return -1;
-               }
-               eeprom->offset = r.eeprom->offset;
-               eeprom->byte_count = r.eeprom->byte_count;
-               if (le16_to_cpu(eeprom->byte_count) > 0)
-                       memcpy(&eeprom->value, &r.eeprom->value,
-                              le16_to_cpu(r.eeprom->byte_count));
-
-               break;
-       default:
-               return -1;
-       }
-       return 0;
-}
-
-/*
- * This function handles the command response of get IBSS coalescing status.
- *
- * If the received BSSID is different than the current one, the current BSSID,
- * beacon interval, ATIM window and ERP information are updated, along with
- * changing the ad-hoc state accordingly.
- */
-static int mwifiex_ret_ibss_coalescing_status(struct mwifiex_private *priv,
-                                             struct host_cmd_ds_command *resp)
-{
-       struct host_cmd_ds_802_11_ibss_status *ibss_coal_resp =
-                                       &(resp->params.ibss_coalescing);
-
-       if (le16_to_cpu(ibss_coal_resp->action) == HostCmd_ACT_GEN_SET)
-               return 0;
-
-       mwifiex_dbg(priv->adapter, INFO,
-                   "info: new BSSID %pM\n", ibss_coal_resp->bssid);
-
-       /* If rsp has NULL BSSID, Just return..... No Action */
-       if (is_zero_ether_addr(ibss_coal_resp->bssid)) {
-               mwifiex_dbg(priv->adapter, FATAL, "new BSSID is NULL\n");
-               return 0;
-       }
-
-       /* If BSSID is diff, modify current BSS parameters */
-       if (!ether_addr_equal(priv->curr_bss_params.bss_descriptor.mac_address, ibss_coal_resp->bssid)) {
-               /* BSSID */
-               memcpy(priv->curr_bss_params.bss_descriptor.mac_address,
-                      ibss_coal_resp->bssid, ETH_ALEN);
-
-               /* Beacon Interval */
-               priv->curr_bss_params.bss_descriptor.beacon_period
-                       = le16_to_cpu(ibss_coal_resp->beacon_interval);
-
-               /* ERP Information */
-               priv->curr_bss_params.bss_descriptor.erp_flags =
-                       (u8) le16_to_cpu(ibss_coal_resp->use_g_rate_protect);
-
-               priv->adhoc_state = ADHOC_COALESCED;
-       }
-
-       return 0;
-}
-static int mwifiex_ret_tdls_oper(struct mwifiex_private *priv,
-                                struct host_cmd_ds_command *resp)
-{
-       struct host_cmd_ds_tdls_oper *cmd_tdls_oper = &resp->params.tdls_oper;
-       u16 reason = le16_to_cpu(cmd_tdls_oper->reason);
-       u16 action = le16_to_cpu(cmd_tdls_oper->tdls_action);
-       struct mwifiex_sta_node *node =
-                          mwifiex_get_sta_entry(priv, cmd_tdls_oper->peer_mac);
-
-       switch (action) {
-       case ACT_TDLS_DELETE:
-               if (reason) {
-                       if (!node || reason == TDLS_ERR_LINK_NONEXISTENT)
-                               mwifiex_dbg(priv->adapter, MSG,
-                                           "TDLS link delete for %pM failed: reason %d\n",
-                                           cmd_tdls_oper->peer_mac, reason);
-                       else
-                               mwifiex_dbg(priv->adapter, ERROR,
-                                           "TDLS link delete for %pM failed: reason %d\n",
-                                           cmd_tdls_oper->peer_mac, reason);
-               } else {
-                       mwifiex_dbg(priv->adapter, MSG,
-                                   "TDLS link delete for %pM successful\n",
-                                   cmd_tdls_oper->peer_mac);
-               }
-               break;
-       case ACT_TDLS_CREATE:
-               if (reason) {
-                       mwifiex_dbg(priv->adapter, ERROR,
-                                   "TDLS link creation for %pM failed: reason %d",
-                                   cmd_tdls_oper->peer_mac, reason);
-                       if (node && reason != TDLS_ERR_LINK_EXISTS)
-                               node->tdls_status = TDLS_SETUP_FAILURE;
-               } else {
-                       mwifiex_dbg(priv->adapter, MSG,
-                                   "TDLS link creation for %pM successful",
-                                   cmd_tdls_oper->peer_mac);
-               }
-               break;
-       case ACT_TDLS_CONFIG:
-               if (reason) {
-                       mwifiex_dbg(priv->adapter, ERROR,
-                                   "TDLS link config for %pM failed, reason %d\n",
-                                   cmd_tdls_oper->peer_mac, reason);
-                       if (node)
-                               node->tdls_status = TDLS_SETUP_FAILURE;
-               } else {
-                       mwifiex_dbg(priv->adapter, MSG,
-                                   "TDLS link config for %pM successful\n",
-                                   cmd_tdls_oper->peer_mac);
-               }
-               break;
-       default:
-               mwifiex_dbg(priv->adapter, ERROR,
-                           "Unknown TDLS command action response %d", action);
-               return -1;
-       }
-
-       return 0;
-}
-/*
- * This function handles the command response for subscribe event command.
- */
-static int mwifiex_ret_subsc_evt(struct mwifiex_private *priv,
-                                struct host_cmd_ds_command *resp)
-{
-       struct host_cmd_ds_802_11_subsc_evt *cmd_sub_event =
-               &resp->params.subsc_evt;
-
-       /* For every subscribe event command (Get/Set/Clear), FW reports the
-        * current set of subscribed events*/
-       mwifiex_dbg(priv->adapter, EVENT,
-                   "Bitmap of currently subscribed events: %16x\n",
-                   le16_to_cpu(cmd_sub_event->events));
-
-       return 0;
-}
-
-static int mwifiex_ret_uap_sta_list(struct mwifiex_private *priv,
-                                   struct host_cmd_ds_command *resp)
-{
-       struct host_cmd_ds_sta_list *sta_list =
-               &resp->params.sta_list;
-       struct mwifiex_ie_types_sta_info *sta_info = (void *)&sta_list->tlv;
-       int i;
-       struct mwifiex_sta_node *sta_node;
-
-       for (i = 0; i < sta_list->sta_count; i++) {
-               sta_node = mwifiex_get_sta_entry(priv, sta_info->mac);
-               if (unlikely(!sta_node))
-                       continue;
-
-               sta_node->stats.rssi = sta_info->rssi;
-               sta_info++;
-       }
-
-       return 0;
-}
-
-/* This function handles the command response of set_cfg_data */
-static int mwifiex_ret_cfg_data(struct mwifiex_private *priv,
-                               struct host_cmd_ds_command *resp)
-{
-       if (resp->result != HostCmd_RESULT_OK) {
-               mwifiex_dbg(priv->adapter, ERROR, "Cal data cmd resp failed\n");
-               return -1;
-       }
-
-       return 0;
-}
-
-/** This Function handles the command response of sdio rx aggr */
-static int mwifiex_ret_sdio_rx_aggr_cfg(struct mwifiex_private *priv,
-                                       struct host_cmd_ds_command *resp)
-{
-       struct mwifiex_adapter *adapter = priv->adapter;
-       struct host_cmd_sdio_sp_rx_aggr_cfg *cfg =
-                               &resp->params.sdio_rx_aggr_cfg;
-
-       adapter->sdio_rx_aggr_enable = cfg->enable;
-       adapter->sdio_rx_block_size = le16_to_cpu(cfg->block_size);
-
-       return 0;
-}
-
-static int mwifiex_ret_robust_coex(struct mwifiex_private *priv,
-                                  struct host_cmd_ds_command *resp,
-                                  bool *is_timeshare)
-{
-       struct host_cmd_ds_robust_coex *coex = &resp->params.coex;
-       struct mwifiex_ie_types_robust_coex *coex_tlv;
-       u16 action = le16_to_cpu(coex->action);
-       u32 mode;
-
-       coex_tlv = (struct mwifiex_ie_types_robust_coex
-                   *)((u8 *)coex + sizeof(struct host_cmd_ds_robust_coex));
-       if (action == HostCmd_ACT_GEN_GET) {
-               mode = le32_to_cpu(coex_tlv->mode);
-               if (mode == MWIFIEX_COEX_MODE_TIMESHARE)
-                       *is_timeshare = true;
-               else
-                       *is_timeshare = false;
-       }
-
-       return 0;
-}
-
-/*
- * This function handles the command responses.
- *
- * This is a generic function, which calls command specific
- * response handlers based on the command ID.
- */
-int mwifiex_process_sta_cmdresp(struct mwifiex_private *priv, u16 cmdresp_no,
-                               struct host_cmd_ds_command *resp)
-{
-       int ret = 0;
-       struct mwifiex_adapter *adapter = priv->adapter;
-       void *data_buf = adapter->curr_cmd->data_buf;
-
-       /* If the command is not successful, cleanup and return failure */
-       if (resp->result != HostCmd_RESULT_OK) {
-               mwifiex_process_cmdresp_error(priv, resp);
-               return -1;
-       }
-       /* Command successful, handle response */
-       switch (cmdresp_no) {
-       case HostCmd_CMD_GET_HW_SPEC:
-               ret = mwifiex_ret_get_hw_spec(priv, resp);
-               break;
-       case HostCmd_CMD_CFG_DATA:
-               ret = mwifiex_ret_cfg_data(priv, resp);
-               break;
-       case HostCmd_CMD_MAC_CONTROL:
-               break;
-       case HostCmd_CMD_802_11_MAC_ADDRESS:
-               ret = mwifiex_ret_802_11_mac_address(priv, resp);
-               break;
-       case HostCmd_CMD_MAC_MULTICAST_ADR:
-               ret = mwifiex_ret_mac_multicast_adr(priv, resp);
-               break;
-       case HostCmd_CMD_TX_RATE_CFG:
-               ret = mwifiex_ret_tx_rate_cfg(priv, resp);
-               break;
-       case HostCmd_CMD_802_11_SCAN:
-               ret = mwifiex_ret_802_11_scan(priv, resp);
-               adapter->curr_cmd->wait_q_enabled = false;
-               break;
-       case HostCmd_CMD_802_11_SCAN_EXT:
-               ret = mwifiex_ret_802_11_scan_ext(priv, resp);
-               adapter->curr_cmd->wait_q_enabled = false;
-               break;
-       case HostCmd_CMD_802_11_BG_SCAN_QUERY:
-               ret = mwifiex_ret_802_11_scan(priv, resp);
-               mwifiex_dbg(adapter, CMD,
-                           "info: CMD_RESP: BG_SCAN result is ready!\n");
-               break;
-       case HostCmd_CMD_TXPWR_CFG:
-               ret = mwifiex_ret_tx_power_cfg(priv, resp);
-               break;
-       case HostCmd_CMD_RF_TX_PWR:
-               ret = mwifiex_ret_rf_tx_power(priv, resp);
-               break;
-       case HostCmd_CMD_RF_ANTENNA:
-               ret = mwifiex_ret_rf_antenna(priv, resp);
-               break;
-       case HostCmd_CMD_802_11_PS_MODE_ENH:
-               ret = mwifiex_ret_enh_power_mode(priv, resp, data_buf);
-               break;
-       case HostCmd_CMD_802_11_HS_CFG_ENH:
-               ret = mwifiex_ret_802_11_hs_cfg(priv, resp);
-               break;
-       case HostCmd_CMD_802_11_ASSOCIATE:
-               ret = mwifiex_ret_802_11_associate(priv, resp);
-               break;
-       case HostCmd_CMD_802_11_DEAUTHENTICATE:
-               ret = mwifiex_ret_802_11_deauthenticate(priv, resp);
-               break;
-       case HostCmd_CMD_802_11_AD_HOC_START:
-       case HostCmd_CMD_802_11_AD_HOC_JOIN:
-               ret = mwifiex_ret_802_11_ad_hoc(priv, resp);
-               break;
-       case HostCmd_CMD_802_11_AD_HOC_STOP:
-               ret = mwifiex_ret_802_11_ad_hoc_stop(priv, resp);
-               break;
-       case HostCmd_CMD_802_11_GET_LOG:
-               ret = mwifiex_ret_get_log(priv, resp, data_buf);
-               break;
-       case HostCmd_CMD_RSSI_INFO:
-               ret = mwifiex_ret_802_11_rssi_info(priv, resp);
-               break;
-       case HostCmd_CMD_802_11_SNMP_MIB:
-               ret = mwifiex_ret_802_11_snmp_mib(priv, resp, data_buf);
-               break;
-       case HostCmd_CMD_802_11_TX_RATE_QUERY:
-               ret = mwifiex_ret_802_11_tx_rate_query(priv, resp);
-               break;
-       case HostCmd_CMD_VERSION_EXT:
-               ret = mwifiex_ret_ver_ext(priv, resp, data_buf);
-               break;
-       case HostCmd_CMD_REMAIN_ON_CHAN:
-               ret = mwifiex_ret_remain_on_chan(priv, resp, data_buf);
-               break;
-       case HostCmd_CMD_11AC_CFG:
-               break;
-       case HostCmd_CMD_P2P_MODE_CFG:
-               ret = mwifiex_ret_p2p_mode_cfg(priv, resp, data_buf);
-               break;
-       case HostCmd_CMD_MGMT_FRAME_REG:
-       case HostCmd_CMD_FUNC_INIT:
-       case HostCmd_CMD_FUNC_SHUTDOWN:
-               break;
-       case HostCmd_CMD_802_11_KEY_MATERIAL:
-               ret = mwifiex_ret_802_11_key_material(priv, resp);
-               break;
-       case HostCmd_CMD_802_11D_DOMAIN_INFO:
-               ret = mwifiex_ret_802_11d_domain_info(priv, resp);
-               break;
-       case HostCmd_CMD_11N_ADDBA_REQ:
-               ret = mwifiex_ret_11n_addba_req(priv, resp);
-               break;
-       case HostCmd_CMD_11N_DELBA:
-               ret = mwifiex_ret_11n_delba(priv, resp);
-               break;
-       case HostCmd_CMD_11N_ADDBA_RSP:
-               ret = mwifiex_ret_11n_addba_resp(priv, resp);
-               break;
-       case HostCmd_CMD_RECONFIGURE_TX_BUFF:
-               if (0xffff == (u16)le16_to_cpu(resp->params.tx_buf.buff_size)) {
-                       if (adapter->iface_type == MWIFIEX_USB &&
-                           adapter->usb_mc_setup) {
-                               if (adapter->if_ops.multi_port_resync)
-                                       adapter->if_ops.
-                                               multi_port_resync(adapter);
-                               adapter->usb_mc_setup = false;
-                               adapter->tx_lock_flag = false;
-                       }
-                       break;
-               }
-               adapter->tx_buf_size = (u16) le16_to_cpu(resp->params.
-                                                            tx_buf.buff_size);
-               adapter->tx_buf_size = (adapter->tx_buf_size
-                                       / MWIFIEX_SDIO_BLOCK_SIZE)
-                                      * MWIFIEX_SDIO_BLOCK_SIZE;
-               adapter->curr_tx_buf_size = adapter->tx_buf_size;
-               mwifiex_dbg(adapter, CMD, "cmd: curr_tx_buf_size=%d\n",
-                           adapter->curr_tx_buf_size);
-
-               if (adapter->if_ops.update_mp_end_port)
-                       adapter->if_ops.update_mp_end_port(adapter,
-                               le16_to_cpu(resp->params.tx_buf.mp_end_port));
-               break;
-       case HostCmd_CMD_AMSDU_AGGR_CTRL:
-               break;
-       case HostCmd_CMD_WMM_GET_STATUS:
-               ret = mwifiex_ret_wmm_get_status(priv, resp);
-               break;
-       case HostCmd_CMD_802_11_IBSS_COALESCING_STATUS:
-               ret = mwifiex_ret_ibss_coalescing_status(priv, resp);
-               break;
-       case HostCmd_CMD_MEM_ACCESS:
-               ret = mwifiex_ret_mem_access(priv, resp, data_buf);
-               break;
-       case HostCmd_CMD_MAC_REG_ACCESS:
-       case HostCmd_CMD_BBP_REG_ACCESS:
-       case HostCmd_CMD_RF_REG_ACCESS:
-       case HostCmd_CMD_PMIC_REG_ACCESS:
-       case HostCmd_CMD_CAU_REG_ACCESS:
-       case HostCmd_CMD_802_11_EEPROM_ACCESS:
-               ret = mwifiex_ret_reg_access(cmdresp_no, resp, data_buf);
-               break;
-       case HostCmd_CMD_SET_BSS_MODE:
-               break;
-       case HostCmd_CMD_11N_CFG:
-               break;
-       case HostCmd_CMD_PCIE_DESC_DETAILS:
-               break;
-       case HostCmd_CMD_802_11_SUBSCRIBE_EVENT:
-               ret = mwifiex_ret_subsc_evt(priv, resp);
-               break;
-       case HostCmd_CMD_UAP_SYS_CONFIG:
-               break;
-       case HOST_CMD_APCMD_STA_LIST:
-               ret = mwifiex_ret_uap_sta_list(priv, resp);
-               break;
-       case HostCmd_CMD_UAP_BSS_START:
-               adapter->tx_lock_flag = false;
-               adapter->pps_uapsd_mode = false;
-               adapter->delay_null_pkt = false;
-               priv->bss_started = 1;
-               break;
-       case HostCmd_CMD_UAP_BSS_STOP:
-               priv->bss_started = 0;
-               break;
-       case HostCmd_CMD_UAP_STA_DEAUTH:
-               break;
-       case HOST_CMD_APCMD_SYS_RESET:
-               break;
-       case HostCmd_CMD_MEF_CFG:
-               break;
-       case HostCmd_CMD_COALESCE_CFG:
-               break;
-       case HostCmd_CMD_TDLS_OPER:
-               ret = mwifiex_ret_tdls_oper(priv, resp);
-       case HostCmd_CMD_MC_POLICY:
-               break;
-       case HostCmd_CMD_CHAN_REPORT_REQUEST:
-               break;
-       case HostCmd_CMD_SDIO_SP_RX_AGGR_CFG:
-               ret = mwifiex_ret_sdio_rx_aggr_cfg(priv, resp);
-               break;
-       case HostCmd_CMD_TDLS_CONFIG:
-               break;
-       case HostCmd_CMD_ROBUST_COEX:
-               ret = mwifiex_ret_robust_coex(priv, resp, data_buf);
-               break;
-       default:
-               mwifiex_dbg(adapter, ERROR,
-                           "CMD_RESP: unknown cmd response %#x\n",
-                           resp->command);
-               break;
-       }
-
-       return ret;
-}
diff --git a/drivers/net/wireless/mwifiex/sta_event.c b/drivers/net/wireless/mwifiex/sta_event.c
deleted file mode 100644 (file)
index ff3ee9d..0000000
+++ /dev/null
@@ -1,864 +0,0 @@
-/*
- * Marvell Wireless LAN device driver: station event handling
- *
- * Copyright (C) 2011-2014, Marvell International Ltd.
- *
- * This software file (the "File") is distributed by Marvell International
- * Ltd. under the terms of the GNU General Public License Version 2, June 1991
- * (the "License").  You may use, redistribute and/or modify this File in
- * accordance with the terms and conditions of the License, a copy of which
- * is available by writing to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the
- * worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
- *
- * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
- * ARE EXPRESSLY DISCLAIMED.  The License provides additional details about
- * this warranty disclaimer.
- */
-
-#include "decl.h"
-#include "ioctl.h"
-#include "util.h"
-#include "fw.h"
-#include "main.h"
-#include "wmm.h"
-#include "11n.h"
-
-/*
- * This function resets the connection state.
- *
- * The function is invoked after receiving a disconnect event from firmware,
- * and performs the following actions -
- *      - Set media status to disconnected
- *      - Clean up Tx and Rx packets
- *      - Resets SNR/NF/RSSI value in driver
- *      - Resets security configurations in driver
- *      - Enables auto data rate
- *      - Saves the previous SSID and BSSID so that they can
- *        be used for re-association, if required
- *      - Erases current SSID and BSSID information
- *      - Sends a disconnect event to upper layers/applications.
- */
-void
-mwifiex_reset_connect_state(struct mwifiex_private *priv, u16 reason_code)
-{
-       struct mwifiex_adapter *adapter = priv->adapter;
-
-       if (!priv->media_connected)
-               return;
-
-       mwifiex_dbg(adapter, INFO,
-                   "info: handles disconnect event\n");
-
-       priv->media_connected = false;
-
-       priv->scan_block = false;
-       priv->port_open = false;
-
-       if ((GET_BSS_ROLE(priv) == MWIFIEX_BSS_ROLE_STA) &&
-           ISSUPP_TDLS_ENABLED(priv->adapter->fw_cap_info)) {
-               mwifiex_disable_all_tdls_links(priv);
-
-               if (priv->adapter->auto_tdls)
-                       mwifiex_clean_auto_tdls(priv);
-       }
-
-       /* Free Tx and Rx packets, report disconnect to upper layer */
-       mwifiex_clean_txrx(priv);
-
-       /* Reset SNR/NF/RSSI values */
-       priv->data_rssi_last = 0;
-       priv->data_nf_last = 0;
-       priv->data_rssi_avg = 0;
-       priv->data_nf_avg = 0;
-       priv->bcn_rssi_last = 0;
-       priv->bcn_nf_last = 0;
-       priv->bcn_rssi_avg = 0;
-       priv->bcn_nf_avg = 0;
-       priv->rxpd_rate = 0;
-       priv->rxpd_htinfo = 0;
-       priv->sec_info.wpa_enabled = false;
-       priv->sec_info.wpa2_enabled = false;
-       priv->wpa_ie_len = 0;
-
-       priv->sec_info.wapi_enabled = false;
-       priv->wapi_ie_len = 0;
-       priv->sec_info.wapi_key_on = false;
-
-       priv->sec_info.encryption_mode = 0;
-
-       /* Enable auto data rate */
-       priv->is_data_rate_auto = true;
-       priv->data_rate = 0;
-
-       if ((GET_BSS_ROLE(priv) == MWIFIEX_BSS_ROLE_STA ||
-            GET_BSS_ROLE(priv) == MWIFIEX_BSS_ROLE_UAP) && priv->hist_data)
-               mwifiex_hist_data_reset(priv);
-
-       if (priv->bss_mode == NL80211_IFTYPE_ADHOC) {
-               priv->adhoc_state = ADHOC_IDLE;
-               priv->adhoc_is_link_sensed = false;
-       }
-
-       /*
-        * Memorize the previous SSID and BSSID so
-        * it could be used for re-assoc
-        */
-
-       mwifiex_dbg(adapter, INFO,
-                   "info: previous SSID=%s, SSID len=%u\n",
-                   priv->prev_ssid.ssid, priv->prev_ssid.ssid_len);
-
-       mwifiex_dbg(adapter, INFO,
-                   "info: current SSID=%s, SSID len=%u\n",
-                   priv->curr_bss_params.bss_descriptor.ssid.ssid,
-                   priv->curr_bss_params.bss_descriptor.ssid.ssid_len);
-
-       memcpy(&priv->prev_ssid,
-              &priv->curr_bss_params.bss_descriptor.ssid,
-              sizeof(struct cfg80211_ssid));
-
-       memcpy(priv->prev_bssid,
-              priv->curr_bss_params.bss_descriptor.mac_address, ETH_ALEN);
-
-       /* Need to erase the current SSID and BSSID info */
-       memset(&priv->curr_bss_params, 0x00, sizeof(priv->curr_bss_params));
-
-       adapter->tx_lock_flag = false;
-       adapter->pps_uapsd_mode = false;
-
-       if (adapter->is_cmd_timedout && adapter->curr_cmd)
-               return;
-       priv->media_connected = false;
-       mwifiex_dbg(adapter, MSG,
-                   "info: successfully disconnected from %pM: reason code %d\n",
-                   priv->cfg_bssid, reason_code);
-       if (priv->bss_mode == NL80211_IFTYPE_STATION ||
-           priv->bss_mode == NL80211_IFTYPE_P2P_CLIENT) {
-               cfg80211_disconnected(priv->netdev, reason_code, NULL, 0,
-                                     false, GFP_KERNEL);
-       }
-       eth_zero_addr(priv->cfg_bssid);
-
-       mwifiex_stop_net_dev_queue(priv->netdev, adapter);
-       if (netif_carrier_ok(priv->netdev))
-               netif_carrier_off(priv->netdev);
-}
-
-static int mwifiex_parse_tdls_event(struct mwifiex_private *priv,
-                                   struct sk_buff *event_skb)
-{
-       int ret = 0;
-       struct mwifiex_adapter *adapter = priv->adapter;
-       struct mwifiex_sta_node *sta_ptr;
-       struct mwifiex_tdls_generic_event *tdls_evt =
-                       (void *)event_skb->data + sizeof(adapter->event_cause);
-       u8 *mac = tdls_evt->peer_mac;
-
-       /* reserved 2 bytes are not mandatory in tdls event */
-       if (event_skb->len < (sizeof(struct mwifiex_tdls_generic_event) -
-                             sizeof(u16) - sizeof(adapter->event_cause))) {
-               mwifiex_dbg(adapter, ERROR, "Invalid event length!\n");
-               return -1;
-       }
-
-       sta_ptr = mwifiex_get_sta_entry(priv, tdls_evt->peer_mac);
-       if (!sta_ptr) {
-               mwifiex_dbg(adapter, ERROR, "cannot get sta entry!\n");
-               return -1;
-       }
-
-       switch (le16_to_cpu(tdls_evt->type)) {
-       case TDLS_EVENT_LINK_TEAR_DOWN:
-               cfg80211_tdls_oper_request(priv->netdev,
-                                          tdls_evt->peer_mac,
-                                          NL80211_TDLS_TEARDOWN,
-                                          le16_to_cpu(tdls_evt->u.reason_code),
-                                          GFP_KERNEL);
-               break;
-       case TDLS_EVENT_CHAN_SWITCH_RESULT:
-               mwifiex_dbg(adapter, EVENT, "tdls channel switch result :\n");
-               mwifiex_dbg(adapter, EVENT,
-                           "status=0x%x, reason=0x%x cur_chan=%d\n",
-                           tdls_evt->u.switch_result.status,
-                           tdls_evt->u.switch_result.reason,
-                           tdls_evt->u.switch_result.cur_chan);
-
-               /* tdls channel switch failed */
-               if (tdls_evt->u.switch_result.status != 0) {
-                       switch (tdls_evt->u.switch_result.cur_chan) {
-                       case TDLS_BASE_CHANNEL:
-                               sta_ptr->tdls_status = TDLS_IN_BASE_CHAN;
-                               break;
-                       case TDLS_OFF_CHANNEL:
-                               sta_ptr->tdls_status = TDLS_IN_OFF_CHAN;
-                               break;
-                       default:
-                               break;
-                       }
-                       return ret;
-               }
-
-               /* tdls channel switch success */
-               switch (tdls_evt->u.switch_result.cur_chan) {
-               case TDLS_BASE_CHANNEL:
-                       if (sta_ptr->tdls_status == TDLS_IN_BASE_CHAN)
-                               break;
-                       mwifiex_update_ralist_tx_pause_in_tdls_cs(priv, mac,
-                                                                 false);
-                       sta_ptr->tdls_status = TDLS_IN_BASE_CHAN;
-                       break;
-               case TDLS_OFF_CHANNEL:
-                       if (sta_ptr->tdls_status == TDLS_IN_OFF_CHAN)
-                               break;
-                       mwifiex_update_ralist_tx_pause_in_tdls_cs(priv, mac,
-                                                                 true);
-                       sta_ptr->tdls_status = TDLS_IN_OFF_CHAN;
-                       break;
-               default:
-                       break;
-               }
-
-               break;
-       case TDLS_EVENT_START_CHAN_SWITCH:
-               mwifiex_dbg(adapter, EVENT, "tdls start channel switch...\n");
-               sta_ptr->tdls_status = TDLS_CHAN_SWITCHING;
-               break;
-       case TDLS_EVENT_CHAN_SWITCH_STOPPED:
-               mwifiex_dbg(adapter, EVENT,
-                           "tdls chan switch stopped, reason=%d\n",
-                           tdls_evt->u.cs_stop_reason);
-               break;
-       default:
-               break;
-       }
-
-       return ret;
-}
-
-static void mwifiex_process_uap_tx_pause(struct mwifiex_private *priv,
-                                        struct mwifiex_ie_types_header *tlv)
-{
-       struct mwifiex_tx_pause_tlv *tp;
-       struct mwifiex_sta_node *sta_ptr;
-       unsigned long flags;
-
-       tp = (void *)tlv;
-       mwifiex_dbg(priv->adapter, EVENT,
-                   "uap tx_pause: %pM pause=%d, pkts=%d\n",
-                   tp->peermac, tp->tx_pause,
-                   tp->pkt_cnt);
-
-       if (ether_addr_equal(tp->peermac, priv->netdev->dev_addr)) {
-               if (tp->tx_pause)
-                       priv->port_open = false;
-               else
-                       priv->port_open = true;
-       } else if (is_multicast_ether_addr(tp->peermac)) {
-               mwifiex_update_ralist_tx_pause(priv, tp->peermac, tp->tx_pause);
-       } else {
-               spin_lock_irqsave(&priv->sta_list_spinlock, flags);
-               sta_ptr = mwifiex_get_sta_entry(priv, tp->peermac);
-               spin_unlock_irqrestore(&priv->sta_list_spinlock, flags);
-
-               if (sta_ptr && sta_ptr->tx_pause != tp->tx_pause) {
-                       sta_ptr->tx_pause = tp->tx_pause;
-                       mwifiex_update_ralist_tx_pause(priv, tp->peermac,
-                                                      tp->tx_pause);
-               }
-       }
-}
-
-static void mwifiex_process_sta_tx_pause(struct mwifiex_private *priv,
-                                        struct mwifiex_ie_types_header *tlv)
-{
-       struct mwifiex_tx_pause_tlv *tp;
-       struct mwifiex_sta_node *sta_ptr;
-       int status;
-       unsigned long flags;
-
-       tp = (void *)tlv;
-       mwifiex_dbg(priv->adapter, EVENT,
-                   "sta tx_pause: %pM pause=%d, pkts=%d\n",
-                   tp->peermac, tp->tx_pause,
-                   tp->pkt_cnt);
-
-       if (ether_addr_equal(tp->peermac, priv->cfg_bssid)) {
-               if (tp->tx_pause)
-                       priv->port_open = false;
-               else
-                       priv->port_open = true;
-       } else {
-               if (!ISSUPP_TDLS_ENABLED(priv->adapter->fw_cap_info))
-                       return;
-
-               status = mwifiex_get_tdls_link_status(priv, tp->peermac);
-               if (mwifiex_is_tdls_link_setup(status)) {
-                       spin_lock_irqsave(&priv->sta_list_spinlock, flags);
-                       sta_ptr = mwifiex_get_sta_entry(priv, tp->peermac);
-                       spin_unlock_irqrestore(&priv->sta_list_spinlock, flags);
-
-                       if (sta_ptr && sta_ptr->tx_pause != tp->tx_pause) {
-                               sta_ptr->tx_pause = tp->tx_pause;
-                               mwifiex_update_ralist_tx_pause(priv,
-                                                              tp->peermac,
-                                                              tp->tx_pause);
-                       }
-               }
-       }
-}
-
-void mwifiex_process_multi_chan_event(struct mwifiex_private *priv,
-                                     struct sk_buff *event_skb)
-{
-       struct mwifiex_ie_types_multi_chan_info *chan_info;
-       struct mwifiex_ie_types_mc_group_info *grp_info;
-       struct mwifiex_adapter *adapter = priv->adapter;
-       struct mwifiex_ie_types_header *tlv;
-       u16 tlv_buf_left, tlv_type, tlv_len;
-       int intf_num, bss_type, bss_num, i;
-       struct mwifiex_private *intf_priv;
-
-       tlv_buf_left = event_skb->len - sizeof(u32);
-       chan_info = (void *)event_skb->data + sizeof(u32);
-
-       if (le16_to_cpu(chan_info->header.type) != TLV_TYPE_MULTI_CHAN_INFO ||
-           tlv_buf_left < sizeof(struct mwifiex_ie_types_multi_chan_info)) {
-               mwifiex_dbg(adapter, ERROR,
-                           "unknown TLV in chan_info event\n");
-               return;
-       }
-
-       adapter->usb_mc_status = le16_to_cpu(chan_info->status);
-       mwifiex_dbg(adapter, EVENT, "multi chan operation %s\n",
-                   adapter->usb_mc_status ? "started" : "over");
-
-       tlv_buf_left -= sizeof(struct mwifiex_ie_types_multi_chan_info);
-       tlv = (struct mwifiex_ie_types_header *)chan_info->tlv_buffer;
-
-       while (tlv_buf_left >= (int)sizeof(struct mwifiex_ie_types_header)) {
-               tlv_type = le16_to_cpu(tlv->type);
-               tlv_len  = le16_to_cpu(tlv->len);
-               if ((sizeof(struct mwifiex_ie_types_header) + tlv_len) >
-                   tlv_buf_left) {
-                       mwifiex_dbg(adapter, ERROR, "wrong tlv: tlvLen=%d,\t"
-                                   "tlvBufLeft=%d\n", tlv_len, tlv_buf_left);
-                       break;
-               }
-               if (tlv_type != TLV_TYPE_MC_GROUP_INFO) {
-                       mwifiex_dbg(adapter, ERROR, "wrong tlv type: 0x%x\n",
-                                   tlv_type);
-                       break;
-               }
-
-               grp_info = (struct mwifiex_ie_types_mc_group_info *)tlv;
-               intf_num = grp_info->intf_num;
-               for (i = 0; i < intf_num; i++) {
-                       bss_type = grp_info->bss_type_numlist[i] >> 4;
-                       bss_num = grp_info->bss_type_numlist[i] & BSS_NUM_MASK;
-                       intf_priv = mwifiex_get_priv_by_id(adapter, bss_num,
-                                                          bss_type);
-                       if (!intf_priv) {
-                               mwifiex_dbg(adapter, ERROR,
-                                           "Invalid bss_type bss_num\t"
-                                           "in multi channel event\n");
-                               continue;
-                       }
-                       if (adapter->iface_type == MWIFIEX_USB) {
-                               u8 ep;
-
-                               ep = grp_info->hid_num.usb_ep_num;
-                               if (ep == MWIFIEX_USB_EP_DATA ||
-                                   ep == MWIFIEX_USB_EP_DATA_CH2)
-                                       intf_priv->usb_port = ep;
-                       }
-               }
-
-               tlv_buf_left -= sizeof(struct mwifiex_ie_types_header) +
-                               tlv_len;
-               tlv = (void *)((u8 *)tlv + tlv_len +
-                              sizeof(struct mwifiex_ie_types_header));
-       }
-
-       if (adapter->iface_type == MWIFIEX_USB) {
-               adapter->tx_lock_flag = true;
-               adapter->usb_mc_setup = true;
-               mwifiex_multi_chan_resync(adapter);
-       }
-}
-
-void mwifiex_process_tx_pause_event(struct mwifiex_private *priv,
-                                   struct sk_buff *event_skb)
-{
-       struct mwifiex_ie_types_header *tlv;
-       u16 tlv_type, tlv_len;
-       int tlv_buf_left;
-
-       if (!priv->media_connected) {
-               mwifiex_dbg(priv->adapter, ERROR,
-                           "tx_pause event while disconnected; bss_role=%d\n",
-                           priv->bss_role);
-               return;
-       }
-
-       tlv_buf_left = event_skb->len - sizeof(u32);
-       tlv = (void *)event_skb->data + sizeof(u32);
-
-       while (tlv_buf_left >= (int)sizeof(struct mwifiex_ie_types_header)) {
-               tlv_type = le16_to_cpu(tlv->type);
-               tlv_len  = le16_to_cpu(tlv->len);
-               if ((sizeof(struct mwifiex_ie_types_header) + tlv_len) >
-                   tlv_buf_left) {
-                       mwifiex_dbg(priv->adapter, ERROR,
-                                   "wrong tlv: tlvLen=%d, tlvBufLeft=%d\n",
-                                   tlv_len, tlv_buf_left);
-                       break;
-               }
-               if (tlv_type == TLV_TYPE_TX_PAUSE) {
-                       if (GET_BSS_ROLE(priv) == MWIFIEX_BSS_ROLE_STA)
-                               mwifiex_process_sta_tx_pause(priv, tlv);
-                       else
-                               mwifiex_process_uap_tx_pause(priv, tlv);
-               }
-
-               tlv_buf_left -= sizeof(struct mwifiex_ie_types_header) +
-                               tlv_len;
-               tlv = (void *)((u8 *)tlv + tlv_len +
-                              sizeof(struct mwifiex_ie_types_header));
-       }
-
-}
-
-/*
-* This function handles coex events generated by firmware
-*/
-void mwifiex_bt_coex_wlan_param_update_event(struct mwifiex_private *priv,
-                                            struct sk_buff *event_skb)
-{
-       struct mwifiex_adapter *adapter = priv->adapter;
-       struct mwifiex_ie_types_header *tlv;
-       struct mwifiex_ie_types_btcoex_aggr_win_size *winsizetlv;
-       struct mwifiex_ie_types_btcoex_scan_time *scantlv;
-       s32 len = event_skb->len - sizeof(u32);
-       u8 *cur_ptr = event_skb->data + sizeof(u32);
-       u16 tlv_type, tlv_len;
-
-       while (len >= sizeof(struct mwifiex_ie_types_header)) {
-               tlv = (struct mwifiex_ie_types_header *)cur_ptr;
-               tlv_len = le16_to_cpu(tlv->len);
-               tlv_type = le16_to_cpu(tlv->type);
-
-               if ((tlv_len + sizeof(struct mwifiex_ie_types_header)) > len)
-                       break;
-               switch (tlv_type) {
-               case TLV_BTCOEX_WL_AGGR_WINSIZE:
-                       winsizetlv =
-                           (struct mwifiex_ie_types_btcoex_aggr_win_size *)tlv;
-                       adapter->coex_win_size = winsizetlv->coex_win_size;
-                       adapter->coex_tx_win_size =
-                               winsizetlv->tx_win_size;
-                       adapter->coex_rx_win_size =
-                               winsizetlv->rx_win_size;
-                       mwifiex_coex_ampdu_rxwinsize(adapter);
-                       mwifiex_update_ampdu_txwinsize(adapter);
-                       break;
-
-               case TLV_BTCOEX_WL_SCANTIME:
-                       scantlv =
-                           (struct mwifiex_ie_types_btcoex_scan_time *)tlv;
-                       adapter->coex_scan = scantlv->coex_scan;
-                       adapter->coex_min_scan_time = scantlv->min_scan_time;
-                       adapter->coex_max_scan_time = scantlv->max_scan_time;
-                       break;
-
-               default:
-                       break;
-               }
-
-               len -= tlv_len + sizeof(struct mwifiex_ie_types_header);
-               cur_ptr += tlv_len +
-                       sizeof(struct mwifiex_ie_types_header);
-       }
-
-       dev_dbg(adapter->dev, "coex_scan=%d min_scan=%d coex_win=%d, tx_win=%d rx_win=%d\n",
-               adapter->coex_scan, adapter->coex_min_scan_time,
-               adapter->coex_win_size, adapter->coex_tx_win_size,
-               adapter->coex_rx_win_size);
-}
-
-/*
- * This function handles events generated by firmware.
- *
- * This is a generic function and handles all events.
- *
- * Event specific routines are called by this function based
- * upon the generated event cause.
- *
- * For the following events, the function just forwards them to upper
- * layers, optionally recording the change -
- *      - EVENT_LINK_SENSED
- *      - EVENT_MIC_ERR_UNICAST
- *      - EVENT_MIC_ERR_MULTICAST
- *      - EVENT_PORT_RELEASE
- *      - EVENT_RSSI_LOW
- *      - EVENT_SNR_LOW
- *      - EVENT_MAX_FAIL
- *      - EVENT_RSSI_HIGH
- *      - EVENT_SNR_HIGH
- *      - EVENT_DATA_RSSI_LOW
- *      - EVENT_DATA_SNR_LOW
- *      - EVENT_DATA_RSSI_HIGH
- *      - EVENT_DATA_SNR_HIGH
- *      - EVENT_LINK_QUALITY
- *      - EVENT_PRE_BEACON_LOST
- *      - EVENT_IBSS_COALESCED
- *      - EVENT_WEP_ICV_ERR
- *      - EVENT_BW_CHANGE
- *      - EVENT_HOSTWAKE_STAIE
-  *
- * For the following events, no action is taken -
- *      - EVENT_MIB_CHANGED
- *      - EVENT_INIT_DONE
- *      - EVENT_DUMMY_HOST_WAKEUP_SIGNAL
- *
- * Rest of the supported events requires driver handling -
- *      - EVENT_DEAUTHENTICATED
- *      - EVENT_DISASSOCIATED
- *      - EVENT_LINK_LOST
- *      - EVENT_PS_SLEEP
- *      - EVENT_PS_AWAKE
- *      - EVENT_DEEP_SLEEP_AWAKE
- *      - EVENT_HS_ACT_REQ
- *      - EVENT_ADHOC_BCN_LOST
- *      - EVENT_BG_SCAN_REPORT
- *      - EVENT_WMM_STATUS_CHANGE
- *      - EVENT_ADDBA
- *      - EVENT_DELBA
- *      - EVENT_BA_STREAM_TIEMOUT
- *      - EVENT_AMSDU_AGGR_CTRL
- */
-int mwifiex_process_sta_event(struct mwifiex_private *priv)
-{
-       struct mwifiex_adapter *adapter = priv->adapter;
-       int ret = 0;
-       u32 eventcause = adapter->event_cause;
-       u16 ctrl, reason_code;
-
-       switch (eventcause) {
-       case EVENT_DUMMY_HOST_WAKEUP_SIGNAL:
-               mwifiex_dbg(adapter, ERROR,
-                           "invalid EVENT: DUMMY_HOST_WAKEUP_SIGNAL, ignore it\n");
-               break;
-       case EVENT_LINK_SENSED:
-               mwifiex_dbg(adapter, EVENT, "event: LINK_SENSED\n");
-               if (!netif_carrier_ok(priv->netdev))
-                       netif_carrier_on(priv->netdev);
-               mwifiex_wake_up_net_dev_queue(priv->netdev, adapter);
-               break;
-
-       case EVENT_DEAUTHENTICATED:
-               mwifiex_dbg(adapter, EVENT, "event: Deauthenticated\n");
-               if (priv->wps.session_enable) {
-                       mwifiex_dbg(adapter, INFO,
-                                   "info: receive deauth event in wps session\n");
-                       break;
-               }
-               adapter->dbg.num_event_deauth++;
-               if (priv->media_connected) {
-                       reason_code =
-                               le16_to_cpu(*(__le16 *)adapter->event_body);
-                       mwifiex_reset_connect_state(priv, reason_code);
-               }
-               break;
-
-       case EVENT_DISASSOCIATED:
-               mwifiex_dbg(adapter, EVENT, "event: Disassociated\n");
-               if (priv->wps.session_enable) {
-                       mwifiex_dbg(adapter, INFO,
-                                   "info: receive disassoc event in wps session\n");
-                       break;
-               }
-               adapter->dbg.num_event_disassoc++;
-               if (priv->media_connected) {
-                       reason_code =
-                               le16_to_cpu(*(__le16 *)adapter->event_body);
-                       mwifiex_reset_connect_state(priv, reason_code);
-               }
-               break;
-
-       case EVENT_LINK_LOST:
-               mwifiex_dbg(adapter, EVENT, "event: Link lost\n");
-               adapter->dbg.num_event_link_lost++;
-               if (priv->media_connected) {
-                       reason_code =
-                               le16_to_cpu(*(__le16 *)adapter->event_body);
-                       mwifiex_reset_connect_state(priv, reason_code);
-               }
-               break;
-
-       case EVENT_PS_SLEEP:
-               mwifiex_dbg(adapter, EVENT, "info: EVENT: SLEEP\n");
-
-               adapter->ps_state = PS_STATE_PRE_SLEEP;
-
-               mwifiex_check_ps_cond(adapter);
-               break;
-
-       case EVENT_PS_AWAKE:
-               mwifiex_dbg(adapter, EVENT, "info: EVENT: AWAKE\n");
-               if (!adapter->pps_uapsd_mode && priv->port_open &&
-                   priv->media_connected && adapter->sleep_period.period) {
-                               adapter->pps_uapsd_mode = true;
-                               mwifiex_dbg(adapter, EVENT,
-                                           "event: PPS/UAPSD mode activated\n");
-               }
-               adapter->tx_lock_flag = false;
-               if (adapter->pps_uapsd_mode && adapter->gen_null_pkt) {
-                       if (mwifiex_check_last_packet_indication(priv)) {
-                               if (adapter->data_sent ||
-                                   (adapter->if_ops.is_port_ready &&
-                                    !adapter->if_ops.is_port_ready(priv))) {
-                                       adapter->ps_state = PS_STATE_AWAKE;
-                                       adapter->pm_wakeup_card_req = false;
-                                       adapter->pm_wakeup_fw_try = false;
-                                       del_timer(&adapter->wakeup_timer);
-                                       break;
-                               }
-                               if (!mwifiex_send_null_packet
-                                       (priv,
-                                        MWIFIEX_TxPD_POWER_MGMT_NULL_PACKET |
-                                        MWIFIEX_TxPD_POWER_MGMT_LAST_PACKET))
-                                               adapter->ps_state =
-                                                       PS_STATE_SLEEP;
-                                       return 0;
-                       }
-               }
-               adapter->ps_state = PS_STATE_AWAKE;
-               adapter->pm_wakeup_card_req = false;
-               adapter->pm_wakeup_fw_try = false;
-               del_timer(&adapter->wakeup_timer);
-
-               break;
-
-       case EVENT_DEEP_SLEEP_AWAKE:
-               adapter->if_ops.wakeup_complete(adapter);
-               mwifiex_dbg(adapter, EVENT, "event: DS_AWAKE\n");
-               if (adapter->is_deep_sleep)
-                       adapter->is_deep_sleep = false;
-               break;
-
-       case EVENT_HS_ACT_REQ:
-               mwifiex_dbg(adapter, EVENT, "event: HS_ACT_REQ\n");
-               ret = mwifiex_send_cmd(priv, HostCmd_CMD_802_11_HS_CFG_ENH,
-                                      0, 0, NULL, false);
-               break;
-
-       case EVENT_MIC_ERR_UNICAST:
-               mwifiex_dbg(adapter, EVENT, "event: UNICAST MIC ERROR\n");
-               cfg80211_michael_mic_failure(priv->netdev, priv->cfg_bssid,
-                                            NL80211_KEYTYPE_PAIRWISE,
-                                            -1, NULL, GFP_KERNEL);
-               break;
-
-       case EVENT_MIC_ERR_MULTICAST:
-               mwifiex_dbg(adapter, EVENT, "event: MULTICAST MIC ERROR\n");
-               cfg80211_michael_mic_failure(priv->netdev, priv->cfg_bssid,
-                                            NL80211_KEYTYPE_GROUP,
-                                            -1, NULL, GFP_KERNEL);
-               break;
-       case EVENT_MIB_CHANGED:
-       case EVENT_INIT_DONE:
-               break;
-
-       case EVENT_ADHOC_BCN_LOST:
-               mwifiex_dbg(adapter, EVENT, "event: ADHOC_BCN_LOST\n");
-               priv->adhoc_is_link_sensed = false;
-               mwifiex_clean_txrx(priv);
-               mwifiex_stop_net_dev_queue(priv->netdev, adapter);
-               if (netif_carrier_ok(priv->netdev))
-                       netif_carrier_off(priv->netdev);
-               break;
-
-       case EVENT_BG_SCAN_REPORT:
-               mwifiex_dbg(adapter, EVENT, "event: BGS_REPORT\n");
-               ret = mwifiex_send_cmd(priv, HostCmd_CMD_802_11_BG_SCAN_QUERY,
-                                      HostCmd_ACT_GEN_GET, 0, NULL, false);
-               break;
-
-       case EVENT_PORT_RELEASE:
-               mwifiex_dbg(adapter, EVENT, "event: PORT RELEASE\n");
-               priv->port_open = true;
-               break;
-
-       case EVENT_EXT_SCAN_REPORT:
-               mwifiex_dbg(adapter, EVENT, "event: EXT_SCAN Report\n");
-               if (adapter->ext_scan)
-                       ret = mwifiex_handle_event_ext_scan_report(priv,
-                                               adapter->event_skb->data);
-
-               break;
-
-       case EVENT_WMM_STATUS_CHANGE:
-               mwifiex_dbg(adapter, EVENT, "event: WMM status changed\n");
-               ret = mwifiex_send_cmd(priv, HostCmd_CMD_WMM_GET_STATUS,
-                                      0, 0, NULL, false);
-               break;
-
-       case EVENT_RSSI_LOW:
-               cfg80211_cqm_rssi_notify(priv->netdev,
-                                        NL80211_CQM_RSSI_THRESHOLD_EVENT_LOW,
-                                        GFP_KERNEL);
-               mwifiex_send_cmd(priv, HostCmd_CMD_RSSI_INFO,
-                                HostCmd_ACT_GEN_GET, 0, NULL, false);
-               priv->subsc_evt_rssi_state = RSSI_LOW_RECVD;
-               mwifiex_dbg(adapter, EVENT, "event: Beacon RSSI_LOW\n");
-               break;
-       case EVENT_SNR_LOW:
-               mwifiex_dbg(adapter, EVENT, "event: Beacon SNR_LOW\n");
-               break;
-       case EVENT_MAX_FAIL:
-               mwifiex_dbg(adapter, EVENT, "event: MAX_FAIL\n");
-               break;
-       case EVENT_RSSI_HIGH:
-               cfg80211_cqm_rssi_notify(priv->netdev,
-                                        NL80211_CQM_RSSI_THRESHOLD_EVENT_HIGH,
-                                        GFP_KERNEL);
-               mwifiex_send_cmd(priv, HostCmd_CMD_RSSI_INFO,
-                                HostCmd_ACT_GEN_GET, 0, NULL, false);
-               priv->subsc_evt_rssi_state = RSSI_HIGH_RECVD;
-               mwifiex_dbg(adapter, EVENT, "event: Beacon RSSI_HIGH\n");
-               break;
-       case EVENT_SNR_HIGH:
-               mwifiex_dbg(adapter, EVENT, "event: Beacon SNR_HIGH\n");
-               break;
-       case EVENT_DATA_RSSI_LOW:
-               mwifiex_dbg(adapter, EVENT, "event: Data RSSI_LOW\n");
-               break;
-       case EVENT_DATA_SNR_LOW:
-               mwifiex_dbg(adapter, EVENT, "event: Data SNR_LOW\n");
-               break;
-       case EVENT_DATA_RSSI_HIGH:
-               mwifiex_dbg(adapter, EVENT, "event: Data RSSI_HIGH\n");
-               break;
-       case EVENT_DATA_SNR_HIGH:
-               mwifiex_dbg(adapter, EVENT, "event: Data SNR_HIGH\n");
-               break;
-       case EVENT_LINK_QUALITY:
-               mwifiex_dbg(adapter, EVENT, "event: Link Quality\n");
-               break;
-       case EVENT_PRE_BEACON_LOST:
-               mwifiex_dbg(adapter, EVENT, "event: Pre-Beacon Lost\n");
-               break;
-       case EVENT_IBSS_COALESCED:
-               mwifiex_dbg(adapter, EVENT, "event: IBSS_COALESCED\n");
-               ret = mwifiex_send_cmd(priv,
-                               HostCmd_CMD_802_11_IBSS_COALESCING_STATUS,
-                               HostCmd_ACT_GEN_GET, 0, NULL, false);
-               break;
-       case EVENT_ADDBA:
-               mwifiex_dbg(adapter, EVENT, "event: ADDBA Request\n");
-               mwifiex_send_cmd(priv, HostCmd_CMD_11N_ADDBA_RSP,
-                                HostCmd_ACT_GEN_SET, 0,
-                                adapter->event_body, false);
-               break;
-       case EVENT_DELBA:
-               mwifiex_dbg(adapter, EVENT, "event: DELBA Request\n");
-               mwifiex_11n_delete_ba_stream(priv, adapter->event_body);
-               break;
-       case EVENT_BA_STREAM_TIEMOUT:
-               mwifiex_dbg(adapter, EVENT, "event:  BA Stream timeout\n");
-               mwifiex_11n_ba_stream_timeout(priv,
-                                             (struct host_cmd_ds_11n_batimeout
-                                              *)
-                                             adapter->event_body);
-               break;
-       case EVENT_AMSDU_AGGR_CTRL:
-               ctrl = le16_to_cpu(*(__le16 *)adapter->event_body);
-               mwifiex_dbg(adapter, EVENT,
-                           "event: AMSDU_AGGR_CTRL %d\n", ctrl);
-
-               adapter->tx_buf_size =
-                               min_t(u16, adapter->curr_tx_buf_size, ctrl);
-               mwifiex_dbg(adapter, EVENT, "event: tx_buf_size %d\n",
-                           adapter->tx_buf_size);
-               break;
-
-       case EVENT_WEP_ICV_ERR:
-               mwifiex_dbg(adapter, EVENT, "event: WEP ICV error\n");
-               break;
-
-       case EVENT_BW_CHANGE:
-               mwifiex_dbg(adapter, EVENT, "event: BW Change\n");
-               break;
-
-       case EVENT_HOSTWAKE_STAIE:
-               mwifiex_dbg(adapter, EVENT,
-                           "event: HOSTWAKE_STAIE %d\n", eventcause);
-               break;
-
-       case EVENT_REMAIN_ON_CHAN_EXPIRED:
-               mwifiex_dbg(adapter, EVENT,
-                           "event: Remain on channel expired\n");
-               cfg80211_remain_on_channel_expired(&priv->wdev,
-                                                  priv->roc_cfg.cookie,
-                                                  &priv->roc_cfg.chan,
-                                                  GFP_ATOMIC);
-
-               memset(&priv->roc_cfg, 0x00, sizeof(struct mwifiex_roc_cfg));
-
-               break;
-
-       case EVENT_CHANNEL_SWITCH_ANN:
-               mwifiex_dbg(adapter, EVENT, "event: Channel Switch Announcement\n");
-               priv->csa_expire_time =
-                               jiffies + msecs_to_jiffies(DFS_CHAN_MOVE_TIME);
-               priv->csa_chan = priv->curr_bss_params.bss_descriptor.channel;
-               ret = mwifiex_send_cmd(priv, HostCmd_CMD_802_11_DEAUTHENTICATE,
-                       HostCmd_ACT_GEN_SET, 0,
-                       priv->curr_bss_params.bss_descriptor.mac_address,
-                       false);
-               break;
-
-       case EVENT_TDLS_GENERIC_EVENT:
-               ret = mwifiex_parse_tdls_event(priv, adapter->event_skb);
-               break;
-
-       case EVENT_TX_DATA_PAUSE:
-               mwifiex_dbg(adapter, EVENT, "event: TX DATA PAUSE\n");
-               mwifiex_process_tx_pause_event(priv, adapter->event_skb);
-               break;
-
-       case EVENT_MULTI_CHAN_INFO:
-               mwifiex_dbg(adapter, EVENT, "event: multi-chan info\n");
-               mwifiex_process_multi_chan_event(priv, adapter->event_skb);
-               break;
-
-       case EVENT_TX_STATUS_REPORT:
-               mwifiex_dbg(adapter, EVENT, "event: TX_STATUS Report\n");
-               mwifiex_parse_tx_status_event(priv, adapter->event_body);
-               break;
-
-       case EVENT_CHANNEL_REPORT_RDY:
-               mwifiex_dbg(adapter, EVENT, "event: Channel Report\n");
-               ret = mwifiex_11h_handle_chanrpt_ready(priv,
-                                                      adapter->event_skb);
-               break;
-       case EVENT_RADAR_DETECTED:
-               mwifiex_dbg(adapter, EVENT, "event: Radar detected\n");
-               ret = mwifiex_11h_handle_radar_detected(priv,
-                                                       adapter->event_skb);
-               break;
-       case EVENT_BT_COEX_WLAN_PARA_CHANGE:
-               dev_dbg(adapter->dev, "EVENT: BT coex wlan param update\n");
-               mwifiex_bt_coex_wlan_param_update_event(priv,
-                                                       adapter->event_skb);
-               break;
-       default:
-               mwifiex_dbg(adapter, ERROR, "event: unknown event id: %#x\n",
-                           eventcause);
-               break;
-       }
-
-       return ret;
-}
diff --git a/drivers/net/wireless/mwifiex/sta_ioctl.c b/drivers/net/wireless/mwifiex/sta_ioctl.c
deleted file mode 100644 (file)
index a6c8a4f..0000000
+++ /dev/null
@@ -1,1421 +0,0 @@
-/*
- * Marvell Wireless LAN device driver: functions for station ioctl
- *
- * Copyright (C) 2011-2014, Marvell International Ltd.
- *
- * This software file (the "File") is distributed by Marvell International
- * Ltd. under the terms of the GNU General Public License Version 2, June 1991
- * (the "License").  You may use, redistribute and/or modify this File in
- * accordance with the terms and conditions of the License, a copy of which
- * is available by writing to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the
- * worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
- *
- * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
- * ARE EXPRESSLY DISCLAIMED.  The License provides additional details about
- * this warranty disclaimer.
- */
-
-#include "decl.h"
-#include "ioctl.h"
-#include "util.h"
-#include "fw.h"
-#include "main.h"
-#include "wmm.h"
-#include "11n.h"
-#include "cfg80211.h"
-
-static int disconnect_on_suspend;
-module_param(disconnect_on_suspend, int, 0644);
-
-/*
- * Copies the multicast address list from device to driver.
- *
- * This function does not validate the destination memory for
- * size, and the calling function must ensure enough memory is
- * available.
- */
-int mwifiex_copy_mcast_addr(struct mwifiex_multicast_list *mlist,
-                           struct net_device *dev)
-{
-       int i = 0;
-       struct netdev_hw_addr *ha;
-
-       netdev_for_each_mc_addr(ha, dev)
-               memcpy(&mlist->mac_list[i++], ha->addr, ETH_ALEN);
-
-       return i;
-}
-
-/*
- * Wait queue completion handler.
- *
- * This function waits on a cmd wait queue. It also cancels the pending
- * request after waking up, in case of errors.
- */
-int mwifiex_wait_queue_complete(struct mwifiex_adapter *adapter,
-                               struct cmd_ctrl_node *cmd_queued)
-{
-       int status;
-
-       /* Wait for completion */
-       status = wait_event_interruptible_timeout(adapter->cmd_wait_q.wait,
-                                                 *(cmd_queued->condition),
-                                                 (12 * HZ));
-       if (status <= 0) {
-               if (status == 0)
-                       status = -ETIMEDOUT;
-               mwifiex_dbg(adapter, ERROR, "cmd_wait_q terminated: %d\n",
-                           status);
-               mwifiex_cancel_all_pending_cmd(adapter);
-               return status;
-       }
-
-       status = adapter->cmd_wait_q.status;
-       adapter->cmd_wait_q.status = 0;
-
-       return status;
-}
-
-/*
- * This function prepares the correct firmware command and
- * issues it to set the multicast list.
- *
- * This function can be used to enable promiscuous mode, or enable all
- * multicast packets, or to enable selective multicast.
- */
-int mwifiex_request_set_multicast_list(struct mwifiex_private *priv,
-                               struct mwifiex_multicast_list *mcast_list)
-{
-       int ret = 0;
-       u16 old_pkt_filter;
-
-       old_pkt_filter = priv->curr_pkt_filter;
-
-       if (mcast_list->mode == MWIFIEX_PROMISC_MODE) {
-               mwifiex_dbg(priv->adapter, INFO,
-                           "info: Enable Promiscuous mode\n");
-               priv->curr_pkt_filter |= HostCmd_ACT_MAC_PROMISCUOUS_ENABLE;
-               priv->curr_pkt_filter &=
-                       ~HostCmd_ACT_MAC_ALL_MULTICAST_ENABLE;
-       } else {
-               /* Multicast */
-               priv->curr_pkt_filter &= ~HostCmd_ACT_MAC_PROMISCUOUS_ENABLE;
-               if (mcast_list->mode == MWIFIEX_ALL_MULTI_MODE) {
-                       mwifiex_dbg(priv->adapter, INFO,
-                                   "info: Enabling All Multicast!\n");
-                       priv->curr_pkt_filter |=
-                               HostCmd_ACT_MAC_ALL_MULTICAST_ENABLE;
-               } else {
-                       priv->curr_pkt_filter &=
-                               ~HostCmd_ACT_MAC_ALL_MULTICAST_ENABLE;
-                       mwifiex_dbg(priv->adapter, INFO,
-                                   "info: Set multicast list=%d\n",
-                                   mcast_list->num_multicast_addr);
-                       /* Send multicast addresses to firmware */
-                       ret = mwifiex_send_cmd(priv,
-                                              HostCmd_CMD_MAC_MULTICAST_ADR,
-                                              HostCmd_ACT_GEN_SET, 0,
-                                              mcast_list, false);
-               }
-       }
-       mwifiex_dbg(priv->adapter, INFO,
-                   "info: old_pkt_filter=%#x, curr_pkt_filter=%#x\n",
-                   old_pkt_filter, priv->curr_pkt_filter);
-       if (old_pkt_filter != priv->curr_pkt_filter) {
-               ret = mwifiex_send_cmd(priv, HostCmd_CMD_MAC_CONTROL,
-                                      HostCmd_ACT_GEN_SET,
-                                      0, &priv->curr_pkt_filter, false);
-       }
-
-       return ret;
-}
-
-/*
- * This function fills bss descriptor structure using provided
- * information.
- * beacon_ie buffer is allocated in this function. It is caller's
- * responsibility to free the memory.
- */
-int mwifiex_fill_new_bss_desc(struct mwifiex_private *priv,
-                             struct cfg80211_bss *bss,
-                             struct mwifiex_bssdescriptor *bss_desc)
-{
-       u8 *beacon_ie;
-       size_t beacon_ie_len;
-       struct mwifiex_bss_priv *bss_priv = (void *)bss->priv;
-       const struct cfg80211_bss_ies *ies;
-
-       rcu_read_lock();
-       ies = rcu_dereference(bss->ies);
-       beacon_ie = kmemdup(ies->data, ies->len, GFP_ATOMIC);
-       beacon_ie_len = ies->len;
-       bss_desc->timestamp = ies->tsf;
-       rcu_read_unlock();
-
-       if (!beacon_ie) {
-               mwifiex_dbg(priv->adapter, ERROR,
-                           " failed to alloc beacon_ie\n");
-               return -ENOMEM;
-       }
-
-       memcpy(bss_desc->mac_address, bss->bssid, ETH_ALEN);
-       bss_desc->rssi = bss->signal;
-       /* The caller of this function will free beacon_ie */
-       bss_desc->beacon_buf = beacon_ie;
-       bss_desc->beacon_buf_size = beacon_ie_len;
-       bss_desc->beacon_period = bss->beacon_interval;
-       bss_desc->cap_info_bitmap = bss->capability;
-       bss_desc->bss_band = bss_priv->band;
-       bss_desc->fw_tsf = bss_priv->fw_tsf;
-       if (bss_desc->cap_info_bitmap & WLAN_CAPABILITY_PRIVACY) {
-               mwifiex_dbg(priv->adapter, INFO,
-                           "info: InterpretIE: AP WEP enabled\n");
-               bss_desc->privacy = MWIFIEX_802_11_PRIV_FILTER_8021X_WEP;
-       } else {
-               bss_desc->privacy = MWIFIEX_802_11_PRIV_FILTER_ACCEPT_ALL;
-       }
-       if (bss_desc->cap_info_bitmap & WLAN_CAPABILITY_IBSS)
-               bss_desc->bss_mode = NL80211_IFTYPE_ADHOC;
-       else
-               bss_desc->bss_mode = NL80211_IFTYPE_STATION;
-
-       /* Disable 11ac by default. Enable it only where there
-        * exist VHT_CAP IE in AP beacon
-        */
-       bss_desc->disable_11ac = true;
-
-       if (bss_desc->cap_info_bitmap & WLAN_CAPABILITY_SPECTRUM_MGMT)
-               bss_desc->sensed_11h = true;
-
-       return mwifiex_update_bss_desc_with_ie(priv->adapter, bss_desc);
-}
-
-void mwifiex_dnld_txpwr_table(struct mwifiex_private *priv)
-{
-       if (priv->adapter->dt_node) {
-               char txpwr[] = {"marvell,00_txpwrlimit"};
-
-               memcpy(&txpwr[8], priv->adapter->country_code, 2);
-               mwifiex_dnld_dt_cfgdata(priv, priv->adapter->dt_node, txpwr);
-       }
-}
-
-static int mwifiex_process_country_ie(struct mwifiex_private *priv,
-                                     struct cfg80211_bss *bss)
-{
-       const u8 *country_ie;
-       u8 country_ie_len;
-       struct mwifiex_802_11d_domain_reg *domain_info =
-                                       &priv->adapter->domain_reg;
-
-       rcu_read_lock();
-       country_ie = ieee80211_bss_get_ie(bss, WLAN_EID_COUNTRY);
-       if (!country_ie) {
-               rcu_read_unlock();
-               return 0;
-       }
-
-       country_ie_len = country_ie[1];
-       if (country_ie_len < IEEE80211_COUNTRY_IE_MIN_LEN) {
-               rcu_read_unlock();
-               return 0;
-       }
-
-       if (!strncmp(priv->adapter->country_code, &country_ie[2], 2)) {
-               rcu_read_unlock();
-               mwifiex_dbg(priv->adapter, INFO,
-                           "11D: skip setting domain info in FW\n");
-               return 0;
-       }
-       memcpy(priv->adapter->country_code, &country_ie[2], 2);
-
-       domain_info->country_code[0] = country_ie[2];
-       domain_info->country_code[1] = country_ie[3];
-       domain_info->country_code[2] = ' ';
-
-       country_ie_len -= IEEE80211_COUNTRY_STRING_LEN;
-
-       domain_info->no_of_triplet =
-               country_ie_len / sizeof(struct ieee80211_country_ie_triplet);
-
-       memcpy((u8 *)domain_info->triplet,
-              &country_ie[2] + IEEE80211_COUNTRY_STRING_LEN, country_ie_len);
-
-       rcu_read_unlock();
-
-       if (mwifiex_send_cmd(priv, HostCmd_CMD_802_11D_DOMAIN_INFO,
-                            HostCmd_ACT_GEN_SET, 0, NULL, false)) {
-               mwifiex_dbg(priv->adapter, ERROR,
-                           "11D: setting domain info in FW fail\n");
-               return -1;
-       }
-
-       mwifiex_dnld_txpwr_table(priv);
-
-       return 0;
-}
-
-/*
- * In Ad-Hoc mode, the IBSS is created if not found in scan list.
- * In both Ad-Hoc and infra mode, an deauthentication is performed
- * first.
- */
-int mwifiex_bss_start(struct mwifiex_private *priv, struct cfg80211_bss *bss,
-                     struct cfg80211_ssid *req_ssid)
-{
-       int ret;
-       struct mwifiex_adapter *adapter = priv->adapter;
-       struct mwifiex_bssdescriptor *bss_desc = NULL;
-
-       priv->scan_block = false;
-
-       if (bss) {
-               mwifiex_process_country_ie(priv, bss);
-
-               /* Allocate and fill new bss descriptor */
-               bss_desc = kzalloc(sizeof(struct mwifiex_bssdescriptor),
-                                  GFP_KERNEL);
-               if (!bss_desc)
-                       return -ENOMEM;
-
-               ret = mwifiex_fill_new_bss_desc(priv, bss, bss_desc);
-               if (ret)
-                       goto done;
-       }
-
-       if (priv->bss_mode == NL80211_IFTYPE_STATION ||
-           priv->bss_mode == NL80211_IFTYPE_P2P_CLIENT) {
-               u8 config_bands;
-
-               if (!bss_desc)
-                       return -1;
-
-               if (mwifiex_band_to_radio_type(bss_desc->bss_band) ==
-                                               HostCmd_SCAN_RADIO_TYPE_BG) {
-                       config_bands = BAND_B | BAND_G | BAND_GN;
-               } else {
-                       config_bands = BAND_A | BAND_AN;
-                       if (adapter->fw_bands & BAND_AAC)
-                               config_bands |= BAND_AAC;
-               }
-
-               if (!((config_bands | adapter->fw_bands) & ~adapter->fw_bands))
-                       adapter->config_bands = config_bands;
-
-               ret = mwifiex_check_network_compatibility(priv, bss_desc);
-               if (ret)
-                       goto done;
-
-               if (mwifiex_11h_get_csa_closed_channel(priv) ==
-                                                       (u8)bss_desc->channel) {
-                       mwifiex_dbg(adapter, ERROR,
-                                   "Attempt to reconnect on csa closed chan(%d)\n",
-                                   bss_desc->channel);
-                       goto done;
-               }
-
-               mwifiex_dbg(adapter, INFO,
-                           "info: SSID found in scan list ...\t"
-                           "associating...\n");
-
-               mwifiex_stop_net_dev_queue(priv->netdev, adapter);
-               if (netif_carrier_ok(priv->netdev))
-                       netif_carrier_off(priv->netdev);
-
-               /* Clear any past association response stored for
-                * application retrieval */
-               priv->assoc_rsp_size = 0;
-               ret = mwifiex_associate(priv, bss_desc);
-
-               /* If auth type is auto and association fails using open mode,
-                * try to connect using shared mode */
-               if (ret == WLAN_STATUS_NOT_SUPPORTED_AUTH_ALG &&
-                   priv->sec_info.is_authtype_auto &&
-                   priv->sec_info.wep_enabled) {
-                       priv->sec_info.authentication_mode =
-                                               NL80211_AUTHTYPE_SHARED_KEY;
-                       ret = mwifiex_associate(priv, bss_desc);
-               }
-
-               if (bss)
-                       cfg80211_put_bss(priv->adapter->wiphy, bss);
-       } else {
-               /* Adhoc mode */
-               /* If the requested SSID matches current SSID, return */
-               if (bss_desc && bss_desc->ssid.ssid_len &&
-                   (!mwifiex_ssid_cmp(&priv->curr_bss_params.bss_descriptor.
-                                      ssid, &bss_desc->ssid))) {
-                       ret = 0;
-                       goto done;
-               }
-
-               priv->adhoc_is_link_sensed = false;
-
-               ret = mwifiex_check_network_compatibility(priv, bss_desc);
-
-               mwifiex_stop_net_dev_queue(priv->netdev, adapter);
-               if (netif_carrier_ok(priv->netdev))
-                       netif_carrier_off(priv->netdev);
-
-               if (!ret) {
-                       mwifiex_dbg(adapter, INFO,
-                                   "info: network found in scan\t"
-                                   " list. Joining...\n");
-                       ret = mwifiex_adhoc_join(priv, bss_desc);
-                       if (bss)
-                               cfg80211_put_bss(priv->adapter->wiphy, bss);
-               } else {
-                       mwifiex_dbg(adapter, INFO,
-                                   "info: Network not found in\t"
-                                   "the list, creating adhoc with ssid = %s\n",
-                                   req_ssid->ssid);
-                       ret = mwifiex_adhoc_start(priv, req_ssid);
-               }
-       }
-
-done:
-       /* beacon_ie buffer was allocated in function
-        * mwifiex_fill_new_bss_desc(). Free it now.
-        */
-       if (bss_desc)
-               kfree(bss_desc->beacon_buf);
-       kfree(bss_desc);
-       return ret;
-}
-
-/*
- * IOCTL request handler to set host sleep configuration.
- *
- * This function prepares the correct firmware command and
- * issues it.
- */
-int mwifiex_set_hs_params(struct mwifiex_private *priv, u16 action,
-                         int cmd_type, struct mwifiex_ds_hs_cfg *hs_cfg)
-
-{
-       struct mwifiex_adapter *adapter = priv->adapter;
-       int status = 0;
-       u32 prev_cond = 0;
-
-       if (!hs_cfg)
-               return -ENOMEM;
-
-       switch (action) {
-       case HostCmd_ACT_GEN_SET:
-               if (adapter->pps_uapsd_mode) {
-                       mwifiex_dbg(adapter, INFO,
-                                   "info: Host Sleep IOCTL\t"
-                                   "is blocked in UAPSD/PPS mode\n");
-                       status = -1;
-                       break;
-               }
-               if (hs_cfg->is_invoke_hostcmd) {
-                       if (hs_cfg->conditions == HS_CFG_CANCEL) {
-                               if (!adapter->is_hs_configured)
-                                       /* Already cancelled */
-                                       break;
-                               /* Save previous condition */
-                               prev_cond = le32_to_cpu(adapter->hs_cfg
-                                                       .conditions);
-                               adapter->hs_cfg.conditions =
-                                               cpu_to_le32(hs_cfg->conditions);
-                       } else if (hs_cfg->conditions) {
-                               adapter->hs_cfg.conditions =
-                                               cpu_to_le32(hs_cfg->conditions);
-                               adapter->hs_cfg.gpio = (u8)hs_cfg->gpio;
-                               if (hs_cfg->gap)
-                                       adapter->hs_cfg.gap = (u8)hs_cfg->gap;
-                       } else if (adapter->hs_cfg.conditions ==
-                                  cpu_to_le32(HS_CFG_CANCEL)) {
-                               /* Return failure if no parameters for HS
-                                  enable */
-                               status = -1;
-                               break;
-                       }
-
-                       status = mwifiex_send_cmd(priv,
-                                                 HostCmd_CMD_802_11_HS_CFG_ENH,
-                                                 HostCmd_ACT_GEN_SET, 0,
-                                                 &adapter->hs_cfg,
-                                                 cmd_type == MWIFIEX_SYNC_CMD);
-
-                       if (hs_cfg->conditions == HS_CFG_CANCEL)
-                               /* Restore previous condition */
-                               adapter->hs_cfg.conditions =
-                                               cpu_to_le32(prev_cond);
-               } else {
-                       adapter->hs_cfg.conditions =
-                                               cpu_to_le32(hs_cfg->conditions);
-                       adapter->hs_cfg.gpio = (u8)hs_cfg->gpio;
-                       adapter->hs_cfg.gap = (u8)hs_cfg->gap;
-               }
-               break;
-       case HostCmd_ACT_GEN_GET:
-               hs_cfg->conditions = le32_to_cpu(adapter->hs_cfg.conditions);
-               hs_cfg->gpio = adapter->hs_cfg.gpio;
-               hs_cfg->gap = adapter->hs_cfg.gap;
-               break;
-       default:
-               status = -1;
-               break;
-       }
-
-       return status;
-}
-
-/*
- * Sends IOCTL request to cancel the existing Host Sleep configuration.
- *
- * This function allocates the IOCTL request buffer, fills it
- * with requisite parameters and calls the IOCTL handler.
- */
-int mwifiex_cancel_hs(struct mwifiex_private *priv, int cmd_type)
-{
-       struct mwifiex_ds_hs_cfg hscfg;
-
-       hscfg.conditions = HS_CFG_CANCEL;
-       hscfg.is_invoke_hostcmd = true;
-
-       return mwifiex_set_hs_params(priv, HostCmd_ACT_GEN_SET,
-                                   cmd_type, &hscfg);
-}
-EXPORT_SYMBOL_GPL(mwifiex_cancel_hs);
-
-/*
- * Sends IOCTL request to cancel the existing Host Sleep configuration.
- *
- * This function allocates the IOCTL request buffer, fills it
- * with requisite parameters and calls the IOCTL handler.
- */
-int mwifiex_enable_hs(struct mwifiex_adapter *adapter)
-{
-       struct mwifiex_ds_hs_cfg hscfg;
-       struct mwifiex_private *priv;
-       int i;
-
-       if (disconnect_on_suspend) {
-               for (i = 0; i < adapter->priv_num; i++) {
-                       priv = adapter->priv[i];
-                       if (priv)
-                               mwifiex_deauthenticate(priv, NULL);
-               }
-       }
-
-       if (adapter->hs_activated) {
-               mwifiex_dbg(adapter, CMD,
-                           "cmd: HS Already activated\n");
-               return true;
-       }
-
-       adapter->hs_activate_wait_q_woken = false;
-
-       memset(&hscfg, 0, sizeof(struct mwifiex_ds_hs_cfg));
-       hscfg.is_invoke_hostcmd = true;
-
-       adapter->hs_enabling = true;
-       mwifiex_cancel_all_pending_cmd(adapter);
-
-       if (mwifiex_set_hs_params(mwifiex_get_priv(adapter,
-                                                  MWIFIEX_BSS_ROLE_STA),
-                                 HostCmd_ACT_GEN_SET, MWIFIEX_SYNC_CMD,
-                                 &hscfg)) {
-               mwifiex_dbg(adapter, ERROR,
-                           "IOCTL request HS enable failed\n");
-               return false;
-       }
-
-       if (wait_event_interruptible_timeout(adapter->hs_activate_wait_q,
-                                            adapter->hs_activate_wait_q_woken,
-                                            (10 * HZ)) <= 0) {
-               mwifiex_dbg(adapter, ERROR,
-                           "hs_activate_wait_q terminated\n");
-               return false;
-       }
-
-       return true;
-}
-EXPORT_SYMBOL_GPL(mwifiex_enable_hs);
-
-/*
- * IOCTL request handler to get BSS information.
- *
- * This function collates the information from different driver structures
- * to send to the user.
- */
-int mwifiex_get_bss_info(struct mwifiex_private *priv,
-                        struct mwifiex_bss_info *info)
-{
-       struct mwifiex_adapter *adapter = priv->adapter;
-       struct mwifiex_bssdescriptor *bss_desc;
-
-       if (!info)
-               return -1;
-
-       bss_desc = &priv->curr_bss_params.bss_descriptor;
-
-       info->bss_mode = priv->bss_mode;
-
-       memcpy(&info->ssid, &bss_desc->ssid, sizeof(struct cfg80211_ssid));
-
-       memcpy(&info->bssid, &bss_desc->mac_address, ETH_ALEN);
-
-       info->bss_chan = bss_desc->channel;
-
-       memcpy(info->country_code, adapter->country_code,
-              IEEE80211_COUNTRY_STRING_LEN);
-
-       info->media_connected = priv->media_connected;
-
-       info->max_power_level = priv->max_tx_power_level;
-       info->min_power_level = priv->min_tx_power_level;
-
-       info->adhoc_state = priv->adhoc_state;
-
-       info->bcn_nf_last = priv->bcn_nf_last;
-
-       if (priv->sec_info.wep_enabled)
-               info->wep_status = true;
-       else
-               info->wep_status = false;
-
-       info->is_hs_configured = adapter->is_hs_configured;
-       info->is_deep_sleep = adapter->is_deep_sleep;
-
-       return 0;
-}
-
-/*
- * The function disables auto deep sleep mode.
- */
-int mwifiex_disable_auto_ds(struct mwifiex_private *priv)
-{
-       struct mwifiex_ds_auto_ds auto_ds;
-
-       auto_ds.auto_ds = DEEP_SLEEP_OFF;
-
-       return mwifiex_send_cmd(priv, HostCmd_CMD_802_11_PS_MODE_ENH,
-                               DIS_AUTO_PS, BITMAP_AUTO_DS, &auto_ds, true);
-}
-EXPORT_SYMBOL_GPL(mwifiex_disable_auto_ds);
-
-/*
- * Sends IOCTL request to get the data rate.
- *
- * This function allocates the IOCTL request buffer, fills it
- * with requisite parameters and calls the IOCTL handler.
- */
-int mwifiex_drv_get_data_rate(struct mwifiex_private *priv, u32 *rate)
-{
-       int ret;
-
-       ret = mwifiex_send_cmd(priv, HostCmd_CMD_802_11_TX_RATE_QUERY,
-                              HostCmd_ACT_GEN_GET, 0, NULL, true);
-
-       if (!ret) {
-               if (priv->is_data_rate_auto)
-                       *rate = mwifiex_index_to_data_rate(priv, priv->tx_rate,
-                                                          priv->tx_htinfo);
-               else
-                       *rate = priv->data_rate;
-       }
-
-       return ret;
-}
-
-/*
- * IOCTL request handler to set tx power configuration.
- *
- * This function prepares the correct firmware command and
- * issues it.
- *
- * For non-auto power mode, all the following power groups are set -
- *      - Modulation class HR/DSSS
- *      - Modulation class OFDM
- *      - Modulation class HTBW20
- *      - Modulation class HTBW40
- */
-int mwifiex_set_tx_power(struct mwifiex_private *priv,
-                        struct mwifiex_power_cfg *power_cfg)
-{
-       int ret;
-       struct host_cmd_ds_txpwr_cfg *txp_cfg;
-       struct mwifiex_types_power_group *pg_tlv;
-       struct mwifiex_power_group *pg;
-       u8 *buf;
-       u16 dbm = 0;
-
-       if (!power_cfg->is_power_auto) {
-               dbm = (u16) power_cfg->power_level;
-               if ((dbm < priv->min_tx_power_level) ||
-                   (dbm > priv->max_tx_power_level)) {
-                       mwifiex_dbg(priv->adapter, ERROR,
-                                   "txpower value %d dBm\t"
-                                   "is out of range (%d dBm-%d dBm)\n",
-                                   dbm, priv->min_tx_power_level,
-                                   priv->max_tx_power_level);
-                       return -1;
-               }
-       }
-       buf = kzalloc(MWIFIEX_SIZE_OF_CMD_BUFFER, GFP_KERNEL);
-       if (!buf)
-               return -ENOMEM;
-
-       txp_cfg = (struct host_cmd_ds_txpwr_cfg *) buf;
-       txp_cfg->action = cpu_to_le16(HostCmd_ACT_GEN_SET);
-       if (!power_cfg->is_power_auto) {
-               txp_cfg->mode = cpu_to_le32(1);
-               pg_tlv = (struct mwifiex_types_power_group *)
-                        (buf + sizeof(struct host_cmd_ds_txpwr_cfg));
-               pg_tlv->type = cpu_to_le16(TLV_TYPE_POWER_GROUP);
-               pg_tlv->length =
-                       cpu_to_le16(4 * sizeof(struct mwifiex_power_group));
-               pg = (struct mwifiex_power_group *)
-                    (buf + sizeof(struct host_cmd_ds_txpwr_cfg)
-                     + sizeof(struct mwifiex_types_power_group));
-               /* Power group for modulation class HR/DSSS */
-               pg->first_rate_code = 0x00;
-               pg->last_rate_code = 0x03;
-               pg->modulation_class = MOD_CLASS_HR_DSSS;
-               pg->power_step = 0;
-               pg->power_min = (s8) dbm;
-               pg->power_max = (s8) dbm;
-               pg++;
-               /* Power group for modulation class OFDM */
-               pg->first_rate_code = 0x00;
-               pg->last_rate_code = 0x07;
-               pg->modulation_class = MOD_CLASS_OFDM;
-               pg->power_step = 0;
-               pg->power_min = (s8) dbm;
-               pg->power_max = (s8) dbm;
-               pg++;
-               /* Power group for modulation class HTBW20 */
-               pg->first_rate_code = 0x00;
-               pg->last_rate_code = 0x20;
-               pg->modulation_class = MOD_CLASS_HT;
-               pg->power_step = 0;
-               pg->power_min = (s8) dbm;
-               pg->power_max = (s8) dbm;
-               pg->ht_bandwidth = HT_BW_20;
-               pg++;
-               /* Power group for modulation class HTBW40 */
-               pg->first_rate_code = 0x00;
-               pg->last_rate_code = 0x20;
-               pg->modulation_class = MOD_CLASS_HT;
-               pg->power_step = 0;
-               pg->power_min = (s8) dbm;
-               pg->power_max = (s8) dbm;
-               pg->ht_bandwidth = HT_BW_40;
-       }
-       ret = mwifiex_send_cmd(priv, HostCmd_CMD_TXPWR_CFG,
-                              HostCmd_ACT_GEN_SET, 0, buf, true);
-
-       kfree(buf);
-       return ret;
-}
-
-/*
- * IOCTL request handler to get power save mode.
- *
- * This function prepares the correct firmware command and
- * issues it.
- */
-int mwifiex_drv_set_power(struct mwifiex_private *priv, u32 *ps_mode)
-{
-       int ret;
-       struct mwifiex_adapter *adapter = priv->adapter;
-       u16 sub_cmd;
-
-       if (*ps_mode)
-               adapter->ps_mode = MWIFIEX_802_11_POWER_MODE_PSP;
-       else
-               adapter->ps_mode = MWIFIEX_802_11_POWER_MODE_CAM;
-       sub_cmd = (*ps_mode) ? EN_AUTO_PS : DIS_AUTO_PS;
-       ret = mwifiex_send_cmd(priv, HostCmd_CMD_802_11_PS_MODE_ENH,
-                              sub_cmd, BITMAP_STA_PS, NULL, true);
-       if ((!ret) && (sub_cmd == DIS_AUTO_PS))
-               ret = mwifiex_send_cmd(priv, HostCmd_CMD_802_11_PS_MODE_ENH,
-                                      GET_PS, 0, NULL, false);
-
-       return ret;
-}
-
-/*
- * IOCTL request handler to set/reset WPA IE.
- *
- * The supplied WPA IE is treated as a opaque buffer. Only the first field
- * is checked to determine WPA version. If buffer length is zero, the existing
- * WPA IE is reset.
- */
-static int mwifiex_set_wpa_ie_helper(struct mwifiex_private *priv,
-                                    u8 *ie_data_ptr, u16 ie_len)
-{
-       if (ie_len) {
-               if (ie_len > sizeof(priv->wpa_ie)) {
-                       mwifiex_dbg(priv->adapter, ERROR,
-                                   "failed to copy WPA IE, too big\n");
-                       return -1;
-               }
-               memcpy(priv->wpa_ie, ie_data_ptr, ie_len);
-               priv->wpa_ie_len = (u8) ie_len;
-               mwifiex_dbg(priv->adapter, CMD,
-                           "cmd: Set Wpa_ie_len=%d IE=%#x\n",
-                           priv->wpa_ie_len, priv->wpa_ie[0]);
-
-               if (priv->wpa_ie[0] == WLAN_EID_VENDOR_SPECIFIC) {
-                       priv->sec_info.wpa_enabled = true;
-               } else if (priv->wpa_ie[0] == WLAN_EID_RSN) {
-                       priv->sec_info.wpa2_enabled = true;
-               } else {
-                       priv->sec_info.wpa_enabled = false;
-                       priv->sec_info.wpa2_enabled = false;
-               }
-       } else {
-               memset(priv->wpa_ie, 0, sizeof(priv->wpa_ie));
-               priv->wpa_ie_len = 0;
-               mwifiex_dbg(priv->adapter, INFO,
-                           "info: reset wpa_ie_len=%d IE=%#x\n",
-                           priv->wpa_ie_len, priv->wpa_ie[0]);
-               priv->sec_info.wpa_enabled = false;
-               priv->sec_info.wpa2_enabled = false;
-       }
-
-       return 0;
-}
-
-/*
- * IOCTL request handler to set/reset WAPI IE.
- *
- * The supplied WAPI IE is treated as a opaque buffer. Only the first field
- * is checked to internally enable WAPI. If buffer length is zero, the existing
- * WAPI IE is reset.
- */
-static int mwifiex_set_wapi_ie(struct mwifiex_private *priv,
-                              u8 *ie_data_ptr, u16 ie_len)
-{
-       if (ie_len) {
-               if (ie_len > sizeof(priv->wapi_ie)) {
-                       mwifiex_dbg(priv->adapter, ERROR,
-                                   "info: failed to copy WAPI IE, too big\n");
-                       return -1;
-               }
-               memcpy(priv->wapi_ie, ie_data_ptr, ie_len);
-               priv->wapi_ie_len = ie_len;
-               mwifiex_dbg(priv->adapter, CMD,
-                           "cmd: Set wapi_ie_len=%d IE=%#x\n",
-                           priv->wapi_ie_len, priv->wapi_ie[0]);
-
-               if (priv->wapi_ie[0] == WLAN_EID_BSS_AC_ACCESS_DELAY)
-                       priv->sec_info.wapi_enabled = true;
-       } else {
-               memset(priv->wapi_ie, 0, sizeof(priv->wapi_ie));
-               priv->wapi_ie_len = ie_len;
-               mwifiex_dbg(priv->adapter, INFO,
-                           "info: Reset wapi_ie_len=%d IE=%#x\n",
-                           priv->wapi_ie_len, priv->wapi_ie[0]);
-               priv->sec_info.wapi_enabled = false;
-       }
-       return 0;
-}
-
-/*
- * IOCTL request handler to set/reset WPS IE.
- *
- * The supplied WPS IE is treated as a opaque buffer. Only the first field
- * is checked to internally enable WPS. If buffer length is zero, the existing
- * WPS IE is reset.
- */
-static int mwifiex_set_wps_ie(struct mwifiex_private *priv,
-                              u8 *ie_data_ptr, u16 ie_len)
-{
-       if (ie_len) {
-               if (ie_len > MWIFIEX_MAX_VSIE_LEN) {
-                       mwifiex_dbg(priv->adapter, ERROR,
-                                   "info: failed to copy WPS IE, too big\n");
-                       return -1;
-               }
-
-               priv->wps_ie = kzalloc(MWIFIEX_MAX_VSIE_LEN, GFP_KERNEL);
-               if (!priv->wps_ie)
-                       return -ENOMEM;
-
-               memcpy(priv->wps_ie, ie_data_ptr, ie_len);
-               priv->wps_ie_len = ie_len;
-               mwifiex_dbg(priv->adapter, CMD,
-                           "cmd: Set wps_ie_len=%d IE=%#x\n",
-                           priv->wps_ie_len, priv->wps_ie[0]);
-       } else {
-               kfree(priv->wps_ie);
-               priv->wps_ie_len = ie_len;
-               mwifiex_dbg(priv->adapter, INFO,
-                           "info: Reset wps_ie_len=%d\n", priv->wps_ie_len);
-       }
-       return 0;
-}
-
-/*
- * IOCTL request handler to set WAPI key.
- *
- * This function prepares the correct firmware command and
- * issues it.
- */
-static int mwifiex_sec_ioctl_set_wapi_key(struct mwifiex_private *priv,
-                              struct mwifiex_ds_encrypt_key *encrypt_key)
-{
-
-       return mwifiex_send_cmd(priv, HostCmd_CMD_802_11_KEY_MATERIAL,
-                               HostCmd_ACT_GEN_SET, KEY_INFO_ENABLED,
-                               encrypt_key, true);
-}
-
-/*
- * IOCTL request handler to set WEP network key.
- *
- * This function prepares the correct firmware command and
- * issues it, after validation checks.
- */
-static int mwifiex_sec_ioctl_set_wep_key(struct mwifiex_private *priv,
-                             struct mwifiex_ds_encrypt_key *encrypt_key)
-{
-       struct mwifiex_adapter *adapter = priv->adapter;
-       int ret;
-       struct mwifiex_wep_key *wep_key;
-       int index;
-
-       if (priv->wep_key_curr_index >= NUM_WEP_KEYS)
-               priv->wep_key_curr_index = 0;
-       wep_key = &priv->wep_key[priv->wep_key_curr_index];
-       index = encrypt_key->key_index;
-       if (encrypt_key->key_disable) {
-               priv->sec_info.wep_enabled = 0;
-       } else if (!encrypt_key->key_len) {
-               /* Copy the required key as the current key */
-               wep_key = &priv->wep_key[index];
-               if (!wep_key->key_length) {
-                       mwifiex_dbg(adapter, ERROR,
-                                   "key not set, so cannot enable it\n");
-                       return -1;
-               }
-
-               if (adapter->key_api_major_ver == KEY_API_VER_MAJOR_V2) {
-                       memcpy(encrypt_key->key_material,
-                              wep_key->key_material, wep_key->key_length);
-                       encrypt_key->key_len = wep_key->key_length;
-               }
-
-               priv->wep_key_curr_index = (u16) index;
-               priv->sec_info.wep_enabled = 1;
-       } else {
-               wep_key = &priv->wep_key[index];
-               memset(wep_key, 0, sizeof(struct mwifiex_wep_key));
-               /* Copy the key in the driver */
-               memcpy(wep_key->key_material,
-                      encrypt_key->key_material,
-                      encrypt_key->key_len);
-               wep_key->key_index = index;
-               wep_key->key_length = encrypt_key->key_len;
-               priv->sec_info.wep_enabled = 1;
-       }
-       if (wep_key->key_length) {
-               void *enc_key;
-
-               if (encrypt_key->key_disable) {
-                       memset(&priv->wep_key[index], 0,
-                              sizeof(struct mwifiex_wep_key));
-                       if (wep_key->key_length)
-                               goto done;
-                       }
-
-               if (adapter->key_api_major_ver == KEY_API_VER_MAJOR_V2)
-                       enc_key = encrypt_key;
-               else
-                       enc_key = NULL;
-
-               /* Send request to firmware */
-               ret = mwifiex_send_cmd(priv, HostCmd_CMD_802_11_KEY_MATERIAL,
-                                      HostCmd_ACT_GEN_SET, 0, enc_key, false);
-               if (ret)
-                       return ret;
-       }
-
-done:
-       if (priv->sec_info.wep_enabled)
-               priv->curr_pkt_filter |= HostCmd_ACT_MAC_WEP_ENABLE;
-       else
-               priv->curr_pkt_filter &= ~HostCmd_ACT_MAC_WEP_ENABLE;
-
-       ret = mwifiex_send_cmd(priv, HostCmd_CMD_MAC_CONTROL,
-                              HostCmd_ACT_GEN_SET, 0,
-                              &priv->curr_pkt_filter, true);
-
-       return ret;
-}
-
-/*
- * IOCTL request handler to set WPA key.
- *
- * This function prepares the correct firmware command and
- * issues it, after validation checks.
- *
- * Current driver only supports key length of up to 32 bytes.
- *
- * This function can also be used to disable a currently set key.
- */
-static int mwifiex_sec_ioctl_set_wpa_key(struct mwifiex_private *priv,
-                             struct mwifiex_ds_encrypt_key *encrypt_key)
-{
-       int ret;
-       u8 remove_key = false;
-       struct host_cmd_ds_802_11_key_material *ibss_key;
-
-       /* Current driver only supports key length of up to 32 bytes */
-       if (encrypt_key->key_len > WLAN_MAX_KEY_LEN) {
-               mwifiex_dbg(priv->adapter, ERROR,
-                           "key length too long\n");
-               return -1;
-       }
-
-       if (priv->bss_mode == NL80211_IFTYPE_ADHOC) {
-               /*
-                * IBSS/WPA-None uses only one key (Group) for both receiving
-                * and sending unicast and multicast packets.
-                */
-               /* Send the key as PTK to firmware */
-               encrypt_key->key_index = MWIFIEX_KEY_INDEX_UNICAST;
-               ret = mwifiex_send_cmd(priv, HostCmd_CMD_802_11_KEY_MATERIAL,
-                                      HostCmd_ACT_GEN_SET,
-                                      KEY_INFO_ENABLED, encrypt_key, false);
-               if (ret)
-                       return ret;
-
-               ibss_key = &priv->aes_key;
-               memset(ibss_key, 0,
-                      sizeof(struct host_cmd_ds_802_11_key_material));
-               /* Copy the key in the driver */
-               memcpy(ibss_key->key_param_set.key, encrypt_key->key_material,
-                      encrypt_key->key_len);
-               memcpy(&ibss_key->key_param_set.key_len, &encrypt_key->key_len,
-                      sizeof(ibss_key->key_param_set.key_len));
-               ibss_key->key_param_set.key_type_id
-                       = cpu_to_le16(KEY_TYPE_ID_TKIP);
-               ibss_key->key_param_set.key_info = cpu_to_le16(KEY_ENABLED);
-
-               /* Send the key as GTK to firmware */
-               encrypt_key->key_index = ~MWIFIEX_KEY_INDEX_UNICAST;
-       }
-
-       if (!encrypt_key->key_index)
-               encrypt_key->key_index = MWIFIEX_KEY_INDEX_UNICAST;
-
-       if (remove_key)
-               ret = mwifiex_send_cmd(priv, HostCmd_CMD_802_11_KEY_MATERIAL,
-                                      HostCmd_ACT_GEN_SET,
-                                      !KEY_INFO_ENABLED, encrypt_key, true);
-       else
-               ret = mwifiex_send_cmd(priv, HostCmd_CMD_802_11_KEY_MATERIAL,
-                                      HostCmd_ACT_GEN_SET,
-                                      KEY_INFO_ENABLED, encrypt_key, true);
-
-       return ret;
-}
-
-/*
- * IOCTL request handler to set/get network keys.
- *
- * This is a generic key handling function which supports WEP, WPA
- * and WAPI.
- */
-static int
-mwifiex_sec_ioctl_encrypt_key(struct mwifiex_private *priv,
-                             struct mwifiex_ds_encrypt_key *encrypt_key)
-{
-       int status;
-
-       if (encrypt_key->is_wapi_key)
-               status = mwifiex_sec_ioctl_set_wapi_key(priv, encrypt_key);
-       else if (encrypt_key->key_len > WLAN_KEY_LEN_WEP104)
-               status = mwifiex_sec_ioctl_set_wpa_key(priv, encrypt_key);
-       else
-               status = mwifiex_sec_ioctl_set_wep_key(priv, encrypt_key);
-       return status;
-}
-
-/*
- * This function returns the driver version.
- */
-int
-mwifiex_drv_get_driver_version(struct mwifiex_adapter *adapter, char *version,
-                              int max_len)
-{
-       union {
-               __le32 l;
-               u8 c[4];
-       } ver;
-       char fw_ver[32];
-
-       ver.l = cpu_to_le32(adapter->fw_release_number);
-       sprintf(fw_ver, "%u.%u.%u.p%u", ver.c[2], ver.c[1], ver.c[0], ver.c[3]);
-
-       snprintf(version, max_len, driver_version, fw_ver);
-
-       mwifiex_dbg(adapter, MSG, "info: MWIFIEX VERSION: %s\n", version);
-
-       return 0;
-}
-
-/*
- * Sends IOCTL request to set encoding parameters.
- *
- * This function allocates the IOCTL request buffer, fills it
- * with requisite parameters and calls the IOCTL handler.
- */
-int mwifiex_set_encode(struct mwifiex_private *priv, struct key_params *kp,
-                      const u8 *key, int key_len, u8 key_index,
-                      const u8 *mac_addr, int disable)
-{
-       struct mwifiex_ds_encrypt_key encrypt_key;
-
-       memset(&encrypt_key, 0, sizeof(struct mwifiex_ds_encrypt_key));
-       encrypt_key.key_len = key_len;
-       encrypt_key.key_index = key_index;
-
-       if (kp && kp->cipher == WLAN_CIPHER_SUITE_AES_CMAC)
-               encrypt_key.is_igtk_key = true;
-
-       if (!disable) {
-               if (key_len)
-                       memcpy(encrypt_key.key_material, key, key_len);
-               else
-                       encrypt_key.is_current_wep_key = true;
-
-               if (mac_addr)
-                       memcpy(encrypt_key.mac_addr, mac_addr, ETH_ALEN);
-               if (kp && kp->seq && kp->seq_len) {
-                       memcpy(encrypt_key.pn, kp->seq, kp->seq_len);
-                       encrypt_key.pn_len = kp->seq_len;
-                       encrypt_key.is_rx_seq_valid = true;
-               }
-       } else {
-               if (GET_BSS_ROLE(priv) == MWIFIEX_BSS_ROLE_UAP)
-                       return 0;
-               encrypt_key.key_disable = true;
-               if (mac_addr)
-                       memcpy(encrypt_key.mac_addr, mac_addr, ETH_ALEN);
-       }
-
-       return mwifiex_sec_ioctl_encrypt_key(priv, &encrypt_key);
-}
-
-/*
- * Sends IOCTL request to get extended version.
- *
- * This function allocates the IOCTL request buffer, fills it
- * with requisite parameters and calls the IOCTL handler.
- */
-int
-mwifiex_get_ver_ext(struct mwifiex_private *priv)
-{
-       struct mwifiex_ver_ext ver_ext;
-
-       memset(&ver_ext, 0, sizeof(struct host_cmd_ds_version_ext));
-       if (mwifiex_send_cmd(priv, HostCmd_CMD_VERSION_EXT,
-                            HostCmd_ACT_GEN_GET, 0, &ver_ext, true))
-               return -1;
-
-       return 0;
-}
-
-int
-mwifiex_remain_on_chan_cfg(struct mwifiex_private *priv, u16 action,
-                          struct ieee80211_channel *chan,
-                          unsigned int duration)
-{
-       struct host_cmd_ds_remain_on_chan roc_cfg;
-       u8 sc;
-
-       memset(&roc_cfg, 0, sizeof(roc_cfg));
-       roc_cfg.action = cpu_to_le16(action);
-       if (action == HostCmd_ACT_GEN_SET) {
-               roc_cfg.band_cfg = chan->band;
-               sc = mwifiex_chan_type_to_sec_chan_offset(NL80211_CHAN_NO_HT);
-               roc_cfg.band_cfg |= (sc << 2);
-
-               roc_cfg.channel =
-                       ieee80211_frequency_to_channel(chan->center_freq);
-               roc_cfg.duration = cpu_to_le32(duration);
-       }
-       if (mwifiex_send_cmd(priv, HostCmd_CMD_REMAIN_ON_CHAN,
-                            action, 0, &roc_cfg, true)) {
-               mwifiex_dbg(priv->adapter, ERROR,
-                           "failed to remain on channel\n");
-               return -1;
-       }
-
-       return roc_cfg.status;
-}
-
-/*
- * Sends IOCTL request to get statistics information.
- *
- * This function allocates the IOCTL request buffer, fills it
- * with requisite parameters and calls the IOCTL handler.
- */
-int
-mwifiex_get_stats_info(struct mwifiex_private *priv,
-                      struct mwifiex_ds_get_stats *log)
-{
-       return mwifiex_send_cmd(priv, HostCmd_CMD_802_11_GET_LOG,
-                               HostCmd_ACT_GEN_GET, 0, log, true);
-}
-
-/*
- * IOCTL request handler to read/write register.
- *
- * This function prepares the correct firmware command and
- * issues it.
- *
- * Access to the following registers are supported -
- *      - MAC
- *      - BBP
- *      - RF
- *      - PMIC
- *      - CAU
- */
-static int mwifiex_reg_mem_ioctl_reg_rw(struct mwifiex_private *priv,
-                                       struct mwifiex_ds_reg_rw *reg_rw,
-                                       u16 action)
-{
-       u16 cmd_no;
-
-       switch (le32_to_cpu(reg_rw->type)) {
-       case MWIFIEX_REG_MAC:
-               cmd_no = HostCmd_CMD_MAC_REG_ACCESS;
-               break;
-       case MWIFIEX_REG_BBP:
-               cmd_no = HostCmd_CMD_BBP_REG_ACCESS;
-               break;
-       case MWIFIEX_REG_RF:
-               cmd_no = HostCmd_CMD_RF_REG_ACCESS;
-               break;
-       case MWIFIEX_REG_PMIC:
-               cmd_no = HostCmd_CMD_PMIC_REG_ACCESS;
-               break;
-       case MWIFIEX_REG_CAU:
-               cmd_no = HostCmd_CMD_CAU_REG_ACCESS;
-               break;
-       default:
-               return -1;
-       }
-
-       return mwifiex_send_cmd(priv, cmd_no, action, 0, reg_rw, true);
-}
-
-/*
- * Sends IOCTL request to write to a register.
- *
- * This function allocates the IOCTL request buffer, fills it
- * with requisite parameters and calls the IOCTL handler.
- */
-int
-mwifiex_reg_write(struct mwifiex_private *priv, u32 reg_type,
-                 u32 reg_offset, u32 reg_value)
-{
-       struct mwifiex_ds_reg_rw reg_rw;
-
-       reg_rw.type = cpu_to_le32(reg_type);
-       reg_rw.offset = cpu_to_le32(reg_offset);
-       reg_rw.value = cpu_to_le32(reg_value);
-
-       return mwifiex_reg_mem_ioctl_reg_rw(priv, &reg_rw, HostCmd_ACT_GEN_SET);
-}
-
-/*
- * Sends IOCTL request to read from a register.
- *
- * This function allocates the IOCTL request buffer, fills it
- * with requisite parameters and calls the IOCTL handler.
- */
-int
-mwifiex_reg_read(struct mwifiex_private *priv, u32 reg_type,
-                u32 reg_offset, u32 *value)
-{
-       int ret;
-       struct mwifiex_ds_reg_rw reg_rw;
-
-       reg_rw.type = cpu_to_le32(reg_type);
-       reg_rw.offset = cpu_to_le32(reg_offset);
-       ret = mwifiex_reg_mem_ioctl_reg_rw(priv, &reg_rw, HostCmd_ACT_GEN_GET);
-
-       if (ret)
-               goto done;
-
-       *value = le32_to_cpu(reg_rw.value);
-
-done:
-       return ret;
-}
-
-/*
- * Sends IOCTL request to read from EEPROM.
- *
- * This function allocates the IOCTL request buffer, fills it
- * with requisite parameters and calls the IOCTL handler.
- */
-int
-mwifiex_eeprom_read(struct mwifiex_private *priv, u16 offset, u16 bytes,
-                   u8 *value)
-{
-       int ret;
-       struct mwifiex_ds_read_eeprom rd_eeprom;
-
-       rd_eeprom.offset = cpu_to_le16((u16) offset);
-       rd_eeprom.byte_count = cpu_to_le16((u16) bytes);
-
-       /* Send request to firmware */
-       ret = mwifiex_send_cmd(priv, HostCmd_CMD_802_11_EEPROM_ACCESS,
-                              HostCmd_ACT_GEN_GET, 0, &rd_eeprom, true);
-
-       if (!ret)
-               memcpy(value, rd_eeprom.value, MAX_EEPROM_DATA);
-       return ret;
-}
-
-/*
- * This function sets a generic IE. In addition to generic IE, it can
- * also handle WPA, WPA2 and WAPI IEs.
- */
-static int
-mwifiex_set_gen_ie_helper(struct mwifiex_private *priv, u8 *ie_data_ptr,
-                         u16 ie_len)
-{
-       int ret = 0;
-       struct ieee_types_vendor_header *pvendor_ie;
-       const u8 wpa_oui[] = { 0x00, 0x50, 0xf2, 0x01 };
-       const u8 wps_oui[] = { 0x00, 0x50, 0xf2, 0x04 };
-
-       /* If the passed length is zero, reset the buffer */
-       if (!ie_len) {
-               priv->gen_ie_buf_len = 0;
-               priv->wps.session_enable = false;
-
-               return 0;
-       } else if (!ie_data_ptr) {
-               return -1;
-       }
-       pvendor_ie = (struct ieee_types_vendor_header *) ie_data_ptr;
-       /* Test to see if it is a WPA IE, if not, then it is a gen IE */
-       if (((pvendor_ie->element_id == WLAN_EID_VENDOR_SPECIFIC) &&
-            (!memcmp(pvendor_ie->oui, wpa_oui, sizeof(wpa_oui)))) ||
-           (pvendor_ie->element_id == WLAN_EID_RSN)) {
-
-               /* IE is a WPA/WPA2 IE so call set_wpa function */
-               ret = mwifiex_set_wpa_ie_helper(priv, ie_data_ptr, ie_len);
-               priv->wps.session_enable = false;
-
-               return ret;
-       } else if (pvendor_ie->element_id == WLAN_EID_BSS_AC_ACCESS_DELAY) {
-               /* IE is a WAPI IE so call set_wapi function */
-               ret = mwifiex_set_wapi_ie(priv, ie_data_ptr, ie_len);
-
-               return ret;
-       }
-       /*
-        * Verify that the passed length is not larger than the
-        * available space remaining in the buffer
-        */
-       if (ie_len < (sizeof(priv->gen_ie_buf) - priv->gen_ie_buf_len)) {
-
-               /* Test to see if it is a WPS IE, if so, enable
-                * wps session flag
-                */
-               pvendor_ie = (struct ieee_types_vendor_header *) ie_data_ptr;
-               if ((pvendor_ie->element_id == WLAN_EID_VENDOR_SPECIFIC) &&
-                   (!memcmp(pvendor_ie->oui, wps_oui, sizeof(wps_oui)))) {
-                       priv->wps.session_enable = true;
-                       mwifiex_dbg(priv->adapter, INFO,
-                                   "info: WPS Session Enabled.\n");
-                       ret = mwifiex_set_wps_ie(priv, ie_data_ptr, ie_len);
-               }
-
-               /* Append the passed data to the end of the
-                  genIeBuffer */
-               memcpy(priv->gen_ie_buf + priv->gen_ie_buf_len, ie_data_ptr,
-                      ie_len);
-               /* Increment the stored buffer length by the
-                  size passed */
-               priv->gen_ie_buf_len += ie_len;
-       } else {
-               /* Passed data does not fit in the remaining
-                  buffer space */
-               ret = -1;
-       }
-
-       /* Return 0, or -1 for error case */
-       return ret;
-}
-
-/*
- * IOCTL request handler to set/get generic IE.
- *
- * In addition to various generic IEs, this function can also be
- * used to set the ARP filter.
- */
-static int mwifiex_misc_ioctl_gen_ie(struct mwifiex_private *priv,
-                                    struct mwifiex_ds_misc_gen_ie *gen_ie,
-                                    u16 action)
-{
-       struct mwifiex_adapter *adapter = priv->adapter;
-
-       switch (gen_ie->type) {
-       case MWIFIEX_IE_TYPE_GEN_IE:
-               if (action == HostCmd_ACT_GEN_GET) {
-                       gen_ie->len = priv->wpa_ie_len;
-                       memcpy(gen_ie->ie_data, priv->wpa_ie, gen_ie->len);
-               } else {
-                       mwifiex_set_gen_ie_helper(priv, gen_ie->ie_data,
-                                                 (u16) gen_ie->len);
-               }
-               break;
-       case MWIFIEX_IE_TYPE_ARP_FILTER:
-               memset(adapter->arp_filter, 0, sizeof(adapter->arp_filter));
-               if (gen_ie->len > ARP_FILTER_MAX_BUF_SIZE) {
-                       adapter->arp_filter_size = 0;
-                       mwifiex_dbg(adapter, ERROR,
-                                   "invalid ARP filter size\n");
-                       return -1;
-               } else {
-                       memcpy(adapter->arp_filter, gen_ie->ie_data,
-                              gen_ie->len);
-                       adapter->arp_filter_size = gen_ie->len;
-               }
-               break;
-       default:
-               mwifiex_dbg(adapter, ERROR, "invalid IE type\n");
-               return -1;
-       }
-       return 0;
-}
-
-/*
- * Sends IOCTL request to set a generic IE.
- *
- * This function allocates the IOCTL request buffer, fills it
- * with requisite parameters and calls the IOCTL handler.
- */
-int
-mwifiex_set_gen_ie(struct mwifiex_private *priv, const u8 *ie, int ie_len)
-{
-       struct mwifiex_ds_misc_gen_ie gen_ie;
-
-       if (ie_len > IEEE_MAX_IE_SIZE)
-               return -EFAULT;
-
-       gen_ie.type = MWIFIEX_IE_TYPE_GEN_IE;
-       gen_ie.len = ie_len;
-       memcpy(gen_ie.ie_data, ie, ie_len);
-       if (mwifiex_misc_ioctl_gen_ie(priv, &gen_ie, HostCmd_ACT_GEN_SET))
-               return -EFAULT;
-
-       return 0;
-}
diff --git a/drivers/net/wireless/mwifiex/sta_rx.c b/drivers/net/wireless/mwifiex/sta_rx.c
deleted file mode 100644 (file)
index d4d4cb1..0000000
+++ /dev/null
@@ -1,267 +0,0 @@
-/*
- * Marvell Wireless LAN device driver: station RX data handling
- *
- * Copyright (C) 2011-2014, Marvell International Ltd.
- *
- * This software file (the "File") is distributed by Marvell International
- * Ltd. under the terms of the GNU General Public License Version 2, June 1991
- * (the "License").  You may use, redistribute and/or modify this File in
- * accordance with the terms and conditions of the License, a copy of which
- * is available by writing to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the
- * worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
- *
- * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
- * ARE EXPRESSLY DISCLAIMED.  The License provides additional details about
- * this warranty disclaimer.
- */
-
-#include <uapi/linux/ipv6.h>
-#include <net/ndisc.h>
-#include "decl.h"
-#include "ioctl.h"
-#include "util.h"
-#include "fw.h"
-#include "main.h"
-#include "11n_aggr.h"
-#include "11n_rxreorder.h"
-
-/* This function checks if a frame is IPv4 ARP or IPv6 Neighbour advertisement
- * frame. If frame has both source and destination mac address as same, this
- * function drops such gratuitous frames.
- */
-static bool
-mwifiex_discard_gratuitous_arp(struct mwifiex_private *priv,
-                              struct sk_buff *skb)
-{
-       const struct mwifiex_arp_eth_header *arp;
-       struct ethhdr *eth;
-       struct ipv6hdr *ipv6;
-       struct icmp6hdr *icmpv6;
-
-       eth = (struct ethhdr *)skb->data;
-       switch (ntohs(eth->h_proto)) {
-       case ETH_P_ARP:
-               arp = (void *)(skb->data + sizeof(struct ethhdr));
-               if (arp->hdr.ar_op == htons(ARPOP_REPLY) ||
-                   arp->hdr.ar_op == htons(ARPOP_REQUEST)) {
-                       if (!memcmp(arp->ar_sip, arp->ar_tip, 4))
-                               return true;
-               }
-               break;
-       case ETH_P_IPV6:
-               ipv6 = (void *)(skb->data + sizeof(struct ethhdr));
-               icmpv6 = (void *)(skb->data + sizeof(struct ethhdr) +
-                                 sizeof(struct ipv6hdr));
-               if (NDISC_NEIGHBOUR_ADVERTISEMENT == icmpv6->icmp6_type) {
-                       if (!memcmp(&ipv6->saddr, &ipv6->daddr,
-                                   sizeof(struct in6_addr)))
-                               return true;
-               }
-               break;
-       default:
-               break;
-       }
-
-       return false;
-}
-
-/*
- * This function processes the received packet and forwards it
- * to kernel/upper layer.
- *
- * This function parses through the received packet and determines
- * if it is a debug packet or normal packet.
- *
- * For non-debug packets, the function chops off unnecessary leading
- * header bytes, reconstructs the packet as an ethernet frame or
- * 802.2/llc/snap frame as required, and sends it to kernel/upper layer.
- *
- * The completion callback is called after processing in complete.
- */
-int mwifiex_process_rx_packet(struct mwifiex_private *priv,
-                             struct sk_buff *skb)
-{
-       int ret;
-       struct rx_packet_hdr *rx_pkt_hdr;
-       struct rxpd *local_rx_pd;
-       int hdr_chop;
-       struct ethhdr *eth;
-       u16 rx_pkt_off, rx_pkt_len;
-       u8 *offset;
-       u8 adj_rx_rate = 0;
-
-       local_rx_pd = (struct rxpd *) (skb->data);
-
-       rx_pkt_off = le16_to_cpu(local_rx_pd->rx_pkt_offset);
-       rx_pkt_len = le16_to_cpu(local_rx_pd->rx_pkt_length);
-       rx_pkt_hdr = (void *)local_rx_pd + rx_pkt_off;
-
-       if ((!memcmp(&rx_pkt_hdr->rfc1042_hdr, bridge_tunnel_header,
-                    sizeof(bridge_tunnel_header))) ||
-           (!memcmp(&rx_pkt_hdr->rfc1042_hdr, rfc1042_header,
-                    sizeof(rfc1042_header)) &&
-            ntohs(rx_pkt_hdr->rfc1042_hdr.snap_type) != ETH_P_AARP &&
-            ntohs(rx_pkt_hdr->rfc1042_hdr.snap_type) != ETH_P_IPX)) {
-               /*
-                *  Replace the 803 header and rfc1042 header (llc/snap) with an
-                *    EthernetII header, keep the src/dst and snap_type
-                *    (ethertype).
-                *  The firmware only passes up SNAP frames converting
-                *    all RX Data from 802.11 to 802.2/LLC/SNAP frames.
-                *  To create the Ethernet II, just move the src, dst address
-                *    right before the snap_type.
-                */
-               eth = (struct ethhdr *)
-                       ((u8 *) &rx_pkt_hdr->eth803_hdr
-                        + sizeof(rx_pkt_hdr->eth803_hdr) +
-                        sizeof(rx_pkt_hdr->rfc1042_hdr)
-                        - sizeof(rx_pkt_hdr->eth803_hdr.h_dest)
-                        - sizeof(rx_pkt_hdr->eth803_hdr.h_source)
-                        - sizeof(rx_pkt_hdr->rfc1042_hdr.snap_type));
-
-               memcpy(eth->h_source, rx_pkt_hdr->eth803_hdr.h_source,
-                      sizeof(eth->h_source));
-               memcpy(eth->h_dest, rx_pkt_hdr->eth803_hdr.h_dest,
-                      sizeof(eth->h_dest));
-
-               /* Chop off the rxpd + the excess memory from the 802.2/llc/snap
-                  header that was removed. */
-               hdr_chop = (u8 *) eth - (u8 *) local_rx_pd;
-       } else {
-               /* Chop off the rxpd */
-               hdr_chop = (u8 *) &rx_pkt_hdr->eth803_hdr -
-                       (u8 *) local_rx_pd;
-       }
-
-       /* Chop off the leading header bytes so the it points to the start of
-          either the reconstructed EthII frame or the 802.2/llc/snap frame */
-       skb_pull(skb, hdr_chop);
-
-       if (priv->hs2_enabled &&
-           mwifiex_discard_gratuitous_arp(priv, skb)) {
-               mwifiex_dbg(priv->adapter, INFO, "Bypassed Gratuitous ARP\n");
-               dev_kfree_skb_any(skb);
-               return 0;
-       }
-
-       if (ISSUPP_TDLS_ENABLED(priv->adapter->fw_cap_info) &&
-           ntohs(rx_pkt_hdr->eth803_hdr.h_proto) == ETH_P_TDLS) {
-               offset = (u8 *)local_rx_pd + rx_pkt_off;
-               mwifiex_process_tdls_action_frame(priv, offset, rx_pkt_len);
-       }
-
-       priv->rxpd_rate = local_rx_pd->rx_rate;
-
-       priv->rxpd_htinfo = local_rx_pd->ht_info;
-
-       if (GET_BSS_ROLE(priv) == MWIFIEX_BSS_ROLE_STA ||
-           GET_BSS_ROLE(priv) == MWIFIEX_BSS_ROLE_UAP) {
-               adj_rx_rate = mwifiex_adjust_data_rate(priv, priv->rxpd_rate,
-                                                      priv->rxpd_htinfo);
-               mwifiex_hist_data_add(priv, adj_rx_rate, local_rx_pd->snr,
-                                     local_rx_pd->nf);
-       }
-
-       ret = mwifiex_recv_packet(priv, skb);
-       if (ret == -1)
-               mwifiex_dbg(priv->adapter, ERROR,
-                           "recv packet failed\n");
-
-       return ret;
-}
-
-/*
- * This function processes the received buffer.
- *
- * The function looks into the RxPD and performs sanity tests on the
- * received buffer to ensure its a valid packet, before processing it
- * further. If the packet is determined to be aggregated, it is
- * de-aggregated accordingly. Non-unicast packets are sent directly to
- * the kernel/upper layers. Unicast packets are handed over to the
- * Rx reordering routine if 11n is enabled.
- *
- * The completion callback is called after processing in complete.
- */
-int mwifiex_process_sta_rx_packet(struct mwifiex_private *priv,
-                                 struct sk_buff *skb)
-{
-       struct mwifiex_adapter *adapter = priv->adapter;
-       int ret = 0;
-       struct rxpd *local_rx_pd;
-       struct rx_packet_hdr *rx_pkt_hdr;
-       u8 ta[ETH_ALEN];
-       u16 rx_pkt_type, rx_pkt_offset, rx_pkt_length, seq_num;
-       struct mwifiex_sta_node *sta_ptr;
-
-       local_rx_pd = (struct rxpd *) (skb->data);
-       rx_pkt_type = le16_to_cpu(local_rx_pd->rx_pkt_type);
-       rx_pkt_offset = le16_to_cpu(local_rx_pd->rx_pkt_offset);
-       rx_pkt_length = le16_to_cpu(local_rx_pd->rx_pkt_length);
-       seq_num = le16_to_cpu(local_rx_pd->seq_num);
-
-       rx_pkt_hdr = (void *)local_rx_pd + rx_pkt_offset;
-
-       if ((rx_pkt_offset + rx_pkt_length) > (u16) skb->len) {
-               mwifiex_dbg(adapter, ERROR,
-                           "wrong rx packet: len=%d, rx_pkt_offset=%d, rx_pkt_length=%d\n",
-                           skb->len, rx_pkt_offset, rx_pkt_length);
-               priv->stats.rx_dropped++;
-               dev_kfree_skb_any(skb);
-               return ret;
-       }
-
-       if (rx_pkt_type == PKT_TYPE_MGMT) {
-               ret = mwifiex_process_mgmt_packet(priv, skb);
-               if (ret)
-                       mwifiex_dbg(adapter, ERROR, "Rx of mgmt packet failed");
-               dev_kfree_skb_any(skb);
-               return ret;
-       }
-
-       /*
-        * If the packet is not an unicast packet then send the packet
-        * directly to os. Don't pass thru rx reordering
-        */
-       if ((!IS_11N_ENABLED(priv) &&
-            !(ISSUPP_TDLS_ENABLED(priv->adapter->fw_cap_info) &&
-              !(local_rx_pd->flags & MWIFIEX_RXPD_FLAGS_TDLS_PACKET))) ||
-           !ether_addr_equal_unaligned(priv->curr_addr, rx_pkt_hdr->eth803_hdr.h_dest)) {
-               mwifiex_process_rx_packet(priv, skb);
-               return ret;
-       }
-
-       if (mwifiex_queuing_ra_based(priv) ||
-           (ISSUPP_TDLS_ENABLED(priv->adapter->fw_cap_info) &&
-            local_rx_pd->flags & MWIFIEX_RXPD_FLAGS_TDLS_PACKET)) {
-               memcpy(ta, rx_pkt_hdr->eth803_hdr.h_source, ETH_ALEN);
-               if (local_rx_pd->flags & MWIFIEX_RXPD_FLAGS_TDLS_PACKET &&
-                   local_rx_pd->priority < MAX_NUM_TID) {
-                       sta_ptr = mwifiex_get_sta_entry(priv, ta);
-                       if (sta_ptr)
-                               sta_ptr->rx_seq[local_rx_pd->priority] =
-                                             le16_to_cpu(local_rx_pd->seq_num);
-                       mwifiex_auto_tdls_update_peer_signal(priv, ta,
-                                                            local_rx_pd->snr,
-                                                            local_rx_pd->nf);
-               }
-       } else {
-               if (rx_pkt_type != PKT_TYPE_BAR)
-                       priv->rx_seq[local_rx_pd->priority] = seq_num;
-               memcpy(ta, priv->curr_bss_params.bss_descriptor.mac_address,
-                      ETH_ALEN);
-       }
-
-       /* Reorder and send to OS */
-       ret = mwifiex_11n_rx_reorder_pkt(priv, seq_num, local_rx_pd->priority,
-                                        ta, (u8) rx_pkt_type, skb);
-
-       if (ret || (rx_pkt_type == PKT_TYPE_BAR))
-               dev_kfree_skb_any(skb);
-
-       if (ret)
-               priv->stats.rx_dropped++;
-
-       return ret;
-}
diff --git a/drivers/net/wireless/mwifiex/sta_tx.c b/drivers/net/wireless/mwifiex/sta_tx.c
deleted file mode 100644 (file)
index f6683ea..0000000
+++ /dev/null
@@ -1,244 +0,0 @@
-/*
- * Marvell Wireless LAN device driver: station TX data handling
- *
- * Copyright (C) 2011-2014, Marvell International Ltd.
- *
- * This software file (the "File") is distributed by Marvell International
- * Ltd. under the terms of the GNU General Public License Version 2, June 1991
- * (the "License").  You may use, redistribute and/or modify this File in
- * accordance with the terms and conditions of the License, a copy of which
- * is available by writing to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the
- * worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
- *
- * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
- * ARE EXPRESSLY DISCLAIMED.  The License provides additional details about
- * this warranty disclaimer.
- */
-
-#include "decl.h"
-#include "ioctl.h"
-#include "util.h"
-#include "fw.h"
-#include "main.h"
-#include "wmm.h"
-
-/*
- * This function fills the TxPD for tx packets.
- *
- * The Tx buffer received by this function should already have the
- * header space allocated for TxPD.
- *
- * This function inserts the TxPD in between interface header and actual
- * data and adjusts the buffer pointers accordingly.
- *
- * The following TxPD fields are set by this function, as required -
- *      - BSS number
- *      - Tx packet length and offset
- *      - Priority
- *      - Packet delay
- *      - Priority specific Tx control
- *      - Flags
- */
-void *mwifiex_process_sta_txpd(struct mwifiex_private *priv,
-                               struct sk_buff *skb)
-{
-       struct mwifiex_adapter *adapter = priv->adapter;
-       struct txpd *local_tx_pd;
-       struct mwifiex_txinfo *tx_info = MWIFIEX_SKB_TXCB(skb);
-       unsigned int pad;
-       u16 pkt_type, pkt_offset;
-       int hroom = (priv->adapter->iface_type == MWIFIEX_USB) ? 0 :
-                      INTF_HEADER_LEN;
-
-       if (!skb->len) {
-               mwifiex_dbg(adapter, ERROR,
-                           "Tx: bad packet length: %d\n", skb->len);
-               tx_info->status_code = -1;
-               return skb->data;
-       }
-
-       BUG_ON(skb_headroom(skb) < MWIFIEX_MIN_DATA_HEADER_LEN);
-
-       pkt_type = mwifiex_is_skb_mgmt_frame(skb) ? PKT_TYPE_MGMT : 0;
-
-       pad = ((void *)skb->data - (sizeof(*local_tx_pd) + hroom)-
-                        NULL) & (MWIFIEX_DMA_ALIGN_SZ - 1);
-       skb_push(skb, sizeof(*local_tx_pd) + pad);
-
-       local_tx_pd = (struct txpd *) skb->data;
-       memset(local_tx_pd, 0, sizeof(struct txpd));
-       local_tx_pd->bss_num = priv->bss_num;
-       local_tx_pd->bss_type = priv->bss_type;
-       local_tx_pd->tx_pkt_length = cpu_to_le16((u16)(skb->len -
-                                                      (sizeof(struct txpd) +
-                                                       pad)));
-
-       local_tx_pd->priority = (u8) skb->priority;
-       local_tx_pd->pkt_delay_2ms =
-                               mwifiex_wmm_compute_drv_pkt_delay(priv, skb);
-
-       if (tx_info->flags & MWIFIEX_BUF_FLAG_EAPOL_TX_STATUS ||
-           tx_info->flags & MWIFIEX_BUF_FLAG_ACTION_TX_STATUS) {
-               local_tx_pd->tx_token_id = tx_info->ack_frame_id;
-               local_tx_pd->flags |= MWIFIEX_TXPD_FLAGS_REQ_TX_STATUS;
-       }
-
-       if (local_tx_pd->priority <
-           ARRAY_SIZE(priv->wmm.user_pri_pkt_tx_ctrl))
-               /*
-                * Set the priority specific tx_control field, setting of 0 will
-                *   cause the default value to be used later in this function
-                */
-               local_tx_pd->tx_control =
-                       cpu_to_le32(priv->wmm.user_pri_pkt_tx_ctrl[local_tx_pd->
-                                                                  priority]);
-
-       if (adapter->pps_uapsd_mode) {
-               if (mwifiex_check_last_packet_indication(priv)) {
-                       adapter->tx_lock_flag = true;
-                       local_tx_pd->flags =
-                               MWIFIEX_TxPD_POWER_MGMT_LAST_PACKET;
-               }
-       }
-
-       if (tx_info->flags & MWIFIEX_BUF_FLAG_TDLS_PKT)
-               local_tx_pd->flags |= MWIFIEX_TXPD_FLAGS_TDLS_PACKET;
-
-       /* Offset of actual data */
-       pkt_offset = sizeof(struct txpd) + pad;
-       if (pkt_type == PKT_TYPE_MGMT) {
-               /* Set the packet type and add header for management frame */
-               local_tx_pd->tx_pkt_type = cpu_to_le16(pkt_type);
-               pkt_offset += MWIFIEX_MGMT_FRAME_HEADER_SIZE;
-       }
-
-       local_tx_pd->tx_pkt_offset = cpu_to_le16(pkt_offset);
-
-       /* make space for INTF_HEADER_LEN */
-       skb_push(skb, hroom);
-
-       if (!local_tx_pd->tx_control)
-               /* TxCtrl set by user or default */
-               local_tx_pd->tx_control = cpu_to_le32(priv->pkt_tx_ctrl);
-
-       return skb->data;
-}
-
-/*
- * This function tells firmware to send a NULL data packet.
- *
- * The function creates a NULL data packet with TxPD and sends to the
- * firmware for transmission, with highest priority setting.
- */
-int mwifiex_send_null_packet(struct mwifiex_private *priv, u8 flags)
-{
-       struct mwifiex_adapter *adapter = priv->adapter;
-       struct txpd *local_tx_pd;
-       struct mwifiex_tx_param tx_param;
-/* sizeof(struct txpd) + Interface specific header */
-#define NULL_PACKET_HDR 64
-       u32 data_len = NULL_PACKET_HDR;
-       struct sk_buff *skb;
-       int ret;
-       struct mwifiex_txinfo *tx_info = NULL;
-
-       if (adapter->surprise_removed)
-               return -1;
-
-       if (!priv->media_connected)
-               return -1;
-
-       if (adapter->data_sent)
-               return -1;
-
-       if (adapter->if_ops.is_port_ready &&
-           !adapter->if_ops.is_port_ready(priv))
-               return -1;
-
-       skb = dev_alloc_skb(data_len);
-       if (!skb)
-               return -1;
-
-       tx_info = MWIFIEX_SKB_TXCB(skb);
-       memset(tx_info, 0, sizeof(*tx_info));
-       tx_info->bss_num = priv->bss_num;
-       tx_info->bss_type = priv->bss_type;
-       tx_info->pkt_len = data_len - (sizeof(struct txpd) + INTF_HEADER_LEN);
-       skb_reserve(skb, sizeof(struct txpd) + INTF_HEADER_LEN);
-       skb_push(skb, sizeof(struct txpd));
-
-       local_tx_pd = (struct txpd *) skb->data;
-       local_tx_pd->tx_control = cpu_to_le32(priv->pkt_tx_ctrl);
-       local_tx_pd->flags = flags;
-       local_tx_pd->priority = WMM_HIGHEST_PRIORITY;
-       local_tx_pd->tx_pkt_offset = cpu_to_le16(sizeof(struct txpd));
-       local_tx_pd->bss_num = priv->bss_num;
-       local_tx_pd->bss_type = priv->bss_type;
-
-       if (adapter->iface_type == MWIFIEX_USB) {
-               ret = adapter->if_ops.host_to_card(adapter, priv->usb_port,
-                                                  skb, NULL);
-       } else {
-               skb_push(skb, INTF_HEADER_LEN);
-               tx_param.next_pkt_len = 0;
-               ret = adapter->if_ops.host_to_card(adapter, MWIFIEX_TYPE_DATA,
-                                                  skb, &tx_param);
-       }
-       switch (ret) {
-       case -EBUSY:
-               dev_kfree_skb_any(skb);
-               mwifiex_dbg(adapter, ERROR,
-                           "%s: host_to_card failed: ret=%d\n",
-                           __func__, ret);
-               adapter->dbg.num_tx_host_to_card_failure++;
-               break;
-       case -1:
-               dev_kfree_skb_any(skb);
-               mwifiex_dbg(adapter, ERROR,
-                           "%s: host_to_card failed: ret=%d\n",
-                           __func__, ret);
-               adapter->dbg.num_tx_host_to_card_failure++;
-               break;
-       case 0:
-               dev_kfree_skb_any(skb);
-               mwifiex_dbg(adapter, DATA,
-                           "data: %s: host_to_card succeeded\n",
-                           __func__);
-               adapter->tx_lock_flag = true;
-               break;
-       case -EINPROGRESS:
-               adapter->tx_lock_flag = true;
-               break;
-       default:
-               break;
-       }
-
-       return ret;
-}
-
-/*
- * This function checks if we need to send last packet indication.
- */
-u8
-mwifiex_check_last_packet_indication(struct mwifiex_private *priv)
-{
-       struct mwifiex_adapter *adapter = priv->adapter;
-       u8 ret = false;
-
-       if (!adapter->sleep_period.period)
-               return ret;
-       if (mwifiex_wmm_lists_empty(adapter))
-                       ret = true;
-
-       if (ret && !adapter->cmd_sent && !adapter->curr_cmd &&
-           !is_command_pending(adapter)) {
-               adapter->delay_null_pkt = false;
-               ret = true;
-       } else {
-               ret = false;
-               adapter->delay_null_pkt = true;
-       }
-       return ret;
-}
diff --git a/drivers/net/wireless/mwifiex/tdls.c b/drivers/net/wireless/mwifiex/tdls.c
deleted file mode 100644 (file)
index 9275f9c..0000000
+++ /dev/null
@@ -1,1500 +0,0 @@
-/* Marvell Wireless LAN device driver: TDLS handling
- *
- * Copyright (C) 2014, Marvell International Ltd.
- *
- * This software file (the "File") is distributed by Marvell International
- * Ltd. under the terms of the GNU General Public License Version 2, June 1991
- * (the "License").  You may use, redistribute and/or modify this File in
- * accordance with the terms and conditions of the License, a copy of which
- * is available on the worldwide web at
- * http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
- *
- * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
- * ARE EXPRESSLY DISCLAIMED.  The License provides additional details about
- * this warranty disclaimer.
- */
-
-#include "main.h"
-#include "wmm.h"
-#include "11n.h"
-#include "11n_rxreorder.h"
-#include "11ac.h"
-
-#define TDLS_REQ_FIX_LEN      6
-#define TDLS_RESP_FIX_LEN     8
-#define TDLS_CONFIRM_FIX_LEN  6
-#define MWIFIEX_TDLS_WMM_INFO_SIZE 7
-
-static void mwifiex_restore_tdls_packets(struct mwifiex_private *priv,
-                                        const u8 *mac, u8 status)
-{
-       struct mwifiex_ra_list_tbl *ra_list;
-       struct list_head *tid_list;
-       struct sk_buff *skb, *tmp;
-       struct mwifiex_txinfo *tx_info;
-       unsigned long flags;
-       u32 tid;
-       u8 tid_down;
-
-       mwifiex_dbg(priv->adapter, DATA, "%s: %pM\n", __func__, mac);
-       spin_lock_irqsave(&priv->wmm.ra_list_spinlock, flags);
-
-       skb_queue_walk_safe(&priv->tdls_txq, skb, tmp) {
-               if (!ether_addr_equal(mac, skb->data))
-                       continue;
-
-               __skb_unlink(skb, &priv->tdls_txq);
-               tx_info = MWIFIEX_SKB_TXCB(skb);
-               tid = skb->priority;
-               tid_down = mwifiex_wmm_downgrade_tid(priv, tid);
-
-               if (mwifiex_is_tdls_link_setup(status)) {
-                       ra_list = mwifiex_wmm_get_queue_raptr(priv, tid, mac);
-                       ra_list->tdls_link = true;
-                       tx_info->flags |= MWIFIEX_BUF_FLAG_TDLS_PKT;
-               } else {
-                       tid_list = &priv->wmm.tid_tbl_ptr[tid_down].ra_list;
-                       if (!list_empty(tid_list))
-                               ra_list = list_first_entry(tid_list,
-                                             struct mwifiex_ra_list_tbl, list);
-                       else
-                               ra_list = NULL;
-                       tx_info->flags &= ~MWIFIEX_BUF_FLAG_TDLS_PKT;
-               }
-
-               if (!ra_list) {
-                       mwifiex_write_data_complete(priv->adapter, skb, 0, -1);
-                       continue;
-               }
-
-               skb_queue_tail(&ra_list->skb_head, skb);
-
-               ra_list->ba_pkt_count++;
-               ra_list->total_pkt_count++;
-
-               if (atomic_read(&priv->wmm.highest_queued_prio) <
-                                                      tos_to_tid_inv[tid_down])
-                       atomic_set(&priv->wmm.highest_queued_prio,
-                                  tos_to_tid_inv[tid_down]);
-
-               atomic_inc(&priv->wmm.tx_pkts_queued);
-       }
-
-       spin_unlock_irqrestore(&priv->wmm.ra_list_spinlock, flags);
-       return;
-}
-
-static void mwifiex_hold_tdls_packets(struct mwifiex_private *priv,
-                                     const u8 *mac)
-{
-       struct mwifiex_ra_list_tbl *ra_list;
-       struct list_head *ra_list_head;
-       struct sk_buff *skb, *tmp;
-       unsigned long flags;
-       int i;
-
-       mwifiex_dbg(priv->adapter, DATA, "%s: %pM\n", __func__, mac);
-       spin_lock_irqsave(&priv->wmm.ra_list_spinlock, flags);
-
-       for (i = 0; i < MAX_NUM_TID; i++) {
-               if (!list_empty(&priv->wmm.tid_tbl_ptr[i].ra_list)) {
-                       ra_list_head = &priv->wmm.tid_tbl_ptr[i].ra_list;
-                       list_for_each_entry(ra_list, ra_list_head, list) {
-                               skb_queue_walk_safe(&ra_list->skb_head, skb,
-                                                   tmp) {
-                                       if (!ether_addr_equal(mac, skb->data))
-                                               continue;
-                                       __skb_unlink(skb, &ra_list->skb_head);
-                                       atomic_dec(&priv->wmm.tx_pkts_queued);
-                                       ra_list->total_pkt_count--;
-                                       skb_queue_tail(&priv->tdls_txq, skb);
-                               }
-                       }
-               }
-       }
-
-       spin_unlock_irqrestore(&priv->wmm.ra_list_spinlock, flags);
-       return;
-}
-
-/* This function appends rate TLV to scan config command. */
-static int
-mwifiex_tdls_append_rates_ie(struct mwifiex_private *priv,
-                            struct sk_buff *skb)
-{
-       u8 rates[MWIFIEX_SUPPORTED_RATES], *pos;
-       u16 rates_size, supp_rates_size, ext_rates_size;
-
-       memset(rates, 0, sizeof(rates));
-       rates_size = mwifiex_get_supported_rates(priv, rates);
-
-       supp_rates_size = min_t(u16, rates_size, MWIFIEX_TDLS_SUPPORTED_RATES);
-
-       if (skb_tailroom(skb) < rates_size + 4) {
-               mwifiex_dbg(priv->adapter, ERROR,
-                           "Insuffient space while adding rates\n");
-               return -ENOMEM;
-       }
-
-       pos = skb_put(skb, supp_rates_size + 2);
-       *pos++ = WLAN_EID_SUPP_RATES;
-       *pos++ = supp_rates_size;
-       memcpy(pos, rates, supp_rates_size);
-
-       if (rates_size > MWIFIEX_TDLS_SUPPORTED_RATES) {
-               ext_rates_size = rates_size - MWIFIEX_TDLS_SUPPORTED_RATES;
-               pos = skb_put(skb, ext_rates_size + 2);
-               *pos++ = WLAN_EID_EXT_SUPP_RATES;
-               *pos++ = ext_rates_size;
-               memcpy(pos, rates + MWIFIEX_TDLS_SUPPORTED_RATES,
-                      ext_rates_size);
-       }
-
-       return 0;
-}
-
-static void mwifiex_tdls_add_aid(struct mwifiex_private *priv,
-                               struct sk_buff *skb)
-{
-       struct ieee_types_assoc_rsp *assoc_rsp;
-       u8 *pos;
-
-       assoc_rsp = (struct ieee_types_assoc_rsp *)&priv->assoc_rsp_buf;
-       pos = (void *)skb_put(skb, 4);
-       *pos++ = WLAN_EID_AID;
-       *pos++ = 2;
-       memcpy(pos, &assoc_rsp->a_id, sizeof(assoc_rsp->a_id));
-
-       return;
-}
-
-static int mwifiex_tdls_add_vht_capab(struct mwifiex_private *priv,
-                                     struct sk_buff *skb)
-{
-       struct ieee80211_vht_cap vht_cap;
-       u8 *pos;
-
-       pos = (void *)skb_put(skb, sizeof(struct ieee80211_vht_cap) + 2);
-       *pos++ = WLAN_EID_VHT_CAPABILITY;
-       *pos++ = sizeof(struct ieee80211_vht_cap);
-
-       memset(&vht_cap, 0, sizeof(struct ieee80211_vht_cap));
-
-       mwifiex_fill_vht_cap_tlv(priv, &vht_cap, priv->curr_bss_params.band);
-       memcpy(pos, &vht_cap, sizeof(vht_cap));
-
-       return 0;
-}
-
-static int
-mwifiex_tdls_add_ht_oper(struct mwifiex_private *priv, const u8 *mac,
-                        u8 vht_enabled, struct sk_buff *skb)
-{
-       struct ieee80211_ht_operation *ht_oper;
-       struct mwifiex_sta_node *sta_ptr;
-       struct mwifiex_bssdescriptor *bss_desc =
-                                       &priv->curr_bss_params.bss_descriptor;
-       u8 *pos;
-
-       sta_ptr = mwifiex_get_sta_entry(priv, mac);
-       if (unlikely(!sta_ptr)) {
-               mwifiex_dbg(priv->adapter, ERROR,
-                           "TDLS peer station not found in list\n");
-               return -1;
-       }
-
-       if (!(le16_to_cpu(sta_ptr->tdls_cap.ht_capb.cap_info))) {
-               mwifiex_dbg(priv->adapter, WARN,
-                           "TDLS peer doesn't support ht capabilities\n");
-               return 0;
-       }
-
-       pos = (void *)skb_put(skb, sizeof(struct ieee80211_ht_operation) + 2);
-       *pos++ = WLAN_EID_HT_OPERATION;
-       *pos++ = sizeof(struct ieee80211_ht_operation);
-       ht_oper = (void *)pos;
-
-       ht_oper->primary_chan = bss_desc->channel;
-
-       /* follow AP's channel bandwidth */
-       if (ISSUPP_CHANWIDTH40(priv->adapter->hw_dot_11n_dev_cap) &&
-           bss_desc->bcn_ht_cap &&
-           ISALLOWED_CHANWIDTH40(bss_desc->bcn_ht_oper->ht_param))
-               ht_oper->ht_param = bss_desc->bcn_ht_oper->ht_param;
-
-       if (vht_enabled) {
-               ht_oper->ht_param =
-                         mwifiex_get_sec_chan_offset(bss_desc->channel);
-               ht_oper->ht_param |= BIT(2);
-       }
-
-       memcpy(&sta_ptr->tdls_cap.ht_oper, ht_oper,
-              sizeof(struct ieee80211_ht_operation));
-
-       return 0;
-}
-
-static int mwifiex_tdls_add_vht_oper(struct mwifiex_private *priv,
-                                    const u8 *mac, struct sk_buff *skb)
-{
-       struct mwifiex_bssdescriptor *bss_desc;
-       struct ieee80211_vht_operation *vht_oper;
-       struct ieee80211_vht_cap *vht_cap, *ap_vht_cap = NULL;
-       struct mwifiex_sta_node *sta_ptr;
-       struct mwifiex_adapter *adapter = priv->adapter;
-       u8 supp_chwd_set, peer_supp_chwd_set;
-       u8 *pos, ap_supp_chwd_set, chan_bw;
-       u16 mcs_map_user, mcs_map_resp, mcs_map_result;
-       u16 mcs_user, mcs_resp, nss;
-       u32 usr_vht_cap_info;
-
-       bss_desc = &priv->curr_bss_params.bss_descriptor;
-
-       sta_ptr = mwifiex_get_sta_entry(priv, mac);
-       if (unlikely(!sta_ptr)) {
-               mwifiex_dbg(adapter, ERROR,
-                           "TDLS peer station not found in list\n");
-               return -1;
-       }
-
-       if (!(le32_to_cpu(sta_ptr->tdls_cap.vhtcap.vht_cap_info))) {
-               mwifiex_dbg(adapter, WARN,
-                           "TDLS peer doesn't support vht capabilities\n");
-               return 0;
-       }
-
-       if (!mwifiex_is_bss_in_11ac_mode(priv)) {
-               if (sta_ptr->tdls_cap.extcap.ext_capab[7] &
-                  WLAN_EXT_CAPA8_TDLS_WIDE_BW_ENABLED) {
-                       mwifiex_dbg(adapter, WARN,
-                                   "TDLS peer doesn't support wider bandwidth\n");
-                       return 0;
-               }
-       } else {
-               ap_vht_cap = bss_desc->bcn_vht_cap;
-       }
-
-       pos = (void *)skb_put(skb, sizeof(struct ieee80211_vht_operation) + 2);
-       *pos++ = WLAN_EID_VHT_OPERATION;
-       *pos++ = sizeof(struct ieee80211_vht_operation);
-       vht_oper = (struct ieee80211_vht_operation *)pos;
-
-       if (bss_desc->bss_band & BAND_A)
-               usr_vht_cap_info = adapter->usr_dot_11ac_dev_cap_a;
-       else
-               usr_vht_cap_info = adapter->usr_dot_11ac_dev_cap_bg;
-
-       /* find the minmum bandwith between AP/TDLS peers */
-       vht_cap = &sta_ptr->tdls_cap.vhtcap;
-       supp_chwd_set = GET_VHTCAP_CHWDSET(usr_vht_cap_info);
-       peer_supp_chwd_set =
-                        GET_VHTCAP_CHWDSET(le32_to_cpu(vht_cap->vht_cap_info));
-       supp_chwd_set = min_t(u8, supp_chwd_set, peer_supp_chwd_set);
-
-       /* We need check AP's bandwidth when TDLS_WIDER_BANDWIDTH is off */
-
-       if (ap_vht_cap && sta_ptr->tdls_cap.extcap.ext_capab[7] &
-           WLAN_EXT_CAPA8_TDLS_WIDE_BW_ENABLED) {
-               ap_supp_chwd_set =
-                     GET_VHTCAP_CHWDSET(le32_to_cpu(ap_vht_cap->vht_cap_info));
-               supp_chwd_set = min_t(u8, supp_chwd_set, ap_supp_chwd_set);
-       }
-
-       switch (supp_chwd_set) {
-       case IEEE80211_VHT_CHANWIDTH_80MHZ:
-               vht_oper->chan_width = IEEE80211_VHT_CHANWIDTH_80MHZ;
-               break;
-       case IEEE80211_VHT_CHANWIDTH_160MHZ:
-               vht_oper->chan_width = IEEE80211_VHT_CHANWIDTH_160MHZ;
-               break;
-       case IEEE80211_VHT_CHANWIDTH_80P80MHZ:
-               vht_oper->chan_width = IEEE80211_VHT_CHANWIDTH_80P80MHZ;
-               break;
-       default:
-               vht_oper->chan_width = IEEE80211_VHT_CHANWIDTH_USE_HT;
-               break;
-       }
-
-       mcs_map_user = GET_DEVRXMCSMAP(adapter->usr_dot_11ac_mcs_support);
-       mcs_map_resp = le16_to_cpu(vht_cap->supp_mcs.rx_mcs_map);
-       mcs_map_result = 0;
-
-       for (nss = 1; nss <= 8; nss++) {
-               mcs_user = GET_VHTNSSMCS(mcs_map_user, nss);
-               mcs_resp = GET_VHTNSSMCS(mcs_map_resp, nss);
-
-               if ((mcs_user == IEEE80211_VHT_MCS_NOT_SUPPORTED) ||
-                   (mcs_resp == IEEE80211_VHT_MCS_NOT_SUPPORTED))
-                       SET_VHTNSSMCS(mcs_map_result, nss,
-                                     IEEE80211_VHT_MCS_NOT_SUPPORTED);
-               else
-                       SET_VHTNSSMCS(mcs_map_result, nss,
-                                     min_t(u16, mcs_user, mcs_resp));
-       }
-
-       vht_oper->basic_mcs_set = cpu_to_le16(mcs_map_result);
-
-       switch (vht_oper->chan_width) {
-       case IEEE80211_VHT_CHANWIDTH_80MHZ:
-               chan_bw = IEEE80211_VHT_CHANWIDTH_80MHZ;
-               break;
-       case IEEE80211_VHT_CHANWIDTH_160MHZ:
-               chan_bw = IEEE80211_VHT_CHANWIDTH_160MHZ;
-               break;
-       case IEEE80211_VHT_CHANWIDTH_80P80MHZ:
-               chan_bw = IEEE80211_VHT_CHANWIDTH_80MHZ;
-               break;
-       default:
-               chan_bw = IEEE80211_VHT_CHANWIDTH_USE_HT;
-               break;
-       }
-       vht_oper->center_freq_seg1_idx =
-                       mwifiex_get_center_freq_index(priv, BAND_AAC,
-                                                     bss_desc->channel,
-                                                     chan_bw);
-
-       return 0;
-}
-
-static void mwifiex_tdls_add_ext_capab(struct mwifiex_private *priv,
-                                      struct sk_buff *skb)
-{
-       struct ieee_types_extcap *extcap;
-
-       extcap = (void *)skb_put(skb, sizeof(struct ieee_types_extcap));
-       extcap->ieee_hdr.element_id = WLAN_EID_EXT_CAPABILITY;
-       extcap->ieee_hdr.len = 8;
-       memset(extcap->ext_capab, 0, 8);
-       extcap->ext_capab[4] |= WLAN_EXT_CAPA5_TDLS_ENABLED;
-       extcap->ext_capab[3] |= WLAN_EXT_CAPA4_TDLS_CHAN_SWITCH;
-
-       if (priv->adapter->is_hw_11ac_capable)
-               extcap->ext_capab[7] |= WLAN_EXT_CAPA8_TDLS_WIDE_BW_ENABLED;
-}
-
-static void mwifiex_tdls_add_qos_capab(struct sk_buff *skb)
-{
-       u8 *pos = (void *)skb_put(skb, 3);
-
-       *pos++ = WLAN_EID_QOS_CAPA;
-       *pos++ = 1;
-       *pos++ = MWIFIEX_TDLS_DEF_QOS_CAPAB;
-}
-
-static void
-mwifiex_tdls_add_wmm_param_ie(struct mwifiex_private *priv, struct sk_buff *skb)
-{
-       struct ieee80211_wmm_param_ie *wmm;
-       u8 ac_vi[] = {0x42, 0x43, 0x5e, 0x00};
-       u8 ac_vo[] = {0x62, 0x32, 0x2f, 0x00};
-       u8 ac_be[] = {0x03, 0xa4, 0x00, 0x00};
-       u8 ac_bk[] = {0x27, 0xa4, 0x00, 0x00};
-
-       wmm = (void *)skb_put(skb, sizeof(*wmm));
-       memset(wmm, 0, sizeof(*wmm));
-
-       wmm->element_id = WLAN_EID_VENDOR_SPECIFIC;
-       wmm->len = sizeof(*wmm) - 2;
-       wmm->oui[0] = 0x00; /* Microsoft OUI 00:50:F2 */
-       wmm->oui[1] = 0x50;
-       wmm->oui[2] = 0xf2;
-       wmm->oui_type = 2; /* WME */
-       wmm->oui_subtype = 1; /* WME param */
-       wmm->version = 1; /* WME ver */
-       wmm->qos_info = 0; /* U-APSD not in use */
-
-       /* use default WMM AC parameters for TDLS link*/
-       memcpy(&wmm->ac[0], ac_be, sizeof(ac_be));
-       memcpy(&wmm->ac[1], ac_bk, sizeof(ac_bk));
-       memcpy(&wmm->ac[2], ac_vi, sizeof(ac_vi));
-       memcpy(&wmm->ac[3], ac_vo, sizeof(ac_vo));
-}
-
-static void
-mwifiex_add_wmm_info_ie(struct mwifiex_private *priv, struct sk_buff *skb,
-                       u8 qosinfo)
-{
-       u8 *buf;
-
-       buf = (void *)skb_put(skb, MWIFIEX_TDLS_WMM_INFO_SIZE +
-                             sizeof(struct ieee_types_header));
-
-       *buf++ = WLAN_EID_VENDOR_SPECIFIC;
-       *buf++ = 7; /* len */
-       *buf++ = 0x00; /* Microsoft OUI 00:50:F2 */
-       *buf++ = 0x50;
-       *buf++ = 0xf2;
-       *buf++ = 2; /* WME */
-       *buf++ = 0; /* WME info */
-       *buf++ = 1; /* WME ver */
-       *buf++ = qosinfo; /* U-APSD no in use */
-}
-
-static int mwifiex_prep_tdls_encap_data(struct mwifiex_private *priv,
-                                       const u8 *peer, u8 action_code,
-                                       u8 dialog_token,
-                                       u16 status_code, struct sk_buff *skb)
-{
-       struct ieee80211_tdls_data *tf;
-       int ret;
-       u16 capab;
-       struct ieee80211_ht_cap *ht_cap;
-       u8 radio, *pos;
-
-       capab = priv->curr_bss_params.bss_descriptor.cap_info_bitmap;
-
-       tf = (void *)skb_put(skb, offsetof(struct ieee80211_tdls_data, u));
-       memcpy(tf->da, peer, ETH_ALEN);
-       memcpy(tf->sa, priv->curr_addr, ETH_ALEN);
-       tf->ether_type = cpu_to_be16(ETH_P_TDLS);
-       tf->payload_type = WLAN_TDLS_SNAP_RFTYPE;
-
-       switch (action_code) {
-       case WLAN_TDLS_SETUP_REQUEST:
-               tf->category = WLAN_CATEGORY_TDLS;
-               tf->action_code = WLAN_TDLS_SETUP_REQUEST;
-               skb_put(skb, sizeof(tf->u.setup_req));
-               tf->u.setup_req.dialog_token = dialog_token;
-               tf->u.setup_req.capability = cpu_to_le16(capab);
-               ret = mwifiex_tdls_append_rates_ie(priv, skb);
-               if (ret) {
-                       dev_kfree_skb_any(skb);
-                       return ret;
-               }
-
-               pos = (void *)skb_put(skb, sizeof(struct ieee80211_ht_cap) + 2);
-               *pos++ = WLAN_EID_HT_CAPABILITY;
-               *pos++ = sizeof(struct ieee80211_ht_cap);
-               ht_cap = (void *)pos;
-               radio = mwifiex_band_to_radio_type(priv->curr_bss_params.band);
-               ret = mwifiex_fill_cap_info(priv, radio, ht_cap);
-               if (ret) {
-                       dev_kfree_skb_any(skb);
-                       return ret;
-               }
-
-               if (priv->adapter->is_hw_11ac_capable) {
-                       ret = mwifiex_tdls_add_vht_capab(priv, skb);
-                       if (ret) {
-                               dev_kfree_skb_any(skb);
-                               return ret;
-                       }
-                       mwifiex_tdls_add_aid(priv, skb);
-               }
-
-               mwifiex_tdls_add_ext_capab(priv, skb);
-               mwifiex_tdls_add_qos_capab(skb);
-               mwifiex_add_wmm_info_ie(priv, skb, 0);
-               break;
-
-       case WLAN_TDLS_SETUP_RESPONSE:
-               tf->category = WLAN_CATEGORY_TDLS;
-               tf->action_code = WLAN_TDLS_SETUP_RESPONSE;
-               skb_put(skb, sizeof(tf->u.setup_resp));
-               tf->u.setup_resp.status_code = cpu_to_le16(status_code);
-               tf->u.setup_resp.dialog_token = dialog_token;
-               tf->u.setup_resp.capability = cpu_to_le16(capab);
-               ret = mwifiex_tdls_append_rates_ie(priv, skb);
-               if (ret) {
-                       dev_kfree_skb_any(skb);
-                       return ret;
-               }
-
-               pos = (void *)skb_put(skb, sizeof(struct ieee80211_ht_cap) + 2);
-               *pos++ = WLAN_EID_HT_CAPABILITY;
-               *pos++ = sizeof(struct ieee80211_ht_cap);
-               ht_cap = (void *)pos;
-               radio = mwifiex_band_to_radio_type(priv->curr_bss_params.band);
-               ret = mwifiex_fill_cap_info(priv, radio, ht_cap);
-               if (ret) {
-                       dev_kfree_skb_any(skb);
-                       return ret;
-               }
-
-               if (priv->adapter->is_hw_11ac_capable) {
-                       ret = mwifiex_tdls_add_vht_capab(priv, skb);
-                       if (ret) {
-                               dev_kfree_skb_any(skb);
-                               return ret;
-                       }
-                       mwifiex_tdls_add_aid(priv, skb);
-               }
-
-               mwifiex_tdls_add_ext_capab(priv, skb);
-               mwifiex_tdls_add_qos_capab(skb);
-               mwifiex_add_wmm_info_ie(priv, skb, 0);
-               break;
-
-       case WLAN_TDLS_SETUP_CONFIRM:
-               tf->category = WLAN_CATEGORY_TDLS;
-               tf->action_code = WLAN_TDLS_SETUP_CONFIRM;
-               skb_put(skb, sizeof(tf->u.setup_cfm));
-               tf->u.setup_cfm.status_code = cpu_to_le16(status_code);
-               tf->u.setup_cfm.dialog_token = dialog_token;
-
-               mwifiex_tdls_add_wmm_param_ie(priv, skb);
-               if (priv->adapter->is_hw_11ac_capable) {
-                       ret = mwifiex_tdls_add_vht_oper(priv, peer, skb);
-                       if (ret) {
-                               dev_kfree_skb_any(skb);
-                               return ret;
-                       }
-                       ret = mwifiex_tdls_add_ht_oper(priv, peer, 1, skb);
-                       if (ret) {
-                               dev_kfree_skb_any(skb);
-                               return ret;
-                       }
-               } else {
-                       ret = mwifiex_tdls_add_ht_oper(priv, peer, 0, skb);
-                       if (ret) {
-                               dev_kfree_skb_any(skb);
-                               return ret;
-                       }
-               }
-               break;
-
-       case WLAN_TDLS_TEARDOWN:
-               tf->category = WLAN_CATEGORY_TDLS;
-               tf->action_code = WLAN_TDLS_TEARDOWN;
-               skb_put(skb, sizeof(tf->u.teardown));
-               tf->u.teardown.reason_code = cpu_to_le16(status_code);
-               break;
-
-       case WLAN_TDLS_DISCOVERY_REQUEST:
-               tf->category = WLAN_CATEGORY_TDLS;
-               tf->action_code = WLAN_TDLS_DISCOVERY_REQUEST;
-               skb_put(skb, sizeof(tf->u.discover_req));
-               tf->u.discover_req.dialog_token = dialog_token;
-               break;
-       default:
-               mwifiex_dbg(priv->adapter, ERROR, "Unknown TDLS frame type.\n");
-               return -EINVAL;
-       }
-
-       return 0;
-}
-
-static void
-mwifiex_tdls_add_link_ie(struct sk_buff *skb, const u8 *src_addr,
-                        const u8 *peer, const u8 *bssid)
-{
-       struct ieee80211_tdls_lnkie *lnkid;
-
-       lnkid = (void *)skb_put(skb, sizeof(struct ieee80211_tdls_lnkie));
-       lnkid->ie_type = WLAN_EID_LINK_ID;
-       lnkid->ie_len = sizeof(struct ieee80211_tdls_lnkie) -
-                       sizeof(struct ieee_types_header);
-
-       memcpy(lnkid->bssid, bssid, ETH_ALEN);
-       memcpy(lnkid->init_sta, src_addr, ETH_ALEN);
-       memcpy(lnkid->resp_sta, peer, ETH_ALEN);
-}
-
-int mwifiex_send_tdls_data_frame(struct mwifiex_private *priv, const u8 *peer,
-                                u8 action_code, u8 dialog_token,
-                                u16 status_code, const u8 *extra_ies,
-                                size_t extra_ies_len)
-{
-       struct sk_buff *skb;
-       struct mwifiex_txinfo *tx_info;
-       int ret;
-       u16 skb_len;
-
-       skb_len = MWIFIEX_MIN_DATA_HEADER_LEN +
-                 max(sizeof(struct ieee80211_mgmt),
-                     sizeof(struct ieee80211_tdls_data)) +
-                 MWIFIEX_MGMT_FRAME_HEADER_SIZE +
-                 MWIFIEX_SUPPORTED_RATES +
-                 3 + /* Qos Info */
-                 sizeof(struct ieee_types_extcap) +
-                 sizeof(struct ieee80211_ht_cap) +
-                 sizeof(struct ieee_types_bss_co_2040) +
-                 sizeof(struct ieee80211_ht_operation) +
-                 sizeof(struct ieee80211_tdls_lnkie) +
-                 sizeof(struct ieee80211_wmm_param_ie) +
-                 extra_ies_len;
-
-       if (priv->adapter->is_hw_11ac_capable)
-               skb_len += sizeof(struct ieee_types_vht_cap) +
-                          sizeof(struct ieee_types_vht_oper) +
-                          sizeof(struct ieee_types_aid);
-
-       skb = dev_alloc_skb(skb_len);
-       if (!skb) {
-               mwifiex_dbg(priv->adapter, ERROR,
-                           "allocate skb failed for management frame\n");
-               return -ENOMEM;
-       }
-       skb_reserve(skb, MWIFIEX_MIN_DATA_HEADER_LEN);
-
-       switch (action_code) {
-       case WLAN_TDLS_SETUP_REQUEST:
-       case WLAN_TDLS_SETUP_CONFIRM:
-       case WLAN_TDLS_TEARDOWN:
-       case WLAN_TDLS_DISCOVERY_REQUEST:
-               ret = mwifiex_prep_tdls_encap_data(priv, peer, action_code,
-                                                  dialog_token, status_code,
-                                                  skb);
-               if (ret) {
-                       dev_kfree_skb_any(skb);
-                       return ret;
-               }
-               if (extra_ies_len)
-                       memcpy(skb_put(skb, extra_ies_len), extra_ies,
-                              extra_ies_len);
-               mwifiex_tdls_add_link_ie(skb, priv->curr_addr, peer,
-                                        priv->cfg_bssid);
-               break;
-       case WLAN_TDLS_SETUP_RESPONSE:
-               ret = mwifiex_prep_tdls_encap_data(priv, peer, action_code,
-                                                  dialog_token, status_code,
-                                                  skb);
-               if (ret) {
-                       dev_kfree_skb_any(skb);
-                       return ret;
-               }
-               if (extra_ies_len)
-                       memcpy(skb_put(skb, extra_ies_len), extra_ies,
-                              extra_ies_len);
-               mwifiex_tdls_add_link_ie(skb, peer, priv->curr_addr,
-                                        priv->cfg_bssid);
-               break;
-       }
-
-       switch (action_code) {
-       case WLAN_TDLS_SETUP_REQUEST:
-       case WLAN_TDLS_SETUP_RESPONSE:
-               skb->priority = MWIFIEX_PRIO_BK;
-               break;
-       default:
-               skb->priority = MWIFIEX_PRIO_VI;
-               break;
-       }
-
-       tx_info = MWIFIEX_SKB_TXCB(skb);
-       memset(tx_info, 0, sizeof(*tx_info));
-       tx_info->bss_num = priv->bss_num;
-       tx_info->bss_type = priv->bss_type;
-
-       __net_timestamp(skb);
-       mwifiex_queue_tx_pkt(priv, skb);
-
-       return 0;
-}
-
-static int
-mwifiex_construct_tdls_action_frame(struct mwifiex_private *priv,
-                                   const u8 *peer,
-                                   u8 action_code, u8 dialog_token,
-                                   u16 status_code, struct sk_buff *skb)
-{
-       struct ieee80211_mgmt *mgmt;
-       u8 bc_addr[] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
-       int ret;
-       u16 capab;
-       struct ieee80211_ht_cap *ht_cap;
-       u8 radio, *pos;
-
-       capab = priv->curr_bss_params.bss_descriptor.cap_info_bitmap;
-
-       mgmt = (void *)skb_put(skb, offsetof(struct ieee80211_mgmt, u));
-
-       memset(mgmt, 0, 24);
-       memcpy(mgmt->da, peer, ETH_ALEN);
-       memcpy(mgmt->sa, priv->curr_addr, ETH_ALEN);
-       memcpy(mgmt->bssid, priv->cfg_bssid, ETH_ALEN);
-       mgmt->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT |
-                                         IEEE80211_STYPE_ACTION);
-
-       /* add address 4 */
-       pos = skb_put(skb, ETH_ALEN);
-
-       switch (action_code) {
-       case WLAN_PUB_ACTION_TDLS_DISCOVER_RES:
-               skb_put(skb, sizeof(mgmt->u.action.u.tdls_discover_resp) + 1);
-               mgmt->u.action.category = WLAN_CATEGORY_PUBLIC;
-               mgmt->u.action.u.tdls_discover_resp.action_code =
-                                             WLAN_PUB_ACTION_TDLS_DISCOVER_RES;
-               mgmt->u.action.u.tdls_discover_resp.dialog_token =
-                                                                  dialog_token;
-               mgmt->u.action.u.tdls_discover_resp.capability =
-                                                            cpu_to_le16(capab);
-               /* move back for addr4 */
-               memmove(pos + ETH_ALEN, &mgmt->u.action.category,
-                       sizeof(mgmt->u.action.u.tdls_discover_resp));
-               /* init address 4 */
-               memcpy(pos, bc_addr, ETH_ALEN);
-
-               ret = mwifiex_tdls_append_rates_ie(priv, skb);
-               if (ret) {
-                       dev_kfree_skb_any(skb);
-                       return ret;
-               }
-
-               pos = (void *)skb_put(skb, sizeof(struct ieee80211_ht_cap) + 2);
-               *pos++ = WLAN_EID_HT_CAPABILITY;
-               *pos++ = sizeof(struct ieee80211_ht_cap);
-               ht_cap = (void *)pos;
-               radio = mwifiex_band_to_radio_type(priv->curr_bss_params.band);
-               ret = mwifiex_fill_cap_info(priv, radio, ht_cap);
-               if (ret) {
-                       dev_kfree_skb_any(skb);
-                       return ret;
-               }
-
-               if (priv->adapter->is_hw_11ac_capable) {
-                       ret = mwifiex_tdls_add_vht_capab(priv, skb);
-                       if (ret) {
-                               dev_kfree_skb_any(skb);
-                               return ret;
-                       }
-                       mwifiex_tdls_add_aid(priv, skb);
-               }
-
-               mwifiex_tdls_add_ext_capab(priv, skb);
-               mwifiex_tdls_add_qos_capab(skb);
-               break;
-       default:
-               mwifiex_dbg(priv->adapter, ERROR, "Unknown TDLS action frame type\n");
-               return -EINVAL;
-       }
-
-       return 0;
-}
-
-int mwifiex_send_tdls_action_frame(struct mwifiex_private *priv, const u8 *peer,
-                                  u8 action_code, u8 dialog_token,
-                                  u16 status_code, const u8 *extra_ies,
-                                  size_t extra_ies_len)
-{
-       struct sk_buff *skb;
-       struct mwifiex_txinfo *tx_info;
-       u8 *pos;
-       u32 pkt_type, tx_control;
-       u16 pkt_len, skb_len;
-
-       skb_len = MWIFIEX_MIN_DATA_HEADER_LEN +
-                 max(sizeof(struct ieee80211_mgmt),
-                     sizeof(struct ieee80211_tdls_data)) +
-                 MWIFIEX_MGMT_FRAME_HEADER_SIZE +
-                 MWIFIEX_SUPPORTED_RATES +
-                 sizeof(struct ieee_types_extcap) +
-                 sizeof(struct ieee80211_ht_cap) +
-                 sizeof(struct ieee_types_bss_co_2040) +
-                 sizeof(struct ieee80211_ht_operation) +
-                 sizeof(struct ieee80211_tdls_lnkie) +
-                 extra_ies_len +
-                 3 + /* Qos Info */
-                 ETH_ALEN; /* Address4 */
-
-       if (priv->adapter->is_hw_11ac_capable)
-               skb_len += sizeof(struct ieee_types_vht_cap) +
-                          sizeof(struct ieee_types_vht_oper) +
-                          sizeof(struct ieee_types_aid);
-
-       skb = dev_alloc_skb(skb_len);
-       if (!skb) {
-               mwifiex_dbg(priv->adapter, ERROR,
-                           "allocate skb failed for management frame\n");
-               return -ENOMEM;
-       }
-
-       skb_reserve(skb, MWIFIEX_MIN_DATA_HEADER_LEN);
-
-       pkt_type = PKT_TYPE_MGMT;
-       tx_control = 0;
-       pos = skb_put(skb, MWIFIEX_MGMT_FRAME_HEADER_SIZE + sizeof(pkt_len));
-       memset(pos, 0, MWIFIEX_MGMT_FRAME_HEADER_SIZE + sizeof(pkt_len));
-       memcpy(pos, &pkt_type, sizeof(pkt_type));
-       memcpy(pos + sizeof(pkt_type), &tx_control, sizeof(tx_control));
-
-       if (mwifiex_construct_tdls_action_frame(priv, peer, action_code,
-                                               dialog_token, status_code,
-                                               skb)) {
-               dev_kfree_skb_any(skb);
-               return -EINVAL;
-       }
-
-       if (extra_ies_len)
-               memcpy(skb_put(skb, extra_ies_len), extra_ies, extra_ies_len);
-
-       /* the TDLS link IE is always added last we are the responder */
-
-       mwifiex_tdls_add_link_ie(skb, peer, priv->curr_addr,
-                                priv->cfg_bssid);
-
-       skb->priority = MWIFIEX_PRIO_VI;
-
-       tx_info = MWIFIEX_SKB_TXCB(skb);
-       memset(tx_info, 0, sizeof(*tx_info));
-       tx_info->bss_num = priv->bss_num;
-       tx_info->bss_type = priv->bss_type;
-       tx_info->flags |= MWIFIEX_BUF_FLAG_TDLS_PKT;
-
-       pkt_len = skb->len - MWIFIEX_MGMT_FRAME_HEADER_SIZE - sizeof(pkt_len);
-       memcpy(skb->data + MWIFIEX_MGMT_FRAME_HEADER_SIZE, &pkt_len,
-              sizeof(pkt_len));
-       __net_timestamp(skb);
-       mwifiex_queue_tx_pkt(priv, skb);
-
-       return 0;
-}
-
-/* This function process tdls action frame from peer.
- * Peer capabilities are stored into station node structure.
- */
-void mwifiex_process_tdls_action_frame(struct mwifiex_private *priv,
-                                      u8 *buf, int len)
-{
-       struct mwifiex_sta_node *sta_ptr;
-       u8 *peer, *pos, *end;
-       u8 i, action, basic;
-       __le16 cap = 0;
-       int ie_len = 0;
-
-       if (len < (sizeof(struct ethhdr) + 3))
-               return;
-       if (*(buf + sizeof(struct ethhdr)) != WLAN_TDLS_SNAP_RFTYPE)
-               return;
-       if (*(buf + sizeof(struct ethhdr) + 1) != WLAN_CATEGORY_TDLS)
-               return;
-
-       peer = buf + ETH_ALEN;
-       action = *(buf + sizeof(struct ethhdr) + 2);
-       mwifiex_dbg(priv->adapter, DATA,
-                   "rx:tdls action: peer=%pM, action=%d\n", peer, action);
-
-       switch (action) {
-       case WLAN_TDLS_SETUP_REQUEST:
-               if (len < (sizeof(struct ethhdr) + TDLS_REQ_FIX_LEN))
-                       return;
-
-               pos = buf + sizeof(struct ethhdr) + 4;
-               /* payload 1+ category 1 + action 1 + dialog 1 */
-               cap = cpu_to_le16(*(u16 *)pos);
-               ie_len = len - sizeof(struct ethhdr) - TDLS_REQ_FIX_LEN;
-               pos += 2;
-               break;
-
-       case WLAN_TDLS_SETUP_RESPONSE:
-               if (len < (sizeof(struct ethhdr) + TDLS_RESP_FIX_LEN))
-                       return;
-               /* payload 1+ category 1 + action 1 + dialog 1 + status code 2*/
-               pos = buf + sizeof(struct ethhdr) + 6;
-               cap = cpu_to_le16(*(u16 *)pos);
-               ie_len = len - sizeof(struct ethhdr) - TDLS_RESP_FIX_LEN;
-               pos += 2;
-               break;
-
-       case WLAN_TDLS_SETUP_CONFIRM:
-               if (len < (sizeof(struct ethhdr) + TDLS_CONFIRM_FIX_LEN))
-                       return;
-               pos = buf + sizeof(struct ethhdr) + TDLS_CONFIRM_FIX_LEN;
-               ie_len = len - sizeof(struct ethhdr) - TDLS_CONFIRM_FIX_LEN;
-               break;
-       default:
-               mwifiex_dbg(priv->adapter, ERROR, "Unknown TDLS frame type.\n");
-               return;
-       }
-
-       sta_ptr = mwifiex_add_sta_entry(priv, peer);
-       if (!sta_ptr)
-               return;
-
-       sta_ptr->tdls_cap.capab = cap;
-
-       for (end = pos + ie_len; pos + 1 < end; pos += 2 + pos[1]) {
-               if (pos + 2 + pos[1] > end)
-                       break;
-
-               switch (*pos) {
-               case WLAN_EID_SUPP_RATES:
-                       sta_ptr->tdls_cap.rates_len = pos[1];
-                       for (i = 0; i < pos[1]; i++)
-                               sta_ptr->tdls_cap.rates[i] = pos[i + 2];
-                       break;
-
-               case WLAN_EID_EXT_SUPP_RATES:
-                       basic = sta_ptr->tdls_cap.rates_len;
-                       for (i = 0; i < pos[1]; i++)
-                               sta_ptr->tdls_cap.rates[basic + i] = pos[i + 2];
-                       sta_ptr->tdls_cap.rates_len += pos[1];
-                       break;
-               case WLAN_EID_HT_CAPABILITY:
-                       memcpy((u8 *)&sta_ptr->tdls_cap.ht_capb, pos,
-                              sizeof(struct ieee80211_ht_cap));
-                       sta_ptr->is_11n_enabled = 1;
-                       break;
-               case WLAN_EID_HT_OPERATION:
-                       memcpy(&sta_ptr->tdls_cap.ht_oper, pos,
-                              sizeof(struct ieee80211_ht_operation));
-                       break;
-               case WLAN_EID_BSS_COEX_2040:
-                       sta_ptr->tdls_cap.coex_2040 = pos[2];
-                       break;
-               case WLAN_EID_EXT_CAPABILITY:
-                       memcpy((u8 *)&sta_ptr->tdls_cap.extcap, pos,
-                              sizeof(struct ieee_types_header) +
-                              min_t(u8, pos[1], 8));
-                       break;
-               case WLAN_EID_RSN:
-                       memcpy((u8 *)&sta_ptr->tdls_cap.rsn_ie, pos,
-                              sizeof(struct ieee_types_header) +
-                              min_t(u8, pos[1], IEEE_MAX_IE_SIZE -
-                                    sizeof(struct ieee_types_header)));
-                       break;
-               case WLAN_EID_QOS_CAPA:
-                       sta_ptr->tdls_cap.qos_info = pos[2];
-                       break;
-               case WLAN_EID_VHT_OPERATION:
-                       if (priv->adapter->is_hw_11ac_capable)
-                               memcpy(&sta_ptr->tdls_cap.vhtoper, pos,
-                                      sizeof(struct ieee80211_vht_operation));
-                       break;
-               case WLAN_EID_VHT_CAPABILITY:
-                       if (priv->adapter->is_hw_11ac_capable) {
-                               memcpy((u8 *)&sta_ptr->tdls_cap.vhtcap, pos,
-                                      sizeof(struct ieee80211_vht_cap));
-                               sta_ptr->is_11ac_enabled = 1;
-                       }
-                       break;
-               case WLAN_EID_AID:
-                       if (priv->adapter->is_hw_11ac_capable)
-                               sta_ptr->tdls_cap.aid =
-                                             le16_to_cpu(*(__le16 *)(pos + 2));
-               default:
-                       break;
-               }
-       }
-
-       return;
-}
-
-static int
-mwifiex_tdls_process_config_link(struct mwifiex_private *priv, const u8 *peer)
-{
-       struct mwifiex_sta_node *sta_ptr;
-       struct mwifiex_ds_tdls_oper tdls_oper;
-
-       memset(&tdls_oper, 0, sizeof(struct mwifiex_ds_tdls_oper));
-       sta_ptr = mwifiex_get_sta_entry(priv, peer);
-
-       if (!sta_ptr || sta_ptr->tdls_status == TDLS_SETUP_FAILURE) {
-               mwifiex_dbg(priv->adapter, ERROR,
-                           "link absent for peer %pM; cannot config\n", peer);
-               return -EINVAL;
-       }
-
-       memcpy(&tdls_oper.peer_mac, peer, ETH_ALEN);
-       tdls_oper.tdls_action = MWIFIEX_TDLS_CONFIG_LINK;
-       return mwifiex_send_cmd(priv, HostCmd_CMD_TDLS_OPER,
-                               HostCmd_ACT_GEN_SET, 0, &tdls_oper, true);
-}
-
-static int
-mwifiex_tdls_process_create_link(struct mwifiex_private *priv, const u8 *peer)
-{
-       struct mwifiex_sta_node *sta_ptr;
-       struct mwifiex_ds_tdls_oper tdls_oper;
-
-       memset(&tdls_oper, 0, sizeof(struct mwifiex_ds_tdls_oper));
-       sta_ptr = mwifiex_get_sta_entry(priv, peer);
-
-       if (sta_ptr && sta_ptr->tdls_status == TDLS_SETUP_INPROGRESS) {
-               mwifiex_dbg(priv->adapter, WARN,
-                           "Setup already in progress for peer %pM\n", peer);
-               return 0;
-       }
-
-       sta_ptr = mwifiex_add_sta_entry(priv, peer);
-       if (!sta_ptr)
-               return -ENOMEM;
-
-       sta_ptr->tdls_status = TDLS_SETUP_INPROGRESS;
-       mwifiex_hold_tdls_packets(priv, peer);
-       memcpy(&tdls_oper.peer_mac, peer, ETH_ALEN);
-       tdls_oper.tdls_action = MWIFIEX_TDLS_CREATE_LINK;
-       return mwifiex_send_cmd(priv, HostCmd_CMD_TDLS_OPER,
-                               HostCmd_ACT_GEN_SET, 0, &tdls_oper, true);
-}
-
-static int
-mwifiex_tdls_process_disable_link(struct mwifiex_private *priv, const u8 *peer)
-{
-       struct mwifiex_sta_node *sta_ptr;
-       struct mwifiex_ds_tdls_oper tdls_oper;
-       unsigned long flags;
-
-       memset(&tdls_oper, 0, sizeof(struct mwifiex_ds_tdls_oper));
-       sta_ptr = mwifiex_get_sta_entry(priv, peer);
-
-       if (sta_ptr) {
-               if (sta_ptr->is_11n_enabled) {
-                       mwifiex_11n_cleanup_reorder_tbl(priv);
-                       spin_lock_irqsave(&priv->wmm.ra_list_spinlock,
-                                         flags);
-                       mwifiex_11n_delete_all_tx_ba_stream_tbl(priv);
-                       spin_unlock_irqrestore(&priv->wmm.ra_list_spinlock,
-                                              flags);
-               }
-               mwifiex_del_sta_entry(priv, peer);
-       }
-
-       mwifiex_restore_tdls_packets(priv, peer, TDLS_LINK_TEARDOWN);
-       mwifiex_auto_tdls_update_peer_status(priv, peer, TDLS_NOT_SETUP);
-       memcpy(&tdls_oper.peer_mac, peer, ETH_ALEN);
-       tdls_oper.tdls_action = MWIFIEX_TDLS_DISABLE_LINK;
-       return mwifiex_send_cmd(priv, HostCmd_CMD_TDLS_OPER,
-                               HostCmd_ACT_GEN_SET, 0, &tdls_oper, true);
-}
-
-static int
-mwifiex_tdls_process_enable_link(struct mwifiex_private *priv, const u8 *peer)
-{
-       struct mwifiex_sta_node *sta_ptr;
-       struct ieee80211_mcs_info mcs;
-       unsigned long flags;
-       int i;
-
-       sta_ptr = mwifiex_get_sta_entry(priv, peer);
-
-       if (sta_ptr && (sta_ptr->tdls_status != TDLS_SETUP_FAILURE)) {
-               mwifiex_dbg(priv->adapter, MSG,
-                           "tdls: enable link %pM success\n", peer);
-
-               sta_ptr->tdls_status = TDLS_SETUP_COMPLETE;
-
-               mcs = sta_ptr->tdls_cap.ht_capb.mcs;
-               if (mcs.rx_mask[0] != 0xff)
-                       sta_ptr->is_11n_enabled = true;
-               if (sta_ptr->is_11n_enabled) {
-                       if (le16_to_cpu(sta_ptr->tdls_cap.ht_capb.cap_info) &
-                           IEEE80211_HT_CAP_MAX_AMSDU)
-                               sta_ptr->max_amsdu =
-                                       MWIFIEX_TX_DATA_BUF_SIZE_8K;
-                       else
-                               sta_ptr->max_amsdu =
-                                       MWIFIEX_TX_DATA_BUF_SIZE_4K;
-
-                       for (i = 0; i < MAX_NUM_TID; i++)
-                               sta_ptr->ampdu_sta[i] =
-                                             priv->aggr_prio_tbl[i].ampdu_user;
-               } else {
-                       for (i = 0; i < MAX_NUM_TID; i++)
-                               sta_ptr->ampdu_sta[i] = BA_STREAM_NOT_ALLOWED;
-               }
-               if (sta_ptr->tdls_cap.extcap.ext_capab[3] &
-                   WLAN_EXT_CAPA4_TDLS_CHAN_SWITCH) {
-                       mwifiex_config_tdls_enable(priv);
-                       mwifiex_config_tdls_cs_params(priv);
-               }
-
-               memset(sta_ptr->rx_seq, 0xff, sizeof(sta_ptr->rx_seq));
-               mwifiex_restore_tdls_packets(priv, peer, TDLS_SETUP_COMPLETE);
-               mwifiex_auto_tdls_update_peer_status(priv, peer,
-                                                    TDLS_SETUP_COMPLETE);
-       } else {
-               mwifiex_dbg(priv->adapter, ERROR,
-                           "tdls: enable link %pM failed\n", peer);
-               if (sta_ptr) {
-                       mwifiex_11n_cleanup_reorder_tbl(priv);
-                       spin_lock_irqsave(&priv->wmm.ra_list_spinlock,
-                                         flags);
-                       mwifiex_11n_delete_all_tx_ba_stream_tbl(priv);
-                       spin_unlock_irqrestore(&priv->wmm.ra_list_spinlock,
-                                              flags);
-                       mwifiex_del_sta_entry(priv, peer);
-               }
-               mwifiex_restore_tdls_packets(priv, peer, TDLS_LINK_TEARDOWN);
-               mwifiex_auto_tdls_update_peer_status(priv, peer,
-                                                    TDLS_NOT_SETUP);
-
-               return -1;
-       }
-
-       return 0;
-}
-
-int mwifiex_tdls_oper(struct mwifiex_private *priv, const u8 *peer, u8 action)
-{
-       switch (action) {
-       case MWIFIEX_TDLS_ENABLE_LINK:
-               return mwifiex_tdls_process_enable_link(priv, peer);
-       case MWIFIEX_TDLS_DISABLE_LINK:
-               return mwifiex_tdls_process_disable_link(priv, peer);
-       case MWIFIEX_TDLS_CREATE_LINK:
-               return mwifiex_tdls_process_create_link(priv, peer);
-       case MWIFIEX_TDLS_CONFIG_LINK:
-               return mwifiex_tdls_process_config_link(priv, peer);
-       }
-       return 0;
-}
-
-int mwifiex_get_tdls_link_status(struct mwifiex_private *priv, const u8 *mac)
-{
-       struct mwifiex_sta_node *sta_ptr;
-
-       sta_ptr = mwifiex_get_sta_entry(priv, mac);
-       if (sta_ptr)
-               return sta_ptr->tdls_status;
-
-       return TDLS_NOT_SETUP;
-}
-
-int mwifiex_get_tdls_list(struct mwifiex_private *priv,
-                         struct tdls_peer_info *buf)
-{
-       struct mwifiex_sta_node *sta_ptr;
-       struct tdls_peer_info *peer = buf;
-       int count = 0;
-       unsigned long flags;
-
-       if (!ISSUPP_TDLS_ENABLED(priv->adapter->fw_cap_info))
-               return 0;
-
-       /* make sure we are in station mode and connected */
-       if (!(priv->bss_type == MWIFIEX_BSS_TYPE_STA && priv->media_connected))
-               return 0;
-
-       spin_lock_irqsave(&priv->sta_list_spinlock, flags);
-       list_for_each_entry(sta_ptr, &priv->sta_list, list) {
-               if (mwifiex_is_tdls_link_setup(sta_ptr->tdls_status)) {
-                       ether_addr_copy(peer->peer_addr, sta_ptr->mac_addr);
-                       peer++;
-                       count++;
-                       if (count >= MWIFIEX_MAX_TDLS_PEER_SUPPORTED)
-                               break;
-               }
-       }
-       spin_unlock_irqrestore(&priv->sta_list_spinlock, flags);
-
-       return count;
-}
-
-void mwifiex_disable_all_tdls_links(struct mwifiex_private *priv)
-{
-       struct mwifiex_sta_node *sta_ptr;
-       struct mwifiex_ds_tdls_oper tdls_oper;
-       unsigned long flags;
-
-       if (list_empty(&priv->sta_list))
-               return;
-
-       list_for_each_entry(sta_ptr, &priv->sta_list, list) {
-               memset(&tdls_oper, 0, sizeof(struct mwifiex_ds_tdls_oper));
-
-               if (sta_ptr->is_11n_enabled) {
-                       mwifiex_11n_cleanup_reorder_tbl(priv);
-                       spin_lock_irqsave(&priv->wmm.ra_list_spinlock,
-                                         flags);
-                       mwifiex_11n_delete_all_tx_ba_stream_tbl(priv);
-                       spin_unlock_irqrestore(&priv->wmm.ra_list_spinlock,
-                                              flags);
-               }
-
-               mwifiex_restore_tdls_packets(priv, sta_ptr->mac_addr,
-                                            TDLS_LINK_TEARDOWN);
-               memcpy(&tdls_oper.peer_mac, sta_ptr->mac_addr, ETH_ALEN);
-               tdls_oper.tdls_action = MWIFIEX_TDLS_DISABLE_LINK;
-               if (mwifiex_send_cmd(priv, HostCmd_CMD_TDLS_OPER,
-                                    HostCmd_ACT_GEN_SET, 0, &tdls_oper, false))
-                       mwifiex_dbg(priv->adapter, ERROR,
-                                   "Disable link failed for TDLS peer %pM",
-                                   sta_ptr->mac_addr);
-       }
-
-       mwifiex_del_all_sta_list(priv);
-}
-
-int mwifiex_tdls_check_tx(struct mwifiex_private *priv, struct sk_buff *skb)
-{
-       struct mwifiex_auto_tdls_peer *peer;
-       unsigned long flags;
-       u8 mac[ETH_ALEN];
-
-       ether_addr_copy(mac, skb->data);
-
-       spin_lock_irqsave(&priv->auto_tdls_lock, flags);
-       list_for_each_entry(peer, &priv->auto_tdls_list, list) {
-               if (!memcmp(mac, peer->mac_addr, ETH_ALEN)) {
-                       if (peer->rssi <= MWIFIEX_TDLS_RSSI_HIGH &&
-                           peer->tdls_status == TDLS_NOT_SETUP &&
-                           (peer->failure_count <
-                            MWIFIEX_TDLS_MAX_FAIL_COUNT)) {
-                               peer->tdls_status = TDLS_SETUP_INPROGRESS;
-                               mwifiex_dbg(priv->adapter, INFO,
-                                           "setup TDLS link, peer=%pM rssi=%d\n",
-                                           peer->mac_addr, peer->rssi);
-
-                               cfg80211_tdls_oper_request(priv->netdev,
-                                                          peer->mac_addr,
-                                                          NL80211_TDLS_SETUP,
-                                                          0, GFP_ATOMIC);
-                               peer->do_setup = false;
-                               priv->check_tdls_tx = false;
-                       } else if (peer->failure_count <
-                                  MWIFIEX_TDLS_MAX_FAIL_COUNT &&
-                                  peer->do_discover) {
-                               mwifiex_send_tdls_data_frame(priv,
-                                                            peer->mac_addr,
-                                                   WLAN_TDLS_DISCOVERY_REQUEST,
-                                                            1, 0, NULL, 0);
-                               peer->do_discover = false;
-                       }
-               }
-       }
-       spin_unlock_irqrestore(&priv->auto_tdls_lock, flags);
-
-       return 0;
-}
-
-void mwifiex_flush_auto_tdls_list(struct mwifiex_private *priv)
-{
-       struct mwifiex_auto_tdls_peer *peer, *tmp_node;
-       unsigned long flags;
-
-       spin_lock_irqsave(&priv->auto_tdls_lock, flags);
-       list_for_each_entry_safe(peer, tmp_node, &priv->auto_tdls_list, list) {
-               list_del(&peer->list);
-               kfree(peer);
-       }
-
-       INIT_LIST_HEAD(&priv->auto_tdls_list);
-       spin_unlock_irqrestore(&priv->auto_tdls_lock, flags);
-       priv->check_tdls_tx = false;
-}
-
-void mwifiex_add_auto_tdls_peer(struct mwifiex_private *priv, const u8 *mac)
-{
-       struct mwifiex_auto_tdls_peer *tdls_peer;
-       unsigned long flags;
-
-       if (!priv->adapter->auto_tdls)
-               return;
-
-       spin_lock_irqsave(&priv->auto_tdls_lock, flags);
-       list_for_each_entry(tdls_peer, &priv->auto_tdls_list, list) {
-               if (!memcmp(tdls_peer->mac_addr, mac, ETH_ALEN)) {
-                       tdls_peer->tdls_status = TDLS_SETUP_INPROGRESS;
-                       tdls_peer->rssi_jiffies = jiffies;
-                       spin_unlock_irqrestore(&priv->auto_tdls_lock, flags);
-                       return;
-               }
-       }
-
-       /* create new TDLS peer */
-       tdls_peer = kzalloc(sizeof(*tdls_peer), GFP_ATOMIC);
-       if (tdls_peer) {
-               ether_addr_copy(tdls_peer->mac_addr, mac);
-               tdls_peer->tdls_status = TDLS_SETUP_INPROGRESS;
-               tdls_peer->rssi_jiffies = jiffies;
-               INIT_LIST_HEAD(&tdls_peer->list);
-               list_add_tail(&tdls_peer->list, &priv->auto_tdls_list);
-               mwifiex_dbg(priv->adapter, INFO,
-                           "Add auto TDLS peer= %pM to list\n", mac);
-       }
-
-       spin_unlock_irqrestore(&priv->auto_tdls_lock, flags);
-}
-
-void mwifiex_auto_tdls_update_peer_status(struct mwifiex_private *priv,
-                                         const u8 *mac, u8 link_status)
-{
-       struct mwifiex_auto_tdls_peer *peer;
-       unsigned long flags;
-
-       if (!priv->adapter->auto_tdls)
-               return;
-
-       spin_lock_irqsave(&priv->auto_tdls_lock, flags);
-       list_for_each_entry(peer, &priv->auto_tdls_list, list) {
-               if (!memcmp(peer->mac_addr, mac, ETH_ALEN)) {
-                       if ((link_status == TDLS_NOT_SETUP) &&
-                           (peer->tdls_status == TDLS_SETUP_INPROGRESS))
-                               peer->failure_count++;
-                       else if (mwifiex_is_tdls_link_setup(link_status))
-                               peer->failure_count = 0;
-
-                       peer->tdls_status = link_status;
-                       break;
-               }
-       }
-       spin_unlock_irqrestore(&priv->auto_tdls_lock, flags);
-}
-
-void mwifiex_auto_tdls_update_peer_signal(struct mwifiex_private *priv,
-                                         u8 *mac, s8 snr, s8 nflr)
-{
-       struct mwifiex_auto_tdls_peer *peer;
-       unsigned long flags;
-
-       if (!priv->adapter->auto_tdls)
-               return;
-
-       spin_lock_irqsave(&priv->auto_tdls_lock, flags);
-       list_for_each_entry(peer, &priv->auto_tdls_list, list) {
-               if (!memcmp(peer->mac_addr, mac, ETH_ALEN)) {
-                       peer->rssi = nflr - snr;
-                       peer->rssi_jiffies = jiffies;
-                       break;
-               }
-       }
-       spin_unlock_irqrestore(&priv->auto_tdls_lock, flags);
-}
-
-void mwifiex_check_auto_tdls(unsigned long context)
-{
-       struct mwifiex_private *priv = (struct mwifiex_private *)context;
-       struct mwifiex_auto_tdls_peer *tdls_peer;
-       unsigned long flags;
-       u16 reason = WLAN_REASON_TDLS_TEARDOWN_UNSPECIFIED;
-
-       if (WARN_ON_ONCE(!priv || !priv->adapter)) {
-               pr_err("mwifiex: %s: adapter or private structure is NULL\n",
-                      __func__);
-               return;
-       }
-
-       if (unlikely(!priv->adapter->auto_tdls))
-               return;
-
-       if (!priv->auto_tdls_timer_active) {
-               mwifiex_dbg(priv->adapter, INFO,
-                           "auto TDLS timer inactive; return");
-               return;
-       }
-
-       priv->check_tdls_tx = false;
-
-       if (list_empty(&priv->auto_tdls_list)) {
-               mod_timer(&priv->auto_tdls_timer,
-                         jiffies +
-                         msecs_to_jiffies(MWIFIEX_TIMER_10S));
-               return;
-       }
-
-       spin_lock_irqsave(&priv->auto_tdls_lock, flags);
-       list_for_each_entry(tdls_peer, &priv->auto_tdls_list, list) {
-               if ((jiffies - tdls_peer->rssi_jiffies) >
-                   (MWIFIEX_AUTO_TDLS_IDLE_TIME * HZ)) {
-                       tdls_peer->rssi = 0;
-                       tdls_peer->do_discover = true;
-                       priv->check_tdls_tx = true;
-               }
-
-               if (((tdls_peer->rssi >= MWIFIEX_TDLS_RSSI_LOW) ||
-                    !tdls_peer->rssi) &&
-                   mwifiex_is_tdls_link_setup(tdls_peer->tdls_status)) {
-                       tdls_peer->tdls_status = TDLS_LINK_TEARDOWN;
-                       mwifiex_dbg(priv->adapter, MSG,
-                                   "teardown TDLS link,peer=%pM rssi=%d\n",
-                                   tdls_peer->mac_addr, -tdls_peer->rssi);
-                       tdls_peer->do_discover = true;
-                       priv->check_tdls_tx = true;
-                       cfg80211_tdls_oper_request(priv->netdev,
-                                                  tdls_peer->mac_addr,
-                                                  NL80211_TDLS_TEARDOWN,
-                                                  reason, GFP_ATOMIC);
-               } else if (tdls_peer->rssi &&
-                          tdls_peer->rssi <= MWIFIEX_TDLS_RSSI_HIGH &&
-                          tdls_peer->tdls_status == TDLS_NOT_SETUP &&
-                          tdls_peer->failure_count <
-                          MWIFIEX_TDLS_MAX_FAIL_COUNT) {
-                               priv->check_tdls_tx = true;
-                               tdls_peer->do_setup = true;
-                               mwifiex_dbg(priv->adapter, INFO,
-                                           "check TDLS with peer=%pM\t"
-                                           "rssi=%d\n", tdls_peer->mac_addr,
-                                           tdls_peer->rssi);
-               }
-       }
-       spin_unlock_irqrestore(&priv->auto_tdls_lock, flags);
-
-       mod_timer(&priv->auto_tdls_timer,
-                 jiffies + msecs_to_jiffies(MWIFIEX_TIMER_10S));
-}
-
-void mwifiex_setup_auto_tdls_timer(struct mwifiex_private *priv)
-{
-       setup_timer(&priv->auto_tdls_timer, mwifiex_check_auto_tdls,
-                   (unsigned long)priv);
-       priv->auto_tdls_timer_active = true;
-       mod_timer(&priv->auto_tdls_timer,
-                 jiffies + msecs_to_jiffies(MWIFIEX_TIMER_10S));
-}
-
-void mwifiex_clean_auto_tdls(struct mwifiex_private *priv)
-{
-       if (ISSUPP_TDLS_ENABLED(priv->adapter->fw_cap_info) &&
-           priv->adapter->auto_tdls &&
-           priv->bss_type == MWIFIEX_BSS_TYPE_STA) {
-               priv->auto_tdls_timer_active = false;
-               del_timer(&priv->auto_tdls_timer);
-               mwifiex_flush_auto_tdls_list(priv);
-       }
-}
-
-static int mwifiex_config_tdls(struct mwifiex_private *priv, u8 enable)
-{
-       struct mwifiex_tdls_config config;
-
-       config.enable = cpu_to_le16(enable);
-       return mwifiex_send_cmd(priv, HostCmd_CMD_TDLS_CONFIG,
-                               ACT_TDLS_CS_ENABLE_CONFIG, 0, &config, true);
-}
-
-int mwifiex_config_tdls_enable(struct mwifiex_private *priv)
-{
-       return mwifiex_config_tdls(priv, true);
-}
-
-int mwifiex_config_tdls_disable(struct mwifiex_private *priv)
-{
-       return mwifiex_config_tdls(priv, false);
-}
-
-int mwifiex_config_tdls_cs_params(struct mwifiex_private *priv)
-{
-       struct mwifiex_tdls_config_cs_params config_tdls_cs_params;
-
-       config_tdls_cs_params.unit_time = MWIFIEX_DEF_CS_UNIT_TIME;
-       config_tdls_cs_params.thr_otherlink = MWIFIEX_DEF_CS_THR_OTHERLINK;
-       config_tdls_cs_params.thr_directlink = MWIFIEX_DEF_THR_DIRECTLINK;
-
-       return mwifiex_send_cmd(priv, HostCmd_CMD_TDLS_CONFIG,
-                               ACT_TDLS_CS_PARAMS, 0,
-                               &config_tdls_cs_params, true);
-}
-
-int mwifiex_stop_tdls_cs(struct mwifiex_private *priv, const u8 *peer_mac)
-{
-       struct mwifiex_tdls_stop_cs_params stop_tdls_cs_params;
-
-       ether_addr_copy(stop_tdls_cs_params.peer_mac, peer_mac);
-
-       return mwifiex_send_cmd(priv, HostCmd_CMD_TDLS_CONFIG,
-                               ACT_TDLS_CS_STOP, 0,
-                               &stop_tdls_cs_params, true);
-}
-
-int mwifiex_start_tdls_cs(struct mwifiex_private *priv, const u8 *peer_mac,
-                         u8 primary_chan, u8 second_chan_offset, u8 band)
-{
-       struct mwifiex_tdls_init_cs_params start_tdls_cs_params;
-
-       ether_addr_copy(start_tdls_cs_params.peer_mac, peer_mac);
-       start_tdls_cs_params.primary_chan = primary_chan;
-       start_tdls_cs_params.second_chan_offset = second_chan_offset;
-       start_tdls_cs_params.band = band;
-
-       start_tdls_cs_params.switch_time = cpu_to_le16(MWIFIEX_DEF_CS_TIME);
-       start_tdls_cs_params.switch_timeout =
-                                       cpu_to_le16(MWIFIEX_DEF_CS_TIMEOUT);
-       start_tdls_cs_params.reg_class = MWIFIEX_DEF_CS_REG_CLASS;
-       start_tdls_cs_params.periodicity = MWIFIEX_DEF_CS_PERIODICITY;
-
-       return mwifiex_send_cmd(priv, HostCmd_CMD_TDLS_CONFIG,
-                               ACT_TDLS_CS_INIT, 0,
-                               &start_tdls_cs_params, true);
-}
diff --git a/drivers/net/wireless/mwifiex/txrx.c b/drivers/net/wireless/mwifiex/txrx.c
deleted file mode 100644 (file)
index bf6182b..0000000
+++ /dev/null
@@ -1,386 +0,0 @@
-/*
- * Marvell Wireless LAN device driver: generic TX/RX data handling
- *
- * Copyright (C) 2011-2014, Marvell International Ltd.
- *
- * This software file (the "File") is distributed by Marvell International
- * Ltd. under the terms of the GNU General Public License Version 2, June 1991
- * (the "License").  You may use, redistribute and/or modify this File in
- * accordance with the terms and conditions of the License, a copy of which
- * is available by writing to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the
- * worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
- *
- * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
- * ARE EXPRESSLY DISCLAIMED.  The License provides additional details about
- * this warranty disclaimer.
- */
-
-#include "decl.h"
-#include "ioctl.h"
-#include "util.h"
-#include "fw.h"
-#include "main.h"
-#include "wmm.h"
-
-/*
- * This function processes the received buffer.
- *
- * Main responsibility of this function is to parse the RxPD to
- * identify the correct interface this packet is headed for and
- * forwarding it to the associated handling function, where the
- * packet will be further processed and sent to kernel/upper layer
- * if required.
- */
-int mwifiex_handle_rx_packet(struct mwifiex_adapter *adapter,
-                            struct sk_buff *skb)
-{
-       struct mwifiex_private *priv =
-               mwifiex_get_priv(adapter, MWIFIEX_BSS_ROLE_ANY);
-       struct rxpd *local_rx_pd;
-       struct mwifiex_rxinfo *rx_info = MWIFIEX_SKB_RXCB(skb);
-       int ret;
-
-       local_rx_pd = (struct rxpd *) (skb->data);
-       /* Get the BSS number from rxpd, get corresponding priv */
-       priv = mwifiex_get_priv_by_id(adapter, local_rx_pd->bss_num &
-                                     BSS_NUM_MASK, local_rx_pd->bss_type);
-       if (!priv)
-               priv = mwifiex_get_priv(adapter, MWIFIEX_BSS_ROLE_ANY);
-
-       if (!priv) {
-               mwifiex_dbg(adapter, ERROR,
-                           "data: priv not found. Drop RX packet\n");
-               dev_kfree_skb_any(skb);
-               return -1;
-       }
-
-       mwifiex_dbg_dump(adapter, DAT_D, "rx pkt:", skb->data,
-                        min_t(size_t, skb->len, DEBUG_DUMP_DATA_MAX_LEN));
-
-       memset(rx_info, 0, sizeof(*rx_info));
-       rx_info->bss_num = priv->bss_num;
-       rx_info->bss_type = priv->bss_type;
-
-       if (priv->bss_role == MWIFIEX_BSS_ROLE_UAP)
-               ret = mwifiex_process_uap_rx_packet(priv, skb);
-       else
-               ret = mwifiex_process_sta_rx_packet(priv, skb);
-
-       return ret;
-}
-EXPORT_SYMBOL_GPL(mwifiex_handle_rx_packet);
-
-/*
- * This function sends a packet to device.
- *
- * It processes the packet to add the TxPD, checks condition and
- * sends the processed packet to firmware for transmission.
- *
- * On successful completion, the function calls the completion callback
- * and logs the time.
- */
-int mwifiex_process_tx(struct mwifiex_private *priv, struct sk_buff *skb,
-                      struct mwifiex_tx_param *tx_param)
-{
-       int hroom, ret = -1;
-       struct mwifiex_adapter *adapter = priv->adapter;
-       u8 *head_ptr;
-       struct txpd *local_tx_pd = NULL;
-       struct mwifiex_sta_node *dest_node;
-       struct ethhdr *hdr = (void *)skb->data;
-
-       hroom = (adapter->iface_type == MWIFIEX_USB) ? 0 : INTF_HEADER_LEN;
-
-       if (priv->bss_role == MWIFIEX_BSS_ROLE_UAP) {
-               dest_node = mwifiex_get_sta_entry(priv, hdr->h_dest);
-               if (dest_node) {
-                       dest_node->stats.tx_bytes += skb->len;
-                       dest_node->stats.tx_packets++;
-               }
-
-               head_ptr = mwifiex_process_uap_txpd(priv, skb);
-       } else {
-               head_ptr = mwifiex_process_sta_txpd(priv, skb);
-       }
-
-       if ((adapter->data_sent || adapter->tx_lock_flag) && head_ptr) {
-               skb_queue_tail(&adapter->tx_data_q, skb);
-               atomic_inc(&adapter->tx_queued);
-               return 0;
-       }
-
-       if (head_ptr) {
-               if (GET_BSS_ROLE(priv) == MWIFIEX_BSS_ROLE_STA)
-                       local_tx_pd = (struct txpd *)(head_ptr + hroom);
-               if (adapter->iface_type == MWIFIEX_USB) {
-                       ret = adapter->if_ops.host_to_card(adapter,
-                                                          priv->usb_port,
-                                                          skb, NULL);
-               } else {
-                       ret = adapter->if_ops.host_to_card(adapter,
-                                                          MWIFIEX_TYPE_DATA,
-                                                          skb, tx_param);
-               }
-       }
-       mwifiex_dbg_dump(adapter, DAT_D, "tx pkt:", skb->data,
-                        min_t(size_t, skb->len, DEBUG_DUMP_DATA_MAX_LEN));
-
-       switch (ret) {
-       case -ENOSR:
-               mwifiex_dbg(adapter, DATA, "data: -ENOSR is returned\n");
-               break;
-       case -EBUSY:
-               if ((GET_BSS_ROLE(priv) == MWIFIEX_BSS_ROLE_STA) &&
-                   (adapter->pps_uapsd_mode) && (adapter->tx_lock_flag)) {
-                               priv->adapter->tx_lock_flag = false;
-                               if (local_tx_pd)
-                                       local_tx_pd->flags = 0;
-               }
-               mwifiex_dbg(adapter, ERROR, "data: -EBUSY is returned\n");
-               break;
-       case -1:
-               mwifiex_dbg(adapter, ERROR,
-                           "mwifiex_write_data_async failed: 0x%X\n",
-                           ret);
-               adapter->dbg.num_tx_host_to_card_failure++;
-               mwifiex_write_data_complete(adapter, skb, 0, ret);
-               break;
-       case -EINPROGRESS:
-               break;
-       case 0:
-               mwifiex_write_data_complete(adapter, skb, 0, ret);
-               break;
-       default:
-               break;
-       }
-
-       return ret;
-}
-
-static int mwifiex_host_to_card(struct mwifiex_adapter *adapter,
-                               struct sk_buff *skb,
-                               struct mwifiex_tx_param *tx_param)
-{
-       struct txpd *local_tx_pd = NULL;
-       u8 *head_ptr = skb->data;
-       int ret = 0;
-       struct mwifiex_private *priv;
-       struct mwifiex_txinfo *tx_info;
-
-       tx_info = MWIFIEX_SKB_TXCB(skb);
-       priv = mwifiex_get_priv_by_id(adapter, tx_info->bss_num,
-                                     tx_info->bss_type);
-       if (!priv) {
-               mwifiex_dbg(adapter, ERROR,
-                           "data: priv not found. Drop TX packet\n");
-               adapter->dbg.num_tx_host_to_card_failure++;
-               mwifiex_write_data_complete(adapter, skb, 0, 0);
-               return ret;
-       }
-       if (GET_BSS_ROLE(priv) == MWIFIEX_BSS_ROLE_STA) {
-               if (adapter->iface_type == MWIFIEX_USB)
-                       local_tx_pd = (struct txpd *)head_ptr;
-               else
-                       local_tx_pd = (struct txpd *) (head_ptr +
-                               INTF_HEADER_LEN);
-       }
-
-       if (adapter->iface_type == MWIFIEX_USB) {
-               ret = adapter->if_ops.host_to_card(adapter,
-                                                  priv->usb_port,
-                                                  skb, NULL);
-       } else {
-               ret = adapter->if_ops.host_to_card(adapter,
-                                                  MWIFIEX_TYPE_DATA,
-                                                  skb, tx_param);
-       }
-       switch (ret) {
-       case -ENOSR:
-               mwifiex_dbg(adapter, ERROR, "data: -ENOSR is returned\n");
-               break;
-       case -EBUSY:
-               if ((GET_BSS_ROLE(priv) == MWIFIEX_BSS_ROLE_STA) &&
-                   (adapter->pps_uapsd_mode) &&
-                   (adapter->tx_lock_flag)) {
-                       priv->adapter->tx_lock_flag = false;
-                       if (local_tx_pd)
-                               local_tx_pd->flags = 0;
-               }
-               skb_queue_head(&adapter->tx_data_q, skb);
-               if (tx_info->flags & MWIFIEX_BUF_FLAG_AGGR_PKT)
-                       atomic_add(tx_info->aggr_num, &adapter->tx_queued);
-               else
-                       atomic_inc(&adapter->tx_queued);
-               mwifiex_dbg(adapter, ERROR, "data: -EBUSY is returned\n");
-               break;
-       case -1:
-               mwifiex_dbg(adapter, ERROR,
-                           "mwifiex_write_data_async failed: 0x%X\n", ret);
-               adapter->dbg.num_tx_host_to_card_failure++;
-               mwifiex_write_data_complete(adapter, skb, 0, ret);
-               break;
-       case -EINPROGRESS:
-               break;
-       case 0:
-               mwifiex_write_data_complete(adapter, skb, 0, ret);
-               break;
-       default:
-               break;
-       }
-       return ret;
-}
-
-static int
-mwifiex_dequeue_tx_queue(struct mwifiex_adapter *adapter)
-{
-       struct sk_buff *skb, *skb_next;
-       struct mwifiex_txinfo *tx_info;
-       struct mwifiex_tx_param tx_param;
-
-       skb = skb_dequeue(&adapter->tx_data_q);
-       if (!skb)
-               return -1;
-
-       tx_info = MWIFIEX_SKB_TXCB(skb);
-       if (tx_info->flags & MWIFIEX_BUF_FLAG_AGGR_PKT)
-               atomic_sub(tx_info->aggr_num, &adapter->tx_queued);
-       else
-               atomic_dec(&adapter->tx_queued);
-
-       if (!skb_queue_empty(&adapter->tx_data_q))
-               skb_next = skb_peek(&adapter->tx_data_q);
-       else
-               skb_next = NULL;
-       tx_param.next_pkt_len = ((skb_next) ? skb_next->len : 0);
-       if (!tx_param.next_pkt_len) {
-               if (!mwifiex_wmm_lists_empty(adapter))
-                       tx_param.next_pkt_len = 1;
-       }
-       return mwifiex_host_to_card(adapter, skb, &tx_param);
-}
-
-void
-mwifiex_process_tx_queue(struct mwifiex_adapter *adapter)
-{
-       do {
-               if (adapter->data_sent || adapter->tx_lock_flag)
-                       break;
-               if (mwifiex_dequeue_tx_queue(adapter))
-                       break;
-       } while (!skb_queue_empty(&adapter->tx_data_q));
-}
-
-/*
- * Packet send completion callback handler.
- *
- * It either frees the buffer directly or forwards it to another
- * completion callback which checks conditions, updates statistics,
- * wakes up stalled traffic queue if required, and then frees the buffer.
- */
-int mwifiex_write_data_complete(struct mwifiex_adapter *adapter,
-                               struct sk_buff *skb, int aggr, int status)
-{
-       struct mwifiex_private *priv;
-       struct mwifiex_txinfo *tx_info;
-       struct netdev_queue *txq;
-       int index;
-
-       if (!skb)
-               return 0;
-
-       tx_info = MWIFIEX_SKB_TXCB(skb);
-       priv = mwifiex_get_priv_by_id(adapter, tx_info->bss_num,
-                                     tx_info->bss_type);
-       if (!priv)
-               goto done;
-
-       mwifiex_set_trans_start(priv->netdev);
-       if (!status) {
-               priv->stats.tx_packets++;
-               priv->stats.tx_bytes += tx_info->pkt_len;
-               if (priv->tx_timeout_cnt)
-                       priv->tx_timeout_cnt = 0;
-       } else {
-               priv->stats.tx_errors++;
-       }
-
-       if (tx_info->flags & MWIFIEX_BUF_FLAG_BRIDGED_PKT)
-               atomic_dec_return(&adapter->pending_bridged_pkts);
-
-       if (tx_info->flags & MWIFIEX_BUF_FLAG_AGGR_PKT)
-               goto done;
-
-       if (aggr)
-               /* For skb_aggr, do not wake up tx queue */
-               goto done;
-
-       atomic_dec(&adapter->tx_pending);
-
-       index = mwifiex_1d_to_wmm_queue[skb->priority];
-       if (atomic_dec_return(&priv->wmm_tx_pending[index]) < LOW_TX_PENDING) {
-               txq = netdev_get_tx_queue(priv->netdev, index);
-               if (netif_tx_queue_stopped(txq)) {
-                       netif_tx_wake_queue(txq);
-                       mwifiex_dbg(adapter, DATA, "wake queue: %d\n", index);
-               }
-       }
-done:
-       dev_kfree_skb_any(skb);
-
-       return 0;
-}
-EXPORT_SYMBOL_GPL(mwifiex_write_data_complete);
-
-void mwifiex_parse_tx_status_event(struct mwifiex_private *priv,
-                                  void *event_body)
-{
-       struct tx_status_event *tx_status = (void *)priv->adapter->event_body;
-       struct sk_buff *ack_skb;
-       unsigned long flags;
-       struct mwifiex_txinfo *tx_info;
-
-       if (!tx_status->tx_token_id)
-               return;
-
-       spin_lock_irqsave(&priv->ack_status_lock, flags);
-       ack_skb = idr_find(&priv->ack_status_frames, tx_status->tx_token_id);
-       if (ack_skb)
-               idr_remove(&priv->ack_status_frames, tx_status->tx_token_id);
-       spin_unlock_irqrestore(&priv->ack_status_lock, flags);
-
-       if (ack_skb) {
-               tx_info = MWIFIEX_SKB_TXCB(ack_skb);
-
-               if (tx_info->flags & MWIFIEX_BUF_FLAG_EAPOL_TX_STATUS) {
-                       /* consumes ack_skb */
-                       skb_complete_wifi_ack(ack_skb, !tx_status->status);
-               } else {
-                       /* Remove broadcast address which was added by driver */
-                       memmove(ack_skb->data +
-                               sizeof(struct ieee80211_hdr_3addr) +
-                               MWIFIEX_MGMT_FRAME_HEADER_SIZE + sizeof(u16),
-                               ack_skb->data +
-                               sizeof(struct ieee80211_hdr_3addr) +
-                               MWIFIEX_MGMT_FRAME_HEADER_SIZE + sizeof(u16) +
-                               ETH_ALEN, ack_skb->len -
-                               (sizeof(struct ieee80211_hdr_3addr) +
-                               MWIFIEX_MGMT_FRAME_HEADER_SIZE + sizeof(u16) +
-                               ETH_ALEN));
-                       ack_skb->len = ack_skb->len - ETH_ALEN;
-                       /* Remove driver's proprietary header including 2 bytes
-                        * of packet length and pass actual management frame buffer
-                        * to cfg80211.
-                        */
-                       cfg80211_mgmt_tx_status(&priv->wdev, tx_info->cookie,
-                                               ack_skb->data +
-                                               MWIFIEX_MGMT_FRAME_HEADER_SIZE +
-                                               sizeof(u16), ack_skb->len -
-                                               (MWIFIEX_MGMT_FRAME_HEADER_SIZE
-                                                + sizeof(u16)),
-                                               !tx_status->status, GFP_ATOMIC);
-                       dev_kfree_skb_any(ack_skb);
-               }
-       }
-}
diff --git a/drivers/net/wireless/mwifiex/uap_cmd.c b/drivers/net/wireless/mwifiex/uap_cmd.c
deleted file mode 100644 (file)
index 759a6ad..0000000
+++ /dev/null
@@ -1,885 +0,0 @@
-/*
- * Marvell Wireless LAN device driver: AP specific command handling
- *
- * Copyright (C) 2012-2014, Marvell International Ltd.
- *
- * This software file (the "File") is distributed by Marvell International
- * Ltd. under the terms of the GNU General Public License Version 2, June 1991
- * (the "License").  You may use, redistribute and/or modify this File in
- * accordance with the terms and conditions of the License, a copy of which
- * is available by writing to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the
- * worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
- *
- * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
- * ARE EXPRESSLY DISCLAIMED.  The License provides additional details about
- * this warranty disclaimer.
- */
-
-#include "main.h"
-#include "11ac.h"
-
-/* This function parses security related parameters from cfg80211_ap_settings
- * and sets into FW understandable bss_config structure.
- */
-int mwifiex_set_secure_params(struct mwifiex_private *priv,
-                             struct mwifiex_uap_bss_param *bss_config,
-                             struct cfg80211_ap_settings *params) {
-       int i;
-       struct mwifiex_wep_key wep_key;
-
-       if (!params->privacy) {
-               bss_config->protocol = PROTOCOL_NO_SECURITY;
-               bss_config->key_mgmt = KEY_MGMT_NONE;
-               bss_config->wpa_cfg.length = 0;
-               priv->sec_info.wep_enabled = 0;
-               priv->sec_info.wpa_enabled = 0;
-               priv->sec_info.wpa2_enabled = 0;
-
-               return 0;
-       }
-
-       switch (params->auth_type) {
-       case NL80211_AUTHTYPE_OPEN_SYSTEM:
-               bss_config->auth_mode = WLAN_AUTH_OPEN;
-               break;
-       case NL80211_AUTHTYPE_SHARED_KEY:
-               bss_config->auth_mode = WLAN_AUTH_SHARED_KEY;
-               break;
-       case NL80211_AUTHTYPE_NETWORK_EAP:
-               bss_config->auth_mode = WLAN_AUTH_LEAP;
-               break;
-       default:
-               bss_config->auth_mode = MWIFIEX_AUTH_MODE_AUTO;
-               break;
-       }
-
-       bss_config->key_mgmt_operation |= KEY_MGMT_ON_HOST;
-
-       for (i = 0; i < params->crypto.n_akm_suites; i++) {
-               switch (params->crypto.akm_suites[i]) {
-               case WLAN_AKM_SUITE_8021X:
-                       if (params->crypto.wpa_versions &
-                           NL80211_WPA_VERSION_1) {
-                               bss_config->protocol = PROTOCOL_WPA;
-                               bss_config->key_mgmt = KEY_MGMT_EAP;
-                       }
-                       if (params->crypto.wpa_versions &
-                           NL80211_WPA_VERSION_2) {
-                               bss_config->protocol |= PROTOCOL_WPA2;
-                               bss_config->key_mgmt = KEY_MGMT_EAP;
-                       }
-                       break;
-               case WLAN_AKM_SUITE_PSK:
-                       if (params->crypto.wpa_versions &
-                           NL80211_WPA_VERSION_1) {
-                               bss_config->protocol = PROTOCOL_WPA;
-                               bss_config->key_mgmt = KEY_MGMT_PSK;
-                       }
-                       if (params->crypto.wpa_versions &
-                           NL80211_WPA_VERSION_2) {
-                               bss_config->protocol |= PROTOCOL_WPA2;
-                               bss_config->key_mgmt = KEY_MGMT_PSK;
-                       }
-                       break;
-               default:
-                       break;
-               }
-       }
-       for (i = 0; i < params->crypto.n_ciphers_pairwise; i++) {
-               switch (params->crypto.ciphers_pairwise[i]) {
-               case WLAN_CIPHER_SUITE_WEP40:
-               case WLAN_CIPHER_SUITE_WEP104:
-                       break;
-               case WLAN_CIPHER_SUITE_TKIP:
-                       if (params->crypto.wpa_versions & NL80211_WPA_VERSION_1)
-                               bss_config->wpa_cfg.pairwise_cipher_wpa |=
-                                                               CIPHER_TKIP;
-                       if (params->crypto.wpa_versions & NL80211_WPA_VERSION_2)
-                               bss_config->wpa_cfg.pairwise_cipher_wpa2 |=
-                                                               CIPHER_TKIP;
-                       break;
-               case WLAN_CIPHER_SUITE_CCMP:
-                       if (params->crypto.wpa_versions & NL80211_WPA_VERSION_1)
-                               bss_config->wpa_cfg.pairwise_cipher_wpa |=
-                                                               CIPHER_AES_CCMP;
-                       if (params->crypto.wpa_versions & NL80211_WPA_VERSION_2)
-                               bss_config->wpa_cfg.pairwise_cipher_wpa2 |=
-                                                               CIPHER_AES_CCMP;
-               default:
-                       break;
-               }
-       }
-
-       switch (params->crypto.cipher_group) {
-       case WLAN_CIPHER_SUITE_WEP40:
-       case WLAN_CIPHER_SUITE_WEP104:
-               if (priv->sec_info.wep_enabled) {
-                       bss_config->protocol = PROTOCOL_STATIC_WEP;
-                       bss_config->key_mgmt = KEY_MGMT_NONE;
-                       bss_config->wpa_cfg.length = 0;
-
-                       for (i = 0; i < NUM_WEP_KEYS; i++) {
-                               wep_key = priv->wep_key[i];
-                               bss_config->wep_cfg[i].key_index = i;
-
-                               if (priv->wep_key_curr_index == i)
-                                       bss_config->wep_cfg[i].is_default = 1;
-                               else
-                                       bss_config->wep_cfg[i].is_default = 0;
-
-                               bss_config->wep_cfg[i].length =
-                                                            wep_key.key_length;
-                               memcpy(&bss_config->wep_cfg[i].key,
-                                      &wep_key.key_material,
-                                      wep_key.key_length);
-                       }
-               }
-               break;
-       case WLAN_CIPHER_SUITE_TKIP:
-               bss_config->wpa_cfg.group_cipher = CIPHER_TKIP;
-               break;
-       case WLAN_CIPHER_SUITE_CCMP:
-               bss_config->wpa_cfg.group_cipher = CIPHER_AES_CCMP;
-               break;
-       default:
-               break;
-       }
-
-       return 0;
-}
-
-/* This function updates 11n related parameters from IE and sets them into
- * bss_config structure.
- */
-void
-mwifiex_set_ht_params(struct mwifiex_private *priv,
-                     struct mwifiex_uap_bss_param *bss_cfg,
-                     struct cfg80211_ap_settings *params)
-{
-       const u8 *ht_ie;
-       u16 cap_info;
-
-       if (!ISSUPP_11NENABLED(priv->adapter->fw_cap_info))
-               return;
-
-       ht_ie = cfg80211_find_ie(WLAN_EID_HT_CAPABILITY, params->beacon.tail,
-                                params->beacon.tail_len);
-       if (ht_ie) {
-               memcpy(&bss_cfg->ht_cap, ht_ie + 2,
-                      sizeof(struct ieee80211_ht_cap));
-               cap_info = le16_to_cpu(bss_cfg->ht_cap.cap_info);
-               memset(&bss_cfg->ht_cap.mcs, 0,
-                      priv->adapter->number_of_antenna);
-               switch (GET_RXSTBC(cap_info)) {
-               case MWIFIEX_RX_STBC1:
-                       /* HT_CAP 1X1 mode */
-                       bss_cfg->ht_cap.mcs.rx_mask[0] = 0xff;
-                       break;
-               case MWIFIEX_RX_STBC12: /* fall through */
-               case MWIFIEX_RX_STBC123:
-                       /* HT_CAP 2X2 mode */
-                       bss_cfg->ht_cap.mcs.rx_mask[0] = 0xff;
-                       bss_cfg->ht_cap.mcs.rx_mask[1] = 0xff;
-                       break;
-               default:
-                       mwifiex_dbg(priv->adapter, WARN,
-                                   "Unsupported RX-STBC, default to 2x2\n");
-                       bss_cfg->ht_cap.mcs.rx_mask[0] = 0xff;
-                       bss_cfg->ht_cap.mcs.rx_mask[1] = 0xff;
-                       break;
-               }
-               priv->ap_11n_enabled = 1;
-       } else {
-               memset(&bss_cfg->ht_cap , 0, sizeof(struct ieee80211_ht_cap));
-               bss_cfg->ht_cap.cap_info = cpu_to_le16(MWIFIEX_DEF_HT_CAP);
-               bss_cfg->ht_cap.ampdu_params_info = MWIFIEX_DEF_AMPDU;
-       }
-
-       return;
-}
-
-/* This function updates 11ac related parameters from IE
- * and sets them into bss_config structure.
- */
-void mwifiex_set_vht_params(struct mwifiex_private *priv,
-                           struct mwifiex_uap_bss_param *bss_cfg,
-                           struct cfg80211_ap_settings *params)
-{
-       const u8 *vht_ie;
-
-       vht_ie = cfg80211_find_ie(WLAN_EID_VHT_CAPABILITY, params->beacon.tail,
-                                 params->beacon.tail_len);
-       if (vht_ie) {
-               memcpy(&bss_cfg->vht_cap, vht_ie + 2,
-                      sizeof(struct ieee80211_vht_cap));
-               priv->ap_11ac_enabled = 1;
-       } else {
-               priv->ap_11ac_enabled = 0;
-       }
-
-       return;
-}
-
-/* This function updates 11ac related parameters from IE
- * and sets them into bss_config structure.
- */
-void mwifiex_set_tpc_params(struct mwifiex_private *priv,
-                           struct mwifiex_uap_bss_param *bss_cfg,
-                           struct cfg80211_ap_settings *params)
-{
-       const u8 *tpc_ie;
-
-       tpc_ie = cfg80211_find_ie(WLAN_EID_TPC_REQUEST, params->beacon.tail,
-                                 params->beacon.tail_len);
-       if (tpc_ie)
-               bss_cfg->power_constraint = *(tpc_ie + 2);
-       else
-               bss_cfg->power_constraint = 0;
-}
-
-/* Enable VHT only when cfg80211_ap_settings has VHT IE.
- * Otherwise disable VHT.
- */
-void mwifiex_set_vht_width(struct mwifiex_private *priv,
-                          enum nl80211_chan_width width,
-                          bool ap_11ac_enable)
-{
-       struct mwifiex_adapter *adapter = priv->adapter;
-       struct mwifiex_11ac_vht_cfg vht_cfg;
-
-       vht_cfg.band_config = VHT_CFG_5GHZ;
-       vht_cfg.cap_info = adapter->hw_dot_11ac_dev_cap;
-
-       if (!ap_11ac_enable) {
-               vht_cfg.mcs_tx_set = DISABLE_VHT_MCS_SET;
-               vht_cfg.mcs_rx_set = DISABLE_VHT_MCS_SET;
-       } else {
-               vht_cfg.mcs_tx_set = DEFAULT_VHT_MCS_SET;
-               vht_cfg.mcs_rx_set = DEFAULT_VHT_MCS_SET;
-       }
-
-       vht_cfg.misc_config  = VHT_CAP_UAP_ONLY;
-
-       if (ap_11ac_enable && width >= NL80211_CHAN_WIDTH_80)
-               vht_cfg.misc_config |= VHT_BW_80_160_80P80;
-
-       mwifiex_send_cmd(priv, HostCmd_CMD_11AC_CFG,
-                        HostCmd_ACT_GEN_SET, 0, &vht_cfg, true);
-
-       return;
-}
-
-/* This function finds supported rates IE from beacon parameter and sets
- * these rates into bss_config structure.
- */
-void
-mwifiex_set_uap_rates(struct mwifiex_uap_bss_param *bss_cfg,
-                     struct cfg80211_ap_settings *params)
-{
-       struct ieee_types_header *rate_ie;
-       int var_offset = offsetof(struct ieee80211_mgmt, u.beacon.variable);
-       const u8 *var_pos = params->beacon.head + var_offset;
-       int len = params->beacon.head_len - var_offset;
-       u8 rate_len = 0;
-
-       rate_ie = (void *)cfg80211_find_ie(WLAN_EID_SUPP_RATES, var_pos, len);
-       if (rate_ie) {
-               memcpy(bss_cfg->rates, rate_ie + 1, rate_ie->len);
-               rate_len = rate_ie->len;
-       }
-
-       rate_ie = (void *)cfg80211_find_ie(WLAN_EID_EXT_SUPP_RATES,
-                                          params->beacon.tail,
-                                          params->beacon.tail_len);
-       if (rate_ie)
-               memcpy(bss_cfg->rates + rate_len, rate_ie + 1, rate_ie->len);
-
-       return;
-}
-
-/* This function initializes some of mwifiex_uap_bss_param variables.
- * This helps FW in ignoring invalid values. These values may or may not
- * be get updated to valid ones at later stage.
- */
-void mwifiex_set_sys_config_invalid_data(struct mwifiex_uap_bss_param *config)
-{
-       config->bcast_ssid_ctl = 0x7F;
-       config->radio_ctl = 0x7F;
-       config->dtim_period = 0x7F;
-       config->beacon_period = 0x7FFF;
-       config->auth_mode = 0x7F;
-       config->rts_threshold = 0x7FFF;
-       config->frag_threshold = 0x7FFF;
-       config->retry_limit = 0x7F;
-       config->qos_info = 0xFF;
-}
-
-/* This function parses BSS related parameters from structure
- * and prepares TLVs specific to WPA/WPA2 security.
- * These TLVs are appended to command buffer.
- */
-static void
-mwifiex_uap_bss_wpa(u8 **tlv_buf, void *cmd_buf, u16 *param_size)
-{
-       struct host_cmd_tlv_pwk_cipher *pwk_cipher;
-       struct host_cmd_tlv_gwk_cipher *gwk_cipher;
-       struct host_cmd_tlv_passphrase *passphrase;
-       struct host_cmd_tlv_akmp *tlv_akmp;
-       struct mwifiex_uap_bss_param *bss_cfg = cmd_buf;
-       u16 cmd_size = *param_size;
-       u8 *tlv = *tlv_buf;
-
-       tlv_akmp = (struct host_cmd_tlv_akmp *)tlv;
-       tlv_akmp->header.type = cpu_to_le16(TLV_TYPE_UAP_AKMP);
-       tlv_akmp->header.len = cpu_to_le16(sizeof(struct host_cmd_tlv_akmp) -
-                                       sizeof(struct mwifiex_ie_types_header));
-       tlv_akmp->key_mgmt_operation = cpu_to_le16(bss_cfg->key_mgmt_operation);
-       tlv_akmp->key_mgmt = cpu_to_le16(bss_cfg->key_mgmt);
-       cmd_size += sizeof(struct host_cmd_tlv_akmp);
-       tlv += sizeof(struct host_cmd_tlv_akmp);
-
-       if (bss_cfg->wpa_cfg.pairwise_cipher_wpa & VALID_CIPHER_BITMAP) {
-               pwk_cipher = (struct host_cmd_tlv_pwk_cipher *)tlv;
-               pwk_cipher->header.type = cpu_to_le16(TLV_TYPE_PWK_CIPHER);
-               pwk_cipher->header.len =
-                       cpu_to_le16(sizeof(struct host_cmd_tlv_pwk_cipher) -
-                                   sizeof(struct mwifiex_ie_types_header));
-               pwk_cipher->proto = cpu_to_le16(PROTOCOL_WPA);
-               pwk_cipher->cipher = bss_cfg->wpa_cfg.pairwise_cipher_wpa;
-               cmd_size += sizeof(struct host_cmd_tlv_pwk_cipher);
-               tlv += sizeof(struct host_cmd_tlv_pwk_cipher);
-       }
-
-       if (bss_cfg->wpa_cfg.pairwise_cipher_wpa2 & VALID_CIPHER_BITMAP) {
-               pwk_cipher = (struct host_cmd_tlv_pwk_cipher *)tlv;
-               pwk_cipher->header.type = cpu_to_le16(TLV_TYPE_PWK_CIPHER);
-               pwk_cipher->header.len =
-                       cpu_to_le16(sizeof(struct host_cmd_tlv_pwk_cipher) -
-                                   sizeof(struct mwifiex_ie_types_header));
-               pwk_cipher->proto = cpu_to_le16(PROTOCOL_WPA2);
-               pwk_cipher->cipher = bss_cfg->wpa_cfg.pairwise_cipher_wpa2;
-               cmd_size += sizeof(struct host_cmd_tlv_pwk_cipher);
-               tlv += sizeof(struct host_cmd_tlv_pwk_cipher);
-       }
-
-       if (bss_cfg->wpa_cfg.group_cipher & VALID_CIPHER_BITMAP) {
-               gwk_cipher = (struct host_cmd_tlv_gwk_cipher *)tlv;
-               gwk_cipher->header.type = cpu_to_le16(TLV_TYPE_GWK_CIPHER);
-               gwk_cipher->header.len =
-                       cpu_to_le16(sizeof(struct host_cmd_tlv_gwk_cipher) -
-                                   sizeof(struct mwifiex_ie_types_header));
-               gwk_cipher->cipher = bss_cfg->wpa_cfg.group_cipher;
-               cmd_size += sizeof(struct host_cmd_tlv_gwk_cipher);
-               tlv += sizeof(struct host_cmd_tlv_gwk_cipher);
-       }
-
-       if (bss_cfg->wpa_cfg.length) {
-               passphrase = (struct host_cmd_tlv_passphrase *)tlv;
-               passphrase->header.type =
-                               cpu_to_le16(TLV_TYPE_UAP_WPA_PASSPHRASE);
-               passphrase->header.len = cpu_to_le16(bss_cfg->wpa_cfg.length);
-               memcpy(passphrase->passphrase, bss_cfg->wpa_cfg.passphrase,
-                      bss_cfg->wpa_cfg.length);
-               cmd_size += sizeof(struct mwifiex_ie_types_header) +
-                           bss_cfg->wpa_cfg.length;
-               tlv += sizeof(struct mwifiex_ie_types_header) +
-                               bss_cfg->wpa_cfg.length;
-       }
-
-       *param_size = cmd_size;
-       *tlv_buf = tlv;
-
-       return;
-}
-
-/* This function parses WMM related parameters from cfg80211_ap_settings
- * structure and updates bss_config structure.
- */
-void
-mwifiex_set_wmm_params(struct mwifiex_private *priv,
-                      struct mwifiex_uap_bss_param *bss_cfg,
-                      struct cfg80211_ap_settings *params)
-{
-       const u8 *vendor_ie;
-       struct ieee_types_header *wmm_ie;
-       u8 wmm_oui[] = {0x00, 0x50, 0xf2, 0x02};
-
-       vendor_ie = cfg80211_find_vendor_ie(WLAN_OUI_MICROSOFT,
-                                           WLAN_OUI_TYPE_MICROSOFT_WMM,
-                                           params->beacon.tail,
-                                           params->beacon.tail_len);
-       if (vendor_ie) {
-               wmm_ie = (struct ieee_types_header *)vendor_ie;
-               memcpy(&bss_cfg->wmm_info, wmm_ie + 1,
-                      sizeof(bss_cfg->wmm_info));
-               priv->wmm_enabled = 1;
-       } else {
-               memset(&bss_cfg->wmm_info, 0, sizeof(bss_cfg->wmm_info));
-               memcpy(&bss_cfg->wmm_info.oui, wmm_oui, sizeof(wmm_oui));
-               bss_cfg->wmm_info.subtype = MWIFIEX_WMM_SUBTYPE;
-               bss_cfg->wmm_info.version = MWIFIEX_WMM_VERSION;
-               priv->wmm_enabled = 0;
-       }
-
-       bss_cfg->qos_info = 0x00;
-       return;
-}
-/* This function parses BSS related parameters from structure
- * and prepares TLVs specific to WEP encryption.
- * These TLVs are appended to command buffer.
- */
-static void
-mwifiex_uap_bss_wep(u8 **tlv_buf, void *cmd_buf, u16 *param_size)
-{
-       struct host_cmd_tlv_wep_key *wep_key;
-       u16 cmd_size = *param_size;
-       int i;
-       u8 *tlv = *tlv_buf;
-       struct mwifiex_uap_bss_param *bss_cfg = cmd_buf;
-
-       for (i = 0; i < NUM_WEP_KEYS; i++) {
-               if (bss_cfg->wep_cfg[i].length &&
-                   (bss_cfg->wep_cfg[i].length == WLAN_KEY_LEN_WEP40 ||
-                    bss_cfg->wep_cfg[i].length == WLAN_KEY_LEN_WEP104)) {
-                       wep_key = (struct host_cmd_tlv_wep_key *)tlv;
-                       wep_key->header.type =
-                               cpu_to_le16(TLV_TYPE_UAP_WEP_KEY);
-                       wep_key->header.len =
-                               cpu_to_le16(bss_cfg->wep_cfg[i].length + 2);
-                       wep_key->key_index = bss_cfg->wep_cfg[i].key_index;
-                       wep_key->is_default = bss_cfg->wep_cfg[i].is_default;
-                       memcpy(wep_key->key, bss_cfg->wep_cfg[i].key,
-                              bss_cfg->wep_cfg[i].length);
-                       cmd_size += sizeof(struct mwifiex_ie_types_header) + 2 +
-                                   bss_cfg->wep_cfg[i].length;
-                       tlv += sizeof(struct mwifiex_ie_types_header) + 2 +
-                                   bss_cfg->wep_cfg[i].length;
-               }
-       }
-
-       *param_size = cmd_size;
-       *tlv_buf = tlv;
-
-       return;
-}
-
-/* This function parses BSS related parameters from structure
- * and prepares TLVs. These TLVs are appended to command buffer.
-*/
-static int
-mwifiex_uap_bss_param_prepare(u8 *tlv, void *cmd_buf, u16 *param_size)
-{
-       struct host_cmd_tlv_dtim_period *dtim_period;
-       struct host_cmd_tlv_beacon_period *beacon_period;
-       struct host_cmd_tlv_ssid *ssid;
-       struct host_cmd_tlv_bcast_ssid *bcast_ssid;
-       struct host_cmd_tlv_channel_band *chan_band;
-       struct host_cmd_tlv_frag_threshold *frag_threshold;
-       struct host_cmd_tlv_rts_threshold *rts_threshold;
-       struct host_cmd_tlv_retry_limit *retry_limit;
-       struct host_cmd_tlv_encrypt_protocol *encrypt_protocol;
-       struct host_cmd_tlv_auth_type *auth_type;
-       struct host_cmd_tlv_rates *tlv_rates;
-       struct host_cmd_tlv_ageout_timer *ao_timer, *ps_ao_timer;
-       struct host_cmd_tlv_power_constraint *pwr_ct;
-       struct mwifiex_ie_types_htcap *htcap;
-       struct mwifiex_ie_types_wmmcap *wmm_cap;
-       struct mwifiex_uap_bss_param *bss_cfg = cmd_buf;
-       int i;
-       u16 cmd_size = *param_size;
-
-       if (bss_cfg->ssid.ssid_len) {
-               ssid = (struct host_cmd_tlv_ssid *)tlv;
-               ssid->header.type = cpu_to_le16(TLV_TYPE_UAP_SSID);
-               ssid->header.len = cpu_to_le16((u16)bss_cfg->ssid.ssid_len);
-               memcpy(ssid->ssid, bss_cfg->ssid.ssid, bss_cfg->ssid.ssid_len);
-               cmd_size += sizeof(struct mwifiex_ie_types_header) +
-                           bss_cfg->ssid.ssid_len;
-               tlv += sizeof(struct mwifiex_ie_types_header) +
-                               bss_cfg->ssid.ssid_len;
-
-               bcast_ssid = (struct host_cmd_tlv_bcast_ssid *)tlv;
-               bcast_ssid->header.type = cpu_to_le16(TLV_TYPE_UAP_BCAST_SSID);
-               bcast_ssid->header.len =
-                               cpu_to_le16(sizeof(bcast_ssid->bcast_ctl));
-               bcast_ssid->bcast_ctl = bss_cfg->bcast_ssid_ctl;
-               cmd_size += sizeof(struct host_cmd_tlv_bcast_ssid);
-               tlv += sizeof(struct host_cmd_tlv_bcast_ssid);
-       }
-       if (bss_cfg->rates[0]) {
-               tlv_rates = (struct host_cmd_tlv_rates *)tlv;
-               tlv_rates->header.type = cpu_to_le16(TLV_TYPE_UAP_RATES);
-
-               for (i = 0; i < MWIFIEX_SUPPORTED_RATES && bss_cfg->rates[i];
-                    i++)
-                       tlv_rates->rates[i] = bss_cfg->rates[i];
-
-               tlv_rates->header.len = cpu_to_le16(i);
-               cmd_size += sizeof(struct host_cmd_tlv_rates) + i;
-               tlv += sizeof(struct host_cmd_tlv_rates) + i;
-       }
-       if (bss_cfg->channel &&
-           ((bss_cfg->band_cfg == BAND_CONFIG_BG &&
-             bss_cfg->channel <= MAX_CHANNEL_BAND_BG) ||
-           (bss_cfg->band_cfg == BAND_CONFIG_A &&
-            bss_cfg->channel <= MAX_CHANNEL_BAND_A))) {
-               chan_band = (struct host_cmd_tlv_channel_band *)tlv;
-               chan_band->header.type = cpu_to_le16(TLV_TYPE_CHANNELBANDLIST);
-               chan_band->header.len =
-                       cpu_to_le16(sizeof(struct host_cmd_tlv_channel_band) -
-                                   sizeof(struct mwifiex_ie_types_header));
-               chan_band->band_config = bss_cfg->band_cfg;
-               chan_band->channel = bss_cfg->channel;
-               cmd_size += sizeof(struct host_cmd_tlv_channel_band);
-               tlv += sizeof(struct host_cmd_tlv_channel_band);
-       }
-       if (bss_cfg->beacon_period >= MIN_BEACON_PERIOD &&
-           bss_cfg->beacon_period <= MAX_BEACON_PERIOD) {
-               beacon_period = (struct host_cmd_tlv_beacon_period *)tlv;
-               beacon_period->header.type =
-                                       cpu_to_le16(TLV_TYPE_UAP_BEACON_PERIOD);
-               beacon_period->header.len =
-                       cpu_to_le16(sizeof(struct host_cmd_tlv_beacon_period) -
-                                   sizeof(struct mwifiex_ie_types_header));
-               beacon_period->period = cpu_to_le16(bss_cfg->beacon_period);
-               cmd_size += sizeof(struct host_cmd_tlv_beacon_period);
-               tlv += sizeof(struct host_cmd_tlv_beacon_period);
-       }
-       if (bss_cfg->dtim_period >= MIN_DTIM_PERIOD &&
-           bss_cfg->dtim_period <= MAX_DTIM_PERIOD) {
-               dtim_period = (struct host_cmd_tlv_dtim_period *)tlv;
-               dtim_period->header.type =
-                       cpu_to_le16(TLV_TYPE_UAP_DTIM_PERIOD);
-               dtim_period->header.len =
-                       cpu_to_le16(sizeof(struct host_cmd_tlv_dtim_period) -
-                                   sizeof(struct mwifiex_ie_types_header));
-               dtim_period->period = bss_cfg->dtim_period;
-               cmd_size += sizeof(struct host_cmd_tlv_dtim_period);
-               tlv += sizeof(struct host_cmd_tlv_dtim_period);
-       }
-       if (bss_cfg->rts_threshold <= MWIFIEX_RTS_MAX_VALUE) {
-               rts_threshold = (struct host_cmd_tlv_rts_threshold *)tlv;
-               rts_threshold->header.type =
-                                       cpu_to_le16(TLV_TYPE_UAP_RTS_THRESHOLD);
-               rts_threshold->header.len =
-                       cpu_to_le16(sizeof(struct host_cmd_tlv_rts_threshold) -
-                                   sizeof(struct mwifiex_ie_types_header));
-               rts_threshold->rts_thr = cpu_to_le16(bss_cfg->rts_threshold);
-               cmd_size += sizeof(struct host_cmd_tlv_frag_threshold);
-               tlv += sizeof(struct host_cmd_tlv_frag_threshold);
-       }
-       if ((bss_cfg->frag_threshold >= MWIFIEX_FRAG_MIN_VALUE) &&
-           (bss_cfg->frag_threshold <= MWIFIEX_FRAG_MAX_VALUE)) {
-               frag_threshold = (struct host_cmd_tlv_frag_threshold *)tlv;
-               frag_threshold->header.type =
-                               cpu_to_le16(TLV_TYPE_UAP_FRAG_THRESHOLD);
-               frag_threshold->header.len =
-                       cpu_to_le16(sizeof(struct host_cmd_tlv_frag_threshold) -
-                                   sizeof(struct mwifiex_ie_types_header));
-               frag_threshold->frag_thr = cpu_to_le16(bss_cfg->frag_threshold);
-               cmd_size += sizeof(struct host_cmd_tlv_frag_threshold);
-               tlv += sizeof(struct host_cmd_tlv_frag_threshold);
-       }
-       if (bss_cfg->retry_limit <= MWIFIEX_RETRY_LIMIT) {
-               retry_limit = (struct host_cmd_tlv_retry_limit *)tlv;
-               retry_limit->header.type =
-                       cpu_to_le16(TLV_TYPE_UAP_RETRY_LIMIT);
-               retry_limit->header.len =
-                       cpu_to_le16(sizeof(struct host_cmd_tlv_retry_limit) -
-                                   sizeof(struct mwifiex_ie_types_header));
-               retry_limit->limit = (u8)bss_cfg->retry_limit;
-               cmd_size += sizeof(struct host_cmd_tlv_retry_limit);
-               tlv += sizeof(struct host_cmd_tlv_retry_limit);
-       }
-       if ((bss_cfg->protocol & PROTOCOL_WPA) ||
-           (bss_cfg->protocol & PROTOCOL_WPA2) ||
-           (bss_cfg->protocol & PROTOCOL_EAP))
-               mwifiex_uap_bss_wpa(&tlv, cmd_buf, &cmd_size);
-       else
-               mwifiex_uap_bss_wep(&tlv, cmd_buf, &cmd_size);
-
-       if ((bss_cfg->auth_mode <= WLAN_AUTH_SHARED_KEY) ||
-           (bss_cfg->auth_mode == MWIFIEX_AUTH_MODE_AUTO)) {
-               auth_type = (struct host_cmd_tlv_auth_type *)tlv;
-               auth_type->header.type = cpu_to_le16(TLV_TYPE_AUTH_TYPE);
-               auth_type->header.len =
-                       cpu_to_le16(sizeof(struct host_cmd_tlv_auth_type) -
-                       sizeof(struct mwifiex_ie_types_header));
-               auth_type->auth_type = (u8)bss_cfg->auth_mode;
-               cmd_size += sizeof(struct host_cmd_tlv_auth_type);
-               tlv += sizeof(struct host_cmd_tlv_auth_type);
-       }
-       if (bss_cfg->protocol) {
-               encrypt_protocol = (struct host_cmd_tlv_encrypt_protocol *)tlv;
-               encrypt_protocol->header.type =
-                       cpu_to_le16(TLV_TYPE_UAP_ENCRY_PROTOCOL);
-               encrypt_protocol->header.len =
-                       cpu_to_le16(sizeof(struct host_cmd_tlv_encrypt_protocol)
-                       - sizeof(struct mwifiex_ie_types_header));
-               encrypt_protocol->proto = cpu_to_le16(bss_cfg->protocol);
-               cmd_size += sizeof(struct host_cmd_tlv_encrypt_protocol);
-               tlv += sizeof(struct host_cmd_tlv_encrypt_protocol);
-       }
-
-       if (bss_cfg->ht_cap.cap_info) {
-               htcap = (struct mwifiex_ie_types_htcap *)tlv;
-               htcap->header.type = cpu_to_le16(WLAN_EID_HT_CAPABILITY);
-               htcap->header.len =
-                               cpu_to_le16(sizeof(struct ieee80211_ht_cap));
-               htcap->ht_cap.cap_info = bss_cfg->ht_cap.cap_info;
-               htcap->ht_cap.ampdu_params_info =
-                                            bss_cfg->ht_cap.ampdu_params_info;
-               memcpy(&htcap->ht_cap.mcs, &bss_cfg->ht_cap.mcs,
-                      sizeof(struct ieee80211_mcs_info));
-               htcap->ht_cap.extended_ht_cap_info =
-                                       bss_cfg->ht_cap.extended_ht_cap_info;
-               htcap->ht_cap.tx_BF_cap_info = bss_cfg->ht_cap.tx_BF_cap_info;
-               htcap->ht_cap.antenna_selection_info =
-                                       bss_cfg->ht_cap.antenna_selection_info;
-               cmd_size += sizeof(struct mwifiex_ie_types_htcap);
-               tlv += sizeof(struct mwifiex_ie_types_htcap);
-       }
-
-       if (bss_cfg->wmm_info.qos_info != 0xFF) {
-               wmm_cap = (struct mwifiex_ie_types_wmmcap *)tlv;
-               wmm_cap->header.type = cpu_to_le16(WLAN_EID_VENDOR_SPECIFIC);
-               wmm_cap->header.len = cpu_to_le16(sizeof(wmm_cap->wmm_info));
-               memcpy(&wmm_cap->wmm_info, &bss_cfg->wmm_info,
-                      sizeof(wmm_cap->wmm_info));
-               cmd_size += sizeof(struct mwifiex_ie_types_wmmcap);
-               tlv += sizeof(struct mwifiex_ie_types_wmmcap);
-       }
-
-       if (bss_cfg->sta_ao_timer) {
-               ao_timer = (struct host_cmd_tlv_ageout_timer *)tlv;
-               ao_timer->header.type = cpu_to_le16(TLV_TYPE_UAP_AO_TIMER);
-               ao_timer->header.len = cpu_to_le16(sizeof(*ao_timer) -
-                                       sizeof(struct mwifiex_ie_types_header));
-               ao_timer->sta_ao_timer = cpu_to_le32(bss_cfg->sta_ao_timer);
-               cmd_size += sizeof(*ao_timer);
-               tlv += sizeof(*ao_timer);
-       }
-
-       if (bss_cfg->power_constraint) {
-               pwr_ct = (void *)tlv;
-               pwr_ct->header.type = cpu_to_le16(TLV_TYPE_PWR_CONSTRAINT);
-               pwr_ct->header.len = cpu_to_le16(sizeof(u8));
-               pwr_ct->constraint = bss_cfg->power_constraint;
-               cmd_size += sizeof(*pwr_ct);
-               tlv += sizeof(*pwr_ct);
-       }
-
-       if (bss_cfg->ps_sta_ao_timer) {
-               ps_ao_timer = (struct host_cmd_tlv_ageout_timer *)tlv;
-               ps_ao_timer->header.type =
-                               cpu_to_le16(TLV_TYPE_UAP_PS_AO_TIMER);
-               ps_ao_timer->header.len = cpu_to_le16(sizeof(*ps_ao_timer) -
-                               sizeof(struct mwifiex_ie_types_header));
-               ps_ao_timer->sta_ao_timer =
-                                       cpu_to_le32(bss_cfg->ps_sta_ao_timer);
-               cmd_size += sizeof(*ps_ao_timer);
-               tlv += sizeof(*ps_ao_timer);
-       }
-
-       *param_size = cmd_size;
-
-       return 0;
-}
-
-/* This function parses custom IEs from IE list and prepares command buffer */
-static int mwifiex_uap_custom_ie_prepare(u8 *tlv, void *cmd_buf, u16 *ie_size)
-{
-       struct mwifiex_ie_list *ap_ie = cmd_buf;
-       struct mwifiex_ie_types_header *tlv_ie = (void *)tlv;
-
-       if (!ap_ie || !ap_ie->len || !ap_ie->ie_list)
-               return -1;
-
-       *ie_size += le16_to_cpu(ap_ie->len) +
-                       sizeof(struct mwifiex_ie_types_header);
-
-       tlv_ie->type = cpu_to_le16(TLV_TYPE_MGMT_IE);
-       tlv_ie->len = ap_ie->len;
-       tlv += sizeof(struct mwifiex_ie_types_header);
-
-       memcpy(tlv, ap_ie->ie_list, le16_to_cpu(ap_ie->len));
-
-       return 0;
-}
-
-/* Parse AP config structure and prepare TLV based command structure
- * to be sent to FW for uAP configuration
- */
-static int
-mwifiex_cmd_uap_sys_config(struct host_cmd_ds_command *cmd, u16 cmd_action,
-                          u32 type, void *cmd_buf)
-{
-       u8 *tlv;
-       u16 cmd_size, param_size, ie_size;
-       struct host_cmd_ds_sys_config *sys_cfg;
-
-       cmd->command = cpu_to_le16(HostCmd_CMD_UAP_SYS_CONFIG);
-       cmd_size = (u16)(sizeof(struct host_cmd_ds_sys_config) + S_DS_GEN);
-       sys_cfg = (struct host_cmd_ds_sys_config *)&cmd->params.uap_sys_config;
-       sys_cfg->action = cpu_to_le16(cmd_action);
-       tlv = sys_cfg->tlv;
-
-       switch (type) {
-       case UAP_BSS_PARAMS_I:
-               param_size = cmd_size;
-               if (mwifiex_uap_bss_param_prepare(tlv, cmd_buf, &param_size))
-                       return -1;
-               cmd->size = cpu_to_le16(param_size);
-               break;
-       case UAP_CUSTOM_IE_I:
-               ie_size = cmd_size;
-               if (mwifiex_uap_custom_ie_prepare(tlv, cmd_buf, &ie_size))
-                       return -1;
-               cmd->size = cpu_to_le16(ie_size);
-               break;
-       default:
-               return -1;
-       }
-
-       return 0;
-}
-
-/* This function prepares AP specific deauth command with mac supplied in
- * function parameter.
- */
-static int mwifiex_cmd_uap_sta_deauth(struct mwifiex_private *priv,
-                                     struct host_cmd_ds_command *cmd, u8 *mac)
-{
-       struct host_cmd_ds_sta_deauth *sta_deauth = &cmd->params.sta_deauth;
-
-       cmd->command = cpu_to_le16(HostCmd_CMD_UAP_STA_DEAUTH);
-       memcpy(sta_deauth->mac, mac, ETH_ALEN);
-       sta_deauth->reason = cpu_to_le16(WLAN_REASON_DEAUTH_LEAVING);
-
-       cmd->size = cpu_to_le16(sizeof(struct host_cmd_ds_sta_deauth) +
-                               S_DS_GEN);
-       return 0;
-}
-
-/* This function prepares the AP specific commands before sending them
- * to the firmware.
- * This is a generic function which calls specific command preparation
- * routines based upon the command number.
- */
-int mwifiex_uap_prepare_cmd(struct mwifiex_private *priv, u16 cmd_no,
-                           u16 cmd_action, u32 type,
-                           void *data_buf, void *cmd_buf)
-{
-       struct host_cmd_ds_command *cmd = cmd_buf;
-
-       switch (cmd_no) {
-       case HostCmd_CMD_UAP_SYS_CONFIG:
-               if (mwifiex_cmd_uap_sys_config(cmd, cmd_action, type, data_buf))
-                       return -1;
-               break;
-       case HostCmd_CMD_UAP_BSS_START:
-       case HostCmd_CMD_UAP_BSS_STOP:
-       case HOST_CMD_APCMD_SYS_RESET:
-       case HOST_CMD_APCMD_STA_LIST:
-               cmd->command = cpu_to_le16(cmd_no);
-               cmd->size = cpu_to_le16(S_DS_GEN);
-               break;
-       case HostCmd_CMD_UAP_STA_DEAUTH:
-               if (mwifiex_cmd_uap_sta_deauth(priv, cmd, data_buf))
-                       return -1;
-               break;
-       case HostCmd_CMD_CHAN_REPORT_REQUEST:
-               if (mwifiex_cmd_issue_chan_report_request(priv, cmd_buf,
-                                                         data_buf))
-                       return -1;
-               break;
-       default:
-               mwifiex_dbg(priv->adapter, ERROR,
-                           "PREP_CMD: unknown cmd %#x\n", cmd_no);
-               return -1;
-       }
-
-       return 0;
-}
-
-void mwifiex_uap_set_channel(struct mwifiex_private *priv,
-                            struct mwifiex_uap_bss_param *bss_cfg,
-                            struct cfg80211_chan_def chandef)
-{
-       u8 config_bands = 0, old_bands = priv->adapter->config_bands;
-
-       priv->bss_chandef = chandef;
-
-       bss_cfg->channel = ieee80211_frequency_to_channel(
-                                                    chandef.chan->center_freq);
-
-       /* Set appropriate bands */
-       if (chandef.chan->band == IEEE80211_BAND_2GHZ) {
-               bss_cfg->band_cfg = BAND_CONFIG_BG;
-               config_bands = BAND_B | BAND_G;
-
-               if (chandef.width > NL80211_CHAN_WIDTH_20_NOHT)
-                       config_bands |= BAND_GN;
-       } else {
-               bss_cfg->band_cfg = BAND_CONFIG_A;
-               config_bands = BAND_A;
-
-               if (chandef.width > NL80211_CHAN_WIDTH_20_NOHT)
-                       config_bands |= BAND_AN;
-
-               if (chandef.width > NL80211_CHAN_WIDTH_40)
-                       config_bands |= BAND_AAC;
-       }
-
-       priv->adapter->config_bands = config_bands;
-
-       if (old_bands != config_bands) {
-               mwifiex_send_domain_info_cmd_fw(priv->adapter->wiphy);
-               mwifiex_dnld_txpwr_table(priv);
-       }
-}
-
-int mwifiex_config_start_uap(struct mwifiex_private *priv,
-                            struct mwifiex_uap_bss_param *bss_cfg)
-{
-       enum state_11d_t state_11d;
-
-       if (mwifiex_send_cmd(priv, HostCmd_CMD_UAP_SYS_CONFIG,
-                            HostCmd_ACT_GEN_SET,
-                            UAP_BSS_PARAMS_I, bss_cfg, false)) {
-               mwifiex_dbg(priv->adapter, ERROR,
-                           "Failed to set the SSID\n");
-               return -1;
-       }
-
-       /* Send cmd to FW to enable 11D function */
-       state_11d = ENABLE_11D;
-       if (mwifiex_send_cmd(priv, HostCmd_CMD_802_11_SNMP_MIB,
-                            HostCmd_ACT_GEN_SET, DOT11D_I,
-                            &state_11d, true)) {
-               mwifiex_dbg(priv->adapter, ERROR,
-                           "11D: failed to enable 11D\n");
-               return -1;
-       }
-
-       if (mwifiex_send_cmd(priv, HostCmd_CMD_UAP_BSS_START,
-                            HostCmd_ACT_GEN_SET, 0, NULL, false)) {
-               mwifiex_dbg(priv->adapter, ERROR,
-                           "Failed to start the BSS\n");
-               return -1;
-       }
-
-       if (priv->sec_info.wep_enabled)
-               priv->curr_pkt_filter |= HostCmd_ACT_MAC_WEP_ENABLE;
-       else
-               priv->curr_pkt_filter &= ~HostCmd_ACT_MAC_WEP_ENABLE;
-
-       if (mwifiex_send_cmd(priv, HostCmd_CMD_MAC_CONTROL,
-                            HostCmd_ACT_GEN_SET, 0,
-                            &priv->curr_pkt_filter, true))
-               return -1;
-
-       return 0;
-}
diff --git a/drivers/net/wireless/mwifiex/uap_event.c b/drivers/net/wireless/mwifiex/uap_event.c
deleted file mode 100644 (file)
index 86ff542..0000000
+++ /dev/null
@@ -1,333 +0,0 @@
-/*
- * Marvell Wireless LAN device driver: AP event handling
- *
- * Copyright (C) 2012-2014, Marvell International Ltd.
- *
- * This software file (the "File") is distributed by Marvell International
- * Ltd. under the terms of the GNU General Public License Version 2, June 1991
- * (the "License").  You may use, redistribute and/or modify this File in
- * accordance with the terms and conditions of the License, a copy of which
- * is available by writing to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the
- * worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
- *
- * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
- * ARE EXPRESSLY DISCLAIMED.  The License provides additional details about
- * this warranty disclaimer.
- */
-
-#include "decl.h"
-#include "main.h"
-#include "11n.h"
-
-#define MWIFIEX_BSS_START_EVT_FIX_SIZE    12
-
-static int mwifiex_check_uap_capabilties(struct mwifiex_private *priv,
-                                        struct sk_buff *event)
-{
-       int evt_len;
-       u8 *curr;
-       u16 tlv_len;
-       struct mwifiex_ie_types_data *tlv_hdr;
-       struct ieee_types_wmm_parameter *wmm_param_ie = NULL;
-       int mask = IEEE80211_WMM_IE_AP_QOSINFO_PARAM_SET_CNT_MASK;
-
-       priv->wmm_enabled = false;
-       skb_pull(event, MWIFIEX_BSS_START_EVT_FIX_SIZE);
-       evt_len = event->len;
-       curr = event->data;
-
-       mwifiex_dbg_dump(priv->adapter, EVT_D, "uap capabilties:",
-                        event->data, event->len);
-
-       skb_push(event, MWIFIEX_BSS_START_EVT_FIX_SIZE);
-
-       while ((evt_len >= sizeof(tlv_hdr->header))) {
-               tlv_hdr = (struct mwifiex_ie_types_data *)curr;
-               tlv_len = le16_to_cpu(tlv_hdr->header.len);
-
-               if (evt_len < tlv_len + sizeof(tlv_hdr->header))
-                       break;
-
-               switch (le16_to_cpu(tlv_hdr->header.type)) {
-               case WLAN_EID_HT_CAPABILITY:
-                       priv->ap_11n_enabled = true;
-                       break;
-
-               case WLAN_EID_VHT_CAPABILITY:
-                       priv->ap_11ac_enabled = true;
-                       break;
-
-               case WLAN_EID_VENDOR_SPECIFIC:
-                       /* Point the regular IEEE IE 2 bytes into the Marvell IE
-                        * and setup the IEEE IE type and length byte fields
-                        */
-                       wmm_param_ie = (void *)(curr + 2);
-                       wmm_param_ie->vend_hdr.len = (u8)tlv_len;
-                       wmm_param_ie->vend_hdr.element_id =
-                                               WLAN_EID_VENDOR_SPECIFIC;
-                       mwifiex_dbg(priv->adapter, EVENT,
-                                   "info: check uap capabilities:\t"
-                                   "wmm parameter set count: %d\n",
-                                   wmm_param_ie->qos_info_bitmap & mask);
-
-                       mwifiex_wmm_setup_ac_downgrade(priv);
-                       priv->wmm_enabled = true;
-                       mwifiex_wmm_setup_queue_priorities(priv, wmm_param_ie);
-                       break;
-
-               default:
-                       break;
-               }
-
-               curr += (tlv_len + sizeof(tlv_hdr->header));
-               evt_len -= (tlv_len + sizeof(tlv_hdr->header));
-       }
-
-       return 0;
-}
-
-/*
- * This function handles AP interface specific events generated by firmware.
- *
- * Event specific routines are called by this function based
- * upon the generated event cause.
- *
- *
- * Events supported for AP -
- *      - EVENT_UAP_STA_ASSOC
- *      - EVENT_UAP_STA_DEAUTH
- *      - EVENT_UAP_BSS_ACTIVE
- *      - EVENT_UAP_BSS_START
- *      - EVENT_UAP_BSS_IDLE
- *      - EVENT_UAP_MIC_COUNTERMEASURES:
- */
-int mwifiex_process_uap_event(struct mwifiex_private *priv)
-{
-       struct mwifiex_adapter *adapter = priv->adapter;
-       int len, i;
-       u32 eventcause = adapter->event_cause;
-       struct station_info sinfo;
-       struct mwifiex_assoc_event *event;
-       struct mwifiex_sta_node *node;
-       u8 *deauth_mac;
-       struct host_cmd_ds_11n_batimeout *ba_timeout;
-       u16 ctrl;
-
-       switch (eventcause) {
-       case EVENT_UAP_STA_ASSOC:
-               memset(&sinfo, 0, sizeof(sinfo));
-               event = (struct mwifiex_assoc_event *)
-                       (adapter->event_body + MWIFIEX_UAP_EVENT_EXTRA_HEADER);
-               if (le16_to_cpu(event->type) == TLV_TYPE_UAP_MGMT_FRAME) {
-                       len = -1;
-
-                       if (ieee80211_is_assoc_req(event->frame_control))
-                               len = 0;
-                       else if (ieee80211_is_reassoc_req(event->frame_control))
-                               /* There will be ETH_ALEN bytes of
-                                * current_ap_addr before the re-assoc ies.
-                                */
-                               len = ETH_ALEN;
-
-                       if (len != -1) {
-                               sinfo.assoc_req_ies = &event->data[len];
-                               len = (u8 *)sinfo.assoc_req_ies -
-                                     (u8 *)&event->frame_control;
-                               sinfo.assoc_req_ies_len =
-                                       le16_to_cpu(event->len) - (u16)len;
-                       }
-               }
-               cfg80211_new_sta(priv->netdev, event->sta_addr, &sinfo,
-                                GFP_KERNEL);
-
-               node = mwifiex_add_sta_entry(priv, event->sta_addr);
-               if (!node) {
-                       mwifiex_dbg(adapter, ERROR,
-                                   "could not create station entry!\n");
-                       return -1;
-               }
-
-               if (!priv->ap_11n_enabled)
-                       break;
-
-               mwifiex_set_sta_ht_cap(priv, sinfo.assoc_req_ies,
-                                      sinfo.assoc_req_ies_len, node);
-
-               for (i = 0; i < MAX_NUM_TID; i++) {
-                       if (node->is_11n_enabled)
-                               node->ampdu_sta[i] =
-                                             priv->aggr_prio_tbl[i].ampdu_user;
-                       else
-                               node->ampdu_sta[i] = BA_STREAM_NOT_ALLOWED;
-               }
-               memset(node->rx_seq, 0xff, sizeof(node->rx_seq));
-               break;
-       case EVENT_UAP_STA_DEAUTH:
-               deauth_mac = adapter->event_body +
-                            MWIFIEX_UAP_EVENT_EXTRA_HEADER;
-               cfg80211_del_sta(priv->netdev, deauth_mac, GFP_KERNEL);
-
-               if (priv->ap_11n_enabled) {
-                       mwifiex_11n_del_rx_reorder_tbl_by_ta(priv, deauth_mac);
-                       mwifiex_del_tx_ba_stream_tbl_by_ra(priv, deauth_mac);
-               }
-               mwifiex_wmm_del_peer_ra_list(priv, deauth_mac);
-               mwifiex_del_sta_entry(priv, deauth_mac);
-               break;
-       case EVENT_UAP_BSS_IDLE:
-               priv->media_connected = false;
-               priv->port_open = false;
-               mwifiex_clean_txrx(priv);
-               mwifiex_del_all_sta_list(priv);
-               break;
-       case EVENT_UAP_BSS_ACTIVE:
-               priv->media_connected = true;
-               priv->port_open = true;
-               break;
-       case EVENT_UAP_BSS_START:
-               mwifiex_dbg(adapter, EVENT,
-                           "AP EVENT: event id: %#x\n", eventcause);
-               priv->port_open = false;
-               memcpy(priv->netdev->dev_addr, adapter->event_body + 2,
-                      ETH_ALEN);
-               if (priv->hist_data)
-                       mwifiex_hist_data_reset(priv);
-               mwifiex_check_uap_capabilties(priv, adapter->event_skb);
-               break;
-       case EVENT_UAP_MIC_COUNTERMEASURES:
-               /* For future development */
-               mwifiex_dbg(adapter, EVENT,
-                           "AP EVENT: event id: %#x\n", eventcause);
-               break;
-       case EVENT_AMSDU_AGGR_CTRL:
-               ctrl = le16_to_cpu(*(__le16 *)adapter->event_body);
-               mwifiex_dbg(adapter, EVENT,
-                           "event: AMSDU_AGGR_CTRL %d\n", ctrl);
-
-               if (priv->media_connected) {
-                       adapter->tx_buf_size =
-                               min_t(u16, adapter->curr_tx_buf_size, ctrl);
-                       mwifiex_dbg(adapter, EVENT,
-                                   "event: tx_buf_size %d\n",
-                                   adapter->tx_buf_size);
-               }
-               break;
-       case EVENT_ADDBA:
-               mwifiex_dbg(adapter, EVENT, "event: ADDBA Request\n");
-               if (priv->media_connected)
-                       mwifiex_send_cmd(priv, HostCmd_CMD_11N_ADDBA_RSP,
-                                        HostCmd_ACT_GEN_SET, 0,
-                                        adapter->event_body, false);
-               break;
-       case EVENT_DELBA:
-               mwifiex_dbg(adapter, EVENT, "event: DELBA Request\n");
-               if (priv->media_connected)
-                       mwifiex_11n_delete_ba_stream(priv, adapter->event_body);
-               break;
-       case EVENT_BA_STREAM_TIEMOUT:
-               mwifiex_dbg(adapter, EVENT, "event:  BA Stream timeout\n");
-               if (priv->media_connected) {
-                       ba_timeout = (void *)adapter->event_body;
-                       mwifiex_11n_ba_stream_timeout(priv, ba_timeout);
-               }
-               break;
-       case EVENT_EXT_SCAN_REPORT:
-               mwifiex_dbg(adapter, EVENT, "event: EXT_SCAN Report\n");
-               if (adapter->ext_scan)
-                       return mwifiex_handle_event_ext_scan_report(priv,
-                                               adapter->event_skb->data);
-               break;
-       case EVENT_TX_STATUS_REPORT:
-               mwifiex_dbg(adapter, EVENT, "event: TX_STATUS Report\n");
-               mwifiex_parse_tx_status_event(priv, adapter->event_body);
-               break;
-       case EVENT_PS_SLEEP:
-               mwifiex_dbg(adapter, EVENT, "info: EVENT: SLEEP\n");
-
-               adapter->ps_state = PS_STATE_PRE_SLEEP;
-
-               mwifiex_check_ps_cond(adapter);
-               break;
-
-       case EVENT_PS_AWAKE:
-               mwifiex_dbg(adapter, EVENT, "info: EVENT: AWAKE\n");
-               if (!adapter->pps_uapsd_mode &&
-                   priv->media_connected && adapter->sleep_period.period) {
-                               adapter->pps_uapsd_mode = true;
-                               mwifiex_dbg(adapter, EVENT,
-                                           "event: PPS/UAPSD mode activated\n");
-               }
-               adapter->tx_lock_flag = false;
-               if (adapter->pps_uapsd_mode && adapter->gen_null_pkt) {
-                       if (mwifiex_check_last_packet_indication(priv)) {
-                               if (adapter->data_sent ||
-                                   (adapter->if_ops.is_port_ready &&
-                                    !adapter->if_ops.is_port_ready(priv))) {
-                                       adapter->ps_state = PS_STATE_AWAKE;
-                                       adapter->pm_wakeup_card_req = false;
-                                       adapter->pm_wakeup_fw_try = false;
-                                       break;
-                               }
-                               if (!mwifiex_send_null_packet
-                                       (priv,
-                                        MWIFIEX_TxPD_POWER_MGMT_NULL_PACKET |
-                                        MWIFIEX_TxPD_POWER_MGMT_LAST_PACKET))
-                                               adapter->ps_state =
-                                                       PS_STATE_SLEEP;
-                                       return 0;
-                       }
-               }
-               adapter->ps_state = PS_STATE_AWAKE;
-               adapter->pm_wakeup_card_req = false;
-               adapter->pm_wakeup_fw_try = false;
-               break;
-
-       case EVENT_CHANNEL_REPORT_RDY:
-               mwifiex_dbg(adapter, EVENT, "event: Channel Report\n");
-               mwifiex_11h_handle_chanrpt_ready(priv, adapter->event_skb);
-               break;
-       case EVENT_RADAR_DETECTED:
-               mwifiex_dbg(adapter, EVENT, "event: Radar detected\n");
-               mwifiex_11h_handle_radar_detected(priv, adapter->event_skb);
-               break;
-       case EVENT_BT_COEX_WLAN_PARA_CHANGE:
-               dev_err(adapter->dev, "EVENT: BT coex wlan param update\n");
-               mwifiex_bt_coex_wlan_param_update_event(priv,
-                                                       adapter->event_skb);
-               break;
-       case EVENT_TX_DATA_PAUSE:
-               mwifiex_dbg(adapter, EVENT, "event: TX DATA PAUSE\n");
-               mwifiex_process_tx_pause_event(priv, adapter->event_skb);
-               break;
-
-       case EVENT_MULTI_CHAN_INFO:
-               mwifiex_dbg(adapter, EVENT, "event: multi-chan info\n");
-               mwifiex_process_multi_chan_event(priv, adapter->event_skb);
-               break;
-
-       default:
-               mwifiex_dbg(adapter, EVENT,
-                           "event: unknown event id: %#x\n", eventcause);
-               break;
-       }
-
-       return 0;
-}
-
-/* This function deletes station entry from associated station list.
- * Also if both AP and STA are 11n enabled, RxReorder tables and TxBA stream
- * tables created for this station are deleted.
- */
-void mwifiex_uap_del_sta_data(struct mwifiex_private *priv,
-                             struct mwifiex_sta_node *node)
-{
-       if (priv->ap_11n_enabled && node->is_11n_enabled) {
-               mwifiex_11n_del_rx_reorder_tbl_by_ta(priv, node->mac_addr);
-               mwifiex_del_tx_ba_stream_tbl_by_ra(priv, node->mac_addr);
-       }
-       mwifiex_del_sta_entry(priv, node->mac_addr);
-
-       return;
-}
diff --git a/drivers/net/wireless/mwifiex/uap_txrx.c b/drivers/net/wireless/mwifiex/uap_txrx.c
deleted file mode 100644 (file)
index 74d5d72..0000000
+++ /dev/null
@@ -1,437 +0,0 @@
-/*
- * Marvell Wireless LAN device driver: AP TX and RX data handling
- *
- * Copyright (C) 2012-2014, Marvell International Ltd.
- *
- * This software file (the "File") is distributed by Marvell International
- * Ltd. under the terms of the GNU General Public License Version 2, June 1991
- * (the "License").  You may use, redistribute and/or modify this File in
- * accordance with the terms and conditions of the License, a copy of which
- * is available by writing to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the
- * worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
- *
- * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
- * ARE EXPRESSLY DISCLAIMED.  The License provides additional details about
- * this warranty disclaimer.
- */
-
-#include "decl.h"
-#include "ioctl.h"
-#include "main.h"
-#include "wmm.h"
-#include "11n_aggr.h"
-#include "11n_rxreorder.h"
-
-/* This function checks if particular RA list has packets more than low bridge
- * packet threshold and then deletes packet from this RA list.
- * Function deletes packets from such RA list and returns true. If no such list
- * is found, false is returned.
- */
-static bool
-mwifiex_uap_del_tx_pkts_in_ralist(struct mwifiex_private *priv,
-                                 struct list_head *ra_list_head,
-                                 int tid)
-{
-       struct mwifiex_ra_list_tbl *ra_list;
-       struct sk_buff *skb, *tmp;
-       bool pkt_deleted = false;
-       struct mwifiex_txinfo *tx_info;
-       struct mwifiex_adapter *adapter = priv->adapter;
-
-       list_for_each_entry(ra_list, ra_list_head, list) {
-               if (skb_queue_empty(&ra_list->skb_head))
-                       continue;
-
-               skb_queue_walk_safe(&ra_list->skb_head, skb, tmp) {
-                       tx_info = MWIFIEX_SKB_TXCB(skb);
-                       if (tx_info->flags & MWIFIEX_BUF_FLAG_BRIDGED_PKT) {
-                               __skb_unlink(skb, &ra_list->skb_head);
-                               mwifiex_write_data_complete(adapter, skb, 0,
-                                                           -1);
-                               if (ra_list->tx_paused)
-                                       priv->wmm.pkts_paused[tid]--;
-                               else
-                                       atomic_dec(&priv->wmm.tx_pkts_queued);
-                               pkt_deleted = true;
-                       }
-                       if ((atomic_read(&adapter->pending_bridged_pkts) <=
-                                            MWIFIEX_BRIDGED_PKTS_THR_LOW))
-                               break;
-               }
-       }
-
-       return pkt_deleted;
-}
-
-/* This function deletes packets from particular RA List. RA list index
- * from which packets are deleted is preserved so that packets from next RA
- * list are deleted upon subsequent call thus maintaining fairness.
- */
-static void mwifiex_uap_cleanup_tx_queues(struct mwifiex_private *priv)
-{
-       unsigned long flags;
-       struct list_head *ra_list;
-       int i;
-
-       spin_lock_irqsave(&priv->wmm.ra_list_spinlock, flags);
-
-       for (i = 0; i < MAX_NUM_TID; i++, priv->del_list_idx++) {
-               if (priv->del_list_idx == MAX_NUM_TID)
-                       priv->del_list_idx = 0;
-               ra_list = &priv->wmm.tid_tbl_ptr[priv->del_list_idx].ra_list;
-               if (mwifiex_uap_del_tx_pkts_in_ralist(priv, ra_list, i)) {
-                       priv->del_list_idx++;
-                       break;
-               }
-       }
-
-       spin_unlock_irqrestore(&priv->wmm.ra_list_spinlock, flags);
-}
-
-
-static void mwifiex_uap_queue_bridged_pkt(struct mwifiex_private *priv,
-                                        struct sk_buff *skb)
-{
-       struct mwifiex_adapter *adapter = priv->adapter;
-       struct uap_rxpd *uap_rx_pd;
-       struct rx_packet_hdr *rx_pkt_hdr;
-       struct sk_buff *new_skb;
-       struct mwifiex_txinfo *tx_info;
-       int hdr_chop;
-       struct ethhdr *p_ethhdr;
-       struct mwifiex_sta_node *src_node;
-
-       uap_rx_pd = (struct uap_rxpd *)(skb->data);
-       rx_pkt_hdr = (void *)uap_rx_pd + le16_to_cpu(uap_rx_pd->rx_pkt_offset);
-
-       if ((atomic_read(&adapter->pending_bridged_pkts) >=
-                                            MWIFIEX_BRIDGED_PKTS_THR_HIGH)) {
-               mwifiex_dbg(priv->adapter, ERROR,
-                           "Tx: Bridge packet limit reached. Drop packet!\n");
-               kfree_skb(skb);
-               mwifiex_uap_cleanup_tx_queues(priv);
-               return;
-       }
-
-       if ((!memcmp(&rx_pkt_hdr->rfc1042_hdr, bridge_tunnel_header,
-                    sizeof(bridge_tunnel_header))) ||
-           (!memcmp(&rx_pkt_hdr->rfc1042_hdr, rfc1042_header,
-                    sizeof(rfc1042_header)) &&
-            ntohs(rx_pkt_hdr->rfc1042_hdr.snap_type) != ETH_P_AARP &&
-            ntohs(rx_pkt_hdr->rfc1042_hdr.snap_type) != ETH_P_IPX)) {
-               /* Replace the 803 header and rfc1042 header (llc/snap) with
-                * an Ethernet II header, keep the src/dst and snap_type
-                * (ethertype).
-                *
-                * The firmware only passes up SNAP frames converting all RX
-                * data from 802.11 to 802.2/LLC/SNAP frames.
-                *
-                * To create the Ethernet II, just move the src, dst address
-                * right before the snap_type.
-                */
-               p_ethhdr = (struct ethhdr *)
-                       ((u8 *)(&rx_pkt_hdr->eth803_hdr)
-                        + sizeof(rx_pkt_hdr->eth803_hdr)
-                        + sizeof(rx_pkt_hdr->rfc1042_hdr)
-                        - sizeof(rx_pkt_hdr->eth803_hdr.h_dest)
-                        - sizeof(rx_pkt_hdr->eth803_hdr.h_source)
-                        - sizeof(rx_pkt_hdr->rfc1042_hdr.snap_type));
-               memcpy(p_ethhdr->h_source, rx_pkt_hdr->eth803_hdr.h_source,
-                      sizeof(p_ethhdr->h_source));
-               memcpy(p_ethhdr->h_dest, rx_pkt_hdr->eth803_hdr.h_dest,
-                      sizeof(p_ethhdr->h_dest));
-               /* Chop off the rxpd + the excess memory from
-                * 802.2/llc/snap header that was removed.
-                */
-               hdr_chop = (u8 *)p_ethhdr - (u8 *)uap_rx_pd;
-       } else {
-               /* Chop off the rxpd */
-               hdr_chop = (u8 *)&rx_pkt_hdr->eth803_hdr - (u8 *)uap_rx_pd;
-       }
-
-       /* Chop off the leading header bytes so that it points
-        * to the start of either the reconstructed EthII frame
-        * or the 802.2/llc/snap frame.
-        */
-       skb_pull(skb, hdr_chop);
-
-       if (skb_headroom(skb) < MWIFIEX_MIN_DATA_HEADER_LEN) {
-               mwifiex_dbg(priv->adapter, ERROR,
-                           "data: Tx: insufficient skb headroom %d\n",
-                           skb_headroom(skb));
-               /* Insufficient skb headroom - allocate a new skb */
-               new_skb =
-                       skb_realloc_headroom(skb, MWIFIEX_MIN_DATA_HEADER_LEN);
-               if (unlikely(!new_skb)) {
-                       mwifiex_dbg(priv->adapter, ERROR,
-                                   "Tx: cannot allocate new_skb\n");
-                       kfree_skb(skb);
-                       priv->stats.tx_dropped++;
-                       return;
-               }
-
-               kfree_skb(skb);
-               skb = new_skb;
-               mwifiex_dbg(priv->adapter, INFO,
-                           "info: new skb headroom %d\n",
-                           skb_headroom(skb));
-       }
-
-       tx_info = MWIFIEX_SKB_TXCB(skb);
-       memset(tx_info, 0, sizeof(*tx_info));
-       tx_info->bss_num = priv->bss_num;
-       tx_info->bss_type = priv->bss_type;
-       tx_info->flags |= MWIFIEX_BUF_FLAG_BRIDGED_PKT;
-
-       src_node = mwifiex_get_sta_entry(priv, rx_pkt_hdr->eth803_hdr.h_source);
-       if (src_node) {
-               src_node->stats.last_rx = jiffies;
-               src_node->stats.rx_bytes += skb->len;
-               src_node->stats.rx_packets++;
-               src_node->stats.last_tx_rate = uap_rx_pd->rx_rate;
-               src_node->stats.last_tx_htinfo = uap_rx_pd->ht_info;
-       }
-
-       if (is_unicast_ether_addr(rx_pkt_hdr->eth803_hdr.h_dest)) {
-               /* Update bridge packet statistics as the
-                * packet is not going to kernel/upper layer.
-                */
-               priv->stats.rx_bytes += skb->len;
-               priv->stats.rx_packets++;
-
-               /* Sending bridge packet to TX queue, so save the packet
-                * length in TXCB to update statistics in TX complete.
-                */
-               tx_info->pkt_len = skb->len;
-       }
-
-       __net_timestamp(skb);
-       mwifiex_wmm_add_buf_txqueue(priv, skb);
-       atomic_inc(&adapter->tx_pending);
-       atomic_inc(&adapter->pending_bridged_pkts);
-
-       return;
-}
-
-/*
- * This function contains logic for AP packet forwarding.
- *
- * If a packet is multicast/broadcast, it is sent to kernel/upper layer
- * as well as queued back to AP TX queue so that it can be sent to other
- * associated stations.
- * If a packet is unicast and RA is present in associated station list,
- * it is again requeued into AP TX queue.
- * If a packet is unicast and RA is not in associated station list,
- * packet is forwarded to kernel to handle routing logic.
- */
-int mwifiex_handle_uap_rx_forward(struct mwifiex_private *priv,
-                                 struct sk_buff *skb)
-{
-       struct mwifiex_adapter *adapter = priv->adapter;
-       struct uap_rxpd *uap_rx_pd;
-       struct rx_packet_hdr *rx_pkt_hdr;
-       u8 ra[ETH_ALEN];
-       struct sk_buff *skb_uap;
-
-       uap_rx_pd = (struct uap_rxpd *)(skb->data);
-       rx_pkt_hdr = (void *)uap_rx_pd + le16_to_cpu(uap_rx_pd->rx_pkt_offset);
-
-       /* don't do packet forwarding in disconnected state */
-       if (!priv->media_connected) {
-               mwifiex_dbg(adapter, ERROR,
-                           "drop packet in disconnected state.\n");
-               dev_kfree_skb_any(skb);
-               return 0;
-       }
-
-       memcpy(ra, rx_pkt_hdr->eth803_hdr.h_dest, ETH_ALEN);
-
-       if (is_multicast_ether_addr(ra)) {
-               skb_uap = skb_copy(skb, GFP_ATOMIC);
-               mwifiex_uap_queue_bridged_pkt(priv, skb_uap);
-       } else {
-               if (mwifiex_get_sta_entry(priv, ra)) {
-                       /* Requeue Intra-BSS packet */
-                       mwifiex_uap_queue_bridged_pkt(priv, skb);
-                       return 0;
-               }
-       }
-
-       /* Forward unicat/Inter-BSS packets to kernel. */
-       return mwifiex_process_rx_packet(priv, skb);
-}
-
-/*
- * This function processes the packet received on AP interface.
- *
- * The function looks into the RxPD and performs sanity tests on the
- * received buffer to ensure its a valid packet before processing it
- * further. If the packet is determined to be aggregated, it is
- * de-aggregated accordingly. Then skb is passed to AP packet forwarding logic.
- *
- * The completion callback is called after processing is complete.
- */
-int mwifiex_process_uap_rx_packet(struct mwifiex_private *priv,
-                                 struct sk_buff *skb)
-{
-       struct mwifiex_adapter *adapter = priv->adapter;
-       int ret;
-       struct uap_rxpd *uap_rx_pd;
-       struct rx_packet_hdr *rx_pkt_hdr;
-       u16 rx_pkt_type;
-       u8 ta[ETH_ALEN], pkt_type;
-       unsigned long flags;
-       struct mwifiex_sta_node *node;
-
-       uap_rx_pd = (struct uap_rxpd *)(skb->data);
-       rx_pkt_type = le16_to_cpu(uap_rx_pd->rx_pkt_type);
-       rx_pkt_hdr = (void *)uap_rx_pd + le16_to_cpu(uap_rx_pd->rx_pkt_offset);
-
-       ether_addr_copy(ta, rx_pkt_hdr->eth803_hdr.h_source);
-
-       if ((le16_to_cpu(uap_rx_pd->rx_pkt_offset) +
-            le16_to_cpu(uap_rx_pd->rx_pkt_length)) > (u16) skb->len) {
-               mwifiex_dbg(adapter, ERROR,
-                           "wrong rx packet: len=%d, offset=%d, length=%d\n",
-                           skb->len, le16_to_cpu(uap_rx_pd->rx_pkt_offset),
-                           le16_to_cpu(uap_rx_pd->rx_pkt_length));
-               priv->stats.rx_dropped++;
-
-               node = mwifiex_get_sta_entry(priv, ta);
-               if (node)
-                       node->stats.tx_failed++;
-
-               dev_kfree_skb_any(skb);
-               return 0;
-       }
-
-       if (rx_pkt_type == PKT_TYPE_MGMT) {
-               ret = mwifiex_process_mgmt_packet(priv, skb);
-               if (ret)
-                       mwifiex_dbg(adapter, ERROR,
-                                   "Rx of mgmt packet failed");
-               dev_kfree_skb_any(skb);
-               return ret;
-       }
-
-
-       if (rx_pkt_type != PKT_TYPE_BAR && uap_rx_pd->priority < MAX_NUM_TID) {
-               spin_lock_irqsave(&priv->sta_list_spinlock, flags);
-               node = mwifiex_get_sta_entry(priv, ta);
-               if (node)
-                       node->rx_seq[uap_rx_pd->priority] =
-                                               le16_to_cpu(uap_rx_pd->seq_num);
-               spin_unlock_irqrestore(&priv->sta_list_spinlock, flags);
-       }
-
-       if (!priv->ap_11n_enabled ||
-           (!mwifiex_11n_get_rx_reorder_tbl(priv, uap_rx_pd->priority, ta) &&
-           (le16_to_cpu(uap_rx_pd->rx_pkt_type) != PKT_TYPE_AMSDU))) {
-               ret = mwifiex_handle_uap_rx_forward(priv, skb);
-               return ret;
-       }
-
-       /* Reorder and send to kernel */
-       pkt_type = (u8)le16_to_cpu(uap_rx_pd->rx_pkt_type);
-       ret = mwifiex_11n_rx_reorder_pkt(priv, le16_to_cpu(uap_rx_pd->seq_num),
-                                        uap_rx_pd->priority, ta, pkt_type,
-                                        skb);
-
-       if (ret || (rx_pkt_type == PKT_TYPE_BAR))
-               dev_kfree_skb_any(skb);
-
-       if (ret)
-               priv->stats.rx_dropped++;
-
-       return ret;
-}
-
-/*
- * This function fills the TxPD for AP tx packets.
- *
- * The Tx buffer received by this function should already have the
- * header space allocated for TxPD.
- *
- * This function inserts the TxPD in between interface header and actual
- * data and adjusts the buffer pointers accordingly.
- *
- * The following TxPD fields are set by this function, as required -
- *      - BSS number
- *      - Tx packet length and offset
- *      - Priority
- *      - Packet delay
- *      - Priority specific Tx control
- *      - Flags
- */
-void *mwifiex_process_uap_txpd(struct mwifiex_private *priv,
-                              struct sk_buff *skb)
-{
-       struct mwifiex_adapter *adapter = priv->adapter;
-       struct uap_txpd *txpd;
-       struct mwifiex_txinfo *tx_info = MWIFIEX_SKB_TXCB(skb);
-       int pad;
-       u16 pkt_type, pkt_offset;
-       int hroom = (priv->adapter->iface_type == MWIFIEX_USB) ? 0 :
-                      INTF_HEADER_LEN;
-
-       if (!skb->len) {
-               mwifiex_dbg(adapter, ERROR,
-                           "Tx: bad packet length: %d\n", skb->len);
-               tx_info->status_code = -1;
-               return skb->data;
-       }
-
-       BUG_ON(skb_headroom(skb) < MWIFIEX_MIN_DATA_HEADER_LEN);
-
-       pkt_type = mwifiex_is_skb_mgmt_frame(skb) ? PKT_TYPE_MGMT : 0;
-
-       pad = ((void *)skb->data - (sizeof(*txpd) + hroom) - NULL) &
-                       (MWIFIEX_DMA_ALIGN_SZ - 1);
-
-       skb_push(skb, sizeof(*txpd) + pad);
-
-       txpd = (struct uap_txpd *)skb->data;
-       memset(txpd, 0, sizeof(*txpd));
-       txpd->bss_num = priv->bss_num;
-       txpd->bss_type = priv->bss_type;
-       txpd->tx_pkt_length = cpu_to_le16((u16)(skb->len - (sizeof(*txpd) +
-                                               pad)));
-       txpd->priority = (u8)skb->priority;
-
-       txpd->pkt_delay_2ms = mwifiex_wmm_compute_drv_pkt_delay(priv, skb);
-
-       if (tx_info->flags & MWIFIEX_BUF_FLAG_EAPOL_TX_STATUS ||
-           tx_info->flags & MWIFIEX_BUF_FLAG_ACTION_TX_STATUS) {
-               txpd->tx_token_id = tx_info->ack_frame_id;
-               txpd->flags |= MWIFIEX_TXPD_FLAGS_REQ_TX_STATUS;
-       }
-
-       if (txpd->priority < ARRAY_SIZE(priv->wmm.user_pri_pkt_tx_ctrl))
-               /*
-                * Set the priority specific tx_control field, setting of 0 will
-                * cause the default value to be used later in this function.
-                */
-               txpd->tx_control =
-                   cpu_to_le32(priv->wmm.user_pri_pkt_tx_ctrl[txpd->priority]);
-
-       /* Offset of actual data */
-       pkt_offset = sizeof(*txpd) + pad;
-       if (pkt_type == PKT_TYPE_MGMT) {
-               /* Set the packet type and add header for management frame */
-               txpd->tx_pkt_type = cpu_to_le16(pkt_type);
-               pkt_offset += MWIFIEX_MGMT_FRAME_HEADER_SIZE;
-       }
-
-       txpd->tx_pkt_offset = cpu_to_le16(pkt_offset);
-
-       /* make space for INTF_HEADER_LEN */
-       skb_push(skb, hroom);
-
-       if (!txpd->tx_control)
-               /* TxCtrl set by user or default */
-               txpd->tx_control = cpu_to_le32(priv->pkt_tx_ctrl);
-
-       return skb->data;
-}
diff --git a/drivers/net/wireless/mwifiex/usb.c b/drivers/net/wireless/mwifiex/usb.c
deleted file mode 100644 (file)
index e43aff9..0000000
+++ /dev/null
@@ -1,1267 +0,0 @@
-/*
- * Marvell Wireless LAN device driver: USB specific handling
- *
- * Copyright (C) 2012-2014, Marvell International Ltd.
- *
- * This software file (the "File") is distributed by Marvell International
- * Ltd. under the terms of the GNU General Public License Version 2, June 1991
- * (the "License").  You may use, redistribute and/or modify this File in
- * accordance with the terms and conditions of the License, a copy of which
- * is available by writing to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the
- * worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
- *
- * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
- * ARE EXPRESSLY DISCLAIMED.  The License provides additional details about
- * this warranty disclaimer.
- */
-
-#include "main.h"
-#include "usb.h"
-
-#define USB_VERSION    "1.0"
-
-static u8 user_rmmod;
-static struct mwifiex_if_ops usb_ops;
-static struct semaphore add_remove_card_sem;
-
-static struct usb_device_id mwifiex_usb_table[] = {
-       /* 8766 */
-       {USB_DEVICE(USB8XXX_VID, USB8766_PID_1)},
-       {USB_DEVICE_AND_INTERFACE_INFO(USB8XXX_VID, USB8766_PID_2,
-                                      USB_CLASS_VENDOR_SPEC,
-                                      USB_SUBCLASS_VENDOR_SPEC, 0xff)},
-       /* 8797 */
-       {USB_DEVICE(USB8XXX_VID, USB8797_PID_1)},
-       {USB_DEVICE_AND_INTERFACE_INFO(USB8XXX_VID, USB8797_PID_2,
-                                      USB_CLASS_VENDOR_SPEC,
-                                      USB_SUBCLASS_VENDOR_SPEC, 0xff)},
-       /* 8801 */
-       {USB_DEVICE(USB8XXX_VID, USB8801_PID_1)},
-       {USB_DEVICE_AND_INTERFACE_INFO(USB8XXX_VID, USB8801_PID_2,
-                                      USB_CLASS_VENDOR_SPEC,
-                                      USB_SUBCLASS_VENDOR_SPEC, 0xff)},
-       /* 8997 */
-       {USB_DEVICE(USB8XXX_VID, USB8997_PID_1)},
-       {USB_DEVICE_AND_INTERFACE_INFO(USB8XXX_VID, USB8997_PID_2,
-                                      USB_CLASS_VENDOR_SPEC,
-                                      USB_SUBCLASS_VENDOR_SPEC, 0xff)},
-       { }     /* Terminating entry */
-};
-
-MODULE_DEVICE_TABLE(usb, mwifiex_usb_table);
-
-static int mwifiex_usb_submit_rx_urb(struct urb_context *ctx, int size);
-
-/* This function handles received packet. Necessary action is taken based on
- * cmd/event/data.
- */
-static int mwifiex_usb_recv(struct mwifiex_adapter *adapter,
-                           struct sk_buff *skb, u8 ep)
-{
-       u32 recv_type;
-       __le32 tmp;
-       int ret;
-
-       if (adapter->hs_activated)
-               mwifiex_process_hs_config(adapter);
-
-       if (skb->len < INTF_HEADER_LEN) {
-               mwifiex_dbg(adapter, ERROR,
-                           "%s: invalid skb->len\n", __func__);
-               return -1;
-       }
-
-       switch (ep) {
-       case MWIFIEX_USB_EP_CMD_EVENT:
-               mwifiex_dbg(adapter, EVENT,
-                           "%s: EP_CMD_EVENT\n", __func__);
-               skb_copy_from_linear_data(skb, &tmp, INTF_HEADER_LEN);
-               recv_type = le32_to_cpu(tmp);
-               skb_pull(skb, INTF_HEADER_LEN);
-
-               switch (recv_type) {
-               case MWIFIEX_USB_TYPE_CMD:
-                       if (skb->len > MWIFIEX_SIZE_OF_CMD_BUFFER) {
-                               mwifiex_dbg(adapter, ERROR,
-                                           "CMD: skb->len too large\n");
-                               ret = -1;
-                               goto exit_restore_skb;
-                       } else if (!adapter->curr_cmd) {
-                               mwifiex_dbg(adapter, WARN, "CMD: no curr_cmd\n");
-                               if (adapter->ps_state == PS_STATE_SLEEP_CFM) {
-                                       mwifiex_process_sleep_confirm_resp(
-                                                       adapter, skb->data,
-                                                       skb->len);
-                                       ret = 0;
-                                       goto exit_restore_skb;
-                               }
-                               ret = -1;
-                               goto exit_restore_skb;
-                       }
-
-                       adapter->curr_cmd->resp_skb = skb;
-                       adapter->cmd_resp_received = true;
-                       break;
-               case MWIFIEX_USB_TYPE_EVENT:
-                       if (skb->len < sizeof(u32)) {
-                               mwifiex_dbg(adapter, ERROR,
-                                           "EVENT: skb->len too small\n");
-                               ret = -1;
-                               goto exit_restore_skb;
-                       }
-                       skb_copy_from_linear_data(skb, &tmp, sizeof(u32));
-                       adapter->event_cause = le32_to_cpu(tmp);
-                       mwifiex_dbg(adapter, EVENT,
-                                   "event_cause %#x\n", adapter->event_cause);
-
-                       if (skb->len > MAX_EVENT_SIZE) {
-                               mwifiex_dbg(adapter, ERROR,
-                                           "EVENT: event body too large\n");
-                               ret = -1;
-                               goto exit_restore_skb;
-                       }
-
-                       memcpy(adapter->event_body, skb->data +
-                              MWIFIEX_EVENT_HEADER_LEN, skb->len);
-
-                       adapter->event_received = true;
-                       adapter->event_skb = skb;
-                       break;
-               default:
-                       mwifiex_dbg(adapter, ERROR,
-                                   "unknown recv_type %#x\n", recv_type);
-                       return -1;
-               }
-               break;
-       case MWIFIEX_USB_EP_DATA:
-               mwifiex_dbg(adapter, DATA, "%s: EP_DATA\n", __func__);
-               if (skb->len > MWIFIEX_RX_DATA_BUF_SIZE) {
-                       mwifiex_dbg(adapter, ERROR,
-                                   "DATA: skb->len too large\n");
-                       return -1;
-               }
-
-               skb_queue_tail(&adapter->rx_data_q, skb);
-               adapter->data_received = true;
-               atomic_inc(&adapter->rx_pending);
-               break;
-       default:
-               mwifiex_dbg(adapter, ERROR,
-                           "%s: unknown endport %#x\n", __func__, ep);
-               return -1;
-       }
-
-       return -EINPROGRESS;
-
-exit_restore_skb:
-       /* The buffer will be reused for further cmds/events */
-       skb_push(skb, INTF_HEADER_LEN);
-
-       return ret;
-}
-
-static void mwifiex_usb_rx_complete(struct urb *urb)
-{
-       struct urb_context *context = (struct urb_context *)urb->context;
-       struct mwifiex_adapter *adapter = context->adapter;
-       struct sk_buff *skb = context->skb;
-       struct usb_card_rec *card;
-       int recv_length = urb->actual_length;
-       int size, status;
-
-       if (!adapter || !adapter->card) {
-               pr_err("mwifiex adapter or card structure is not valid\n");
-               return;
-       }
-
-       card = (struct usb_card_rec *)adapter->card;
-       if (card->rx_cmd_ep == context->ep)
-               atomic_dec(&card->rx_cmd_urb_pending);
-       else
-               atomic_dec(&card->rx_data_urb_pending);
-
-       if (recv_length) {
-               if (urb->status || (adapter->surprise_removed)) {
-                       mwifiex_dbg(adapter, ERROR,
-                                   "URB status is failed: %d\n", urb->status);
-                       /* Do not free skb in case of command ep */
-                       if (card->rx_cmd_ep != context->ep)
-                               dev_kfree_skb_any(skb);
-                       goto setup_for_next;
-               }
-               if (skb->len > recv_length)
-                       skb_trim(skb, recv_length);
-               else
-                       skb_put(skb, recv_length - skb->len);
-
-               status = mwifiex_usb_recv(adapter, skb, context->ep);
-
-               mwifiex_dbg(adapter, INFO,
-                           "info: recv_length=%d, status=%d\n",
-                           recv_length, status);
-               if (status == -EINPROGRESS) {
-                       mwifiex_queue_main_work(adapter);
-
-                       /* urb for data_ep is re-submitted now;
-                        * urb for cmd_ep will be re-submitted in callback
-                        * mwifiex_usb_recv_complete
-                        */
-                       if (card->rx_cmd_ep == context->ep)
-                               return;
-               } else {
-                       if (status == -1)
-                               mwifiex_dbg(adapter, ERROR,
-                                           "received data processing failed!\n");
-
-                       /* Do not free skb in case of command ep */
-                       if (card->rx_cmd_ep != context->ep)
-                               dev_kfree_skb_any(skb);
-               }
-       } else if (urb->status) {
-               if (!adapter->is_suspended) {
-                       mwifiex_dbg(adapter, FATAL,
-                                   "Card is removed: %d\n", urb->status);
-                       adapter->surprise_removed = true;
-               }
-               dev_kfree_skb_any(skb);
-               return;
-       } else {
-               /* Do not free skb in case of command ep */
-               if (card->rx_cmd_ep != context->ep)
-                       dev_kfree_skb_any(skb);
-
-               /* fall through setup_for_next */
-       }
-
-setup_for_next:
-       if (card->rx_cmd_ep == context->ep)
-               size = MWIFIEX_RX_CMD_BUF_SIZE;
-       else
-               size = MWIFIEX_RX_DATA_BUF_SIZE;
-
-       if (card->rx_cmd_ep == context->ep) {
-               mwifiex_usb_submit_rx_urb(context, size);
-       } else {
-               if (atomic_read(&adapter->rx_pending) <= HIGH_RX_PENDING){
-                       mwifiex_usb_submit_rx_urb(context, size);
-               }else{
-                       context->skb = NULL;
-               }
-       }
-
-       return;
-}
-
-static void mwifiex_usb_tx_complete(struct urb *urb)
-{
-       struct urb_context *context = (struct urb_context *)(urb->context);
-       struct mwifiex_adapter *adapter = context->adapter;
-       struct usb_card_rec *card = adapter->card;
-       struct usb_tx_data_port *port;
-       int i;
-
-       mwifiex_dbg(adapter, INFO,
-                   "%s: status: %d\n", __func__, urb->status);
-
-       if (context->ep == card->tx_cmd_ep) {
-               mwifiex_dbg(adapter, CMD,
-                           "%s: CMD\n", __func__);
-               atomic_dec(&card->tx_cmd_urb_pending);
-               adapter->cmd_sent = false;
-       } else {
-               mwifiex_dbg(adapter, DATA,
-                           "%s: DATA\n", __func__);
-               for (i = 0; i < MWIFIEX_TX_DATA_PORT; i++) {
-                       port = &card->port[i];
-                       if (context->ep == port->tx_data_ep) {
-                               atomic_dec(&port->tx_data_urb_pending);
-                               port->block_status = false;
-                               break;
-                       }
-               }
-               adapter->data_sent = false;
-               mwifiex_write_data_complete(adapter, context->skb, 0,
-                                           urb->status ? -1 : 0);
-       }
-
-       if (card->mc_resync_flag)
-               mwifiex_multi_chan_resync(adapter);
-
-       mwifiex_queue_main_work(adapter);
-
-       return;
-}
-
-static int mwifiex_usb_submit_rx_urb(struct urb_context *ctx, int size)
-{
-       struct mwifiex_adapter *adapter = ctx->adapter;
-       struct usb_card_rec *card = (struct usb_card_rec *)adapter->card;
-
-       if (card->rx_cmd_ep != ctx->ep) {
-               ctx->skb = dev_alloc_skb(size);
-               if (!ctx->skb) {
-                       mwifiex_dbg(adapter, ERROR,
-                                   "%s: dev_alloc_skb failed\n", __func__);
-                       return -ENOMEM;
-               }
-       }
-
-       usb_fill_bulk_urb(ctx->urb, card->udev,
-                         usb_rcvbulkpipe(card->udev, ctx->ep), ctx->skb->data,
-                         size, mwifiex_usb_rx_complete, (void *)ctx);
-
-       if (card->rx_cmd_ep == ctx->ep)
-               atomic_inc(&card->rx_cmd_urb_pending);
-       else
-               atomic_inc(&card->rx_data_urb_pending);
-
-       if (usb_submit_urb(ctx->urb, GFP_ATOMIC)) {
-               mwifiex_dbg(adapter, ERROR, "usb_submit_urb failed\n");
-               dev_kfree_skb_any(ctx->skb);
-               ctx->skb = NULL;
-
-               if (card->rx_cmd_ep == ctx->ep)
-                       atomic_dec(&card->rx_cmd_urb_pending);
-               else
-                       atomic_dec(&card->rx_data_urb_pending);
-
-               return -1;
-       }
-
-       return 0;
-}
-
-static void mwifiex_usb_free(struct usb_card_rec *card)
-{
-       struct usb_tx_data_port *port;
-       int i, j;
-
-       if (atomic_read(&card->rx_cmd_urb_pending) && card->rx_cmd.urb)
-               usb_kill_urb(card->rx_cmd.urb);
-
-       usb_free_urb(card->rx_cmd.urb);
-       card->rx_cmd.urb = NULL;
-
-       if (atomic_read(&card->rx_data_urb_pending))
-               for (i = 0; i < MWIFIEX_RX_DATA_URB; i++)
-                       if (card->rx_data_list[i].urb)
-                               usb_kill_urb(card->rx_data_list[i].urb);
-
-       for (i = 0; i < MWIFIEX_RX_DATA_URB; i++) {
-               usb_free_urb(card->rx_data_list[i].urb);
-               card->rx_data_list[i].urb = NULL;
-       }
-
-       for (i = 0; i < MWIFIEX_TX_DATA_PORT; i++) {
-               port = &card->port[i];
-               for (j = 0; j < MWIFIEX_TX_DATA_URB; j++) {
-                       usb_free_urb(port->tx_data_list[j].urb);
-                       port->tx_data_list[j].urb = NULL;
-               }
-       }
-
-       usb_free_urb(card->tx_cmd.urb);
-       card->tx_cmd.urb = NULL;
-
-       return;
-}
-
-/* This function probes an mwifiex device and registers it. It allocates
- * the card structure, initiates the device registration and initialization
- * procedure by adding a logical interface.
- */
-static int mwifiex_usb_probe(struct usb_interface *intf,
-                            const struct usb_device_id *id)
-{
-       struct usb_device *udev = interface_to_usbdev(intf);
-       struct usb_host_interface *iface_desc = intf->cur_altsetting;
-       struct usb_endpoint_descriptor *epd;
-       int ret, i;
-       struct usb_card_rec *card;
-       u16 id_vendor, id_product, bcd_device, bcd_usb;
-
-       card = kzalloc(sizeof(struct usb_card_rec), GFP_KERNEL);
-       if (!card)
-               return -ENOMEM;
-
-       id_vendor = le16_to_cpu(udev->descriptor.idVendor);
-       id_product = le16_to_cpu(udev->descriptor.idProduct);
-       bcd_device = le16_to_cpu(udev->descriptor.bcdDevice);
-       bcd_usb = le16_to_cpu(udev->descriptor.bcdUSB);
-       pr_debug("info: VID/PID = %X/%X, Boot2 version = %X\n",
-                id_vendor, id_product, bcd_device);
-
-       /* PID_1 is used for firmware downloading only */
-       switch (id_product) {
-       case USB8766_PID_1:
-       case USB8797_PID_1:
-       case USB8801_PID_1:
-       case USB8997_PID_1:
-               card->usb_boot_state = USB8XXX_FW_DNLD;
-               break;
-       case USB8766_PID_2:
-       case USB8797_PID_2:
-       case USB8801_PID_2:
-       case USB8997_PID_2:
-               card->usb_boot_state = USB8XXX_FW_READY;
-               break;
-       default:
-               pr_warn("unknown id_product %#x\n", id_product);
-               card->usb_boot_state = USB8XXX_FW_DNLD;
-               break;
-       }
-
-       card->udev = udev;
-       card->intf = intf;
-
-       pr_debug("info: bcdUSB=%#x Device Class=%#x SubClass=%#x Protocol=%#x\n",
-                udev->descriptor.bcdUSB, udev->descriptor.bDeviceClass,
-                udev->descriptor.bDeviceSubClass,
-                udev->descriptor.bDeviceProtocol);
-
-       for (i = 0; i < iface_desc->desc.bNumEndpoints; ++i) {
-               epd = &iface_desc->endpoint[i].desc;
-               if (usb_endpoint_dir_in(epd) &&
-                   usb_endpoint_num(epd) == MWIFIEX_USB_EP_CMD_EVENT &&
-                   usb_endpoint_xfer_bulk(epd)) {
-                       pr_debug("info: bulk IN: max pkt size: %d, addr: %d\n",
-                                le16_to_cpu(epd->wMaxPacketSize),
-                                epd->bEndpointAddress);
-                       card->rx_cmd_ep = usb_endpoint_num(epd);
-                       atomic_set(&card->rx_cmd_urb_pending, 0);
-               }
-               if (usb_endpoint_dir_in(epd) &&
-                   usb_endpoint_num(epd) == MWIFIEX_USB_EP_DATA &&
-                   usb_endpoint_xfer_bulk(epd)) {
-                       pr_debug("info: bulk IN: max pkt size: %d, addr: %d\n",
-                                le16_to_cpu(epd->wMaxPacketSize),
-                                epd->bEndpointAddress);
-                       card->rx_data_ep = usb_endpoint_num(epd);
-                       atomic_set(&card->rx_data_urb_pending, 0);
-               }
-               if (usb_endpoint_dir_out(epd) &&
-                   usb_endpoint_num(epd) == MWIFIEX_USB_EP_DATA &&
-                   usb_endpoint_xfer_bulk(epd)) {
-                       pr_debug("info: bulk OUT: max pkt size: %d, addr: %d\n",
-                                le16_to_cpu(epd->wMaxPacketSize),
-                                epd->bEndpointAddress);
-                       card->port[0].tx_data_ep = usb_endpoint_num(epd);
-                       atomic_set(&card->port[0].tx_data_urb_pending, 0);
-               }
-               if (usb_endpoint_dir_out(epd) &&
-                   usb_endpoint_num(epd) == MWIFIEX_USB_EP_DATA_CH2 &&
-                   usb_endpoint_xfer_bulk(epd)) {
-                       pr_debug("info: bulk OUT chan2:\t"
-                                "max pkt size: %d, addr: %d\n",
-                                le16_to_cpu(epd->wMaxPacketSize),
-                                epd->bEndpointAddress);
-                       card->port[1].tx_data_ep = usb_endpoint_num(epd);
-                       atomic_set(&card->port[1].tx_data_urb_pending, 0);
-               }
-               if (usb_endpoint_dir_out(epd) &&
-                   usb_endpoint_num(epd) == MWIFIEX_USB_EP_CMD_EVENT &&
-                   usb_endpoint_xfer_bulk(epd)) {
-                       pr_debug("info: bulk OUT: max pkt size: %d, addr: %d\n",
-                                le16_to_cpu(epd->wMaxPacketSize),
-                                epd->bEndpointAddress);
-                       card->tx_cmd_ep = usb_endpoint_num(epd);
-                       atomic_set(&card->tx_cmd_urb_pending, 0);
-                       card->bulk_out_maxpktsize =
-                                       le16_to_cpu(epd->wMaxPacketSize);
-               }
-       }
-
-       usb_set_intfdata(intf, card);
-
-       ret = mwifiex_add_card(card, &add_remove_card_sem, &usb_ops,
-                              MWIFIEX_USB);
-       if (ret) {
-               pr_err("%s: mwifiex_add_card failed: %d\n", __func__, ret);
-               usb_reset_device(udev);
-               kfree(card);
-               return ret;
-       }
-
-       usb_get_dev(udev);
-
-       return 0;
-}
-
-/* Kernel needs to suspend all functions separately. Therefore all
- * registered functions must have drivers with suspend and resume
- * methods. Failing that the kernel simply removes the whole card.
- *
- * If already not suspended, this function allocates and sends a
- * 'host sleep activate' request to the firmware and turns off the traffic.
- */
-static int mwifiex_usb_suspend(struct usb_interface *intf, pm_message_t message)
-{
-       struct usb_card_rec *card = usb_get_intfdata(intf);
-       struct mwifiex_adapter *adapter;
-       struct usb_tx_data_port *port;
-       int i, j;
-
-       if (!card || !card->adapter) {
-               pr_err("%s: card or card->adapter is NULL\n", __func__);
-               return 0;
-       }
-       adapter = card->adapter;
-
-       if (unlikely(adapter->is_suspended))
-               mwifiex_dbg(adapter, WARN,
-                           "Device already suspended\n");
-
-       mwifiex_enable_hs(adapter);
-
-       /* 'is_suspended' flag indicates device is suspended.
-        * It must be set here before the usb_kill_urb() calls. Reason
-        * is in the complete handlers, urb->status(= -ENOENT) and
-        * this flag is used in combination to distinguish between a
-        * 'suspended' state and a 'disconnect' one.
-        */
-       adapter->is_suspended = true;
-       adapter->hs_enabling = false;
-
-       if (atomic_read(&card->rx_cmd_urb_pending) && card->rx_cmd.urb)
-               usb_kill_urb(card->rx_cmd.urb);
-
-       if (atomic_read(&card->rx_data_urb_pending))
-               for (i = 0; i < MWIFIEX_RX_DATA_URB; i++)
-                       if (card->rx_data_list[i].urb)
-                               usb_kill_urb(card->rx_data_list[i].urb);
-
-       for (i = 0; i < MWIFIEX_TX_DATA_PORT; i++) {
-               port = &card->port[i];
-               for (j = 0; j < MWIFIEX_TX_DATA_URB; j++) {
-                       if (port->tx_data_list[j].urb)
-                               usb_kill_urb(port->tx_data_list[j].urb);
-               }
-       }
-
-       if (card->tx_cmd.urb)
-               usb_kill_urb(card->tx_cmd.urb);
-
-       return 0;
-}
-
-/* Kernel needs to suspend all functions separately. Therefore all
- * registered functions must have drivers with suspend and resume
- * methods. Failing that the kernel simply removes the whole card.
- *
- * If already not resumed, this function turns on the traffic and
- * sends a 'host sleep cancel' request to the firmware.
- */
-static int mwifiex_usb_resume(struct usb_interface *intf)
-{
-       struct usb_card_rec *card = usb_get_intfdata(intf);
-       struct mwifiex_adapter *adapter;
-       int i;
-
-       if (!card || !card->adapter) {
-               pr_err("%s: card or card->adapter is NULL\n", __func__);
-               return 0;
-       }
-       adapter = card->adapter;
-
-       if (unlikely(!adapter->is_suspended)) {
-               mwifiex_dbg(adapter, WARN,
-                           "Device already resumed\n");
-               return 0;
-       }
-
-       /* Indicate device resumed. The netdev queue will be resumed only
-        * after the urbs have been re-submitted
-        */
-       adapter->is_suspended = false;
-
-       if (!atomic_read(&card->rx_data_urb_pending))
-               for (i = 0; i < MWIFIEX_RX_DATA_URB; i++)
-                       mwifiex_usb_submit_rx_urb(&card->rx_data_list[i],
-                                                 MWIFIEX_RX_DATA_BUF_SIZE);
-
-       if (!atomic_read(&card->rx_cmd_urb_pending)) {
-               card->rx_cmd.skb = dev_alloc_skb(MWIFIEX_RX_CMD_BUF_SIZE);
-               if (card->rx_cmd.skb)
-                       mwifiex_usb_submit_rx_urb(&card->rx_cmd,
-                                                 MWIFIEX_RX_CMD_BUF_SIZE);
-       }
-
-       /* Disable Host Sleep */
-       if (adapter->hs_activated)
-               mwifiex_cancel_hs(mwifiex_get_priv(adapter,
-                                                  MWIFIEX_BSS_ROLE_ANY),
-                                 MWIFIEX_ASYNC_CMD);
-
-       return 0;
-}
-
-static void mwifiex_usb_disconnect(struct usb_interface *intf)
-{
-       struct usb_card_rec *card = usb_get_intfdata(intf);
-       struct mwifiex_adapter *adapter;
-
-       if (!card || !card->adapter) {
-               pr_err("%s: card or card->adapter is NULL\n", __func__);
-               return;
-       }
-
-       adapter = card->adapter;
-       if (!adapter->priv_num)
-               return;
-
-       if (user_rmmod) {
-#ifdef CONFIG_PM
-               if (adapter->is_suspended)
-                       mwifiex_usb_resume(intf);
-#endif
-
-               mwifiex_deauthenticate_all(adapter);
-
-               mwifiex_init_shutdown_fw(mwifiex_get_priv(adapter,
-                                                         MWIFIEX_BSS_ROLE_ANY),
-                                        MWIFIEX_FUNC_SHUTDOWN);
-       }
-
-       mwifiex_usb_free(card);
-
-       mwifiex_dbg(adapter, FATAL,
-                   "%s: removing card\n", __func__);
-       mwifiex_remove_card(adapter, &add_remove_card_sem);
-
-       usb_set_intfdata(intf, NULL);
-       usb_put_dev(interface_to_usbdev(intf));
-       kfree(card);
-
-       return;
-}
-
-static struct usb_driver mwifiex_usb_driver = {
-       .name = "mwifiex_usb",
-       .probe = mwifiex_usb_probe,
-       .disconnect = mwifiex_usb_disconnect,
-       .id_table = mwifiex_usb_table,
-       .suspend = mwifiex_usb_suspend,
-       .resume = mwifiex_usb_resume,
-       .soft_unbind = 1,
-};
-
-static int mwifiex_usb_tx_init(struct mwifiex_adapter *adapter)
-{
-       struct usb_card_rec *card = (struct usb_card_rec *)adapter->card;
-       struct usb_tx_data_port *port;
-       int i, j;
-
-       card->tx_cmd.adapter = adapter;
-       card->tx_cmd.ep = card->tx_cmd_ep;
-
-       card->tx_cmd.urb = usb_alloc_urb(0, GFP_KERNEL);
-       if (!card->tx_cmd.urb) {
-               mwifiex_dbg(adapter, ERROR,
-                           "tx_cmd.urb allocation failed\n");
-               return -ENOMEM;
-       }
-
-       for (i = 0; i < MWIFIEX_TX_DATA_PORT; i++) {
-               port = &card->port[i];
-               if (!port->tx_data_ep)
-                       continue;
-               port->tx_data_ix = 0;
-               if (port->tx_data_ep == MWIFIEX_USB_EP_DATA)
-                       port->block_status = false;
-               else
-                       port->block_status = true;
-               for (j = 0; j < MWIFIEX_TX_DATA_URB; j++) {
-                       port->tx_data_list[j].adapter = adapter;
-                       port->tx_data_list[j].ep = port->tx_data_ep;
-                       port->tx_data_list[j].urb =
-                                       usb_alloc_urb(0, GFP_KERNEL);
-                       if (!port->tx_data_list[j].urb) {
-                               mwifiex_dbg(adapter, ERROR,
-                                           "urb allocation failed\n");
-                               return -ENOMEM;
-                       }
-               }
-       }
-
-       return 0;
-}
-
-static int mwifiex_usb_rx_init(struct mwifiex_adapter *adapter)
-{
-       struct usb_card_rec *card = (struct usb_card_rec *)adapter->card;
-       int i;
-
-       card->rx_cmd.adapter = adapter;
-       card->rx_cmd.ep = card->rx_cmd_ep;
-
-       card->rx_cmd.urb = usb_alloc_urb(0, GFP_KERNEL);
-       if (!card->rx_cmd.urb) {
-               mwifiex_dbg(adapter, ERROR, "rx_cmd.urb allocation failed\n");
-               return -ENOMEM;
-       }
-
-       card->rx_cmd.skb = dev_alloc_skb(MWIFIEX_RX_CMD_BUF_SIZE);
-       if (!card->rx_cmd.skb)
-               return -ENOMEM;
-
-       if (mwifiex_usb_submit_rx_urb(&card->rx_cmd, MWIFIEX_RX_CMD_BUF_SIZE))
-               return -1;
-
-       for (i = 0; i < MWIFIEX_RX_DATA_URB; i++) {
-               card->rx_data_list[i].adapter = adapter;
-               card->rx_data_list[i].ep = card->rx_data_ep;
-
-               card->rx_data_list[i].urb = usb_alloc_urb(0, GFP_KERNEL);
-               if (!card->rx_data_list[i].urb) {
-                       mwifiex_dbg(adapter, ERROR,
-                                   "rx_data_list[] urb allocation failed\n");
-                       return -1;
-               }
-               if (mwifiex_usb_submit_rx_urb(&card->rx_data_list[i],
-                                             MWIFIEX_RX_DATA_BUF_SIZE))
-                       return -1;
-       }
-
-       return 0;
-}
-
-static int mwifiex_write_data_sync(struct mwifiex_adapter *adapter, u8 *pbuf,
-                                  u32 *len, u8 ep, u32 timeout)
-{
-       struct usb_card_rec *card = adapter->card;
-       int actual_length, ret;
-
-       if (!(*len % card->bulk_out_maxpktsize))
-               (*len)++;
-
-       /* Send the data block */
-       ret = usb_bulk_msg(card->udev, usb_sndbulkpipe(card->udev, ep), pbuf,
-                          *len, &actual_length, timeout);
-       if (ret) {
-               mwifiex_dbg(adapter, ERROR,
-                           "usb_bulk_msg for tx failed: %d\n", ret);
-               return ret;
-       }
-
-       *len = actual_length;
-
-       return ret;
-}
-
-static int mwifiex_read_data_sync(struct mwifiex_adapter *adapter, u8 *pbuf,
-                                 u32 *len, u8 ep, u32 timeout)
-{
-       struct usb_card_rec *card = adapter->card;
-       int actual_length, ret;
-
-       /* Receive the data response */
-       ret = usb_bulk_msg(card->udev, usb_rcvbulkpipe(card->udev, ep), pbuf,
-                          *len, &actual_length, timeout);
-       if (ret) {
-               mwifiex_dbg(adapter, ERROR,
-                           "usb_bulk_msg for rx failed: %d\n", ret);
-               return ret;
-       }
-
-       *len = actual_length;
-
-       return ret;
-}
-
-static void mwifiex_usb_port_resync(struct mwifiex_adapter *adapter)
-{
-       struct usb_card_rec *card = adapter->card;
-       u8 active_port = MWIFIEX_USB_EP_DATA;
-       struct mwifiex_private *priv = NULL;
-       int i;
-
-       if (adapter->usb_mc_status) {
-               for (i = 0; i < adapter->priv_num; i++) {
-                       priv = adapter->priv[i];
-                       if (!priv)
-                               continue;
-                       if ((priv->bss_role == MWIFIEX_BSS_ROLE_UAP &&
-                            !priv->bss_started) ||
-                           (priv->bss_role == MWIFIEX_BSS_ROLE_STA &&
-                            !priv->media_connected))
-                               priv->usb_port = MWIFIEX_USB_EP_DATA;
-               }
-               for (i = 0; i < MWIFIEX_TX_DATA_PORT; i++)
-                       card->port[i].block_status = false;
-       } else {
-               for (i = 0; i < adapter->priv_num; i++) {
-                       priv = adapter->priv[i];
-                       if (!priv)
-                               continue;
-                       if ((priv->bss_role == MWIFIEX_BSS_ROLE_UAP &&
-                            priv->bss_started) ||
-                           (priv->bss_role == MWIFIEX_BSS_ROLE_STA &&
-                            priv->media_connected)) {
-                               active_port = priv->usb_port;
-                               break;
-                       }
-               }
-               for (i = 0; i < adapter->priv_num; i++) {
-                       priv = adapter->priv[i];
-                       if (priv)
-                               priv->usb_port = active_port;
-               }
-               for (i = 0; i < MWIFIEX_TX_DATA_PORT; i++) {
-                       if (active_port == card->port[i].tx_data_ep)
-                               card->port[i].block_status = false;
-                       else
-                               card->port[i].block_status = true;
-               }
-       }
-}
-
-static bool mwifiex_usb_is_port_ready(struct mwifiex_private *priv)
-{
-       struct usb_card_rec *card = priv->adapter->card;
-       int idx;
-
-       for (idx = 0; idx < MWIFIEX_TX_DATA_PORT; idx++) {
-               if (priv->usb_port == card->port[idx].tx_data_ep)
-                       return !card->port[idx].block_status;
-       }
-
-       return false;
-}
-
-static inline u8 mwifiex_usb_data_sent(struct mwifiex_adapter *adapter)
-{
-       struct usb_card_rec *card = adapter->card;
-       int i;
-
-       for (i = 0; i < MWIFIEX_TX_DATA_PORT; i++)
-               if (!card->port[i].block_status)
-                       return false;
-
-       return true;
-}
-
-/* This function write a command/data packet to card. */
-static int mwifiex_usb_host_to_card(struct mwifiex_adapter *adapter, u8 ep,
-                                   struct sk_buff *skb,
-                                   struct mwifiex_tx_param *tx_param)
-{
-       struct usb_card_rec *card = adapter->card;
-       struct urb_context *context = NULL;
-       struct usb_tx_data_port *port = NULL;
-       u8 *data = (u8 *)skb->data;
-       struct urb *tx_urb;
-       int idx, ret;
-
-       if (adapter->is_suspended) {
-               mwifiex_dbg(adapter, ERROR,
-                           "%s: not allowed while suspended\n", __func__);
-               return -1;
-       }
-
-       if (adapter->surprise_removed) {
-               mwifiex_dbg(adapter, ERROR, "%s: device removed\n", __func__);
-               return -1;
-       }
-
-       mwifiex_dbg(adapter, INFO, "%s: ep=%d\n", __func__, ep);
-
-       if (ep == card->tx_cmd_ep) {
-               context = &card->tx_cmd;
-       } else {
-               for (idx = 0; idx < MWIFIEX_TX_DATA_PORT; idx++) {
-                       if (ep == card->port[idx].tx_data_ep) {
-                               port = &card->port[idx];
-                               if (atomic_read(&port->tx_data_urb_pending)
-                                   >= MWIFIEX_TX_DATA_URB) {
-                                       port->block_status = true;
-                                       ret = -EBUSY;
-                                       goto done;
-                               }
-                               if (port->tx_data_ix >= MWIFIEX_TX_DATA_URB)
-                                       port->tx_data_ix = 0;
-                               context =
-                                       &port->tx_data_list[port->tx_data_ix++];
-                               break;
-                       }
-               }
-               if (!port) {
-                       mwifiex_dbg(adapter, ERROR, "Wrong usb tx data port\n");
-                       return -1;
-               }
-       }
-
-       context->adapter = adapter;
-       context->ep = ep;
-       context->skb = skb;
-       tx_urb = context->urb;
-
-       usb_fill_bulk_urb(tx_urb, card->udev, usb_sndbulkpipe(card->udev, ep),
-                         data, skb->len, mwifiex_usb_tx_complete,
-                         (void *)context);
-
-       tx_urb->transfer_flags |= URB_ZERO_PACKET;
-
-       if (ep == card->tx_cmd_ep)
-               atomic_inc(&card->tx_cmd_urb_pending);
-       else
-               atomic_inc(&port->tx_data_urb_pending);
-
-       if (usb_submit_urb(tx_urb, GFP_ATOMIC)) {
-               mwifiex_dbg(adapter, ERROR,
-                           "%s: usb_submit_urb failed\n", __func__);
-               if (ep == card->tx_cmd_ep) {
-                       atomic_dec(&card->tx_cmd_urb_pending);
-               } else {
-                       atomic_dec(&port->tx_data_urb_pending);
-                       port->block_status = false;
-                       if (port->tx_data_ix)
-                               port->tx_data_ix--;
-                       else
-                               port->tx_data_ix = MWIFIEX_TX_DATA_URB;
-               }
-
-               return -1;
-       } else {
-               if (ep != card->tx_cmd_ep &&
-                   atomic_read(&port->tx_data_urb_pending) ==
-                                                       MWIFIEX_TX_DATA_URB) {
-                       port->block_status = true;
-                       ret = -ENOSR;
-                       goto done;
-               }
-       }
-
-       return -EINPROGRESS;
-
-done:
-       if (ep != card->tx_cmd_ep)
-               adapter->data_sent = mwifiex_usb_data_sent(adapter);
-
-       return ret;
-}
-
-/* This function register usb device and initialize parameter. */
-static int mwifiex_register_dev(struct mwifiex_adapter *adapter)
-{
-       struct usb_card_rec *card = (struct usb_card_rec *)adapter->card;
-
-       card->adapter = adapter;
-       adapter->dev = &card->udev->dev;
-
-       switch (le16_to_cpu(card->udev->descriptor.idProduct)) {
-       case USB8997_PID_1:
-       case USB8997_PID_2:
-               adapter->tx_buf_size = MWIFIEX_TX_DATA_BUF_SIZE_4K;
-               strcpy(adapter->fw_name, USB8997_DEFAULT_FW_NAME);
-               adapter->ext_scan = true;
-               break;
-       case USB8766_PID_1:
-       case USB8766_PID_2:
-               adapter->tx_buf_size = MWIFIEX_TX_DATA_BUF_SIZE_2K;
-               strcpy(adapter->fw_name, USB8766_DEFAULT_FW_NAME);
-               adapter->ext_scan = true;
-               break;
-       case USB8801_PID_1:
-       case USB8801_PID_2:
-               adapter->tx_buf_size = MWIFIEX_TX_DATA_BUF_SIZE_2K;
-               strcpy(adapter->fw_name, USB8801_DEFAULT_FW_NAME);
-               adapter->ext_scan = false;
-               break;
-       case USB8797_PID_1:
-       case USB8797_PID_2:
-       default:
-               adapter->tx_buf_size = MWIFIEX_TX_DATA_BUF_SIZE_2K;
-               strcpy(adapter->fw_name, USB8797_DEFAULT_FW_NAME);
-               break;
-       }
-
-       adapter->usb_mc_status = false;
-       adapter->usb_mc_setup = false;
-
-       return 0;
-}
-
-static void mwifiex_unregister_dev(struct mwifiex_adapter *adapter)
-{
-       struct usb_card_rec *card = (struct usb_card_rec *)adapter->card;
-
-       card->adapter = NULL;
-}
-
-static int mwifiex_prog_fw_w_helper(struct mwifiex_adapter *adapter,
-                                   struct mwifiex_fw_image *fw)
-{
-       int ret = 0;
-       u8 *firmware = fw->fw_buf, *recv_buff;
-       u32 retries = USB8XXX_FW_MAX_RETRY, dlen;
-       u32 fw_seqnum = 0, tlen = 0, dnld_cmd = 0;
-       struct fw_data *fwdata;
-       struct fw_sync_header sync_fw;
-       u8 check_winner = 1;
-
-       if (!firmware) {
-               mwifiex_dbg(adapter, ERROR,
-                           "No firmware image found! Terminating download\n");
-               ret = -1;
-               goto fw_exit;
-       }
-
-       /* Allocate memory for transmit */
-       fwdata = kzalloc(FW_DNLD_TX_BUF_SIZE, GFP_KERNEL);
-       if (!fwdata) {
-               ret = -ENOMEM;
-               goto fw_exit;
-       }
-
-       /* Allocate memory for receive */
-       recv_buff = kzalloc(FW_DNLD_RX_BUF_SIZE, GFP_KERNEL);
-       if (!recv_buff)
-               goto cleanup;
-
-       do {
-               /* Send pseudo data to check winner status first */
-               if (check_winner) {
-                       memset(&fwdata->fw_hdr, 0, sizeof(struct fw_header));
-                       dlen = 0;
-               } else {
-                       /* copy the header of the fw_data to get the length */
-                       memcpy(&fwdata->fw_hdr, &firmware[tlen],
-                              sizeof(struct fw_header));
-
-                       dlen = le32_to_cpu(fwdata->fw_hdr.data_len);
-                       dnld_cmd = le32_to_cpu(fwdata->fw_hdr.dnld_cmd);
-                       tlen += sizeof(struct fw_header);
-
-                       memcpy(fwdata->data, &firmware[tlen], dlen);
-
-                       fwdata->seq_num = cpu_to_le32(fw_seqnum);
-                       tlen += dlen;
-               }
-
-               /* If the send/receive fails or CRC occurs then retry */
-               while (retries--) {
-                       u8 *buf = (u8 *)fwdata;
-                       u32 len = FW_DATA_XMIT_SIZE;
-
-                       /* send the firmware block */
-                       ret = mwifiex_write_data_sync(adapter, buf, &len,
-                                               MWIFIEX_USB_EP_CMD_EVENT,
-                                               MWIFIEX_USB_TIMEOUT);
-                       if (ret) {
-                               mwifiex_dbg(adapter, ERROR,
-                                           "write_data_sync: failed: %d\n",
-                                           ret);
-                               continue;
-                       }
-
-                       buf = recv_buff;
-                       len = FW_DNLD_RX_BUF_SIZE;
-
-                       /* Receive the firmware block response */
-                       ret = mwifiex_read_data_sync(adapter, buf, &len,
-                                               MWIFIEX_USB_EP_CMD_EVENT,
-                                               MWIFIEX_USB_TIMEOUT);
-                       if (ret) {
-                               mwifiex_dbg(adapter, ERROR,
-                                           "read_data_sync: failed: %d\n",
-                                           ret);
-                               continue;
-                       }
-
-                       memcpy(&sync_fw, recv_buff,
-                              sizeof(struct fw_sync_header));
-
-                       /* check 1st firmware block resp for highest bit set */
-                       if (check_winner) {
-                               if (le32_to_cpu(sync_fw.cmd) & 0x80000000) {
-                                       mwifiex_dbg(adapter, WARN,
-                                                   "USB is not the winner %#x\n",
-                                                   sync_fw.cmd);
-
-                                       /* returning success */
-                                       ret = 0;
-                                       goto cleanup;
-                               }
-
-                               mwifiex_dbg(adapter, MSG,
-                                           "start to download FW...\n");
-
-                               check_winner = 0;
-                               break;
-                       }
-
-                       /* check the firmware block response for CRC errors */
-                       if (sync_fw.cmd) {
-                               mwifiex_dbg(adapter, ERROR,
-                                           "FW received block with CRC %#x\n",
-                                           sync_fw.cmd);
-                               ret = -1;
-                               continue;
-                       }
-
-                       retries = USB8XXX_FW_MAX_RETRY;
-                       break;
-               }
-               fw_seqnum++;
-       } while ((dnld_cmd != FW_HAS_LAST_BLOCK) && retries);
-
-cleanup:
-       mwifiex_dbg(adapter, MSG,
-                   "info: FW download over, size %d bytes\n", tlen);
-
-       kfree(recv_buff);
-       kfree(fwdata);
-
-       if (retries)
-               ret = 0;
-fw_exit:
-       return ret;
-}
-
-static int mwifiex_usb_dnld_fw(struct mwifiex_adapter *adapter,
-                       struct mwifiex_fw_image *fw)
-{
-       int ret;
-       struct usb_card_rec *card = (struct usb_card_rec *)adapter->card;
-
-       if (card->usb_boot_state == USB8XXX_FW_DNLD) {
-               ret = mwifiex_prog_fw_w_helper(adapter, fw);
-               if (ret)
-                       return -1;
-
-               /* Boot state changes after successful firmware download */
-               if (card->usb_boot_state == USB8XXX_FW_DNLD)
-                       return -1;
-       }
-
-       ret = mwifiex_usb_rx_init(adapter);
-       if (!ret)
-               ret = mwifiex_usb_tx_init(adapter);
-
-       return ret;
-}
-
-static void mwifiex_submit_rx_urb(struct mwifiex_adapter *adapter, u8 ep)
-{
-       struct usb_card_rec *card = (struct usb_card_rec *)adapter->card;
-
-       skb_push(card->rx_cmd.skb, INTF_HEADER_LEN);
-       if ((ep == card->rx_cmd_ep) &&
-           (!atomic_read(&card->rx_cmd_urb_pending)))
-               mwifiex_usb_submit_rx_urb(&card->rx_cmd,
-                                         MWIFIEX_RX_CMD_BUF_SIZE);
-
-       return;
-}
-
-static int mwifiex_usb_cmd_event_complete(struct mwifiex_adapter *adapter,
-                                      struct sk_buff *skb)
-{
-       mwifiex_submit_rx_urb(adapter, MWIFIEX_USB_EP_CMD_EVENT);
-
-       return 0;
-}
-
-/* This function wakes up the card. */
-static int mwifiex_pm_wakeup_card(struct mwifiex_adapter *adapter)
-{
-       /* Simulation of HS_AWAKE event */
-       adapter->pm_wakeup_fw_try = false;
-       del_timer(&adapter->wakeup_timer);
-       adapter->pm_wakeup_card_req = false;
-       adapter->ps_state = PS_STATE_AWAKE;
-
-       return 0;
-}
-
-static void mwifiex_usb_submit_rem_rx_urbs(struct mwifiex_adapter *adapter)
-{
-       struct usb_card_rec *card = (struct usb_card_rec *)adapter->card;
-       int i;
-       struct urb_context *ctx;
-
-       for (i = 0; i < MWIFIEX_RX_DATA_URB; i++) {
-               if (card->rx_data_list[i].skb)
-                       continue;
-               ctx = &card->rx_data_list[i];
-               mwifiex_usb_submit_rx_urb(ctx, MWIFIEX_RX_DATA_BUF_SIZE);
-       }
-}
-
-/* This function is called after the card has woken up. */
-static inline int
-mwifiex_pm_wakeup_card_complete(struct mwifiex_adapter *adapter)
-{
-       return 0;
-}
-
-static struct mwifiex_if_ops usb_ops = {
-       .register_dev =         mwifiex_register_dev,
-       .unregister_dev =       mwifiex_unregister_dev,
-       .wakeup =               mwifiex_pm_wakeup_card,
-       .wakeup_complete =      mwifiex_pm_wakeup_card_complete,
-
-       /* USB specific */
-       .dnld_fw =              mwifiex_usb_dnld_fw,
-       .cmdrsp_complete =      mwifiex_usb_cmd_event_complete,
-       .event_complete =       mwifiex_usb_cmd_event_complete,
-       .host_to_card =         mwifiex_usb_host_to_card,
-       .submit_rem_rx_urbs =   mwifiex_usb_submit_rem_rx_urbs,
-       .multi_port_resync =    mwifiex_usb_port_resync,
-       .is_port_ready =        mwifiex_usb_is_port_ready,
-};
-
-/* This function initializes the USB driver module.
- *
- * This initiates the semaphore and registers the device with
- * USB bus.
- */
-static int mwifiex_usb_init_module(void)
-{
-       int ret;
-
-       pr_debug("Marvell USB8797 Driver\n");
-
-       sema_init(&add_remove_card_sem, 1);
-
-       ret = usb_register(&mwifiex_usb_driver);
-       if (ret)
-               pr_err("Driver register failed!\n");
-       else
-               pr_debug("info: Driver registered successfully!\n");
-
-       return ret;
-}
-
-/* This function cleans up the USB driver.
- *
- * The following major steps are followed in .disconnect for cleanup:
- *      - Resume the device if its suspended
- *      - Disconnect the device if connected
- *      - Shutdown the firmware
- *      - Unregister the device from USB bus.
- */
-static void mwifiex_usb_cleanup_module(void)
-{
-       if (!down_interruptible(&add_remove_card_sem))
-               up(&add_remove_card_sem);
-
-       /* set the flag as user is removing this module */
-       user_rmmod = 1;
-
-       usb_deregister(&mwifiex_usb_driver);
-}
-
-module_init(mwifiex_usb_init_module);
-module_exit(mwifiex_usb_cleanup_module);
-
-MODULE_AUTHOR("Marvell International Ltd.");
-MODULE_DESCRIPTION("Marvell WiFi-Ex USB Driver version" USB_VERSION);
-MODULE_VERSION(USB_VERSION);
-MODULE_LICENSE("GPL v2");
-MODULE_FIRMWARE(USB8766_DEFAULT_FW_NAME);
-MODULE_FIRMWARE(USB8797_DEFAULT_FW_NAME);
-MODULE_FIRMWARE(USB8801_DEFAULT_FW_NAME);
-MODULE_FIRMWARE(USB8997_DEFAULT_FW_NAME);
diff --git a/drivers/net/wireless/mwifiex/usb.h b/drivers/net/wireless/mwifiex/usb.h
deleted file mode 100644 (file)
index b4e9246..0000000
+++ /dev/null
@@ -1,110 +0,0 @@
-/*
- * This file contains definitions for mwifiex USB interface driver.
- *
- * Copyright (C) 2012-2014, Marvell International Ltd.
- *
- * This software file (the "File") is distributed by Marvell International
- * Ltd. under the terms of the GNU General Public License Version 2, June 1991
- * (the "License").  You may use, redistribute and/or modify this File in
- * accordance with the terms and conditions of the License, a copy of which
- * is available by writing to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the
- * worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
- *
- * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
- * ARE EXPRESSLY DISCLAIMED.  The License provides additional details about
- * this warranty disclaimer.
- */
-
-#ifndef _MWIFIEX_USB_H
-#define _MWIFIEX_USB_H
-
-#include <linux/usb.h>
-
-#define USB8XXX_VID            0x1286
-
-#define USB8766_PID_1          0x2041
-#define USB8766_PID_2          0x2042
-#define USB8797_PID_1          0x2043
-#define USB8797_PID_2          0x2044
-#define USB8801_PID_1          0x2049
-#define USB8801_PID_2          0x204a
-#define USB8997_PID_1          0x2052
-#define USB8997_PID_2          0x204e
-
-
-#define USB8XXX_FW_DNLD                1
-#define USB8XXX_FW_READY       2
-#define USB8XXX_FW_MAX_RETRY   3
-
-#define MWIFIEX_TX_DATA_PORT   2
-#define MWIFIEX_TX_DATA_URB    6
-#define MWIFIEX_RX_DATA_URB    6
-#define MWIFIEX_USB_TIMEOUT    100
-
-#define USB8766_DEFAULT_FW_NAME        "mrvl/usb8766_uapsta.bin"
-#define USB8797_DEFAULT_FW_NAME        "mrvl/usb8797_uapsta.bin"
-#define USB8801_DEFAULT_FW_NAME        "mrvl/usb8801_uapsta.bin"
-#define USB8997_DEFAULT_FW_NAME        "mrvl/usb8997_uapsta.bin"
-
-#define FW_DNLD_TX_BUF_SIZE    620
-#define FW_DNLD_RX_BUF_SIZE    2048
-#define FW_HAS_LAST_BLOCK      0x00000004
-
-#define FW_DATA_XMIT_SIZE \
-       (sizeof(struct fw_header) + dlen + sizeof(u32))
-
-struct urb_context {
-       struct mwifiex_adapter *adapter;
-       struct sk_buff *skb;
-       struct urb *urb;
-       u8 ep;
-};
-
-struct usb_tx_data_port {
-       u8 tx_data_ep;
-       u8 block_status;
-       atomic_t tx_data_urb_pending;
-       int tx_data_ix;
-       struct urb_context tx_data_list[MWIFIEX_TX_DATA_URB];
-};
-
-struct usb_card_rec {
-       struct mwifiex_adapter *adapter;
-       struct usb_device *udev;
-       struct usb_interface *intf;
-       u8 rx_cmd_ep;
-       struct urb_context rx_cmd;
-       atomic_t rx_cmd_urb_pending;
-       struct urb_context rx_data_list[MWIFIEX_RX_DATA_URB];
-       u8 usb_boot_state;
-       u8 rx_data_ep;
-       atomic_t rx_data_urb_pending;
-       u8 tx_cmd_ep;
-       atomic_t tx_cmd_urb_pending;
-       int bulk_out_maxpktsize;
-       struct urb_context tx_cmd;
-       u8 mc_resync_flag;
-       struct usb_tx_data_port port[MWIFIEX_TX_DATA_PORT];
-};
-
-struct fw_header {
-       __le32 dnld_cmd;
-       __le32 base_addr;
-       __le32 data_len;
-       __le32 crc;
-};
-
-struct fw_sync_header {
-       __le32 cmd;
-       __le32 seq_num;
-};
-
-struct fw_data {
-       struct fw_header fw_hdr;
-       __le32 seq_num;
-       u8 data[1];
-};
-
-#endif /*_MWIFIEX_USB_H */
diff --git a/drivers/net/wireless/mwifiex/util.c b/drivers/net/wireless/mwifiex/util.c
deleted file mode 100644 (file)
index 0cec8a6..0000000
+++ /dev/null
@@ -1,751 +0,0 @@
-/*
- * Marvell Wireless LAN device driver: utility functions
- *
- * Copyright (C) 2011-2014, Marvell International Ltd.
- *
- * This software file (the "File") is distributed by Marvell International
- * Ltd. under the terms of the GNU General Public License Version 2, June 1991
- * (the "License").  You may use, redistribute and/or modify this File in
- * accordance with the terms and conditions of the License, a copy of which
- * is available by writing to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the
- * worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
- *
- * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
- * ARE EXPRESSLY DISCLAIMED.  The License provides additional details about
- * this warranty disclaimer.
- */
-
-#include "decl.h"
-#include "ioctl.h"
-#include "util.h"
-#include "fw.h"
-#include "main.h"
-#include "wmm.h"
-#include "11n.h"
-
-static struct mwifiex_debug_data items[] = {
-       {"debug_mask", item_size(debug_mask),
-        item_addr(debug_mask), 1},
-       {"int_counter", item_size(int_counter),
-        item_addr(int_counter), 1},
-       {"wmm_ac_vo", item_size(packets_out[WMM_AC_VO]),
-        item_addr(packets_out[WMM_AC_VO]), 1},
-       {"wmm_ac_vi", item_size(packets_out[WMM_AC_VI]),
-        item_addr(packets_out[WMM_AC_VI]), 1},
-       {"wmm_ac_be", item_size(packets_out[WMM_AC_BE]),
-        item_addr(packets_out[WMM_AC_BE]), 1},
-       {"wmm_ac_bk", item_size(packets_out[WMM_AC_BK]),
-        item_addr(packets_out[WMM_AC_BK]), 1},
-       {"tx_buf_size", item_size(tx_buf_size),
-        item_addr(tx_buf_size), 1},
-       {"curr_tx_buf_size", item_size(curr_tx_buf_size),
-        item_addr(curr_tx_buf_size), 1},
-       {"ps_mode", item_size(ps_mode),
-        item_addr(ps_mode), 1},
-       {"ps_state", item_size(ps_state),
-        item_addr(ps_state), 1},
-       {"is_deep_sleep", item_size(is_deep_sleep),
-        item_addr(is_deep_sleep), 1},
-       {"wakeup_dev_req", item_size(pm_wakeup_card_req),
-        item_addr(pm_wakeup_card_req), 1},
-       {"wakeup_tries", item_size(pm_wakeup_fw_try),
-        item_addr(pm_wakeup_fw_try), 1},
-       {"hs_configured", item_size(is_hs_configured),
-        item_addr(is_hs_configured), 1},
-       {"hs_activated", item_size(hs_activated),
-        item_addr(hs_activated), 1},
-       {"num_tx_timeout", item_size(num_tx_timeout),
-        item_addr(num_tx_timeout), 1},
-       {"is_cmd_timedout", item_size(is_cmd_timedout),
-        item_addr(is_cmd_timedout), 1},
-       {"timeout_cmd_id", item_size(timeout_cmd_id),
-        item_addr(timeout_cmd_id), 1},
-       {"timeout_cmd_act", item_size(timeout_cmd_act),
-        item_addr(timeout_cmd_act), 1},
-       {"last_cmd_id", item_size(last_cmd_id),
-        item_addr(last_cmd_id), DBG_CMD_NUM},
-       {"last_cmd_act", item_size(last_cmd_act),
-        item_addr(last_cmd_act), DBG_CMD_NUM},
-       {"last_cmd_index", item_size(last_cmd_index),
-        item_addr(last_cmd_index), 1},
-       {"last_cmd_resp_id", item_size(last_cmd_resp_id),
-        item_addr(last_cmd_resp_id), DBG_CMD_NUM},
-       {"last_cmd_resp_index", item_size(last_cmd_resp_index),
-        item_addr(last_cmd_resp_index), 1},
-       {"last_event", item_size(last_event),
-        item_addr(last_event), DBG_CMD_NUM},
-       {"last_event_index", item_size(last_event_index),
-        item_addr(last_event_index), 1},
-       {"num_cmd_h2c_fail", item_size(num_cmd_host_to_card_failure),
-        item_addr(num_cmd_host_to_card_failure), 1},
-       {"num_cmd_sleep_cfm_fail",
-        item_size(num_cmd_sleep_cfm_host_to_card_failure),
-        item_addr(num_cmd_sleep_cfm_host_to_card_failure), 1},
-       {"num_tx_h2c_fail", item_size(num_tx_host_to_card_failure),
-        item_addr(num_tx_host_to_card_failure), 1},
-       {"num_evt_deauth", item_size(num_event_deauth),
-        item_addr(num_event_deauth), 1},
-       {"num_evt_disassoc", item_size(num_event_disassoc),
-        item_addr(num_event_disassoc), 1},
-       {"num_evt_link_lost", item_size(num_event_link_lost),
-        item_addr(num_event_link_lost), 1},
-       {"num_cmd_deauth", item_size(num_cmd_deauth),
-        item_addr(num_cmd_deauth), 1},
-       {"num_cmd_assoc_ok", item_size(num_cmd_assoc_success),
-        item_addr(num_cmd_assoc_success), 1},
-       {"num_cmd_assoc_fail", item_size(num_cmd_assoc_failure),
-        item_addr(num_cmd_assoc_failure), 1},
-       {"cmd_sent", item_size(cmd_sent),
-        item_addr(cmd_sent), 1},
-       {"data_sent", item_size(data_sent),
-        item_addr(data_sent), 1},
-       {"cmd_resp_received", item_size(cmd_resp_received),
-        item_addr(cmd_resp_received), 1},
-       {"event_received", item_size(event_received),
-        item_addr(event_received), 1},
-
-       /* variables defined in struct mwifiex_adapter */
-       {"cmd_pending", adapter_item_size(cmd_pending),
-        adapter_item_addr(cmd_pending), 1},
-       {"tx_pending", adapter_item_size(tx_pending),
-        adapter_item_addr(tx_pending), 1},
-       {"rx_pending", adapter_item_size(rx_pending),
-        adapter_item_addr(rx_pending), 1},
-};
-
-static int num_of_items = ARRAY_SIZE(items);
-
-/*
- * Firmware initialization complete callback handler.
- *
- * This function wakes up the function waiting on the init
- * wait queue for the firmware initialization to complete.
- */
-int mwifiex_init_fw_complete(struct mwifiex_adapter *adapter)
-{
-
-       if (adapter->hw_status == MWIFIEX_HW_STATUS_READY)
-               if (adapter->if_ops.init_fw_port)
-                       adapter->if_ops.init_fw_port(adapter);
-
-       adapter->init_wait_q_woken = true;
-       wake_up_interruptible(&adapter->init_wait_q);
-       return 0;
-}
-
-/*
- * Firmware shutdown complete callback handler.
- *
- * This function sets the hardware status to not ready and wakes up
- * the function waiting on the init wait queue for the firmware
- * shutdown to complete.
- */
-int mwifiex_shutdown_fw_complete(struct mwifiex_adapter *adapter)
-{
-       adapter->hw_status = MWIFIEX_HW_STATUS_NOT_READY;
-       adapter->init_wait_q_woken = true;
-       wake_up_interruptible(&adapter->init_wait_q);
-       return 0;
-}
-
-/*
- * This function sends init/shutdown command
- * to firmware.
- */
-int mwifiex_init_shutdown_fw(struct mwifiex_private *priv,
-                            u32 func_init_shutdown)
-{
-       u16 cmd;
-
-       if (func_init_shutdown == MWIFIEX_FUNC_INIT) {
-               cmd = HostCmd_CMD_FUNC_INIT;
-       } else if (func_init_shutdown == MWIFIEX_FUNC_SHUTDOWN) {
-               cmd = HostCmd_CMD_FUNC_SHUTDOWN;
-       } else {
-               mwifiex_dbg(priv->adapter, ERROR,
-                           "unsupported parameter\n");
-               return -1;
-       }
-
-       return mwifiex_send_cmd(priv, cmd, HostCmd_ACT_GEN_SET, 0, NULL, true);
-}
-EXPORT_SYMBOL_GPL(mwifiex_init_shutdown_fw);
-
-/*
- * IOCTL request handler to set/get debug information.
- *
- * This function collates/sets the information from/to different driver
- * structures.
- */
-int mwifiex_get_debug_info(struct mwifiex_private *priv,
-                          struct mwifiex_debug_info *info)
-{
-       struct mwifiex_adapter *adapter = priv->adapter;
-
-       if (info) {
-               info->debug_mask = adapter->debug_mask;
-               memcpy(info->packets_out,
-                      priv->wmm.packets_out,
-                      sizeof(priv->wmm.packets_out));
-               info->curr_tx_buf_size = (u32) adapter->curr_tx_buf_size;
-               info->tx_buf_size = (u32) adapter->tx_buf_size;
-               info->rx_tbl_num = mwifiex_get_rx_reorder_tbl(priv,
-                                                             info->rx_tbl);
-               info->tx_tbl_num = mwifiex_get_tx_ba_stream_tbl(priv,
-                                                               info->tx_tbl);
-               info->tdls_peer_num = mwifiex_get_tdls_list(priv,
-                                                           info->tdls_list);
-               info->ps_mode = adapter->ps_mode;
-               info->ps_state = adapter->ps_state;
-               info->is_deep_sleep = adapter->is_deep_sleep;
-               info->pm_wakeup_card_req = adapter->pm_wakeup_card_req;
-               info->pm_wakeup_fw_try = adapter->pm_wakeup_fw_try;
-               info->is_hs_configured = adapter->is_hs_configured;
-               info->hs_activated = adapter->hs_activated;
-               info->is_cmd_timedout = adapter->is_cmd_timedout;
-               info->num_cmd_host_to_card_failure
-                               = adapter->dbg.num_cmd_host_to_card_failure;
-               info->num_cmd_sleep_cfm_host_to_card_failure
-                       = adapter->dbg.num_cmd_sleep_cfm_host_to_card_failure;
-               info->num_tx_host_to_card_failure
-                               = adapter->dbg.num_tx_host_to_card_failure;
-               info->num_event_deauth = adapter->dbg.num_event_deauth;
-               info->num_event_disassoc = adapter->dbg.num_event_disassoc;
-               info->num_event_link_lost = adapter->dbg.num_event_link_lost;
-               info->num_cmd_deauth = adapter->dbg.num_cmd_deauth;
-               info->num_cmd_assoc_success =
-                                       adapter->dbg.num_cmd_assoc_success;
-               info->num_cmd_assoc_failure =
-                                       adapter->dbg.num_cmd_assoc_failure;
-               info->num_tx_timeout = adapter->dbg.num_tx_timeout;
-               info->timeout_cmd_id = adapter->dbg.timeout_cmd_id;
-               info->timeout_cmd_act = adapter->dbg.timeout_cmd_act;
-               memcpy(info->last_cmd_id, adapter->dbg.last_cmd_id,
-                      sizeof(adapter->dbg.last_cmd_id));
-               memcpy(info->last_cmd_act, adapter->dbg.last_cmd_act,
-                      sizeof(adapter->dbg.last_cmd_act));
-               info->last_cmd_index = adapter->dbg.last_cmd_index;
-               memcpy(info->last_cmd_resp_id, adapter->dbg.last_cmd_resp_id,
-                      sizeof(adapter->dbg.last_cmd_resp_id));
-               info->last_cmd_resp_index = adapter->dbg.last_cmd_resp_index;
-               memcpy(info->last_event, adapter->dbg.last_event,
-                      sizeof(adapter->dbg.last_event));
-               info->last_event_index = adapter->dbg.last_event_index;
-               info->data_sent = adapter->data_sent;
-               info->cmd_sent = adapter->cmd_sent;
-               info->cmd_resp_received = adapter->cmd_resp_received;
-       }
-
-       return 0;
-}
-
-int mwifiex_debug_info_to_buffer(struct mwifiex_private *priv, char *buf,
-                                struct mwifiex_debug_info *info)
-{
-       char *p = buf;
-       struct mwifiex_debug_data *d = &items[0];
-       size_t size, addr;
-       long val;
-       int i, j;
-
-       if (!info)
-               return 0;
-
-       for (i = 0; i < num_of_items; i++) {
-               p += sprintf(p, "%s=", d[i].name);
-
-               size = d[i].size / d[i].num;
-
-               if (i < (num_of_items - 3))
-                       addr = d[i].addr + (size_t)info;
-               else /* The last 3 items are struct mwifiex_adapter variables */
-                       addr = d[i].addr + (size_t)priv->adapter;
-
-               for (j = 0; j < d[i].num; j++) {
-                       switch (size) {
-                       case 1:
-                               val = *((u8 *)addr);
-                               break;
-                       case 2:
-                               val = *((u16 *)addr);
-                               break;
-                       case 4:
-                               val = *((u32 *)addr);
-                               break;
-                       case 8:
-                               val = *((long long *)addr);
-                               break;
-                       default:
-                               val = -1;
-                               break;
-                       }
-
-                       p += sprintf(p, "%#lx ", val);
-                       addr += size;
-               }
-
-               p += sprintf(p, "\n");
-       }
-
-       if (info->tx_tbl_num) {
-               p += sprintf(p, "Tx BA stream table:\n");
-               for (i = 0; i < info->tx_tbl_num; i++)
-                       p += sprintf(p, "tid = %d, ra = %pM\n",
-                                    info->tx_tbl[i].tid, info->tx_tbl[i].ra);
-       }
-
-       if (info->rx_tbl_num) {
-               p += sprintf(p, "Rx reorder table:\n");
-               for (i = 0; i < info->rx_tbl_num; i++) {
-                       p += sprintf(p, "tid = %d, ta = %pM, ",
-                                    info->rx_tbl[i].tid,
-                                    info->rx_tbl[i].ta);
-                       p += sprintf(p, "start_win = %d, ",
-                                    info->rx_tbl[i].start_win);
-                       p += sprintf(p, "win_size = %d, buffer: ",
-                                    info->rx_tbl[i].win_size);
-
-                       for (j = 0; j < info->rx_tbl[i].win_size; j++)
-                               p += sprintf(p, "%c ",
-                                            info->rx_tbl[i].buffer[j] ?
-                                            '1' : '0');
-
-                       p += sprintf(p, "\n");
-               }
-       }
-
-       if (info->tdls_peer_num) {
-               p += sprintf(p, "TDLS peer table:\n");
-               for (i = 0; i < info->tdls_peer_num; i++) {
-                       p += sprintf(p, "peer = %pM",
-                                    info->tdls_list[i].peer_addr);
-                       p += sprintf(p, "\n");
-               }
-       }
-
-       return p - buf;
-}
-
-static int
-mwifiex_parse_mgmt_packet(struct mwifiex_private *priv, u8 *payload, u16 len,
-                         struct rxpd *rx_pd)
-{
-       u16 stype;
-       u8 category, action_code, *addr2;
-       struct ieee80211_hdr *ieee_hdr = (void *)payload;
-
-       stype = (le16_to_cpu(ieee_hdr->frame_control) & IEEE80211_FCTL_STYPE);
-
-       switch (stype) {
-       case IEEE80211_STYPE_ACTION:
-               category = *(payload + sizeof(struct ieee80211_hdr));
-               switch (category) {
-               case WLAN_CATEGORY_PUBLIC:
-                       action_code = *(payload + sizeof(struct ieee80211_hdr)
-                                       + 1);
-                       if (action_code == WLAN_PUB_ACTION_TDLS_DISCOVER_RES) {
-                               addr2 = ieee_hdr->addr2;
-                               mwifiex_dbg(priv->adapter, INFO,
-                                           "TDLS discovery response %pM nf=%d, snr=%d\n",
-                                           addr2, rx_pd->nf, rx_pd->snr);
-                               mwifiex_auto_tdls_update_peer_signal(priv,
-                                                                    addr2,
-                                                                    rx_pd->snr,
-                                                                    rx_pd->nf);
-                       }
-                       break;
-               case WLAN_CATEGORY_BACK:
-                       /*we dont indicate BACK action frames to cfg80211*/
-                       mwifiex_dbg(priv->adapter, INFO,
-                                   "drop BACK action frames");
-                       return -1;
-               default:
-                       mwifiex_dbg(priv->adapter, INFO,
-                                   "unknown public action frame category %d\n",
-                                   category);
-               }
-       default:
-               mwifiex_dbg(priv->adapter, INFO,
-                   "unknown mgmt frame subtype %#x\n", stype);
-               return 0;
-       }
-
-       return 0;
-}
-/*
- * This function processes the received management packet and send it
- * to the kernel.
- */
-int
-mwifiex_process_mgmt_packet(struct mwifiex_private *priv,
-                           struct sk_buff *skb)
-{
-       struct rxpd *rx_pd;
-       u16 pkt_len;
-       struct ieee80211_hdr *ieee_hdr;
-
-       if (!skb)
-               return -1;
-
-       if (!priv->mgmt_frame_mask ||
-           priv->wdev.iftype == NL80211_IFTYPE_UNSPECIFIED) {
-               mwifiex_dbg(priv->adapter, ERROR,
-                           "do not receive mgmt frames on uninitialized intf");
-               return -1;
-       }
-
-       rx_pd = (struct rxpd *)skb->data;
-
-       skb_pull(skb, le16_to_cpu(rx_pd->rx_pkt_offset));
-       skb_pull(skb, sizeof(pkt_len));
-
-       pkt_len = le16_to_cpu(rx_pd->rx_pkt_length);
-
-       ieee_hdr = (void *)skb->data;
-       if (ieee80211_is_mgmt(ieee_hdr->frame_control)) {
-               if (mwifiex_parse_mgmt_packet(priv, (u8 *)ieee_hdr,
-                                             pkt_len, rx_pd))
-                       return -1;
-       }
-       /* Remove address4 */
-       memmove(skb->data + sizeof(struct ieee80211_hdr_3addr),
-               skb->data + sizeof(struct ieee80211_hdr),
-               pkt_len - sizeof(struct ieee80211_hdr));
-
-       pkt_len -= ETH_ALEN + sizeof(pkt_len);
-       rx_pd->rx_pkt_length = cpu_to_le16(pkt_len);
-
-       cfg80211_rx_mgmt(&priv->wdev, priv->roc_cfg.chan.center_freq,
-                        CAL_RSSI(rx_pd->snr, rx_pd->nf), skb->data, pkt_len,
-                        0);
-
-       return 0;
-}
-
-/*
- * This function processes the received packet before sending it to the
- * kernel.
- *
- * It extracts the SKB from the received buffer and sends it to kernel.
- * In case the received buffer does not contain the data in SKB format,
- * the function creates a blank SKB, fills it with the data from the
- * received buffer and then sends this new SKB to the kernel.
- */
-int mwifiex_recv_packet(struct mwifiex_private *priv, struct sk_buff *skb)
-{
-       struct mwifiex_sta_node *src_node;
-       struct ethhdr *p_ethhdr;
-
-       if (!skb)
-               return -1;
-
-       priv->stats.rx_bytes += skb->len;
-       priv->stats.rx_packets++;
-
-       if (GET_BSS_ROLE(priv) == MWIFIEX_BSS_ROLE_UAP) {
-               p_ethhdr = (void *)skb->data;
-               src_node = mwifiex_get_sta_entry(priv, p_ethhdr->h_source);
-               if (src_node) {
-                       src_node->stats.last_rx = jiffies;
-                       src_node->stats.rx_bytes += skb->len;
-                       src_node->stats.rx_packets++;
-               }
-       }
-
-       skb->dev = priv->netdev;
-       skb->protocol = eth_type_trans(skb, priv->netdev);
-       skb->ip_summed = CHECKSUM_NONE;
-
-       /* This is required only in case of 11n and USB/PCIE as we alloc
-        * a buffer of 4K only if its 11N (to be able to receive 4K
-        * AMSDU packets). In case of SD we allocate buffers based
-        * on the size of packet and hence this is not needed.
-        *
-        * Modifying the truesize here as our allocation for each
-        * skb is 4K but we only receive 2K packets and this cause
-        * the kernel to start dropping packets in case where
-        * application has allocated buffer based on 2K size i.e.
-        * if there a 64K packet received (in IP fragments and
-        * application allocates 64K to receive this packet but
-        * this packet would almost double up because we allocate
-        * each 1.5K fragment in 4K and pass it up. As soon as the
-        * 64K limit hits kernel will start to drop rest of the
-        * fragments. Currently we fail the Filesndl-ht.scr script
-        * for UDP, hence this fix
-        */
-       if ((priv->adapter->iface_type == MWIFIEX_USB ||
-            priv->adapter->iface_type == MWIFIEX_PCIE) &&
-           (skb->truesize > MWIFIEX_RX_DATA_BUF_SIZE))
-               skb->truesize += (skb->len - MWIFIEX_RX_DATA_BUF_SIZE);
-
-       if (in_interrupt())
-               netif_rx(skb);
-       else
-               netif_rx_ni(skb);
-
-       return 0;
-}
-
-/*
- * IOCTL completion callback handler.
- *
- * This function is called when a pending IOCTL is completed.
- *
- * If work queue support is enabled, the function wakes up the
- * corresponding waiting function. Otherwise, it processes the
- * IOCTL response and frees the response buffer.
- */
-int mwifiex_complete_cmd(struct mwifiex_adapter *adapter,
-                        struct cmd_ctrl_node *cmd_node)
-{
-       WARN_ON(!cmd_node->wait_q_enabled);
-       mwifiex_dbg(adapter, CMD, "cmd completed: status=%d\n",
-                   adapter->cmd_wait_q.status);
-
-       *cmd_node->condition = true;
-       wake_up_interruptible(&adapter->cmd_wait_q.wait);
-
-       return 0;
-}
-
-/* This function will return the pointer to station entry in station list
- * table which matches specified mac address.
- * This function should be called after acquiring RA list spinlock.
- * NULL is returned if station entry is not found in associated STA list.
- */
-struct mwifiex_sta_node *
-mwifiex_get_sta_entry(struct mwifiex_private *priv, const u8 *mac)
-{
-       struct mwifiex_sta_node *node;
-
-       if (!mac)
-               return NULL;
-
-       list_for_each_entry(node, &priv->sta_list, list) {
-               if (!memcmp(node->mac_addr, mac, ETH_ALEN))
-                       return node;
-       }
-
-       return NULL;
-}
-
-static struct mwifiex_sta_node *
-mwifiex_get_tdls_sta_entry(struct mwifiex_private *priv, u8 status)
-{
-       struct mwifiex_sta_node *node;
-
-       list_for_each_entry(node, &priv->sta_list, list) {
-               if (node->tdls_status == status)
-                       return node;
-       }
-
-       return NULL;
-}
-
-/* If tdls channel switching is on-going, tx data traffic should be
- * blocked until the switching stage completed.
- */
-u8 mwifiex_is_tdls_chan_switching(struct mwifiex_private *priv)
-{
-       struct mwifiex_sta_node *sta_ptr;
-
-       if (!priv || !ISSUPP_TDLS_ENABLED(priv->adapter->fw_cap_info))
-               return false;
-
-       sta_ptr = mwifiex_get_tdls_sta_entry(priv, TDLS_CHAN_SWITCHING);
-       if (sta_ptr)
-               return true;
-
-       return false;
-}
-
-u8 mwifiex_is_tdls_off_chan(struct mwifiex_private *priv)
-{
-       struct mwifiex_sta_node *sta_ptr;
-
-       if (!priv || !ISSUPP_TDLS_ENABLED(priv->adapter->fw_cap_info))
-               return false;
-
-       sta_ptr = mwifiex_get_tdls_sta_entry(priv, TDLS_IN_OFF_CHAN);
-       if (sta_ptr)
-               return true;
-
-       return false;
-}
-
-/* If tdls channel switching is on-going or tdls operate on off-channel,
- * cmd path should be blocked until tdls switched to base-channel.
- */
-u8 mwifiex_is_send_cmd_allowed(struct mwifiex_private *priv)
-{
-       if (!priv || !ISSUPP_TDLS_ENABLED(priv->adapter->fw_cap_info))
-               return true;
-
-       if (mwifiex_is_tdls_chan_switching(priv) ||
-           mwifiex_is_tdls_off_chan(priv))
-               return false;
-
-       return true;
-}
-
-/* This function will add a sta_node entry to associated station list
- * table with the given mac address.
- * If entry exist already, existing entry is returned.
- * If received mac address is NULL, NULL is returned.
- */
-struct mwifiex_sta_node *
-mwifiex_add_sta_entry(struct mwifiex_private *priv, const u8 *mac)
-{
-       struct mwifiex_sta_node *node;
-       unsigned long flags;
-
-       if (!mac)
-               return NULL;
-
-       spin_lock_irqsave(&priv->sta_list_spinlock, flags);
-       node = mwifiex_get_sta_entry(priv, mac);
-       if (node)
-               goto done;
-
-       node = kzalloc(sizeof(*node), GFP_ATOMIC);
-       if (!node)
-               goto done;
-
-       memcpy(node->mac_addr, mac, ETH_ALEN);
-       list_add_tail(&node->list, &priv->sta_list);
-
-done:
-       spin_unlock_irqrestore(&priv->sta_list_spinlock, flags);
-       return node;
-}
-
-/* This function will search for HT IE in association request IEs
- * and set station HT parameters accordingly.
- */
-void
-mwifiex_set_sta_ht_cap(struct mwifiex_private *priv, const u8 *ies,
-                      int ies_len, struct mwifiex_sta_node *node)
-{
-       struct ieee_types_header *ht_cap_ie;
-       const struct ieee80211_ht_cap *ht_cap;
-
-       if (!ies)
-               return;
-
-       ht_cap_ie = (void *)cfg80211_find_ie(WLAN_EID_HT_CAPABILITY, ies,
-                                            ies_len);
-       if (ht_cap_ie) {
-               ht_cap = (void *)(ht_cap_ie + 1);
-               node->is_11n_enabled = 1;
-               node->max_amsdu = le16_to_cpu(ht_cap->cap_info) &
-                                 IEEE80211_HT_CAP_MAX_AMSDU ?
-                                 MWIFIEX_TX_DATA_BUF_SIZE_8K :
-                                 MWIFIEX_TX_DATA_BUF_SIZE_4K;
-       } else {
-               node->is_11n_enabled = 0;
-       }
-
-       return;
-}
-
-/* This function will delete a station entry from station list */
-void mwifiex_del_sta_entry(struct mwifiex_private *priv, const u8 *mac)
-{
-       struct mwifiex_sta_node *node;
-       unsigned long flags;
-
-       spin_lock_irqsave(&priv->sta_list_spinlock, flags);
-
-       node = mwifiex_get_sta_entry(priv, mac);
-       if (node) {
-               list_del(&node->list);
-               kfree(node);
-       }
-
-       spin_unlock_irqrestore(&priv->sta_list_spinlock, flags);
-       return;
-}
-
-/* This function will delete all stations from associated station list. */
-void mwifiex_del_all_sta_list(struct mwifiex_private *priv)
-{
-       struct mwifiex_sta_node *node, *tmp;
-       unsigned long flags;
-
-       spin_lock_irqsave(&priv->sta_list_spinlock, flags);
-
-       list_for_each_entry_safe(node, tmp, &priv->sta_list, list) {
-               list_del(&node->list);
-               kfree(node);
-       }
-
-       INIT_LIST_HEAD(&priv->sta_list);
-       spin_unlock_irqrestore(&priv->sta_list_spinlock, flags);
-       return;
-}
-
-/* This function adds histogram data to histogram array*/
-void mwifiex_hist_data_add(struct mwifiex_private *priv,
-                          u8 rx_rate, s8 snr, s8 nflr)
-{
-       struct mwifiex_histogram_data *phist_data = priv->hist_data;
-
-       if (atomic_read(&phist_data->num_samples) > MWIFIEX_HIST_MAX_SAMPLES)
-               mwifiex_hist_data_reset(priv);
-       mwifiex_hist_data_set(priv, rx_rate, snr, nflr);
-}
-
-/* function to add histogram record */
-void mwifiex_hist_data_set(struct mwifiex_private *priv, u8 rx_rate, s8 snr,
-                          s8 nflr)
-{
-       struct mwifiex_histogram_data *phist_data = priv->hist_data;
-
-       atomic_inc(&phist_data->num_samples);
-       atomic_inc(&phist_data->rx_rate[rx_rate]);
-       atomic_inc(&phist_data->snr[snr]);
-       atomic_inc(&phist_data->noise_flr[128 + nflr]);
-       atomic_inc(&phist_data->sig_str[nflr - snr]);
-}
-
-/* function to reset histogram data during init/reset */
-void mwifiex_hist_data_reset(struct mwifiex_private *priv)
-{
-       int ix;
-       struct mwifiex_histogram_data *phist_data = priv->hist_data;
-
-       atomic_set(&phist_data->num_samples, 0);
-       for (ix = 0; ix < MWIFIEX_MAX_AC_RX_RATES; ix++)
-               atomic_set(&phist_data->rx_rate[ix], 0);
-       for (ix = 0; ix < MWIFIEX_MAX_SNR; ix++)
-               atomic_set(&phist_data->snr[ix], 0);
-       for (ix = 0; ix < MWIFIEX_MAX_NOISE_FLR; ix++)
-               atomic_set(&phist_data->noise_flr[ix], 0);
-       for (ix = 0; ix < MWIFIEX_MAX_SIG_STRENGTH; ix++)
-               atomic_set(&phist_data->sig_str[ix], 0);
-}
-
-void *mwifiex_alloc_dma_align_buf(int rx_len, gfp_t flags)
-{
-       struct sk_buff *skb;
-       int buf_len, pad;
-
-       buf_len = rx_len + MWIFIEX_RX_HEADROOM + MWIFIEX_DMA_ALIGN_SZ;
-
-       skb = __dev_alloc_skb(buf_len, flags);
-
-       if (!skb)
-               return NULL;
-
-       skb_reserve(skb, MWIFIEX_RX_HEADROOM);
-
-       pad = MWIFIEX_ALIGN_ADDR(skb->data, MWIFIEX_DMA_ALIGN_SZ) -
-             (long)skb->data;
-
-       skb_reserve(skb, pad);
-
-       return skb;
-}
-EXPORT_SYMBOL_GPL(mwifiex_alloc_dma_align_buf);
diff --git a/drivers/net/wireless/mwifiex/util.h b/drivers/net/wireless/mwifiex/util.h
deleted file mode 100644 (file)
index b541d66..0000000
+++ /dev/null
@@ -1,96 +0,0 @@
-/*
- * Marvell Wireless LAN device driver: utility functions
- *
- * Copyright (C) 2011-2014, Marvell International Ltd.
- *
- * This software file (the "File") is distributed by Marvell International
- * Ltd. under the terms of the GNU General Public License Version 2, June 1991
- * (the "License").  You may use, redistribute and/or modify this File in
- * accordance with the terms and conditions of the License, a copy of which
- * is available by writing to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the
- * worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
- *
- * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
- * ARE EXPRESSLY DISCLAIMED.  The License provides additional details about
- * this warranty disclaimer.
- */
-
-#ifndef _MWIFIEX_UTIL_H_
-#define _MWIFIEX_UTIL_H_
-
-struct mwifiex_private;
-
-struct mwifiex_dma_mapping {
-       dma_addr_t addr;
-       size_t len;
-};
-
-struct mwifiex_cb {
-       struct mwifiex_dma_mapping dma_mapping;
-       union {
-               struct mwifiex_rxinfo rx_info;
-               struct mwifiex_txinfo tx_info;
-       };
-};
-
-/* size/addr for mwifiex_debug_info */
-#define item_size(n)           (FIELD_SIZEOF(struct mwifiex_debug_info, n))
-#define item_addr(n)           (offsetof(struct mwifiex_debug_info, n))
-
-/* size/addr for struct mwifiex_adapter */
-#define adapter_item_size(n)   (FIELD_SIZEOF(struct mwifiex_adapter, n))
-#define adapter_item_addr(n)   (offsetof(struct mwifiex_adapter, n))
-
-struct mwifiex_debug_data {
-       char name[32];          /* variable/array name */
-       u32 size;               /* size of the variable/array */
-       size_t addr;            /* address of the variable/array */
-       int num;                /* number of variables in an array */
-};
-
-static inline struct mwifiex_rxinfo *MWIFIEX_SKB_RXCB(struct sk_buff *skb)
-{
-       struct mwifiex_cb *cb = (struct mwifiex_cb *)skb->cb;
-
-       BUILD_BUG_ON(sizeof(struct mwifiex_cb) > sizeof(skb->cb));
-       return &cb->rx_info;
-}
-
-static inline struct mwifiex_txinfo *MWIFIEX_SKB_TXCB(struct sk_buff *skb)
-{
-       struct mwifiex_cb *cb = (struct mwifiex_cb *)skb->cb;
-
-       return &cb->tx_info;
-}
-
-static inline void mwifiex_store_mapping(struct sk_buff *skb,
-                                        struct mwifiex_dma_mapping *mapping)
-{
-       struct mwifiex_cb *cb = (struct mwifiex_cb *)skb->cb;
-
-       memcpy(&cb->dma_mapping, mapping, sizeof(*mapping));
-}
-
-static inline void mwifiex_get_mapping(struct sk_buff *skb,
-                                      struct mwifiex_dma_mapping *mapping)
-{
-       struct mwifiex_cb *cb = (struct mwifiex_cb *)skb->cb;
-
-       memcpy(mapping, &cb->dma_mapping, sizeof(*mapping));
-}
-
-static inline dma_addr_t MWIFIEX_SKB_DMA_ADDR(struct sk_buff *skb)
-{
-       struct mwifiex_dma_mapping mapping;
-
-       mwifiex_get_mapping(skb, &mapping);
-
-       return mapping.addr;
-}
-
-int mwifiex_debug_info_to_buffer(struct mwifiex_private *priv, char *buf,
-                                struct mwifiex_debug_info *info);
-
-#endif /* !_MWIFIEX_UTIL_H_ */
diff --git a/drivers/net/wireless/mwifiex/wmm.c b/drivers/net/wireless/mwifiex/wmm.c
deleted file mode 100644 (file)
index acccd67..0000000
+++ /dev/null
@@ -1,1531 +0,0 @@
-/*
- * Marvell Wireless LAN device driver: WMM
- *
- * Copyright (C) 2011-2014, Marvell International Ltd.
- *
- * This software file (the "File") is distributed by Marvell International
- * Ltd. under the terms of the GNU General Public License Version 2, June 1991
- * (the "License").  You may use, redistribute and/or modify this File in
- * accordance with the terms and conditions of the License, a copy of which
- * is available by writing to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the
- * worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
- *
- * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
- * ARE EXPRESSLY DISCLAIMED.  The License provides additional details about
- * this warranty disclaimer.
- */
-
-#include "decl.h"
-#include "ioctl.h"
-#include "util.h"
-#include "fw.h"
-#include "main.h"
-#include "wmm.h"
-#include "11n.h"
-
-
-/* Maximum value FW can accept for driver delay in packet transmission */
-#define DRV_PKT_DELAY_TO_FW_MAX   512
-
-
-#define WMM_QUEUED_PACKET_LOWER_LIMIT   180
-
-#define WMM_QUEUED_PACKET_UPPER_LIMIT   200
-
-/* Offset for TOS field in the IP header */
-#define IPTOS_OFFSET 5
-
-static bool disable_tx_amsdu;
-module_param(disable_tx_amsdu, bool, 0644);
-
-/* WMM information IE */
-static const u8 wmm_info_ie[] = { WLAN_EID_VENDOR_SPECIFIC, 0x07,
-       0x00, 0x50, 0xf2, 0x02,
-       0x00, 0x01, 0x00
-};
-
-static const u8 wmm_aci_to_qidx_map[] = { WMM_AC_BE,
-       WMM_AC_BK,
-       WMM_AC_VI,
-       WMM_AC_VO
-};
-
-static u8 tos_to_tid[] = {
-       /* TID DSCP_P2 DSCP_P1 DSCP_P0 WMM_AC */
-       0x01,                   /* 0 1 0 AC_BK */
-       0x02,                   /* 0 0 0 AC_BK */
-       0x00,                   /* 0 0 1 AC_BE */
-       0x03,                   /* 0 1 1 AC_BE */
-       0x04,                   /* 1 0 0 AC_VI */
-       0x05,                   /* 1 0 1 AC_VI */
-       0x06,                   /* 1 1 0 AC_VO */
-       0x07                    /* 1 1 1 AC_VO */
-};
-
-static u8 ac_to_tid[4][2] = { {1, 2}, {0, 3}, {4, 5}, {6, 7} };
-
-/*
- * This function debug prints the priority parameters for a WMM AC.
- */
-static void
-mwifiex_wmm_ac_debug_print(const struct ieee_types_wmm_ac_parameters *ac_param)
-{
-       const char *ac_str[] = { "BK", "BE", "VI", "VO" };
-
-       pr_debug("info: WMM AC_%s: ACI=%d, ACM=%d, Aifsn=%d, "
-                "EcwMin=%d, EcwMax=%d, TxopLimit=%d\n",
-                ac_str[wmm_aci_to_qidx_map[(ac_param->aci_aifsn_bitmap
-                                            & MWIFIEX_ACI) >> 5]],
-                (ac_param->aci_aifsn_bitmap & MWIFIEX_ACI) >> 5,
-                (ac_param->aci_aifsn_bitmap & MWIFIEX_ACM) >> 4,
-                ac_param->aci_aifsn_bitmap & MWIFIEX_AIFSN,
-                ac_param->ecw_bitmap & MWIFIEX_ECW_MIN,
-                (ac_param->ecw_bitmap & MWIFIEX_ECW_MAX) >> 4,
-                le16_to_cpu(ac_param->tx_op_limit));
-}
-
-/*
- * This function allocates a route address list.
- *
- * The function also initializes the list with the provided RA.
- */
-static struct mwifiex_ra_list_tbl *
-mwifiex_wmm_allocate_ralist_node(struct mwifiex_adapter *adapter, const u8 *ra)
-{
-       struct mwifiex_ra_list_tbl *ra_list;
-
-       ra_list = kzalloc(sizeof(struct mwifiex_ra_list_tbl), GFP_ATOMIC);
-       if (!ra_list)
-               return NULL;
-
-       INIT_LIST_HEAD(&ra_list->list);
-       skb_queue_head_init(&ra_list->skb_head);
-
-       memcpy(ra_list->ra, ra, ETH_ALEN);
-
-       ra_list->total_pkt_count = 0;
-
-       mwifiex_dbg(adapter, INFO, "info: allocated ra_list %p\n", ra_list);
-
-       return ra_list;
-}
-
-/* This function returns random no between 16 and 32 to be used as threshold
- * for no of packets after which BA setup is initiated.
- */
-static u8 mwifiex_get_random_ba_threshold(void)
-{
-       u64 ns;
-       /* setup ba_packet_threshold here random number between
-        * [BA_SETUP_PACKET_OFFSET,
-        * BA_SETUP_PACKET_OFFSET+BA_SETUP_MAX_PACKET_THRESHOLD-1]
-        */
-       ns = ktime_get_ns();
-       ns += (ns >> 32) + (ns >> 16);
-
-       return ((u8)ns % BA_SETUP_MAX_PACKET_THRESHOLD) + BA_SETUP_PACKET_OFFSET;
-}
-
-/*
- * This function allocates and adds a RA list for all TIDs
- * with the given RA.
- */
-void mwifiex_ralist_add(struct mwifiex_private *priv, const u8 *ra)
-{
-       int i;
-       struct mwifiex_ra_list_tbl *ra_list;
-       struct mwifiex_adapter *adapter = priv->adapter;
-       struct mwifiex_sta_node *node;
-       unsigned long flags;
-
-
-       for (i = 0; i < MAX_NUM_TID; ++i) {
-               ra_list = mwifiex_wmm_allocate_ralist_node(adapter, ra);
-               mwifiex_dbg(adapter, INFO,
-                           "info: created ra_list %p\n", ra_list);
-
-               if (!ra_list)
-                       break;
-
-               ra_list->is_11n_enabled = 0;
-               ra_list->tdls_link = false;
-               ra_list->ba_status = BA_SETUP_NONE;
-               ra_list->amsdu_in_ampdu = false;
-               if (!mwifiex_queuing_ra_based(priv)) {
-                       if (mwifiex_is_tdls_link_setup
-                               (mwifiex_get_tdls_link_status(priv, ra))) {
-                               ra_list->tdls_link = true;
-                               ra_list->is_11n_enabled =
-                                       mwifiex_tdls_peer_11n_enabled(priv, ra);
-                       } else {
-                               ra_list->is_11n_enabled = IS_11N_ENABLED(priv);
-                       }
-               } else {
-                       spin_lock_irqsave(&priv->sta_list_spinlock, flags);
-                       node = mwifiex_get_sta_entry(priv, ra);
-                       if (node)
-                               ra_list->tx_paused = node->tx_pause;
-                       ra_list->is_11n_enabled =
-                                     mwifiex_is_sta_11n_enabled(priv, node);
-                       if (ra_list->is_11n_enabled)
-                               ra_list->max_amsdu = node->max_amsdu;
-                       spin_unlock_irqrestore(&priv->sta_list_spinlock, flags);
-               }
-
-               mwifiex_dbg(adapter, DATA, "data: ralist %p: is_11n_enabled=%d\n",
-                           ra_list, ra_list->is_11n_enabled);
-
-               if (ra_list->is_11n_enabled) {
-                       ra_list->ba_pkt_count = 0;
-                       ra_list->ba_packet_thr =
-                                             mwifiex_get_random_ba_threshold();
-               }
-               list_add_tail(&ra_list->list,
-                             &priv->wmm.tid_tbl_ptr[i].ra_list);
-       }
-}
-
-/*
- * This function sets the WMM queue priorities to their default values.
- */
-static void mwifiex_wmm_default_queue_priorities(struct mwifiex_private *priv)
-{
-       /* Default queue priorities: VO->VI->BE->BK */
-       priv->wmm.queue_priority[0] = WMM_AC_VO;
-       priv->wmm.queue_priority[1] = WMM_AC_VI;
-       priv->wmm.queue_priority[2] = WMM_AC_BE;
-       priv->wmm.queue_priority[3] = WMM_AC_BK;
-}
-
-/*
- * This function map ACs to TIDs.
- */
-static void
-mwifiex_wmm_queue_priorities_tid(struct mwifiex_private *priv)
-{
-       struct mwifiex_wmm_desc *wmm = &priv->wmm;
-       u8 *queue_priority = wmm->queue_priority;
-       int i;
-
-       for (i = 0; i < 4; ++i) {
-               tos_to_tid[7 - (i * 2)] = ac_to_tid[queue_priority[i]][1];
-               tos_to_tid[6 - (i * 2)] = ac_to_tid[queue_priority[i]][0];
-       }
-
-       for (i = 0; i < MAX_NUM_TID; ++i)
-               priv->tos_to_tid_inv[tos_to_tid[i]] = (u8)i;
-
-       atomic_set(&wmm->highest_queued_prio, HIGH_PRIO_TID);
-}
-
-/*
- * This function initializes WMM priority queues.
- */
-void
-mwifiex_wmm_setup_queue_priorities(struct mwifiex_private *priv,
-                                  struct ieee_types_wmm_parameter *wmm_ie)
-{
-       u16 cw_min, avg_back_off, tmp[4];
-       u32 i, j, num_ac;
-       u8 ac_idx;
-
-       if (!wmm_ie || !priv->wmm_enabled) {
-               /* WMM is not enabled, just set the defaults and return */
-               mwifiex_wmm_default_queue_priorities(priv);
-               return;
-       }
-
-       mwifiex_dbg(priv->adapter, INFO,
-                   "info: WMM Parameter IE: version=%d,\t"
-                   "qos_info Parameter Set Count=%d, Reserved=%#x\n",
-                   wmm_ie->vend_hdr.version, wmm_ie->qos_info_bitmap &
-                   IEEE80211_WMM_IE_AP_QOSINFO_PARAM_SET_CNT_MASK,
-                   wmm_ie->reserved);
-
-       for (num_ac = 0; num_ac < ARRAY_SIZE(wmm_ie->ac_params); num_ac++) {
-               u8 ecw = wmm_ie->ac_params[num_ac].ecw_bitmap;
-               u8 aci_aifsn = wmm_ie->ac_params[num_ac].aci_aifsn_bitmap;
-               cw_min = (1 << (ecw & MWIFIEX_ECW_MIN)) - 1;
-               avg_back_off = (cw_min >> 1) + (aci_aifsn & MWIFIEX_AIFSN);
-
-               ac_idx = wmm_aci_to_qidx_map[(aci_aifsn & MWIFIEX_ACI) >> 5];
-               priv->wmm.queue_priority[ac_idx] = ac_idx;
-               tmp[ac_idx] = avg_back_off;
-
-               mwifiex_dbg(priv->adapter, INFO,
-                           "info: WMM: CWmax=%d CWmin=%d Avg Back-off=%d\n",
-                           (1 << ((ecw & MWIFIEX_ECW_MAX) >> 4)) - 1,
-                           cw_min, avg_back_off);
-               mwifiex_wmm_ac_debug_print(&wmm_ie->ac_params[num_ac]);
-       }
-
-       /* Bubble sort */
-       for (i = 0; i < num_ac; i++) {
-               for (j = 1; j < num_ac - i; j++) {
-                       if (tmp[j - 1] > tmp[j]) {
-                               swap(tmp[j - 1], tmp[j]);
-                               swap(priv->wmm.queue_priority[j - 1],
-                                    priv->wmm.queue_priority[j]);
-                       } else if (tmp[j - 1] == tmp[j]) {
-                               if (priv->wmm.queue_priority[j - 1]
-                                   < priv->wmm.queue_priority[j])
-                                       swap(priv->wmm.queue_priority[j - 1],
-                                            priv->wmm.queue_priority[j]);
-                       }
-               }
-       }
-
-       mwifiex_wmm_queue_priorities_tid(priv);
-}
-
-/*
- * This function evaluates whether or not an AC is to be downgraded.
- *
- * In case the AC is not enabled, the highest AC is returned that is
- * enabled and does not require admission control.
- */
-static enum mwifiex_wmm_ac_e
-mwifiex_wmm_eval_downgrade_ac(struct mwifiex_private *priv,
-                             enum mwifiex_wmm_ac_e eval_ac)
-{
-       int down_ac;
-       enum mwifiex_wmm_ac_e ret_ac;
-       struct mwifiex_wmm_ac_status *ac_status;
-
-       ac_status = &priv->wmm.ac_status[eval_ac];
-
-       if (!ac_status->disabled)
-               /* Okay to use this AC, its enabled */
-               return eval_ac;
-
-       /* Setup a default return value of the lowest priority */
-       ret_ac = WMM_AC_BK;
-
-       /*
-        *  Find the highest AC that is enabled and does not require
-        *  admission control. The spec disallows downgrading to an AC,
-        *  which is enabled due to a completed admission control.
-        *  Unadmitted traffic is not to be sent on an AC with admitted
-        *  traffic.
-        */
-       for (down_ac = WMM_AC_BK; down_ac < eval_ac; down_ac++) {
-               ac_status = &priv->wmm.ac_status[down_ac];
-
-               if (!ac_status->disabled && !ac_status->flow_required)
-                       /* AC is enabled and does not require admission
-                          control */
-                       ret_ac = (enum mwifiex_wmm_ac_e) down_ac;
-       }
-
-       return ret_ac;
-}
-
-/*
- * This function downgrades WMM priority queue.
- */
-void
-mwifiex_wmm_setup_ac_downgrade(struct mwifiex_private *priv)
-{
-       int ac_val;
-
-       mwifiex_dbg(priv->adapter, INFO, "info: WMM: AC Priorities:\t"
-                   "BK(0), BE(1), VI(2), VO(3)\n");
-
-       if (!priv->wmm_enabled) {
-               /* WMM is not enabled, default priorities */
-               for (ac_val = WMM_AC_BK; ac_val <= WMM_AC_VO; ac_val++)
-                       priv->wmm.ac_down_graded_vals[ac_val] =
-                                               (enum mwifiex_wmm_ac_e) ac_val;
-       } else {
-               for (ac_val = WMM_AC_BK; ac_val <= WMM_AC_VO; ac_val++) {
-                       priv->wmm.ac_down_graded_vals[ac_val]
-                               = mwifiex_wmm_eval_downgrade_ac(priv,
-                                               (enum mwifiex_wmm_ac_e) ac_val);
-                       mwifiex_dbg(priv->adapter, INFO,
-                                   "info: WMM: AC PRIO %d maps to %d\n",
-                                   ac_val,
-                                   priv->wmm.ac_down_graded_vals[ac_val]);
-               }
-       }
-}
-
-/*
- * This function converts the IP TOS field to an WMM AC
- * Queue assignment.
- */
-static enum mwifiex_wmm_ac_e
-mwifiex_wmm_convert_tos_to_ac(struct mwifiex_adapter *adapter, u32 tos)
-{
-       /* Map of TOS UP values to WMM AC */
-       const enum mwifiex_wmm_ac_e tos_to_ac[] = { WMM_AC_BE,
-               WMM_AC_BK,
-               WMM_AC_BK,
-               WMM_AC_BE,
-               WMM_AC_VI,
-               WMM_AC_VI,
-               WMM_AC_VO,
-               WMM_AC_VO
-       };
-
-       if (tos >= ARRAY_SIZE(tos_to_ac))
-               return WMM_AC_BE;
-
-       return tos_to_ac[tos];
-}
-
-/*
- * This function evaluates a given TID and downgrades it to a lower
- * TID if the WMM Parameter IE received from the AP indicates that the
- * AP is disabled (due to call admission control (ACM bit). Mapping
- * of TID to AC is taken care of internally.
- */
-u8 mwifiex_wmm_downgrade_tid(struct mwifiex_private *priv, u32 tid)
-{
-       enum mwifiex_wmm_ac_e ac, ac_down;
-       u8 new_tid;
-
-       ac = mwifiex_wmm_convert_tos_to_ac(priv->adapter, tid);
-       ac_down = priv->wmm.ac_down_graded_vals[ac];
-
-       /* Send the index to tid array, picking from the array will be
-        * taken care by dequeuing function
-        */
-       new_tid = ac_to_tid[ac_down][tid % 2];
-
-       return new_tid;
-}
-
-/*
- * This function initializes the WMM state information and the
- * WMM data path queues.
- */
-void
-mwifiex_wmm_init(struct mwifiex_adapter *adapter)
-{
-       int i, j;
-       struct mwifiex_private *priv;
-
-       for (j = 0; j < adapter->priv_num; ++j) {
-               priv = adapter->priv[j];
-               if (!priv)
-                       continue;
-
-               for (i = 0; i < MAX_NUM_TID; ++i) {
-                       if (!disable_tx_amsdu &&
-                           adapter->tx_buf_size > MWIFIEX_TX_DATA_BUF_SIZE_2K)
-                               priv->aggr_prio_tbl[i].amsdu =
-                                                       priv->tos_to_tid_inv[i];
-                       else
-                               priv->aggr_prio_tbl[i].amsdu =
-                                                       BA_STREAM_NOT_ALLOWED;
-                       priv->aggr_prio_tbl[i].ampdu_ap =
-                                                       priv->tos_to_tid_inv[i];
-                       priv->aggr_prio_tbl[i].ampdu_user =
-                                                       priv->tos_to_tid_inv[i];
-               }
-
-               priv->aggr_prio_tbl[6].amsdu
-                                       = priv->aggr_prio_tbl[6].ampdu_ap
-                                       = priv->aggr_prio_tbl[6].ampdu_user
-                                       = BA_STREAM_NOT_ALLOWED;
-
-               priv->aggr_prio_tbl[7].amsdu = priv->aggr_prio_tbl[7].ampdu_ap
-                                       = priv->aggr_prio_tbl[7].ampdu_user
-                                       = BA_STREAM_NOT_ALLOWED;
-
-               mwifiex_set_ba_params(priv);
-               mwifiex_reset_11n_rx_seq_num(priv);
-
-               atomic_set(&priv->wmm.tx_pkts_queued, 0);
-               atomic_set(&priv->wmm.highest_queued_prio, HIGH_PRIO_TID);
-       }
-}
-
-int mwifiex_bypass_txlist_empty(struct mwifiex_adapter *adapter)
-{
-       struct mwifiex_private *priv;
-       int i;
-
-       for (i = 0; i < adapter->priv_num; i++) {
-               priv = adapter->priv[i];
-               if (!priv)
-                       continue;
-               if (adapter->if_ops.is_port_ready &&
-                   !adapter->if_ops.is_port_ready(priv))
-                       continue;
-               if (!skb_queue_empty(&priv->bypass_txq))
-                       return false;
-       }
-
-       return true;
-}
-
-/*
- * This function checks if WMM Tx queue is empty.
- */
-int
-mwifiex_wmm_lists_empty(struct mwifiex_adapter *adapter)
-{
-       int i;
-       struct mwifiex_private *priv;
-
-       for (i = 0; i < adapter->priv_num; ++i) {
-               priv = adapter->priv[i];
-               if (!priv)
-                       continue;
-               if (!priv->port_open)
-                       continue;
-               if (adapter->if_ops.is_port_ready &&
-                   !adapter->if_ops.is_port_ready(priv))
-                       continue;
-               if (atomic_read(&priv->wmm.tx_pkts_queued))
-                       return false;
-       }
-
-       return true;
-}
-
-/*
- * This function deletes all packets in an RA list node.
- *
- * The packet sent completion callback handler are called with
- * status failure, after they are dequeued to ensure proper
- * cleanup. The RA list node itself is freed at the end.
- */
-static void
-mwifiex_wmm_del_pkts_in_ralist_node(struct mwifiex_private *priv,
-                                   struct mwifiex_ra_list_tbl *ra_list)
-{
-       struct mwifiex_adapter *adapter = priv->adapter;
-       struct sk_buff *skb, *tmp;
-
-       skb_queue_walk_safe(&ra_list->skb_head, skb, tmp)
-               mwifiex_write_data_complete(adapter, skb, 0, -1);
-}
-
-/*
- * This function deletes all packets in an RA list.
- *
- * Each nodes in the RA list are freed individually first, and then
- * the RA list itself is freed.
- */
-static void
-mwifiex_wmm_del_pkts_in_ralist(struct mwifiex_private *priv,
-                              struct list_head *ra_list_head)
-{
-       struct mwifiex_ra_list_tbl *ra_list;
-
-       list_for_each_entry(ra_list, ra_list_head, list)
-               mwifiex_wmm_del_pkts_in_ralist_node(priv, ra_list);
-}
-
-/*
- * This function deletes all packets in all RA lists.
- */
-static void mwifiex_wmm_cleanup_queues(struct mwifiex_private *priv)
-{
-       int i;
-
-       for (i = 0; i < MAX_NUM_TID; i++)
-               mwifiex_wmm_del_pkts_in_ralist(priv, &priv->wmm.tid_tbl_ptr[i].
-                                                                      ra_list);
-
-       atomic_set(&priv->wmm.tx_pkts_queued, 0);
-       atomic_set(&priv->wmm.highest_queued_prio, HIGH_PRIO_TID);
-}
-
-/*
- * This function deletes all route addresses from all RA lists.
- */
-static void mwifiex_wmm_delete_all_ralist(struct mwifiex_private *priv)
-{
-       struct mwifiex_ra_list_tbl *ra_list, *tmp_node;
-       int i;
-
-       for (i = 0; i < MAX_NUM_TID; ++i) {
-               mwifiex_dbg(priv->adapter, INFO,
-                           "info: ra_list: freeing buf for tid %d\n", i);
-               list_for_each_entry_safe(ra_list, tmp_node,
-                                        &priv->wmm.tid_tbl_ptr[i].ra_list,
-                                        list) {
-                       list_del(&ra_list->list);
-                       kfree(ra_list);
-               }
-
-               INIT_LIST_HEAD(&priv->wmm.tid_tbl_ptr[i].ra_list);
-       }
-}
-
-static int mwifiex_free_ack_frame(int id, void *p, void *data)
-{
-       pr_warn("Have pending ack frames!\n");
-       kfree_skb(p);
-       return 0;
-}
-
-/*
- * This function cleans up the Tx and Rx queues.
- *
- * Cleanup includes -
- *      - All packets in RA lists
- *      - All entries in Rx reorder table
- *      - All entries in Tx BA stream table
- *      - MPA buffer (if required)
- *      - All RA lists
- */
-void
-mwifiex_clean_txrx(struct mwifiex_private *priv)
-{
-       unsigned long flags;
-       struct sk_buff *skb, *tmp;
-
-       mwifiex_11n_cleanup_reorder_tbl(priv);
-       spin_lock_irqsave(&priv->wmm.ra_list_spinlock, flags);
-
-       mwifiex_wmm_cleanup_queues(priv);
-       mwifiex_11n_delete_all_tx_ba_stream_tbl(priv);
-
-       if (priv->adapter->if_ops.cleanup_mpa_buf)
-               priv->adapter->if_ops.cleanup_mpa_buf(priv->adapter);
-
-       mwifiex_wmm_delete_all_ralist(priv);
-       memcpy(tos_to_tid, ac_to_tid, sizeof(tos_to_tid));
-
-       if (priv->adapter->if_ops.clean_pcie_ring &&
-           !priv->adapter->surprise_removed)
-               priv->adapter->if_ops.clean_pcie_ring(priv->adapter);
-       spin_unlock_irqrestore(&priv->wmm.ra_list_spinlock, flags);
-
-       skb_queue_walk_safe(&priv->tdls_txq, skb, tmp)
-               mwifiex_write_data_complete(priv->adapter, skb, 0, -1);
-
-       skb_queue_walk_safe(&priv->bypass_txq, skb, tmp)
-               mwifiex_write_data_complete(priv->adapter, skb, 0, -1);
-       atomic_set(&priv->adapter->bypass_tx_pending, 0);
-
-       idr_for_each(&priv->ack_status_frames, mwifiex_free_ack_frame, NULL);
-       idr_destroy(&priv->ack_status_frames);
-}
-
-/*
- * This function retrieves a particular RA list node, matching with the
- * given TID and RA address.
- */
-struct mwifiex_ra_list_tbl *
-mwifiex_wmm_get_ralist_node(struct mwifiex_private *priv, u8 tid,
-                           const u8 *ra_addr)
-{
-       struct mwifiex_ra_list_tbl *ra_list;
-
-       list_for_each_entry(ra_list, &priv->wmm.tid_tbl_ptr[tid].ra_list,
-                           list) {
-               if (!memcmp(ra_list->ra, ra_addr, ETH_ALEN))
-                       return ra_list;
-       }
-
-       return NULL;
-}
-
-void mwifiex_update_ralist_tx_pause(struct mwifiex_private *priv, u8 *mac,
-                                   u8 tx_pause)
-{
-       struct mwifiex_ra_list_tbl *ra_list;
-       u32 pkt_cnt = 0, tx_pkts_queued;
-       unsigned long flags;
-       int i;
-
-       spin_lock_irqsave(&priv->wmm.ra_list_spinlock, flags);
-
-       for (i = 0; i < MAX_NUM_TID; ++i) {
-               ra_list = mwifiex_wmm_get_ralist_node(priv, i, mac);
-               if (ra_list && ra_list->tx_paused != tx_pause) {
-                       pkt_cnt += ra_list->total_pkt_count;
-                       ra_list->tx_paused = tx_pause;
-                       if (tx_pause)
-                               priv->wmm.pkts_paused[i] +=
-                                       ra_list->total_pkt_count;
-                       else
-                               priv->wmm.pkts_paused[i] -=
-                                       ra_list->total_pkt_count;
-               }
-       }
-
-       if (pkt_cnt) {
-               tx_pkts_queued = atomic_read(&priv->wmm.tx_pkts_queued);
-               if (tx_pause)
-                       tx_pkts_queued -= pkt_cnt;
-               else
-                       tx_pkts_queued += pkt_cnt;
-
-               atomic_set(&priv->wmm.tx_pkts_queued, tx_pkts_queued);
-               atomic_set(&priv->wmm.highest_queued_prio, HIGH_PRIO_TID);
-       }
-       spin_unlock_irqrestore(&priv->wmm.ra_list_spinlock, flags);
-}
-
-/* This function update non-tdls peer ralist tx_pause while
- * tdls channel swithing
- */
-void mwifiex_update_ralist_tx_pause_in_tdls_cs(struct mwifiex_private *priv,
-                                              u8 *mac, u8 tx_pause)
-{
-       struct mwifiex_ra_list_tbl *ra_list;
-       u32 pkt_cnt = 0, tx_pkts_queued;
-       unsigned long flags;
-       int i;
-
-       spin_lock_irqsave(&priv->wmm.ra_list_spinlock, flags);
-
-       for (i = 0; i < MAX_NUM_TID; ++i) {
-               list_for_each_entry(ra_list, &priv->wmm.tid_tbl_ptr[i].ra_list,
-                                   list) {
-                       if (!memcmp(ra_list->ra, mac, ETH_ALEN))
-                               continue;
-
-                       if (ra_list->tx_paused != tx_pause) {
-                               pkt_cnt += ra_list->total_pkt_count;
-                               ra_list->tx_paused = tx_pause;
-                               if (tx_pause)
-                                       priv->wmm.pkts_paused[i] +=
-                                               ra_list->total_pkt_count;
-                               else
-                                       priv->wmm.pkts_paused[i] -=
-                                               ra_list->total_pkt_count;
-                       }
-               }
-       }
-
-       if (pkt_cnt) {
-               tx_pkts_queued = atomic_read(&priv->wmm.tx_pkts_queued);
-               if (tx_pause)
-                       tx_pkts_queued -= pkt_cnt;
-               else
-                       tx_pkts_queued += pkt_cnt;
-
-               atomic_set(&priv->wmm.tx_pkts_queued, tx_pkts_queued);
-               atomic_set(&priv->wmm.highest_queued_prio, HIGH_PRIO_TID);
-       }
-       spin_unlock_irqrestore(&priv->wmm.ra_list_spinlock, flags);
-}
-
-/*
- * This function retrieves an RA list node for a given TID and
- * RA address pair.
- *
- * If no such node is found, a new node is added first and then
- * retrieved.
- */
-struct mwifiex_ra_list_tbl *
-mwifiex_wmm_get_queue_raptr(struct mwifiex_private *priv, u8 tid,
-                           const u8 *ra_addr)
-{
-       struct mwifiex_ra_list_tbl *ra_list;
-
-       ra_list = mwifiex_wmm_get_ralist_node(priv, tid, ra_addr);
-       if (ra_list)
-               return ra_list;
-       mwifiex_ralist_add(priv, ra_addr);
-
-       return mwifiex_wmm_get_ralist_node(priv, tid, ra_addr);
-}
-
-/*
- * This function deletes RA list nodes for given mac for all TIDs.
- * Function also decrements TX pending count accordingly.
- */
-void
-mwifiex_wmm_del_peer_ra_list(struct mwifiex_private *priv, const u8 *ra_addr)
-{
-       struct mwifiex_ra_list_tbl *ra_list;
-       unsigned long flags;
-       int i;
-
-       spin_lock_irqsave(&priv->wmm.ra_list_spinlock, flags);
-
-       for (i = 0; i < MAX_NUM_TID; ++i) {
-               ra_list = mwifiex_wmm_get_ralist_node(priv, i, ra_addr);
-
-               if (!ra_list)
-                       continue;
-               mwifiex_wmm_del_pkts_in_ralist_node(priv, ra_list);
-               if (ra_list->tx_paused)
-                       priv->wmm.pkts_paused[i] -= ra_list->total_pkt_count;
-               else
-                       atomic_sub(ra_list->total_pkt_count,
-                                  &priv->wmm.tx_pkts_queued);
-               list_del(&ra_list->list);
-               kfree(ra_list);
-       }
-       spin_unlock_irqrestore(&priv->wmm.ra_list_spinlock, flags);
-}
-
-/*
- * This function checks if a particular RA list node exists in a given TID
- * table index.
- */
-int
-mwifiex_is_ralist_valid(struct mwifiex_private *priv,
-                       struct mwifiex_ra_list_tbl *ra_list, int ptr_index)
-{
-       struct mwifiex_ra_list_tbl *rlist;
-
-       list_for_each_entry(rlist, &priv->wmm.tid_tbl_ptr[ptr_index].ra_list,
-                           list) {
-               if (rlist == ra_list)
-                       return true;
-       }
-
-       return false;
-}
-
-/*
- * This function adds a packet to bypass TX queue.
- * This is special TX queue for packets which can be sent even when port_open
- * is false.
- */
-void
-mwifiex_wmm_add_buf_bypass_txqueue(struct mwifiex_private *priv,
-                                  struct sk_buff *skb)
-{
-       skb_queue_tail(&priv->bypass_txq, skb);
-}
-
-/*
- * This function adds a packet to WMM queue.
- *
- * In disconnected state the packet is immediately dropped and the
- * packet send completion callback is called with status failure.
- *
- * Otherwise, the correct RA list node is located and the packet
- * is queued at the list tail.
- */
-void
-mwifiex_wmm_add_buf_txqueue(struct mwifiex_private *priv,
-                           struct sk_buff *skb)
-{
-       struct mwifiex_adapter *adapter = priv->adapter;
-       u32 tid;
-       struct mwifiex_ra_list_tbl *ra_list;
-       u8 ra[ETH_ALEN], tid_down;
-       unsigned long flags;
-       struct list_head list_head;
-       int tdls_status = TDLS_NOT_SETUP;
-       struct ethhdr *eth_hdr = (struct ethhdr *)skb->data;
-       struct mwifiex_txinfo *tx_info = MWIFIEX_SKB_TXCB(skb);
-
-       memcpy(ra, eth_hdr->h_dest, ETH_ALEN);
-
-       if (GET_BSS_ROLE(priv) == MWIFIEX_BSS_ROLE_STA &&
-           ISSUPP_TDLS_ENABLED(adapter->fw_cap_info)) {
-               if (ntohs(eth_hdr->h_proto) == ETH_P_TDLS)
-                       mwifiex_dbg(adapter, DATA,
-                                   "TDLS setup packet for %pM.\t"
-                                   "Don't block\n", ra);
-               else if (memcmp(priv->cfg_bssid, ra, ETH_ALEN))
-                       tdls_status = mwifiex_get_tdls_link_status(priv, ra);
-       }
-
-       if (!priv->media_connected && !mwifiex_is_skb_mgmt_frame(skb)) {
-               mwifiex_dbg(adapter, DATA, "data: drop packet in disconnect\n");
-               mwifiex_write_data_complete(adapter, skb, 0, -1);
-               return;
-       }
-
-       tid = skb->priority;
-
-       spin_lock_irqsave(&priv->wmm.ra_list_spinlock, flags);
-
-       tid_down = mwifiex_wmm_downgrade_tid(priv, tid);
-
-       /* In case of infra as we have already created the list during
-          association we just don't have to call get_queue_raptr, we will
-          have only 1 raptr for a tid in case of infra */
-       if (!mwifiex_queuing_ra_based(priv) &&
-           !mwifiex_is_skb_mgmt_frame(skb)) {
-               switch (tdls_status) {
-               case TDLS_SETUP_COMPLETE:
-               case TDLS_CHAN_SWITCHING:
-               case TDLS_IN_BASE_CHAN:
-               case TDLS_IN_OFF_CHAN:
-                       ra_list = mwifiex_wmm_get_queue_raptr(priv, tid_down,
-                                                             ra);
-                       tx_info->flags |= MWIFIEX_BUF_FLAG_TDLS_PKT;
-                       break;
-               case TDLS_SETUP_INPROGRESS:
-                       skb_queue_tail(&priv->tdls_txq, skb);
-                       spin_unlock_irqrestore(&priv->wmm.ra_list_spinlock,
-                                              flags);
-                       return;
-               default:
-                       list_head = priv->wmm.tid_tbl_ptr[tid_down].ra_list;
-                       if (!list_empty(&list_head))
-                               ra_list = list_first_entry(
-                                       &list_head, struct mwifiex_ra_list_tbl,
-                                       list);
-                       else
-                               ra_list = NULL;
-                       break;
-               }
-       } else {
-               memcpy(ra, skb->data, ETH_ALEN);
-               if (ra[0] & 0x01 || mwifiex_is_skb_mgmt_frame(skb))
-                       eth_broadcast_addr(ra);
-               ra_list = mwifiex_wmm_get_queue_raptr(priv, tid_down, ra);
-       }
-
-       if (!ra_list) {
-               spin_unlock_irqrestore(&priv->wmm.ra_list_spinlock, flags);
-               mwifiex_write_data_complete(adapter, skb, 0, -1);
-               return;
-       }
-
-       skb_queue_tail(&ra_list->skb_head, skb);
-
-       ra_list->ba_pkt_count++;
-       ra_list->total_pkt_count++;
-
-       if (atomic_read(&priv->wmm.highest_queued_prio) <
-                                               priv->tos_to_tid_inv[tid_down])
-               atomic_set(&priv->wmm.highest_queued_prio,
-                          priv->tos_to_tid_inv[tid_down]);
-
-       if (ra_list->tx_paused)
-               priv->wmm.pkts_paused[tid_down]++;
-       else
-               atomic_inc(&priv->wmm.tx_pkts_queued);
-
-       spin_unlock_irqrestore(&priv->wmm.ra_list_spinlock, flags);
-}
-
-/*
- * This function processes the get WMM status command response from firmware.
- *
- * The response may contain multiple TLVs -
- *      - AC Queue status TLVs
- *      - Current WMM Parameter IE TLV
- *      - Admission Control action frame TLVs
- *
- * This function parses the TLVs and then calls further specific functions
- * to process any changes in the queue prioritize or state.
- */
-int mwifiex_ret_wmm_get_status(struct mwifiex_private *priv,
-                              const struct host_cmd_ds_command *resp)
-{
-       u8 *curr = (u8 *) &resp->params.get_wmm_status;
-       uint16_t resp_len = le16_to_cpu(resp->size), tlv_len;
-       int mask = IEEE80211_WMM_IE_AP_QOSINFO_PARAM_SET_CNT_MASK;
-       bool valid = true;
-
-       struct mwifiex_ie_types_data *tlv_hdr;
-       struct mwifiex_ie_types_wmm_queue_status *tlv_wmm_qstatus;
-       struct ieee_types_wmm_parameter *wmm_param_ie = NULL;
-       struct mwifiex_wmm_ac_status *ac_status;
-
-       mwifiex_dbg(priv->adapter, INFO,
-                   "info: WMM: WMM_GET_STATUS cmdresp received: %d\n",
-                   resp_len);
-
-       while ((resp_len >= sizeof(tlv_hdr->header)) && valid) {
-               tlv_hdr = (struct mwifiex_ie_types_data *) curr;
-               tlv_len = le16_to_cpu(tlv_hdr->header.len);
-
-               if (resp_len < tlv_len + sizeof(tlv_hdr->header))
-                       break;
-
-               switch (le16_to_cpu(tlv_hdr->header.type)) {
-               case TLV_TYPE_WMMQSTATUS:
-                       tlv_wmm_qstatus =
-                               (struct mwifiex_ie_types_wmm_queue_status *)
-                               tlv_hdr;
-                       mwifiex_dbg(priv->adapter, CMD,
-                                   "info: CMD_RESP: WMM_GET_STATUS:\t"
-                                   "QSTATUS TLV: %d, %d, %d\n",
-                                   tlv_wmm_qstatus->queue_index,
-                                   tlv_wmm_qstatus->flow_required,
-                                   tlv_wmm_qstatus->disabled);
-
-                       ac_status = &priv->wmm.ac_status[tlv_wmm_qstatus->
-                                                        queue_index];
-                       ac_status->disabled = tlv_wmm_qstatus->disabled;
-                       ac_status->flow_required =
-                                               tlv_wmm_qstatus->flow_required;
-                       ac_status->flow_created = tlv_wmm_qstatus->flow_created;
-                       break;
-
-               case WLAN_EID_VENDOR_SPECIFIC:
-                       /*
-                        * Point the regular IEEE IE 2 bytes into the Marvell IE
-                        *   and setup the IEEE IE type and length byte fields
-                        */
-
-                       wmm_param_ie =
-                               (struct ieee_types_wmm_parameter *) (curr +
-                                                                   2);
-                       wmm_param_ie->vend_hdr.len = (u8) tlv_len;
-                       wmm_param_ie->vend_hdr.element_id =
-                                               WLAN_EID_VENDOR_SPECIFIC;
-
-                       mwifiex_dbg(priv->adapter, CMD,
-                                   "info: CMD_RESP: WMM_GET_STATUS:\t"
-                                   "WMM Parameter Set Count: %d\n",
-                                   wmm_param_ie->qos_info_bitmap & mask);
-
-                       memcpy((u8 *) &priv->curr_bss_params.bss_descriptor.
-                              wmm_ie, wmm_param_ie,
-                              wmm_param_ie->vend_hdr.len + 2);
-
-                       break;
-
-               default:
-                       valid = false;
-                       break;
-               }
-
-               curr += (tlv_len + sizeof(tlv_hdr->header));
-               resp_len -= (tlv_len + sizeof(tlv_hdr->header));
-       }
-
-       mwifiex_wmm_setup_queue_priorities(priv, wmm_param_ie);
-       mwifiex_wmm_setup_ac_downgrade(priv);
-
-       return 0;
-}
-
-/*
- * Callback handler from the command module to allow insertion of a WMM TLV.
- *
- * If the BSS we are associating to supports WMM, this function adds the
- * required WMM Information IE to the association request command buffer in
- * the form of a Marvell extended IEEE IE.
- */
-u32
-mwifiex_wmm_process_association_req(struct mwifiex_private *priv,
-                                   u8 **assoc_buf,
-                                   struct ieee_types_wmm_parameter *wmm_ie,
-                                   struct ieee80211_ht_cap *ht_cap)
-{
-       struct mwifiex_ie_types_wmm_param_set *wmm_tlv;
-       u32 ret_len = 0;
-
-       /* Null checks */
-       if (!assoc_buf)
-               return 0;
-       if (!(*assoc_buf))
-               return 0;
-
-       if (!wmm_ie)
-               return 0;
-
-       mwifiex_dbg(priv->adapter, INFO,
-                   "info: WMM: process assoc req: bss->wmm_ie=%#x\n",
-                   wmm_ie->vend_hdr.element_id);
-
-       if ((priv->wmm_required ||
-            (ht_cap && (priv->adapter->config_bands & BAND_GN ||
-            priv->adapter->config_bands & BAND_AN))) &&
-           wmm_ie->vend_hdr.element_id == WLAN_EID_VENDOR_SPECIFIC) {
-               wmm_tlv = (struct mwifiex_ie_types_wmm_param_set *) *assoc_buf;
-               wmm_tlv->header.type = cpu_to_le16((u16) wmm_info_ie[0]);
-               wmm_tlv->header.len = cpu_to_le16((u16) wmm_info_ie[1]);
-               memcpy(wmm_tlv->wmm_ie, &wmm_info_ie[2],
-                      le16_to_cpu(wmm_tlv->header.len));
-               if (wmm_ie->qos_info_bitmap & IEEE80211_WMM_IE_AP_QOSINFO_UAPSD)
-                       memcpy((u8 *) (wmm_tlv->wmm_ie
-                                      + le16_to_cpu(wmm_tlv->header.len)
-                                      - sizeof(priv->wmm_qosinfo)),
-                              &priv->wmm_qosinfo, sizeof(priv->wmm_qosinfo));
-
-               ret_len = sizeof(wmm_tlv->header)
-                         + le16_to_cpu(wmm_tlv->header.len);
-
-               *assoc_buf += ret_len;
-       }
-
-       return ret_len;
-}
-
-/*
- * This function computes the time delay in the driver queues for a
- * given packet.
- *
- * When the packet is received at the OS/Driver interface, the current
- * time is set in the packet structure. The difference between the present
- * time and that received time is computed in this function and limited
- * based on pre-compiled limits in the driver.
- */
-u8
-mwifiex_wmm_compute_drv_pkt_delay(struct mwifiex_private *priv,
-                                 const struct sk_buff *skb)
-{
-       u32 queue_delay = ktime_to_ms(net_timedelta(skb->tstamp));
-       u8 ret_val;
-
-       /*
-        * Queue delay is passed as a uint8 in units of 2ms (ms shifted
-        *  by 1). Min value (other than 0) is therefore 2ms, max is 510ms.
-        *
-        * Pass max value if queue_delay is beyond the uint8 range
-        */
-       ret_val = (u8) (min(queue_delay, priv->wmm.drv_pkt_delay_max) >> 1);
-
-       mwifiex_dbg(priv->adapter, DATA, "data: WMM: Pkt Delay: %d ms,\t"
-                   "%d ms sent to FW\n", queue_delay, ret_val);
-
-       return ret_val;
-}
-
-/*
- * This function retrieves the highest priority RA list table pointer.
- */
-static struct mwifiex_ra_list_tbl *
-mwifiex_wmm_get_highest_priolist_ptr(struct mwifiex_adapter *adapter,
-                                    struct mwifiex_private **priv, int *tid)
-{
-       struct mwifiex_private *priv_tmp;
-       struct mwifiex_ra_list_tbl *ptr;
-       struct mwifiex_tid_tbl *tid_ptr;
-       atomic_t *hqp;
-       unsigned long flags_ra;
-       int i, j;
-
-       /* check the BSS with highest priority first */
-       for (j = adapter->priv_num - 1; j >= 0; --j) {
-               /* iterate over BSS with the equal priority */
-               list_for_each_entry(adapter->bss_prio_tbl[j].bss_prio_cur,
-                                   &adapter->bss_prio_tbl[j].bss_prio_head,
-                                   list) {
-
-                       priv_tmp = adapter->bss_prio_tbl[j].bss_prio_cur->priv;
-
-                       if (!priv_tmp->port_open ||
-                           (atomic_read(&priv_tmp->wmm.tx_pkts_queued) == 0))
-                               continue;
-
-                       if (adapter->if_ops.is_port_ready &&
-                           !adapter->if_ops.is_port_ready(priv_tmp))
-                               continue;
-
-                       /* iterate over the WMM queues of the BSS */
-                       hqp = &priv_tmp->wmm.highest_queued_prio;
-                       for (i = atomic_read(hqp); i >= LOW_PRIO_TID; --i) {
-
-                               spin_lock_irqsave(&priv_tmp->wmm.
-                                                 ra_list_spinlock, flags_ra);
-
-                               tid_ptr = &(priv_tmp)->wmm.
-                                       tid_tbl_ptr[tos_to_tid[i]];
-
-                               /* iterate over receiver addresses */
-                               list_for_each_entry(ptr, &tid_ptr->ra_list,
-                                                   list) {
-
-                                       if (!ptr->tx_paused &&
-                                           !skb_queue_empty(&ptr->skb_head))
-                                               /* holds both locks */
-                                               goto found;
-                               }
-
-                               spin_unlock_irqrestore(&priv_tmp->wmm.
-                                                      ra_list_spinlock,
-                                                      flags_ra);
-                       }
-               }
-
-       }
-
-       return NULL;
-
-found:
-       /* holds ra_list_spinlock */
-       if (atomic_read(hqp) > i)
-               atomic_set(hqp, i);
-       spin_unlock_irqrestore(&priv_tmp->wmm.ra_list_spinlock, flags_ra);
-
-       *priv = priv_tmp;
-       *tid = tos_to_tid[i];
-
-       return ptr;
-}
-
-/* This functions rotates ra and bss lists so packets are picked round robin.
- *
- * After a packet is successfully transmitted, rotate the ra list, so the ra
- * next to the one transmitted, will come first in the list. This way we pick
- * the ra' in a round robin fashion. Same applies to bss nodes of equal
- * priority.
- *
- * Function also increments wmm.packets_out counter.
- */
-void mwifiex_rotate_priolists(struct mwifiex_private *priv,
-                                struct mwifiex_ra_list_tbl *ra,
-                                int tid)
-{
-       struct mwifiex_adapter *adapter = priv->adapter;
-       struct mwifiex_bss_prio_tbl *tbl = adapter->bss_prio_tbl;
-       struct mwifiex_tid_tbl *tid_ptr = &priv->wmm.tid_tbl_ptr[tid];
-       unsigned long flags;
-
-       spin_lock_irqsave(&tbl[priv->bss_priority].bss_prio_lock, flags);
-       /*
-        * dirty trick: we remove 'head' temporarily and reinsert it after
-        * curr bss node. imagine list to stay fixed while head is moved
-        */
-       list_move(&tbl[priv->bss_priority].bss_prio_head,
-                 &tbl[priv->bss_priority].bss_prio_cur->list);
-       spin_unlock_irqrestore(&tbl[priv->bss_priority].bss_prio_lock, flags);
-
-       spin_lock_irqsave(&priv->wmm.ra_list_spinlock, flags);
-       if (mwifiex_is_ralist_valid(priv, ra, tid)) {
-               priv->wmm.packets_out[tid]++;
-               /* same as above */
-               list_move(&tid_ptr->ra_list, &ra->list);
-       }
-       spin_unlock_irqrestore(&priv->wmm.ra_list_spinlock, flags);
-}
-
-/*
- * This function checks if 11n aggregation is possible.
- */
-static int
-mwifiex_is_11n_aggragation_possible(struct mwifiex_private *priv,
-                                   struct mwifiex_ra_list_tbl *ptr,
-                                   int max_buf_size)
-{
-       int count = 0, total_size = 0;
-       struct sk_buff *skb, *tmp;
-       int max_amsdu_size;
-
-       if (priv->bss_role == MWIFIEX_BSS_ROLE_UAP && priv->ap_11n_enabled &&
-           ptr->is_11n_enabled)
-               max_amsdu_size = min_t(int, ptr->max_amsdu, max_buf_size);
-       else
-               max_amsdu_size = max_buf_size;
-
-       skb_queue_walk_safe(&ptr->skb_head, skb, tmp) {
-               total_size += skb->len;
-               if (total_size >= max_amsdu_size)
-                       break;
-               if (++count >= MIN_NUM_AMSDU)
-                       return true;
-       }
-
-       return false;
-}
-
-/*
- * This function sends a single packet to firmware for transmission.
- */
-static void
-mwifiex_send_single_packet(struct mwifiex_private *priv,
-                          struct mwifiex_ra_list_tbl *ptr, int ptr_index,
-                          unsigned long ra_list_flags)
-                          __releases(&priv->wmm.ra_list_spinlock)
-{
-       struct sk_buff *skb, *skb_next;
-       struct mwifiex_tx_param tx_param;
-       struct mwifiex_adapter *adapter = priv->adapter;
-       struct mwifiex_txinfo *tx_info;
-
-       if (skb_queue_empty(&ptr->skb_head)) {
-               spin_unlock_irqrestore(&priv->wmm.ra_list_spinlock,
-                                      ra_list_flags);
-               mwifiex_dbg(adapter, DATA, "data: nothing to send\n");
-               return;
-       }
-
-       skb = skb_dequeue(&ptr->skb_head);
-
-       tx_info = MWIFIEX_SKB_TXCB(skb);
-       mwifiex_dbg(adapter, DATA,
-                   "data: dequeuing the packet %p %p\n", ptr, skb);
-
-       ptr->total_pkt_count--;
-
-       if (!skb_queue_empty(&ptr->skb_head))
-               skb_next = skb_peek(&ptr->skb_head);
-       else
-               skb_next = NULL;
-
-       spin_unlock_irqrestore(&priv->wmm.ra_list_spinlock, ra_list_flags);
-
-       tx_param.next_pkt_len = ((skb_next) ? skb_next->len +
-                               sizeof(struct txpd) : 0);
-
-       if (mwifiex_process_tx(priv, skb, &tx_param) == -EBUSY) {
-               /* Queue the packet back at the head */
-               spin_lock_irqsave(&priv->wmm.ra_list_spinlock, ra_list_flags);
-
-               if (!mwifiex_is_ralist_valid(priv, ptr, ptr_index)) {
-                       spin_unlock_irqrestore(&priv->wmm.ra_list_spinlock,
-                                              ra_list_flags);
-                       mwifiex_write_data_complete(adapter, skb, 0, -1);
-                       return;
-               }
-
-               skb_queue_tail(&ptr->skb_head, skb);
-
-               ptr->total_pkt_count++;
-               ptr->ba_pkt_count++;
-               tx_info->flags |= MWIFIEX_BUF_FLAG_REQUEUED_PKT;
-               spin_unlock_irqrestore(&priv->wmm.ra_list_spinlock,
-                                      ra_list_flags);
-       } else {
-               mwifiex_rotate_priolists(priv, ptr, ptr_index);
-               atomic_dec(&priv->wmm.tx_pkts_queued);
-       }
-}
-
-/*
- * This function checks if the first packet in the given RA list
- * is already processed or not.
- */
-static int
-mwifiex_is_ptr_processed(struct mwifiex_private *priv,
-                        struct mwifiex_ra_list_tbl *ptr)
-{
-       struct sk_buff *skb;
-       struct mwifiex_txinfo *tx_info;
-
-       if (skb_queue_empty(&ptr->skb_head))
-               return false;
-
-       skb = skb_peek(&ptr->skb_head);
-
-       tx_info = MWIFIEX_SKB_TXCB(skb);
-       if (tx_info->flags & MWIFIEX_BUF_FLAG_REQUEUED_PKT)
-               return true;
-
-       return false;
-}
-
-/*
- * This function sends a single processed packet to firmware for
- * transmission.
- */
-static void
-mwifiex_send_processed_packet(struct mwifiex_private *priv,
-                             struct mwifiex_ra_list_tbl *ptr, int ptr_index,
-                             unsigned long ra_list_flags)
-                               __releases(&priv->wmm.ra_list_spinlock)
-{
-       struct mwifiex_tx_param tx_param;
-       struct mwifiex_adapter *adapter = priv->adapter;
-       int ret = -1;
-       struct sk_buff *skb, *skb_next;
-       struct mwifiex_txinfo *tx_info;
-
-       if (skb_queue_empty(&ptr->skb_head)) {
-               spin_unlock_irqrestore(&priv->wmm.ra_list_spinlock,
-                                      ra_list_flags);
-               return;
-       }
-
-       skb = skb_dequeue(&ptr->skb_head);
-
-       if (adapter->data_sent || adapter->tx_lock_flag) {
-               spin_unlock_irqrestore(&priv->wmm.ra_list_spinlock,
-                                      ra_list_flags);
-               skb_queue_tail(&adapter->tx_data_q, skb);
-               atomic_inc(&adapter->tx_queued);
-               return;
-       }
-
-       if (!skb_queue_empty(&ptr->skb_head))
-               skb_next = skb_peek(&ptr->skb_head);
-       else
-               skb_next = NULL;
-
-       tx_info = MWIFIEX_SKB_TXCB(skb);
-
-       spin_unlock_irqrestore(&priv->wmm.ra_list_spinlock, ra_list_flags);
-
-       if (adapter->iface_type == MWIFIEX_USB) {
-               ret = adapter->if_ops.host_to_card(adapter, priv->usb_port,
-                                                  skb, NULL);
-       } else {
-               tx_param.next_pkt_len =
-                       ((skb_next) ? skb_next->len +
-                        sizeof(struct txpd) : 0);
-               ret = adapter->if_ops.host_to_card(adapter, MWIFIEX_TYPE_DATA,
-                                                  skb, &tx_param);
-       }
-
-       switch (ret) {
-       case -EBUSY:
-               mwifiex_dbg(adapter, ERROR, "data: -EBUSY is returned\n");
-               spin_lock_irqsave(&priv->wmm.ra_list_spinlock, ra_list_flags);
-
-               if (!mwifiex_is_ralist_valid(priv, ptr, ptr_index)) {
-                       spin_unlock_irqrestore(&priv->wmm.ra_list_spinlock,
-                                              ra_list_flags);
-                       mwifiex_write_data_complete(adapter, skb, 0, -1);
-                       return;
-               }
-
-               skb_queue_tail(&ptr->skb_head, skb);
-
-               tx_info->flags |= MWIFIEX_BUF_FLAG_REQUEUED_PKT;
-               spin_unlock_irqrestore(&priv->wmm.ra_list_spinlock,
-                                      ra_list_flags);
-               break;
-       case -1:
-               mwifiex_dbg(adapter, ERROR, "host_to_card failed: %#x\n", ret);
-               adapter->dbg.num_tx_host_to_card_failure++;
-               mwifiex_write_data_complete(adapter, skb, 0, ret);
-               break;
-       case -EINPROGRESS:
-               break;
-       case 0:
-               mwifiex_write_data_complete(adapter, skb, 0, ret);
-       default:
-               break;
-       }
-       if (ret != -EBUSY) {
-               mwifiex_rotate_priolists(priv, ptr, ptr_index);
-               atomic_dec(&priv->wmm.tx_pkts_queued);
-       }
-}
-
-/*
- * This function dequeues a packet from the highest priority list
- * and transmits it.
- */
-static int
-mwifiex_dequeue_tx_packet(struct mwifiex_adapter *adapter)
-{
-       struct mwifiex_ra_list_tbl *ptr;
-       struct mwifiex_private *priv = NULL;
-       int ptr_index = 0;
-       u8 ra[ETH_ALEN];
-       int tid_del = 0, tid = 0;
-       unsigned long flags;
-
-       ptr = mwifiex_wmm_get_highest_priolist_ptr(adapter, &priv, &ptr_index);
-       if (!ptr)
-               return -1;
-
-       tid = mwifiex_get_tid(ptr);
-
-       mwifiex_dbg(adapter, DATA, "data: tid=%d\n", tid);
-
-       spin_lock_irqsave(&priv->wmm.ra_list_spinlock, flags);
-       if (!mwifiex_is_ralist_valid(priv, ptr, ptr_index)) {
-               spin_unlock_irqrestore(&priv->wmm.ra_list_spinlock, flags);
-               return -1;
-       }
-
-       if (mwifiex_is_ptr_processed(priv, ptr)) {
-               mwifiex_send_processed_packet(priv, ptr, ptr_index, flags);
-               /* ra_list_spinlock has been freed in
-                  mwifiex_send_processed_packet() */
-               return 0;
-       }
-
-       if (!ptr->is_11n_enabled ||
-               ptr->ba_status ||
-               priv->wps.session_enable) {
-               if (ptr->is_11n_enabled &&
-                       ptr->ba_status &&
-                       ptr->amsdu_in_ampdu &&
-                       mwifiex_is_amsdu_allowed(priv, tid) &&
-                       mwifiex_is_11n_aggragation_possible(priv, ptr,
-                                                       adapter->tx_buf_size))
-                       mwifiex_11n_aggregate_pkt(priv, ptr, ptr_index, flags);
-                       /* ra_list_spinlock has been freed in
-                        * mwifiex_11n_aggregate_pkt()
-                        */
-               else
-                       mwifiex_send_single_packet(priv, ptr, ptr_index, flags);
-                       /* ra_list_spinlock has been freed in
-                        * mwifiex_send_single_packet()
-                        */
-       } else {
-               if (mwifiex_is_ampdu_allowed(priv, ptr, tid) &&
-                   ptr->ba_pkt_count > ptr->ba_packet_thr) {
-                       if (mwifiex_space_avail_for_new_ba_stream(adapter)) {
-                               mwifiex_create_ba_tbl(priv, ptr->ra, tid,
-                                                     BA_SETUP_INPROGRESS);
-                               mwifiex_send_addba(priv, tid, ptr->ra);
-                       } else if (mwifiex_find_stream_to_delete
-                                  (priv, tid, &tid_del, ra)) {
-                               mwifiex_create_ba_tbl(priv, ptr->ra, tid,
-                                                     BA_SETUP_INPROGRESS);
-                               mwifiex_send_delba(priv, tid_del, ra, 1);
-                       }
-               }
-               if (mwifiex_is_amsdu_allowed(priv, tid) &&
-                   mwifiex_is_11n_aggragation_possible(priv, ptr,
-                                                       adapter->tx_buf_size))
-                       mwifiex_11n_aggregate_pkt(priv, ptr, ptr_index, flags);
-                       /* ra_list_spinlock has been freed in
-                          mwifiex_11n_aggregate_pkt() */
-               else
-                       mwifiex_send_single_packet(priv, ptr, ptr_index, flags);
-                       /* ra_list_spinlock has been freed in
-                          mwifiex_send_single_packet() */
-       }
-       return 0;
-}
-
-void mwifiex_process_bypass_tx(struct mwifiex_adapter *adapter)
-{
-       struct mwifiex_tx_param tx_param;
-       struct sk_buff *skb;
-       struct mwifiex_txinfo *tx_info;
-       struct mwifiex_private *priv;
-       int i;
-
-       if (adapter->data_sent || adapter->tx_lock_flag)
-               return;
-
-       for (i = 0; i < adapter->priv_num; ++i) {
-               priv = adapter->priv[i];
-
-               if (!priv)
-                       continue;
-
-               if (adapter->if_ops.is_port_ready &&
-                   !adapter->if_ops.is_port_ready(priv))
-                       continue;
-
-               if (skb_queue_empty(&priv->bypass_txq))
-                       continue;
-
-               skb = skb_dequeue(&priv->bypass_txq);
-               tx_info = MWIFIEX_SKB_TXCB(skb);
-
-               /* no aggregation for bypass packets */
-               tx_param.next_pkt_len = 0;
-
-               if (mwifiex_process_tx(priv, skb, &tx_param) == -EBUSY) {
-                       skb_queue_head(&priv->bypass_txq, skb);
-                       tx_info->flags |= MWIFIEX_BUF_FLAG_REQUEUED_PKT;
-               } else {
-                       atomic_dec(&adapter->bypass_tx_pending);
-               }
-       }
-}
-
-/*
- * This function transmits the highest priority packet awaiting in the
- * WMM Queues.
- */
-void
-mwifiex_wmm_process_tx(struct mwifiex_adapter *adapter)
-{
-       do {
-               if (mwifiex_dequeue_tx_packet(adapter))
-                       break;
-               if (adapter->iface_type != MWIFIEX_SDIO) {
-                       if (adapter->data_sent ||
-                           adapter->tx_lock_flag)
-                               break;
-               } else {
-                       if (atomic_read(&adapter->tx_queued) >=
-                           MWIFIEX_MAX_PKTS_TXQ)
-                               break;
-               }
-       } while (!mwifiex_wmm_lists_empty(adapter));
-}
diff --git a/drivers/net/wireless/mwifiex/wmm.h b/drivers/net/wireless/mwifiex/wmm.h
deleted file mode 100644 (file)
index 38f0976..0000000
+++ /dev/null
@@ -1,140 +0,0 @@
-/*
- * Marvell Wireless LAN device driver: WMM
- *
- * Copyright (C) 2011-2014, Marvell International Ltd.
- *
- * This software file (the "File") is distributed by Marvell International
- * Ltd. under the terms of the GNU General Public License Version 2, June 1991
- * (the "License").  You may use, redistribute and/or modify this File in
- * accordance with the terms and conditions of the License, a copy of which
- * is available by writing to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the
- * worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
- *
- * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
- * ARE EXPRESSLY DISCLAIMED.  The License provides additional details about
- * this warranty disclaimer.
- */
-
-#ifndef _MWIFIEX_WMM_H_
-#define _MWIFIEX_WMM_H_
-
-enum ieee_types_wmm_aciaifsn_bitmasks {
-       MWIFIEX_AIFSN = (BIT(0) | BIT(1) | BIT(2) | BIT(3)),
-       MWIFIEX_ACM = BIT(4),
-       MWIFIEX_ACI = (BIT(5) | BIT(6)),
-};
-
-enum ieee_types_wmm_ecw_bitmasks {
-       MWIFIEX_ECW_MIN = (BIT(0) | BIT(1) | BIT(2) | BIT(3)),
-       MWIFIEX_ECW_MAX = (BIT(4) | BIT(5) | BIT(6) | BIT(7)),
-};
-
-static const u16 mwifiex_1d_to_wmm_queue[8] = { 1, 0, 0, 1, 2, 2, 3, 3 };
-
-/*
- * This table inverses the tos_to_tid operation to get a priority
- * which is in sequential order, and can be compared.
- * Use this to compare the priority of two different TIDs.
- */
-static const u8 tos_to_tid_inv[] = {
-       0x02,  /* from tos_to_tid[2] = 0 */
-       0x00,  /* from tos_to_tid[0] = 1 */
-       0x01,  /* from tos_to_tid[1] = 2 */
-       0x03,
-       0x04,
-       0x05,
-       0x06,
-       0x07};
-
-/*
- * This function retrieves the TID of the given RA list.
- */
-static inline int
-mwifiex_get_tid(struct mwifiex_ra_list_tbl *ptr)
-{
-       struct sk_buff *skb;
-
-       if (skb_queue_empty(&ptr->skb_head))
-               return 0;
-
-       skb = skb_peek(&ptr->skb_head);
-
-       return skb->priority;
-}
-
-/*
- * This function gets the length of a list.
- */
-static inline int
-mwifiex_wmm_list_len(struct list_head *head)
-{
-       struct list_head *pos;
-       int count = 0;
-
-       list_for_each(pos, head)
-               ++count;
-
-       return count;
-}
-
-/*
- * This function checks if a RA list is empty or not.
- */
-static inline u8
-mwifiex_wmm_is_ra_list_empty(struct list_head *ra_list_hhead)
-{
-       struct mwifiex_ra_list_tbl *ra_list;
-       int is_list_empty;
-
-       list_for_each_entry(ra_list, ra_list_hhead, list) {
-               is_list_empty = skb_queue_empty(&ra_list->skb_head);
-               if (!is_list_empty)
-                       return false;
-       }
-
-       return true;
-}
-
-void mwifiex_wmm_add_buf_txqueue(struct mwifiex_private *priv,
-                                struct sk_buff *skb);
-void mwifiex_wmm_add_buf_bypass_txqueue(struct mwifiex_private *priv,
-                                       struct sk_buff *skb);
-void mwifiex_ralist_add(struct mwifiex_private *priv, const u8 *ra);
-void mwifiex_rotate_priolists(struct mwifiex_private *priv,
-                             struct mwifiex_ra_list_tbl *ra, int tid);
-
-int mwifiex_wmm_lists_empty(struct mwifiex_adapter *adapter);
-int mwifiex_bypass_txlist_empty(struct mwifiex_adapter *adapter);
-void mwifiex_wmm_process_tx(struct mwifiex_adapter *adapter);
-void mwifiex_process_bypass_tx(struct mwifiex_adapter *adapter);
-int mwifiex_is_ralist_valid(struct mwifiex_private *priv,
-                           struct mwifiex_ra_list_tbl *ra_list, int tid);
-
-u8 mwifiex_wmm_compute_drv_pkt_delay(struct mwifiex_private *priv,
-                                    const struct sk_buff *skb);
-void mwifiex_wmm_init(struct mwifiex_adapter *adapter);
-
-u32 mwifiex_wmm_process_association_req(struct mwifiex_private *priv,
-                                       u8 **assoc_buf,
-                                       struct ieee_types_wmm_parameter *wmmie,
-                                       struct ieee80211_ht_cap *htcap);
-
-void mwifiex_wmm_setup_queue_priorities(struct mwifiex_private *priv,
-                                       struct ieee_types_wmm_parameter *wmm_ie);
-void mwifiex_wmm_setup_ac_downgrade(struct mwifiex_private *priv);
-int mwifiex_ret_wmm_get_status(struct mwifiex_private *priv,
-                              const struct host_cmd_ds_command *resp);
-struct mwifiex_ra_list_tbl *
-mwifiex_wmm_get_queue_raptr(struct mwifiex_private *priv, u8 tid,
-                           const u8 *ra_addr);
-u8 mwifiex_wmm_downgrade_tid(struct mwifiex_private *priv, u32 tid);
-void mwifiex_update_ralist_tx_pause(struct mwifiex_private *priv, u8 *mac,
-                                   u8 tx_pause);
-void mwifiex_update_ralist_tx_pause_in_tdls_cs(struct mwifiex_private *priv,
-                                              u8 *mac, u8 tx_pause);
-
-struct mwifiex_ra_list_tbl *mwifiex_wmm_get_ralist_node(struct mwifiex_private
-                                       *priv, u8 tid, const u8 *ra_addr);
-#endif /* !_MWIFIEX_WMM_H_ */