summaryrefslogtreecommitdiff
path: root/drivers/net/wireless/nxp/mxm_wifiex/wlan_src/mlan
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/wireless/nxp/mxm_wifiex/wlan_src/mlan')
-rw-r--r--drivers/net/wireless/nxp/mxm_wifiex/wlan_src/mlan/mlan.h37
-rw-r--r--drivers/net/wireless/nxp/mxm_wifiex/wlan_src/mlan/mlan_11ac.c1309
-rw-r--r--drivers/net/wireless/nxp/mxm_wifiex/wlan_src/mlan/mlan_11ac.h52
-rw-r--r--drivers/net/wireless/nxp/mxm_wifiex/wlan_src/mlan/mlan_11ax.c904
-rw-r--r--drivers/net/wireless/nxp/mxm_wifiex/wlan_src/mlan/mlan_11ax.h58
-rw-r--r--drivers/net/wireless/nxp/mxm_wifiex/wlan_src/mlan/mlan_11d.c1590
-rw-r--r--drivers/net/wireless/nxp/mxm_wifiex/wlan_src/mlan/mlan_11h.c4274
-rw-r--r--drivers/net/wireless/nxp/mxm_wifiex/wlan_src/mlan/mlan_11h.h201
-rw-r--r--drivers/net/wireless/nxp/mxm_wifiex/wlan_src/mlan/mlan_11n.c3092
-rw-r--r--drivers/net/wireless/nxp/mxm_wifiex/wlan_src/mlan/mlan_11n.h408
-rw-r--r--drivers/net/wireless/nxp/mxm_wifiex/wlan_src/mlan/mlan_11n_aggr.c603
-rw-r--r--drivers/net/wireless/nxp/mxm_wifiex/wlan_src/mlan/mlan_11n_aggr.h38
-rw-r--r--drivers/net/wireless/nxp/mxm_wifiex/wlan_src/mlan/mlan_11n_rxreorder.c1497
-rw-r--r--drivers/net/wireless/nxp/mxm_wifiex/wlan_src/mlan/mlan_11n_rxreorder.h104
-rw-r--r--drivers/net/wireless/nxp/mxm_wifiex/wlan_src/mlan/mlan_cfp.c3608
-rw-r--r--drivers/net/wireless/nxp/mxm_wifiex/wlan_src/mlan/mlan_cmdevt.c8377
-rw-r--r--drivers/net/wireless/nxp/mxm_wifiex/wlan_src/mlan/mlan_decl.h1988
-rw-r--r--drivers/net/wireless/nxp/mxm_wifiex/wlan_src/mlan/mlan_fw.h7410
-rw-r--r--drivers/net/wireless/nxp/mxm_wifiex/wlan_src/mlan/mlan_ieee.h1888
-rw-r--r--drivers/net/wireless/nxp/mxm_wifiex/wlan_src/mlan/mlan_init.c1959
-rw-r--r--drivers/net/wireless/nxp/mxm_wifiex/wlan_src/mlan/mlan_init.h125
-rw-r--r--drivers/net/wireless/nxp/mxm_wifiex/wlan_src/mlan/mlan_ioctl.h5159
-rw-r--r--drivers/net/wireless/nxp/mxm_wifiex/wlan_src/mlan/mlan_join.c2621
-rw-r--r--drivers/net/wireless/nxp/mxm_wifiex/wlan_src/mlan/mlan_join.h42
-rw-r--r--drivers/net/wireless/nxp/mxm_wifiex/wlan_src/mlan/mlan_main.h4137
-rw-r--r--drivers/net/wireless/nxp/mxm_wifiex/wlan_src/mlan/mlan_meas.c465
-rw-r--r--drivers/net/wireless/nxp/mxm_wifiex/wlan_src/mlan/mlan_meas.h55
-rw-r--r--drivers/net/wireless/nxp/mxm_wifiex/wlan_src/mlan/mlan_misc.c5866
-rw-r--r--drivers/net/wireless/nxp/mxm_wifiex/wlan_src/mlan/mlan_module.c65
-rw-r--r--drivers/net/wireless/nxp/mxm_wifiex/wlan_src/mlan/mlan_pcie.c4205
-rw-r--r--drivers/net/wireless/nxp/mxm_wifiex/wlan_src/mlan/mlan_pcie.h650
-rw-r--r--drivers/net/wireless/nxp/mxm_wifiex/wlan_src/mlan/mlan_scan.c6468
-rw-r--r--drivers/net/wireless/nxp/mxm_wifiex/wlan_src/mlan/mlan_sdio.c3013
-rw-r--r--drivers/net/wireless/nxp/mxm_wifiex/wlan_src/mlan/mlan_sdio.h550
-rw-r--r--drivers/net/wireless/nxp/mxm_wifiex/wlan_src/mlan/mlan_shim.c1700
-rw-r--r--drivers/net/wireless/nxp/mxm_wifiex/wlan_src/mlan/mlan_sta_cmd.c2950
-rw-r--r--drivers/net/wireless/nxp/mxm_wifiex/wlan_src/mlan/mlan_sta_cmdresp.c2749
-rw-r--r--drivers/net/wireless/nxp/mxm_wifiex/wlan_src/mlan/mlan_sta_event.c1026
-rw-r--r--drivers/net/wireless/nxp/mxm_wifiex/wlan_src/mlan/mlan_sta_ioctl.c5615
-rw-r--r--drivers/net/wireless/nxp/mxm_wifiex/wlan_src/mlan/mlan_sta_rx.c488
-rw-r--r--drivers/net/wireless/nxp/mxm_wifiex/wlan_src/mlan/mlan_sta_tx.c326
-rw-r--r--drivers/net/wireless/nxp/mxm_wifiex/wlan_src/mlan/mlan_txrx.c424
-rw-r--r--drivers/net/wireless/nxp/mxm_wifiex/wlan_src/mlan/mlan_uap.h57
-rw-r--r--drivers/net/wireless/nxp/mxm_wifiex/wlan_src/mlan/mlan_uap_cmdevent.c5587
-rw-r--r--drivers/net/wireless/nxp/mxm_wifiex/wlan_src/mlan/mlan_uap_ioctl.c2240
-rw-r--r--drivers/net/wireless/nxp/mxm_wifiex/wlan_src/mlan/mlan_uap_txrx.c820
-rw-r--r--drivers/net/wireless/nxp/mxm_wifiex/wlan_src/mlan/mlan_usb.c1264
-rw-r--r--drivers/net/wireless/nxp/mxm_wifiex/wlan_src/mlan/mlan_util.h492
-rw-r--r--drivers/net/wireless/nxp/mxm_wifiex/wlan_src/mlan/mlan_wmm.c3282
-rw-r--r--drivers/net/wireless/nxp/mxm_wifiex/wlan_src/mlan/mlan_wmm.h242
50 files changed, 102080 insertions, 0 deletions
diff --git a/drivers/net/wireless/nxp/mxm_wifiex/wlan_src/mlan/mlan.h b/drivers/net/wireless/nxp/mxm_wifiex/wlan_src/mlan/mlan.h
new file mode 100644
index 000000000000..d2cd022e02d7
--- /dev/null
+++ b/drivers/net/wireless/nxp/mxm_wifiex/wlan_src/mlan/mlan.h
@@ -0,0 +1,37 @@
+/** @file mlan.h
+ *
+ * @brief This file declares all APIs that will be called from MOAL module.
+ * It also defines the data structures used for APIs between MLAN and MOAL.
+ *
+ *
+ * Copyright 2014-2020 NXP
+ *
+ * This software file (the File) is distributed by NXP
+ * under the terms of the GNU General Public License Version 2, June 1991
+ * (the License). You may use, redistribute and/or modify the 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.
+ *
+ */
+
+/******************************************************
+Change log:
+ 10/13/2008: initial version
+ 11/07/2008: split mlan.h into mlan_decl.h & mlan_ioctl.h
+******************************************************/
+
+#ifndef _MLAN_H_
+#define _MLAN_H_
+
+#include "mlan_decl.h"
+#include "mlan_ioctl.h"
+#include "mlan_ieee.h"
+
+#endif /* !_MLAN_H_ */
diff --git a/drivers/net/wireless/nxp/mxm_wifiex/wlan_src/mlan/mlan_11ac.c b/drivers/net/wireless/nxp/mxm_wifiex/wlan_src/mlan/mlan_11ac.c
new file mode 100644
index 000000000000..04aee8d4e019
--- /dev/null
+++ b/drivers/net/wireless/nxp/mxm_wifiex/wlan_src/mlan/mlan_11ac.c
@@ -0,0 +1,1309 @@
+/** @file mlan_11ac.c
+ *
+ * @brief This file contains the functions for station ioctl.
+ *
+ *
+ * Copyright 2014-2020 NXP
+ *
+ * This software file (the File) is distributed by NXP
+ * under the terms of the GNU General Public License Version 2, June 1991
+ * (the License). You may use, redistribute and/or modify the 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 "mlan.h"
+#include "mlan_join.h"
+#include "mlan_util.h"
+#include "mlan_fw.h"
+#include "mlan_main.h"
+#include "mlan_wmm.h"
+#include "mlan_11n.h"
+
+#define NO_NSS_SUPPORT 0x3
+
+/********************************************************
+ Local Variables
+********************************************************/
+
+/********************************************************
+ Global Variables
+********************************************************/
+
+/********************************************************
+ Local Functions
+********************************************************/
+t_u16 wlan_convert_mcsmap_to_maxrate(mlan_private *priv, t_u16 bands,
+ t_u16 mcs_map);
+/**
+ * @brief determine the center frquency center index for bandwidth
+ * of 80 MHz and 160 MHz
+ *
+ * @param pmpriv A pointer to mlan_private structure
+ * @param band band
+ * @param pri_chan primary channel
+ * @param chan_bw channel bandwidth
+ *
+ * @return channel center frequency center, if found; O, otherwise
+ */
+
+t_u8 wlan_get_center_freq_idx(mlan_private *pmpriv, t_u16 band, t_u32 pri_chan,
+ t_u8 chan_bw)
+{
+ t_u8 center_freq_idx = 0;
+
+ if (band & BAND_AAC) {
+ switch (pri_chan) {
+ case 36:
+ case 40:
+ case 44:
+ case 48:
+ if (chan_bw == CHANNEL_BW_80MHZ) {
+ center_freq_idx = 42;
+ break;
+ }
+ /* fall through */
+ case 52:
+ case 56:
+ case 60:
+ case 64:
+ if (chan_bw == CHANNEL_BW_80MHZ) {
+ center_freq_idx = 58;
+ break;
+ } else if (chan_bw == CHANNEL_BW_160MHZ) {
+ center_freq_idx = 50;
+ break;
+ }
+ /* fall through */
+ case 100:
+ case 104:
+ case 108:
+ case 112:
+ if (chan_bw == CHANNEL_BW_80MHZ) {
+ center_freq_idx = 106;
+ break;
+ }
+ /* fall through */
+ case 116:
+ case 120:
+ case 124:
+ case 128:
+ if (chan_bw == CHANNEL_BW_80MHZ) {
+ center_freq_idx = 122;
+ break;
+ } else if (chan_bw == CHANNEL_BW_160MHZ) {
+ center_freq_idx = 114;
+ break;
+ }
+ /* fall through */
+ case 132:
+ case 136:
+ case 140:
+ case 144:
+ if (chan_bw == CHANNEL_BW_80MHZ) {
+ center_freq_idx = 138;
+ break;
+ }
+ /* fall through */
+ case 149:
+ case 153:
+ case 157:
+ case 161:
+ if (chan_bw == CHANNEL_BW_80MHZ) {
+ center_freq_idx = 155;
+ break;
+ }
+ /* fall through */
+ case 165:
+ case 169:
+ case 173:
+ case 177:
+ if (chan_bw == CHANNEL_BW_80MHZ) {
+ center_freq_idx = 171;
+ break;
+ }
+ /* fall through */
+ case 184:
+ case 188:
+ case 192:
+ case 196:
+ if (chan_bw == CHANNEL_BW_80MHZ) {
+ center_freq_idx = 190;
+ break;
+ }
+ /* fall through */
+ default: /* error. go to the default */
+ center_freq_idx = 42;
+ }
+ }
+ return center_freq_idx;
+}
+
+/**
+ * @brief This function gets the bitmap of nss which supports VHT mcs
+ *
+ * @param mcs_map_set VHT mcs map
+ *
+ * @return The bitmap of supported nss
+ */
+static t_u8 wlan_get_nss_vht_mcs(t_u16 mcs_map_set)
+{
+ t_u8 nss, nss_map = 0;
+ for (nss = 1; nss <= 8; nss++) {
+ if (GET_VHTNSSMCS(mcs_map_set, nss) != NO_NSS_SUPPORT)
+ nss_map |= 1 << (nss - 1);
+ }
+ PRINTM(MCMND, "Supported nss bit map:0x%02x\n", nss_map);
+ return nss_map;
+}
+
+/**
+ * @brief This function gets the bitmap of nss which supports VHT mcs
+ *
+ * @param mcs_map_set VHT mcs map
+ *
+ * @return The bitmap of supported nss
+ */
+static t_u8 wlan_get_nss_num_vht_mcs(t_u16 mcs_map_set)
+{
+ t_u8 nss, nss_num = 0;
+ for (nss = 1; nss <= 8; nss++) {
+ if (GET_VHTNSSMCS(mcs_map_set, nss) != NO_NSS_SUPPORT)
+ nss_num++;
+ }
+ PRINTM(MCMND, "Supported nss:%d\n", nss_num);
+ return nss_num;
+}
+
+/**
+ * @brief This function fills the cap info
+ *
+ * @param priv A pointer to mlan_private structure
+ * @param pht_cap A pointer to MrvlIETypes_HTCap_t structure
+ * @param bands Band configuration
+ *
+ * @return N/A
+ */
+static void wlan_fill_cap_info(mlan_private *priv, VHT_capa_t *vht_cap,
+ t_u8 bands)
+{
+ t_u32 usr_dot_11ac_dev_cap;
+
+ ENTER();
+
+ if (bands & BAND_A)
+ usr_dot_11ac_dev_cap = priv->usr_dot_11ac_dev_cap_a;
+ else
+ usr_dot_11ac_dev_cap = priv->usr_dot_11ac_dev_cap_bg;
+
+ vht_cap->vht_cap_info = usr_dot_11ac_dev_cap;
+
+ LEAVE();
+}
+
+/**
+ * @brief Set/get 11ac configuration
+ *
+ * @param pmadapter A pointer to mlan_adapter structure
+ * @param pioctl_req A pointer to ioctl request buffer
+ *
+ * @return MLAN_STATUS_PENDING --success, otherwise fail
+ */
+static mlan_status wlan_11ac_ioctl_vhtcfg(pmlan_adapter pmadapter,
+ pmlan_ioctl_req pioctl_req)
+{
+ mlan_status ret = MLAN_STATUS_SUCCESS;
+ mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index];
+ mlan_ds_11ac_cfg *cfg = MNULL;
+ t_u16 cmd_action = 0;
+ t_u32 usr_vht_cap_info = 0;
+ t_u32 cfg_value = 0;
+ t_u32 hw_value = 0;
+ t_u8 nss = 0;
+#if defined(PCIE9098) || defined(SD9098) || defined(USB9098) || \
+ defined(PCIE9097) || defined(USB9097) || defined(SD9097)
+ t_u16 rx_nss = 0;
+ t_u16 tx_nss = 0;
+#endif
+
+ ENTER();
+
+#define VHT_CAP_INFO_BIT_FIELDS \
+ (MBIT(4) | MBIT(5) | MBIT(6) | MBIT(7) | MBIT(11) | MBIT(12) | \
+ MBIT(19) | MBIT(20) | MBIT(21) | MBIT(22) | MBIT(28) | MBIT(29))
+
+ cfg = (mlan_ds_11ac_cfg *)pioctl_req->pbuf;
+
+ if (pioctl_req->action == MLAN_ACT_SET) {
+ /** SET operation */
+ /** validate the user input and correct it if necessary */
+ if (pmpriv->bss_role == MLAN_BSS_ROLE_STA) {
+ if (cfg->param.vht_cfg.txrx == 3) {
+ PRINTM(MERROR,
+ "Configuration of VHT capabilities for TX/RX 3 is not supported in STA mode!\n");
+ return MLAN_STATUS_FAILURE;
+ }
+ }
+ if (pmpriv->bss_role == MLAN_BSS_ROLE_UAP) {
+ if (cfg->param.vht_cfg.txrx != 3) {
+ PRINTM(MERROR,
+ "Configuration of VHT capabilities for TX/RX %d is not supported in UAP mode!\n",
+ cfg->param.vht_cfg.txrx);
+ return MLAN_STATUS_FAILURE;
+ }
+ }
+ /** set bit fileds */
+ usr_vht_cap_info = VHT_CAP_INFO_BIT_FIELDS &
+ cfg->param.vht_cfg.vht_cap_info &
+ pmadapter->hw_dot_11ac_dev_cap;
+ /** set MAX MPDU LEN field (bit 0 - bit 1) */
+ cfg_value =
+ GET_VHTCAP_MAXMPDULEN(cfg->param.vht_cfg.vht_cap_info);
+ hw_value =
+ GET_VHTCAP_MAXMPDULEN(pmadapter->hw_dot_11ac_dev_cap);
+ SET_VHTCAP_MAXMPDULEN(usr_vht_cap_info,
+ MIN(cfg_value, hw_value));
+ /** set CHAN Width Set field (bit 2 - bit 3) */
+ cfg_value = GET_VHTCAP_CHWDSET(cfg->param.vht_cfg.vht_cap_info);
+ hw_value = GET_VHTCAP_CHWDSET(pmadapter->hw_dot_11ac_dev_cap);
+ SET_VHTCAP_CHWDSET(usr_vht_cap_info, MIN(cfg_value, hw_value));
+ /** set Rx STBC field (bit 8 - bit 10) */
+ cfg_value = GET_VHTCAP_RXSTBC(cfg->param.vht_cfg.vht_cap_info);
+ hw_value = GET_VHTCAP_RXSTBC(pmadapter->hw_dot_11ac_dev_cap);
+ SET_VHTCAP_RXSTBC(usr_vht_cap_info, MIN(cfg_value, hw_value));
+ /** set Steering Number of BFer Ant (bit 13 - bit 15) */
+ cfg_value =
+ GET_VHTCAP_SNBFERANT(cfg->param.vht_cfg.vht_cap_info);
+ hw_value = GET_VHTCAP_SNBFERANT(pmadapter->hw_dot_11ac_dev_cap);
+ SET_VHTCAP_SNBFERANT(usr_vht_cap_info,
+ MIN(cfg_value, hw_value));
+ /** set Number of Sounding Dimension (bit 16 - bit 18) */
+ cfg_value =
+ GET_VHTCAP_NUMSNDDM(cfg->param.vht_cfg.vht_cap_info);
+ hw_value = GET_VHTCAP_NUMSNDDM(pmadapter->hw_dot_11ac_dev_cap);
+ SET_VHTCAP_NUMSNDDM(usr_vht_cap_info, MIN(cfg_value, hw_value));
+ /** set Number of Max AMPDU Length Exponent (bit 23 - bit 25) */
+ cfg_value = GET_VHTCAP_MAXAMPDULENEXP(
+ cfg->param.vht_cfg.vht_cap_info);
+ hw_value = GET_VHTCAP_MAXAMPDULENEXP(
+ pmadapter->hw_dot_11ac_dev_cap);
+ SET_VHTCAP_MAXAMPDULENEXP(usr_vht_cap_info,
+ MIN(cfg_value, hw_value));
+ /** set VHT Link Adaptation Capable (bit 26 - bit 27) */
+ cfg_value =
+ GET_VHTCAP_LINKADPCAP(cfg->param.vht_cfg.vht_cap_info);
+ hw_value =
+ GET_VHTCAP_LINKADPCAP(pmadapter->hw_dot_11ac_dev_cap);
+ SET_VHTCAP_LINKADPCAP(usr_vht_cap_info,
+ MIN(cfg_value, hw_value));
+ /** update the user setting if it is beyond the hw capabiliteis
+ */
+ cfg->param.vht_cfg.vht_cap_info = usr_vht_cap_info;
+ PRINTM(MINFO, "Set: vht cap info 0x%x\n", usr_vht_cap_info);
+
+ /** update the RX MCS map */
+ if (cfg->param.vht_cfg.txrx & MLAN_RADIO_RX) {
+#if defined(PCIE9098) || defined(SD9098) || defined(USB9098) || \
+ defined(PCIE9097) || defined(SD9097) || defined(USB9097)
+ if (IS_CARD9098(pmadapter->card_type) ||
+ IS_CARD9097(pmadapter->card_type)) {
+ if (cfg->param.vht_cfg.band == BAND_SELECT_A) {
+ rx_nss = GET_RXMCSSUPP(
+ pmadapter->user_htstream >> 8);
+ tx_nss =
+ GET_TXMCSSUPP(
+ pmadapter->user_htstream >>
+ 8) &
+ 0x0f;
+ } else {
+ rx_nss = GET_RXMCSSUPP(
+ pmadapter->user_htstream);
+ tx_nss =
+ GET_TXMCSSUPP(
+ pmadapter->user_htstream) &
+ 0x0f;
+ }
+ }
+#endif
+ /* use the previous user value */
+ if (cfg->param.vht_cfg.vht_rx_mcs == 0xffffffff)
+ cfg->param.vht_cfg.vht_rx_mcs = GET_VHTMCS(
+ pmpriv->usr_dot_11ac_mcs_support);
+ for (nss = 1; nss <= 8; nss++) {
+ cfg_value = GET_VHTNSSMCS(
+ cfg->param.vht_cfg.vht_rx_mcs, nss);
+ hw_value = GET_DEVNSSRXMCS(
+ pmadapter->hw_dot_11ac_mcs_support,
+ nss);
+#if defined(PCIE9098) || defined(SD9098) || defined(USB9098) || \
+ defined(PCIE9097) || defined(SD9097) || defined(USB9097)
+ if ((rx_nss != 0) && (nss > rx_nss))
+ cfg_value = NO_NSS_SUPPORT;
+#endif
+ if ((hw_value == NO_NSS_SUPPORT) ||
+ (cfg_value == NO_NSS_SUPPORT))
+ SET_VHTNSSMCS(
+ cfg->param.vht_cfg.vht_rx_mcs,
+ nss, NO_NSS_SUPPORT);
+ else
+ SET_VHTNSSMCS(
+ cfg->param.vht_cfg.vht_rx_mcs,
+ nss, MIN(cfg_value, hw_value));
+ }
+ PRINTM(MINFO, "Set: vht rx mcs set 0x%08x\n",
+ cfg->param.vht_cfg.vht_rx_mcs);
+ /* use the previous user value */
+ if (cfg->param.vht_cfg.vht_tx_mcs == 0xffffffff)
+ cfg->param.vht_cfg.vht_tx_mcs = GET_VHTMCS(
+ pmpriv->usr_dot_11ac_mcs_support >> 16);
+ for (nss = 1; nss <= 8; nss++) {
+ cfg_value = GET_VHTNSSMCS(
+ cfg->param.vht_cfg.vht_tx_mcs, nss);
+ hw_value = GET_DEVNSSTXMCS(
+ pmadapter->hw_dot_11ac_mcs_support,
+ nss);
+#if defined(PCIE9098) || defined(SD9098) || defined(USB9098) || \
+ defined(PCIE9097) || defined(SD9097) || defined(USB9097)
+ if ((rx_nss != 0) && (nss > rx_nss))
+ cfg_value = NO_NSS_SUPPORT;
+#endif
+ if ((hw_value == NO_NSS_SUPPORT) ||
+ (cfg_value == NO_NSS_SUPPORT))
+ SET_VHTNSSMCS(
+ cfg->param.vht_cfg.vht_tx_mcs,
+ nss, NO_NSS_SUPPORT);
+ else
+ SET_VHTNSSMCS(
+ cfg->param.vht_cfg.vht_tx_mcs,
+ nss, MIN(cfg_value, hw_value));
+ }
+ PRINTM(MINFO, "Set: vht tx mcs set 0x%08x\n",
+ cfg->param.vht_cfg.vht_tx_mcs);
+ if (!cfg->param.vht_cfg.skip_usr_11ac_mcs_cfg) {
+ RESET_DEVRXMCSMAP(
+ pmpriv->usr_dot_11ac_mcs_support);
+ pmpriv->usr_dot_11ac_mcs_support |= GET_VHTMCS(
+ cfg->param.vht_cfg.vht_rx_mcs);
+ RESET_DEVTXMCSMAP(
+ pmpriv->usr_dot_11ac_mcs_support);
+ pmpriv->usr_dot_11ac_mcs_support |=
+ (GET_VHTMCS(
+ cfg->param.vht_cfg.vht_tx_mcs)
+ << 16);
+ PRINTM(MINFO, "Set: vht mcs set 0x%08x\n",
+ pmpriv->usr_dot_11ac_mcs_support);
+ } else {
+ PRINTM(MINFO,
+ "Skipped user 11ac mcs configuration\n");
+ cfg->param.vht_cfg.skip_usr_11ac_mcs_cfg =
+ MFALSE;
+ }
+ }
+ }
+
+ if (pmpriv->bss_role == MLAN_BSS_ROLE_STA) {
+ if (cfg->param.vht_cfg.txrx & MLAN_RADIO_RX) {
+ /* maximum VHT configuration used in association */
+ if (pioctl_req->action == MLAN_ACT_SET) {
+ if (cfg->param.vht_cfg.band == BAND_SELECT_BG)
+ pmpriv->usr_dot_11ac_dev_cap_bg =
+ usr_vht_cap_info;
+ else if (cfg->param.vht_cfg.band ==
+ BAND_SELECT_A)
+ pmpriv->usr_dot_11ac_dev_cap_a =
+ usr_vht_cap_info;
+ else {
+ pmpriv->usr_dot_11ac_dev_cap_bg =
+ usr_vht_cap_info;
+ pmpriv->usr_dot_11ac_dev_cap_a =
+ usr_vht_cap_info;
+ }
+ pmpriv->usr_dot_11ac_bw =
+ cfg->param.vht_cfg.bwcfg;
+
+ } else {
+ /** GET operation */
+ if (cfg->param.vht_cfg.band == BAND_SELECT_BG) {
+ cfg->param.vht_cfg.vht_cap_info =
+ pmpriv->usr_dot_11ac_dev_cap_bg;
+ PRINTM(MINFO,
+ "Get: vht cap info for 2.4GHz 0x%x\n",
+ pmpriv->usr_dot_11ac_dev_cap_bg);
+ } else if (cfg->param.vht_cfg.band ==
+ BAND_SELECT_A) {
+ cfg->param.vht_cfg.vht_cap_info =
+ pmpriv->usr_dot_11ac_dev_cap_a;
+ PRINTM(MINFO,
+ "Get: vht cap info for 5GHz 0x%x\n",
+ pmpriv->usr_dot_11ac_dev_cap_a);
+ } else {
+ PRINTM(MINFO,
+ "Get: invalid band selection for vht cap info\n");
+ ret = MLAN_STATUS_FAILURE;
+ }
+ cfg->param.vht_cfg.bwcfg =
+ pmpriv->usr_dot_11ac_bw;
+ cfg->param.vht_cfg.vht_rx_mcs = GET_DEVRXMCSMAP(
+ pmpriv->usr_dot_11ac_mcs_support);
+ cfg->param.vht_cfg.vht_tx_mcs = GET_DEVTXMCSMAP(
+ pmpriv->usr_dot_11ac_mcs_support);
+ cfg->param.vht_cfg.vht_rx_max_rate =
+ wlan_convert_mcsmap_to_maxrate(
+ pmpriv, cfg->param.vht_cfg.band,
+ cfg->param.vht_cfg.vht_rx_mcs);
+ cfg->param.vht_cfg.vht_tx_max_rate =
+ wlan_convert_mcsmap_to_maxrate(
+ pmpriv, cfg->param.vht_cfg.band,
+ cfg->param.vht_cfg.vht_tx_mcs);
+ }
+ LEAVE();
+ return ret;
+ }
+ }
+
+ if (pioctl_req->action == MLAN_ACT_SET)
+ cmd_action = HostCmd_ACT_GEN_SET;
+ else
+ cmd_action = HostCmd_ACT_GEN_GET;
+
+ /* Send request to firmware */
+ ret = wlan_prepare_cmd(pmpriv, HostCmd_CMD_11AC_CFG, cmd_action, 0,
+ (t_void *)pioctl_req,
+ (t_void *)&cfg->param.vht_cfg);
+ if (ret == MLAN_STATUS_SUCCESS)
+ ret = MLAN_STATUS_PENDING;
+
+ LEAVE();
+ return ret;
+}
+
+/**
+ * @brief Get/Set Operating Mode Notification cfg
+ *
+ * @param pmadapter A pointer to mlan_adapter structure
+ * @param pioctl_req A pointer to ioctl request buffer
+ *
+ * @return MLAN_STATUS_SUCCESS --success, otherwise fail
+ */
+static mlan_status wlan_11ac_ioctl_opermodecfg(pmlan_adapter pmadapter,
+ pmlan_ioctl_req pioctl_req)
+{
+ mlan_ds_11ac_cfg *cfg = MNULL;
+ mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index];
+ t_u8 hw_bw_160or8080 = 0;
+ t_u8 hw_rx_nss = 0;
+
+ ENTER();
+
+ cfg = (mlan_ds_11ac_cfg *)pioctl_req->pbuf;
+ if (pioctl_req->action == MLAN_ACT_GET) {
+ cfg->param.opermode_cfg.bw = pmpriv->usr_dot_11ac_opermode_bw;
+ cfg->param.opermode_cfg.nss = pmpriv->usr_dot_11ac_opermode_nss;
+ } else if (pioctl_req->action == MLAN_ACT_SET) {
+ hw_bw_160or8080 =
+ GET_VHTCAP_CHWDSET(pmadapter->hw_dot_11ac_dev_cap);
+ hw_rx_nss = wlan_get_nss_num_vht_mcs(
+ GET_DEVRXMCSMAP(pmadapter->hw_dot_11ac_mcs_support));
+ if ((((cfg->param.opermode_cfg.bw - 1) > BW_80MHZ) &&
+ !hw_bw_160or8080) ||
+ (cfg->param.opermode_cfg.nss > hw_rx_nss)) {
+ PRINTM(MERROR,
+ "bw or nss NOT supported. HW support bw_160or8080=%d rx_nss=%d.\n",
+ hw_bw_160or8080, hw_rx_nss);
+ LEAVE();
+ return MLAN_STATUS_FAILURE;
+ }
+ pmpriv->usr_dot_11ac_opermode_bw = cfg->param.opermode_cfg.bw;
+ pmpriv->usr_dot_11ac_opermode_nss = cfg->param.opermode_cfg.nss;
+ }
+
+ LEAVE();
+ return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ * @brief Get supported MCS set
+ *
+ * @param pmadapter A pointer to mlan_adapter structure
+ * @param pioctl_req A pointer to ioctl request buffer
+ *
+ * @return MLAN_STATUS_SUCCESS --success, otherwise fail
+ */
+static mlan_status wlan_11ac_ioctl_supported_mcs_set(pmlan_adapter pmadapter,
+ pmlan_ioctl_req pioctl_req)
+{
+ /*mlan_ds_11ac_cfg *cfg= MNULL;*/
+ /*int rx_mcs_supp;*/
+ /*t_u8 mcs_set[NUM_MCS_SUPP];*/
+
+ ENTER();
+#if 0
+ if (pioctl_req->action == MLAN_ACT_SET) {
+ PRINTM(MERROR, "Set operation is not supported\n");
+ pioctl_req->status_code = MLAN_ERROR_IOCTL_INVALID;
+ LEAVE();
+ return MLAN_STATUS_FAILURE;
+ }
+ rx_mcs_supp = GET_11ACRXMCSSUPP(pmadapter->usr_dot_11ac_mcs_support);
+ /* Set MCS */
+ memset(pmadapter, (t_u8 *) mcs_set, 0xff, rx_mcs_supp);
+ /* Clear all the other values */
+ memset(pmadapter, (t_u8 *) &mcs_set[rx_mcs_supp], 0,
+ NUM_MCS_FIELD - rx_mcs_supp);
+ /* Set MCS32 with 40MHz support */
+ if (ISSUPP_CHANWIDTH80(pmadapter->usr_dot_11ac_dev_cap_bg)
+ || ISSUPP_CHANWIDTH80(pmadapter->usr_dot_11ac_dev_cap_a)
+ )
+ SETHT_MCS32(mcs_set);
+
+ cfg = (mlan_ds_11ac_cfg *)pioctl_req->pbuf;
+ memcpy_ext(pmadapter, cfg->param.supported_mcs_set, mcs_set,
+ NUM_MCS_SUPP, sizeof(cfg->param.supported_mcs_set));
+
+#endif
+ LEAVE();
+ return MLAN_STATUS_SUCCESS;
+}
+
+/********************************************************
+ Global Functions
+********************************************************/
+
+/**
+ * @brief This function prints the 802.11ac device capability
+ *
+ * @param pmadapter A pointer to mlan_adapter structure
+ * @param cap Capability value
+ *
+ * @return N/A
+ */
+void wlan_show_dot11acdevcap(pmlan_adapter pmadapter, t_u32 cap)
+{
+ ENTER();
+
+ switch (GET_VHTCAP_MAXMPDULEN(cap)) {
+ case 0x0:
+ PRINTM(MINFO,
+ "GET_HW_SPEC: Maximum MSDU length = 3895 octets\n");
+ break;
+ case 0x1:
+ PRINTM(MINFO,
+ "GET_HW_SPEC: Maximum MSDU length = 7991 octets\n");
+ break;
+ case 0x2:
+ PRINTM(MINFO,
+ "GET_HW_SPEC: Maximum MSDU length = 11454 octets\n");
+ break;
+ default:
+ PRINTM(MINFO, "Unsupport value\n");
+ break;
+ }
+
+ PRINTM(MINFO, "GET_HW_SPEC: HTC-VHT %s\n",
+ (ISSUPP_11ACVHTHTCVHT(cap) ? "supported" : "not supported"));
+ PRINTM(MINFO, "GET_HW_SPEC: VHT TXOP PS %s\n",
+ (ISSUPP_11ACVHTTXOPPS(cap) ? "supported" : "not supported"));
+ PRINTM(MINFO, "GET_HW_SPEC: MU RX beamformee %s\n",
+ (ISSUPP_11ACMURXBEAMFORMEE(cap) ? "supported" :
+ "not supported"));
+ PRINTM(MINFO, "GET_HW_SPEC: MU TX beamformee %s\n",
+ (ISSUPP_11ACMUTXBEAMFORMEE(cap) ? "supported" :
+ "not supported"));
+ PRINTM(MINFO, "GET_HW_SPEC: SU RX Beamformee %s\n",
+ (ISSUPP_11ACSUBEAMFORMEE(cap) ? "supported" : "not supported"));
+ PRINTM(MINFO, "GET_HW_SPEC: SU TX Beamformer %s\n",
+ (ISSUPP_11ACSUBEAMFORMER(cap) ? "supported" : "not supported"));
+ PRINTM(MINFO, "GET_HW_SPEC: Rx STBC %s\n",
+ (ISSUPP_11ACRXSTBC(cap) ? "supported" : "not supported"));
+ PRINTM(MINFO, "GET_HW_SPEC: Tx STBC %s\n",
+ (ISSUPP_11ACTXSTBC(cap) ? "supported" : "not supported"));
+ PRINTM(MINFO, "GET_HW_SPEC: Short GI %s for 160MHz BW\n",
+ (ISSUPP_11ACSGI160(cap) ? "supported" : "not supported"));
+ PRINTM(MINFO, "GET_HW_SPEC: Short GI %s for 80MHz BW\n",
+ (ISSUPP_11ACSGI80(cap) ? "supported" : "not supported"));
+ PRINTM(MINFO, "GET_HW_SPEC: LDPC coding %s\n",
+ (ISSUPP_11ACLDPC(cap) ? "supported" : "not supported"));
+ PRINTM(MINFO, "GET_HW_SPEC: Channel BW 20/40/80/160/80+80 MHz %s\n",
+ (ISSUPP_11ACBW8080(cap) ? "supported" : "not supported"));
+ PRINTM(MINFO, "GET_HW_SPEC: Channel BW 20/40/80/160 MHz %s\n",
+ (ISSUPP_11ACBW160(cap) ? "supported" : "not supported"));
+
+ LEAVE();
+ return;
+}
+
+/**
+ * @brief This function prints the 802.11ac device MCS
+ *
+ * @param pmadapter A pointer to mlan_adapter structure
+ * @param support Support value
+ *
+ * @return N/A
+ */
+void wlan_show_dot11acmcssupport(pmlan_adapter pmadapter, t_u32 support)
+{
+ ENTER();
+
+ PRINTM(MINFO, "GET_HW_SPEC: MCSs for %2dx%2d MIMO\n",
+ GET_DEVRXMCSMAP(support), GET_DEVTXMCSMAP(support));
+
+ LEAVE();
+ return;
+}
+
+/**
+ * @brief This function converts the 2-bit MCS map to the highest long GI
+ * VHT PPDU data rate
+ *
+ * @param priv A pointer to mlan_private structure
+ * @param bands Supported bands
+ * @param mcs_map 2-bit MCS map
+ *
+ * @return the max data rate for long GI
+ */
+t_u16 wlan_convert_mcsmap_to_maxrate(mlan_private *priv, t_u16 bands,
+ t_u16 mcs_map)
+{
+ t_u8 i;
+ t_u8 nss;
+ t_u8 max_mcs;
+ t_u16 max_rate = 0;
+ t_u32 usr_vht_cap_info = 0;
+ t_u32 usr_dot_11n_dev_cap;
+
+ /* tables of the MCS map to the highest data rate (in Mbps)
+ * supported for long GI */
+ t_u16 max_rate_lgi_20MHZ[8][3] = {
+ {0x41, 0x4E, 0x0}, /* NSS = 1 */
+ {0x82, 0x9C, 0x0}, /* NSS = 2 */
+ {0xC3, 0xEA, 0x104}, /* NSS = 3 */
+ {0x104, 0x138, 0x0}, /* NSS = 4 */
+ {0x145, 0x186, 0x0}, /* NSS = 5 */
+ {0x186, 0x1D4, 0x208}, /* NSS = 6 */
+ {0x1C7, 0x222, 0x0}, /* NSS = 7 */
+ {0x208, 0x270, 0x0} /* NSS = 8 */
+ };
+
+ t_u16 max_rate_lgi_40MHZ[8][3] = {
+ {0x87, 0xA2, 0xB4}, /* NSS = 1 */
+ {0x10E, 0x144, 0x168}, /* NSS = 2 */
+ {0x195, 0x1E6, 0x21C}, /* NSS = 3 */
+ {0x21C, 0x288, 0x2D0}, /* NSS = 4 */
+ {0x2A3, 0x32A, 0x384}, /* NSS = 5 */
+ {0x32A, 0x3CC, 0x438}, /* NSS = 6 */
+ {0x3B1, 0x46E, 0x4EC}, /* NSS = 7 */
+ {0x438, 0x510, 0x5A0} /* NSS = 8 */
+ };
+
+ t_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 */
+ };
+ t_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 */
+ };
+
+ if (bands & BAND_AAC) {
+ usr_vht_cap_info = priv->usr_dot_11ac_dev_cap_a;
+ usr_dot_11n_dev_cap = priv->usr_dot_11n_dev_cap_a;
+ } else {
+ usr_vht_cap_info = priv->usr_dot_11ac_dev_cap_bg;
+ usr_dot_11n_dev_cap = priv->usr_dot_11n_dev_cap_bg;
+ }
+
+ /* find the max NSS supported */
+ nss = 0;
+ for (i = 0; i < 8; i++) {
+ max_mcs = (mcs_map >> (2 * i)) & 0x3;
+ if (max_mcs < 3)
+ nss = i;
+ }
+
+ max_mcs = (mcs_map >> (2 * nss)) & 0x3;
+ /* if max_mcs is 3, nss must be 0 (SS = 1). Thus, max mcs is MCS 9*/
+ if (max_mcs >= 3)
+ max_mcs = 2;
+
+ if (GET_VHTCAP_CHWDSET(usr_vht_cap_info)) {
+ /* support 160 MHz */
+ max_rate = max_rate_lgi_160MHZ[nss][max_mcs];
+ if (max_mcs >= 1 && max_rate == 0)
+ /* MCS9 is not supported in NSS6 */
+ max_rate = max_rate_lgi_160MHZ[nss][max_mcs - 1];
+
+ } else {
+ if (priv->usr_dot_11ac_bw == BW_FOLLOW_VHTCAP) {
+ max_rate = max_rate_lgi_80MHZ[nss][max_mcs];
+ if (max_mcs >= 1 && max_rate == 0)
+ /* MCS9 is not supported in NSS3 */
+ max_rate = max_rate_lgi_80MHZ[nss][max_mcs - 1];
+ } else {
+ if (ISSUPP_CHANWIDTH40(usr_dot_11n_dev_cap)) {
+ max_rate = max_rate_lgi_40MHZ[nss][max_mcs];
+ } else {
+ max_rate = max_rate_lgi_20MHZ[nss][max_mcs];
+ /* MCS9 is not supported in NSS1/2/4/5/7/8 */
+ if (max_mcs >= 1 && max_rate == 0)
+ max_rate =
+ max_rate_lgi_20MHZ[nss]
+ [max_mcs - 1];
+ }
+ }
+ }
+ PRINTM(MCMND, "max_rate=%dM\n", max_rate);
+ return max_rate;
+}
+
+/**
+ * @brief This function fills the VHT cap tlv out put format is LE, not CPU
+ *
+ * @param priv A pointer to mlan_private structure
+ * @param pvht_cap A pointer to MrvlIETypes_HTCap_t structure
+ * @param bands Band configuration
+ * @param flag TREU--pvht_cap has the setting for resp
+ * MFALSE -- pvht_cap is clean
+ * @param bw_80p80 TRUE -- enable 80p80
+ * @return N/A
+ */
+void wlan_fill_vht_cap_tlv(mlan_private *priv, MrvlIETypes_VHTCap_t *pvht_cap,
+ t_u16 bands, t_u8 flag, t_u8 bw_80p80)
+{
+ t_u16 mcs_map_user = 0;
+ t_u16 mcs_map_resp = 0;
+ t_u16 mcs_map_result = 0;
+ t_u16 mcs_user = 0;
+ t_u16 mcs_resp = 0;
+ t_u16 nss;
+#if defined(PCIE9098) || defined(SD9098) || defined(USB9098) || \
+ defined(PCIE9097) || defined(SD9097) || defined(USB9097)
+ t_u16 rx_nss = 0, tx_nss = 0;
+#endif
+ ENTER();
+
+ /* Fill VHT cap info */
+ wlan_fill_cap_info(priv, &pvht_cap->vht_cap, bands);
+ /* clear 80p80 in vht_cap_info */
+ if (!bw_80p80)
+ pvht_cap->vht_cap.vht_cap_info &= ~(MBIT(2) | MBIT(3));
+ pvht_cap->vht_cap.vht_cap_info =
+ wlan_cpu_to_le32(pvht_cap->vht_cap.vht_cap_info);
+
+ /* Fill VHT MCS Set */
+ /* rx MCS Set, find the minimum of the user rx mcs and ap rx mcs*/
+ mcs_map_resp = mcs_map_user =
+ GET_DEVRXMCSMAP(priv->usr_dot_11ac_mcs_support);
+ if (flag)
+ mcs_map_resp =
+ wlan_le16_to_cpu(pvht_cap->vht_cap.mcs_sets.rx_mcs_map);
+#if defined(PCIE9098) || defined(SD9098) || defined(USB9098) || \
+ defined(PCIE9097) || defined(SD9097) || defined(USB9097)
+ if (IS_CARD9098(priv->adapter->card_type) ||
+ IS_CARD9097(priv->adapter->card_type)) {
+ if (bands & BAND_A) {
+ rx_nss = GET_RXMCSSUPP(priv->adapter->user_htstream >>
+ 8);
+ tx_nss = GET_TXMCSSUPP(priv->adapter->user_htstream >>
+ 8) &
+ 0x0f;
+ } else {
+ rx_nss = GET_RXMCSSUPP(priv->adapter->user_htstream);
+ tx_nss = GET_TXMCSSUPP(priv->adapter->user_htstream) &
+ 0x0f;
+ }
+ /** force 1x1 when enable 80P80 */
+ if (bw_80p80)
+ rx_nss = tx_nss = 1;
+ }
+#endif
+ 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 defined(PCIE9098) || defined(SD9098) || defined(USB9098) || \
+ defined(PCIE9097) || defined(SD9097) || defined(USB9097)
+ if ((rx_nss != 0) && (nss > rx_nss))
+ mcs_user = NO_NSS_SUPPORT;
+#endif
+ if ((mcs_user == NO_NSS_SUPPORT) ||
+ (mcs_resp == NO_NSS_SUPPORT))
+ SET_VHTNSSMCS(mcs_map_result, nss, NO_NSS_SUPPORT);
+ else
+ SET_VHTNSSMCS(mcs_map_result, nss,
+ MIN(mcs_user, mcs_resp));
+ }
+ /* rx MCS map */
+ pvht_cap->vht_cap.mcs_sets.rx_mcs_map =
+ wlan_cpu_to_le16(mcs_map_result);
+
+ /* rx highest rate */
+ pvht_cap->vht_cap.mcs_sets.rx_max_rate =
+ wlan_convert_mcsmap_to_maxrate(priv, bands, mcs_map_result);
+ pvht_cap->vht_cap.mcs_sets.rx_max_rate =
+ wlan_cpu_to_le16(pvht_cap->vht_cap.mcs_sets.rx_max_rate);
+
+ /* tx MCS Set find the minimum of the user tx mcs and ap tx mcs */
+ mcs_map_resp = mcs_map_user =
+ GET_DEVTXMCSMAP(priv->usr_dot_11ac_mcs_support);
+ if (flag)
+ mcs_map_resp =
+ wlan_le16_to_cpu(pvht_cap->vht_cap.mcs_sets.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 defined(PCIE9098) || defined(SD9098) || defined(USB9098) || \
+ defined(PCIE9097) || defined(SD9097) || defined(USB9097)
+ if ((tx_nss != 0) && (nss > tx_nss))
+ mcs_user = NO_NSS_SUPPORT;
+#endif
+ if ((mcs_user == NO_NSS_SUPPORT) ||
+ (mcs_resp == NO_NSS_SUPPORT))
+ SET_VHTNSSMCS(mcs_map_result, nss, NO_NSS_SUPPORT);
+ else
+ SET_VHTNSSMCS(mcs_map_result, nss,
+ MIN(mcs_user, mcs_resp));
+ }
+
+ /* tx MCS map */
+ pvht_cap->vht_cap.mcs_sets.tx_mcs_map =
+ wlan_cpu_to_le16(mcs_map_result);
+ /* tx highest rate */
+ pvht_cap->vht_cap.mcs_sets.tx_max_rate =
+ wlan_convert_mcsmap_to_maxrate(priv, bands, mcs_map_result);
+ pvht_cap->vht_cap.mcs_sets.tx_max_rate =
+ wlan_cpu_to_le16(pvht_cap->vht_cap.mcs_sets.tx_max_rate);
+
+ LEAVE();
+ return;
+}
+
+/**
+ * @brief This function fills the VHT cap tlv out put format is CPU
+ *
+ * @param priv A pointer to mlan_private structure
+ * @param pvht_cap A pointer to MrvlIETypes_HTCap_t structure
+ * @param bands Band configuration
+ *
+ * @return N/A
+ */
+void wlan_fill_vht_cap_ie(mlan_private *priv, IEEEtypes_VHTCap_t *pvht_cap,
+ t_u16 bands)
+{
+ ENTER();
+
+ pvht_cap->ieee_hdr.element_id = VHT_CAPABILITY;
+ pvht_cap->ieee_hdr.len = sizeof(VHT_capa_t);
+
+ /* Fill VHT cap info */
+ wlan_fill_cap_info(priv, &pvht_cap->vht_cap, bands);
+
+ /* rx MCS map */
+ pvht_cap->vht_cap.mcs_sets.rx_mcs_map =
+ GET_DEVRXMCSMAP(priv->usr_dot_11ac_mcs_support);
+
+ /* rx highest rate */
+ pvht_cap->vht_cap.mcs_sets.rx_max_rate = wlan_convert_mcsmap_to_maxrate(
+ priv, bands, pvht_cap->vht_cap.mcs_sets.rx_mcs_map);
+
+ /* tx MCS map */
+ pvht_cap->vht_cap.mcs_sets.tx_mcs_map =
+ GET_DEVTXMCSMAP(priv->usr_dot_11ac_mcs_support);
+ /* tx highest rate */
+ pvht_cap->vht_cap.mcs_sets.tx_max_rate = wlan_convert_mcsmap_to_maxrate(
+ priv, bands, pvht_cap->vht_cap.mcs_sets.tx_mcs_map);
+
+ LEAVE();
+ return;
+}
+
+/**
+ * @brief This function would check whether support 80+80Mhz
+ *
+ * @param pmpriv A pointer to mlan_private structure
+ * @param pbss_desc A pointer to BSSDescriptor_t structure
+ *
+ * @return ret suport 80+80Mhz or not
+ */
+t_u8 wlan_is_80_80_support(mlan_private *pmpriv, BSSDescriptor_t *pbss_desc)
+{
+ t_u8 ret = MFALSE;
+#if defined(PCIE9098) || defined(SD9098) || defined(USB9098) || \
+ defined(PCIE9097) || defined(SD9097) || defined(USB9097)
+ t_u16 rx_nss = 0, tx_nss = 0;
+ IEEEtypes_VHTCap_t *pvht_cap = pbss_desc->pvht_cap;
+ MrvlIEtypes_He_cap_t *phecap = MNULL;
+ IEEEtypes_HECap_t *pBsshecap = MNULL;
+#endif
+
+ ENTER();
+
+#if defined(PCIE9098) || defined(SD9098) || defined(USB9098) || \
+ defined(PCIE9097) || defined(SD9097) || defined(USB9097)
+ if (!IS_CARD9098(pmpriv->adapter->card_type) &&
+ !IS_CARD9097(pmpriv->adapter->card_type))
+ return ret;
+ /** check band A */
+ if (!(pbss_desc->bss_band & BAND_A))
+ return ret;
+
+ /** check band A antenna setting */
+ rx_nss = GET_RXMCSSUPP(pmpriv->adapter->user_htstream >> 8);
+ tx_nss = GET_TXMCSSUPP(pmpriv->adapter->user_htstream >> 8) & 0x0f;
+ /** check if support 2*2 */
+ if (rx_nss != 2 || tx_nss != 2)
+ return ret;
+ /** check if AP support AC 80P80 */
+ if (ISSUPP_11ACBW8080(pmpriv->usr_dot_11ac_dev_cap_a) && pvht_cap &&
+ ISSUPP_11ACBW8080(pvht_cap->vht_cap.vht_cap_info))
+ ret = MTRUE;
+ /** check if AP support AX 80P80 */
+ if (pbss_desc->phe_cap) {
+ pBsshecap = (IEEEtypes_HECap_t *)pbss_desc->phe_cap;
+ phecap = (MrvlIEtypes_He_cap_t *)pmpriv->user_he_cap;
+ if (ret && (phecap->he_phy_cap[0] & MBIT(4)) &&
+ (pBsshecap->he_phy_cap[0] & MBIT(4)))
+ ret = MTRUE;
+ else
+ ret = MFALSE;
+ }
+#endif
+ LEAVE();
+ return ret;
+}
+
+/**
+ * @brief This function append the 802_11N tlv
+ *
+ * @param pmpriv A pointer to mlan_private structure
+ * @param pbss_desc A pointer to BSSDescriptor_t structure
+ * @param ppbuffer A Pointer to command buffer pointer
+ *
+ * @return bytes added to the buffer
+ */
+int wlan_cmd_append_11ac_tlv(mlan_private *pmpriv, BSSDescriptor_t *pbss_desc,
+ t_u8 **ppbuffer)
+{
+ pmlan_adapter pmadapter = pmpriv->adapter;
+ MrvlIETypes_VHTCap_t *pvht_cap;
+ MrvlIETypes_OperModeNtf_t *pmrvl_oper_mode;
+ t_u16 mcs_map_user = 0;
+ t_u16 nss;
+ int ret_len = 0;
+ t_u8 bw_80p80 = MFALSE;
+#if defined(PCIE9098) || defined(SD9098) || defined(USB9098) || \
+ defined(PCIE9097) || defined(USB9097) || defined(SD9097)
+ t_u16 rx_nss = 0;
+#endif
+
+ ENTER();
+
+ /* Null Checks */
+ if (ppbuffer == MNULL) {
+ LEAVE();
+ return 0;
+ }
+ if (*ppbuffer == MNULL) {
+ LEAVE();
+ return 0;
+ }
+
+ /* VHT Capabilities IE */
+ if (pbss_desc->pvht_cap &&
+ wlan_get_nss_vht_mcs(
+ pbss_desc->pvht_cap->vht_cap.mcs_sets.rx_mcs_map)) {
+ pvht_cap = (MrvlIETypes_VHTCap_t *)*ppbuffer;
+ memset(pmadapter, pvht_cap, 0, sizeof(MrvlIETypes_VHTCap_t));
+ pvht_cap->header.type = wlan_cpu_to_le16(VHT_CAPABILITY);
+ pvht_cap->header.len = sizeof(VHT_capa_t);
+ memcpy_ext(pmadapter,
+ (t_u8 *)pvht_cap + sizeof(MrvlIEtypesHeader_t),
+ (t_u8 *)pbss_desc->pvht_cap +
+ sizeof(IEEEtypes_Header_t),
+ pvht_cap->header.len, sizeof(VHT_capa_t));
+ bw_80p80 = wlan_is_80_80_support(pmpriv, pbss_desc);
+ wlan_fill_vht_cap_tlv(pmpriv, pvht_cap, pbss_desc->bss_band,
+ MTRUE, bw_80p80);
+
+ HEXDUMP("VHT_CAPABILITIES IE", (t_u8 *)pvht_cap,
+ sizeof(MrvlIETypes_VHTCap_t));
+ *ppbuffer += sizeof(MrvlIETypes_VHTCap_t);
+ ret_len += sizeof(MrvlIETypes_VHTCap_t);
+ pvht_cap->header.len = wlan_cpu_to_le16(pvht_cap->header.len);
+ } else {
+ LEAVE();
+ return 0;
+ }
+
+ /* Operating Mode Notification IE */
+ pmrvl_oper_mode = (MrvlIETypes_OperModeNtf_t *)*ppbuffer;
+ memset(pmadapter, pmrvl_oper_mode, 0,
+ sizeof(MrvlIETypes_OperModeNtf_t));
+ pmrvl_oper_mode->header.type = wlan_cpu_to_le16(OPER_MODE_NTF);
+ pmrvl_oper_mode->header.len = sizeof(t_u8);
+
+ if (pmpriv->usr_dot_11ac_opermode_bw ||
+ pmpriv->usr_dot_11ac_opermode_nss) {
+ pmrvl_oper_mode->oper_mode |=
+ (pmpriv->usr_dot_11ac_opermode_nss - 1) << 4;
+ pmrvl_oper_mode->oper_mode |=
+ pmpriv->usr_dot_11ac_opermode_bw - 1;
+ if (pbss_desc->bss_band & BAND_G) {
+ if (!(IS_OPER_MODE_20M(pmrvl_oper_mode->oper_mode))) {
+ if (pbss_desc->pht_cap->ht_cap.ht_cap_info &
+ MBIT(1))
+ SET_OPER_MODE_40M(
+ pmrvl_oper_mode->oper_mode);
+ else
+ SET_OPER_MODE_20M(
+ pmrvl_oper_mode->oper_mode);
+ }
+ }
+ } else {
+ /** set default bandwidth:80M*/
+ SET_OPER_MODE_80M(pmrvl_oper_mode->oper_mode);
+#if defined(PCIE9098) || defined(SD9098) || defined(USB9098) || \
+ defined(PCIE9097) || defined(SD9097) || defined(USB9097)
+ if (IS_CARD9098(pmadapter->card_type) ||
+ IS_CARD9097(pmadapter->card_type)) {
+ if (pbss_desc->bss_band & BAND_A)
+ rx_nss = GET_RXMCSSUPP(
+ pmadapter->user_htstream >> 8);
+ else
+ rx_nss =
+ GET_RXMCSSUPP(pmadapter->user_htstream);
+ }
+#endif
+ mcs_map_user =
+ GET_DEVRXMCSMAP(pmpriv->usr_dot_11ac_mcs_support);
+ nss = wlan_get_nss_num_vht_mcs(mcs_map_user);
+
+#if defined(PCIE9098) || defined(SD9098) || defined(USB9098) || \
+ defined(PCIE9097) || defined(SD9097) || defined(USB9097)
+ if (IS_CARD9098(pmadapter->card_type) ||
+ IS_CARD9097(pmadapter->card_type)) {
+ PRINTM(MCMND, "rx_nss=%d nss=%d\n", rx_nss, nss);
+ nss = MIN(rx_nss, nss);
+ }
+#endif
+
+ pmrvl_oper_mode->oper_mode |= (nss - 1) << 4;
+
+ switch (pbss_desc->curr_bandwidth) {
+ case BW_20MHZ:
+ SET_OPER_MODE_20M(pmrvl_oper_mode->oper_mode);
+ break;
+ case BW_40MHZ:
+ SET_OPER_MODE_40M(pmrvl_oper_mode->oper_mode);
+ break;
+ case BW_80MHZ:
+ default:
+ break;
+ }
+ }
+ HEXDUMP("OPER MODE NTF IE", (t_u8 *)pmrvl_oper_mode,
+ sizeof(MrvlIETypes_OperModeNtf_t));
+ *ppbuffer += sizeof(MrvlIETypes_OperModeNtf_t);
+ ret_len += sizeof(MrvlIETypes_OperModeNtf_t);
+ pmrvl_oper_mode->header.len =
+ wlan_cpu_to_le16(pmrvl_oper_mode->header.len);
+
+ LEAVE();
+ return ret_len;
+}
+
+/**
+ * @brief 11ac configuration handler
+ *
+ * @param pmadapter A pointer to mlan_adapter structure
+ * @param pioctl_req A pointer to ioctl request buffer
+ *
+ * @return MLAN_STATUS_SUCCESS --success, otherwise fail
+ */
+mlan_status wlan_11ac_cfg_ioctl(pmlan_adapter pmadapter,
+ pmlan_ioctl_req pioctl_req)
+{
+ mlan_status status = MLAN_STATUS_SUCCESS;
+ mlan_ds_11ac_cfg *cfg = MNULL;
+
+ ENTER();
+
+ if (pioctl_req->buf_len < sizeof(mlan_ds_11ac_cfg)) {
+ PRINTM(MINFO, "MLAN bss IOCTL length is too short.\n");
+ pioctl_req->data_read_written = 0;
+ pioctl_req->buf_len_needed = sizeof(mlan_ds_11ac_cfg);
+ pioctl_req->status_code = MLAN_ERROR_INVALID_PARAMETER;
+ LEAVE();
+ return MLAN_STATUS_RESOURCE;
+ }
+ cfg = (mlan_ds_11ac_cfg *)pioctl_req->pbuf;
+ switch (cfg->sub_command) {
+ case MLAN_OID_11AC_VHT_CFG:
+ status = wlan_11ac_ioctl_vhtcfg(pmadapter, pioctl_req);
+ break;
+ case MLAN_OID_11AC_CFG_SUPPORTED_MCS_SET:
+ status = wlan_11ac_ioctl_supported_mcs_set(pmadapter,
+ pioctl_req);
+ break;
+ case MLAN_OID_11AC_OPERMODE_CFG:
+ status = wlan_11ac_ioctl_opermodecfg(pmadapter, pioctl_req);
+ break;
+ default:
+ pioctl_req->status_code = MLAN_ERROR_IOCTL_INVALID;
+ status = MLAN_STATUS_FAILURE;
+ break;
+ }
+ LEAVE();
+ return status;
+}
+
+/**
+ * @brief This function prepares 11ac cfg command
+ *
+ * @param pmpriv A pointer to mlan_private structure
+ * @param cmd A pointer to HostCmd_DS_COMMAND structure
+ * @param cmd_action the action: GET or SET
+ * @param pdata_buf A pointer to data buffer
+ * @return MLAN_STATUS_SUCCESS
+ */
+mlan_status wlan_cmd_11ac_cfg(pmlan_private pmpriv, HostCmd_DS_COMMAND *cmd,
+ t_u16 cmd_action, t_void *pdata_buf)
+{
+ pmlan_adapter pmadapter = pmpriv->adapter;
+ HostCmd_DS_11AC_CFG *vhtcfg = &cmd->params.vhtcfg;
+ mlan_ds_11ac_vht_cfg *vht_cfg = (mlan_ds_11ac_vht_cfg *)pdata_buf;
+
+ ENTER();
+ cmd->command = wlan_cpu_to_le16(HostCmd_CMD_11AC_CFG);
+ cmd->size = wlan_cpu_to_le16(sizeof(HostCmd_DS_11AC_CFG) + S_DS_GEN);
+ vhtcfg->action = wlan_cpu_to_le16(cmd_action);
+ vhtcfg->band_config = vht_cfg->band & 0xFF;
+ // block user enable 80MHZ
+ if (IS_FW_SUPPORT_NO_80MHZ(pmadapter))
+ vht_cfg->bwcfg = 0;
+
+ vhtcfg->misc_config = vht_cfg->txrx & 0x3;
+ if (vhtcfg->misc_config != 2)
+ vhtcfg->misc_config |= (vht_cfg->bwcfg << 2);
+
+ vhtcfg->vht_cap_info = wlan_cpu_to_le32(vht_cfg->vht_cap_info);
+ vht_cfg->vht_rx_mcs = wlan_cpu_to_le32(vht_cfg->vht_rx_mcs);
+ memcpy_ext(pmadapter, &vhtcfg->vht_supp_mcs_set[0],
+ &vht_cfg->vht_rx_mcs, sizeof(t_u32), sizeof(t_u32));
+ vht_cfg->vht_tx_mcs = wlan_cpu_to_le32(vht_cfg->vht_tx_mcs);
+ memcpy_ext(pmadapter, &vhtcfg->vht_supp_mcs_set[4],
+ &vht_cfg->vht_tx_mcs, sizeof(t_u32), sizeof(t_u32));
+ LEAVE();
+ return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ * @brief This function handles the command response of 11accfg
+ *
+ * @param pmpriv A pointer to mlan_private structure
+ * @param resp A pointer to HostCmd_DS_COMMAND
+ * @param pioctl_buf A pointer to mlan_ioctl_req structure
+ *
+ * @return MLAN_STATUS_SUCCESS
+ */
+mlan_status wlan_ret_11ac_cfg(pmlan_private pmpriv, HostCmd_DS_COMMAND *resp,
+ mlan_ioctl_req *pioctl_buf)
+{
+ pmlan_adapter pmadapter = pmpriv->adapter;
+ mlan_ds_11ac_cfg *cfg = MNULL;
+ HostCmd_DS_11AC_CFG *vhtcfg = &resp->params.vhtcfg;
+
+ ENTER();
+ if (pioctl_buf &&
+ (wlan_le16_to_cpu(vhtcfg->action) == HostCmd_ACT_GEN_GET)) {
+ cfg = (mlan_ds_11ac_cfg *)pioctl_buf->pbuf;
+ cfg->param.vht_cfg.band = vhtcfg->band_config;
+ cfg->param.vht_cfg.txrx = vhtcfg->misc_config & 0x03;
+ if (cfg->param.vht_cfg.txrx & 0x1)
+ cfg->param.vht_cfg.bwcfg =
+ (vhtcfg->misc_config & 0x04) >> 2;
+ else
+ cfg->param.vht_cfg.bwcfg = 0;
+
+ cfg->param.vht_cfg.vht_cap_info =
+ wlan_le32_to_cpu(vhtcfg->vht_cap_info);
+ memcpy_ext(pmadapter, &cfg->param.vht_cfg.vht_rx_mcs,
+ &vhtcfg->vht_supp_mcs_set[0], sizeof(t_u32),
+ sizeof(t_u32));
+ cfg->param.vht_cfg.vht_rx_mcs =
+ wlan_le32_to_cpu(cfg->param.vht_cfg.vht_rx_mcs);
+ memcpy_ext(pmadapter, &cfg->param.vht_cfg.vht_tx_mcs,
+ &vhtcfg->vht_supp_mcs_set[4], sizeof(t_u32),
+ sizeof(t_u32));
+ cfg->param.vht_cfg.vht_tx_mcs =
+ wlan_le32_to_cpu(cfg->param.vht_cfg.vht_tx_mcs);
+ cfg->param.vht_cfg.vht_rx_max_rate =
+ wlan_convert_mcsmap_to_maxrate(
+ pmpriv, cfg->param.vht_cfg.band,
+ cfg->param.vht_cfg.vht_rx_mcs);
+ cfg->param.vht_cfg.vht_tx_max_rate =
+ wlan_convert_mcsmap_to_maxrate(
+ pmpriv, cfg->param.vht_cfg.band,
+ cfg->param.vht_cfg.vht_tx_mcs);
+ }
+ LEAVE();
+ return MLAN_STATUS_SUCCESS;
+}
+
+void wlan_update_11ac_cap(mlan_private *pmpriv)
+{
+ mlan_adapter *pmadapter = pmpriv->adapter;
+
+ pmpriv->usr_dot_11ac_mcs_support = pmadapter->hw_dot_11ac_mcs_support;
+ pmpriv->usr_dot_11ac_dev_cap_bg =
+ pmadapter->hw_dot_11ac_dev_cap &
+ ~DEFALUT_11AC_CAP_BEAMFORMING_RESET_MASK;
+ pmpriv->usr_dot_11ac_dev_cap_a =
+ pmadapter->hw_dot_11ac_dev_cap &
+ ~DEFALUT_11AC_CAP_BEAMFORMING_RESET_MASK;
+ pmpriv->usr_dot_11ac_bw = BW_FOLLOW_VHTCAP;
+}
+
+/**
+ * @brief This function check if 11AC is allowed in bandcfg
+ *
+ * @param pmpriv A pointer to mlan_private structure
+ * @param bss_band bss band
+ *
+ * @return 0--not allowed, other value allowed
+ */
+t_u8 wlan_11ac_bandconfig_allowed(mlan_private *pmpriv, t_u16 bss_band)
+{
+ if (pmpriv->bss_mode == MLAN_BSS_MODE_IBSS) {
+ if (bss_band & BAND_G)
+ return (pmpriv->adapter->adhoc_start_band & BAND_GAC);
+ else if (bss_band & BAND_A)
+ return (pmpriv->adapter->adhoc_start_band & BAND_AAC);
+ } else {
+ if (bss_band & BAND_G)
+ return (pmpriv->config_bands & BAND_GAC);
+ else if (bss_band & BAND_A)
+ return (pmpriv->config_bands & BAND_AAC);
+ }
+ return 0;
+}
diff --git a/drivers/net/wireless/nxp/mxm_wifiex/wlan_src/mlan/mlan_11ac.h b/drivers/net/wireless/nxp/mxm_wifiex/wlan_src/mlan/mlan_11ac.h
new file mode 100644
index 000000000000..81661065bbaf
--- /dev/null
+++ b/drivers/net/wireless/nxp/mxm_wifiex/wlan_src/mlan/mlan_11ac.h
@@ -0,0 +1,52 @@
+/** @file mlan_11ac.h
+ *
+ * @brief This file contains the functions for station ioctl.
+ *
+ *
+ * Copyright 2014-2020 NXP
+ *
+ * This software file (the File) is distributed by NXP
+ * under the terms of the GNU General Public License Version 2, June 1991
+ * (the License). You may use, redistribute and/or modify the 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 _MLAN_11AC_H_
+#define _MLAN_11AC_H_
+
+#include "mlan_11n_aggr.h"
+#include "mlan_11n_rxreorder.h"
+#include "mlan_wmm.h"
+
+void wlan_show_dot11acdevcap(pmlan_adapter pmadapter, t_u32 cap);
+void wlan_show_dot11acmcssupport(pmlan_adapter pmadapter, t_u32 support);
+t_u16 wlan_convert_mcsmap_to_maxrate(mlan_private *priv, t_u16 bands,
+ t_u16 mcs_map);
+void wlan_fill_vht_cap_tlv(mlan_private *priv, MrvlIETypes_VHTCap_t *pvht_cap,
+ t_u16 bands, t_u8 flag, t_u8 bw_80p80);
+void wlan_fill_vht_cap_ie(mlan_private *priv, IEEEtypes_VHTCap_t *pvht_cap,
+ t_u16 bands);
+int wlan_cmd_append_11ac_tlv(mlan_private *pmpriv, BSSDescriptor_t *pbss_desc,
+ t_u8 **ppbuffer);
+mlan_status wlan_11ac_cfg_ioctl(pmlan_adapter pmadapter,
+ pmlan_ioctl_req pioctl_req);
+void wlan_update_11ac_cap(mlan_private *pmpriv);
+t_u8 wlan_11ac_bandconfig_allowed(mlan_private *pmpriv, t_u8 bss_band);
+t_u8 wlan_is_80_80_support(mlan_private *pmpriv, BSSDescriptor_t *pbss_desc);
+
+mlan_status wlan_cmd_11ac_cfg(pmlan_private pmpriv, HostCmd_DS_COMMAND *cmd,
+ t_u16 cmd_action, t_void *pdata_buf);
+
+mlan_status wlan_ret_11ac_cfg(pmlan_private pmpriv, HostCmd_DS_COMMAND *resp,
+ mlan_ioctl_req *pioctl_buf);
+
+#endif /* _MLAN_11AC_H_ */
diff --git a/drivers/net/wireless/nxp/mxm_wifiex/wlan_src/mlan/mlan_11ax.c b/drivers/net/wireless/nxp/mxm_wifiex/wlan_src/mlan/mlan_11ax.c
new file mode 100644
index 000000000000..628e430dfe4e
--- /dev/null
+++ b/drivers/net/wireless/nxp/mxm_wifiex/wlan_src/mlan/mlan_11ax.c
@@ -0,0 +1,904 @@
+/** @file mlan_11ax.c
+ *
+ * @brief This file contains the functions for 11ax related features.
+ *
+ *
+ * Copyright 2014-2020 NXP
+ *
+ * This software file (the File) is distributed by NXP
+ * under the terms of the GNU General Public License Version 2, June 1991
+ * (the License). You may use, redistribute and/or modify the 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 "mlan.h"
+#include "mlan_join.h"
+#include "mlan_util.h"
+#include "mlan_ioctl.h"
+#include "mlan_fw.h"
+#include "mlan_main.h"
+#include "mlan_wmm.h"
+#include "mlan_11n.h"
+#include "mlan_11ax.h"
+#include "mlan_11ac.h"
+
+/********************************************************
+ Local Variables
+********************************************************/
+
+/********************************************************
+ Global Variables
+********************************************************/
+
+/********************************************************
+ Local Functions
+********************************************************/
+
+/********************************************************
+ Global Functions
+********************************************************/
+
+/**
+ * @brief This function prints the 802.11ax HE mac capability
+ *
+ * @param pmadapter A pointer to mlan_adapter structure
+ * @param cap Capability value
+ *
+ * @return N/A
+ */
+void wlan_show_dot11axmaccap(pmlan_adapter pmadapter, t_u32 cap)
+{
+ ENTER();
+
+ LEAVE();
+ return;
+}
+
+/**
+ * @brief This function check if AP support TWT Response.
+ *
+ * @param pbss_desc A pointer to BSSDescriptor_t structure
+ *
+ * @return MTRUE/MFALSE
+ */
+t_u8 wlan_check_ap_11ax_twt_supported(BSSDescriptor_t *pbss_desc)
+{
+ if (!pbss_desc->phe_cap)
+ return MFALSE;
+ if (!(pbss_desc->phe_cap->he_mac_cap[0] & HE_MAC_CAP_TWT_REQ_SUPPORT))
+ return MFALSE;
+ if (!pbss_desc->pext_cap)
+ return MFALSE;
+ if (!ISSUPP_EXTCAP_EXT_TWT_RESP(pbss_desc->pext_cap->ext_cap))
+ return MFALSE;
+ return MTRUE;
+}
+
+/**
+ * @brief This function check if we should enable TWT support
+ *
+ * @param pbss_desc A pointer to BSSDescriptor_t structure
+ *
+ * @return MTRUE/MFALSE
+ */
+t_u8 wlan_check_11ax_twt_supported(mlan_private *pmpriv,
+ BSSDescriptor_t *pbss_desc)
+{
+ MrvlIEtypes_He_cap_t *phecap =
+ (MrvlIEtypes_He_cap_t *)&pmpriv->user_he_cap;
+ MrvlIEtypes_He_cap_t *hw_he_cap =
+ (MrvlIEtypes_He_cap_t *)&pmpriv->adapter->hw_he_cap;
+ if (pbss_desc && !wlan_check_ap_11ax_twt_supported(pbss_desc)) {
+ PRINTM(MINFO, "AP don't support twt feature\n");
+ return MFALSE;
+ }
+ if (pbss_desc) {
+ if (pbss_desc->bss_band & BAND_A) {
+ hw_he_cap = (MrvlIEtypes_He_cap_t *)&pmpriv->adapter
+ ->hw_he_cap;
+ phecap = (MrvlIEtypes_He_cap_t *)&pmpriv->user_he_cap;
+ } else {
+ hw_he_cap = (MrvlIEtypes_He_cap_t *)&pmpriv->adapter
+ ->hw_2g_he_cap;
+ phecap =
+ (MrvlIEtypes_He_cap_t *)&pmpriv->user_2g_he_cap;
+ }
+ }
+ if (!(hw_he_cap->he_mac_cap[0] & HE_MAC_CAP_TWT_REQ_SUPPORT)) {
+ PRINTM(MINFO, "FW don't support TWT\n");
+ return MFALSE;
+ }
+ if (phecap->he_mac_cap[0] & HE_MAC_CAP_TWT_REQ_SUPPORT)
+ return MTRUE;
+ PRINTM(MINFO, "USER HE_MAC_CAP don't support TWT\n");
+ return MFALSE;
+}
+
+/**
+ * @brief This function prints the 802.11ax HE PHY cap
+ *
+ * @param pmadapter A pointer to mlan_adapter structure
+ * @param support Support value
+ *
+ * @return N/A
+ */
+void wlan_show_dot11axphycap(pmlan_adapter pmadapter, t_u32 support)
+{
+ ENTER();
+
+ LEAVE();
+ return;
+}
+
+/**
+ * @brief This function fills the HE cap tlv out put format is LE, not CPU
+ *
+ * @param priv A pointer to mlan_private structure
+ * @param band 5G or 2.4 G
+ * @param phe_cap A pointer to MrvlIEtypes_Data_t structure
+ * @param flag TREU--pvht_cap has the setting for resp
+ * MFALSE -- pvht_cap is clean
+ *
+ * @return bytes added to the phe_cap
+ */
+t_u16 wlan_fill_he_cap_tlv(mlan_private *pmpriv, t_u8 band,
+ MrvlIEtypes_Extension_t *phe_cap, t_u8 flag)
+{
+ pmlan_adapter pmadapter = pmpriv->adapter;
+ t_u16 len = 0;
+
+ if (!phe_cap) {
+ LEAVE();
+ return 0;
+ }
+ if (band & BAND_A) {
+ memcpy_ext(pmadapter, (t_u8 *)phe_cap, pmpriv->user_he_cap,
+ pmpriv->user_hecap_len,
+ sizeof(MrvlIEtypes_He_cap_t));
+ len = pmpriv->user_hecap_len;
+ } else {
+ memcpy_ext(pmadapter, (t_u8 *)phe_cap, pmpriv->user_2g_he_cap,
+ pmpriv->user_2g_hecap_len,
+ sizeof(MrvlIEtypes_He_cap_t));
+ len = pmpriv->user_2g_hecap_len;
+ }
+ phe_cap->type = wlan_cpu_to_le16(phe_cap->type);
+ phe_cap->len = wlan_cpu_to_le16(phe_cap->len);
+
+ LEAVE();
+ return len;
+}
+
+/**
+ * @brief This function append the 802_11ax HE capability tlv
+ *
+ * @param pmpriv A pointer to mlan_private structure
+ * @param pbss_desc A pointer to BSSDescriptor_t structure
+ * @param ppbuffer A Pointer to command buffer pointer
+ *
+ * @return bytes added to the buffer
+ */
+int wlan_cmd_append_11ax_tlv(mlan_private *pmpriv, BSSDescriptor_t *pbss_desc,
+ t_u8 **ppbuffer)
+{
+ pmlan_adapter pmadapter = pmpriv->adapter;
+ MrvlIEtypes_He_cap_t *phecap = MNULL;
+ int len = 0;
+ t_u8 bw_80p80 = MFALSE;
+
+ ENTER();
+
+ /* Null Checks */
+ if (ppbuffer == MNULL) {
+ LEAVE();
+ return 0;
+ }
+ if (*ppbuffer == MNULL) {
+ LEAVE();
+ return 0;
+ }
+ /** check if AP support HE, if not return right away */
+ if (!pbss_desc->phe_cap) {
+ LEAVE();
+ return 0;
+ }
+ bw_80p80 = wlan_is_80_80_support(pmpriv, pbss_desc);
+ phecap = (MrvlIEtypes_He_cap_t *)*ppbuffer;
+ if (pbss_desc->bss_band & BAND_A) {
+ memcpy_ext(pmadapter, *ppbuffer, pmpriv->user_he_cap,
+ pmpriv->user_hecap_len, pmpriv->user_hecap_len);
+ *ppbuffer += pmpriv->user_hecap_len;
+ len = pmpriv->user_hecap_len;
+ } else {
+ memcpy_ext(pmadapter, *ppbuffer, pmpriv->user_2g_he_cap,
+ pmpriv->user_2g_hecap_len,
+ pmpriv->user_2g_hecap_len);
+ *ppbuffer += pmpriv->user_2g_hecap_len;
+ len = pmpriv->user_2g_hecap_len;
+ }
+ phecap->type = wlan_cpu_to_le16(phecap->type);
+ phecap->len = wlan_cpu_to_le16(phecap->len);
+
+ if (bw_80p80) {
+ /** configure 2*2 to 1*1 to support 80+80Mhz*/
+ /** set 1*1 mcs rate for 80Mhz rx*/
+ phecap->he_txrx_mcs_support[0] &= ~(MBIT(0) | MBIT(1));
+ /** set 1*1 mcs rate for 80Mhz tx*/
+ phecap->he_txrx_mcs_support[3] &= ~(MBIT(0) | MBIT(1));
+ /** set 1*1 mcs rate for 160Mhz rx*/
+ phecap->he160_txrx_mcs_support[0] &= ~(MBIT(0) | MBIT(1));
+ /** set 1*1 mcs rate for 160Mhz tx*/
+ phecap->he160_txrx_mcs_support[3] &= ~(MBIT(0) | MBIT(1));
+ /** set 1*1 mcs rate for 80+80Mhz rx*/
+ phecap->he8080_txrx_mcs_support[0] &= ~(MBIT(0) | MBIT(1));
+ /** set 1*1 mcs rate for 80+80Mhz tx*/
+ phecap->he8080_txrx_mcs_support[3] &= ~(MBIT(0) | MBIT(1));
+ } else {
+ /** reset BIT3 and BIT4 channel width ,not support 80 + 80*/
+ /** not support 160Mhz now, if support,not reset bit3 */
+ phecap->he_phy_cap[0] &= ~(MBIT(3) | MBIT(4));
+ }
+
+ LEAVE();
+ return len;
+}
+
+/**
+ * @brief This function save the 11ax cap from FW.
+ *
+ * @param pmadapater A pointer to mlan_adapter
+ * @param hw_he_cap A pointer to MrvlIEtypes_Extension_t
+ *
+ * @return N/A
+ */
+void wlan_update_11ax_cap(mlan_adapter *pmadapter,
+ MrvlIEtypes_Extension_t *hw_he_cap)
+{
+ MrvlIEtypes_He_cap_t *phe_cap = MNULL;
+ t_u8 i = 0;
+ t_u8 he_cap_2g = 0;
+
+ ENTER();
+ if ((hw_he_cap->len + sizeof(MrvlIEtypesHeader_t)) >
+ sizeof(pmadapter->hw_he_cap)) {
+ PRINTM(MERROR, "hw_he_cap too big, len=%d\n", hw_he_cap->len);
+ LEAVE();
+ return;
+ }
+ phe_cap = (MrvlIEtypes_He_cap_t *)hw_he_cap;
+ if (phe_cap->he_phy_cap[0] &
+ (AX_2G_40MHZ_SUPPORT | AX_2G_20MHZ_SUPPORT)) {
+ pmadapter->hw_2g_hecap_len =
+ hw_he_cap->len + sizeof(MrvlIEtypesHeader_t);
+ memcpy_ext(pmadapter, pmadapter->hw_2g_he_cap,
+ (t_u8 *)hw_he_cap,
+ hw_he_cap->len + sizeof(MrvlIEtypesHeader_t),
+ sizeof(pmadapter->hw_2g_he_cap));
+ pmadapter->fw_bands |= BAND_GAX;
+ pmadapter->config_bands |= BAND_GAX;
+ he_cap_2g = MTRUE;
+ DBG_HEXDUMP(MCMD_D, "2.4G HE capability IE ",
+ (t_u8 *)pmadapter->hw_2g_he_cap,
+ pmadapter->hw_2g_hecap_len);
+ } else {
+ pmadapter->fw_bands |= BAND_AAX;
+ pmadapter->config_bands |= BAND_AAX;
+ pmadapter->hw_hecap_len =
+ hw_he_cap->len + sizeof(MrvlIEtypesHeader_t);
+ memcpy_ext(pmadapter, pmadapter->hw_he_cap, (t_u8 *)hw_he_cap,
+ hw_he_cap->len + sizeof(MrvlIEtypesHeader_t),
+ sizeof(pmadapter->hw_he_cap));
+ DBG_HEXDUMP(MCMD_D, "5G HE capability IE ",
+ (t_u8 *)pmadapter->hw_he_cap,
+ pmadapter->hw_hecap_len);
+ }
+ for (i = 0; i < pmadapter->priv_num; i++) {
+ if (pmadapter->priv[i]) {
+ pmadapter->priv[i]->config_bands =
+ pmadapter->config_bands;
+ if (he_cap_2g) {
+ pmadapter->priv[i]->user_2g_hecap_len =
+ pmadapter->hw_2g_hecap_len;
+ memcpy_ext(pmadapter,
+ pmadapter->priv[i]->user_2g_he_cap,
+ pmadapter->hw_2g_he_cap,
+ pmadapter->hw_2g_hecap_len,
+ sizeof(pmadapter->priv[i]
+ ->user_2g_he_cap));
+ } else {
+ pmadapter->priv[i]->user_hecap_len =
+ pmadapter->hw_hecap_len;
+ memcpy_ext(
+ pmadapter,
+ pmadapter->priv[i]->user_he_cap,
+ pmadapter->hw_he_cap,
+ pmadapter->hw_hecap_len,
+ sizeof(pmadapter->priv[i]->user_he_cap));
+ }
+ }
+ }
+ LEAVE();
+ return;
+}
+
+/**
+ * @brief This function check if 11AX is allowed in bandcfg
+ *
+ * @param pmpriv A pointer to mlan_private structure
+ * @param bss_band bss band
+ *
+ * @return 0--not allowed, other value allowed
+ */
+t_u16 wlan_11ax_bandconfig_allowed(mlan_private *pmpriv, t_u16 bss_band)
+{
+ if (!IS_FW_SUPPORT_11AX(pmpriv->adapter))
+ return MFALSE;
+ if (pmpriv->bss_mode == MLAN_BSS_MODE_IBSS) {
+ if (bss_band & BAND_G)
+ return (pmpriv->adapter->adhoc_start_band & BAND_GAX);
+ else if (bss_band & BAND_A)
+ return (pmpriv->adapter->adhoc_start_band & BAND_AAX);
+ } else {
+ if (bss_band & BAND_G)
+ return (pmpriv->config_bands & BAND_GAX);
+ else if (bss_band & BAND_A)
+ return (pmpriv->config_bands & BAND_AAX);
+ }
+ return MFALSE;
+}
+
+/**
+ * @brief Set 11ax configuration
+ *
+ * @param pmadapter A pointer to mlan_adapter structure
+ * @param pioctl_req A pointer to ioctl request buffer
+ *
+ * @return MLAN_STATUS_PENDING --success, otherwise fail
+ */
+static mlan_status wlan_11ax_ioctl_hecfg(pmlan_adapter pmadapter,
+ pmlan_ioctl_req pioctl_req)
+{
+ mlan_status ret = MLAN_STATUS_SUCCESS;
+ mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index];
+ mlan_ds_11ax_cfg *cfg = MNULL;
+ t_u16 cmd_action = 0;
+
+ ENTER();
+
+ if (pioctl_req->buf_len < sizeof(mlan_ds_11ax_cfg)) {
+ PRINTM(MINFO, "MLAN bss IOCTL length is too short.\n");
+ pioctl_req->data_read_written = 0;
+ pioctl_req->buf_len_needed = sizeof(mlan_ds_11ax_cfg);
+ pioctl_req->status_code = MLAN_ERROR_INVALID_PARAMETER;
+ LEAVE();
+ return MLAN_STATUS_RESOURCE;
+ }
+
+ cfg = (mlan_ds_11ax_cfg *)pioctl_req->pbuf;
+
+ if ((cfg->param.he_cfg.band & MBIT(0)) &&
+ !(pmadapter->fw_bands & BAND_GAX)) {
+ PRINTM(MERROR, "FW don't support 2.4G AX\n");
+ return MLAN_STATUS_FAILURE;
+ }
+ if ((cfg->param.he_cfg.band & MBIT(1)) &&
+ !(pmadapter->fw_bands & BAND_AAX)) {
+ PRINTM(MERROR, "FW don't support 5G AX\n");
+ return MLAN_STATUS_FAILURE;
+ }
+ if (pioctl_req->action == MLAN_ACT_SET)
+ cmd_action = HostCmd_ACT_GEN_SET;
+ else
+ cmd_action = HostCmd_ACT_GEN_GET;
+
+ /* Send request to firmware */
+ ret = wlan_prepare_cmd(pmpriv, HostCmd_CMD_11AX_CFG, cmd_action, 0,
+ (t_void *)pioctl_req,
+ (t_void *)&cfg->param.he_cfg);
+ if (ret == MLAN_STATUS_SUCCESS)
+ ret = MLAN_STATUS_PENDING;
+
+ LEAVE();
+ return ret;
+}
+
+/**
+ * @brief 11ax configuration handler
+ *
+ * @param pmadapter A pointer to mlan_adapter structure
+ * @param pioctl_req A pointer to ioctl request buffer
+ *
+ * @return MLAN_STATUS_SUCCESS --success, otherwise fail
+ */
+mlan_status wlan_11ax_cfg_ioctl(pmlan_adapter pmadapter,
+ pmlan_ioctl_req pioctl_req)
+{
+ mlan_status status = MLAN_STATUS_SUCCESS;
+ mlan_ds_11ax_cfg *cfg = MNULL;
+
+ ENTER();
+
+ cfg = (mlan_ds_11ax_cfg *)pioctl_req->pbuf;
+ switch (cfg->sub_command) {
+ case MLAN_OID_11AX_HE_CFG:
+ status = wlan_11ax_ioctl_hecfg(pmadapter, pioctl_req);
+ break;
+ case MLAN_OID_11AX_CMD_CFG:
+ status = wlan_11ax_ioctl_cmd(pmadapter, pioctl_req);
+ break;
+ case MLAN_OID_11AX_TWT_CFG:
+ status = wlan_11ax_ioctl_twtcfg(pmadapter, pioctl_req);
+ break;
+ default:
+ pioctl_req->status_code = MLAN_ERROR_IOCTL_INVALID;
+ status = MLAN_STATUS_FAILURE;
+ break;
+ }
+ LEAVE();
+ return status;
+}
+
+/**
+ * @brief This function prepares 11ax cfg command
+ *
+ * @param pmpriv A pointer to mlan_private structure
+ * @param cmd A pointer to HostCmd_DS_COMMAND structure
+ * @param cmd_action the action: GET or SET
+ * @param pdata_buf A pointer to data buffer
+ * @return MLAN_STATUS_SUCCESS
+ */
+mlan_status wlan_cmd_11ax_cfg(pmlan_private pmpriv, HostCmd_DS_COMMAND *cmd,
+ t_u16 cmd_action, t_void *pdata_buf)
+{
+ pmlan_adapter pmadapter = pmpriv->adapter;
+ HostCmd_DS_11AX_CFG *axcfg = &cmd->params.axcfg;
+ mlan_ds_11ax_he_cfg *hecfg = (mlan_ds_11ax_he_cfg *)pdata_buf;
+ MrvlIEtypes_Extension_t *tlv = MNULL;
+ t_u8 *pos = MNULL;
+
+ ENTER();
+ cmd->command = wlan_cpu_to_le16(HostCmd_CMD_11AX_CFG);
+ cmd->size = sizeof(HostCmd_DS_11AX_CFG) + S_DS_GEN;
+
+ axcfg->action = wlan_cpu_to_le16(cmd_action);
+ axcfg->band_config = hecfg->band & 0xFF;
+
+ pos = (t_u8 *)axcfg->val;
+ /**HE Capability */
+ if (hecfg->he_cap.len && (hecfg->he_cap.ext_id == HE_CAPABILITY)) {
+ tlv = (MrvlIEtypes_Extension_t *)pos;
+ tlv->type = wlan_cpu_to_le16(hecfg->he_cap.id);
+ tlv->len = wlan_cpu_to_le16(hecfg->he_cap.len);
+ memcpy_ext(pmadapter, &tlv->ext_id, &hecfg->he_cap.ext_id,
+ hecfg->he_cap.len,
+ MRVDRV_SIZE_OF_CMD_BUFFER - cmd->size);
+ cmd->size += hecfg->he_cap.len + sizeof(MrvlIEtypesHeader_t);
+ pos += hecfg->he_cap.len + sizeof(MrvlIEtypesHeader_t);
+ }
+
+ cmd->size = wlan_cpu_to_le16(cmd->size);
+
+ LEAVE();
+ return MLAN_STATUS_SUCCESS;
+}
+/**
+ * @brief This function handles the command response of 11axcfg
+ *
+ * @param pmpriv A pointer to mlan_private structure
+ * @param resp A pointer to HostCmd_DS_COMMAND
+ * @param pioctl_buf A pointer to mlan_ioctl_req structure
+ *
+ * @return MLAN_STATUS_SUCCESS
+ */
+mlan_status wlan_ret_11ax_cfg(pmlan_private pmpriv, HostCmd_DS_COMMAND *resp,
+ mlan_ioctl_req *pioctl_buf)
+{
+ pmlan_adapter pmadapter = pmpriv->adapter;
+ mlan_ds_11ax_cfg *cfg = MNULL;
+ mlan_ds_11ax_he_capa *hecap = MNULL;
+ HostCmd_DS_11AX_CFG *axcfg = &resp->params.axcfg;
+ MrvlIEtypes_Extension_t *tlv = MNULL;
+ t_u16 left_len = 0, tlv_type = 0, tlv_len = 0;
+
+ ENTER();
+
+ if (pioctl_buf == MNULL)
+ goto done;
+
+ cfg = (mlan_ds_11ax_cfg *)pioctl_buf->pbuf;
+ cfg->param.he_cfg.band = axcfg->band_config;
+ hecap = (mlan_ds_11ax_he_capa *)&cfg->param.he_cfg.he_cap;
+
+ /* TLV parse */
+ left_len = resp->size - sizeof(HostCmd_DS_11AX_CFG) - S_DS_GEN;
+ tlv = (MrvlIEtypes_Extension_t *)axcfg->val;
+
+ while (left_len > sizeof(MrvlIEtypesHeader_t)) {
+ tlv_type = wlan_le16_to_cpu(tlv->type);
+ tlv_len = wlan_le16_to_cpu(tlv->len);
+ if (tlv_type == EXTENSION) {
+ switch (tlv->ext_id) {
+ case HE_CAPABILITY:
+ hecap->id = tlv_type;
+ hecap->len = tlv_len;
+ memcpy_ext(pmadapter, (t_u8 *)&hecap->ext_id,
+ (t_u8 *)&tlv->ext_id, tlv_len,
+ sizeof(mlan_ds_11ax_he_capa) -
+ sizeof(MrvlIEtypesHeader_t));
+ if (cfg->param.he_cfg.band & MBIT(1)) {
+ memcpy_ext(
+ pmadapter,
+ (t_u8 *)&pmpriv->user_he_cap,
+ (t_u8 *)tlv,
+ tlv_len +
+ sizeof(MrvlIEtypesHeader_t),
+ sizeof(pmpriv->user_he_cap));
+ pmpriv->user_hecap_len = MIN(
+ tlv_len +
+ sizeof(MrvlIEtypesHeader_t),
+ sizeof(pmpriv->user_he_cap));
+ PRINTM(MCMND, "user_hecap_len=%d\n",
+ pmpriv->user_hecap_len);
+ } else {
+ memcpy_ext(
+ pmadapter,
+ (t_u8 *)&pmpriv->user_2g_he_cap,
+ (t_u8 *)tlv,
+ tlv_len +
+ sizeof(MrvlIEtypesHeader_t),
+ sizeof(pmpriv->user_2g_he_cap));
+ pmpriv->user_2g_hecap_len = MIN(
+ tlv_len +
+ sizeof(MrvlIEtypesHeader_t),
+ sizeof(pmpriv->user_2g_he_cap));
+ PRINTM(MCMND, "user_2g_hecap_len=%d\n",
+ pmpriv->user_2g_hecap_len);
+ }
+ break;
+ default:
+ break;
+ }
+ }
+
+ left_len -= (sizeof(MrvlIEtypesHeader_t) + tlv_len);
+ tlv = (MrvlIEtypes_Extension_t *)((t_u8 *)tlv + tlv_len +
+ sizeof(MrvlIEtypesHeader_t));
+ }
+
+done:
+ LEAVE();
+ return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ * @brief 11ax command handler
+ *
+ * @param pmadapter A pointer to mlan_adapter structure
+ * @param pioctl_req A pointer to ioctl request buffer
+ *
+ * @return MLAN_STATUS_SUCCESS --success, otherwise fail
+ */
+mlan_status wlan_11ax_ioctl_cmd(pmlan_adapter pmadapter,
+ pmlan_ioctl_req pioctl_req)
+{
+ mlan_status status = MLAN_STATUS_SUCCESS;
+ mlan_ds_11ax_cmd_cfg *cfg = MNULL;
+ mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index];
+ t_u16 cmd_action = 0;
+
+ ENTER();
+
+ if (pioctl_req->buf_len < sizeof(mlan_ds_11ax_cmd_cfg)) {
+ PRINTM(MINFO, "MLAN bss IOCTL length is too short.\n");
+ pioctl_req->data_read_written = 0;
+ pioctl_req->buf_len_needed = sizeof(mlan_ds_11ax_cmd_cfg);
+ pioctl_req->status_code = MLAN_ERROR_INVALID_PARAMETER;
+ LEAVE();
+ return MLAN_STATUS_RESOURCE;
+ }
+ cfg = (mlan_ds_11ax_cmd_cfg *)pioctl_req->pbuf;
+
+ if (pioctl_req->action == MLAN_ACT_SET)
+ cmd_action = HostCmd_ACT_GEN_SET;
+ else
+ cmd_action = HostCmd_ACT_GEN_GET;
+
+ /* Send request to firmware */
+ status = wlan_prepare_cmd(pmpriv, HostCmd_CMD_11AX_CMD, cmd_action, 0,
+ (t_void *)pioctl_req, (t_void *)cfg);
+ if (status == MLAN_STATUS_SUCCESS)
+ status = MLAN_STATUS_PENDING;
+
+ LEAVE();
+ return status;
+}
+
+/**
+ * @brief This function prepares 11ax command
+ *
+ * @param pmpriv A pointer to mlan_private structure
+ * @param cmd A pointer to HostCmd_DS_COMMAND structure
+ * @param cmd_action the action: GET or SET
+ * @param pdata_buf A pointer to data buffer
+ * @return MLAN_STATUS_SUCCESS
+ */
+mlan_status wlan_cmd_11ax_cmd(pmlan_private pmpriv, HostCmd_DS_COMMAND *cmd,
+ t_u16 cmd_action, t_void *pdata_buf)
+{
+ pmlan_adapter pmadapter = pmpriv->adapter;
+ HostCmd_DS_11AX_CMD_CFG *axcmd = &cmd->params.axcmd;
+ mlan_ds_11ax_cmd_cfg *ds_11ax_cmd = (mlan_ds_11ax_cmd_cfg *)pdata_buf;
+ mlan_ds_11ax_sr_cmd *sr_cmd =
+ (mlan_ds_11ax_sr_cmd *)&ds_11ax_cmd->param;
+ mlan_ds_11ax_beam_cmd *beam_cmd =
+ (mlan_ds_11ax_beam_cmd *)&ds_11ax_cmd->param;
+ mlan_ds_11ax_htc_cmd *htc_cmd =
+ (mlan_ds_11ax_htc_cmd *)&ds_11ax_cmd->param;
+ mlan_ds_11ax_txop_cmd *txop_cmd =
+ (mlan_ds_11ax_txop_cmd *)&ds_11ax_cmd->param;
+ mlan_ds_11ax_txomi_cmd *txomi_cmd =
+ (mlan_ds_11ax_txomi_cmd *)&ds_11ax_cmd->param;
+ mlan_ds_11ax_toltime_cmd *toltime_cmd =
+ (mlan_ds_11ax_toltime_cmd *)&ds_11ax_cmd->param;
+ MrvlIEtypes_Data_t *tlv = MNULL;
+
+ ENTER();
+ cmd->command = wlan_cpu_to_le16(HostCmd_CMD_11AX_CMD);
+ cmd->size = sizeof(HostCmd_DS_11AX_CMD_CFG) + S_DS_GEN;
+
+ axcmd->action = wlan_cpu_to_le16(cmd_action);
+ axcmd->sub_id = wlan_cpu_to_le16(ds_11ax_cmd->sub_id);
+ switch (ds_11ax_cmd->sub_id) {
+ case MLAN_11AXCMD_SR_SUBID:
+ tlv = (MrvlIEtypes_Data_t *)axcmd->val;
+ tlv->header.type = wlan_cpu_to_le16(sr_cmd->type);
+ tlv->header.len = wlan_cpu_to_le16(sr_cmd->len);
+ memcpy_ext(pmadapter, tlv->data,
+ &sr_cmd->param.obss_pd_offset.offset, sr_cmd->len,
+ sr_cmd->len);
+ cmd->size += sizeof(MrvlIEtypesHeader_t) + sr_cmd->len;
+ break;
+ case MLAN_11AXCMD_BEAM_SUBID:
+ axcmd->val[0] = beam_cmd->value;
+ cmd->size += sizeof(t_u8);
+ break;
+ case MLAN_11AXCMD_HTC_SUBID:
+ axcmd->val[0] = htc_cmd->value;
+ cmd->size += sizeof(t_u8);
+ break;
+ case MLAN_11AXCMD_TXOPRTS_SUBID:
+ memcpy_ext(pmadapter, axcmd->val, &txop_cmd->rts_thres,
+ sizeof(t_u16), sizeof(t_u16));
+ cmd->size += sizeof(t_u16);
+ break;
+ case MLAN_11AXCMD_TXOMI_SUBID:
+ memcpy_ext(pmadapter, axcmd->val, &txomi_cmd->omi,
+ sizeof(t_u16), sizeof(t_u16));
+ cmd->size += sizeof(t_u16);
+ break;
+ case MLAN_11AXCMD_OBSS_TOLTIME_SUBID:
+ memcpy_ext(pmadapter, axcmd->val, &toltime_cmd->tol_time,
+ sizeof(t_u32), sizeof(t_u32));
+ cmd->size += sizeof(t_u32);
+ break;
+ default:
+ PRINTM(MERROR, "Unknown subcmd %x\n", ds_11ax_cmd->sub_id);
+ break;
+ }
+
+ cmd->size = wlan_cpu_to_le16(cmd->size);
+
+ LEAVE();
+ return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ * @brief This function handles the command response of 11axcmd
+ *
+ * @param pmpriv A pointer to mlan_private structure
+ * @param resp A pointer to HostCmd_DS_COMMAND
+ * @param pioctl_buf A pointer to mlan_ioctl_req structure
+ *
+ * @return MLAN_STATUS_SUCCESS
+ */
+mlan_status wlan_ret_11ax_cmd(pmlan_private pmpriv, HostCmd_DS_COMMAND *resp,
+ mlan_ioctl_req *pioctl_buf)
+{
+ pmlan_adapter pmadapter = pmpriv->adapter;
+ mlan_ds_11ax_cmd_cfg *cfg = MNULL;
+ HostCmd_DS_11AX_CMD_CFG *axcmd = &resp->params.axcmd;
+ MrvlIEtypes_Data_t *tlv = MNULL;
+ t_s16 left_len = 0;
+ t_u16 tlv_type = 0, tlv_len = 0;
+
+ ENTER();
+
+ if (pioctl_buf == MNULL)
+ goto done;
+
+ cfg = (mlan_ds_11ax_cmd_cfg *)pioctl_buf->pbuf;
+ cfg->sub_id = wlan_le16_to_cpu(axcmd->sub_id);
+
+ switch (axcmd->sub_id) {
+ case MLAN_11AXCMD_SR_SUBID:
+ /* TLV parse */
+ left_len =
+ resp->size - sizeof(HostCmd_DS_11AX_CMD_CFG) - S_DS_GEN;
+ // tlv = (MrvlIEtypes_Extension_t *)axcfg->val;
+ tlv = (MrvlIEtypes_Data_t *)axcmd->val;
+ while (left_len > sizeof(MrvlIEtypesHeader_t)) {
+ tlv_type = wlan_le16_to_cpu(tlv->header.type);
+ tlv_len = wlan_le16_to_cpu(tlv->header.len);
+ memcpy_ext(
+ pmadapter,
+ cfg->param.sr_cfg.param.obss_pd_offset.offset,
+ tlv->data, tlv_len, tlv_len);
+ left_len -= (sizeof(MrvlIEtypesHeader_t) + tlv_len);
+ tlv = (MrvlIEtypes_Data_t
+ *)((t_u8 *)tlv + tlv_len +
+ sizeof(MrvlIEtypesHeader_t));
+ }
+ break;
+ case MLAN_11AXCMD_BEAM_SUBID:
+ cfg->param.beam_cfg.value = *axcmd->val;
+ break;
+ case MLAN_11AXCMD_HTC_SUBID:
+ cfg->param.htc_cfg.value = *axcmd->val;
+ break;
+ case MLAN_11AXCMD_TXOPRTS_SUBID:
+ memcpy_ext(pmadapter, &cfg->param.txop_cfg.rts_thres,
+ axcmd->val, sizeof(t_u16), sizeof(t_u16));
+ break;
+ case MLAN_11AXCMD_TXOMI_SUBID:
+ memcpy_ext(pmadapter, &cfg->param.txomi_cfg.omi, axcmd->val,
+ sizeof(t_u16), sizeof(t_u16));
+ break;
+ case MLAN_11AXCMD_OBSS_TOLTIME_SUBID:
+ memcpy_ext(pmadapter, &cfg->param.toltime_cfg.tol_time,
+ axcmd->val, sizeof(t_u32), sizeof(t_u32));
+ break;
+ default:
+ PRINTM(MERROR, "Unknown subcmd %x\n", axcmd->sub_id);
+ break;
+ }
+
+done:
+ LEAVE();
+ return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ * @brief This function prepares TWT cfg command to configure
+ * setup/teardown
+ *
+ * @param pmpriv A pointer to mlan_private structure
+ * @param cmd A pointer to HostCmd_DS_COMMAND structure
+ * @param cmd_action The action: GET or SET
+ * @param pdata_buf A pointer to data buffer
+ * @return Status returned
+ */
+mlan_status wlan_cmd_twt_cfg(pmlan_private pmpriv, HostCmd_DS_COMMAND *cmd,
+ t_u16 cmd_action, t_void *pdata_buf)
+{
+ pmlan_adapter pmadapter = pmpriv->adapter;
+ HostCmd_DS_TWT_CFG *hostcmd_twtcfg =
+ (HostCmd_DS_TWT_CFG *)&cmd->params.twtcfg;
+ mlan_ds_twtcfg *ds_twtcfg = (mlan_ds_twtcfg *)pdata_buf;
+ hostcmd_twt_setup *twt_setup_params = MNULL;
+ hostcmd_twt_teardown *twt_teardown_params = MNULL;
+ mlan_status ret = MLAN_STATUS_SUCCESS;
+
+ ENTER();
+ cmd->command = wlan_cpu_to_le16(HostCmd_CMD_TWT_CFG);
+
+ hostcmd_twtcfg->action = wlan_cpu_to_le16(cmd_action);
+ hostcmd_twtcfg->sub_id = wlan_cpu_to_le16(ds_twtcfg->sub_id);
+
+ cmd->size = S_DS_GEN + sizeof(hostcmd_twtcfg->action) +
+ sizeof(hostcmd_twtcfg->sub_id);
+
+ switch (hostcmd_twtcfg->sub_id) {
+ case MLAN_11AX_TWT_SETUP_SUBID:
+ twt_setup_params = &hostcmd_twtcfg->param.twt_setup;
+ memset(pmadapter, twt_setup_params, 0x00,
+ sizeof(hostcmd_twtcfg->param.twt_setup));
+ twt_setup_params->implicit =
+ ds_twtcfg->param.twt_setup.implicit;
+ twt_setup_params->announced =
+ ds_twtcfg->param.twt_setup.announced;
+ twt_setup_params->trigger_enabled =
+ ds_twtcfg->param.twt_setup.trigger_enabled;
+ twt_setup_params->twt_info_disabled =
+ ds_twtcfg->param.twt_setup.twt_info_disabled;
+ twt_setup_params->negotiation_type =
+ ds_twtcfg->param.twt_setup.negotiation_type;
+ twt_setup_params->twt_wakeup_duration =
+ ds_twtcfg->param.twt_setup.twt_wakeup_duration;
+ twt_setup_params->flow_identifier =
+ ds_twtcfg->param.twt_setup.flow_identifier;
+ twt_setup_params->hard_constraint =
+ ds_twtcfg->param.twt_setup.hard_constraint;
+ twt_setup_params->twt_exponent =
+ ds_twtcfg->param.twt_setup.twt_exponent;
+ twt_setup_params->twt_mantissa = wlan_cpu_to_le16(
+ ds_twtcfg->param.twt_setup.twt_mantissa);
+ twt_setup_params->twt_request =
+ ds_twtcfg->param.twt_setup.twt_request;
+ cmd->size += sizeof(hostcmd_twtcfg->param.twt_setup);
+ break;
+ case MLAN_11AX_TWT_TEARDOWN_SUBID:
+ twt_teardown_params = &hostcmd_twtcfg->param.twt_teardown;
+ memset(pmadapter, twt_teardown_params, 0x00,
+ sizeof(hostcmd_twtcfg->param.twt_teardown));
+ twt_teardown_params->flow_identifier =
+ ds_twtcfg->param.twt_teardown.flow_identifier;
+ twt_teardown_params->negotiation_type =
+ ds_twtcfg->param.twt_teardown.negotiation_type;
+ twt_teardown_params->teardown_all_twt =
+ ds_twtcfg->param.twt_teardown.teardown_all_twt;
+ cmd->size += sizeof(hostcmd_twtcfg->param.twt_teardown);
+ break;
+ default:
+ PRINTM(MERROR, "Unknown subcmd %x\n", ds_twtcfg->sub_id);
+ ret = MLAN_STATUS_FAILURE;
+ break;
+ }
+
+ cmd->size = wlan_cpu_to_le16(cmd->size);
+
+ LEAVE();
+ return ret;
+}
+
+/**
+ * @brief TWT config command handler
+ *
+ * @param pmadapter A pointer to mlan_adapter structure
+ * @param pioctl_req A pointer to ioctl request buffer
+ *
+ * @return MLAN_STATUS_SUCCESS --success, otherwise fail
+ */
+mlan_status wlan_11ax_ioctl_twtcfg(pmlan_adapter pmadapter,
+ pmlan_ioctl_req pioctl_req)
+{
+ mlan_status ret = MLAN_STATUS_SUCCESS;
+ mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index];
+ mlan_ds_twtcfg *cfg = MNULL;
+ t_u16 cmd_action = 0;
+
+ ENTER();
+
+ if (pioctl_req->buf_len < sizeof(mlan_ds_twtcfg)) {
+ PRINTM(MERROR, "MLAN bss IOCTL length is too short.\n");
+ pioctl_req->data_read_written = 0;
+ pioctl_req->buf_len_needed = sizeof(mlan_ds_twtcfg);
+ pioctl_req->status_code = MLAN_ERROR_INVALID_PARAMETER;
+ LEAVE();
+ return MLAN_STATUS_RESOURCE;
+ }
+
+ cfg = (mlan_ds_twtcfg *)pioctl_req->pbuf;
+
+ if (pioctl_req->action == MLAN_ACT_SET)
+ cmd_action = HostCmd_ACT_GEN_SET;
+ else
+ cmd_action = HostCmd_ACT_GEN_GET;
+
+ /* Send request to firmware */
+ ret = wlan_prepare_cmd(pmpriv, HostCmd_CMD_TWT_CFG, cmd_action, 0,
+ (t_void *)pioctl_req, (t_void *)cfg);
+ if (ret == MLAN_STATUS_SUCCESS)
+ ret = MLAN_STATUS_PENDING;
+
+ LEAVE();
+ return ret;
+}
diff --git a/drivers/net/wireless/nxp/mxm_wifiex/wlan_src/mlan/mlan_11ax.h b/drivers/net/wireless/nxp/mxm_wifiex/wlan_src/mlan/mlan_11ax.h
new file mode 100644
index 000000000000..4e64772adfa4
--- /dev/null
+++ b/drivers/net/wireless/nxp/mxm_wifiex/wlan_src/mlan/mlan_11ax.h
@@ -0,0 +1,58 @@
+/** @file mlan_11ax.h
+ *
+ * @brief This file contains the functions for station ioctl.
+ *
+ *
+ * Copyright 2014-2020 NXP
+ *
+ * This software file (the File) is distributed by NXP
+ * under the terms of the GNU General Public License Version 2, June 1991
+ * (the License). You may use, redistribute and/or modify the 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 _MLAN_11AX_H_
+#define _MLAN_11AX_H_
+
+/** device support 2.4G 40MHZ*/
+#define AX_2G_40MHZ_SUPPORT MBIT(1)
+/** device support 2.4G 242 tone RUs */
+#define AX_2G_20MHZ_SUPPORT MBIT(5)
+
+t_u8 wlan_check_11ax_twt_supported(mlan_private *pmpriv,
+ BSSDescriptor_t *pbss_desc);
+mlan_status wlan_11ax_ioctl_twtcfg(pmlan_adapter pmadapter,
+ pmlan_ioctl_req pioctl_req);
+mlan_status wlan_cmd_twt_cfg(pmlan_private pmpriv, HostCmd_DS_COMMAND *cmd,
+ t_u16 cmd_action, t_void *pdata_buf);
+t_u16 wlan_fill_he_cap_tlv(mlan_private *pmpriv, t_u8 band,
+ MrvlIEtypes_Extension_t *phe_cap, t_u8 flag);
+void wlan_update_11ax_cap(mlan_adapter *pmadapter,
+ MrvlIEtypes_Extension_t *hw_he_cap);
+int wlan_cmd_append_11ax_tlv(mlan_private *pmpriv, BSSDescriptor_t *pbss_desc,
+ t_u8 **ppbuffer);
+t_u16 wlan_11ax_bandconfig_allowed(mlan_private *pmpriv, t_u16 bss_band);
+mlan_status wlan_11ax_cfg_ioctl(pmlan_adapter pmadapter,
+ pmlan_ioctl_req pioctl_req);
+mlan_status wlan_11ax_ioctl_cmd(pmlan_adapter pmadapter,
+ pmlan_ioctl_req pioctl_req);
+
+mlan_status wlan_cmd_11ax_cfg(pmlan_private pmpriv, HostCmd_DS_COMMAND *cmd,
+ t_u16 cmd_action, t_void *pdata_buf);
+mlan_status wlan_ret_11ax_cfg(pmlan_private pmpriv, HostCmd_DS_COMMAND *resp,
+ mlan_ioctl_req *pioctl_buf);
+mlan_status wlan_cmd_11ax_cmd(pmlan_private pmpriv, HostCmd_DS_COMMAND *cmd,
+ t_u16 cmd_action, t_void *pdata_buf);
+mlan_status wlan_ret_11ax_cmd(pmlan_private pmpriv, HostCmd_DS_COMMAND *resp,
+ mlan_ioctl_req *pioctl_buf);
+
+#endif /* _MLAN_11AX_H_ */
diff --git a/drivers/net/wireless/nxp/mxm_wifiex/wlan_src/mlan/mlan_11d.c b/drivers/net/wireless/nxp/mxm_wifiex/wlan_src/mlan/mlan_11d.c
new file mode 100644
index 000000000000..a9ac930eb2dd
--- /dev/null
+++ b/drivers/net/wireless/nxp/mxm_wifiex/wlan_src/mlan/mlan_11d.c
@@ -0,0 +1,1590 @@
+/** @file mlan_11d.c
+ *
+ * @brief This file contains functions for 802.11D.
+ *
+ *
+ * Copyright 2014-2020 NXP
+ *
+ * This software file (the File) is distributed by NXP
+ * under the terms of the GNU General Public License Version 2, June 1991
+ * (the License). You may use, redistribute and/or modify the 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.
+ *
+ */
+/********************************************************
+Change log:
+ 10/21/2008: initial version
+********************************************************/
+
+#include "mlan.h"
+#include "mlan_join.h"
+#include "mlan_util.h"
+#include "mlan_fw.h"
+#include "mlan_main.h"
+#include "mlan_11h.h"
+
+/********************************************************
+ Local Variables
+********************************************************/
+
+#ifdef STA_SUPPORT
+/** Region code mapping */
+typedef struct _region_code_mapping {
+ /** Region */
+ t_u8 region[COUNTRY_CODE_LEN];
+ /** Code */
+ t_u8 code;
+} region_code_mapping_t;
+
+/** Region code mapping table */
+static region_code_mapping_t region_code_mapping[] = {
+ {"US ", 0x10}, /* US FCC */
+ {"CA ", 0x20}, /* IC Canada */
+ {"SG ", 0x10}, /* Singapore */
+ {"EU ", 0x30}, /* ETSI */
+ {"AU ", 0x30}, /* Australia */
+ {"KR ", 0x30}, /* Republic Of Korea */
+ {"FR ", 0x32}, /* France */
+ {"JP ", 0x40}, /* Japan */
+ {"JP ", 0x41}, /* Japan */
+ {"CN ", 0x50}, /* China */
+ {"JP ", 0xFE}, /* Japan */
+ {"JP ", 0xFF}, /* Japan special */
+ {"NE ", 0x30}, /* New Zeland */
+};
+
+/** Universal region code */
+#define UNIVERSAL_REGION_CODE 0xff
+#endif
+
+/** Default Tx power */
+#define TX_PWR_DEFAULT 10
+
+/* Following two structures define the supported channels */
+/** Channels for 802.11b/g */
+static chan_freq_power_t channel_freq_power_UN_BG[] = {
+ {1, 2412, TX_PWR_DEFAULT}, {2, 2417, TX_PWR_DEFAULT},
+ {3, 2422, TX_PWR_DEFAULT}, {4, 2427, TX_PWR_DEFAULT},
+ {5, 2432, TX_PWR_DEFAULT}, {6, 2437, TX_PWR_DEFAULT},
+ {7, 2442, TX_PWR_DEFAULT}, {8, 2447, TX_PWR_DEFAULT},
+ {9, 2452, TX_PWR_DEFAULT}, {10, 2457, TX_PWR_DEFAULT},
+ {11, 2462, TX_PWR_DEFAULT}, {12, 2467, TX_PWR_DEFAULT},
+ {13, 2472, TX_PWR_DEFAULT}, {14, 2484, TX_PWR_DEFAULT}};
+
+/** Channels for 802.11a/j */
+static chan_freq_power_t channel_freq_power_UN_AJ[] = {
+ {8, 5040, TX_PWR_DEFAULT}, {12, 5060, TX_PWR_DEFAULT},
+ {16, 5080, TX_PWR_DEFAULT}, {34, 5170, TX_PWR_DEFAULT},
+ {38, 5190, TX_PWR_DEFAULT}, {42, 5210, TX_PWR_DEFAULT},
+ {46, 5230, TX_PWR_DEFAULT}, {36, 5180, TX_PWR_DEFAULT},
+ {40, 5200, TX_PWR_DEFAULT}, {44, 5220, TX_PWR_DEFAULT},
+ {48, 5240, TX_PWR_DEFAULT}, {52, 5260, TX_PWR_DEFAULT},
+ {56, 5280, TX_PWR_DEFAULT}, {60, 5300, TX_PWR_DEFAULT},
+ {64, 5320, TX_PWR_DEFAULT}, {100, 5500, TX_PWR_DEFAULT},
+ {104, 5520, TX_PWR_DEFAULT}, {108, 5540, TX_PWR_DEFAULT},
+ {112, 5560, TX_PWR_DEFAULT}, {116, 5580, TX_PWR_DEFAULT},
+ {120, 5600, TX_PWR_DEFAULT}, {124, 5620, TX_PWR_DEFAULT},
+ {128, 5640, TX_PWR_DEFAULT}, {132, 5660, TX_PWR_DEFAULT},
+ {136, 5680, TX_PWR_DEFAULT}, {140, 5700, TX_PWR_DEFAULT},
+ {149, 5745, TX_PWR_DEFAULT}, {153, 5765, TX_PWR_DEFAULT},
+ {157, 5785, TX_PWR_DEFAULT}, {161, 5805, TX_PWR_DEFAULT},
+ {165, 5825, TX_PWR_DEFAULT},
+ /* {240, 4920, TX_PWR_DEFAULT},
+ {244, 4940, TX_PWR_DEFAULT},
+ {248, 4960, TX_PWR_DEFAULT},
+ {252, 4980, TX_PWR_DEFAULT},
+ channels for 11J JP 10M channel gap */
+};
+
+/********************************************************
+ Global Variables
+********************************************************/
+
+/********************************************************
+ Local Functions
+********************************************************/
+#ifdef STA_SUPPORT
+/**
+ * @brief This function converts integer code to region string
+ *
+ * @param pmadapter A pointer to mlan_adapter structure
+ * @param code Region code
+ *
+ * @return Region string
+ */
+static t_u8 *wlan_11d_code_2_region(pmlan_adapter pmadapter, t_u8 code)
+{
+ t_u8 i;
+
+ ENTER();
+
+ /* Look for code in mapping table */
+ for (i = 0; i < NELEMENTS(region_code_mapping); i++) {
+ if (region_code_mapping[i].code == code) {
+ LEAVE();
+ return region_code_mapping[i].region;
+ }
+ }
+
+ LEAVE();
+ /* Default is US */
+ return region_code_mapping[0].region;
+}
+
+/**
+ * @brief This function Checks if channel txpwr is learned from AP/IBSS
+ *
+ * @param pmadapter A pointer to mlan_adapter structure
+ * @param band Band number
+ * @param chan Channel number
+ * @param parsed_region_chan Pointer to parsed_region_chan_11d_t
+ *
+ * @return MTRUE or MFALSE
+ */
+static t_u8 wlan_11d_channel_known(pmlan_adapter pmadapter, t_u8 band,
+ t_u8 chan,
+ parsed_region_chan_11d_t *parsed_region_chan)
+{
+ chan_power_11d_t *pchan_pwr = parsed_region_chan->chan_pwr;
+ t_u8 no_of_chan = parsed_region_chan->no_of_chan;
+ t_u8 i = 0;
+ t_u8 ret = MFALSE;
+ mlan_private *pmpriv;
+
+ ENTER();
+
+ HEXDUMP("11D: parsed_region_chan", (t_u8 *)pchan_pwr,
+ sizeof(chan_power_11d_t) * no_of_chan);
+
+ /* Search channel */
+ for (i = 0; i < no_of_chan; i++) {
+ if (chan == pchan_pwr[i].chan && band == pchan_pwr[i].band) {
+ PRINTM(MINFO, "11D: Found channel:%d (band:%d)\n", chan,
+ band);
+ ret = MTRUE;
+
+ if (band & BAND_A) {
+ /* If chan is a DFS channel, we need to see an
+ * AP on it */
+ pmpriv = wlan_get_priv(pmadapter,
+ MLAN_BSS_ROLE_STA);
+ if (pmpriv && wlan_11h_radar_detect_required(
+ pmpriv, chan)) {
+ PRINTM(MINFO,
+ "11H: DFS channel %d, and ap_seen=%d\n",
+ chan, pchan_pwr[i].ap_seen);
+ ret = pchan_pwr[i].ap_seen;
+ }
+ }
+
+ LEAVE();
+ return ret;
+ }
+ }
+
+ PRINTM(MINFO, "11D: Could not find channel:%d (band:%d)\n", chan, band);
+ LEAVE();
+ return ret;
+}
+
+/**
+ * @brief This function generates parsed_region_chan from Domain Info
+ * learned from AP/IBSS
+ *
+ * @param pmadapter Pointer to mlan_adapter structure
+ * @param region_chan Pointer to region_chan_t
+ * @param parsed_region_chan Pointer to parsed_region_chan_11d_t
+ *
+ * @return N/A
+ */
+static t_void wlan_11d_generate_parsed_region_chan(
+ pmlan_adapter pmadapter, region_chan_t *region_chan,
+ parsed_region_chan_11d_t *parsed_region_chan)
+{
+ chan_freq_power_t *cfp;
+ t_u8 i;
+
+ ENTER();
+
+ /* Region channel must be provided */
+ if (!region_chan) {
+ PRINTM(MWARN, "11D: region_chan is MNULL\n");
+ LEAVE();
+ return;
+ }
+
+ /* Get channel-frequency-power trio */
+ cfp = region_chan->pcfp;
+ if (!cfp) {
+ PRINTM(MWARN, "11D: cfp equal MNULL\n");
+ LEAVE();
+ return;
+ }
+
+ /* Set channel, band and power */
+ for (i = 0; i < region_chan->num_cfp; i++, cfp++) {
+ parsed_region_chan->chan_pwr[i].chan = (t_u8)cfp->channel;
+ parsed_region_chan->chan_pwr[i].band = region_chan->band;
+ parsed_region_chan->chan_pwr[i].pwr = (t_u8)cfp->max_tx_power;
+ PRINTM(MINFO, "11D: Chan[%d] Band[%d] Pwr[%d]\n",
+ parsed_region_chan->chan_pwr[i].chan,
+ parsed_region_chan->chan_pwr[i].band,
+ parsed_region_chan->chan_pwr[i].pwr);
+ }
+ parsed_region_chan->no_of_chan = region_chan->num_cfp;
+
+ PRINTM(MINFO, "11D: no_of_chan[%d]\n", parsed_region_chan->no_of_chan);
+
+ LEAVE();
+ return;
+}
+
+/**
+ * @brief This function generates domain_info from parsed_region_chan
+ *
+ * @param pmadapter Pointer to mlan_adapter structure
+ * @param parsed_region_chan Pointer to parsed_region_chan_11d_t
+ *
+ * @return MLAN_STATUS_SUCCESS
+ */
+static mlan_status
+wlan_11d_generate_domain_info(pmlan_adapter pmadapter,
+ parsed_region_chan_11d_t *parsed_region_chan)
+{
+ t_u8 no_of_sub_band = 0;
+ t_u8 no_of_chan = parsed_region_chan->no_of_chan;
+ t_u8 no_of_parsed_chan = 0;
+ t_u8 first_chan = 0, next_chan = 0, max_pwr = 0;
+ t_u8 i, flag = MFALSE;
+ wlan_802_11d_domain_reg_t *domain_info = &pmadapter->domain_reg;
+
+ ENTER();
+
+ /* Should be only place that clear domain_reg (besides init) */
+ memset(pmadapter, domain_info, 0, sizeof(wlan_802_11d_domain_reg_t));
+
+ /* Set country code */
+ memcpy_ext(pmadapter, domain_info->country_code,
+ wlan_11d_code_2_region(pmadapter,
+ (t_u8)pmadapter->region_code),
+ COUNTRY_CODE_LEN, COUNTRY_CODE_LEN);
+
+ PRINTM(MINFO, "11D: Number of channel = %d\n", no_of_chan);
+ HEXDUMP("11D: parsed_region_chan", (t_u8 *)parsed_region_chan,
+ sizeof(parsed_region_chan_11d_t));
+
+ /* Set channel and power */
+ for (i = 0; i < no_of_chan; i++) {
+ if (!flag) {
+ flag = MTRUE;
+ next_chan = first_chan =
+ parsed_region_chan->chan_pwr[i].chan;
+ max_pwr = parsed_region_chan->chan_pwr[i].pwr;
+ no_of_parsed_chan = 1;
+ continue;
+ }
+
+ if (parsed_region_chan->chan_pwr[i].chan == next_chan + 1 &&
+ parsed_region_chan->chan_pwr[i].pwr == max_pwr) {
+ next_chan++;
+ no_of_parsed_chan++;
+ } else {
+ domain_info->sub_band[no_of_sub_band].first_chan =
+ first_chan;
+ domain_info->sub_band[no_of_sub_band].no_of_chan =
+ no_of_parsed_chan;
+ domain_info->sub_band[no_of_sub_band].max_tx_pwr =
+ max_pwr;
+ no_of_sub_band++;
+ no_of_parsed_chan = 1;
+ next_chan = first_chan =
+ parsed_region_chan->chan_pwr[i].chan;
+ max_pwr = parsed_region_chan->chan_pwr[i].pwr;
+ }
+ }
+
+ if (flag) {
+ domain_info->sub_band[no_of_sub_band].first_chan = first_chan;
+ domain_info->sub_band[no_of_sub_band].no_of_chan =
+ no_of_parsed_chan;
+ domain_info->sub_band[no_of_sub_band].max_tx_pwr = max_pwr;
+ no_of_sub_band++;
+ }
+ domain_info->no_of_sub_band = no_of_sub_band;
+
+ PRINTM(MINFO, "11D: Number of sub-band =0x%x\n",
+ domain_info->no_of_sub_band);
+ HEXDUMP("11D: domain_info", (t_u8 *)domain_info,
+ COUNTRY_CODE_LEN + 1 +
+ sizeof(IEEEtypes_SubbandSet_t) * no_of_sub_band);
+ LEAVE();
+ return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ * @brief This function updates the channel power table with the channel
+ * present in BSSDescriptor.
+ *
+ * @param pmpriv A pointer to mlan_private structure
+ * @param pbss_desc A pointer to BSSDescriptor_t
+ *
+ * @return MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ */
+static mlan_status wlan_11d_update_chan_pwr_table(mlan_private *pmpriv,
+ BSSDescriptor_t *pbss_desc)
+{
+ mlan_adapter *pmadapter = pmpriv->adapter;
+ parsed_region_chan_11d_t *parsed_region_chan =
+ &pmadapter->parsed_region_chan;
+ t_u16 i;
+ t_u8 tx_power = 0;
+ t_u8 chan;
+
+ ENTER();
+
+ chan = pbss_desc->phy_param_set.ds_param_set.current_chan;
+
+ tx_power = wlan_get_txpwr_of_chan_from_cfp(pmpriv, chan);
+
+ if (!tx_power) {
+ PRINTM(MMSG, "11D: Invalid channel\n");
+ LEAVE();
+ return MLAN_STATUS_FAILURE;
+ }
+
+ /* Check whether the channel already exists in channel power table of
+ parsed region */
+ for (i = 0;
+ ((i < parsed_region_chan->no_of_chan) && (i < MAX_NO_OF_CHAN));
+ i++) {
+ if (parsed_region_chan->chan_pwr[i].chan == chan &&
+ parsed_region_chan->chan_pwr[i].band ==
+ pbss_desc->bss_band) {
+ /* Channel already exists, use minimum of existing and
+ tx_power */
+ parsed_region_chan->chan_pwr[i].pwr = MIN(
+ parsed_region_chan->chan_pwr[i].pwr, tx_power);
+ parsed_region_chan->chan_pwr[i].ap_seen = MTRUE;
+ break;
+ }
+ }
+
+ if (i == parsed_region_chan->no_of_chan && i < MAX_NO_OF_CHAN) {
+ /* Channel not found. Update the channel in the channel-power
+ table */
+ parsed_region_chan->chan_pwr[i].chan = chan;
+ parsed_region_chan->chan_pwr[i].band =
+ (t_u8)pbss_desc->bss_band;
+ parsed_region_chan->chan_pwr[i].pwr = tx_power;
+ parsed_region_chan->chan_pwr[i].ap_seen = MTRUE;
+ parsed_region_chan->no_of_chan++;
+ }
+
+ LEAVE();
+ return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ * @brief This function finds the no_of_chan-th chan after the first_chan
+ *
+ * @param pmadapter A pointer to mlan_adapter structure
+ * @param band Band
+ * @param first_chan First channel number
+ * @param no_of_chan Number of channels
+ * @param chan Pointer to the returned no_of_chan-th chan number
+ *
+ * @return MTRUE or MFALSE
+ */
+static t_u8 wlan_11d_get_chan(pmlan_adapter pmadapter, t_u8 band,
+ t_u8 first_chan, t_u8 no_of_chan, t_u8 *chan)
+{
+ chan_freq_power_t *cfp = MNULL;
+ t_u8 i;
+ t_u8 cfp_no = 0;
+
+ ENTER();
+ if (band & (BAND_B | BAND_G | BAND_GN | BAND_GAC)) {
+ cfp = channel_freq_power_UN_BG;
+ cfp_no = NELEMENTS(channel_freq_power_UN_BG);
+ } else if (band & (BAND_A | BAND_AN | BAND_AAC)) {
+ cfp = channel_freq_power_UN_AJ;
+ cfp_no = NELEMENTS(channel_freq_power_UN_AJ);
+ } else {
+ PRINTM(MERROR, "11D: Wrong Band[%d]\n", band);
+ LEAVE();
+ return MFALSE;
+ }
+ /* Locate the first_chan */
+ for (i = 0; i < cfp_no; i++) {
+ if (cfp && ((cfp + i)->channel == first_chan)) {
+ PRINTM(MINFO, "11D: first_chan found\n");
+ break;
+ }
+ }
+
+ if (i < cfp_no) {
+ /* Check if beyond the boundary */
+ if (i + no_of_chan < cfp_no) {
+ /* Get first_chan + no_of_chan */
+ *chan = (t_u8)(cfp + i + no_of_chan)->channel;
+ LEAVE();
+ return MTRUE;
+ }
+ }
+
+ LEAVE();
+ return MFALSE;
+}
+
+/**
+ * @brief This function processes the country info present in BSSDescriptor.
+ *
+ * @param pmpriv A pointer to mlan_private structure
+ * @param pbss_desc A pointer to BSSDescriptor_t
+ *
+ * @return MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ */
+static mlan_status wlan_11d_process_country_info(mlan_private *pmpriv,
+ BSSDescriptor_t *pbss_desc)
+{
+ mlan_adapter *pmadapter = pmpriv->adapter;
+ parsed_region_chan_11d_t region_chan;
+ parsed_region_chan_11d_t *parsed_region_chan =
+ &pmadapter->parsed_region_chan;
+ t_u16 i, j, num_chan_added = 0;
+
+ ENTER();
+
+ memset(pmadapter, &region_chan, 0, sizeof(parsed_region_chan_11d_t));
+
+ /* Parse 11D country info */
+ if (wlan_11d_parse_domain_info(pmadapter, &pbss_desc->country_info,
+ (t_u8)pbss_desc->bss_band,
+ &region_chan) != MLAN_STATUS_SUCCESS) {
+ LEAVE();
+ return MLAN_STATUS_FAILURE;
+ }
+
+ if (parsed_region_chan->no_of_chan != 0) {
+ /*
+ * Check if the channel number already exists in the
+ * chan-power table of parsed_region_chan
+ */
+ for (i = 0; (i < region_chan.no_of_chan && i < MAX_NO_OF_CHAN);
+ i++) {
+ for (j = 0; (j < parsed_region_chan->no_of_chan &&
+ j < MAX_NO_OF_CHAN);
+ j++) {
+ /*
+ * Channel already exists, update the tx power
+ * with new tx power, since country IE is valid
+ * here.
+ */
+ if (region_chan.chan_pwr[i].chan ==
+ parsed_region_chan->chan_pwr[j]
+ .chan &&
+ region_chan.chan_pwr[i].band ==
+ parsed_region_chan->chan_pwr[j]
+ .band) {
+ parsed_region_chan->chan_pwr[j].pwr =
+ region_chan.chan_pwr[i].pwr;
+ break;
+ }
+ }
+
+ if (j == parsed_region_chan->no_of_chan &&
+ (j + num_chan_added) < MAX_NO_OF_CHAN) {
+ /*
+ * Channel does not exist in the channel power
+ * table, update this new chan and tx_power
+ * to the channel power table
+ */
+ parsed_region_chan
+ ->chan_pwr[parsed_region_chan
+ ->no_of_chan +
+ num_chan_added]
+ .chan = region_chan.chan_pwr[i].chan;
+ parsed_region_chan
+ ->chan_pwr[parsed_region_chan
+ ->no_of_chan +
+ num_chan_added]
+ .band = region_chan.chan_pwr[i].band;
+ parsed_region_chan
+ ->chan_pwr[parsed_region_chan
+ ->no_of_chan +
+ num_chan_added]
+ .pwr = region_chan.chan_pwr[i].pwr;
+ parsed_region_chan
+ ->chan_pwr[parsed_region_chan
+ ->no_of_chan +
+ num_chan_added]
+ .ap_seen = MFALSE;
+ num_chan_added++;
+ }
+ }
+ parsed_region_chan->no_of_chan += num_chan_added;
+ } else {
+ /* Parsed region is empty, copy the first one */
+ memcpy_ext(pmadapter, parsed_region_chan, &region_chan,
+ sizeof(parsed_region_chan_11d_t),
+ sizeof(parsed_region_chan_11d_t));
+ }
+
+ LEAVE();
+ return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ * @brief This helper function copies chan_power_11d_t element
+ *
+ * @param chan_dst Pointer to destination of chan_power
+ * @param chan_src Pointer to source of chan_power
+ *
+ * @return N/A
+ */
+static t_void wlan_11d_copy_chan_power(chan_power_11d_t *chan_dst,
+ chan_power_11d_t *chan_src)
+{
+ ENTER();
+
+ chan_dst->chan = chan_src->chan;
+ chan_dst->band = chan_src->band;
+ chan_dst->pwr = chan_src->pwr;
+ chan_dst->ap_seen = chan_src->ap_seen;
+
+ LEAVE();
+ return;
+}
+
+/**
+ * @brief This function sorts parsed_region_chan in ascending
+ * channel number.
+ *
+ * @param parsed_region_chan Pointer to parsed_region_chan_11d_t
+ *
+ * @return N/A
+ */
+static t_void
+wlan_11d_sort_parsed_region_chan(parsed_region_chan_11d_t *parsed_region_chan)
+{
+ int i, j;
+ chan_power_11d_t temp;
+ chan_power_11d_t *pchan_power = parsed_region_chan->chan_pwr;
+
+ ENTER();
+
+ PRINTM(MINFO, "11D: Number of channel = %d\n",
+ parsed_region_chan->no_of_chan);
+
+ /* Use insertion sort method */
+ for (i = 1; i < parsed_region_chan->no_of_chan; i++) {
+ wlan_11d_copy_chan_power(&temp, pchan_power + i);
+ for (j = i; j > 0 && (pchan_power + j - 1)->chan > temp.chan;
+ j--)
+ wlan_11d_copy_chan_power(pchan_power + j,
+ pchan_power + j - 1);
+ wlan_11d_copy_chan_power(pchan_power + j, &temp);
+ }
+
+ HEXDUMP("11D: parsed_region_chan", (t_u8 *)parsed_region_chan,
+ sizeof(parsed_region_chan_11d_t));
+
+ LEAVE();
+ return;
+}
+#endif /* STA_SUPPORT */
+
+/**
+ * @brief This function sends domain info to FW
+ *
+ * @param pmpriv A pointer to mlan_private structure
+ * @param pioctl_buf A pointer to MLAN IOCTL Request buffer
+ *
+ * @return MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ */
+static mlan_status wlan_11d_send_domain_info(mlan_private *pmpriv,
+ t_void *pioctl_buf)
+{
+ mlan_status ret = MLAN_STATUS_SUCCESS;
+
+ ENTER();
+
+ /* Send cmd to FW to set domain info */
+ ret = wlan_prepare_cmd(pmpriv, HostCmd_CMD_802_11D_DOMAIN_INFO,
+ HostCmd_ACT_GEN_SET, 0, (t_void *)pioctl_buf,
+ MNULL);
+ if (ret)
+ PRINTM(MERROR, "11D: Failed to download domain Info\n");
+
+ LEAVE();
+ return ret;
+}
+
+/**
+ * @brief This function overwrites domain_info
+ *
+ * @param pmadapter Pointer to mlan_adapter structure
+ * @param band Intended operating band
+ * @param country_code Intended country code
+ * @param num_sub_band Count of tuples in list below
+ * @param sub_band_list List of sub_band tuples
+ *
+ * @return MLAN_STATUS_SUCCESS
+ */
+static mlan_status
+wlan_11d_set_domain_info(mlan_private *pmpriv, t_u8 band,
+ t_u8 country_code[COUNTRY_CODE_LEN], t_u8 num_sub_band,
+ IEEEtypes_SubbandSet_t *sub_band_list)
+{
+ mlan_adapter *pmadapter = pmpriv->adapter;
+ wlan_802_11d_domain_reg_t *pdomain = &pmadapter->domain_reg;
+ mlan_status ret = MLAN_STATUS_SUCCESS;
+
+ ENTER();
+
+ memset(pmadapter, pdomain, 0, sizeof(wlan_802_11d_domain_reg_t));
+ memcpy_ext(pmadapter, pdomain->country_code, country_code,
+ COUNTRY_CODE_LEN, COUNTRY_CODE_LEN);
+ pdomain->band = band;
+ pdomain->no_of_sub_band = num_sub_band;
+ memcpy_ext(pmadapter, pdomain->sub_band, sub_band_list,
+ num_sub_band * sizeof(IEEEtypes_SubbandSet_t),
+ MRVDRV_MAX_SUBBAND_802_11D * sizeof(IEEEtypes_SubbandSet_t));
+
+ LEAVE();
+ return ret;
+}
+
+/********************************************************
+ Global functions
+********************************************************/
+
+/**
+ * @brief This function gets if priv is a station (STA)
+ *
+ * @param pmpriv Pointer to mlan_private structure
+ *
+ * @return MTRUE or MFALSE
+ */
+t_bool wlan_is_station(mlan_private *pmpriv)
+{
+ ENTER();
+ LEAVE();
+ return (GET_BSS_ROLE(pmpriv) == MLAN_BSS_ROLE_STA) ? MTRUE : MFALSE;
+}
+
+/**
+ * @brief This function gets if 11D is enabled
+ *
+ * @param pmpriv Pointer to mlan_private structure
+ *
+ * @return MTRUE or MFALSE
+ */
+t_bool wlan_11d_is_enabled(mlan_private *pmpriv)
+{
+ ENTER();
+ LEAVE();
+ return (pmpriv->state_11d.enable_11d == ENABLE_11D &&
+ pmpriv->state_11d.user_enable_11d == ENABLE_11D) ?
+ MTRUE :
+ MFALSE;
+}
+
+/**
+ * @brief This function gets if 11D is enabled in FW
+ *
+ * @param pmpriv Pointer to mlan_private structure
+ *
+ * @return MTRUE or MFALSE
+ */
+t_bool wlan_fw_11d_is_enabled(mlan_private *pmpriv)
+{
+ ENTER();
+ LEAVE();
+ return (pmpriv->state_11d.enable_11d == ENABLE_11D) ? MTRUE : MFALSE;
+}
+
+/**
+ * @brief Initialize interface variable for 11D
+ *
+ * @param pmpriv Pointer to mlan_private structure
+ *
+ * @return N/A
+ */
+t_void wlan_11d_priv_init(mlan_private *pmpriv)
+{
+ wlan_802_11d_state_t *state = &pmpriv->state_11d;
+
+ ENTER();
+
+ /* Start in disabled mode */
+ state->enable_11d = DISABLE_11D;
+ if (!pmpriv->adapter->init_para.cfg_11d)
+ state->user_enable_11d = DEFAULT_11D_STATE;
+ else
+ state->user_enable_11d = (pmpriv->adapter->init_para.cfg_11d ==
+ MLAN_INIT_PARA_DISABLED) ?
+ DISABLE_11D :
+ ENABLE_11D;
+
+ LEAVE();
+ return;
+}
+
+/**
+ * @brief Initialize device variable for 11D
+ *
+ * @param pmadapter Pointer to mlan_adapter structure
+ *
+ * @return N/A
+ */
+t_void wlan_11d_init(mlan_adapter *pmadapter)
+{
+ ENTER();
+
+#ifdef STA_SUPPORT
+ memset(pmadapter, &(pmadapter->parsed_region_chan), 0,
+ sizeof(parsed_region_chan_11d_t));
+ memset(pmadapter, &(pmadapter->universal_channel), 0,
+ sizeof(region_chan_t));
+#endif
+ memset(pmadapter, &(pmadapter->domain_reg), 0,
+ sizeof(wlan_802_11d_domain_reg_t));
+
+ LEAVE();
+ return;
+}
+
+/**
+ * @brief This function enable/disable 11D
+ *
+ * @param pmpriv A pointer to mlan_private structure
+ * @param pioctl_buf A pointer to MLAN IOCTL Request buffer
+ * @param flag 11D status
+ *
+ * @return MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ */
+mlan_status wlan_11d_enable(mlan_private *pmpriv, t_void *pioctl_buf,
+ state_11d_t flag)
+{
+#ifdef STA_SUPPORT
+ mlan_adapter *pmadapter = pmpriv->adapter;
+#endif
+ mlan_status ret = MLAN_STATUS_SUCCESS;
+ state_11d_t enable = flag;
+
+ ENTER();
+
+ /* Send cmd to FW to enable/disable 11D function */
+ ret = wlan_prepare_cmd(pmpriv, HostCmd_CMD_802_11_SNMP_MIB,
+ HostCmd_ACT_GEN_SET, Dot11D_i,
+ (t_void *)pioctl_buf, &enable);
+
+ if (ret) {
+ PRINTM(MERROR, "11D: Failed to %s 11D\n",
+ (flag) ? "enable" : "disable");
+ }
+#ifdef STA_SUPPORT
+ else {
+ /* clear parsed table regardless of flag */
+ memset(pmadapter, &(pmadapter->parsed_region_chan), 0,
+ sizeof(parsed_region_chan_11d_t));
+ }
+#endif
+
+ LEAVE();
+ return ret;
+}
+
+/**
+ * @brief This function implements command CMD_802_11D_DOMAIN_INFO
+ *
+ * @param pmpriv A pointer to mlan_private structure
+ * @param pcmd A pointer to HostCmd_DS_COMMAND structure of
+ * command buffer
+ * @param cmd_action Command action
+ *
+ * @return MLAN_STATUS_SUCCESS
+ */
+mlan_status wlan_cmd_802_11d_domain_info(mlan_private *pmpriv,
+ HostCmd_DS_COMMAND *pcmd,
+ t_u16 cmd_action)
+{
+ mlan_adapter *pmadapter = pmpriv->adapter;
+ HostCmd_DS_802_11D_DOMAIN_INFO *pdomain_info =
+ &pcmd->params.domain_info;
+ MrvlIEtypes_DomainParamSet_t *domain = &pdomain_info->domain;
+ t_u8 no_of_sub_band = pmadapter->domain_reg.no_of_sub_band;
+ t_u8 i;
+
+ ENTER();
+ PRINTM(MCMND, "11D:Country=%c%c band=%d sub-band=5d\n",
+ pmadapter->domain_reg.country_code[0],
+ pmadapter->domain_reg.country_code[1],
+ pmadapter->domain_reg.band, no_of_sub_band);
+ for (i = 0; i < no_of_sub_band; i++) {
+ PRINTM(MCMND,
+ "11D: first chan=%d no_of_chan=%d, max_tx_pwr=%d\n",
+ pmadapter->domain_reg.sub_band[i].first_chan,
+ pmadapter->domain_reg.sub_band[i].no_of_chan,
+ pmadapter->domain_reg.sub_band[i].max_tx_pwr);
+ }
+
+ pcmd->command = wlan_cpu_to_le16(HostCmd_CMD_802_11D_DOMAIN_INFO);
+ pdomain_info->action = wlan_cpu_to_le16(cmd_action);
+ if (cmd_action == HostCmd_ACT_GEN_GET) {
+ /* Dump domain info */
+ pcmd->size = wlan_cpu_to_le16(sizeof(pdomain_info->action) +
+ S_DS_GEN);
+ HEXDUMP("11D: 802_11D_DOMAIN_INFO", (t_u8 *)pcmd,
+ wlan_le16_to_cpu(pcmd->size));
+ LEAVE();
+ return MLAN_STATUS_SUCCESS;
+ }
+
+ /* Set domain info fields */
+ domain->header.type = wlan_cpu_to_le16(TLV_TYPE_DOMAIN);
+ memcpy_ext(pmadapter, domain->country_code,
+ pmadapter->domain_reg.country_code,
+ sizeof(domain->country_code), sizeof(domain->country_code));
+
+ domain->header.len =
+ ((no_of_sub_band * sizeof(IEEEtypes_SubbandSet_t)) +
+ sizeof(domain->country_code));
+
+ if (no_of_sub_band) {
+ memcpy_ext(pmadapter, domain->sub_band,
+ pmadapter->domain_reg.sub_band,
+ no_of_sub_band * sizeof(IEEEtypes_SubbandSet_t),
+ MRVDRV_MAX_SUBBAND_802_11D *
+ sizeof(IEEEtypes_SubbandSet_t));
+
+ pcmd->size = wlan_cpu_to_le16(
+ sizeof(pdomain_info->action) + domain->header.len +
+ sizeof(MrvlIEtypesHeader_t) + S_DS_GEN);
+ } else {
+ pcmd->size = wlan_cpu_to_le16(sizeof(pdomain_info->action) +
+ S_DS_GEN);
+ }
+ domain->header.len = wlan_cpu_to_le16(domain->header.len);
+
+ HEXDUMP("11D: 802_11D_DOMAIN_INFO", (t_u8 *)pcmd,
+ wlan_le16_to_cpu(pcmd->size));
+
+ LEAVE();
+ return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ * @brief This function handle response of CMD_802_11D_DOMAIN_INFO
+ *
+ * @param pmpriv A pointer to mlan_private structure
+ * @param resp Pointer to command response buffer
+ *
+ * @return MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ */
+mlan_status wlan_ret_802_11d_domain_info(mlan_private *pmpriv,
+ HostCmd_DS_COMMAND *resp)
+{
+ mlan_status ret = MLAN_STATUS_SUCCESS;
+ HostCmd_DS_802_11D_DOMAIN_INFO_RSP *domain_info =
+ &resp->params.domain_info_resp;
+ MrvlIEtypes_DomainParamSet_t *domain = &domain_info->domain;
+ t_u16 action = wlan_le16_to_cpu(domain_info->action);
+ t_u8 no_of_sub_band = 0;
+
+ ENTER();
+
+ /* Dump domain info response data */
+ HEXDUMP("11D: DOMAIN Info Rsp Data", (t_u8 *)resp, resp->size);
+
+ no_of_sub_band = (t_u8)(
+ (wlan_le16_to_cpu(domain->header.len) - COUNTRY_CODE_LEN) /
+ sizeof(IEEEtypes_SubbandSet_t));
+
+ PRINTM(MINFO, "11D Domain Info Resp: number of sub-band=%d\n",
+ no_of_sub_band);
+
+ if (no_of_sub_band > MRVDRV_MAX_SUBBAND_802_11D) {
+ PRINTM(MWARN, "11D: Invalid number of subbands %d returned!!\n",
+ no_of_sub_band);
+ LEAVE();
+ return MLAN_STATUS_FAILURE;
+ }
+
+ switch (action) {
+ case HostCmd_ACT_GEN_SET: /* Proc Set Action */
+ break;
+ case HostCmd_ACT_GEN_GET:
+ break;
+ default:
+ PRINTM(MERROR, "11D: Invalid Action:%d\n", domain_info->action);
+ ret = MLAN_STATUS_FAILURE;
+ break;
+ }
+
+ LEAVE();
+ return ret;
+}
+
+/**
+ * @brief This function converts channel to frequency
+ *
+ * @param pmadapter A pointer to mlan_adapter structure
+ * @param chan Channel number
+ * @param band Band
+ *
+ * @return Channel frequency
+ */
+t_u32 wlan_11d_chan_2_freq(pmlan_adapter pmadapter, t_u8 chan, t_u8 band)
+{
+ chan_freq_power_t *cf;
+ t_u16 cnt;
+ t_u16 i;
+ t_u32 freq = 0;
+
+ ENTER();
+
+ /* Get channel-frequency-power trios */
+ if (band & (BAND_A | BAND_AN | BAND_AAC)) {
+ cf = channel_freq_power_UN_AJ;
+ cnt = NELEMENTS(channel_freq_power_UN_AJ);
+ } else {
+ cf = channel_freq_power_UN_BG;
+ cnt = NELEMENTS(channel_freq_power_UN_BG);
+ }
+
+ /* Locate channel and return corresponding frequency */
+ for (i = 0; i < cnt; i++) {
+ if (chan == cf[i].channel)
+ freq = cf[i].freq;
+ }
+
+ LEAVE();
+ return freq;
+}
+
+#ifdef STA_SUPPORT
+/**
+ * @brief This function parses country information for region channel
+ *
+ * @param pmadapter Pointer to mlan_adapter structure
+ * @param country_info Country information
+ * @param band Chan band
+ * @param parsed_region_chan Pointer to parsed_region_chan_11d_t
+ *
+ * @return MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ */
+mlan_status wlan_11d_parse_domain_info(
+ pmlan_adapter pmadapter, IEEEtypes_CountryInfoFullSet_t *country_info,
+ t_u8 band, parsed_region_chan_11d_t *parsed_region_chan)
+{
+ t_u8 no_of_sub_band, no_of_chan;
+ t_u8 last_chan, first_chan, cur_chan = 0;
+ t_u8 idx = 0;
+ t_u8 j, i;
+
+ ENTER();
+
+ /*
+ * Validation Rules:
+ * 1. Valid Region Code
+ * 2. First Chan increment
+ * 3. Channel range no overlap
+ * 4. Channel is valid?
+ * 5. Channel is supported by Region?
+ * 6. Others
+ */
+
+ HEXDUMP("country_info", (t_u8 *)country_info, 30);
+
+ /* Step 1: Check region_code */
+ if (!(*(country_info->country_code)) ||
+ (country_info->len <= COUNTRY_CODE_LEN)) {
+ /* No region info or wrong region info: treat as no 11D info */
+ LEAVE();
+ return MLAN_STATUS_FAILURE;
+ }
+
+ no_of_sub_band = (country_info->len - COUNTRY_CODE_LEN) /
+ sizeof(IEEEtypes_SubbandSet_t);
+
+ for (j = 0, last_chan = 0; j < no_of_sub_band; j++) {
+ if (country_info->sub_band[j].first_chan <= last_chan) {
+ /* Step2&3: Check First Chan Num increment and no
+ * overlap */
+ PRINTM(MINFO, "11D: Chan[%d>%d] Overlap\n",
+ country_info->sub_band[j].first_chan, last_chan);
+ continue;
+ }
+
+ first_chan = country_info->sub_band[j].first_chan;
+ no_of_chan = country_info->sub_band[j].no_of_chan;
+
+ for (i = 0; idx < MAX_NO_OF_CHAN && i < no_of_chan; i++) {
+ /* Step 4 : Channel is supported? */
+ if (wlan_11d_get_chan(pmadapter, band, first_chan, i,
+ &cur_chan) == MFALSE) {
+ /* Chan is not found in UN table */
+ PRINTM(MWARN,
+ "11D: channel is not supported: %d\n",
+ i);
+ break;
+ }
+
+ last_chan = cur_chan;
+
+ /* Step 5: We don't need to check if cur_chan is
+ supported by mrvl in region */
+ parsed_region_chan->chan_pwr[idx].chan = cur_chan;
+ parsed_region_chan->chan_pwr[idx].band = band;
+ parsed_region_chan->chan_pwr[idx].pwr =
+ country_info->sub_band[j].max_tx_pwr;
+ idx++;
+ }
+
+ /* Step 6: Add other checking if any */
+ }
+
+ parsed_region_chan->no_of_chan = idx;
+
+ PRINTM(MINFO, "11D: number of channel=0x%x\n",
+ parsed_region_chan->no_of_chan);
+ HEXDUMP("11D: parsed_region_chan", (t_u8 *)parsed_region_chan->chan_pwr,
+ sizeof(chan_power_11d_t) * idx);
+
+ LEAVE();
+ return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ * @brief This function setups scan channels
+ *
+ * @param pmpriv Pointer to mlan_private structure
+ * @param band Band
+ *
+ * @return MLAN_STATUS_SUCCESS
+ */
+mlan_status wlan_11d_set_universaltable(mlan_private *pmpriv, t_u8 band)
+{
+ mlan_adapter *pmadapter = pmpriv->adapter;
+ t_u16 i = 0;
+
+ ENTER();
+
+ memset(pmadapter, pmadapter->universal_channel, 0,
+ sizeof(pmadapter->universal_channel));
+
+ if (band & (BAND_B | BAND_G | BAND_GN))
+ /* If band B, G or N */
+ {
+ /* Set channel-frequency-power */
+ pmadapter->universal_channel[i].num_cfp =
+ NELEMENTS(channel_freq_power_UN_BG);
+ PRINTM(MINFO, "11D: BG-band num_cfp=%d\n",
+ pmadapter->universal_channel[i].num_cfp);
+
+ pmadapter->universal_channel[i].pcfp = channel_freq_power_UN_BG;
+ pmadapter->universal_channel[i].valid = MTRUE;
+
+ /* Set region code */
+ pmadapter->universal_channel[i].region = UNIVERSAL_REGION_CODE;
+
+ /* Set band */
+ if (band & BAND_GN)
+ pmadapter->universal_channel[i].band = BAND_G;
+ else
+ pmadapter->universal_channel[i].band =
+ (band & BAND_G) ? BAND_G : BAND_B;
+ i++;
+ }
+
+ if (band & (BAND_A | BAND_AN | BAND_AAC)) {
+ /* If band A */
+
+ /* Set channel-frequency-power */
+ pmadapter->universal_channel[i].num_cfp =
+ NELEMENTS(channel_freq_power_UN_AJ);
+ PRINTM(MINFO, "11D: AJ-band num_cfp=%d\n",
+ pmadapter->universal_channel[i].num_cfp);
+
+ pmadapter->universal_channel[i].pcfp = channel_freq_power_UN_AJ;
+
+ pmadapter->universal_channel[i].valid = MTRUE;
+
+ /* Set region code */
+ pmadapter->universal_channel[i].region = UNIVERSAL_REGION_CODE;
+
+ /* Set band */
+ pmadapter->universal_channel[i].band = BAND_A;
+ i++;
+ }
+
+ LEAVE();
+ return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ * @brief This function calculates the scan type for channels
+ *
+ * @param pmadapter A pointer to mlan_adapter structure
+ * @param band Band number
+ * @param chan Chan number
+ * @param parsed_region_chan Pointer to parsed_region_chan_11d_t
+ *
+ * @return PASSIVE if chan is unknown; ACTIVE
+ * if chan is known
+ */
+t_u8 wlan_11d_get_scan_type(pmlan_adapter pmadapter, t_u8 band, t_u8 chan,
+ parsed_region_chan_11d_t *parsed_region_chan)
+{
+ t_u8 scan_type = MLAN_SCAN_TYPE_PASSIVE;
+
+ ENTER();
+
+ if (wlan_11d_channel_known(pmadapter, band, chan, parsed_region_chan)) {
+ /* Channel found */
+ PRINTM(MINFO, "11D: Channel found and doing Active Scan\n");
+ scan_type = MLAN_SCAN_TYPE_ACTIVE;
+ } else
+ PRINTM(MINFO,
+ "11D: Channel not found and doing Passive Scan\n");
+
+ LEAVE();
+ return scan_type;
+}
+
+/**
+ * @brief This function clears the parsed region table, if 11D is enabled
+ *
+ * @param pmpriv A pointer to mlan_private structure
+ *
+ * @return MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ */
+mlan_status wlan_11d_clear_parsedtable(mlan_private *pmpriv)
+{
+ mlan_adapter *pmadapter = pmpriv->adapter;
+ mlan_status ret = MLAN_STATUS_SUCCESS;
+
+ ENTER();
+
+ if (wlan_11d_is_enabled(pmpriv))
+ memset(pmadapter, &(pmadapter->parsed_region_chan), 0,
+ sizeof(parsed_region_chan_11d_t));
+ else
+ ret = MLAN_STATUS_FAILURE;
+
+ LEAVE();
+ return ret;
+}
+
+/**
+ * @brief This function generates 11D info from user specified regioncode
+ * and download to FW
+ *
+ * @param pmpriv A pointer to mlan_private structure
+ * @param band Band to create
+ *
+ * @return MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ */
+mlan_status wlan_11d_create_dnld_countryinfo(mlan_private *pmpriv, t_u8 band)
+{
+ mlan_status ret = MLAN_STATUS_SUCCESS;
+ mlan_adapter *pmadapter = pmpriv->adapter;
+ region_chan_t *region_chan;
+ parsed_region_chan_11d_t parsed_region_chan;
+ t_u8 j;
+
+ ENTER();
+
+ /* Only valid if 11D is enabled */
+ if (wlan_11d_is_enabled(pmpriv)) {
+ PRINTM(MINFO, "11D: Band[%d]\n", band);
+
+ /* Update parsed_region_chan; download domain info to FW */
+
+ /* Find region channel */
+ for (j = 0; j < MAX_REGION_CHANNEL_NUM; j++) {
+ region_chan = &pmadapter->region_channel[j];
+
+ PRINTM(MINFO, "11D: [%d] region_chan->Band[%d]\n", j,
+ region_chan->band);
+
+ if (!region_chan || !region_chan->valid ||
+ !region_chan->pcfp)
+ continue;
+ switch (region_chan->band) {
+ case BAND_A:
+ switch (band) {
+ case BAND_A:
+ case BAND_AN:
+ case BAND_A | BAND_AN:
+ case BAND_A | BAND_AN | BAND_AAC:
+ break;
+ default:
+ continue;
+ }
+ break;
+ case BAND_B:
+ case BAND_G:
+ switch (band) {
+ case BAND_B:
+ case BAND_G:
+ case BAND_G | BAND_B:
+ case BAND_GN:
+ case BAND_G | BAND_GN:
+ case BAND_B | BAND_G | BAND_GN:
+ case BAND_B | BAND_G | BAND_GN | BAND_GAC:
+ break;
+ default:
+ continue;
+ }
+ break;
+ default:
+ continue;
+ }
+ break;
+ }
+
+ /* Check if region channel found */
+ if (j >= MAX_REGION_CHANNEL_NUM) {
+ PRINTM(MERROR, "11D: region_chan not found. Band[%d]\n",
+ band);
+ LEAVE();
+ return MLAN_STATUS_FAILURE;
+ }
+
+ /* Generate parsed region channel info from region channel */
+ memset(pmadapter, &parsed_region_chan, 0,
+ sizeof(parsed_region_chan_11d_t));
+ wlan_11d_generate_parsed_region_chan(pmadapter, region_chan,
+ &parsed_region_chan);
+
+ /* Generate domain info from parsed region channel info */
+ wlan_11d_generate_domain_info(pmadapter, &parsed_region_chan);
+
+ /* Set domain info */
+ ret = wlan_11d_send_domain_info(pmpriv, MNULL);
+ if (ret) {
+ PRINTM(MERROR,
+ "11D: Error sending domain info to FW\n");
+ }
+ }
+
+ LEAVE();
+ return ret;
+}
+
+/**
+ * @brief This function parses country info from AP and
+ * download country info to FW
+ *
+ * @param pmpriv A pointer to mlan_private structure
+ * @param pbss_desc A pointer to BSS descriptor
+ *
+ * @return MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ */
+mlan_status wlan_11d_parse_dnld_countryinfo(mlan_private *pmpriv,
+ BSSDescriptor_t *pbss_desc)
+{
+ mlan_status ret = MLAN_STATUS_SUCCESS;
+ mlan_adapter *pmadapter = pmpriv->adapter;
+ parsed_region_chan_11d_t region_chan;
+ parsed_region_chan_11d_t bssdesc_region_chan;
+ t_u32 i, j;
+
+ ENTER();
+
+ /* Only valid if 11D is enabled */
+ if (wlan_11d_is_enabled(pmpriv)) {
+ memset(pmadapter, &region_chan, 0,
+ sizeof(parsed_region_chan_11d_t));
+ memset(pmadapter, &bssdesc_region_chan, 0,
+ sizeof(parsed_region_chan_11d_t));
+
+ memcpy_ext(pmadapter, &region_chan,
+ &pmadapter->parsed_region_chan,
+ sizeof(parsed_region_chan_11d_t),
+ sizeof(parsed_region_chan_11d_t));
+
+ if (pbss_desc) {
+ /* Parse domain info if available */
+ ret = wlan_11d_parse_domain_info(
+ pmadapter, &pbss_desc->country_info,
+ (t_u8)pbss_desc->bss_band,
+ &bssdesc_region_chan);
+
+ if (ret == MLAN_STATUS_SUCCESS) {
+ /* Update the channel-power table */
+ for (i = 0;
+ ((i < bssdesc_region_chan.no_of_chan) &&
+ (i < MAX_NO_OF_CHAN));
+ i++) {
+ for (j = 0;
+ ((j < region_chan.no_of_chan) &&
+ (j < MAX_NO_OF_CHAN));
+ j++) {
+ /*
+ * Channel already exists, use
+ * minimum of existing tx power
+ * and tx_power received from
+ * country info of the current
+ * AP
+ */
+ if (region_chan.chan_pwr[i]
+ .chan ==
+ bssdesc_region_chan
+ .chan_pwr[j]
+ .chan &&
+ region_chan.chan_pwr[i]
+ .band ==
+ bssdesc_region_chan
+ .chan_pwr[j]
+ .band) {
+ region_chan.chan_pwr[j]
+ .pwr = MIN(
+ region_chan
+ .chan_pwr[j]
+ .pwr,
+ bssdesc_region_chan
+ .chan_pwr[i]
+ .pwr);
+ break;
+ }
+ }
+ }
+ }
+ }
+
+ /* Generate domain info */
+ wlan_11d_generate_domain_info(pmadapter, &region_chan);
+
+ /* Set domain info */
+ ret = wlan_11d_send_domain_info(pmpriv, MNULL);
+ if (ret) {
+ PRINTM(MERROR,
+ "11D: Error sending domain info to FW\n");
+ }
+ }
+
+ LEAVE();
+ return ret;
+}
+
+/**
+ * @brief This function prepares domain info from scan table and
+ * downloads the domain info command to the FW.
+ *
+ * @param pmpriv A pointer to mlan_private structure
+ *
+ * @return MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ */
+mlan_status wlan_11d_prepare_dnld_domain_info_cmd(mlan_private *pmpriv)
+{
+ mlan_status ret = MLAN_STATUS_SUCCESS;
+ mlan_adapter *pmadapter = pmpriv->adapter;
+ IEEEtypes_CountryInfoFullSet_t *pcountry_full = MNULL;
+ t_u32 idx;
+
+ ENTER();
+
+ /* Only valid if 11D is enabled */
+ if (wlan_11d_is_enabled(pmpriv) && pmadapter->num_in_scan_table != 0) {
+ for (idx = 0; idx < pmadapter->num_in_scan_table; idx++) {
+ pcountry_full =
+ &pmadapter->pscan_table[idx].country_info;
+
+ ret = wlan_11d_update_chan_pwr_table(
+ pmpriv, &pmadapter->pscan_table[idx]);
+
+ if (*(pcountry_full->country_code) != 0 &&
+ (pcountry_full->len > COUNTRY_CODE_LEN)) {
+ /* Country info found in the BSS Descriptor */
+ ret = wlan_11d_process_country_info(
+ pmpriv, &pmadapter->pscan_table[idx]);
+ }
+ }
+
+ /* Sort parsed_region_chan in ascending channel number */
+ wlan_11d_sort_parsed_region_chan(
+ &pmadapter->parsed_region_chan);
+
+ /* Check if connected */
+ if (pmpriv->media_connected == MTRUE) {
+ ret = wlan_11d_parse_dnld_countryinfo(
+ pmpriv,
+ &pmpriv->curr_bss_params.bss_descriptor);
+ } else {
+ ret = wlan_11d_parse_dnld_countryinfo(pmpriv, MNULL);
+ }
+ }
+
+ LEAVE();
+ return ret;
+}
+#endif /* STA_SUPPORT */
+
+/**
+ * @brief This function checks country code and maps it when needed
+ *
+ * @param pmadapter A pointer to mlan_adapter structure
+ * @param pcountry_code Pointer to the country code string
+ *
+ * @return Pointer to the mapped country code string
+ */
+static t_u8 *wlan_11d_map_country_code(pmlan_adapter pmadapter,
+ t_u8 *pcountry_code)
+{
+ /* Since firmware can only recognize EU as ETSI domain and there is no
+ * memory left for some devices to convert it in firmware, driver need
+ * to convert it before passing country code to firmware through tlv
+ */
+
+ if (wlan_is_etsi_country(pmadapter, pcountry_code))
+ return ("EU ");
+ else
+ return pcountry_code;
+}
+
+/**
+ * @brief This function sets up domain_reg and downloads CMD to FW
+ *
+ * @param pmadapter A pointer to mlan_adapter structure
+ * @param pioctl_req Pointer to the IOCTL request buffer
+ *
+ * @return MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ */
+mlan_status wlan_11d_cfg_domain_info(pmlan_adapter pmadapter,
+ mlan_ioctl_req *pioctl_req)
+{
+ mlan_status ret = MLAN_STATUS_SUCCESS;
+ mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index];
+ mlan_ds_11d_domain_info *domain_info = MNULL;
+ mlan_ds_11d_cfg *cfg_11d = MNULL;
+ t_u8 cfp_bg = 0, cfp_a = 0;
+
+ ENTER();
+
+ if (pmadapter->otp_region && pmadapter->otp_region->force_reg) {
+ PRINTM(MERROR,
+ "ForceRegionRule is set in the on-chip OTP memory\n");
+ ret = MLAN_STATUS_FAILURE;
+ goto done;
+ }
+ if (!wlan_fw_11d_is_enabled(pmpriv))
+ wlan_11d_enable(pmpriv, MNULL, ENABLE_11D);
+
+ cfg_11d = (mlan_ds_11d_cfg *)pioctl_req->pbuf;
+ domain_info = &cfg_11d->param.domain_info;
+ memcpy_ext(pmadapter, pmadapter->country_code,
+ domain_info->country_code, COUNTRY_CODE_LEN,
+ COUNTRY_CODE_LEN);
+ wlan_11d_set_domain_info(
+ pmpriv, domain_info->band,
+ wlan_11d_map_country_code(pmadapter, domain_info->country_code),
+ domain_info->no_of_sub_band,
+ (IEEEtypes_SubbandSet_t *)domain_info->sub_band);
+ ret = wlan_11d_send_domain_info(pmpriv, pioctl_req);
+
+ if (ret == MLAN_STATUS_SUCCESS)
+ ret = MLAN_STATUS_PENDING;
+
+ /* Update region code and table based on country code */
+ if (wlan_misc_country_2_cfp_table_code(
+ pmadapter, domain_info->country_code, &cfp_bg, &cfp_a)) {
+ PRINTM(MIOCTL, "Country code %c%c not found!\n",
+ domain_info->country_code[0],
+ domain_info->country_code[1]);
+ goto done;
+ }
+ pmadapter->cfp_code_bg = cfp_bg;
+ pmadapter->cfp_code_a = cfp_a;
+ if (cfp_a)
+ pmadapter->region_code = cfp_a;
+ else if (cfp_bg)
+ pmadapter->region_code = cfp_bg;
+ else
+ pmadapter->region_code = 0;
+ if (wlan_set_regiontable(pmpriv, pmadapter->region_code,
+ pmadapter->config_bands |
+ pmadapter->adhoc_start_band)) {
+ PRINTM(MIOCTL, "Fail to set regiontabl\n");
+ goto done;
+ }
+done:
+ LEAVE();
+ return ret;
+}
+
+#if defined(UAP_SUPPORT)
+/**
+ * @brief This function handles domain info data from UAP interface.
+ * Checks conditions, sets up domain_reg, then downloads CMD.
+ *
+ * @param pmpriv A pointer to mlan_private structure
+ * @param band Band interface is operating on
+ * @param domain_tlv Pointer to domain_info tlv
+ * @param pioctl_buf Pointer to the IOCTL buffer
+ *
+ * @return MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ */
+mlan_status wlan_11d_handle_uap_domain_info(mlan_private *pmpriv, t_u8 band,
+ t_u8 *domain_tlv,
+ t_void *pioctl_buf)
+{
+ mlan_status ret = MLAN_STATUS_SUCCESS;
+ mlan_adapter *pmadapter = pmpriv->adapter;
+ MrvlIEtypes_DomainParamSet_t *pdomain_tlv;
+ t_u8 num_sub_band = 0;
+ t_u8 cfp_bg = 0, cfp_a = 0;
+
+ ENTER();
+
+ pdomain_tlv = (MrvlIEtypes_DomainParamSet_t *)domain_tlv;
+
+ /* update region code & table based on country string */
+ if (wlan_misc_country_2_cfp_table_code(
+ pmadapter, pdomain_tlv->country_code, &cfp_bg, &cfp_a) ==
+ MLAN_STATUS_SUCCESS) {
+ pmadapter->cfp_code_bg = cfp_bg;
+ pmadapter->cfp_code_a = cfp_a;
+ if (cfp_a)
+ pmadapter->region_code = cfp_a;
+ else if (cfp_bg)
+ pmadapter->region_code = cfp_bg;
+ else
+ pmadapter->region_code = 0;
+ if (wlan_set_regiontable(pmpriv, pmadapter->region_code,
+ pmadapter->config_bands |
+ pmadapter->adhoc_start_band)) {
+ ret = MLAN_STATUS_FAILURE;
+ goto done;
+ }
+ }
+
+ memcpy_ext(pmadapter, pmadapter->country_code,
+ pdomain_tlv->country_code, COUNTRY_CODE_LEN,
+ COUNTRY_CODE_LEN);
+ num_sub_band = ((pdomain_tlv->header.len - COUNTRY_CODE_LEN) /
+ sizeof(IEEEtypes_SubbandSet_t));
+
+ /* TODO: don't just clobber pmadapter->domain_reg.
+ * Add some checking or merging between STA & UAP domain_info
+ */
+ wlan_11d_set_domain_info(pmpriv, band, pdomain_tlv->country_code,
+ num_sub_band, pdomain_tlv->sub_band);
+ ret = wlan_11d_send_domain_info(pmpriv, pioctl_buf);
+
+done:
+ LEAVE();
+ return ret;
+}
+#endif
diff --git a/drivers/net/wireless/nxp/mxm_wifiex/wlan_src/mlan/mlan_11h.c b/drivers/net/wireless/nxp/mxm_wifiex/wlan_src/mlan/mlan_11h.c
new file mode 100644
index 000000000000..027ba589d752
--- /dev/null
+++ b/drivers/net/wireless/nxp/mxm_wifiex/wlan_src/mlan/mlan_11h.c
@@ -0,0 +1,4274 @@
+/** @file mlan_11h.c
+ *
+ * @brief This file contains functions for 802.11H.
+ *
+ *
+ * Copyright 2014-2020 NXP
+ *
+ * This software file (the File) is distributed by NXP
+ * under the terms of the GNU General Public License Version 2, June 1991
+ * (the License). You may use, redistribute and/or modify the 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.
+ *
+ */
+
+/*************************************************************
+Change Log:
+ 03/26/2009: initial version
+************************************************************/
+
+#include "mlan.h"
+#include "mlan_join.h"
+#include "mlan_util.h"
+#include "mlan_fw.h"
+#include "mlan_main.h"
+#include "mlan_ioctl.h"
+#include "mlan_11h.h"
+#include "mlan_11n.h"
+#ifdef UAP_SUPPORT
+#include "mlan_uap.h"
+#endif
+
+/********************************************************
+ Local Variables
+********************************************************/
+
+/** Default IBSS DFS recovery interval (in TBTTs); used for adhoc start */
+#define WLAN_11H_DEFAULT_DFS_RECOVERY_INTERVAL 100
+
+/** Default 11h power constraint used to offset the maximum transmit power */
+#define WLAN_11H_TPC_POWERCONSTRAINT 0
+
+/** 11h TPC Power capability minimum setting, sent in TPC_INFO command to fw */
+#define WLAN_11H_TPC_POWERCAPABILITY_MIN 5
+
+/** 11h TPC Power capability maximum setting, sent in TPC_INFO command to fw */
+#define WLAN_11H_TPC_POWERCAPABILITY_MAX 20
+
+/** Regulatory requirement for the duration of a channel availability check */
+#define WLAN_11H_CHANNEL_AVAIL_CHECK_DURATION 60000 /* in ms */
+
+/** Starting Frequency for 11A band */
+#define START_FREQ_11A_BAND 5000 /* in MHz */
+
+/** DFS Channel Move Time */
+#define DFS_CHAN_MOVE_TIME 10 /* in sec */
+
+/** Regulatory requirement for the duration of a non-occupancy period */
+#define WLAN_11H_NON_OCCUPANCY_PERIOD 1800 /* in sec (30mins) */
+
+/** Maximum allowable age (seconds) on DFS report data */
+#define MAX_DFS_REPORT_USABLE_AGE_SEC (120) /* 2 minutes */
+
+/** Minimum delay for CHAN_SW IE to broadcast by FW */
+#define MIN_RDH_CHAN_SW_IE_PERIOD_MSEC (400) /* 4 beacons @ 100ms */
+
+/** Maximum delay for CHAN_SW IE to broadcast by FW */
+#define MAX_RDH_CHAN_SW_IE_PERIOD_MSEC (3000) /* 5 beacons @ 600ms */
+
+/** Maximum retries on selecting new random channel */
+#define MAX_RANDOM_CHANNEL_RETRIES (20)
+
+/** Maximum retries on selecting new random non-dfs channel */
+#define MAX_SWITCH_CHANNEL_RETRIES (30)
+
+/** Value for undetermined priv_curr_idx on first entry to new RDH stage */
+#define RDH_STAGE_FIRST_ENTRY_PRIV_IDX (0xff)
+
+/** Region codes 0x10, 0x20: channels 1 thru 11 supported */
+static const IEEEtypes_SupportChan_Subband_t wlan_11h_2_4G_region_FCC = {1, 11};
+
+/** Region codes 0x30, 0x32, 0x41, 0x50: channels 1 thru 13 supported */
+static const IEEEtypes_SupportChan_Subband_t wlan_11h_2_4G_region_EU = {1, 13};
+
+/** Region code 0x40: only channel 14 supported */
+static const IEEEtypes_SupportChan_Subband_t wlan_11h_2_4G_region_JPN40 = {14,
+ 1};
+
+/** JPN sub-band config : Start Channel = 8, NumChans = 3 */
+static const IEEEtypes_SupportChan_Subband_t wlan_11h_JPN_bottom_band = {8, 3};
+
+/** U-NII sub-band config : Start Channel = 36, NumChans = 4 */
+static const IEEEtypes_SupportChan_Subband_t wlan_11h_unii_lower_band = {36, 4};
+
+/** U-NII sub-band config : Start Channel = 52, NumChans = 4 */
+static const IEEEtypes_SupportChan_Subband_t wlan_11h_unii_middle_band = {52,
+ 4};
+
+/** U-NII sub-band config : Start Channel = 100, NumChans = 11 */
+static const IEEEtypes_SupportChan_Subband_t wlan_11h_unii_mid_upper_band = {
+ 100, 11};
+
+/** U-NII sub-band config : Start Channel = 100, NumChans = 5 */
+static const IEEEtypes_SupportChan_Subband_t wlan_11h_unii_mid_upper_band_0 = {
+ 100, 5};
+
+/** U-NII sub-band config : Start Channel = 132, NumChans = 3 */
+static const IEEEtypes_SupportChan_Subband_t wlan_11h_unii_mid_upper_band_1 = {
+ 132, 3};
+
+/** U-NII sub-band config : Start Channel = 149, NumChans = 5 */
+static const IEEEtypes_SupportChan_Subband_t wlan_11h_unii_upper_band = {149,
+ 5};
+
+/** Internally passed structure used to send a CMD_802_11_TPC_INFO command */
+typedef struct {
+ t_u8 chan; /**< Channel to which the power constraint applies */
+ t_u8 power_constraint; /**< Local power constraint to send to firmware
+ */
+} wlan_11h_tpc_info_param_t;
+
+/********************************************************
+ Global Variables
+********************************************************/
+
+/********************************************************
+ Local Functions
+********************************************************/
+
+/**
+ * @brief Utility function to get a random number based on the underlying OS
+ *
+ * @param pmadapter Pointer to mlan_adapter
+ * @return random integer
+ */
+static t_u32 wlan_11h_get_random_num(pmlan_adapter pmadapter)
+{
+ t_u32 sec, usec;
+
+ ENTER();
+ pmadapter->callbacks.moal_get_system_time(pmadapter->pmoal_handle, &sec,
+ &usec);
+ sec = (sec & 0xFFFF) + (sec >> 16);
+ usec = (usec & 0xFFFF) + (usec >> 16);
+
+ LEAVE();
+ return (usec << 16) | sec;
+}
+
+/**
+ * @brief Convert an IEEE formatted IE to 16-bit ID/Len NXP
+ * proprietary format
+ *
+ * @param pmadapter Pointer to mlan_adapter
+ * @param pout_buf Output parameter: Buffer to output NXP formatted IE
+ * @param pin_ie Pointer to IEEE IE to be converted to NXP format
+ *
+ * @return Number of bytes output to pout_buf parameter return
+ */
+static t_u32 wlan_11h_convert_ieee_to_mrvl_ie(mlan_adapter *pmadapter,
+ t_u8 *pout_buf,
+ const t_u8 *pin_ie)
+{
+ MrvlIEtypesHeader_t mrvl_ie_hdr;
+ t_u8 *ptmp_buf = pout_buf;
+
+ ENTER();
+ /* Assign the Element Id and Len to the NXP struct attributes */
+ mrvl_ie_hdr.type = wlan_cpu_to_le16(pin_ie[0]);
+ mrvl_ie_hdr.len = wlan_cpu_to_le16(pin_ie[1]);
+
+ /* If the element ID is zero, return without doing any copying */
+ if (!mrvl_ie_hdr.type) {
+ LEAVE();
+ return 0;
+ }
+
+ /* Copy the header to the buffer pointer */
+ memcpy_ext(pmadapter, ptmp_buf, &mrvl_ie_hdr, sizeof(mrvl_ie_hdr),
+ sizeof(mrvl_ie_hdr));
+
+ /* Increment the temp buffer pointer by the size appended */
+ ptmp_buf += sizeof(mrvl_ie_hdr);
+
+ /* Append the data section of the IE; length given by the IEEE IE length
+ */
+ memcpy_ext(pmadapter, ptmp_buf, pin_ie + 2, pin_ie[1], pin_ie[1]);
+
+ LEAVE();
+ /* Return the number of bytes appended to pout_buf */
+ return sizeof(mrvl_ie_hdr) + pin_ie[1];
+}
+
+#ifdef STA_SUPPORT
+/**
+ * @brief Setup the IBSS DFS element passed to the firmware in adhoc start
+ * and join commands
+ *
+ * The DFS Owner and recovery fields are set to be our MAC address and
+ * a predetermined constant recovery value. If we are joining an adhoc
+ * network, these values are replaced with the existing IBSS values.
+ * They are valid only when starting a new IBSS.
+ *
+ * The IBSS DFS Element is variable in size based on the number of
+ * channels supported in our current region.
+ *
+ * @param priv Private driver information structure
+ * @param pdfs Output parameter: Pointer to the IBSS DFS element setup by
+ * this function.
+ *
+ * @return
+ * - Length of the returned element in pdfs output parameter
+ * - 0 if returned element is not setup
+ */
+static t_u32 wlan_11h_set_ibss_dfs_ie(mlan_private *priv,
+ IEEEtypes_IBSS_DFS_t *pdfs)
+{
+ t_u8 num_chans = 0;
+ MeasRptBasicMap_t initial_map;
+ mlan_adapter *adapter = priv->adapter;
+
+ ENTER();
+
+ memset(adapter, pdfs, 0x00, sizeof(IEEEtypes_IBSS_DFS_t));
+
+ /*
+ * A basic measurement report is included with each channel in the
+ * map field. Initial value for the map for each supported channel
+ * is with only the unmeasured bit set.
+ */
+ memset(adapter, &initial_map, 0x00, sizeof(initial_map));
+ initial_map.unmeasured = 1;
+
+ /* Set the DFS Owner and recovery interval fields */
+ memcpy_ext(adapter, pdfs->dfs_owner, priv->curr_addr,
+ sizeof(pdfs->dfs_owner), sizeof(pdfs->dfs_owner));
+ pdfs->dfs_recovery_interval = WLAN_11H_DEFAULT_DFS_RECOVERY_INTERVAL;
+
+ for (; (num_chans < adapter->parsed_region_chan.no_of_chan) &&
+ (num_chans < WLAN_11H_MAX_IBSS_DFS_CHANNELS);
+ num_chans++) {
+ pdfs->channel_map[num_chans].channel_number =
+ adapter->parsed_region_chan.chan_pwr[num_chans].chan;
+
+ /*
+ * Set the initial map field with a basic measurement
+ */
+ pdfs->channel_map[num_chans].rpt_map = initial_map;
+ }
+
+ /*
+ * If we have an established channel map, include it and return
+ * a valid DFS element
+ */
+ if (num_chans) {
+ PRINTM(MINFO, "11h: Added %d channels to IBSS DFS Map\n",
+ num_chans);
+
+ pdfs->element_id = IBSS_DFS;
+ pdfs->len = (sizeof(pdfs->dfs_owner) +
+ sizeof(pdfs->dfs_recovery_interval) +
+ num_chans * sizeof(IEEEtypes_ChannelMap_t));
+
+ LEAVE();
+ return pdfs->len + sizeof(pdfs->len) + sizeof(pdfs->element_id);
+ }
+
+ /* Ensure the element is zeroed out for an invalid return */
+ memset(adapter, pdfs, 0x00, sizeof(IEEEtypes_IBSS_DFS_t));
+
+ LEAVE();
+ return 0;
+}
+#endif
+
+/**
+ * @brief Setup the Supported Channel IE sent in association requests
+ *
+ * The Supported Channels IE is required to be sent when the spectrum
+ * management capability (11h) is enabled. The element contains a
+ * starting channel and number of channels tuple for each sub-band
+ * the STA supports. This information is based on the operating region.
+ *
+ * @param priv Private driver information structure
+ * @param band Band in use
+ * @param psup_chan Output parameter: Pointer to the Supported Chan element
+ * setup by this function.
+ *
+ * @return
+ * - Length of the returned element in psup_chan output parameter
+ * - 0 if returned element is not setup
+ */
+static t_u16
+wlan_11h_set_supp_channels_ie(mlan_private *priv, t_u8 band,
+ IEEEtypes_SupportedChannels_t *psup_chan)
+{
+ t_u16 num_subbands = 0;
+ t_u16 ret_len = 0;
+ t_u8 cfp_bg, cfp_a;
+
+ ENTER();
+ memset(priv->adapter, psup_chan, 0x00,
+ sizeof(IEEEtypes_SupportedChannels_t));
+
+ cfp_bg = cfp_a = priv->adapter->region_code;
+ if (!priv->adapter->region_code) {
+ /* Invalid region code, use CFP code */
+ cfp_bg = priv->adapter->cfp_code_bg;
+ cfp_a = priv->adapter->cfp_code_a;
+ }
+
+ if ((band & BAND_B) || (band & BAND_G)) {
+ /*
+ * Channels are contiguous in 2.4GHz, usually only one subband.
+ */
+ switch (cfp_bg) {
+ case 0x10: /* USA FCC */
+ case 0x20: /* Canada IC */
+ default:
+ psup_chan->subband[num_subbands++] =
+ wlan_11h_2_4G_region_FCC;
+ break;
+ case 0x30: /* Europe ETSI */
+ case 0x41: /* Japan */
+ case 0x50: /* China */
+ psup_chan->subband[num_subbands++] =
+ wlan_11h_2_4G_region_EU;
+ break;
+ case 0x40: /* Japan */
+ psup_chan->subband[num_subbands++] =
+ wlan_11h_2_4G_region_JPN40;
+ break;
+ case 0xff: /* Japan special */
+ psup_chan->subband[num_subbands++] =
+ wlan_11h_2_4G_region_EU;
+ psup_chan->subband[num_subbands++] =
+ wlan_11h_2_4G_region_JPN40;
+ break;
+ }
+ } else if (band & BAND_A) {
+ /*
+ * Set the supported channel elements based on the region code,
+ * incrementing num_subbands for each sub-band we append to the
+ * element.
+ */
+ switch (cfp_a) {
+ case 0x10: /* USA FCC */
+ case 0x20: /* Canada IC */
+ case 0x30: /* Europe ETSI */
+ default:
+ psup_chan->subband[num_subbands++] =
+ wlan_11h_unii_lower_band;
+ psup_chan->subband[num_subbands++] =
+ wlan_11h_unii_middle_band;
+ psup_chan->subband[num_subbands++] =
+ wlan_11h_unii_mid_upper_band;
+ psup_chan->subband[num_subbands++] =
+ wlan_11h_unii_upper_band;
+ break;
+ case 0x50: /* China */
+ psup_chan->subband[num_subbands++] =
+ wlan_11h_unii_lower_band;
+ psup_chan->subband[num_subbands++] =
+ wlan_11h_unii_middle_band;
+ psup_chan->subband[num_subbands++] =
+ wlan_11h_unii_upper_band;
+ break;
+ case 0x40: /* Japan */
+ case 0x41: /* Japan */
+ case 0xff: /* Japan special */
+ psup_chan->subband[num_subbands++] =
+ wlan_11h_JPN_bottom_band;
+ psup_chan->subband[num_subbands++] =
+ wlan_11h_unii_lower_band;
+ psup_chan->subband[num_subbands++] =
+ wlan_11h_unii_middle_band;
+ psup_chan->subband[num_subbands++] =
+ wlan_11h_unii_mid_upper_band;
+ break;
+ case 0x1: /* Low band (5150-5250 MHz) channels */
+ psup_chan->subband[num_subbands++] =
+ wlan_11h_unii_lower_band;
+ break;
+ case 0x2: /* Lower middle band (5250-5350 MHz) channels */
+ psup_chan->subband[num_subbands++] =
+ wlan_11h_unii_middle_band;
+ break;
+ case 0x3: /* Upper middle band (5470-5725 MHz) channels */
+ psup_chan->subband[num_subbands++] =
+ wlan_11h_unii_mid_upper_band;
+ break;
+ case 0x4: /* High band (5725-5850 MHz) channels */
+ psup_chan->subband[num_subbands++] =
+ wlan_11h_unii_upper_band;
+ break;
+ case 0x5: /* Low band (5150-5250 MHz) and High band (5725-5850
+ MHz) channels */
+ psup_chan->subband[num_subbands++] =
+ wlan_11h_unii_lower_band;
+ psup_chan->subband[num_subbands++] =
+ wlan_11h_unii_upper_band;
+ break;
+ case 0x6: /* Low band (5150-5250 MHz) and Lower middle band
+ (5250-5350 MHz) and High band (5725-5850 MHz)
+ channels */
+ psup_chan->subband[num_subbands++] =
+ wlan_11h_unii_lower_band;
+ psup_chan->subband[num_subbands++] =
+ wlan_11h_unii_middle_band;
+ psup_chan->subband[num_subbands++] =
+ wlan_11h_unii_upper_band;
+ break;
+ case 0x7:
+ /* 36-48 */
+ psup_chan->subband[num_subbands++] =
+ wlan_11h_unii_lower_band;
+ /* 52-64 */
+ psup_chan->subband[num_subbands++] =
+ wlan_11h_unii_middle_band;
+ /* 100-116 */
+ psup_chan->subband[num_subbands++] =
+ wlan_11h_unii_mid_upper_band_0;
+ /* 132-140 */
+ psup_chan->subband[num_subbands++] =
+ wlan_11h_unii_mid_upper_band_1;
+ /* 149-165 */
+ psup_chan->subband[num_subbands++] =
+ wlan_11h_unii_upper_band;
+ break;
+ }
+ }
+
+ /*
+ * If we have setup any supported subbands in the element, return a
+ * valid IE along with its size, else return 0.
+ */
+ if (num_subbands) {
+ psup_chan->element_id = SUPPORTED_CHANNELS;
+ psup_chan->len =
+ num_subbands * sizeof(IEEEtypes_SupportChan_Subband_t);
+
+ ret_len = (t_u16)(psup_chan->len + sizeof(psup_chan->len) +
+ sizeof(psup_chan->element_id));
+
+ HEXDUMP("11h: SupChan", (t_u8 *)psup_chan, ret_len);
+ }
+
+ LEAVE();
+ return ret_len;
+}
+
+/**
+ * @brief Prepare CMD_802_11_TPC_ADAPT_REQ firmware command
+ *
+ * @param priv Private driver information structure
+ * @param pcmd_ptr Output parameter: Pointer to the command being prepared
+ * for the firmware
+ * @param pinfo_buf HostCmd_DS_802_11_TPC_ADAPT_REQ passed as void data block
+ *
+ * @return MLAN_STATUS_SUCCESS
+ */
+static mlan_status wlan_11h_cmd_tpc_request(mlan_private *priv,
+ HostCmd_DS_COMMAND *pcmd_ptr,
+ const t_void *pinfo_buf)
+{
+ ENTER();
+
+ memcpy_ext(priv->adapter, &pcmd_ptr->params.tpc_req, pinfo_buf,
+ sizeof(HostCmd_DS_802_11_TPC_ADAPT_REQ),
+ sizeof(HostCmd_DS_802_11_TPC_ADAPT_REQ));
+
+ pcmd_ptr->params.tpc_req.req.timeout =
+ wlan_cpu_to_le16(pcmd_ptr->params.tpc_req.req.timeout);
+
+ /* Converted to little endian in wlan_11h_cmd_process */
+ pcmd_ptr->size = sizeof(HostCmd_DS_802_11_TPC_ADAPT_REQ) + S_DS_GEN;
+
+ HEXDUMP("11h: 11_TPC_ADAPT_REQ:", (t_u8 *)pcmd_ptr,
+ (t_u32)pcmd_ptr->size);
+
+ LEAVE();
+ return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ * @brief Prepare CMD_802_11_TPC_INFO firmware command
+ *
+ * @param priv Private driver information structure
+ * @param pcmd_ptr Output parameter: Pointer to the command being prepared
+ * for the firmware
+ * @param pinfo_buf wlan_11h_tpc_info_param_t passed as void data block
+ *
+ * @return MLAN_STATUS_SUCCESS
+ */
+static mlan_status wlan_11h_cmd_tpc_info(mlan_private *priv,
+ HostCmd_DS_COMMAND *pcmd_ptr,
+ const t_void *pinfo_buf)
+{
+ HostCmd_DS_802_11_TPC_INFO *ptpc_info = &pcmd_ptr->params.tpc_info;
+ MrvlIEtypes_LocalPowerConstraint_t *pconstraint =
+ &ptpc_info->local_constraint;
+ MrvlIEtypes_PowerCapability_t *pcap = &ptpc_info->power_cap;
+
+ wlan_11h_device_state_t *pstate = &priv->adapter->state_11h;
+ const wlan_11h_tpc_info_param_t *ptpc_info_param =
+ (wlan_11h_tpc_info_param_t *)pinfo_buf;
+
+ ENTER();
+
+ pcap->min_power = pstate->min_tx_power_capability;
+ pcap->max_power = pstate->max_tx_power_capability;
+ pcap->header.len = wlan_cpu_to_le16(2);
+ pcap->header.type = wlan_cpu_to_le16(TLV_TYPE_POWER_CAPABILITY);
+
+ pconstraint->chan = ptpc_info_param->chan;
+ pconstraint->constraint = ptpc_info_param->power_constraint;
+ pconstraint->header.type = wlan_cpu_to_le16(TLV_TYPE_POWER_CONSTRAINT);
+ pconstraint->header.len = wlan_cpu_to_le16(2);
+
+ /* Converted to little endian in wlan_11h_cmd_process */
+ pcmd_ptr->size = sizeof(HostCmd_DS_802_11_TPC_INFO) + S_DS_GEN;
+
+ HEXDUMP("11h: TPC INFO", (t_u8 *)pcmd_ptr, (t_u32)pcmd_ptr->size);
+
+ LEAVE();
+ return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ * @brief Prepare CMD_802_11_CHAN_SW_ANN firmware command
+ *
+ * @param priv Private driver information structure
+ * @param pcmd_ptr Output parameter: Pointer to the command being
+ * prepared to for firmware
+ * @param pinfo_buf HostCmd_DS_802_11_CHAN_SW_ANN passed as void data block
+ *
+ * @return MLAN_STATUS_SUCCESS
+ */
+static mlan_status wlan_11h_cmd_chan_sw_ann(mlan_private *priv,
+ HostCmd_DS_COMMAND *pcmd_ptr,
+ const t_void *pinfo_buf)
+{
+ const HostCmd_DS_802_11_CHAN_SW_ANN *pch_sw_ann =
+ (HostCmd_DS_802_11_CHAN_SW_ANN *)pinfo_buf;
+
+ ENTER();
+
+ /* Converted to little endian in wlan_11h_cmd_process */
+ pcmd_ptr->size = sizeof(HostCmd_DS_802_11_CHAN_SW_ANN) + S_DS_GEN;
+
+ memcpy_ext(priv->adapter, &pcmd_ptr->params.chan_sw_ann, pch_sw_ann,
+ sizeof(HostCmd_DS_802_11_CHAN_SW_ANN),
+ sizeof(HostCmd_DS_802_11_CHAN_SW_ANN));
+
+ PRINTM(MINFO, "11h: ChSwAnn: %#x-%u, Seq=%u, Ret=%u\n",
+ pcmd_ptr->command, pcmd_ptr->size, pcmd_ptr->seq_num,
+ pcmd_ptr->result);
+ PRINTM(MINFO, "11h: ChSwAnn: Ch=%d, Cnt=%d, Mode=%d\n",
+ pch_sw_ann->new_chan, pch_sw_ann->switch_count,
+ pch_sw_ann->switch_mode);
+
+ LEAVE();
+ return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ * @brief Prepare CMD_CHAN_REPORT_REQUEST firmware command
+ *
+ * @param priv Private driver information structure
+ * @param pcmd_ptr Output parameter: Pointer to the command being
+ * prepared to for firmware
+ * @param pinfo_buf HostCmd_DS_CHAN_RPT_REQ passed as void data block
+ *
+ * @return MLAN_STATUS_SUCCESS or MLAN_STATUS_PENDING
+ */
+static mlan_status wlan_11h_cmd_chan_rpt_req(mlan_private *priv,
+ HostCmd_DS_COMMAND *pcmd_ptr,
+ const t_void *pinfo_buf)
+{
+ HostCmd_DS_CHAN_RPT_REQ *pchan_rpt_req =
+ (HostCmd_DS_CHAN_RPT_REQ *)pinfo_buf;
+ wlan_dfs_device_state_t *pstate_dfs = &priv->adapter->state_dfs;
+ MrvlIEtypes_ChanRpt11hBasic_t *ptlv_basic;
+ t_bool is_cancel_req = MFALSE;
+ t_u8 dfs53cfg = priv->adapter->dfs53cfg;
+ MrvlIEtypes_DfsW53Cfg_t *ptlv_dfs53cfg;
+
+ ENTER();
+
+ /*
+ * pchan_rpt_req->millisec_dwell_time would be zero if the chan_rpt_req
+ * is to cancel current ongoing report
+ */
+ if (pchan_rpt_req->millisec_dwell_time == 0)
+ is_cancel_req = MTRUE;
+
+ if (pstate_dfs->dfs_check_pending && !is_cancel_req) {
+ PRINTM(MERROR,
+ "11h: ChanRptReq - previous CMD_CHAN_REPORT_REQUEST has"
+ " not returned its result yet (as EVENT_CHANNEL_READY)."
+ " This command will be dropped.\n");
+ LEAVE();
+ return MLAN_STATUS_PENDING;
+ }
+
+ /* Converted to little endian in wlan_11h_cmd_process */
+ pcmd_ptr->size = sizeof(HostCmd_DS_CHAN_RPT_REQ) + S_DS_GEN;
+
+ memcpy_ext(priv->adapter, &pcmd_ptr->params.chan_rpt_req, pchan_rpt_req,
+ sizeof(HostCmd_DS_CHAN_RPT_REQ),
+ sizeof(HostCmd_DS_CHAN_RPT_REQ));
+ pcmd_ptr->params.chan_rpt_req.chan_desc.startFreq =
+ wlan_cpu_to_le16(pchan_rpt_req->chan_desc.startFreq);
+ pcmd_ptr->params.chan_rpt_req.millisec_dwell_time =
+ wlan_cpu_to_le32(pchan_rpt_req->millisec_dwell_time);
+
+ /* if DFS channel, add BASIC report TLV, and set radar bit */
+ if (!is_cancel_req && wlan_11h_radar_detect_required(
+ priv, pchan_rpt_req->chan_desc.chanNum)) {
+ ptlv_basic =
+ (MrvlIEtypes_ChanRpt11hBasic_t *)(((t_u8 *)(pcmd_ptr)) +
+ pcmd_ptr->size);
+ ptlv_basic->Header.type =
+ wlan_cpu_to_le16(TLV_TYPE_CHANRPT_11H_BASIC);
+ ptlv_basic->Header.len =
+ wlan_cpu_to_le16(sizeof(MeasRptBasicMap_t));
+ memset(priv->adapter, &ptlv_basic->map, 0,
+ sizeof(MeasRptBasicMap_t));
+ ptlv_basic->map.radar = 1;
+ pcmd_ptr->size += sizeof(MrvlIEtypes_ChanRpt11hBasic_t);
+ }
+
+ if ((priv->adapter->region_code == COUNTRY_CODE_JP_40 ||
+ priv->adapter->region_code == COUNTRY_CODE_JP_FF) &&
+ (dfs53cfg != DFS_W53_DEFAULT_FW)) {
+ ptlv_dfs53cfg =
+ (MrvlIEtypes_DfsW53Cfg_t *)(((t_u8 *)(pcmd_ptr)) +
+ pcmd_ptr->size);
+ ptlv_dfs53cfg->Header.type =
+ wlan_cpu_to_le16(TLV_TYPE_DFS_W53_CFG);
+ ptlv_dfs53cfg->Header.len = wlan_cpu_to_le16(sizeof(t_u8));
+ ptlv_dfs53cfg->dfs53cfg = dfs53cfg;
+ pcmd_ptr->size += sizeof(MrvlIEtypes_DfsW53Cfg_t);
+ }
+
+ pcmd_ptr->size = wlan_cpu_to_le16(pcmd_ptr->size);
+
+ /* update dfs sturcture.
+ * dfs_check_pending is set when we receive CMD_RESP == SUCCESS */
+ pstate_dfs->dfs_check_pending = MFALSE;
+ pstate_dfs->dfs_radar_found = MFALSE;
+ pstate_dfs->dfs_check_priv = MNULL;
+
+ if (!is_cancel_req)
+ pstate_dfs->dfs_check_channel =
+ pchan_rpt_req->chan_desc.chanNum;
+
+ LEAVE();
+ return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ * @brief Set the local power capability and constraint TLV
+ *
+ * @param ppbuffer The buffer to add these two TLVs
+ * @param channel Channel to which the power constraint applies
+ * @param power_constraint Power constraint to be applied on the channel
+ * @param min_tx_power_capability Min. Tx Power in Power Capability IE
+ * @param max_tx_power_capability Max. Tx Power in Power Capability IE
+ *
+ * @return The len increased
+ */
+static t_u32 wlan_11h_set_local_power_constraint_tlv(
+ t_u8 **ppbuffer, t_u8 channel, t_u8 power_constraint,
+ t_u8 min_tx_power_capability, t_u8 max_tx_power_capability)
+{
+ MrvlIEtypes_PowerCapability_t *pcap;
+ MrvlIEtypes_LocalPowerConstraint_t *pconstraint;
+ t_u8 *start_ptr = MNULL;
+
+ ENTER();
+
+ /* Null Checks */
+ if ((ppbuffer == MNULL) || (((t_u8 *)(*ppbuffer)) == MNULL)) {
+ LEAVE();
+ return 0;
+ }
+
+ start_ptr = (t_u8 *)(*ppbuffer);
+
+ PRINTM(MINFO,
+ "11h: Set local power constraint = %d channel=%d min_tx_pwr=%d max_tx_pwr=%d\n",
+ power_constraint, channel, min_tx_power_capability,
+ max_tx_power_capability);
+
+ pcap = (MrvlIEtypes_PowerCapability_t *)*ppbuffer;
+ pcap->header.type = wlan_cpu_to_le16(TLV_TYPE_POWER_CAPABILITY);
+ pcap->header.len = wlan_cpu_to_le16(2);
+ pcap->min_power = min_tx_power_capability;
+ pcap->max_power = max_tx_power_capability;
+ *ppbuffer += sizeof(MrvlIEtypesHeader_t) + 2;
+
+ pconstraint = (MrvlIEtypes_LocalPowerConstraint_t *)*ppbuffer;
+ pconstraint->header.type = wlan_cpu_to_le16(TLV_TYPE_POWER_CONSTRAINT);
+ pconstraint->header.len = wlan_cpu_to_le16(2);
+ pconstraint->chan = channel;
+ pconstraint->constraint = power_constraint;
+ *ppbuffer += sizeof(MrvlIEtypesHeader_t) + 2;
+
+ LEAVE();
+ return (t_u32)(*ppbuffer - start_ptr);
+}
+
+/**
+ * @brief Utility function to process a join to an infrastructure BSS
+ *
+ * @param priv Private driver information structure
+ * @param ppbuffer Output parameter: Pointer to the TLV output buffer,
+ * modified on return to point after the appended 11h TLVs
+ * @param band Band on which we are joining the BSS
+ * @param channel Channel on which we are joining the BSS
+ * @param p11h_bss_info Pointer to the 11h BSS information for this network
+ * that was parsed out of the scan response.
+ *
+ * @return Integer number of bytes appended to the TLV output
+ * buffer (ppbuffer)
+ */
+static t_u32 wlan_11h_process_infra_join(mlan_private *priv, t_u8 **ppbuffer,
+ t_u8 band, t_u32 channel,
+ wlan_11h_bss_info_t *p11h_bss_info)
+{
+ MrvlIEtypesHeader_t ie_header;
+ IEEEtypes_SupportedChannels_t sup_chan_ie;
+ t_u32 ret_len = 0;
+ t_u16 sup_chan_len = 0;
+
+ ENTER();
+
+ /* Null Checks */
+ if ((ppbuffer == MNULL) || (((t_u8 *)(*ppbuffer)) == MNULL)) {
+ LEAVE();
+ return 0;
+ }
+
+ ret_len += wlan_11h_set_local_power_constraint_tlv(
+ ppbuffer, (t_u8)channel,
+ (t_u8)p11h_bss_info->power_constraint.local_constraint,
+ (t_u8)priv->adapter->state_11h.min_tx_power_capability,
+ (t_u8)priv->adapter->state_11h.max_tx_power_capability);
+
+ /* Setup the Supported Channels IE */
+ sup_chan_len = wlan_11h_set_supp_channels_ie(priv, band, &sup_chan_ie);
+
+ /*
+ * If we returned a valid Supported Channels IE, wrap and append it
+ */
+ if (sup_chan_len) {
+ /* Wrap the supported channels IE with a passthrough TLV type */
+ ie_header.type = wlan_cpu_to_le16(TLV_TYPE_PASSTHROUGH);
+ ie_header.len = wlan_cpu_to_le16(sup_chan_len);
+ memcpy_ext(priv->adapter, *ppbuffer, &ie_header,
+ sizeof(ie_header), sizeof(ie_header));
+
+ /*
+ * Increment the return size and the return buffer
+ * pointer param
+ */
+ *ppbuffer += sizeof(ie_header);
+ ret_len += sizeof(ie_header);
+
+ /*
+ * Copy the supported channels IE to the output buf,
+ * advance pointer
+ */
+ memcpy_ext(priv->adapter, *ppbuffer, &sup_chan_ie, sup_chan_len,
+ sup_chan_len);
+ *ppbuffer += sup_chan_len;
+ ret_len += sup_chan_len;
+ }
+
+ LEAVE();
+ return ret_len;
+}
+
+/**
+ * @brief Utility function to process a start or join to an adhoc network
+ *
+ * Add the elements to the TLV buffer needed in the start/join adhoc commands:
+ * - IBSS DFS IE
+ * - Quiet IE
+ *
+ * Also send the local constraint to the firmware in a TPC_INFO command.
+ *
+ * @param priv Private driver information structure
+ * @param ppbuffer Output parameter: Pointer to the TLV output buffer,
+ * modified on return to point after the appended 11h TLVs
+ * @param channel Channel on which we are starting/joining the IBSS
+ * @param p11h_bss_info Pointer to the 11h BSS information for this network
+ * that was parsed out of the scan response. NULL
+ * indicates we are starting the adhoc network
+ *
+ * @return Integer number of bytes appended to the TLV output
+ * buffer (ppbuffer)
+ */
+static t_u32 wlan_11h_process_adhoc(mlan_private *priv, t_u8 **ppbuffer,
+ t_u32 channel,
+ wlan_11h_bss_info_t *p11h_bss_info)
+{
+ IEEEtypes_IBSS_DFS_t dfs_elem;
+ t_u32 size_appended;
+ t_u32 ret_len = 0;
+ t_s8 local_constraint = 0;
+ mlan_adapter *adapter = priv->adapter;
+
+ ENTER();
+
+#ifdef STA_SUPPORT
+ /* Format our own IBSS DFS Element. Include our channel map fields */
+ wlan_11h_set_ibss_dfs_ie(priv, &dfs_elem);
+#endif
+
+ if (p11h_bss_info) {
+ /*
+ * Copy the DFS Owner/Recovery Interval from the BSS
+ * we are joining
+ */
+ memcpy_ext(adapter, dfs_elem.dfs_owner,
+ p11h_bss_info->ibss_dfs.dfs_owner,
+ sizeof(dfs_elem.dfs_owner),
+ sizeof(dfs_elem.dfs_owner));
+ dfs_elem.dfs_recovery_interval =
+ p11h_bss_info->ibss_dfs.dfs_recovery_interval;
+ }
+
+ /* Append the dfs element to the TLV buffer */
+ size_appended = wlan_11h_convert_ieee_to_mrvl_ie(
+ adapter, (t_u8 *)*ppbuffer, (t_u8 *)&dfs_elem);
+
+ HEXDUMP("11h: IBSS-DFS", (t_u8 *)*ppbuffer, size_appended);
+ *ppbuffer += size_appended;
+ ret_len += size_appended;
+
+ /*
+ * Check to see if we are joining a network. Join is indicated by the
+ * BSS Info pointer being valid (not NULL)
+ */
+ if (p11h_bss_info) {
+ /*
+ * If there was a quiet element, include it in
+ * adhoc join command
+ */
+ if (p11h_bss_info->quiet.element_id == QUIET) {
+ size_appended = wlan_11h_convert_ieee_to_mrvl_ie(
+ adapter, (t_u8 *)*ppbuffer,
+ (t_u8 *)&p11h_bss_info->quiet);
+ HEXDUMP("11h: Quiet", (t_u8 *)*ppbuffer, size_appended);
+ *ppbuffer += size_appended;
+ ret_len += size_appended;
+ }
+
+ /* Copy the local constraint from the network */
+ local_constraint =
+ p11h_bss_info->power_constraint.local_constraint;
+ } else {
+ /*
+ * If we are the adhoc starter, we can add a quiet element
+ */
+ if (adapter->state_11h.quiet_ie.quiet_period) {
+ size_appended = wlan_11h_convert_ieee_to_mrvl_ie(
+ adapter, (t_u8 *)*ppbuffer,
+ (t_u8 *)&adapter->state_11h.quiet_ie);
+ HEXDUMP("11h: Quiet", (t_u8 *)*ppbuffer, size_appended);
+ *ppbuffer += size_appended;
+ ret_len += size_appended;
+ }
+ /* Use the local_constraint configured in the driver state */
+ local_constraint = adapter->state_11h.usr_def_power_constraint;
+ }
+
+ PRINTM(MINFO, "WEILIE 1: ppbuffer = %p\n", *ppbuffer);
+
+ ret_len += wlan_11h_set_local_power_constraint_tlv(
+ ppbuffer, (t_u8)channel, (t_u8)local_constraint,
+ (t_u8)priv->adapter->state_11h.min_tx_power_capability,
+ (t_u8)priv->adapter->state_11h.max_tx_power_capability);
+ PRINTM(MINFO, "WEILIE 2: ppbuffer = %p\n", *ppbuffer);
+
+ LEAVE();
+ return ret_len;
+}
+
+/**
+ * @brief Return whether the driver has enabled 11h for the interface
+ *
+ * Association/Join commands are dynamic in that they enable 11h in the
+ * driver/firmware when they are detected in the existing BSS.
+ *
+ * @param priv Private driver information structure
+ *
+ * @return
+ * - MTRUE if 11h is enabled
+ * - MFALSE otherwise
+ */
+static t_bool wlan_11h_is_enabled(mlan_private *priv)
+{
+ ENTER();
+ LEAVE();
+ return priv->intf_state_11h.is_11h_enabled;
+}
+
+/**
+ * @brief Return whether the device has activated slave radar detection.
+ *
+ * @param priv Private driver information structure
+ *
+ * @return
+ * - MTRUE if slave radar detection is enabled in firmware
+ * - MFALSE otherwise
+ */
+static t_bool wlan_11h_is_slave_radar_det_active(mlan_private *priv)
+{
+ ENTER();
+ LEAVE();
+ return priv->adapter->state_11h.is_slave_radar_det_active;
+}
+/**
+ * @brief Return whether the slave interface is active, and on DFS channel.
+ * priv is assumed to already be a dfs slave interface, doesn't check this.
+ *
+ * @param priv Private driver information structure
+ *
+ * @return
+ * - MTRUE if priv is slave, and meets both conditions
+ * - MFALSE otherwise
+ */
+static t_bool wlan_11h_is_slave_active_on_dfs_chan(mlan_private *priv)
+{
+ t_bool ret = MFALSE;
+
+ ENTER();
+ if ((priv->media_connected == MTRUE) &&
+ (priv->curr_bss_params.band & BAND_A) &&
+ wlan_11h_radar_detect_required(
+ priv, priv->curr_bss_params.bss_descriptor.channel))
+ ret = MTRUE;
+
+ LEAVE();
+ return ret;
+}
+
+/**
+ * @brief Return whether the master interface is active, and on DFS channel.
+ * priv is assumed to already be a dfs master interface, doesn't check this.
+ *
+ * @param priv Private driver information structure
+ *
+ * @return
+ * - MTRUE if priv is master, and meets both conditions
+ * - MFALSE otherwise
+ */
+static t_bool wlan_11h_is_master_active_on_dfs_chan(mlan_private *priv)
+{
+ t_bool ret = MFALSE;
+
+ ENTER();
+ if (GET_BSS_ROLE(priv) == MLAN_BSS_ROLE_STA) {
+ /* Ad-hoc creator */
+ if (((priv->media_connected == MTRUE) ||
+ (priv->adhoc_state == ADHOC_STARTING)) &&
+ (priv->adapter->adhoc_start_band & BAND_A) &&
+ wlan_11h_radar_detect_required(priv, priv->adhoc_channel))
+ ret = MTRUE;
+ } else if (GET_BSS_ROLE(priv) == MLAN_BSS_ROLE_UAP) {
+ /* UAP */
+#ifdef UAP_SUPPORT
+ if ((priv->uap_bss_started == MTRUE) &&
+ (priv->uap_state_chan_cb.bandcfg.chanBand == BAND_5GHZ) &&
+ wlan_11h_radar_detect_required(
+ priv, priv->uap_state_chan_cb.channel))
+ ret = MTRUE;
+#endif
+ }
+ LEAVE();
+ return ret;
+}
+
+/**
+ * @brief Determine if priv is DFS Master interface
+ *
+ * @param priv Pointer to mlan_private
+ *
+ * @return MTRUE or MFALSE
+ */
+static t_bool wlan_11h_is_dfs_master(mlan_private *priv)
+{
+ t_bool ret = MFALSE;
+
+ ENTER();
+ /* UAP: all are master */
+ if (GET_BSS_ROLE(priv) == MLAN_BSS_ROLE_UAP)
+ ret = MTRUE;
+
+ /* STA: only ad-hoc creator is master */
+ else if ((GET_BSS_ROLE(priv) == MLAN_BSS_ROLE_STA) &&
+ (priv->bss_mode == MLAN_BSS_MODE_IBSS) &&
+ (priv->adhoc_state == ADHOC_STARTED ||
+ priv->adhoc_state == ADHOC_STARTING))
+ ret = MTRUE;
+
+ /* all other cases = slave interface */
+ LEAVE();
+ return ret;
+}
+
+/* Need this as function to pass to wlan_count_priv_cond() */
+/**
+ * @brief Determine if priv is DFS Slave interface
+ *
+ * @param priv Pointer to mlan_private
+ *
+ * @return MTRUE or MFALSE
+ */
+
+static t_bool wlan_11h_is_dfs_slave(mlan_private *priv)
+{
+ t_bool ret = MFALSE;
+ ENTER();
+ ret = !wlan_11h_is_dfs_master(priv);
+ LEAVE();
+ return ret;
+}
+
+/**
+ * @brief This function checks if interface is active.
+ *
+ * @param pmpriv A pointer to mlan_private structure
+ *
+ * @return MTRUE or MFALSE
+ */
+t_bool wlan_is_intf_active(mlan_private *pmpriv)
+{
+ t_bool ret = MFALSE;
+ ENTER();
+
+#ifdef UAP_SUPPORT
+ if (GET_BSS_ROLE(pmpriv) == MLAN_BSS_ROLE_UAP)
+ /*
+ * NOTE: UAP's media_connected == true only after first STA
+ * associated. Need different variable to tell if UAP
+ * has been started.
+ */
+ ret = pmpriv->uap_bss_started;
+ else
+#endif
+ if (GET_BSS_ROLE(pmpriv) == MLAN_BSS_ROLE_STA)
+ ret = pmpriv->media_connected;
+
+ LEAVE();
+ return ret;
+}
+
+/**
+ * @brief This function gets current radar detect flags
+ *
+ * @param pmadapter A pointer to mlan_adapter structure
+ *
+ * @return 11H MIB setting for radar detect
+ */
+static t_u32 wlan_11h_get_current_radar_detect_flags(mlan_adapter *pmadapter)
+{
+ t_u32 radar_det_flags = 0;
+
+ ENTER();
+ if (pmadapter->state_11h.is_master_radar_det_active)
+ radar_det_flags |= MASTER_RADAR_DET_MASK;
+ if (pmadapter->state_11h.is_slave_radar_det_active)
+ radar_det_flags |= SLAVE_RADAR_DET_MASK;
+
+ PRINTM(MINFO, "%s: radar_det_state_curr=0x%x\n", __func__,
+ radar_det_flags);
+
+ LEAVE();
+ return radar_det_flags;
+}
+
+/**
+ * @brief This function checks if radar detect flags have/should be changed.
+ *
+ * @param pmadapter A pointer to mlan_adapter structure
+ * @param pnew_state Output param with new state, if return MTRUE.
+ *
+ * @return MTRUE (need update) or MFALSE (no change in flags)
+ */
+static t_bool wlan_11h_check_radar_det_state(mlan_adapter *pmadapter,
+ t_u32 *pnew_state)
+{
+ t_u32 radar_det_state_new = 0;
+ t_bool ret;
+
+ ENTER();
+ PRINTM(MINFO,
+ "%s: master_radar_det_pending=%d, "
+ " slave_radar_det_pending=%d\n",
+ __func__, pmadapter->state_11h.master_radar_det_enable_pending,
+ pmadapter->state_11h.slave_radar_det_enable_pending);
+
+ /* new state comes from evaluating interface states & pending starts */
+ if (pmadapter->state_11h.master_radar_det_enable_pending ||
+ (wlan_count_priv_cond(pmadapter,
+ wlan_11h_is_master_active_on_dfs_chan,
+ wlan_11h_is_dfs_master) > 0))
+ radar_det_state_new |= MASTER_RADAR_DET_MASK;
+ if (pmadapter->state_11h.slave_radar_det_enable_pending ||
+ (wlan_count_priv_cond(pmadapter,
+ wlan_11h_is_slave_active_on_dfs_chan,
+ wlan_11h_is_dfs_slave) > 0))
+ radar_det_state_new |= SLAVE_RADAR_DET_MASK;
+
+ PRINTM(MINFO, "%s: radar_det_state_new=0x%x\n", __func__,
+ radar_det_state_new);
+
+ /* now compare flags with current state */
+ ret = (wlan_11h_get_current_radar_detect_flags(pmadapter) !=
+ radar_det_state_new) ?
+ MTRUE :
+ MFALSE;
+ if (ret)
+ *pnew_state = radar_det_state_new;
+
+ LEAVE();
+ return ret;
+}
+
+/**
+ * @brief generate the channel center frequency index
+ *
+ * @param channel_num channel number
+ *
+ * @return frenquency index
+ */
+static t_u8 wlan_11h_get_channel_freq_idx(t_u8 channel_num)
+{
+ t_u8 index;
+ t_u8 center_freq[] = {42, 58, 106, 122, 138, 155};
+ t_u8 chan_idx, ret = 0;
+
+ chan_idx = channel_num - 100;
+
+ for (index = 0; index < sizeof(center_freq); index++) {
+ if ((chan_idx >= (center_freq[index] - 6)) &&
+ (chan_idx <= (center_freq[index] + 6))) {
+ ret = center_freq[index];
+ break;
+ }
+ }
+
+ return ret;
+}
+
+/**
+ * @brief Prepare ioctl for add/remove CHAN_SW IE - RADAR_DETECTED event
+ * handling
+ *
+ * @param pmadapter Pointer to mlan_adapter
+ * @param pioctl_req Pointer to completed mlan_ioctl_req (allocated
+ * inside)
+ * @param ppcust_chansw_ie Poniter to customer ie
+ * @param is_adding_ie CHAN_SW IE is to be added (MTRUE), or removed
+ * (MFALSE)
+ *
+ * @return MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ */
+static mlan_status
+wlan_11h_prepare_custom_ie_chansw(mlan_adapter *pmadapter,
+ mlan_ioctl_req **ppioctl_req,
+ t_bool is_adding_ie)
+{
+ mlan_ioctl_req *pioctl_req = MNULL;
+ mlan_ds_misc_cfg *pds_misc_cfg = MNULL;
+ custom_ie *pcust_chansw_ie = MNULL;
+ IEEEtypes_ChanSwitchAnn_t *pchansw_ie = MNULL;
+ mlan_status ret;
+ IEEEtypes_Header_t *pChanSwWrap_ie = MNULL;
+ IEEEtypes_WideBWChanSwitch_t *pbwchansw_ie = MNULL;
+ IEEEtypes_VhtTpcEnvelope_t *pvhttpcEnv_ie = MNULL;
+ t_u8 index;
+ mlan_private *pmpriv = MNULL;
+
+ ENTER();
+
+ if (pmadapter == MNULL || ppioctl_req == MNULL) {
+ LEAVE();
+ return MLAN_STATUS_FAILURE;
+ }
+
+ /* allocate buffer for mlan_ioctl_req and mlan_ds_misc_cfg */
+ /* FYI - will be freed as part of cmd_response handler */
+ ret = pmadapter->callbacks.moal_malloc(
+ pmadapter->pmoal_handle,
+ sizeof(mlan_ioctl_req) + sizeof(mlan_ds_misc_cfg), MLAN_MEM_DEF,
+ (t_u8 **)&pioctl_req);
+ if ((ret != MLAN_STATUS_SUCCESS) || !pioctl_req) {
+ PRINTM(MERROR, "%s(): Could not allocate ioctl req\n",
+ __func__);
+ LEAVE();
+ return MLAN_STATUS_FAILURE;
+ }
+ pds_misc_cfg = (mlan_ds_misc_cfg *)((t_u8 *)pioctl_req +
+ sizeof(mlan_ioctl_req));
+
+ /* prepare mlan_ioctl_req */
+ memset(pmadapter, pioctl_req, 0x00, sizeof(mlan_ioctl_req));
+ pioctl_req->req_id = MLAN_IOCTL_MISC_CFG;
+ pioctl_req->action = MLAN_ACT_SET;
+ pioctl_req->pbuf = (t_u8 *)pds_misc_cfg;
+ pioctl_req->buf_len = sizeof(mlan_ds_misc_cfg);
+
+ /* prepare mlan_ds_misc_cfg */
+ memset(pmadapter, pds_misc_cfg, 0x00, sizeof(mlan_ds_misc_cfg));
+ pds_misc_cfg->sub_command = MLAN_OID_MISC_CUSTOM_IE;
+ pds_misc_cfg->param.cust_ie.type = TLV_TYPE_MGMT_IE;
+ pds_misc_cfg->param.cust_ie.len = (sizeof(custom_ie) - MAX_IE_SIZE);
+
+ /* configure custom_ie api settings */
+ pcust_chansw_ie =
+ (custom_ie *)&pds_misc_cfg->param.cust_ie.ie_data_list[0];
+ pcust_chansw_ie->ie_index = 0xffff; /* Auto index */
+ pcust_chansw_ie->ie_length = sizeof(IEEEtypes_ChanSwitchAnn_t);
+ pcust_chansw_ie->mgmt_subtype_mask =
+ (is_adding_ie) ? MBIT(8) | MBIT(5) /* add IE for BEACON |
+ PROBE_RSP */
+ :
+ 0; /* remove IE */
+
+ /* prepare CHAN_SW IE inside ioctl */
+ pchansw_ie = (IEEEtypes_ChanSwitchAnn_t *)pcust_chansw_ie->ie_buffer;
+ pchansw_ie->element_id = CHANNEL_SWITCH_ANN;
+ pchansw_ie->len =
+ sizeof(IEEEtypes_ChanSwitchAnn_t) - sizeof(IEEEtypes_Header_t);
+ pchansw_ie->chan_switch_mode = 1; /* STA should not transmit */
+ pchansw_ie->new_channel_num = pmadapter->state_rdh.new_channel;
+
+ pchansw_ie->chan_switch_count = pmadapter->dfs_cs_count;
+ PRINTM(MCMD_D, "New Channel = %d Channel switch count = %d\n",
+ pmadapter->state_rdh.new_channel, pchansw_ie->chan_switch_count);
+
+ for (index = 0; index < pmadapter->state_rdh.priv_list_count; index++) {
+ pmpriv = pmadapter->state_rdh.priv_list[index];
+ /*find the first AP interface*/
+ if (GET_BSS_ROLE(pmpriv) == MLAN_BSS_ROLE_UAP) {
+ if (pmpriv->is_11ac_enabled) {
+ pChanSwWrap_ie =
+ (IEEEtypes_Header_t
+ *)((t_u8 *)pchansw_ie +
+ sizeof(IEEEtypes_ChanSwitchAnn_t));
+ pChanSwWrap_ie->element_id = EXT_POWER_CONSTR;
+ /*will have multiple sub IEs*/
+ pChanSwWrap_ie->len = 0;
+
+ /* prepare the Wide Bandwidth Channel Switch IE
+ * Channel Switch IE */
+ pbwchansw_ie =
+ (IEEEtypes_WideBWChanSwitch_t
+ *)((t_u8 *)pChanSwWrap_ie +
+ sizeof(IEEEtypes_Header_t));
+ pbwchansw_ie->ieee_hdr.element_id =
+ BW_CHANNEL_SWITCH;
+ pbwchansw_ie->ieee_hdr.len =
+ sizeof(IEEEtypes_WideBWChanSwitch_t) -
+ sizeof(IEEEtypes_Header_t);
+ /*fix 80MHZ now*/
+ pbwchansw_ie->new_channel_width =
+ VHT_OPER_CHWD_80MHZ;
+ pbwchansw_ie->new_channel_center_freq0 =
+ wlan_11h_get_channel_freq_idx(
+ pmadapter->state_rdh
+ .new_channel);
+ pbwchansw_ie->new_channel_center_freq1 =
+ wlan_11h_get_channel_freq_idx(
+ pmadapter->state_rdh
+ .new_channel);
+ pChanSwWrap_ie->len +=
+ sizeof(IEEEtypes_WideBWChanSwitch_t);
+
+ /*prepare the VHT Transmit Power Envelope IE*/
+ pvhttpcEnv_ie =
+ (IEEEtypes_VhtTpcEnvelope_t
+ *)((t_u8 *)pChanSwWrap_ie +
+ sizeof(IEEEtypes_Header_t) +
+ sizeof(IEEEtypes_WideBWChanSwitch_t));
+ pvhttpcEnv_ie->ieee_hdr.element_id =
+ VHT_TX_POWER_ENV;
+ pvhttpcEnv_ie->ieee_hdr.len =
+ sizeof(IEEEtypes_VhtTpcEnvelope_t) -
+ sizeof(IEEEtypes_Header_t);
+ /* Local Max TX Power Count= 3,
+ * Local TX Power Unit Inter=EIP(0) */
+ pvhttpcEnv_ie->tpc_info = 3;
+ pvhttpcEnv_ie->local_max_tp_20mhz = 0xff;
+ pvhttpcEnv_ie->local_max_tp_40mhz = 0xff;
+ pvhttpcEnv_ie->local_max_tp_80mhz = 0xff;
+ pChanSwWrap_ie->len +=
+ sizeof(IEEEtypes_VhtTpcEnvelope_t);
+
+ pcust_chansw_ie->ie_length +=
+ sizeof(IEEEtypes_WideBWChanSwitch_t) +
+ sizeof(IEEEtypes_VhtTpcEnvelope_t) +
+ sizeof(IEEEtypes_Header_t);
+
+ PRINTM(MINFO,
+ "Append Wide Bandwidth Channel Switch IE\n");
+ break;
+ }
+ }
+ }
+
+ pds_misc_cfg->param.cust_ie.len += pcust_chansw_ie->ie_length;
+ DBG_HEXDUMP(MCMD_D, "11h: custom_ie containing CHAN_SW IE",
+ (t_u8 *)pcust_chansw_ie, pds_misc_cfg->param.cust_ie.len);
+
+ /* assign output pointer before returning */
+ *ppioctl_req = pioctl_req;
+ LEAVE();
+ return MLAN_STATUS_SUCCESS;
+}
+
+#ifdef UAP_SUPPORT
+/** Bits 2,3 of band config define the band width */
+#define UAP_BAND_WIDTH_MASK 0x0C
+
+/**
+ * @brief Check if start channel 165 is allowed to operate in
+ * previous uAP channel's band config
+ *
+ * @param start_chn Random Start channel choosen after radar detection
+ * @param uap_band_cfg Private driver uAP band configuration information
+ * structure
+ *
+ * @return MFALSE if the channel is not allowed in given band
+ */
+static t_bool wlan_11h_is_band_valid(t_u8 start_chn, Band_Config_t uap_band_cfg)
+{
+ /* if band width is not 20MHZ (either 40 or 80MHz)
+ * return MFALSE, 165 is not allowed in bands other than 20MHZ
+ */
+ if (start_chn == 165 && (uap_band_cfg.chanWidth != CHAN_BW_20MHZ)) {
+ return MFALSE;
+ }
+ return MTRUE;
+}
+
+/**
+ * @brief Retrieve a randomly selected starting channel if needed for 11h
+ *
+ * If 11h is enabled and 5GHz band is selected in band_config
+ * return a random channel in A band, else one from BG band.
+ *
+ * @param priv Private driver information structure
+ * @param uap_band_cfg Private driver information structure
+ *
+ * @return Starting channel
+ */
+static t_u8 wlan_11h_get_uap_start_channel(mlan_private *priv,
+ Band_Config_t uap_band_cfg)
+{
+ t_u8 start_chn;
+ mlan_adapter *adapter = priv->adapter;
+ t_u32 region;
+ t_u32 rand_entry;
+ region_chan_t *chn_tbl;
+ t_u8 rand_tries = 0;
+
+ /*TODO: right now mostly a copy of wlan_11h_get_adhoc_start_channel.
+ * Improve to be more specfic to UAP, e.g.
+ * 1. take into account COUNTRY_CODE -> region_code
+ * 2. check domain_info for value channels
+ */
+ ENTER();
+
+ /*
+ * Set start_chn to the Default.
+ * Used if 11h is disabled or the band
+ * does not require 11h support.
+ */
+ start_chn = DEFAULT_AD_HOC_CHANNEL;
+
+ /*
+ * Check that we are looking for a channel in the A Band
+ */
+ if (uap_band_cfg.chanBand == BAND_5GHZ) {
+ /*
+ * Set default to the A Band default.
+ * Used if random selection fails
+ * or if 11h is not enabled
+ */
+ start_chn = DEFAULT_AD_HOC_CHANNEL_A;
+
+ /*
+ * Check that 11h is enabled in the driver
+ */
+ if (wlan_11h_is_enabled(priv)) {
+ /*
+ * Search the region_channel tables for a channel table
+ * that is marked for the A Band.
+ */
+ for (region = 0; (region < MAX_REGION_CHANNEL_NUM);
+ region++) {
+ chn_tbl = &adapter->region_channel[region];
+
+ /* Check if table is valid and marked for A Band
+ */
+ if (chn_tbl->valid &&
+ chn_tbl->region == adapter->region_code &&
+ chn_tbl->band & BAND_A) {
+ /*
+ * Set the start channel. Get a random
+ * number and use it to pick an entry
+ * in the table between 0 and the number
+ * of channels in the table (NumCFP).
+ */
+ rand_entry = wlan_11h_get_random_num(
+ adapter) %
+ chn_tbl->num_cfp;
+ start_chn =
+ (t_u8)chn_tbl->pcfp[rand_entry]
+ .channel;
+ /* Loop until a non-dfs channel is found
+ * with compatible band bounded by
+ * chn_tbl->num_cfp entries in the
+ * channel table
+ */
+ while (((chn_tbl->pcfp[rand_entry]
+ .dynamic.flags &
+ NXP_CHANNEL_DISABLED) ||
+ (wlan_11h_is_channel_under_nop(
+ adapter, start_chn) ||
+ ((adapter->state_rdh.stage ==
+ RDH_GET_INFO_CHANNEL) &&
+ wlan_11h_radar_detect_required(
+ priv, start_chn)) ||
+ !(wlan_11h_is_band_valid(
+ start_chn,
+ uap_band_cfg)))) &&
+ (++rand_tries <
+ chn_tbl->num_cfp)) {
+ rand_entry++;
+ rand_entry = rand_entry %
+ chn_tbl->num_cfp;
+ start_chn =
+ (t_u8)chn_tbl
+ ->pcfp[rand_entry]
+ .channel;
+ PRINTM(MINFO,
+ "start chan=%d rand_entry=%d\n",
+ start_chn, rand_entry);
+ }
+
+ if (rand_tries == chn_tbl->num_cfp) {
+ PRINTM(MERROR,
+ "Failed to get UAP start channel\n");
+ start_chn = 0;
+ }
+ }
+ }
+ }
+ }
+
+ PRINTM(MCMD_D, "11h: UAP Get Start Channel %d\n", start_chn);
+ LEAVE();
+ return start_chn;
+}
+#endif /* UAP_SUPPORT */
+
+#ifdef DEBUG_LEVEL1
+static const char *DFS_TS_REPR_STRINGS[] = {"", "NOP_start", "CAC_completed"};
+#endif
+
+/**
+ * @brief Search for a dfs timestamp in the list with desired channel.
+ *
+ * Assumes there will only be one timestamp per channel in the list.
+ *
+ * @param pmadapter Pointer to mlan_adapter
+ * @param channel Channel number
+ *
+ * @return Pointer to timestamp if found, or MNULL
+ */
+static wlan_dfs_timestamp_t *
+wlan_11h_find_dfs_timestamp(mlan_adapter *pmadapter, t_u8 channel)
+{
+ wlan_dfs_timestamp_t *pts = MNULL, *pts_found = MNULL;
+
+ ENTER();
+ pts = (wlan_dfs_timestamp_t *)util_peek_list(
+ pmadapter->pmoal_handle, &pmadapter->state_dfs.dfs_ts_head,
+ MNULL, MNULL);
+
+ while (pts && pts != (wlan_dfs_timestamp_t *)&pmadapter->state_dfs
+ .dfs_ts_head) {
+ PRINTM(MINFO,
+ "dfs_timestamp(@ %p) - chan=%d, repr=%d(%s),"
+ " time(sec.usec)=%lu.%06lu\n",
+ pts, pts->channel, pts->represents,
+ DFS_TS_REPR_STRINGS[pts->represents], pts->ts_sec,
+ pts->ts_usec);
+
+ if (pts->channel == channel) {
+ pts_found = pts;
+ break;
+ }
+ pts = pts->pnext;
+ }
+
+ LEAVE();
+ return pts_found;
+}
+
+/**
+ * @brief Removes dfs timestamp from list.
+ *
+ * @param pmadapter Pointer to mlan_adapter
+ * @param pdfs_ts Pointer to dfs_timestamp to remove
+ */
+static t_void wlan_11h_remove_dfs_timestamp(mlan_adapter *pmadapter,
+ wlan_dfs_timestamp_t *pdfs_ts)
+{
+ ENTER();
+ /* dequeue and delete timestamp */
+ util_unlink_list(pmadapter->pmoal_handle,
+ &pmadapter->state_dfs.dfs_ts_head,
+ (pmlan_linked_list)pdfs_ts, MNULL, MNULL);
+ pmadapter->callbacks.moal_mfree(pmadapter->pmoal_handle,
+ (t_u8 *)pdfs_ts);
+ LEAVE();
+}
+
+/**
+ * @brief Add a dfs timestamp to the list
+ *
+ * Assumes there will only be one timestamp per channel in the list,
+ * and that timestamp modes (represents) are mutually exclusive.
+ *
+ * @param pmadapter Pointer to mlan_adapter
+ * @param repr Timestamp 'represents' value (see _dfs_timestamp_repr_e)
+ * @param channel Channel number
+ *
+ * @return Pointer to timestamp if found, or MNULL
+ */
+static mlan_status wlan_11h_add_dfs_timestamp(mlan_adapter *pmadapter,
+ t_u8 repr, t_u8 channel)
+{
+ wlan_dfs_timestamp_t *pdfs_ts = MNULL;
+ mlan_status ret = MLAN_STATUS_SUCCESS;
+
+ ENTER();
+ pdfs_ts = wlan_11h_find_dfs_timestamp(pmadapter, channel);
+
+ if (!pdfs_ts) {
+ /* need to allocate new timestamp */
+ ret = pmadapter->callbacks.moal_malloc(
+ pmadapter->pmoal_handle, sizeof(wlan_dfs_timestamp_t),
+ MLAN_MEM_DEF, (t_u8 **)&pdfs_ts);
+ if ((ret != MLAN_STATUS_SUCCESS) || !pdfs_ts) {
+ PRINTM(MERROR, "%s(): Could not allocate dfs_ts\n",
+ __func__);
+ LEAVE();
+ return MLAN_STATUS_FAILURE;
+ }
+
+ memset(pmadapter, (t_u8 *)pdfs_ts, 0,
+ sizeof(wlan_dfs_timestamp_t));
+
+ util_enqueue_list_tail(pmadapter->pmoal_handle,
+ &pmadapter->state_dfs.dfs_ts_head,
+ (pmlan_linked_list)pdfs_ts, MNULL,
+ MNULL);
+ pdfs_ts->channel = channel;
+ }
+ /* (else, use existing timestamp for channel; see assumptions above) */
+
+ /* update params */
+ pmadapter->callbacks.moal_get_system_time(
+ pmadapter->pmoal_handle, &pdfs_ts->ts_sec, &pdfs_ts->ts_usec);
+ pdfs_ts->represents = repr;
+
+ PRINTM(MCMD_D,
+ "11h: add/update dfs_timestamp - chan=%d, repr=%d(%s),"
+ " time(sec.usec)=%lu.%06lu\n",
+ pdfs_ts->channel, pdfs_ts->represents,
+ DFS_TS_REPR_STRINGS[pdfs_ts->represents], pdfs_ts->ts_sec,
+ pdfs_ts->ts_usec);
+
+ LEAVE();
+ return ret;
+}
+
+/********************************************************
+ Global functions
+********************************************************/
+
+/**
+ * @brief Return whether the device has activated master radar detection.
+ *
+ * @param priv Private driver information structure
+ *
+ * @return
+ * - MTRUE if master radar detection is enabled in firmware
+ * - MFALSE otherwise
+ */
+t_bool wlan_11h_is_master_radar_det_active(mlan_private *priv)
+{
+ ENTER();
+ LEAVE();
+ return priv->adapter->state_11h.is_master_radar_det_active;
+}
+
+/**
+ * @brief Configure master radar detection.
+ * Call wlan_11h_check_update_radar_det_state() afterwards
+ * to push this to firmware.
+ *
+ * @param priv Private driver information structure
+ * @param enable Whether to enable or disable master radar detection
+ *
+ * @return MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ *
+ * @sa wlan_11h_check_update_radar_det_state
+ */
+mlan_status wlan_11h_config_master_radar_det(mlan_private *priv, t_bool enable)
+{
+ mlan_status ret = MLAN_STATUS_FAILURE;
+
+ /* Force disable master radar detection on in-AP interfaces */
+ if (priv->adapter->dfs_repeater)
+ enable = MFALSE;
+
+ ENTER();
+ if (wlan_11h_is_dfs_master(priv) &&
+ priv->adapter->init_para.dfs_master_radar_det_en) {
+ priv->adapter->state_11h.master_radar_det_enable_pending =
+ enable;
+ ret = MLAN_STATUS_SUCCESS;
+ }
+
+ LEAVE();
+ return ret;
+}
+
+/**
+ * @brief Configure slave radar detection.
+ * Call wlan_11h_check_update_radar_det_state() afterwards
+ * to push this to firmware.
+ *
+ * @param priv Private driver information structure
+ * @param enable Whether to enable or disable slave radar detection
+ *
+ * @return MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ *
+ * @sa wlan_11h_check_update_radar_det_state
+ */
+mlan_status wlan_11h_config_slave_radar_det(mlan_private *priv, t_bool enable)
+{
+ mlan_status ret = MLAN_STATUS_FAILURE;
+
+ /* Force disable radar detection on STA interfaces */
+ if (priv->adapter->dfs_repeater)
+ enable = MFALSE;
+
+ ENTER();
+ if (wlan_11h_is_dfs_slave(priv) &&
+ priv->adapter->init_para.dfs_slave_radar_det_en) {
+ priv->adapter->state_11h.slave_radar_det_enable_pending =
+ enable;
+ ret = MLAN_STATUS_SUCCESS;
+ }
+ LEAVE();
+ return ret;
+}
+
+/**
+ * @brief Checks all interfaces and determines if radar_detect flag states
+ * have/should be changed. If so, sends SNMP_MIB 11H command to FW.
+ * Call this function on any interface enable/disable/channel change.
+ *
+ * @param pmpriv Pointer to mlan_private structure
+ *
+ * @return MLAN_STATUS_SUCCESS (update or not)
+ * or MLAN_STATUS_FAILURE (cmd failure)
+ *
+ * @sa wlan_11h_check_radar_det_state
+ */
+mlan_status wlan_11h_check_update_radar_det_state(mlan_private *pmpriv)
+{
+ t_u32 new_radar_det_state = 0;
+ t_u32 mib_11h = 0;
+ mlan_status ret = MLAN_STATUS_SUCCESS;
+
+ ENTER();
+
+ if (wlan_11h_check_radar_det_state(pmpriv->adapter,
+ &new_radar_det_state)) {
+ PRINTM(MCMD_D, "%s: radar_det_state being updated.\n",
+ __func__);
+
+ mib_11h |= new_radar_det_state;
+ /* keep priv's existing 11h state */
+ if (pmpriv->intf_state_11h.is_11h_active)
+ mib_11h |= ENABLE_11H_MASK;
+
+ /* Send cmd to FW to enable/disable 11h function in firmware */
+ ret = wlan_prepare_cmd(pmpriv, HostCmd_CMD_802_11_SNMP_MIB,
+ HostCmd_ACT_GEN_SET, Dot11H_i, MNULL,
+ &mib_11h);
+ if (ret)
+ ret = MLAN_STATUS_FAILURE;
+ }
+
+ /* updated state sent OR no change, thus no longer pending */
+ pmpriv->adapter->state_11h.master_radar_det_enable_pending = MFALSE;
+ pmpriv->adapter->state_11h.slave_radar_det_enable_pending = MFALSE;
+
+ LEAVE();
+ return ret;
+}
+
+/**
+ * @brief Query 11h firmware enabled state.
+ *
+ * Return whether the firmware currently has 11h extensions enabled
+ *
+ * @param priv Private driver information structure
+ *
+ * @return
+ * - MTRUE if 11h has been activated in the firmware
+ * - MFALSE otherwise
+ *
+ * @sa wlan_11h_activate
+ */
+t_bool wlan_11h_is_active(mlan_private *priv)
+{
+ ENTER();
+ LEAVE();
+ return priv->intf_state_11h.is_11h_active;
+}
+
+/**
+ * @brief Enable the transmit interface and record the state.
+ *
+ * @param priv Private driver information structure
+ *
+ * @return N/A
+ */
+t_void wlan_11h_tx_enable(mlan_private *priv)
+{
+ ENTER();
+ if (priv->intf_state_11h.tx_disabled) {
+ if (priv->media_connected == MTRUE) {
+ wlan_recv_event(priv, MLAN_EVENT_ID_FW_START_TX, MNULL);
+ priv->intf_state_11h.tx_disabled = MFALSE;
+ }
+ }
+ LEAVE();
+}
+
+/**
+ * @brief Disable the transmit interface and record the state.
+ *
+ * @param priv Private driver information structure
+ *
+ * @return N/A
+ */
+t_void wlan_11h_tx_disable(mlan_private *priv)
+{
+ ENTER();
+ if (!priv->intf_state_11h.tx_disabled) {
+ if (priv->media_connected == MTRUE) {
+ priv->intf_state_11h.tx_disabled = MTRUE;
+ wlan_recv_event(priv, MLAN_EVENT_ID_FW_STOP_TX, MNULL);
+ }
+ }
+ LEAVE();
+}
+
+/**
+ * @brief Enable or Disable the 11h extensions in the firmware
+ *
+ * @param priv Private driver information structure
+ * @param pioctl_buf A pointer to MLAN IOCTL Request buffer
+ * @param flag Enable 11h if MTRUE, disable otherwise
+ *
+ * @return MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ */
+mlan_status wlan_11h_activate(mlan_private *priv, t_void *pioctl_buf,
+ t_bool flag)
+{
+ t_u32 enable = flag & ENABLE_11H_MASK;
+ mlan_status ret = MLAN_STATUS_SUCCESS;
+
+ ENTER();
+ /* add bits for master/slave radar detect into enable. */
+ enable |= wlan_11h_get_current_radar_detect_flags(priv->adapter);
+
+ /* Whenever repeater mode is on make sure
+ * we do not enable master or slave radar det mode.
+ * HW will not detect radar in dfs_repeater mode.
+ */
+ if (priv->adapter->dfs_repeater) {
+ enable &= ~(MASTER_RADAR_DET_MASK | SLAVE_RADAR_DET_MASK);
+ }
+
+ /*
+ * Send cmd to FW to enable/disable 11h function in firmware
+ */
+ ret = wlan_prepare_cmd(priv, HostCmd_CMD_802_11_SNMP_MIB,
+ HostCmd_ACT_GEN_SET, Dot11H_i,
+ (t_void *)pioctl_buf, &enable);
+ if (ret)
+ ret = MLAN_STATUS_FAILURE;
+ else
+ /* Set boolean flag in driver 11h state */
+ priv->intf_state_11h.is_11h_active = flag;
+
+ PRINTM(MINFO, "11h: %s\n", flag ? "Activate" : "Deactivate");
+
+ LEAVE();
+ return ret;
+}
+
+/**
+ * @brief Initialize the 11h parameters and enable 11h when starting an IBSS
+ *
+ * @param adapter mlan_adapter structure
+ *
+ * @return N/A
+ */
+t_void wlan_11h_init(mlan_adapter *adapter)
+{
+ wlan_11h_device_state_t *pstate_11h = &adapter->state_11h;
+ IEEEtypes_Quiet_t *pquiet = &adapter->state_11h.quiet_ie;
+ wlan_dfs_device_state_t *pstate_dfs = &adapter->state_dfs;
+ wlan_radar_det_hndlg_state_t *pstate_rdh = &adapter->state_rdh;
+ wlan_dfs_testing_settings_t *pdfs_test = &adapter->dfs_test_params;
+
+ ENTER();
+
+ /* Initialize 11H struct */
+ pstate_11h->usr_def_power_constraint = WLAN_11H_TPC_POWERCONSTRAINT;
+ pstate_11h->min_tx_power_capability = WLAN_11H_TPC_POWERCAPABILITY_MIN;
+ pstate_11h->max_tx_power_capability = WLAN_11H_TPC_POWERCAPABILITY_MAX;
+
+ pstate_11h->recvd_chanswann_event = MFALSE;
+ pstate_11h->master_radar_det_enable_pending = MFALSE;
+ pstate_11h->slave_radar_det_enable_pending = MFALSE;
+ pstate_11h->is_master_radar_det_active = MFALSE;
+ pstate_11h->is_slave_radar_det_active = MFALSE;
+
+ /*Initialize quiet_ie*/
+ memset(adapter, pquiet, 0, sizeof(IEEEtypes_Quiet_t));
+ pquiet->element_id = QUIET;
+ pquiet->len =
+ (sizeof(pquiet->quiet_count) + sizeof(pquiet->quiet_period) +
+ sizeof(pquiet->quiet_duration) + sizeof(pquiet->quiet_offset));
+
+ /* Initialize DFS struct */
+ pstate_dfs->dfs_check_pending = MFALSE;
+ pstate_dfs->dfs_radar_found = MFALSE;
+ pstate_dfs->dfs_check_channel = 0;
+ pstate_dfs->dfs_report_time_sec = 0;
+ util_init_list((pmlan_linked_list)&pstate_dfs->dfs_ts_head);
+
+ /* Initialize RDH struct */
+ pstate_rdh->stage = RDH_OFF;
+ pstate_rdh->priv_list_count = 0;
+ pstate_rdh->priv_curr_idx = 0;
+ pstate_rdh->curr_channel = 0;
+ pstate_rdh->new_channel = 0;
+ memset(adapter, &(pstate_rdh->uap_band_cfg), 0,
+ sizeof(pstate_rdh->uap_band_cfg));
+ pstate_rdh->max_bcn_dtim_ms = 0;
+ memset(adapter, pstate_rdh->priv_list, 0,
+ sizeof(pstate_rdh->priv_list));
+
+ /* Initialize dfs channel switch count */
+#define DFS_CS_COUNT 5
+ adapter->dfs_cs_count = DFS_CS_COUNT;
+
+ /* Initialize DFS testing struct */
+ pdfs_test->user_cac_period_msec = 0;
+ pdfs_test->user_nop_period_sec = 0;
+ pdfs_test->no_channel_change_on_radar = MFALSE;
+ pdfs_test->fixed_new_channel_on_radar = 0;
+ pdfs_test->cac_restart = 0;
+ pdfs_test->millisec_dwell_time = 0;
+ adapter->dfs53cfg = adapter->init_para.dfs53cfg;
+
+ LEAVE();
+}
+
+/**
+ * @brief Cleanup for the 11h parameters that allocated memory, etc.
+ *
+ * @param adapter mlan_adapter structure
+ *
+ * @return N/A
+ */
+t_void wlan_11h_cleanup(mlan_adapter *adapter)
+{
+ wlan_dfs_device_state_t *pstate_dfs = &adapter->state_dfs;
+ wlan_dfs_timestamp_t *pdfs_ts;
+
+ ENTER();
+
+ /* cleanup dfs_timestamp list */
+ pdfs_ts = (wlan_dfs_timestamp_t *)util_peek_list(
+ adapter->pmoal_handle, &pstate_dfs->dfs_ts_head, MNULL, MNULL);
+ while (pdfs_ts) {
+ util_unlink_list(adapter->pmoal_handle,
+ &pstate_dfs->dfs_ts_head,
+ (pmlan_linked_list)pdfs_ts, MNULL, MNULL);
+ adapter->callbacks.moal_mfree(adapter->pmoal_handle,
+ (t_u8 *)pdfs_ts);
+
+ pdfs_ts = (wlan_dfs_timestamp_t *)util_peek_list(
+ adapter->pmoal_handle, &pstate_dfs->dfs_ts_head, MNULL,
+ MNULL);
+ }
+
+ LEAVE();
+}
+
+/**
+ * @brief Initialize the 11h parameters and enable 11h when starting an IBSS
+ *
+ * @param pmpriv Pointer to mlan_private structure
+ *
+ * @return N/A
+ */
+t_void wlan_11h_priv_init(mlan_private *pmpriv)
+{
+ wlan_11h_interface_state_t *pistate_11h = &pmpriv->intf_state_11h;
+
+ ENTER();
+
+ pistate_11h->is_11h_enabled = MTRUE;
+ pistate_11h->is_11h_active = MFALSE;
+ pistate_11h->adhoc_auto_sel_chan = MTRUE;
+ pistate_11h->tx_disabled = MFALSE;
+ pistate_11h->dfs_slave_csa_chan = 0;
+ pistate_11h->dfs_slave_csa_expire_at_sec = 0;
+
+ LEAVE();
+}
+
+/**
+ * @brief Retrieve a randomly selected starting channel if needed for 11h
+ *
+ * If 11h is enabled and an A-Band channel start band preference
+ * configured in the driver, the start channel must be random in order
+ * to meet with
+ *
+ * @param priv Private driver information structure
+ *
+ * @return Starting channel
+ */
+t_u8 wlan_11h_get_adhoc_start_channel(mlan_private *priv)
+{
+ t_u8 start_chn;
+ mlan_adapter *adapter = priv->adapter;
+ t_u32 region;
+ t_u32 rand_entry;
+ region_chan_t *chn_tbl;
+ t_u8 rand_tries = 0;
+
+ ENTER();
+
+ /*
+ * Set start_chn to the Default. Used if 11h is disabled or the band
+ * does not require 11h support.
+ */
+ start_chn = DEFAULT_AD_HOC_CHANNEL;
+
+ /*
+ * Check that we are looking for a channel in the A Band
+ */
+ if ((adapter->adhoc_start_band & BAND_A)) {
+ /*
+ * Set default to the A Band default.
+ * Used if random selection fails
+ * or if 11h is not enabled
+ */
+ start_chn = DEFAULT_AD_HOC_CHANNEL_A;
+
+ /*
+ * Check that 11h is enabled in the driver
+ */
+ if (wlan_11h_is_enabled(priv)) {
+ /*
+ * Search the region_channel tables for a channel table
+ * that is marked for the A Band.
+ */
+ for (region = 0; (region < MAX_REGION_CHANNEL_NUM);
+ region++) {
+ chn_tbl = &adapter->region_channel[region];
+
+ /* Check if table is valid and marked for A Band
+ */
+ if (chn_tbl->valid &&
+ chn_tbl->region == adapter->region_code &&
+ chn_tbl->band & BAND_A) {
+ /*
+ * Set the start channel. Get a random
+ * number and use it to pick an entry
+ * in the table between 0 and the number
+ * of channels in the table (NumCFP).
+ */
+ do {
+ rand_entry =
+ wlan_11h_get_random_num(
+ adapter) %
+ chn_tbl->num_cfp;
+ start_chn =
+ (t_u8)chn_tbl
+ ->pcfp[rand_entry]
+ .channel;
+ } while (
+ (wlan_11h_is_channel_under_nop(
+ adapter, start_chn) ||
+ ((adapter->state_rdh.stage ==
+ RDH_GET_INFO_CHANNEL) &&
+ wlan_11h_radar_detect_required(
+ priv, start_chn))) &&
+ (++rand_tries <
+ MAX_RANDOM_CHANNEL_RETRIES));
+ }
+ }
+ }
+ }
+
+ PRINTM(MINFO, "11h: %s: AdHoc Channel set to %u\n",
+ wlan_11h_is_enabled(priv) ? "Enabled" : "Disabled", start_chn);
+
+ LEAVE();
+ return start_chn;
+}
+
+/**
+ * @brief Retrieve channel closed for operation by Channel Switch Announcement
+ *
+ * After receiving CSA, we must not transmit in any form on the original
+ * channel for a certain duration. This checks the time, and returns
+ * the channel if valid.
+ *
+ * @param priv Private driver information structure
+ *
+ * @return Closed channel, else 0
+ */
+t_u8 wlan_11h_get_csa_closed_channel(mlan_private *priv)
+{
+ t_u32 sec, usec;
+
+ ENTER();
+
+ if (!priv->intf_state_11h.dfs_slave_csa_chan) {
+ LEAVE();
+ return 0;
+ }
+
+ /* have csa channel, check if expired or not */
+ priv->adapter->callbacks.moal_get_system_time(
+ priv->adapter->pmoal_handle, &sec, &usec);
+ if (sec > priv->intf_state_11h.dfs_slave_csa_expire_at_sec) {
+ /* expired: remove channel from blacklist table, and clear vars
+ */
+ wlan_set_chan_blacklist(priv, BAND_A,
+ priv->intf_state_11h.dfs_slave_csa_chan,
+ MFALSE);
+ priv->intf_state_11h.dfs_slave_csa_chan = 0;
+ priv->intf_state_11h.dfs_slave_csa_expire_at_sec = 0;
+ }
+
+ LEAVE();
+ return priv->intf_state_11h.dfs_slave_csa_chan;
+}
+
+/**
+ * @brief Check if the current region's regulations require the input channel
+ * to be scanned for radar.
+ *
+ * Based on statically defined requirements for sub-bands per regulatory
+ * agency requirements.
+ *
+ * Used in adhoc start to determine if channel availability check is required
+ *
+ * @param priv Private driver information structure
+ * @param channel Channel to determine radar detection requirements
+ *
+ * @return
+ * - MTRUE if radar detection is required
+ * - MFALSE otherwise
+ */
+/** @sa wlan_11h_issue_radar_detect
+ */
+t_bool wlan_11h_radar_detect_required(mlan_private *priv, t_u8 channel)
+{
+ t_bool required = MFALSE;
+
+ ENTER();
+
+ /*
+ * No checks for 11h or measurement code being enabled is placed here
+ * since regulatory requirements exist whether we support them or not.
+ */
+
+ required = wlan_get_cfp_radar_detect(priv, channel);
+
+ if (!priv->adapter->region_code) {
+ PRINTM(MINFO,
+ "11h: Radar detection in CFP code BG:%#x "
+ ", A:%#x "
+ "is %srequired for channel %d\n",
+ priv->adapter->cfp_code_bg, priv->adapter->cfp_code_a,
+ (required ? "" : "not "), channel);
+ } else
+ PRINTM(MINFO,
+ "11h: Radar detection in region %#02x "
+ "is %srequired for channel %d\n",
+ priv->adapter->region_code, (required ? "" : "not "),
+ channel);
+
+ if (required == MTRUE && priv->media_connected == MTRUE &&
+ priv->curr_bss_params.bss_descriptor.channel == channel) {
+ required = MFALSE;
+
+ PRINTM(MINFO, "11h: Radar detection not required. "
+ "Already operating on the channel\n");
+ }
+
+ LEAVE();
+ return required;
+}
+
+t_s32 wlan_11h_cancel_radar_detect(mlan_private *priv)
+{
+ t_s32 ret;
+ HostCmd_DS_CHAN_RPT_REQ chan_rpt_req;
+ memset(priv->adapter, &chan_rpt_req, 0x00, sizeof(chan_rpt_req));
+ ret = wlan_prepare_cmd(priv, HostCmd_CMD_CHAN_REPORT_REQUEST,
+ HostCmd_ACT_GEN_SET, 0, (t_void *)MNULL,
+ (t_void *)&chan_rpt_req);
+ return ret;
+}
+
+/**
+ * @brief Perform a radar measurement if required on given channel
+ *
+ * Check to see if the provided channel requires a channel availability
+ * check (60 second radar detection measurement). If required, perform
+ * measurement, stalling calling thread until the measurement completes
+ * and then report result.
+ *
+ * Used when starting an adhoc or AP network.
+ *
+ * @param priv Private driver information structure
+ * @param pioctl_req Pointer to IOCTL request buffer
+ * @param channel Channel on which to perform radar measurement
+ * @param bandcfg Channel Band config structure
+ *
+ * @return
+ * - MTRUE if radar measurement request was successfully issued
+ * - MFALSE if radar detection is not required
+ * - < 0 for error during radar detection (if performed)
+ *
+ * @sa wlan_11h_radar_detect_required
+ */
+t_s32 wlan_11h_issue_radar_detect(mlan_private *priv,
+ pmlan_ioctl_req pioctl_req, t_u8 channel,
+ Band_Config_t bandcfg)
+{
+ t_s32 ret;
+ HostCmd_DS_CHAN_RPT_REQ chan_rpt_req;
+ mlan_adapter *pmadapter = priv->adapter;
+ mlan_ds_11h_cfg *ds_11hcfg = MNULL;
+
+ ENTER();
+
+ ret = wlan_11h_radar_detect_required(priv, channel);
+ if (ret) {
+ /* Prepare and issue CMD_CHAN_RPT_REQ. */
+ memset(priv->adapter, &chan_rpt_req, 0x00,
+ sizeof(chan_rpt_req));
+
+ chan_rpt_req.chan_desc.startFreq = START_FREQ_11A_BAND;
+
+ if (pmadapter->chanrpt_param_bandcfg) {
+ chan_rpt_req.chan_desc.bandcfg = bandcfg;
+ } else {
+ *((t_u8 *)&chan_rpt_req.chan_desc.bandcfg) =
+ (t_u8)bandcfg.chanWidth;
+ }
+
+ chan_rpt_req.chan_desc.chanNum = channel;
+ chan_rpt_req.millisec_dwell_time =
+ WLAN_11H_CHANNEL_AVAIL_CHECK_DURATION;
+
+ /* ETSI new requirement for ch 120, 124 and 128 */
+ if (wlan_is_etsi_country(pmadapter, pmadapter->country_code)) {
+ if (channel == 120 || channel == 124 ||
+ channel == 128) {
+ chan_rpt_req.millisec_dwell_time =
+ WLAN_11H_CHANNEL_AVAIL_CHECK_DURATION *
+ 10;
+ }
+ if (channel == 116 &&
+ ((bandcfg.chanWidth == CHAN_BW_40MHZ) ||
+ (bandcfg.chanWidth == CHAN_BW_80MHZ))) {
+ chan_rpt_req.millisec_dwell_time =
+ WLAN_11H_CHANNEL_AVAIL_CHECK_DURATION *
+ 10;
+ }
+ }
+
+ /* Save dwell time information to be used later in moal */
+ if (pioctl_req) {
+ ds_11hcfg = (mlan_ds_11h_cfg *)pioctl_req->pbuf;
+ if (!ds_11hcfg->param.chan_rpt_req.host_based) {
+ ds_11hcfg->param.chan_rpt_req
+ .millisec_dwell_time =
+ chan_rpt_req.millisec_dwell_time;
+ }
+ }
+
+ if (priv->adapter->dfs_test_params.user_cac_period_msec) {
+ PRINTM(MCMD_D,
+ "dfs_testing - user CAC period=%d (msec)\n",
+ priv->adapter->dfs_test_params
+ .user_cac_period_msec);
+ chan_rpt_req.millisec_dwell_time =
+ priv->adapter->dfs_test_params
+ .user_cac_period_msec;
+ }
+ if (priv->adapter->dfs_test_params.cac_restart) {
+ priv->adapter->dfs_test_params.chan =
+ chan_rpt_req.chan_desc.chanNum;
+ if (chan_rpt_req.millisec_dwell_time)
+ priv->adapter->dfs_test_params
+ .millisec_dwell_time =
+ chan_rpt_req.millisec_dwell_time;
+ else
+ chan_rpt_req.millisec_dwell_time =
+ priv->adapter->dfs_test_params
+ .millisec_dwell_time;
+ memcpy_ext(priv->adapter,
+ &priv->adapter->dfs_test_params.bandcfg,
+ &bandcfg, sizeof(bandcfg), sizeof(bandcfg));
+ }
+ PRINTM(MMSG,
+ "11h: issuing DFS Radar check for channel=%d."
+ " Please wait for response...\n",
+ channel);
+
+ ret = wlan_prepare_cmd(priv, HostCmd_CMD_CHAN_REPORT_REQUEST,
+ HostCmd_ACT_GEN_SET, 0,
+ (t_void *)pioctl_req,
+ (t_void *)&chan_rpt_req);
+ }
+
+ LEAVE();
+ return ret;
+}
+
+/**
+ * @brief Checks if a radar measurement was performed on channel,
+ * and if so, whether radar was detected on it.
+ *
+ * Used when starting an adhoc network.
+ *
+ * @param priv Private driver information structure
+ * @param chan Channel to check upon
+ *
+ * @return
+ * - MLAN_STATUS_SUCCESS if no radar on channel
+ * - MLAN_STATUS_FAILURE if radar was found on channel
+ * - (TBD??) MLAN_STATUS_PENDING if radar report NEEDS TO BE REISSUED
+ *
+ * @sa wlan_11h_issue_radar_detect
+ * @sa wlan_11h_process_start
+ */
+mlan_status wlan_11h_check_chan_report(mlan_private *priv, t_u8 chan)
+{
+ mlan_status ret = MLAN_STATUS_SUCCESS;
+ wlan_dfs_device_state_t *pstate_dfs = &priv->adapter->state_dfs;
+ t_u32 sec, usec;
+
+ ENTER();
+
+ /* check report we hold is valid or not */
+ priv->adapter->callbacks.moal_get_system_time(
+ priv->adapter->pmoal_handle, &sec, &usec);
+
+ PRINTM(MINFO, "11h: %s()\n", __func__);
+ PRINTM(MINFO, "- sec_now=%d, sec_report=%d.\n", sec,
+ pstate_dfs->dfs_report_time_sec);
+ PRINTM(MINFO, "- rpt_channel=%d, rpt_radar=%d.\n",
+ pstate_dfs->dfs_check_channel, pstate_dfs->dfs_radar_found);
+
+ if ((!pstate_dfs->dfs_check_pending) &&
+ (chan == pstate_dfs->dfs_check_channel) &&
+ ((sec - pstate_dfs->dfs_report_time_sec) <
+ MAX_DFS_REPORT_USABLE_AGE_SEC)) {
+ /* valid and not out-dated, check if radar */
+ if (pstate_dfs->dfs_radar_found) {
+ PRINTM(MMSG, "Radar was detected on channel %d.\n",
+ chan);
+ ret = MLAN_STATUS_FAILURE;
+ }
+ } else {
+ /* When Cache is not valid. This is required during extending
+ * cache validity during bss_stop
+ */
+ pstate_dfs->dfs_check_channel = 0;
+
+ /*TODO: reissue report request if not pending.
+ * BUT HOW to make the code wait for it???
+ * For now, just fail since we don't have the info. */
+
+ ret = MLAN_STATUS_PENDING;
+ }
+
+ LEAVE();
+ return ret;
+}
+
+/**
+ * @brief Process an TLV buffer for a pending BSS Adhoc start command.
+ *
+ * Activate 11h functionality in the firmware if driver has is enabled
+ * for 11h (configured by the application via IOCTL).
+ *
+ * @param priv Private driver information structure
+ * @param ppbuffer Output parameter: Pointer to the TLV output buffer,
+ * modified on return to point after the appended 11h TLVs
+ * @param pcap_info Pointer to the capability info for the BSS to join
+ * @param channel Channel on which we are starting the IBSS
+ * @param p11h_bss_info Input/Output parameter: Pointer to the 11h BSS
+ * information for this network that we are establishing.
+ * 11h sensed flag set on output if warranted.
+ *
+ * @return
+ * - MLAN_STATUS_SUCCESS if 11h is disabled
+ * - Integer number of bytes appended to the TLV output buffer (ppbuffer)
+ * - < 0 for error (e.g. radar detected on channel)
+ */
+t_s32 wlan_11h_process_start(mlan_private *priv, t_u8 **ppbuffer,
+ IEEEtypes_CapInfo_t *pcap_info, t_u32 channel,
+ wlan_11h_bss_info_t *p11h_bss_info)
+{
+ mlan_adapter *adapter = priv->adapter;
+ t_s32 ret = MLAN_STATUS_SUCCESS;
+ t_bool is_dfs_chan = MFALSE;
+
+ ENTER();
+ if (wlan_11h_is_enabled(priv) &&
+ ((adapter->adhoc_start_band & BAND_A))) {
+ if (!wlan_fw_11d_is_enabled(priv)) {
+ /* No use having 11h enabled without 11d enabled */
+ wlan_11d_enable(priv, MNULL, ENABLE_11D);
+#ifdef STA_SUPPORT
+ wlan_11d_create_dnld_countryinfo(
+ priv, adapter->adhoc_start_band);
+#endif
+ }
+
+ /*
+ * Activate 11h functions in firmware,
+ * turns on capability bit
+ */
+ wlan_11h_activate(priv, MNULL, MTRUE);
+ pcap_info->spectrum_mgmt = MTRUE;
+
+ /* If using a DFS channel, enable radar detection. */
+ is_dfs_chan = wlan_11h_radar_detect_required(priv, channel);
+ if (is_dfs_chan) {
+ if (!wlan_11h_is_master_radar_det_active(priv))
+ wlan_11h_config_master_radar_det(priv, MTRUE);
+ }
+ wlan_11h_check_update_radar_det_state(priv);
+
+ /* Set flag indicating this BSS we are starting is using 11h */
+ p11h_bss_info->sensed_11h = MTRUE;
+
+ if (is_dfs_chan) {
+ /* check if this channel is under NOP */
+ if (wlan_11h_is_channel_under_nop(adapter, channel))
+ ret = MLAN_STATUS_FAILURE;
+ /* check last channel report, if this channel is free of
+ * radar */
+ if (ret == MLAN_STATUS_SUCCESS)
+ ret = wlan_11h_check_chan_report(priv, channel);
+ }
+ if (ret == MLAN_STATUS_SUCCESS)
+ ret = wlan_11h_process_adhoc(priv, ppbuffer, channel,
+ MNULL);
+ else
+ ret = MLAN_STATUS_FAILURE;
+ } else {
+ /* Deactivate 11h functions in the firmware */
+ wlan_11h_activate(priv, MNULL, MFALSE);
+ pcap_info->spectrum_mgmt = MFALSE;
+ wlan_11h_check_update_radar_det_state(priv);
+ }
+ LEAVE();
+ return ret;
+}
+
+/**
+ * @brief Process an TLV buffer for a pending BSS Join command for
+ * both adhoc and infra networks
+ *
+ * The TLV command processing for a BSS join for either adhoc or
+ * infrastructure network is performed with this function. The
+ * capability bits are inspected for the IBSS flag and the appropriate
+ * local routines are called to setup the necessary TLVs.
+ *
+ * Activate 11h functionality in the firmware if the spectrum management
+ * capability bit is found in the network information for the BSS we are
+ * joining.
+ *
+ * @param priv Private driver information structure
+ * @param ppbuffer Output parameter: Pointer to the TLV output buffer,
+ * modified on return to point after the appended 11h TLVs
+ * @param pcap_info Pointer to the capability info for the BSS to join
+ * @param band Band on which we are joining the BSS
+ * @param channel Channel on which we are joining the BSS
+ * @param p11h_bss_info Pointer to the 11h BSS information for this
+ * network that was parsed out of the scan response.
+ *
+ * @return Integer number of bytes appended to the TLV output
+ * buffer (ppbuffer), MLAN_STATUS_FAILURE (-1),
+ * or MLAN_STATUS_SUCCESS (0)
+ */
+t_s32 wlan_11h_process_join(mlan_private *priv, t_u8 **ppbuffer,
+ IEEEtypes_CapInfo_t *pcap_info, t_u8 band,
+ t_u32 channel, wlan_11h_bss_info_t *p11h_bss_info)
+{
+ t_s32 ret = 0;
+
+ ENTER();
+
+ if (priv->media_connected == MTRUE) {
+ if (wlan_11h_is_active(priv) == p11h_bss_info->sensed_11h) {
+ /*
+ * Assume DFS parameters are the same for roaming as
+ * long as the current & next APs have the same spectrum
+ * mgmt capability bit setting
+ */
+ ret = MLAN_STATUS_SUCCESS;
+
+ } else {
+ /* No support for roaming between DFS/non-DFS yet */
+ ret = MLAN_STATUS_FAILURE;
+ }
+
+ LEAVE();
+ return ret;
+ }
+
+ if (p11h_bss_info->sensed_11h) {
+ if (!wlan_fw_11d_is_enabled(priv)) {
+ /* No use having 11h enabled without 11d enabled */
+ wlan_11d_enable(priv, MNULL, ENABLE_11D);
+#ifdef STA_SUPPORT
+ wlan_11d_parse_dnld_countryinfo(
+ priv, priv->pattempted_bss_desc);
+#endif
+ }
+ /*
+ * Activate 11h functions in firmware,
+ * turns on capability bit
+ */
+ wlan_11h_activate(priv, MNULL, MTRUE);
+ pcap_info->spectrum_mgmt = MTRUE;
+
+ /* If using a DFS channel, enable radar detection. */
+ if ((band & BAND_A) &&
+ wlan_11h_radar_detect_required(priv, channel)) {
+ if (!wlan_11h_is_slave_radar_det_active(priv))
+ wlan_11h_config_slave_radar_det(priv, MTRUE);
+ }
+ wlan_11h_check_update_radar_det_state(priv);
+
+ if (pcap_info->ibss) {
+ PRINTM(MINFO, "11h: Adhoc join: Sensed\n");
+ ret = wlan_11h_process_adhoc(priv, ppbuffer, channel,
+ p11h_bss_info);
+ } else {
+ PRINTM(MINFO, "11h: Infra join: Sensed\n");
+ ret = wlan_11h_process_infra_join(
+ priv, ppbuffer, band, channel, p11h_bss_info);
+ }
+ } else {
+ /* Deactivate 11h functions in the firmware */
+ wlan_11h_activate(priv, MNULL, MFALSE);
+ pcap_info->spectrum_mgmt = MFALSE;
+ wlan_11h_check_update_radar_det_state(priv);
+ }
+
+ LEAVE();
+ return ret;
+}
+
+/**
+ *
+ * @brief Prepare the HostCmd_DS_Command structure for an 11h command.
+ *
+ * Use the Command field to determine if the command being set up is for
+ * 11h and call one of the local command handlers accordingly for:
+ *
+ * - HostCmd_CMD_802_11_TPC_ADAPT_REQ
+ * - HostCmd_CMD_802_11_TPC_INFO
+ * - HostCmd_CMD_802_11_CHAN_SW_ANN
+ */
+/** - HostCmd_CMD_CHAN_REPORT_REQUEST
+ */
+/**
+ * @param priv Private driver information structure
+ * @param pcmd_ptr Output parameter: Pointer to the command being prepared
+ * for the firmware
+ * @param pinfo_buf Void buffer pass through with data necessary for a
+ * specific command type
+ */
+/** @return MLAN_STATUS_SUCCESS, MLAN_STATUS_FAILURE
+ * or MLAN_STATUS_PENDING
+ */
+/** @sa wlan_11h_cmd_tpc_request
+ * @sa wlan_11h_cmd_tpc_info
+ * @sa wlan_11h_cmd_chan_sw_ann
+ */
+/** @sa wlan_11h_cmd_chan_report_req
+ */
+mlan_status wlan_11h_cmd_process(mlan_private *priv,
+ HostCmd_DS_COMMAND *pcmd_ptr,
+ const t_void *pinfo_buf)
+{
+ mlan_status ret = MLAN_STATUS_SUCCESS;
+
+ ENTER();
+ switch (pcmd_ptr->command) {
+ case HostCmd_CMD_802_11_TPC_ADAPT_REQ:
+ ret = wlan_11h_cmd_tpc_request(priv, pcmd_ptr, pinfo_buf);
+ break;
+ case HostCmd_CMD_802_11_TPC_INFO:
+ ret = wlan_11h_cmd_tpc_info(priv, pcmd_ptr, pinfo_buf);
+ break;
+ case HostCmd_CMD_802_11_CHAN_SW_ANN:
+ ret = wlan_11h_cmd_chan_sw_ann(priv, pcmd_ptr, pinfo_buf);
+ break;
+ case HostCmd_CMD_CHAN_REPORT_REQUEST:
+ ret = wlan_11h_cmd_chan_rpt_req(priv, pcmd_ptr, pinfo_buf);
+ break;
+ default:
+ ret = MLAN_STATUS_FAILURE;
+ }
+
+ pcmd_ptr->command = wlan_cpu_to_le16(pcmd_ptr->command);
+ pcmd_ptr->size = wlan_cpu_to_le16(pcmd_ptr->size);
+
+ LEAVE();
+ return ret;
+}
+
+/**
+ * @brief Handle the command response from the firmware if from an 11h command
+ *
+ * Use the Command field to determine if the command response being
+ * is for 11h. Call the local command response handler accordingly for:
+ *
+ * - HostCmd_CMD_802_11_TPC_ADAPT_REQ
+ * - HostCmd_CMD_802_11_TPC_INFO
+ * - HostCmd_CMD_802_11_CHAN_SW_ANN
+ */
+/** - HostCmd_CMD_CHAN_REPORT_REQUEST
+ */
+/**
+ * @param priv Private driver information structure
+ * @param resp HostCmd_DS_COMMAND struct returned from the firmware
+ * command
+ *
+ * @return MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ */
+mlan_status wlan_11h_cmdresp_process(mlan_private *priv,
+ const HostCmd_DS_COMMAND *resp)
+{
+ mlan_status ret = MLAN_STATUS_SUCCESS;
+
+ ENTER();
+ switch (resp->command) {
+ case HostCmd_CMD_802_11_TPC_ADAPT_REQ:
+ HEXDUMP("11h: TPC REQUEST Rsp:", (t_u8 *)resp,
+ (t_u32)resp->size);
+ memcpy_ext(priv->adapter, priv->adapter->curr_cmd->pdata_buf,
+ &resp->params.tpc_req,
+ sizeof(HostCmd_DS_802_11_TPC_ADAPT_REQ),
+ sizeof(HostCmd_DS_802_11_TPC_ADAPT_REQ));
+ break;
+
+ case HostCmd_CMD_802_11_TPC_INFO:
+ HEXDUMP("11h: TPC INFO Rsp Data:", (t_u8 *)resp,
+ (t_u32)resp->size);
+ break;
+
+ case HostCmd_CMD_802_11_CHAN_SW_ANN:
+ PRINTM(MINFO, "11h: Ret ChSwAnn: Sz=%u, Seq=%u, Ret=%u\n",
+ resp->size, resp->seq_num, resp->result);
+ break;
+
+ case HostCmd_CMD_CHAN_REPORT_REQUEST:
+ priv->adapter->state_dfs.dfs_check_priv = priv;
+ priv->adapter->state_dfs.dfs_check_pending = MTRUE;
+
+ if (resp->params.chan_rpt_req.millisec_dwell_time == 0) {
+ /* from wlan_11h_ioctl_dfs_chan_report */
+ priv->adapter->state_dfs.dfs_check_pending = MFALSE;
+ priv->adapter->state_dfs.dfs_check_priv = MNULL;
+ priv->adapter->state_dfs.dfs_check_channel = 0;
+ PRINTM(MINFO, "11h: Cancelling Chan Report \n");
+ } else {
+ PRINTM(MERROR,
+ "11h: Ret ChanRptReq. Set dfs_check_pending and wait"
+ " for EVENT_CHANNEL_REPORT.\n");
+ }
+
+ break;
+
+ default:
+ ret = MLAN_STATUS_FAILURE;
+ }
+
+ LEAVE();
+ return ret;
+}
+
+/**
+ * @brief Process an element from a scan response, copy relevant info for 11h
+ *
+ * @param pmadapter Pointer to mlan_adapter
+ * @param p11h_bss_info Output parameter: Pointer to the 11h BSS information
+ * for the network that is being processed
+ * @param pelement Pointer to the current IE we are inspecting for 11h
+ * relevance
+ *
+ * @return MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ */
+mlan_status wlan_11h_process_bss_elem(mlan_adapter *pmadapter,
+ wlan_11h_bss_info_t *p11h_bss_info,
+ const t_u8 *pelement)
+{
+ mlan_status ret = MLAN_STATUS_SUCCESS;
+ t_u8 element_len = *((t_u8 *)pelement + 1);
+
+ ENTER();
+ switch (*pelement) {
+ case POWER_CONSTRAINT:
+ PRINTM(MINFO, "11h: Power Constraint IE Found\n");
+ p11h_bss_info->sensed_11h = MTRUE;
+ memcpy_ext(pmadapter, &p11h_bss_info->power_constraint,
+ pelement, element_len + sizeof(IEEEtypes_Header_t),
+ sizeof(IEEEtypes_PowerConstraint_t));
+ p11h_bss_info->power_constraint.len =
+ MIN(element_len, (sizeof(IEEEtypes_PowerConstraint_t) -
+ sizeof(IEEEtypes_Header_t)));
+ break;
+
+ case POWER_CAPABILITY:
+ PRINTM(MINFO, "11h: Power Capability IE Found\n");
+ p11h_bss_info->sensed_11h = MTRUE;
+ memcpy_ext(pmadapter, &p11h_bss_info->power_capability,
+ pelement, element_len + sizeof(IEEEtypes_Header_t),
+ sizeof(IEEEtypes_PowerCapability_t));
+ p11h_bss_info->power_capability.len =
+ MIN(element_len, (sizeof(IEEEtypes_PowerCapability_t) -
+ sizeof(IEEEtypes_Header_t)));
+ break;
+
+ case TPC_REPORT:
+ PRINTM(MINFO, "11h: Tpc Report IE Found\n");
+ p11h_bss_info->sensed_11h = MTRUE;
+ memcpy_ext(pmadapter, &p11h_bss_info->tpc_report, pelement,
+ element_len + sizeof(IEEEtypes_Header_t),
+ sizeof(IEEEtypes_TPCReport_t));
+ p11h_bss_info->tpc_report.len =
+ MIN(element_len, (sizeof(IEEEtypes_TPCReport_t) -
+ sizeof(IEEEtypes_Header_t)));
+ break;
+
+ case CHANNEL_SWITCH_ANN:
+ PRINTM(MINFO, "11h: Channel Switch Ann IE Found\n");
+ p11h_bss_info->sensed_11h = MTRUE;
+ memcpy_ext(pmadapter, &p11h_bss_info->chan_switch_ann, pelement,
+ element_len + sizeof(IEEEtypes_Header_t),
+ sizeof(IEEEtypes_ChanSwitchAnn_t));
+ p11h_bss_info->chan_switch_ann.len =
+ MIN(element_len, (sizeof(IEEEtypes_ChanSwitchAnn_t) -
+ sizeof(IEEEtypes_Header_t)));
+ break;
+
+ case QUIET:
+ PRINTM(MINFO, "11h: Quiet IE Found\n");
+ p11h_bss_info->sensed_11h = MTRUE;
+ memcpy_ext(pmadapter, &p11h_bss_info->quiet, pelement,
+ element_len + sizeof(IEEEtypes_Header_t),
+ sizeof(IEEEtypes_Quiet_t));
+ p11h_bss_info->quiet.len =
+ MIN(element_len, (sizeof(IEEEtypes_Quiet_t) -
+ sizeof(IEEEtypes_Header_t)));
+ break;
+
+ case IBSS_DFS:
+ PRINTM(MINFO, "11h: Ibss Dfs IE Found\n");
+ p11h_bss_info->sensed_11h = MTRUE;
+ memcpy_ext(pmadapter, &p11h_bss_info->ibss_dfs, pelement,
+ element_len + sizeof(IEEEtypes_Header_t),
+ sizeof(IEEEtypes_IBSS_DFS_t));
+ p11h_bss_info->ibss_dfs.len =
+ MIN(element_len, (sizeof(IEEEtypes_IBSS_DFS_t) -
+ sizeof(IEEEtypes_Header_t)));
+ break;
+
+ case SUPPORTED_CHANNELS:
+ case TPC_REQUEST:
+ /*
+ * These elements are not in beacons/probe responses.
+ * Included here to cover set of enumerated 11h elements.
+ */
+ break;
+
+ default:
+ ret = MLAN_STATUS_FAILURE;
+ }
+
+ LEAVE();
+ return ret;
+}
+
+/**
+ * @brief Driver handling for CHANNEL_SWITCH_ANN event
+ *
+ * @param priv Pointer to mlan_private
+ *
+ * @return MLAN_STATUS_SUCCESS, MLAN_STATUS_FAILURE or MLAN_STATUS_PENDING
+ */
+mlan_status wlan_11h_handle_event_chanswann(mlan_private *priv)
+{
+ mlan_status ret = MLAN_STATUS_SUCCESS;
+#ifdef STA_SUPPORT
+ mlan_deauth_param deauth_param;
+#endif
+ t_u32 sec, usec;
+#ifdef UAP_SUPPORT
+ mlan_adapter *pmadapter = priv->adapter;
+ int i;
+ t_u8 radar_detected = MFALSE;
+ mlan_private *pmpriv = MNULL;
+#endif
+
+ ENTER();
+#ifdef UAP_SUPPORT
+ if (priv->adapter->state_11h.is_master_radar_det_active) {
+ for (i = 0; i < MIN(pmadapter->priv_num, MLAN_MAX_BSS_NUM);
+ i++) {
+ if (pmadapter->priv[i] &&
+ (pmadapter->priv[i]->bss_role ==
+ MLAN_BSS_ROLE_UAP) &&
+ pmadapter->priv[i]->uap_bss_started &&
+ (priv->curr_bss_params.bss_descriptor.channel ==
+ pmadapter->priv[i]->uap_channel)) {
+ PRINTM(MCMND,
+ "Receive channel switch Ann event on uap_channel=%d\n",
+ pmadapter->priv[i]->uap_channel);
+ radar_detected = MTRUE;
+ pmpriv = pmadapter->priv[i];
+ break;
+ }
+ }
+ if (radar_detected) {
+ if (!pmpriv->intf_state_11h.is_11h_host) {
+ if (pmadapter->state_rdh.stage == RDH_OFF) {
+ pmadapter->state_rdh.stage =
+ RDH_CHK_INTFS;
+ wlan_11h_radar_detected_handling(
+ pmadapter, pmpriv);
+ if (pmpriv->uap_host_based)
+ wlan_recv_event(
+ pmpriv,
+ MLAN_EVENT_ID_FW_RADAR_DETECTED,
+ MNULL);
+ } else {
+ PRINTM(MEVENT,
+ "Ignore Event Radar Detected - handling already in progress.\n");
+ }
+ } else {
+ if (pmpriv->adapter->dfs_test_params
+ .no_channel_change_on_radar ||
+ pmpriv->adapter->dfs_test_params
+ .fixed_new_channel_on_radar) {
+ if (pmadapter->state_rdh.stage ==
+ RDH_OFF ||
+ pmadapter->state_rdh.stage ==
+ RDH_SET_CUSTOM_IE) {
+ pmadapter->state_rdh.stage =
+ RDH_CHK_INTFS;
+ wlan_11h_radar_detected_handling(
+ pmadapter, pmpriv);
+ } else
+ PRINTM(MEVENT,
+ "Ignore Event Radar Detected - handling already in progress.\n");
+ } else {
+ pmpriv->intf_state_11h.tx_disabled =
+ MTRUE;
+ wlan_recv_event(
+ pmpriv,
+ MLAN_EVENT_ID_FW_RADAR_DETECTED,
+ MNULL);
+ }
+ }
+ }
+ }
+ if (pmadapter->ecsa_enable) {
+ t_u8 stop_tx = *(t_u8 *)pmadapter->event_body;
+ if (stop_tx)
+ pmadapter->state_rdh.tx_block = MTRUE;
+ LEAVE();
+ return ret;
+ }
+#endif
+ priv->adapter->state_11h.recvd_chanswann_event = MTRUE;
+
+ /* unlikely: clean up previous csa if still on-going */
+ if (priv->intf_state_11h.dfs_slave_csa_chan) {
+ wlan_set_chan_blacklist(priv, BAND_A,
+ priv->intf_state_11h.dfs_slave_csa_chan,
+ MFALSE);
+ }
+
+ /* record channel and time of occurence */
+ priv->intf_state_11h.dfs_slave_csa_chan =
+ priv->curr_bss_params.bss_descriptor.channel;
+ priv->adapter->callbacks.moal_get_system_time(
+ priv->adapter->pmoal_handle, &sec, &usec);
+ priv->intf_state_11h.dfs_slave_csa_expire_at_sec =
+ sec + DFS_CHAN_MOVE_TIME;
+
+#ifdef STA_SUPPORT
+ /* do directed deauth. recvd_chanswann_event flag will cause different
+ * reason code */
+ PRINTM(MINFO, "11h: handle_event_chanswann() - sending deauth\n");
+ memcpy_ext(priv->adapter, deauth_param.mac_addr,
+ &priv->curr_bss_params.bss_descriptor.mac_address,
+ MLAN_MAC_ADDR_LENGTH, MLAN_MAC_ADDR_LENGTH);
+ deauth_param.reason_code = DEF_DEAUTH_REASON_CODE;
+ ret = wlan_disconnect(priv, MNULL, &deauth_param);
+
+ /* clear region table so next scan will be all passive */
+ PRINTM(MINFO, "11h: handle_event_chanswann() - clear region table\n");
+ wlan_11d_clear_parsedtable(priv);
+
+ /* add channel to blacklist table */
+ PRINTM(MINFO,
+ "11h: handle_event_chanswann() - scan blacklist csa channel\n");
+ wlan_set_chan_blacklist(priv, BAND_A,
+ priv->intf_state_11h.dfs_slave_csa_chan, MTRUE);
+#endif
+
+ priv->adapter->state_11h.recvd_chanswann_event = MFALSE;
+ LEAVE();
+ return ret;
+}
+
+/**
+ * @brief 802.11h DFS Testing configuration
+ *
+ * @param pmadapter Pointer to mlan_adapter
+ * @param pioctl_req Pointer to mlan_ioctl_req
+ *
+ * @return MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ */
+mlan_status wlan_11h_ioctl_dfs_testing(pmlan_adapter pmadapter,
+ pmlan_ioctl_req pioctl_req)
+{
+ mlan_ds_11h_cfg *ds_11hcfg = MNULL;
+ mlan_ds_11h_dfs_testing *dfs_test = MNULL;
+ wlan_dfs_testing_settings_t *pdfs_test_params = MNULL;
+
+ ENTER();
+
+ ds_11hcfg = (mlan_ds_11h_cfg *)pioctl_req->pbuf;
+ dfs_test = &ds_11hcfg->param.dfs_testing;
+ pdfs_test_params = &pmadapter->dfs_test_params;
+
+ if (pioctl_req->action == MLAN_ACT_GET) {
+ dfs_test->usr_cac_period_msec =
+ pdfs_test_params->user_cac_period_msec;
+ dfs_test->usr_nop_period_sec =
+ pdfs_test_params->user_nop_period_sec;
+ dfs_test->usr_no_chan_change =
+ pdfs_test_params->no_channel_change_on_radar;
+ dfs_test->usr_fixed_new_chan =
+ pdfs_test_params->fixed_new_channel_on_radar;
+ dfs_test->usr_cac_restart = pdfs_test_params->cac_restart;
+ } else {
+ pdfs_test_params->user_cac_period_msec =
+ dfs_test->usr_cac_period_msec;
+ pdfs_test_params->user_nop_period_sec =
+ dfs_test->usr_nop_period_sec;
+ pdfs_test_params->no_channel_change_on_radar =
+ dfs_test->usr_no_chan_change;
+ pdfs_test_params->fixed_new_channel_on_radar =
+ dfs_test->usr_fixed_new_chan;
+ pdfs_test_params->cac_restart = dfs_test->usr_cac_restart;
+ }
+
+ LEAVE();
+ return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ * @brief 802.11h IOCTL to handle channel NOP status check
+ * @brief If given channel is under NOP, return a new non-dfs
+ * @brief channel
+ *
+ * @param pmadapter Pointer to mlan_adapter
+ * @param pioctl_req Pointer to mlan_ioctl_req
+ *
+ * @return MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ */
+mlan_status wlan_11h_ioctl_get_channel_nop_info(pmlan_adapter pmadapter,
+ pmlan_ioctl_req pioctl_req)
+{
+ pmlan_private pmpriv = MNULL;
+ mlan_ds_11h_cfg *ds_11hcfg = MNULL;
+ t_s32 ret = MLAN_STATUS_FAILURE;
+ mlan_ds_11h_chan_nop_info *ch_nop_info = MNULL;
+
+ ENTER();
+
+ if (pioctl_req) {
+ pmpriv = pmadapter->priv[pioctl_req->bss_index];
+ ds_11hcfg = (mlan_ds_11h_cfg *)pioctl_req->pbuf;
+ ch_nop_info = &ds_11hcfg->param.ch_nop_info;
+
+ if (pioctl_req->action == MLAN_ACT_GET) {
+ ch_nop_info->chan_under_nop =
+ wlan_11h_is_channel_under_nop(
+ pmadapter, ch_nop_info->curr_chan);
+ if (ch_nop_info->chan_under_nop) {
+ wlan_11h_switch_non_dfs_chan(
+ pmpriv, &ch_nop_info->new_chan.channel);
+ if (ch_nop_info->chan_width == CHAN_BW_80MHZ ||
+ ch_nop_info->chan_width == CHAN_BW_40MHZ)
+ wlan_11h_update_bandcfg(
+ &ch_nop_info->new_chan.bandcfg,
+ ch_nop_info->new_chan.channel);
+ if (ch_nop_info->chan_width == CHAN_BW_80MHZ)
+ ch_nop_info->new_chan.center_chan =
+ wlan_get_center_freq_idx(
+ pmpriv, BAND_AAC,
+ ch_nop_info->new_chan
+ .channel,
+ ch_nop_info->chan_width);
+ }
+ }
+ ret = MLAN_STATUS_SUCCESS;
+ }
+
+ LEAVE();
+ return ret;
+}
+
+/**
+ * @brief 802.11h DFS Channel Switch Count Configuration
+ *
+ * @param pmadapter Pointer to mlan_adapter
+ * @param pioctl_req Pointer to mlan_ioctl_req
+ *
+ * @return MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ */
+mlan_status wlan_11h_ioctl_chan_switch_count(pmlan_adapter pmadapter,
+ pmlan_ioctl_req pioctl_req)
+{
+ mlan_ds_11h_cfg *ds_11hcfg = MNULL;
+ t_s32 ret = MLAN_STATUS_FAILURE;
+
+ ENTER();
+
+ if (pioctl_req) {
+ ds_11hcfg = (mlan_ds_11h_cfg *)pioctl_req->pbuf;
+
+ if (pioctl_req->action == MLAN_ACT_GET) {
+ ds_11hcfg->param.cs_count = pmadapter->dfs_cs_count;
+ } else {
+ pmadapter->dfs_cs_count = ds_11hcfg->param.cs_count;
+ }
+ ret = MLAN_STATUS_SUCCESS;
+ }
+
+ LEAVE();
+ return ret;
+}
+
+/**
+ * @brief 802.11h DFS chan report
+ *
+ * @param priv Pointer to mlan_private
+ * @param pioctl_req Pointer to mlan_ioctl_req
+ *
+ * @return MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ */
+mlan_status wlan_11h_ioctl_dfs_chan_report(mlan_private *priv,
+ pmlan_ioctl_req pioctl_req)
+{
+ mlan_ds_11h_cfg *ds_11hcfg = MNULL;
+ HostCmd_DS_CHAN_RPT_REQ *chan_rpt_req = MNULL;
+ t_s32 ret;
+
+ ENTER();
+
+ ds_11hcfg = (mlan_ds_11h_cfg *)pioctl_req->pbuf;
+
+ chan_rpt_req =
+ (HostCmd_DS_CHAN_RPT_REQ *)&ds_11hcfg->param.chan_rpt_req;
+
+ ret = wlan_prepare_cmd(priv, HostCmd_CMD_CHAN_REPORT_REQUEST,
+ HostCmd_ACT_GEN_SET, 0, (t_void *)pioctl_req,
+ (t_void *)chan_rpt_req);
+
+ if (ret == MLAN_STATUS_SUCCESS)
+ ret = MLAN_STATUS_PENDING;
+
+ LEAVE();
+ return ret;
+}
+/**
+ * @brief Check if channel is under NOP (Non-Occupancy Period)
+ * If so, the channel should not be used until the period expires.
+ *
+ * @param pmadapter Pointer to mlan_adapter
+ * @param channel Channel number
+ *
+ * @return MTRUE or MFALSE
+ */
+t_bool wlan_11h_is_channel_under_nop(mlan_adapter *pmadapter, t_u8 channel)
+{
+ wlan_dfs_timestamp_t *pdfs_ts = MNULL;
+ t_u32 now_sec, now_usec;
+ t_bool ret = MFALSE;
+ ENTER();
+ pdfs_ts = wlan_11h_find_dfs_timestamp(pmadapter, channel);
+
+ if (pdfs_ts && (pdfs_ts->channel == channel) &&
+ (pdfs_ts->represents == DFS_TS_REPR_NOP_START)) {
+ /* found NOP_start timestamp entry on channel */
+ pmadapter->callbacks.moal_get_system_time(
+ pmadapter->pmoal_handle, &now_sec, &now_usec);
+ if (pmadapter->dfs_test_params.user_nop_period_sec) {
+ PRINTM(MCMD_D,
+ "dfs_testing - user NOP period=%d (sec)\n",
+ pmadapter->dfs_test_params.user_nop_period_sec);
+ if ((now_sec - pdfs_ts->ts_sec) <=
+ pmadapter->dfs_test_params.user_nop_period_sec) {
+ ret = MTRUE;
+ }
+ } else {
+ if ((now_sec - pdfs_ts->ts_sec) <=
+ WLAN_11H_NON_OCCUPANCY_PERIOD)
+ ret = MTRUE;
+ }
+
+ /* if entry is expired, remove it */
+ if (!ret) {
+ wlan_11h_remove_dfs_timestamp(pmadapter, pdfs_ts);
+ } else
+ PRINTM(MMSG,
+ "11h: channel %d is under NOP - can't use.\n",
+ channel);
+ }
+
+ LEAVE();
+ return ret;
+}
+
+/**
+ * @brief Driver handling for CHANNEL_REPORT_RDY event
+ * This event will have the channel report data appended.
+ *
+ * @param priv Pointer to mlan_private
+ * @param pevent Pointer to mlan_event
+ *
+ * @return MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ */
+mlan_status wlan_11h_handle_event_chanrpt_ready(mlan_private *priv,
+ mlan_event *pevent,
+ t_u8 *radar_chan)
+{
+ mlan_status ret = MLAN_STATUS_SUCCESS;
+ HostCmd_DS_CHAN_RPT_RSP *pchan_rpt_rsp;
+ MrvlIEtypes_Data_t *ptlv;
+ MeasRptBasicMap_t *pmeas_rpt_basic;
+ t_u8 *pbuffer;
+ t_s32 evt_len;
+ t_u16 tlv_len;
+ t_u32 sec, usec;
+ wlan_dfs_device_state_t *pstate_dfs = &priv->adapter->state_dfs;
+ t_u8 dfs_radar_found = MFALSE;
+ t_u8 dfs_check_channel = pstate_dfs->dfs_check_channel;
+
+ ENTER();
+ pchan_rpt_rsp = (HostCmd_DS_CHAN_RPT_RSP *)&pevent->event_buf;
+ DBG_HEXDUMP(MCMD_D, "11h: Event ChanRptReady (HostCmd_DS_CHAN_RPT_RSP)",
+ (t_u8 *)pchan_rpt_rsp, pevent->event_len);
+
+ if (wlan_le32_to_cpu(pchan_rpt_rsp->cmd_result) ==
+ MLAN_CMD_RESULT_SUCCESS) {
+ pbuffer = (t_u8 *)&pchan_rpt_rsp->tlv_buffer;
+ evt_len = pevent->event_len;
+ evt_len -= sizeof(HostCmd_DS_CHAN_RPT_RSP) -
+ sizeof(pchan_rpt_rsp->tlv_buffer);
+
+ while (evt_len >= sizeof(MrvlIEtypesHeader_t)) {
+ ptlv = (MrvlIEtypes_Data_t *)pbuffer;
+ tlv_len = wlan_le16_to_cpu(ptlv->header.len);
+
+ switch (wlan_le16_to_cpu(ptlv->header.type)) {
+ case TLV_TYPE_CHANRPT_11H_BASIC:
+ pmeas_rpt_basic =
+ (MeasRptBasicMap_t *)&ptlv->data;
+ if (pmeas_rpt_basic->radar)
+ dfs_radar_found = MTRUE;
+ break;
+ default:
+ break;
+ }
+
+ pbuffer += (tlv_len + sizeof(ptlv->header));
+ evt_len -= (tlv_len + sizeof(ptlv->header));
+ evt_len = (evt_len > 0) ? evt_len : 0;
+ }
+ } else {
+ ret = MLAN_STATUS_FAILURE;
+ }
+ if (dfs_radar_found) {
+ PRINTM(MMSG, "RADAR Detected on channel %d!\n",
+ dfs_check_channel);
+ /* add channel to NOP list */
+ wlan_11h_add_dfs_timestamp(priv->adapter, DFS_TS_REPR_NOP_START,
+ dfs_check_channel);
+ }
+ *radar_chan = dfs_check_channel;
+ pstate_dfs->dfs_radar_found = dfs_radar_found;
+ /* Update DFS structure. */
+ priv->adapter->callbacks.moal_get_system_time(
+ priv->adapter->pmoal_handle, &sec, &usec);
+ pstate_dfs->dfs_report_time_sec = sec;
+ pstate_dfs->dfs_check_pending = MFALSE;
+ pstate_dfs->dfs_check_priv = MNULL;
+
+ LEAVE();
+ return ret;
+}
+
+/**
+ * @brief Print debug info in RADAR_DETECTED event
+ * This event may have the dfs record data appended.
+ *
+ * @param priv Pointer to mlan_private
+ * @param pevent Pointer to mlan_event
+ * @param radar_chan Pointer to radar channel
+ *
+ * @return MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ */
+mlan_status wlan_11h_print_event_radar_detected(mlan_private *priv,
+ mlan_event *pevent,
+ t_u8 *radar_chan)
+{
+ wlan_dfs_device_state_t *pstate_dfs = &priv->adapter->state_dfs;
+ ENTER();
+ *radar_chan = pstate_dfs->dfs_check_channel;
+ LEAVE();
+ return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ * @brief Check if RADAR_DETECTED handling is blocking data tx
+ *
+ * @param pmadapter Pointer to mlan_adapter
+ *
+ * @return MTRUE or MFALSE
+ */
+t_bool wlan_11h_radar_detected_tx_blocked(mlan_adapter *pmadapter)
+{
+ if (pmadapter->state_rdh.tx_block)
+ return MTRUE;
+ switch (pmadapter->state_rdh.stage) {
+ case RDH_OFF:
+ case RDH_CHK_INTFS:
+ case RDH_STOP_TRAFFIC:
+ return MFALSE;
+ }
+ return MTRUE;
+}
+
+/**
+ * @brief Callback for RADAR_DETECTED event driver handling
+ *
+ * @param priv Void pointer to mlan_private
+ *
+ * @return MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ */
+mlan_status wlan_11h_radar_detected_callback(t_void *priv)
+{
+ mlan_status ret;
+ ENTER();
+ ret = wlan_11h_radar_detected_handling(
+ ((mlan_private *)(priv))->adapter, (mlan_private *)priv);
+ LEAVE();
+ return ret;
+}
+
+#ifdef UAP_SUPPORT
+/**
+ * @brief Function for handling sta disconnect event in dfs_repeater mode
+ *
+ * @param pmadapter pointer to mlan_adapter
+ *
+ * @return NONE
+ */
+void wlan_dfs_rep_disconnect(mlan_adapter *pmadapter)
+{
+ mlan_private *priv_list[MLAN_MAX_BSS_NUM];
+ mlan_private *pmpriv = MNULL;
+ t_u8 pcount, i;
+
+ memset(pmadapter, priv_list, 0x00, sizeof(priv_list));
+ pcount = wlan_get_privs_by_cond(pmadapter, wlan_is_intf_active,
+ priv_list);
+
+ /* Stop all the active BSSes */
+ for (i = 0; i < pcount; i++) {
+ pmpriv = priv_list[i];
+
+ if (GET_BSS_ROLE(pmpriv) != MLAN_BSS_ROLE_UAP)
+ continue;
+
+ if (wlan_11h_radar_detect_required(pmpriv,
+ pmadapter->dfsr_channel)) {
+ wlan_prepare_cmd(pmpriv, HOST_CMD_APCMD_BSS_STOP,
+ HostCmd_ACT_GEN_SET, 0, MNULL, MNULL);
+ }
+ }
+}
+
+/**
+ * @brief Function for handling sta BW change event in dfs_repeater mode
+ *
+ * @param pmadapter pointer to mlan_adapter
+ *
+ * @return NONE
+ */
+void wlan_dfs_rep_bw_change(mlan_adapter *pmadapter)
+{
+ mlan_private *priv_list[MLAN_MAX_BSS_NUM];
+ mlan_private *pmpriv = MNULL;
+ t_u8 pcount, i;
+
+ memset(pmadapter, priv_list, 0x00, sizeof(priv_list));
+ pcount = wlan_get_privs_by_cond(pmadapter, wlan_is_intf_active,
+ priv_list);
+ if (pcount == 1) {
+ pmpriv = priv_list[0];
+ if (GET_BSS_ROLE(pmpriv) == MLAN_BSS_ROLE_STA) {
+ PRINTM(MMSG,
+ "dfs-repeater: BW change detected\n"
+ "no active priv's, skip event handling.\n");
+ return;
+ }
+ }
+
+ /* Stop all the active BSSes */
+ for (i = 0; i < pcount; i++) {
+ pmpriv = priv_list[i];
+
+ if (GET_BSS_ROLE(pmpriv) == MLAN_BSS_ROLE_UAP) {
+ /* Check if uAPs running on non-dfs channel. If they do
+ * then there is no need to restart the uAPs
+ */
+ if (!wlan_11h_radar_detect_required(
+ pmpriv, pmadapter->dfsr_channel))
+ return;
+
+ wlan_prepare_cmd(pmpriv, HOST_CMD_APCMD_BSS_STOP,
+ HostCmd_ACT_GEN_SET, 0, MNULL, MNULL);
+ }
+ }
+
+ /* Start all old active BSSes */
+ for (i = 0; i < pcount; i++) {
+ pmpriv = priv_list[i];
+
+ if (GET_BSS_ROLE(pmpriv) == MLAN_BSS_ROLE_UAP) {
+ wlan_prepare_cmd(pmpriv, HOST_CMD_APCMD_BSS_START,
+ HostCmd_ACT_GEN_SET, 0, MNULL, MNULL);
+ }
+ }
+}
+#endif
+
+/**
+ * @brief Update band config for the new channel
+ *
+ * @param uap_band_cfg uap's old channel's band configuration
+ * @param new_channel new channel that the device is switching to
+ *
+ * @return MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE or MLAN_STATUS_PENDING
+ */
+void wlan_11h_update_bandcfg(Band_Config_t *uap_band_cfg, t_u8 new_channel)
+{
+ t_u8 chan_offset;
+ ENTER();
+
+ /* Update the channel offset for 20MHz, 40MHz and 80MHz
+ * Clear the channel bandwidth for 20MHz
+ * since channel switch could be happening from 40/80MHz to 20MHz
+ */
+ chan_offset = wlan_get_second_channel_offset(new_channel);
+ uap_band_cfg->chan2Offset = chan_offset;
+
+ if (!chan_offset) { /* 40MHz/80MHz */
+ PRINTM(MCMD_D, "20MHz channel, clear channel bandwidth\n");
+ uap_band_cfg->chanWidth = CHAN_BW_20MHZ;
+ }
+ LEAVE();
+}
+
+/**
+ * @brief Get priv current index -- this is used to enter correct rdh_state
+ * during radar handling
+ *
+ * @param pmpriv Pointer to mlan_private
+ * @param pstate_rdh Pointer to radar detected state handler
+ *
+ * @return MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ */
+mlan_status wlan_11h_get_priv_curr_idx(mlan_private *pmpriv,
+ wlan_radar_det_hndlg_state_t *pstate_rdh)
+{
+ t_bool found = MFALSE;
+ ENTER();
+
+ PRINTM(MINFO, "%s:pmpriv =%p\n", __func__, pmpriv);
+ while ((++pstate_rdh->priv_curr_idx) < pstate_rdh->priv_list_count) {
+ if (pmpriv ==
+ pstate_rdh->priv_list[pstate_rdh->priv_curr_idx]) {
+ PRINTM(MINFO, "found matching priv: priv_idx=%d\n",
+ pstate_rdh->priv_curr_idx);
+ found = MTRUE;
+ break;
+ }
+ }
+ return (found == MTRUE) ? MLAN_STATUS_SUCCESS : MLAN_STATUS_FAILURE;
+}
+
+/**
+ * @brief Driver handling for remove customeie
+ *
+ * @param pmadapter Pointer to mlan_adapter
+ * @param pmpriv Pointer to mlan_private
+ *
+ * @return MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE or MLAN_STATUS_PENDING
+ */
+mlan_status wlan_11h_remove_custom_ie(mlan_adapter *pmadapter,
+ mlan_private *pmpriv)
+{
+ mlan_status ret = MLAN_STATUS_SUCCESS;
+ wlan_radar_det_hndlg_state_t *pstate_rdh = &pmadapter->state_rdh;
+ mlan_ioctl_req *pioctl_req = MNULL;
+
+ ENTER();
+ if (pstate_rdh->stage == RDH_SET_CUSTOM_IE) {
+ pstate_rdh->priv_curr_idx = RDH_STAGE_FIRST_ENTRY_PRIV_IDX;
+ PRINTM(MMSG, "Removing CHAN_SW IE from interfaces.\n");
+ while ((++pstate_rdh->priv_curr_idx) <
+ pstate_rdh->priv_list_count) {
+ pmpriv =
+ pstate_rdh->priv_list[pstate_rdh->priv_curr_idx];
+ if (!wlan_11h_is_dfs_master(pmpriv))
+ continue;
+ ret = wlan_11h_prepare_custom_ie_chansw(
+ pmadapter, &pioctl_req, MFALSE);
+ if ((ret != MLAN_STATUS_SUCCESS) || !pioctl_req) {
+ PRINTM(MERROR,
+ "%s(): Error in preparing CHAN_SW IE.\n",
+ __func__);
+ goto done;
+ }
+
+ pioctl_req->bss_index = pmpriv->bss_index;
+ ret = wlan_misc_ioctl_custom_ie_list(
+ pmadapter, pioctl_req, MFALSE);
+ if (ret != MLAN_STATUS_SUCCESS &&
+ ret != MLAN_STATUS_PENDING) {
+ PRINTM(MERROR,
+ "%s(): Could not remove IE for priv=%p [priv_bss_idx=%d]!\n",
+ __func__, pmpriv, pmpriv->bss_index);
+ /* TODO: hiow to handle this error case??
+ * ignore & continue? */
+ }
+ /* free ioctl buffer memory before we leave */
+ pmadapter->callbacks.moal_mfree(pmadapter->pmoal_handle,
+ (t_u8 *)pioctl_req);
+ }
+ }
+done:
+ LEAVE();
+ return ret;
+}
+
+/**
+ * @brief Driver handling for RADAR_DETECTED event
+ *
+ * @param pmadapter Pointer to mlan_adapter
+ * @param pmpriv Pointer to mlan_private
+ *
+ * @return MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE or MLAN_STATUS_PENDING
+ */
+mlan_status wlan_11h_radar_detected_handling(mlan_adapter *pmadapter,
+ mlan_private *pmpriv)
+{
+#ifdef DEBUG_LEVEL1
+ const char *rdh_stage_str[] = {"RDH_OFF",
+ "RDH_CHK_INTFS",
+ "RDH_STOP_TRAFFIC",
+ "RDH_GET_INFO_CHANNEL",
+ "RDH_GET_INFO_BEACON_DTIM",
+ "RDH_SET_CUSTOM_IE",
+ "RDH_REM_CUSTOM_IE",
+ "RDH_STOP_INTFS",
+ "RDH_SET_NEW_CHANNEL",
+ "RDH_RESTART_INTFS",
+ "RDH_RESTART_TRAFFIC"};
+#endif
+
+ mlan_status ret = MLAN_STATUS_SUCCESS;
+ t_u32 i;
+ wlan_radar_det_hndlg_state_t *pstate_rdh = &pmadapter->state_rdh;
+
+ ENTER();
+
+ if (!pmpriv) {
+ PRINTM(MERROR, "Invalid radar priv -- Exit radar handling\n");
+ LEAVE();
+ return MLAN_STATUS_FAILURE;
+ }
+
+ switch (pstate_rdh->stage) {
+ case RDH_CHK_INTFS:
+ PRINTM(MCMD_D, "%s(): stage(%d)=%s\n", __func__,
+ pstate_rdh->stage, rdh_stage_str[pstate_rdh->stage]);
+
+ /* get active interfaces */
+ memset(pmadapter, pstate_rdh->priv_list, 0x00,
+ sizeof(pstate_rdh->priv_list));
+ pstate_rdh->priv_list_count = wlan_get_privs_by_cond(
+ pmadapter, wlan_is_intf_active, pstate_rdh->priv_list);
+ PRINTM(MCMD_D, "%s(): priv_list_count = %d\n", __func__,
+ pstate_rdh->priv_list_count);
+ for (i = 0; i < pstate_rdh->priv_list_count; i++)
+ PRINTM(MINFO, "%s(): priv_list[%d] = %p\n", __func__,
+ i, pstate_rdh->priv_list[i]);
+
+ if (pstate_rdh->priv_list_count == 0) {
+ /* no interfaces active... nothing to do */
+ PRINTM(MMSG, "11h: Radar Detected - no active priv's,"
+ " skip event handling.\n");
+ pstate_rdh->stage = RDH_OFF;
+ PRINTM(MCMD_D, "%s(): finished - stage(%d)=%s\n",
+ __func__, pstate_rdh->stage,
+ rdh_stage_str[pstate_rdh->stage]);
+ break; /* EXIT CASE */
+ }
+
+ /* else: start handling */
+ pstate_rdh->curr_channel = 0;
+ pstate_rdh->new_channel = 0;
+ memset(pmadapter, &(pstate_rdh->uap_band_cfg), 0,
+ sizeof(pstate_rdh->uap_band_cfg));
+ pstate_rdh->max_bcn_dtim_ms = 0;
+ pstate_rdh->priv_curr_idx = RDH_STAGE_FIRST_ENTRY_PRIV_IDX;
+ pstate_rdh->stage = RDH_STOP_TRAFFIC;
+ /* fall through */
+
+ case RDH_STOP_TRAFFIC:
+ PRINTM(MCMD_D, "%s(): stage(%d)=%s\n", __func__,
+ pstate_rdh->stage, rdh_stage_str[pstate_rdh->stage]);
+
+ PRINTM(MMSG,
+ "11h: Radar Detected - stopping host tx traffic.\n");
+ for (i = 0; i < pstate_rdh->priv_list_count; i++)
+ wlan_11h_tx_disable(pstate_rdh->priv_list[i]);
+
+ pstate_rdh->priv_curr_idx = RDH_STAGE_FIRST_ENTRY_PRIV_IDX;
+ pstate_rdh->stage = RDH_GET_INFO_CHANNEL;
+ /* fall through */
+
+ case RDH_GET_INFO_CHANNEL:
+ PRINTM(MCMD_D, "%s(): stage(%d)=%s, priv_idx=%d\n", __func__,
+ pstate_rdh->stage, rdh_stage_str[pstate_rdh->stage],
+ pstate_rdh->priv_curr_idx);
+
+ /* here, prefer STA info over UAP info - one less CMD to send */
+ if (pstate_rdh->priv_curr_idx ==
+ RDH_STAGE_FIRST_ENTRY_PRIV_IDX) {
+#ifdef UAP_SUPPORT
+ if (GET_BSS_ROLE(pmpriv) == MLAN_BSS_ROLE_UAP) {
+ ret = wlan_11h_get_priv_curr_idx(pmpriv,
+ pstate_rdh);
+ if (ret != MLAN_STATUS_SUCCESS) {
+ PRINTM(MERROR,
+ "Unable to locate pmpriv in current active priv_list\n");
+ break; /* EXIT CASE */
+ }
+
+ /* send cmd to get first UAP's info */
+ pmpriv->uap_state_chan_cb.pioctl_req_curr =
+ MNULL;
+ pmpriv->uap_state_chan_cb.get_chan_callback =
+ wlan_11h_radar_detected_callback;
+ ret = wlan_uap_get_channel(pmpriv);
+ break; /* EXIT CASE */
+ } else
+#endif
+ {
+ /* Assume all STAs on same channel, find first
+ * STA */
+ MASSERT(pstate_rdh->priv_list_count > 0);
+ for (i = 0; i < pstate_rdh->priv_list_count;
+ i++) {
+ pmpriv = pstate_rdh->priv_list[i];
+ if (GET_BSS_ROLE(pmpriv) ==
+ MLAN_BSS_ROLE_STA)
+ break;
+ }
+ /* STA info kept in driver, just copy */
+ pstate_rdh->curr_channel =
+ pmpriv->curr_bss_params.bss_descriptor
+ .channel;
+ }
+ }
+#ifdef UAP_SUPPORT
+ else if (pstate_rdh->priv_curr_idx <
+ pstate_rdh->priv_list_count) {
+ /* repeat entry: UAP return with info */
+ pstate_rdh->curr_channel =
+ pmpriv->uap_state_chan_cb.channel;
+ pstate_rdh->uap_band_cfg =
+ pmpriv->uap_state_chan_cb.bandcfg;
+ PRINTM(MCMD_D,
+ "%s(): uap_band_cfg=0x%02x curr_chan=%d, curr_idx=%d bss_role=%d\n",
+ __func__, pstate_rdh->uap_band_cfg,
+ pstate_rdh->curr_channel,
+ pstate_rdh->priv_curr_idx, GET_BSS_ROLE(pmpriv));
+ }
+#endif
+
+ /* add channel to NOP list */
+ wlan_11h_add_dfs_timestamp(pmadapter, DFS_TS_REPR_NOP_START,
+ pstate_rdh->curr_channel);
+
+ /* choose new channel (!= curr channel) and move on */
+#ifdef UAP_SUPPORT
+ if (GET_BSS_ROLE(pmpriv) == MLAN_BSS_ROLE_UAP)
+ pstate_rdh->new_channel =
+ wlan_11h_get_uap_start_channel(
+ pmpriv,
+ pmpriv->uap_state_chan_cb.bandcfg);
+ else
+#endif
+ pstate_rdh->new_channel =
+ wlan_11h_get_adhoc_start_channel(pmpriv);
+
+ if (!pstate_rdh->new_channel ||
+ (pstate_rdh->new_channel ==
+ pstate_rdh->curr_channel)) { /* report error */
+ PRINTM(MERROR,
+ "%s(): ERROR - Failed to choose new_chan"
+ " (!= curr_chan) !!\n",
+ __func__);
+#ifdef UAP_SUPPORT
+ if (GET_BSS_ROLE(pmpriv) == MLAN_BSS_ROLE_UAP) {
+ ret = wlan_prepare_cmd(pmpriv,
+ HOST_CMD_APCMD_BSS_STOP,
+ HostCmd_ACT_GEN_SET, 0,
+ MNULL, MNULL);
+ PRINTM(MERROR,
+ "STOP UAP and exit radar handling...\n");
+ pstate_rdh->stage = RDH_OFF;
+ break; /* leads to exit case */
+ }
+#endif
+ }
+ if (!pmadapter->dfs_test_params.no_channel_change_on_radar &&
+ pmadapter->dfs_test_params.fixed_new_channel_on_radar) {
+ PRINTM(MCMD_D, "dfs_testing - user fixed new_chan=%d\n",
+ pmadapter->dfs_test_params
+ .fixed_new_channel_on_radar);
+ pstate_rdh->new_channel =
+ pmadapter->dfs_test_params
+ .fixed_new_channel_on_radar;
+ }
+ /* applies to DFS with ECSA support */
+ if (pmadapter->dfs_test_params.no_channel_change_on_radar) {
+ pstate_rdh->new_channel = pstate_rdh->curr_channel;
+ }
+ PRINTM(MCMD_D, "%s(): curr_chan=%d, new_chan=%d\n", __func__,
+ pstate_rdh->curr_channel, pstate_rdh->new_channel);
+
+ pstate_rdh->priv_curr_idx = RDH_STAGE_FIRST_ENTRY_PRIV_IDX;
+ pstate_rdh->stage = RDH_GET_INFO_BEACON_DTIM;
+ /* fall through */
+
+ case RDH_GET_INFO_BEACON_DTIM:
+ PRINTM(MCMD_D, "%s(): stage(%d)=%s, priv_idx=%d\n", __func__,
+ pstate_rdh->stage, rdh_stage_str[pstate_rdh->stage],
+ pstate_rdh->priv_curr_idx);
+
+#ifdef UAP_SUPPORT
+ /* check all intfs in this stage to find longest period */
+ /* UAP intf callback returning with info */
+ if (pstate_rdh->priv_curr_idx < pstate_rdh->priv_list_count) {
+ t_u16 bcn_dtim_msec;
+ pmpriv =
+ pstate_rdh->priv_list[pstate_rdh->priv_curr_idx];
+ PRINTM(MCMD_D, "%s(): uap.bcn_pd=%d, uap.dtim_pd=%d\n",
+ __func__,
+ pmpriv->uap_state_chan_cb.beacon_period,
+ pmpriv->uap_state_chan_cb.dtim_period);
+ bcn_dtim_msec =
+ (pmpriv->uap_state_chan_cb.beacon_period *
+ pmpriv->uap_state_chan_cb.dtim_period);
+ if (bcn_dtim_msec > pstate_rdh->max_bcn_dtim_ms)
+ pstate_rdh->max_bcn_dtim_ms = bcn_dtim_msec;
+ }
+#endif
+
+ /* check next intf */
+ while ((++pstate_rdh->priv_curr_idx) <
+ pstate_rdh->priv_list_count) {
+ pmpriv =
+ pstate_rdh->priv_list[pstate_rdh->priv_curr_idx];
+
+#ifdef UAP_SUPPORT
+ if (GET_BSS_ROLE(pmpriv) == MLAN_BSS_ROLE_UAP) {
+ pmpriv->uap_state_chan_cb.pioctl_req_curr =
+ MNULL;
+ pmpriv->uap_state_chan_cb.get_chan_callback =
+ wlan_11h_radar_detected_callback;
+ ret = wlan_uap_get_beacon_dtim(pmpriv);
+ break; /* leads to exit case */
+ } else
+#endif
+ { /* get STA info from driver and compare here */
+ t_u16 bcn_pd_msec = 100;
+ t_u16 dtim_pd_msec = 1;
+ t_u16 bcn_dtim_msec;
+
+ /* adhoc creator */
+ if (wlan_11h_is_dfs_master(pmpriv)) {
+ bcn_pd_msec = pmpriv->beacon_period;
+ } else {
+ bcn_pd_msec = pmpriv->curr_bss_params
+ .bss_descriptor
+ .beacon_period;
+ /* if (priv->bss_mode !=
+ * MLAN_BSS_MODE_IBSS) */
+ /* TODO: mlan_scan.c needs to parse TLV
+ * 0x05 (TIM) for dtim_period */
+ }
+ PRINTM(MCMD_D,
+ "%s(): sta.bcn_pd=%d, sta.dtim_pd=%d\n",
+ __func__, bcn_pd_msec, dtim_pd_msec);
+ bcn_dtim_msec = (bcn_pd_msec * dtim_pd_msec);
+ if (bcn_dtim_msec > pstate_rdh->max_bcn_dtim_ms)
+ pstate_rdh->max_bcn_dtim_ms =
+ bcn_dtim_msec;
+ }
+ }
+
+ if (pstate_rdh->priv_curr_idx < pstate_rdh->priv_list_count)
+ break; /* EXIT CASE (for UAP) */
+ /* else */
+ pstate_rdh->priv_curr_idx = RDH_STAGE_FIRST_ENTRY_PRIV_IDX;
+ pstate_rdh->stage = RDH_SET_CUSTOM_IE;
+ /* fall through */
+
+ case RDH_SET_CUSTOM_IE:
+ PRINTM(MCMD_D, "%s(): stage(%d)=%s, priv_idx=%d\n", __func__,
+ pstate_rdh->stage, rdh_stage_str[pstate_rdh->stage],
+ pstate_rdh->priv_curr_idx);
+
+ /* add CHAN_SW IE - Need apply on each interface */
+ if (pstate_rdh->priv_curr_idx ==
+ RDH_STAGE_FIRST_ENTRY_PRIV_IDX) {
+ mlan_ioctl_req *pioctl_req = MNULL;
+ PRINTM(MMSG,
+ "11h: Radar Detected - adding CHAN_SW IE to interfaces.\n");
+ while ((++pstate_rdh->priv_curr_idx) <
+ pstate_rdh->priv_list_count) {
+ pmpriv = pstate_rdh->priv_list
+ [pstate_rdh->priv_curr_idx];
+ if (!wlan_11h_is_dfs_master(pmpriv))
+ continue;
+ ret = wlan_11h_prepare_custom_ie_chansw(
+ pmadapter, &pioctl_req, MTRUE);
+ if ((ret != MLAN_STATUS_SUCCESS) ||
+ !pioctl_req) {
+ PRINTM(MERROR,
+ "%s(): Error in preparing CHAN_SW IE.\n",
+ __func__);
+ break; /* EXIT CASE */
+ }
+
+ pioctl_req->bss_index = pmpriv->bss_index;
+ ret = wlan_misc_ioctl_custom_ie_list(
+ pmadapter, pioctl_req, MFALSE);
+ if (ret != MLAN_STATUS_SUCCESS &&
+ ret != MLAN_STATUS_PENDING) {
+ PRINTM(MERROR,
+ "%s(): Could not set IE for priv=%p [priv_bss_idx=%d]!\n",
+ __func__, pmpriv,
+ pmpriv->bss_index);
+ /* TODO: how to handle this error case??
+ * ignore & continue? */
+ }
+ /* free ioctl buffer memory before we leave */
+ pmadapter->callbacks.moal_mfree(
+ pmadapter->pmoal_handle,
+ (t_u8 *)pioctl_req);
+ }
+ break; /* EXIT CASE */
+ }
+ /* else */
+ pstate_rdh->priv_curr_idx = RDH_STAGE_FIRST_ENTRY_PRIV_IDX;
+ pstate_rdh->stage = RDH_REM_CUSTOM_IE;
+ /* fall through */
+
+ case RDH_REM_CUSTOM_IE:
+ PRINTM(MCMD_D, "%s(): stage(%d)=%s, priv_idx=%d\n", __func__,
+ pstate_rdh->stage, rdh_stage_str[pstate_rdh->stage],
+ pstate_rdh->priv_curr_idx);
+
+ /* remove CHAN_SW IE - Need apply on each interface */
+ if (pstate_rdh->priv_curr_idx ==
+ RDH_STAGE_FIRST_ENTRY_PRIV_IDX) {
+ mlan_ioctl_req *pioctl_req = MNULL;
+ /*
+ * first entry to this stage, do delay
+ * DFS requires a minimum of 5 chances for clients to
+ * hear this IE. Use delay: 5 beacons <=
+ * (BCN_DTIM_MSEC*5) <= 3 seconds).
+ */
+ t_u16 delay_ms =
+ MAX(MIN_RDH_CHAN_SW_IE_PERIOD_MSEC,
+ MIN((4 * pstate_rdh->max_bcn_dtim_ms),
+ MAX_RDH_CHAN_SW_IE_PERIOD_MSEC));
+ PRINTM(MMSG,
+ "11h: Radar Detected - delay %d ms for FW to"
+ " broadcast CHAN_SW IE.\n",
+ delay_ms);
+ wlan_mdelay(pmadapter, delay_ms);
+ PRINTM(MMSG,
+ "11h: Radar Detected - delay over, removing"
+ " CHAN_SW IE from interfaces.\n");
+ while ((++pstate_rdh->priv_curr_idx) <
+ pstate_rdh->priv_list_count) {
+ pmpriv = pstate_rdh->priv_list
+ [pstate_rdh->priv_curr_idx];
+ if (!wlan_11h_is_dfs_master(pmpriv))
+ continue;
+ ret = wlan_11h_prepare_custom_ie_chansw(
+ pmadapter, &pioctl_req, MFALSE);
+ if ((ret != MLAN_STATUS_SUCCESS) ||
+ !pioctl_req) {
+ PRINTM(MERROR,
+ "%s(): Error in preparing CHAN_SW IE.\n",
+ __func__);
+ break; /* EXIT CASE */
+ }
+
+ pioctl_req->bss_index = pmpriv->bss_index;
+ ret = wlan_misc_ioctl_custom_ie_list(
+ pmadapter, pioctl_req, MFALSE);
+ if (ret != MLAN_STATUS_SUCCESS &&
+ ret != MLAN_STATUS_PENDING) {
+ PRINTM(MERROR,
+ "%s(): Could not remove IE for priv=%p [priv_bss_idx=%d]!\n",
+ __func__, pmpriv,
+ pmpriv->bss_index);
+ /* TODO: hiow to handle this error
+ * case?? ignore & continue? */
+ }
+ /* free ioctl buffer memory before we leave */
+ pmadapter->callbacks.moal_mfree(
+ pmadapter->pmoal_handle,
+ (t_u8 *)pioctl_req);
+ }
+ break; /* EXIT CASE */
+ }
+ /* else */
+ pstate_rdh->priv_curr_idx = RDH_STAGE_FIRST_ENTRY_PRIV_IDX;
+ pstate_rdh->stage = RDH_STOP_INTFS;
+ /* fall through */
+
+ case RDH_STOP_INTFS:
+ PRINTM(MCMD_D, "%s(): stage(%d)=%s, priv_idx=%d\n", __func__,
+ pstate_rdh->stage, rdh_stage_str[pstate_rdh->stage],
+ pstate_rdh->priv_curr_idx);
+
+ /* issues one cmd (DEAUTH/ADHOC_STOP/BSS_STOP) to each intf */
+ while ((++pstate_rdh->priv_curr_idx) <
+ pstate_rdh->priv_list_count) {
+ pmpriv =
+ pstate_rdh->priv_list[pstate_rdh->priv_curr_idx];
+#ifdef UAP_SUPPORT
+ if (GET_BSS_ROLE(pmpriv) == MLAN_BSS_ROLE_UAP) {
+ ret = wlan_prepare_cmd(pmpriv,
+ HOST_CMD_APCMD_BSS_STOP,
+ HostCmd_ACT_GEN_SET, 0,
+ MNULL, MNULL);
+ break; /* leads to exit case */
+ }
+#endif
+#ifdef STA_SUPPORT
+ if (GET_BSS_ROLE(pmpriv) == MLAN_BSS_ROLE_STA) {
+ if (wlan_11h_is_dfs_master(pmpriv)) {
+ /* Save ad-hoc creator state before stop
+ * clears it */
+ pmpriv->adhoc_state_prev =
+ pmpriv->adhoc_state;
+ }
+ if (pmpriv->media_connected == MTRUE) {
+ wlan_disconnect(pmpriv, MNULL, MNULL);
+ break; /* leads to exit case */
+ }
+ }
+#endif
+ }
+
+ if (pstate_rdh->priv_curr_idx < pstate_rdh->priv_list_count ||
+ ret == MLAN_STATUS_FAILURE)
+ break; /* EXIT CASE */
+ /* else */
+ pstate_rdh->priv_curr_idx = RDH_STAGE_FIRST_ENTRY_PRIV_IDX;
+ pstate_rdh->stage = RDH_SET_NEW_CHANNEL;
+
+ if (pmadapter->dfs_test_params.no_channel_change_on_radar) {
+ PRINTM(MCMD_D,
+ "dfs_testing - no channel change on radar."
+ " Overwrite new_chan = curr_chan.\n");
+ pstate_rdh->new_channel = pstate_rdh->curr_channel;
+ pstate_rdh->priv_curr_idx =
+ RDH_STAGE_FIRST_ENTRY_PRIV_IDX;
+ pstate_rdh->stage = RDH_RESTART_INTFS;
+ goto rdh_restart_intfs; /* skip next stage */
+ }
+ /* fall through */
+
+ case RDH_SET_NEW_CHANNEL:
+ PRINTM(MCMD_D, "%s(): stage(%d)=%s, priv_idx=%d\n", __func__,
+ pstate_rdh->stage, rdh_stage_str[pstate_rdh->stage],
+ pstate_rdh->priv_curr_idx);
+
+ /* only set new channel for UAP intfs */
+ while ((++pstate_rdh->priv_curr_idx) <
+ pstate_rdh->priv_list_count) {
+ pmpriv =
+ pstate_rdh->priv_list[pstate_rdh->priv_curr_idx];
+#ifdef UAP_SUPPORT
+ if (GET_BSS_ROLE(pmpriv) == MLAN_BSS_ROLE_UAP) {
+ pmpriv->uap_state_chan_cb.pioctl_req_curr =
+ MNULL;
+ pmpriv->uap_state_chan_cb.get_chan_callback =
+ wlan_11h_radar_detected_callback;
+
+ /* DFS only in 5GHz */
+ wlan_11h_update_bandcfg(
+ &pstate_rdh->uap_band_cfg,
+ pstate_rdh->new_channel);
+ PRINTM(MCMD_D,
+ "RDH_SET_NEW_CHANNEL: uAP band config = 0x%x channel=%d\n",
+ pstate_rdh->uap_band_cfg,
+ pstate_rdh->new_channel);
+
+ ret = wlan_uap_set_channel(
+ pmpriv, pstate_rdh->uap_band_cfg,
+ pstate_rdh->new_channel);
+ break; /* leads to exit case */
+ }
+#endif
+ }
+
+ if (pstate_rdh->priv_curr_idx < pstate_rdh->priv_list_count ||
+ ret == MLAN_STATUS_FAILURE)
+ break; /* EXIT CASE (for UAP) */
+ /* else */
+ pstate_rdh->priv_curr_idx = RDH_STAGE_FIRST_ENTRY_PRIV_IDX;
+ pstate_rdh->stage = RDH_RESTART_INTFS;
+ /* fall through */
+
+ case RDH_RESTART_INTFS:
+ rdh_restart_intfs:
+ PRINTM(MCMD_D, "%s(): stage(%d)=%s, priv_idx=%d\n", __func__,
+ pstate_rdh->stage, rdh_stage_str[pstate_rdh->stage],
+ pstate_rdh->priv_curr_idx);
+
+ /* can only restart master intfs */
+ while ((++pstate_rdh->priv_curr_idx) <
+ pstate_rdh->priv_list_count) {
+ pmpriv =
+ pstate_rdh->priv_list[pstate_rdh->priv_curr_idx];
+#ifdef UAP_SUPPORT
+ if (GET_BSS_ROLE(pmpriv) == MLAN_BSS_ROLE_UAP) {
+ if (wlan_11h_radar_detect_required(
+ pmpriv, pstate_rdh->new_channel)) {
+ /* Radar detection is required for this
+ channel, make sure 11h is activated
+ in the firmware */
+ ret = wlan_11h_activate(pmpriv, MNULL,
+ MTRUE);
+ ret = wlan_11h_config_master_radar_det(
+ pmpriv, MTRUE);
+ ret = wlan_11h_check_update_radar_det_state(
+ pmpriv);
+ }
+ ret = wlan_prepare_cmd(pmpriv,
+ HOST_CMD_APCMD_BSS_START,
+ HostCmd_ACT_GEN_SET, 0,
+ MNULL, MNULL);
+ break; /* leads to exit case */
+ }
+#endif
+#ifdef STA_SUPPORT
+ if (GET_BSS_ROLE(pmpriv) == MLAN_BSS_ROLE_STA) {
+ /* Check previous state to find former
+ * Ad-hoc creator interface. Set new
+ * state to Starting, so it'll be seen
+ * as a DFS master. */
+ if (pmpriv->adhoc_state_prev == ADHOC_STARTED) {
+ pmpriv->adhoc_state = ADHOC_STARTING;
+ pmpriv->adhoc_state_prev = ADHOC_IDLE;
+ }
+ if (wlan_11h_is_dfs_master(pmpriv)) {
+ /* set new adhoc channel here */
+ pmpriv->adhoc_channel =
+ pstate_rdh->new_channel;
+ if (wlan_11h_radar_detect_required(
+ pmpriv,
+ pstate_rdh->new_channel)) {
+ /* Radar detection is required
+ for this channel, make sure
+ 11h is activated in the
+ firmware */
+ ret = wlan_11h_activate(
+ pmpriv, MNULL, MTRUE);
+ if (ret)
+ break;
+ ret = wlan_11h_config_master_radar_det(
+ pmpriv, MTRUE);
+ if (ret)
+ break;
+ ret = wlan_11h_check_update_radar_det_state(
+ pmpriv);
+ if (ret)
+ break;
+ }
+ ret = wlan_prepare_cmd(
+ pmpriv,
+ HostCmd_CMD_802_11_AD_HOC_START,
+ HostCmd_ACT_GEN_SET, 0, MNULL,
+ &pmpriv->adhoc_last_start_ssid);
+ break; /* leads to exit case */
+ }
+
+ /* NOTE: DON'T reconnect slave STA intfs -
+ * infra/adhoc_joiner Do we want to return to
+ * same AP/network (on radar channel)? If want
+ * to connect back, depend on either:
+ * 1. driver's reassoc thread
+ * 2. wpa_supplicant, or other user-space
+ * app
+ */
+ }
+#endif
+ }
+
+ if (pstate_rdh->priv_curr_idx < pstate_rdh->priv_list_count ||
+ ret == MLAN_STATUS_FAILURE)
+ break; /* EXIT CASE (for UAP) */
+ /* else */
+ pstate_rdh->priv_curr_idx = RDH_STAGE_FIRST_ENTRY_PRIV_IDX;
+ pstate_rdh->stage = RDH_RESTART_TRAFFIC;
+ /* fall through */
+
+ case RDH_RESTART_TRAFFIC:
+ PRINTM(MCMD_D, "%s(): stage(%d)=%s\n", __func__,
+ pstate_rdh->stage, rdh_stage_str[pstate_rdh->stage]);
+ /* remove custome ie */
+ if (pmadapter->ecsa_enable) {
+ mlan_ioctl_req *pioctl_req = MNULL;
+ pstate_rdh->priv_curr_idx =
+ RDH_STAGE_FIRST_ENTRY_PRIV_IDX;
+ while ((++pstate_rdh->priv_curr_idx) <
+ pstate_rdh->priv_list_count) {
+ pmpriv = pstate_rdh->priv_list
+ [pstate_rdh->priv_curr_idx];
+ if (!wlan_11h_is_dfs_master(pmpriv))
+ continue;
+ ret = wlan_11h_prepare_custom_ie_chansw(
+ pmadapter, &pioctl_req, MFALSE);
+ if ((ret != MLAN_STATUS_SUCCESS) ||
+ !pioctl_req) {
+ PRINTM(MERROR,
+ "%s(): Error in preparing CHAN_SW IE.\n",
+ __func__);
+ break; /* EXIT CASE */
+ }
+
+ pioctl_req->bss_index = pmpriv->bss_index;
+
+ ret = wlan_misc_ioctl_custom_ie_list(
+ pmadapter, pioctl_req, MFALSE);
+ if (ret != MLAN_STATUS_SUCCESS &&
+ ret != MLAN_STATUS_PENDING) {
+ PRINTM(MERROR,
+ "%s(): Could not remove IE for priv=%p [priv_bss_idx=%d]!\n",
+ __func__, pmpriv,
+ pmpriv->bss_index);
+ /* TODO: hiow to handle this error
+ * case?? ignore & continue? */
+ }
+ /* free ioctl buffer memory before we leave */
+ pmadapter->callbacks.moal_mfree(
+ pmadapter->pmoal_handle,
+ (t_u8 *)pioctl_req);
+ }
+ }
+ /* continue traffic for reactivated interfaces */
+ PRINTM(MMSG,
+ "11h: Radar Detected - restarting host tx traffic.\n");
+ for (i = 0; i < pstate_rdh->priv_list_count; i++)
+ wlan_11h_tx_enable(pstate_rdh->priv_list[i]);
+
+ pstate_rdh->stage = RDH_OFF; /* DONE! */
+ PRINTM(MCMD_D, "%s(): finished - stage(%d)=%s\n", __func__,
+ pstate_rdh->stage, rdh_stage_str[pstate_rdh->stage]);
+
+ break;
+
+ default:
+ pstate_rdh->stage = RDH_OFF; /* cancel RDH to unblock Tx packets
+ */
+ break;
+ }
+
+ LEAVE();
+ return ret;
+}
+
+/**
+ * @brief DFS Event Preprocessing.
+ * Operates directly on pmadapter variables.
+ *
+ * 1. EVENT_RADAR_DETECTED comes from firmware without specific
+ * bss_num/bss_type. Find it an appropriate interface and
+ * update event_cause field in event_buf.
+ *
+ * @param pmadapter Pointer to mlan_adapter
+ *
+ * @return MLAN_STATUS_SUCCESS (update successful)
+ * or MLAN_STATUS_FAILURE (no change)
+ */
+mlan_status wlan_11h_dfs_event_preprocessing(mlan_adapter *pmadapter)
+{
+ mlan_status ret = MLAN_STATUS_FAILURE;
+ mlan_private *pmpriv = MNULL;
+ mlan_private *priv_list[MLAN_MAX_BSS_NUM] = {0};
+
+ ENTER();
+ switch (pmadapter->event_cause & EVENT_ID_MASK) {
+ case EVENT_RADAR_DETECTED:
+ /* find active intf: prefer dfs_master over dfs_slave */
+ if (wlan_get_privs_by_two_cond(
+ pmadapter, wlan_11h_is_master_active_on_dfs_chan,
+ wlan_11h_is_dfs_master, MTRUE, priv_list)) {
+ pmpriv = priv_list[0];
+ PRINTM(MINFO, "%s: found dfs_master priv=%p\n",
+ __func__, pmpriv);
+ } else if (wlan_get_privs_by_two_cond(
+ pmadapter,
+ wlan_11h_is_slave_active_on_dfs_chan,
+ wlan_11h_is_dfs_slave, MTRUE, priv_list)) {
+ pmpriv = priv_list[0];
+ PRINTM(MINFO, "%s: found dfs_slave priv=%p\n", __func__,
+ pmpriv);
+ } else if (pmadapter->state_dfs.dfs_check_pending) {
+ pmpriv = (mlan_private *)(pmadapter->state_dfs
+ .dfs_check_priv);
+ PRINTM(MINFO, "%s: found dfs priv=%p\n", __func__,
+ pmpriv);
+ }
+
+ /* update event_cause if we found an appropriate priv */
+ if (pmpriv) {
+ pmlan_buffer pmevbuf = pmadapter->pmlan_buffer_event;
+ t_u32 new_event_cause =
+ pmadapter->event_cause & EVENT_ID_MASK;
+ new_event_cause |=
+ ((GET_BSS_NUM(pmpriv) & 0xff) << 16) |
+ ((pmpriv->bss_type & 0xff) << 24);
+ PRINTM(MINFO, "%s: priv - bss_num=%d, bss_type=%d\n",
+ __func__, GET_BSS_NUM(pmpriv), pmpriv->bss_type);
+ memcpy_ext(pmadapter,
+ pmevbuf->pbuf + pmevbuf->data_offset,
+ &new_event_cause, sizeof(new_event_cause),
+ sizeof(new_event_cause));
+ ret = MLAN_STATUS_SUCCESS;
+ } else {
+ PRINTM(MERROR,
+ "Failed to find dfs master/slave priv\n");
+ ret = MLAN_STATUS_FAILURE;
+ }
+ break;
+ }
+
+ LEAVE();
+ return ret;
+}
+
+/**
+ * @brief try to switch to a non-dfs channel
+ *
+ * @param priv Void pointer to mlan_private
+ *
+ * @param chan pointer to channel
+ *
+ * @return MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE or MLAN_STATUS_PENDING
+ */
+mlan_status wlan_11h_switch_non_dfs_chan(mlan_private *priv, t_u8 *chan)
+{
+ mlan_status ret = MLAN_STATUS_FAILURE;
+ t_u32 i;
+ t_u32 rand_entry;
+ t_u8 def_chan;
+ t_u8 rand_tries = 0;
+ region_chan_t *chn_tbl = MNULL;
+ pmlan_adapter pmadapter = priv->adapter;
+
+ ENTER();
+
+ if (!pmadapter->dfs_test_params.no_channel_change_on_radar &&
+ pmadapter->dfs_test_params.fixed_new_channel_on_radar) {
+ PRINTM(MCMD_D, "dfs_testing - user fixed new_chan=%d\n",
+ pmadapter->dfs_test_params.fixed_new_channel_on_radar);
+ *chan = pmadapter->dfs_test_params.fixed_new_channel_on_radar;
+
+ LEAVE();
+ return MLAN_STATUS_SUCCESS;
+ }
+
+ /*get the channel table first*/
+ for (i = 0; i < MAX_REGION_CHANNEL_NUM; i++) {
+ if (pmadapter->region_channel[i].band == BAND_A &&
+ pmadapter->region_channel[i].valid) {
+ chn_tbl = &pmadapter->region_channel[i];
+ break;
+ }
+ }
+
+ if (!chn_tbl || !chn_tbl->pcfp)
+ goto done;
+
+ do {
+ rand_entry =
+ wlan_11h_get_random_num(pmadapter) % chn_tbl->num_cfp;
+ def_chan = (t_u8)chn_tbl->pcfp[rand_entry].channel;
+ rand_tries++;
+ } while ((wlan_11h_is_channel_under_nop(pmadapter, def_chan) ||
+ chn_tbl->pcfp[rand_entry].passive_scan_or_radar_detect ==
+ MTRUE) &&
+ (rand_tries < MAX_SWITCH_CHANNEL_RETRIES));
+
+ /* meet max retries, use the lowest non-dfs channel */
+ if (rand_tries == MAX_SWITCH_CHANNEL_RETRIES) {
+ for (i = 0; i < chn_tbl->num_cfp; i++) {
+ if (chn_tbl->pcfp[i].passive_scan_or_radar_detect ==
+ MFALSE &&
+ !wlan_11h_is_channel_under_nop(
+ pmadapter,
+ (t_u8)chn_tbl->pcfp[i].channel)) {
+ def_chan = (t_u8)chn_tbl->pcfp[i].channel;
+ break;
+ }
+ }
+ if (i == chn_tbl->num_cfp)
+ goto done;
+ }
+
+ *chan = def_chan;
+ ret = MLAN_STATUS_SUCCESS;
+done:
+ LEAVE();
+ return ret;
+}
+
+/**
+ * @brief set dfs check channel
+ *
+ * @param priv Void pointer to mlan_private
+ *
+ * @param chan pointer to channel
+ *
+ * @return N/A
+ */
+void wlan_11h_set_dfs_check_chan(mlan_private *priv, t_u8 chan)
+{
+ wlan_dfs_device_state_t *pstate_dfs = &priv->adapter->state_dfs;
+ ENTER();
+ pstate_dfs->dfs_check_channel = chan;
+ PRINTM(MCMND, "Set dfs_check_channel=%d\n", chan);
+ LEAVE();
+}
+
+/**
+ * @brief 802.11h DFS W53 configuration
+ *
+ * @param pmadapter Pointer to mlan_adapter
+ * @param pioctl_req Pointer to mlan_ioctl_req
+ *
+ * @return MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ */
+mlan_status wlan_11h_ioctl_dfs_w53_cfg(pmlan_adapter pmadapter,
+ pmlan_ioctl_req pioctl_req)
+{
+ mlan_ds_11h_cfg *ds_11hcfg = MNULL;
+ mlan_ds_11h_dfs_w53_cfg *dfs_w53_cfg = MNULL;
+
+ ENTER();
+
+ ds_11hcfg = (mlan_ds_11h_cfg *)pioctl_req->pbuf;
+ dfs_w53_cfg = &ds_11hcfg->param.dfs_w53_cfg;
+
+ if (pioctl_req->action == MLAN_ACT_GET) {
+ dfs_w53_cfg->dfs53cfg = pmadapter->dfs53cfg;
+ } else {
+ pmadapter->dfs53cfg = dfs_w53_cfg->dfs53cfg;
+ }
+
+ LEAVE();
+
+ return MLAN_STATUS_SUCCESS;
+}
diff --git a/drivers/net/wireless/nxp/mxm_wifiex/wlan_src/mlan/mlan_11h.h b/drivers/net/wireless/nxp/mxm_wifiex/wlan_src/mlan/mlan_11h.h
new file mode 100644
index 000000000000..05766a99bb35
--- /dev/null
+++ b/drivers/net/wireless/nxp/mxm_wifiex/wlan_src/mlan/mlan_11h.h
@@ -0,0 +1,201 @@
+/** @file mlan_11h.h
+ *
+ * @brief This header file contains data structures and
+ * function declarations of 802.11h
+ *
+ *
+ * Copyright 2014-2020 NXP
+ *
+ * This software file (the File) is distributed by NXP
+ * under the terms of the GNU General Public License Version 2, June 1991
+ * (the License). You may use, redistribute and/or modify the 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.
+ *
+ */
+
+/*************************************************************
+Change Log:
+ 03/26/2009: initial creation
+*************************************************************/
+
+#ifndef _MLAN_11H_
+#define _MLAN_11H_
+
+/** 11H OID bitmasks */
+#define ENABLE_11H_MASK MBIT(0)
+#define MASTER_RADAR_DET_MASK MBIT(1)
+#define SLAVE_RADAR_DET_MASK MBIT(2)
+
+/** DFS Master Radar Detect global enable */
+#define DFS_MASTER_RADAR_DETECT_EN (MTRUE)
+/** DFS Slave Radar Detect global enable */
+#define DFS_SLAVE_RADAR_DETECT_EN (MFALSE)
+
+#define CHANNEL_OFFSET_MASK 0x30
+#define CHANNEL_BANDWIDTH_MASK 0x0C
+
+/**
+ * 11H APIs
+ */
+
+/* Is master radar detection enabled in firmware? */
+extern t_bool wlan_11h_is_master_radar_det_active(mlan_private *priv);
+
+/** Configure master radar detection.
+ * Need call wlan_11h_check_update_radar_det_state() after.
+ */
+extern mlan_status wlan_11h_config_master_radar_det(mlan_private *priv,
+ t_bool enable);
+
+/** Configure slave radar detection.
+ * Need call wlan_11h_check_update_radar_det_state() after.
+ */
+extern mlan_status wlan_11h_config_slave_radar_det(mlan_private *priv,
+ t_bool enable);
+
+/** Checks all interfaces and updates radar detect flags if necessary */
+extern mlan_status wlan_11h_check_update_radar_det_state(mlan_private *pmpriv);
+
+/** Return 1 if 11h is active in the firmware, 0 if it is inactive */
+extern t_bool wlan_11h_is_active(mlan_private *priv);
+
+/** Enable the tx interface and record the new transmit state */
+extern void wlan_11h_tx_enable(mlan_private *priv);
+
+/** Disable the tx interface and record the new transmit state */
+extern void wlan_11h_tx_disable(mlan_private *priv);
+
+/** Activate 11h extensions in the firmware */
+extern mlan_status wlan_11h_activate(mlan_private *priv, t_void *pioctl_buf,
+ t_bool flag);
+
+/** Initialize the 11h device structure */
+extern void wlan_11h_init(mlan_adapter *pmadapter);
+
+/** Cleanup for the 11h device structure */
+extern void wlan_11h_cleanup(mlan_adapter *pmadapter);
+
+/** Initialize the 11h interface structure */
+extern void wlan_11h_priv_init(mlan_private *pmpriv);
+
+/** Get an initial random channel to start an adhoc network on */
+extern t_u8 wlan_11h_get_adhoc_start_channel(mlan_private *priv);
+
+/** Get channel that has been closed via Channel Switch Announcement */
+extern t_u8 wlan_11h_get_csa_closed_channel(mlan_private *priv);
+
+/** Check if radar detection is required on the specified channel */
+extern t_bool wlan_11h_radar_detect_required(mlan_private *priv, t_u8 channel);
+
+/** Perform a standard availibility check on the specified channel */
+extern t_s32 wlan_11h_issue_radar_detect(mlan_private *priv,
+ pmlan_ioctl_req pioctl_req,
+ t_u8 channel, Band_Config_t bandcfg);
+
+/** Check previously issued radar report for a channel */
+extern mlan_status wlan_11h_check_chan_report(mlan_private *priv, t_u8 chan);
+
+/** Add any 11h TLVs necessary to complete an adhoc start command */
+extern t_s32 wlan_11h_process_start(mlan_private *priv, t_u8 **ppbuffer,
+ IEEEtypes_CapInfo_t *pcap_info,
+ t_u32 channel,
+ wlan_11h_bss_info_t *p11h_bss_info);
+
+/** Add any 11h TLVs necessary to complete a join command (adhoc or infra) */
+extern t_s32 wlan_11h_process_join(mlan_private *priv, t_u8 **ppbuffer,
+ IEEEtypes_CapInfo_t *pcap_info, t_u8 band,
+ t_u32 channel,
+ wlan_11h_bss_info_t *p11h_bss_info);
+
+/** Complete the firmware command preparation for an 11h command function */
+extern mlan_status wlan_11h_cmd_process(mlan_private *priv,
+ HostCmd_DS_COMMAND *pcmd_ptr,
+ const t_void *pinfo_buf);
+
+/** Process the response of an 11h firmware command */
+extern mlan_status wlan_11h_cmdresp_process(mlan_private *priv,
+ const HostCmd_DS_COMMAND *resp);
+
+/** Receive IEs from scan processing and record any needed info for 11h */
+extern mlan_status wlan_11h_process_bss_elem(mlan_adapter *pmadapter,
+ wlan_11h_bss_info_t *p11h_bss_info,
+ const t_u8 *pelement);
+
+/** Handler for EVENT_CHANNEL_SWITCH_ANN */
+extern mlan_status wlan_11h_handle_event_chanswann(mlan_private *priv);
+
+/** Handler for EVENT_CHANNEL_REPORT_RDY */
+extern mlan_status wlan_11h_handle_event_chanrpt_ready(mlan_private *priv,
+ mlan_event *pevent,
+ t_u8 *radar_chan);
+
+/** Debug output for EVENT_RADAR_DETECTED */
+mlan_status wlan_11h_print_event_radar_detected(mlan_private *priv,
+ mlan_event *pevent,
+ t_u8 *radar_chan);
+
+t_s32 wlan_11h_cancel_radar_detect(mlan_private *priv);
+/** Handler for DFS_TESTING IOCTL */
+extern mlan_status wlan_11h_ioctl_dfs_testing(pmlan_adapter pmadapter,
+ pmlan_ioctl_req pioctl_req);
+extern mlan_status
+wlan_11h_ioctl_get_channel_nop_info(pmlan_adapter pmadapter,
+ pmlan_ioctl_req pioctl_req);
+
+extern mlan_status wlan_11h_ioctl_dfs_chan_report(mlan_private *priv,
+ pmlan_ioctl_req pioctl_req);
+extern mlan_status wlan_11h_ioctl_chan_switch_count(pmlan_adapter pmadapter,
+ pmlan_ioctl_req pioctl_req);
+
+/** get/set dfs w53 cfg */
+mlan_status wlan_11h_ioctl_dfs_w53_cfg(pmlan_adapter pmadapter,
+ pmlan_ioctl_req pioctl_req);
+
+/** Check if channel is under a NOP duration (should not be used) */
+extern t_bool wlan_11h_is_channel_under_nop(mlan_adapter *pmadapter,
+ t_u8 channel);
+
+/** Check if RADAR_DETECTED handling is blocking data tx */
+extern t_bool wlan_11h_radar_detected_tx_blocked(mlan_adapter *pmadapter);
+
+/** Callback for RADAR_DETECTED (for UAP cmdresp) */
+extern mlan_status wlan_11h_radar_detected_callback(t_void *priv);
+/** set dfs check channel */
+void wlan_11h_set_dfs_check_chan(mlan_private *priv, t_u8 chan);
+
+#ifdef UAP_SUPPORT
+/** BW_change event Handler for dfs_repeater */
+void wlan_dfs_rep_bw_change(mlan_adapter *pmadapter);
+
+/** disconnect event Handler for dfs_repeater */
+void wlan_dfs_rep_disconnect(mlan_adapter *pmadapter);
+#endif
+
+/** Handler for RADAR_DETECTED */
+extern mlan_status wlan_11h_radar_detected_handling(mlan_adapter *pmadapter,
+ mlan_private *priv);
+
+mlan_status wlan_11h_remove_custom_ie(mlan_adapter *pmadapter,
+ mlan_private *pmpriv);
+
+/** DFS Event pre-processing */
+extern mlan_status wlan_11h_dfs_event_preprocessing(mlan_adapter *pmadapter);
+
+/** DFS switch to non-DFS channel */
+extern mlan_status wlan_11h_switch_non_dfs_chan(mlan_private *priv, t_u8 *chan);
+
+extern void wlan_11h_update_bandcfg(Band_Config_t *uap_band_cfg,
+ t_u8 new_channel);
+
+/** function checks if interface is active. **/
+extern t_bool wlan_is_intf_active(mlan_private *pmpriv);
+
+#endif /*_MLAN_11H_ */
diff --git a/drivers/net/wireless/nxp/mxm_wifiex/wlan_src/mlan/mlan_11n.c b/drivers/net/wireless/nxp/mxm_wifiex/wlan_src/mlan/mlan_11n.c
new file mode 100644
index 000000000000..6be3969ea5ca
--- /dev/null
+++ b/drivers/net/wireless/nxp/mxm_wifiex/wlan_src/mlan/mlan_11n.c
@@ -0,0 +1,3092 @@
+/** @file mlan_11n.c
+ *
+ * @brief This file contains functions for 11n handling.
+ *
+ *
+ * Copyright 2014-2020 NXP
+ *
+ * This software file (the File) is distributed by NXP
+ * under the terms of the GNU General Public License Version 2, June 1991
+ * (the License). You may use, redistribute and/or modify the 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.
+ *
+ */
+
+/********************************************************
+Change log:
+ 11/10/2008: initial version
+********************************************************/
+
+#include "mlan.h"
+#include "mlan_join.h"
+#include "mlan_util.h"
+#include "mlan_fw.h"
+#include "mlan_main.h"
+#include "mlan_wmm.h"
+#include "mlan_11n.h"
+#include "mlan_11ac.h"
+
+/********************************************************
+ Local Variables
+********************************************************/
+
+/********************************************************
+ Global Variables
+********************************************************/
+
+/********************************************************
+ Local Functions
+********************************************************/
+
+/**
+ *
+ * @brief set/get max tx buf size
+ *
+ * @param pmadapter A pointer to mlan_adapter structure
+ * @param pioctl_req A pointer to ioctl request buffer
+ *
+ * @return MLAN_STATUS_SUCCESS --success, otherwise
+ * fail
+ */
+static mlan_status wlan_11n_ioctl_max_tx_buf_size(pmlan_adapter pmadapter,
+ pmlan_ioctl_req pioctl_req)
+{
+ mlan_status ret = MLAN_STATUS_SUCCESS;
+ mlan_ds_11n_cfg *cfg = MNULL;
+
+ ENTER();
+ cfg = (mlan_ds_11n_cfg *)pioctl_req->pbuf;
+ cfg->param.tx_buf_size = (t_u32)pmadapter->max_tx_buf_size;
+ pioctl_req->data_read_written = sizeof(t_u32) + MLAN_SUB_COMMAND_SIZE;
+
+ LEAVE();
+ return ret;
+}
+
+/**
+ * @brief Set/get htcapinfo configuration
+ *
+ * @param pmadapter A pointer to mlan_adapter structure
+ * @param pioctl_req A pointer to ioctl request buffer
+ *
+ * @return MLAN_STATUS_SUCCESS --success, otherwise
+ * fail
+ */
+static mlan_status wlan_11n_ioctl_htusrcfg(pmlan_adapter pmadapter,
+ pmlan_ioctl_req pioctl_req)
+{
+ mlan_status ret = MLAN_STATUS_SUCCESS;
+ mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index];
+ mlan_ds_11n_cfg *cfg = MNULL;
+
+ ENTER();
+
+ cfg = (mlan_ds_11n_cfg *)pioctl_req->pbuf;
+
+ if (pioctl_req->action == MLAN_ACT_SET) {
+ if (((cfg->param.htcap_cfg.htcap & ~IGN_HW_DEV_CAP) &
+ pmpriv->adapter->hw_dot_11n_dev_cap) !=
+ (cfg->param.htcap_cfg.htcap & ~IGN_HW_DEV_CAP)) {
+ pioctl_req->status_code = MLAN_ERROR_INVALID_PARAMETER;
+ ret = MLAN_STATUS_FAILURE;
+ } else {
+ if (cfg->param.htcap_cfg.misc_cfg == BAND_SELECT_BG) {
+ pmpriv->usr_dot_11n_dev_cap_bg =
+ cfg->param.htcap_cfg.htcap;
+ PRINTM(MINFO,
+ "Set: UsrDot11nCap for 2.4GHz 0x%x\n",
+ pmpriv->usr_dot_11n_dev_cap_bg);
+ }
+ if (cfg->param.htcap_cfg.misc_cfg == BAND_SELECT_A) {
+ pmpriv->usr_dot_11n_dev_cap_a =
+ cfg->param.htcap_cfg.htcap;
+ PRINTM(MINFO,
+ "Set: UsrDot11nCap for 5GHz 0x%x\n",
+ pmpriv->usr_dot_11n_dev_cap_a);
+ }
+ if (cfg->param.htcap_cfg.misc_cfg == BAND_SELECT_BOTH) {
+ pmpriv->usr_dot_11n_dev_cap_bg =
+ cfg->param.htcap_cfg.htcap;
+ pmpriv->usr_dot_11n_dev_cap_a =
+ cfg->param.htcap_cfg.htcap;
+ PRINTM(MINFO,
+ "Set: UsrDot11nCap for 2.4GHz and 5GHz 0x%x\n",
+ cfg->param.htcap_cfg.htcap);
+ }
+ }
+ } else {
+ /* Hardware 11N device capability required */
+ if (cfg->param.htcap_cfg.hw_cap_req)
+ cfg->param.htcap_cfg.htcap =
+ pmadapter->hw_dot_11n_dev_cap;
+ else {
+ if (cfg->param.htcap_cfg.misc_cfg == BAND_SELECT_BG) {
+ cfg->param.htcap_cfg.htcap =
+ pmpriv->usr_dot_11n_dev_cap_bg;
+ PRINTM(MINFO,
+ "Get: UsrDot11nCap for 2.4GHz 0x%x\n",
+ cfg->param.htcap_cfg.htcap);
+ }
+ if (cfg->param.htcap_cfg.misc_cfg == BAND_SELECT_A) {
+ cfg->param.htcap_cfg.htcap =
+ pmpriv->usr_dot_11n_dev_cap_a;
+ PRINTM(MINFO,
+ "Get: UsrDot11nCap for 5GHz 0x%x\n",
+ cfg->param.htcap_cfg.htcap);
+ }
+ }
+ }
+
+ LEAVE();
+ return ret;
+}
+
+/**
+ * @brief Enable/Disable AMSDU AGGR CTRL
+ *
+ * @param pmadapter A pointer to mlan_adapter structure
+ * @param pioctl_req A pointer to ioctl request buffer
+ *
+ * @return MLAN_STATUS_PENDING --success, otherwise fail
+ */
+static mlan_status wlan_11n_ioctl_amsdu_aggr_ctrl(pmlan_adapter pmadapter,
+ pmlan_ioctl_req pioctl_req)
+{
+ mlan_status ret = MLAN_STATUS_SUCCESS;
+ mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index];
+ mlan_ds_11n_cfg *cfg = MNULL;
+ t_u16 cmd_action = 0;
+
+ ENTER();
+
+ cfg = (mlan_ds_11n_cfg *)pioctl_req->pbuf;
+ if (pioctl_req->action == MLAN_ACT_SET)
+ cmd_action = HostCmd_ACT_GEN_SET;
+ else
+ cmd_action = HostCmd_ACT_GEN_GET;
+
+ /* Send request to firmware */
+ ret = wlan_prepare_cmd(pmpriv, HostCmd_CMD_AMSDU_AGGR_CTRL, cmd_action,
+ 0, (t_void *)pioctl_req,
+ (t_void *)&cfg->param.amsdu_aggr_ctrl);
+ if (ret == MLAN_STATUS_SUCCESS)
+ ret = MLAN_STATUS_PENDING;
+
+ LEAVE();
+ return ret;
+}
+
+/**
+ * @brief Set/get 11n configuration
+ *
+ * @param pmadapter A pointer to mlan_adapter structure
+ * @param pioctl_req A pointer to ioctl request buffer
+ *
+ * @return MLAN_STATUS_PENDING --success, otherwise fail
+ */
+static mlan_status wlan_11n_ioctl_httxcfg(pmlan_adapter pmadapter,
+ pmlan_ioctl_req pioctl_req)
+{
+ mlan_status ret = MLAN_STATUS_SUCCESS;
+ mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index];
+ mlan_ds_11n_cfg *cfg = MNULL;
+ t_u16 cmd_action = 0;
+
+ ENTER();
+
+ cfg = (mlan_ds_11n_cfg *)pioctl_req->pbuf;
+ if (pioctl_req->action == MLAN_ACT_SET)
+ cmd_action = HostCmd_ACT_GEN_SET;
+ else
+ cmd_action = HostCmd_ACT_GEN_GET;
+
+ /* Send request to firmware */
+ ret = wlan_prepare_cmd(pmpriv, HostCmd_CMD_11N_CFG, cmd_action, 0,
+ (t_void *)pioctl_req,
+ (t_void *)&cfg->param.tx_cfg);
+ if (ret == MLAN_STATUS_SUCCESS)
+ ret = MLAN_STATUS_PENDING;
+
+ LEAVE();
+ return ret;
+}
+
+/**
+ * @brief Set/get TX beamforming capabilities
+ *
+ * @param pmadapter A pointer to mlan_adapter structure
+ * @param pioctl_req A pointer to ioctl request buffer
+ *
+ * @return MLAN_STATUS_SUCCESS --success
+ */
+static mlan_status wlan_11n_ioctl_tx_bf_cap(pmlan_adapter pmadapter,
+ pmlan_ioctl_req pioctl_req)
+{
+ mlan_status ret = MLAN_STATUS_SUCCESS;
+ mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index];
+ mlan_ds_11n_cfg *cfg = MNULL;
+
+ ENTER();
+
+ cfg = (mlan_ds_11n_cfg *)pioctl_req->pbuf;
+ if (pioctl_req->action == MLAN_ACT_SET)
+ pmpriv->tx_bf_cap = cfg->param.tx_bf_cap;
+ else
+ cfg->param.tx_bf_cap = pmpriv->tx_bf_cap;
+
+ LEAVE();
+ return ret;
+}
+
+/**
+ * @brief Set/get TX beamforming configurations
+ *
+ * @param pmadapter A pointer to mlan_adapter structure
+ * @param pioctl_req A pointer to ioctl request buffer
+ *
+ * @return MLAN_STATUS_PENDING --success, otherwise fail
+ */
+static mlan_status wlan_11n_ioctl_tx_bf_cfg(pmlan_adapter pmadapter,
+ pmlan_ioctl_req pioctl_req)
+{
+ mlan_status ret = MLAN_STATUS_SUCCESS;
+ mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index];
+ mlan_ds_11n_cfg *cfg = MNULL;
+ t_u16 cmd_action = 0;
+
+ ENTER();
+
+ cfg = (mlan_ds_11n_cfg *)pioctl_req->pbuf;
+ if (pioctl_req->action == MLAN_ACT_SET)
+ cmd_action = HostCmd_ACT_GEN_SET;
+ else
+ cmd_action = HostCmd_ACT_GEN_GET;
+
+ /* Send request to firmware */
+ ret = wlan_prepare_cmd(pmpriv, HostCmd_CMD_TX_BF_CFG, cmd_action, 0,
+ (t_void *)pioctl_req,
+ (t_void *)&cfg->param.tx_bf);
+ if (ret == MLAN_STATUS_SUCCESS)
+ ret = MLAN_STATUS_PENDING;
+
+ LEAVE();
+ return ret;
+}
+
+/**
+ * @brief Set/get HT stream configurations
+ *
+ * @param pmadapter A pointer to mlan_adapter structure
+ * @param pioctl_req A pointer to ioctl request buffer
+ *
+ * @return MLAN_STATUS_SUCCESS --success, otherwise fail
+ */
+static mlan_status wlan_11n_ioctl_stream_cfg(pmlan_adapter pmadapter,
+ pmlan_ioctl_req pioctl_req)
+{
+ mlan_status ret = MLAN_STATUS_SUCCESS;
+ mlan_ds_11n_cfg *cfg = MNULL;
+ mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index];
+
+ ENTER();
+
+ cfg = (mlan_ds_11n_cfg *)pioctl_req->pbuf;
+ if (pioctl_req->action == MLAN_ACT_GET) {
+ cfg->param.stream_cfg = pmpriv->usr_dev_mcs_support;
+ } else if (pioctl_req->action == MLAN_ACT_SET) {
+ switch (cfg->param.stream_cfg) {
+ case HT_STREAM_MODE_2X2:
+ if (pmadapter->hw_dev_mcs_support ==
+ HT_STREAM_MODE_1X1) {
+ PRINTM(MERROR,
+ "HW does not support this mode\n");
+ ret = MLAN_STATUS_FAILURE;
+ } else
+ pmpriv->usr_dev_mcs_support =
+ cfg->param.stream_cfg;
+ break;
+ case HT_STREAM_MODE_1X1:
+ pmpriv->usr_dev_mcs_support = cfg->param.stream_cfg;
+ break;
+ default:
+ PRINTM(MERROR, "Invalid stream mode\n");
+ pioctl_req->status_code = MLAN_ERROR_INVALID_PARAMETER;
+ ret = MLAN_STATUS_FAILURE;
+ break;
+ }
+ }
+
+ LEAVE();
+ return ret;
+}
+
+/**
+ * @brief Set/get control to coex RX window size configuration
+ *
+ * @param pmadapter A pointer to mlan_adapter structure
+ * @param pioctl_req A pointer to ioctl request buffer
+ *
+ * @return MLAN_STATUS_SUCCESS --success, otherwise fail
+ */
+static mlan_status wlan_11n_ioctl_coex_rx_winsize(pmlan_adapter pmadapter,
+ pmlan_ioctl_req pioctl_req)
+{
+ mlan_status ret = MLAN_STATUS_SUCCESS;
+ mlan_ds_11n_cfg *cfg = MNULL;
+
+ ENTER();
+
+ cfg = (mlan_ds_11n_cfg *)pioctl_req->pbuf;
+ if (pioctl_req->action == MLAN_ACT_GET)
+ cfg->param.coex_rx_winsize = pmadapter->coex_rx_winsize;
+ else if (pioctl_req->action == MLAN_ACT_SET)
+ pmadapter->coex_rx_winsize = (t_u8)cfg->param.coex_rx_winsize;
+
+ LEAVE();
+ return ret;
+}
+
+/**
+ * @brief This function will resend addba request to all
+ * the peer in the TxBAStreamTbl
+ *
+ * @param priv A pointer to mlan_private
+ *
+ * @return N/A
+ */
+static void wlan_11n_update_addba_request(mlan_private *priv)
+{
+ TxBAStreamTbl *ptx_tbl;
+
+ ENTER();
+
+ wlan_request_ralist_lock(priv);
+ ptx_tbl = (TxBAStreamTbl *)util_peek_list(priv->adapter->pmoal_handle,
+ &priv->tx_ba_stream_tbl_ptr,
+ MNULL, MNULL);
+ if (!ptx_tbl) {
+ wlan_release_ralist_lock(priv);
+ LEAVE();
+ return;
+ }
+
+ while (ptx_tbl != (TxBAStreamTbl *)&priv->tx_ba_stream_tbl_ptr) {
+ wlan_send_addba(priv, ptx_tbl->tid, ptx_tbl->ra);
+ ptx_tbl = ptx_tbl->pnext;
+ }
+ wlan_release_ralist_lock(priv);
+ /* Signal MOAL to trigger mlan_main_process */
+ wlan_recv_event(priv, MLAN_EVENT_ID_DRV_DEFER_HANDLING, MNULL);
+ LEAVE();
+ return;
+}
+
+/**
+ * @brief Set/get addba parameter
+ *
+ * @param pmadapter A pointer to mlan_adapter structure
+ * @param pioctl_req A pointer to ioctl request buffer
+ *
+ * @return MLAN_STATUS_SUCCESS --success
+ */
+static mlan_status wlan_11n_ioctl_addba_param(pmlan_adapter pmadapter,
+ pmlan_ioctl_req pioctl_req)
+{
+ mlan_status ret = MLAN_STATUS_SUCCESS;
+ mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index];
+ mlan_ds_11n_cfg *cfg = MNULL;
+ t_u32 timeout;
+
+ ENTER();
+
+ cfg = (mlan_ds_11n_cfg *)pioctl_req->pbuf;
+ if (pioctl_req->action == MLAN_ACT_GET) {
+ cfg->param.addba_param.timeout = pmpriv->add_ba_param.timeout;
+ cfg->param.addba_param.txwinsize =
+ pmpriv->add_ba_param.tx_win_size;
+ cfg->param.addba_param.rxwinsize =
+ pmpriv->add_ba_param.rx_win_size;
+ cfg->param.addba_param.txamsdu = pmpriv->add_ba_param.tx_amsdu;
+ cfg->param.addba_param.rxamsdu = pmpriv->add_ba_param.rx_amsdu;
+ } else {
+ timeout = pmpriv->add_ba_param.timeout;
+ pmpriv->add_ba_param.timeout = cfg->param.addba_param.timeout;
+ pmpriv->add_ba_param.tx_win_size =
+ cfg->param.addba_param.txwinsize;
+
+ pmpriv->add_ba_param.rx_win_size =
+ cfg->param.addba_param.rxwinsize;
+ pmpriv->user_rxwinsize = pmpriv->add_ba_param.rx_win_size;
+ pmpriv->add_ba_param.tx_amsdu = cfg->param.addba_param.txamsdu;
+ pmpriv->add_ba_param.rx_amsdu = cfg->param.addba_param.rxamsdu;
+ if (timeout != pmpriv->add_ba_param.timeout)
+ wlan_11n_update_addba_request(pmpriv);
+ }
+
+ LEAVE();
+ return ret;
+}
+
+/**
+ * @brief This function send delba to specific tid
+ *
+ * @param priv A pointer to mlan_priv
+ * @param tid tid
+ * @return N/A
+ */
+void wlan_11n_delba(mlan_private *priv, int tid)
+{
+ RxReorderTbl *rx_reor_tbl_ptr;
+
+ ENTER();
+
+ rx_reor_tbl_ptr = (RxReorderTbl *)util_peek_list(
+ priv->adapter->pmoal_handle, &priv->rx_reorder_tbl_ptr,
+ priv->adapter->callbacks.moal_spin_lock,
+ priv->adapter->callbacks.moal_spin_unlock);
+ if (!rx_reor_tbl_ptr) {
+ LEAVE();
+ return;
+ }
+
+ while (rx_reor_tbl_ptr != (RxReorderTbl *)&priv->rx_reorder_tbl_ptr) {
+ if (rx_reor_tbl_ptr->tid == tid) {
+ PRINTM(MIOCTL, "Send delba to tid=%d, " MACSTR "\n",
+ tid, MAC2STR(rx_reor_tbl_ptr->ta));
+ wlan_send_delba(priv, MNULL, tid, rx_reor_tbl_ptr->ta,
+ 0);
+ LEAVE();
+ return;
+ }
+ rx_reor_tbl_ptr = rx_reor_tbl_ptr->pnext;
+ }
+
+ LEAVE();
+ return;
+}
+
+/**
+ * @brief Set/get addba reject set
+ *
+ * @param pmadapter A pointer to mlan_adapter structure
+ * @param pioctl_req A pointer to ioctl request buffer
+ *
+ * @return MLAN_STATUS_SUCCESS --success, otherwise fail
+ */
+static mlan_status wlan_11n_ioctl_addba_reject(pmlan_adapter pmadapter,
+ pmlan_ioctl_req pioctl_req)
+{
+ int i = 0;
+ mlan_status ret = MLAN_STATUS_SUCCESS;
+ mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index];
+ mlan_ds_11n_cfg *cfg = MNULL;
+
+ ENTER();
+
+ cfg = (mlan_ds_11n_cfg *)pioctl_req->pbuf;
+
+ if (pioctl_req->action == MLAN_ACT_GET) {
+ PRINTM(MINFO, "Get Addba reject\n");
+ memcpy_ext(pmadapter, cfg->param.addba_reject,
+ pmpriv->addba_reject, MAX_NUM_TID, MAX_NUM_TID);
+ } else {
+ for (i = 0; i < MAX_NUM_TID; i++) {
+ /* For AMPDU */
+ if (cfg->param.addba_reject[i] >
+ ADDBA_RSP_STATUS_REJECT) {
+ pioctl_req->status_code =
+ MLAN_ERROR_INVALID_PARAMETER;
+ ret = MLAN_STATUS_FAILURE;
+ break;
+ }
+
+ pmpriv->addba_reject[i] = cfg->param.addba_reject[i];
+ }
+ if (pmpriv->media_connected == MTRUE) {
+ for (i = 0; i < MAX_NUM_TID; i++) {
+ if (cfg->param.addba_reject[i] ==
+ ADDBA_RSP_STATUS_REJECT) {
+ PRINTM(MIOCTL,
+ "Receive addba reject: tid=%d\n",
+ i);
+ wlan_11n_delba(pmpriv, i);
+ }
+ }
+ wlan_recv_event(pmpriv,
+ MLAN_EVENT_ID_DRV_DEFER_HANDLING,
+ MNULL);
+ }
+ }
+
+ LEAVE();
+ return ret;
+}
+
+/**
+ * @brief Set/get ibss ampdu param
+ *
+ * @param pmadapter A pointer to mlan_adapter structure
+ * @param pioctl_req A pointer to ioctl request buffer
+ *
+ * @return MLAN_STATUS_SUCCESS --success, otherwise fail
+ */
+static mlan_status wlan_11n_ioctl_ibss_ampdu_param(pmlan_adapter pmadapter,
+ pmlan_ioctl_req pioctl_req)
+{
+ int i = 0;
+ mlan_status ret = MLAN_STATUS_SUCCESS;
+ mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index];
+ mlan_ds_11n_cfg *cfg = MNULL;
+
+ ENTER();
+
+ cfg = (mlan_ds_11n_cfg *)pioctl_req->pbuf;
+
+ if (pioctl_req->action == MLAN_ACT_GET) {
+ PRINTM(MINFO, "Get IBSS AMPDU param\n");
+ for (i = 0; i < MAX_NUM_TID; i++) {
+ cfg->param.ibss_ampdu.ampdu[i] = pmpriv->ibss_ampdu[i];
+ cfg->param.ibss_ampdu.addba_reject[i] =
+ pmpriv->ibss_addba_reject[i];
+ }
+ } else {
+ for (i = 0; i < MAX_NUM_TID; i++) {
+ /* For AMPDU RX*/
+ if (cfg->param.ibss_ampdu.addba_reject[i] >
+ ADDBA_RSP_STATUS_REJECT) {
+ pioctl_req->status_code =
+ MLAN_ERROR_INVALID_PARAMETER;
+ ret = MLAN_STATUS_FAILURE;
+ break;
+ }
+ pmpriv->ibss_addba_reject[i] =
+ cfg->param.ibss_ampdu.addba_reject[i];
+ /* For AMPDU TX*/
+ if ((cfg->param.ibss_ampdu.ampdu[i] > HIGH_PRIO_TID) &&
+ (cfg->param.ibss_ampdu.ampdu[i] !=
+ BA_STREAM_NOT_ALLOWED)) {
+ pioctl_req->status_code =
+ MLAN_ERROR_INVALID_PARAMETER;
+ ret = MLAN_STATUS_FAILURE;
+ break;
+ }
+ pmpriv->ibss_ampdu[i] = cfg->param.ibss_ampdu.ampdu[i];
+ }
+ PRINTM(MMSG, "IBSS addba reject: %d %d %d %d %d %d %d %d\n",
+ pmpriv->ibss_addba_reject[0],
+ pmpriv->ibss_addba_reject[1],
+ pmpriv->ibss_addba_reject[2],
+ pmpriv->ibss_addba_reject[3],
+ pmpriv->ibss_addba_reject[4],
+ pmpriv->ibss_addba_reject[5],
+ pmpriv->ibss_addba_reject[6],
+ pmpriv->ibss_addba_reject[7]);
+ PRINTM(MMSG, "IBSS ampdu %d %d %d %d %d %d %d %d\n",
+ pmpriv->ibss_ampdu[0], pmpriv->ibss_ampdu[1],
+ pmpriv->ibss_ampdu[2], pmpriv->ibss_ampdu[3],
+ pmpriv->ibss_ampdu[4], pmpriv->ibss_ampdu[5],
+ pmpriv->ibss_ampdu[6], pmpriv->ibss_ampdu[7]);
+ }
+ LEAVE();
+ return ret;
+}
+
+/**
+ * @brief Set/Get Minimum BA Threshold
+ *
+ * @param pmadapter A pointer to mlan_adapter structure
+ * @param pioctl_req A pointer to ioctl request buffer
+ *
+ * @return MLAN_STATUS_SUCCESS --success
+ */
+static mlan_status
+wlan_11n_ioctl_min_ba_threshold_cfg(pmlan_adapter pmadapter,
+ pmlan_ioctl_req pioctl_req)
+{
+ mlan_status ret = MLAN_STATUS_SUCCESS;
+ mlan_ds_11n_cfg *cfg = MNULL;
+ ENTER();
+ cfg = (mlan_ds_11n_cfg *)pioctl_req->pbuf;
+ if (pioctl_req->action == MLAN_ACT_GET)
+ cfg->param.min_ba_threshold = pmadapter->min_ba_threshold;
+ else
+ pmadapter->min_ba_threshold = cfg->param.min_ba_threshold;
+ pioctl_req->data_read_written = sizeof(t_u8) + MLAN_SUB_COMMAND_SIZE;
+ LEAVE();
+ return ret;
+}
+
+/**
+ * @brief This function will send DELBA to entries in the priv's
+ * Tx BA stream table
+ *
+ * @param priv A pointer to mlan_private
+ * @param pioctl_req A pointer to ioctl request buffer
+ * @param tid TID
+ * @param peer_address A pointer to peer address
+ * @param last_tx_ba_to_delete A pointer to the last entry in TxBAStreamTbl
+ *
+ * @return MLAN_STATUS_SUCCESS or MLAN_STATUS_PENDING
+ */
+static mlan_status wlan_send_delba_to_entry_in_txbastream_tbl(
+ pmlan_private priv, pmlan_ioctl_req pioctl_req, t_u8 tid,
+ t_u8 *peer_address, TxBAStreamTbl *last_tx_ba_to_delete)
+{
+ pmlan_adapter pmadapter = priv->adapter;
+ TxBAStreamTbl *tx_ba_stream_tbl_ptr;
+ t_u8 zero_mac[MLAN_MAC_ADDR_LENGTH] = {0};
+ mlan_status ret = MLAN_STATUS_SUCCESS;
+
+ ENTER();
+
+ wlan_request_ralist_lock(priv);
+ tx_ba_stream_tbl_ptr =
+ (TxBAStreamTbl *)util_peek_list(pmadapter->pmoal_handle,
+ &priv->tx_ba_stream_tbl_ptr,
+ MNULL, MNULL);
+ if (!tx_ba_stream_tbl_ptr) {
+ wlan_release_ralist_lock(priv);
+ LEAVE();
+ return ret;
+ }
+
+ while (tx_ba_stream_tbl_ptr !=
+ (TxBAStreamTbl *)&priv->tx_ba_stream_tbl_ptr) {
+ if (tx_ba_stream_tbl_ptr->ba_status ==
+ BA_STREAM_SETUP_COMPLETE) {
+ if (((tid == DELBA_ALL_TIDS) ||
+ (tid == tx_ba_stream_tbl_ptr->tid)) &&
+ (!memcmp(pmadapter, peer_address, zero_mac,
+ MLAN_MAC_ADDR_LENGTH) ||
+ !memcmp(pmadapter, peer_address,
+ tx_ba_stream_tbl_ptr->ra,
+ MLAN_MAC_ADDR_LENGTH))) {
+ if (last_tx_ba_to_delete &&
+ (tx_ba_stream_tbl_ptr ==
+ last_tx_ba_to_delete))
+ ret = wlan_send_delba(
+ priv, pioctl_req,
+ tx_ba_stream_tbl_ptr->tid,
+ tx_ba_stream_tbl_ptr->ra, 1);
+ else
+ ret = wlan_send_delba(
+ priv, MNULL,
+ tx_ba_stream_tbl_ptr->tid,
+ tx_ba_stream_tbl_ptr->ra, 1);
+ }
+ }
+ tx_ba_stream_tbl_ptr = tx_ba_stream_tbl_ptr->pnext;
+ }
+ wlan_release_ralist_lock(priv);
+
+ LEAVE();
+ return ret;
+}
+
+/**
+ * @brief This function will send DELBA to entries in the priv's
+ * rx reordering table
+ *
+ * @param priv A pointer to mlan_private
+ * @param pioctl_req A pointer to ioctl request buffer
+ * @param tid TID
+ * @param peer_address A pointer to peer address
+ * @param last_rx_ba_to_delete A pointer to the last entry in RxReorderTbl
+ *
+ * @return MLAN_STATUS_SUCCESS or MLAN_STATUS_PENDING
+ */
+static mlan_status wlan_send_delba_to_entry_in_reorder_tbl(
+ pmlan_private priv, pmlan_ioctl_req pioctl_req, t_u8 tid,
+ t_u8 *peer_address, RxReorderTbl *last_rx_ba_to_delete)
+{
+ pmlan_adapter pmadapter = priv->adapter;
+ RxReorderTbl *rx_reor_tbl_ptr;
+ t_u8 zero_mac[MLAN_MAC_ADDR_LENGTH] = {0};
+ mlan_status ret = MLAN_STATUS_SUCCESS;
+
+ ENTER();
+
+ rx_reor_tbl_ptr = (RxReorderTbl *)util_peek_list(
+ pmadapter->pmoal_handle, &priv->rx_reorder_tbl_ptr,
+ pmadapter->callbacks.moal_spin_lock,
+ pmadapter->callbacks.moal_spin_unlock);
+ if (!rx_reor_tbl_ptr) {
+ LEAVE();
+ return ret;
+ }
+
+ while (rx_reor_tbl_ptr != (RxReorderTbl *)&priv->rx_reorder_tbl_ptr) {
+ if (rx_reor_tbl_ptr->ba_status == BA_STREAM_SETUP_COMPLETE) {
+ if (((tid == DELBA_ALL_TIDS) ||
+ (tid == rx_reor_tbl_ptr->tid)) &&
+ (!memcmp(pmadapter, peer_address, zero_mac,
+ MLAN_MAC_ADDR_LENGTH) ||
+ !memcmp(pmadapter, peer_address,
+ rx_reor_tbl_ptr->ta,
+ MLAN_MAC_ADDR_LENGTH))) {
+ if (last_rx_ba_to_delete &&
+ (rx_reor_tbl_ptr == last_rx_ba_to_delete))
+ ret = wlan_send_delba(
+ priv, pioctl_req,
+ rx_reor_tbl_ptr->tid,
+ rx_reor_tbl_ptr->ta, 0);
+ else
+ ret = wlan_send_delba(
+ priv, MNULL,
+ rx_reor_tbl_ptr->tid,
+ rx_reor_tbl_ptr->ta, 0);
+ }
+ }
+ rx_reor_tbl_ptr = rx_reor_tbl_ptr->pnext;
+ }
+
+ LEAVE();
+ return ret;
+}
+
+/**
+ * @brief IOCTL to delete BA
+ *
+ * @param pmadapter A pointer to mlan_adapter structure
+ * @param pioctl_req A pointer to ioctl request buffer
+ *
+ * @return MLAN_STATUS_SUCCESS --success, otherwise fail
+ */
+static mlan_status wlan_11n_ioctl_delba(pmlan_adapter pmadapter,
+ pmlan_ioctl_req pioctl_req)
+{
+ mlan_status ret = MLAN_STATUS_SUCCESS;
+ mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index];
+ mlan_ds_11n_cfg *cfg = MNULL;
+ TxBAStreamTbl *tx_ba_stream_tbl_ptr, *last_tx_ba_to_delete = MNULL;
+ RxReorderTbl *rx_reor_tbl_ptr, *last_rx_ba_to_delete = MNULL;
+ t_u8 zero_mac[MLAN_MAC_ADDR_LENGTH] = {0};
+ t_u8 tid, *peer_address;
+
+ ENTER();
+
+ cfg = (mlan_ds_11n_cfg *)pioctl_req->pbuf;
+ tid = cfg->param.del_ba.tid;
+ peer_address = cfg->param.del_ba.peer_mac_addr;
+
+ PRINTM(MINFO, "DelBA: direction %d, TID %d, peer address " MACSTR "\n",
+ cfg->param.del_ba.direction, tid, MAC2STR(peer_address));
+
+ if (cfg->param.del_ba.direction & DELBA_RX) {
+ rx_reor_tbl_ptr = (RxReorderTbl *)util_peek_list(
+ pmadapter->pmoal_handle, &pmpriv->rx_reorder_tbl_ptr,
+ pmadapter->callbacks.moal_spin_lock,
+ pmadapter->callbacks.moal_spin_unlock);
+
+ if (rx_reor_tbl_ptr) {
+ while (rx_reor_tbl_ptr !=
+ (RxReorderTbl *)&pmpriv->rx_reorder_tbl_ptr) {
+ if (rx_reor_tbl_ptr->ba_status ==
+ BA_STREAM_SETUP_COMPLETE) {
+ if (((tid == DELBA_ALL_TIDS) ||
+ (tid == rx_reor_tbl_ptr->tid)) &&
+ (!memcmp(pmadapter, peer_address,
+ zero_mac,
+ MLAN_MAC_ADDR_LENGTH) ||
+ !memcmp(pmadapter, peer_address,
+ rx_reor_tbl_ptr->ta,
+ MLAN_MAC_ADDR_LENGTH))) {
+ /* Found RX BA to delete */
+ last_rx_ba_to_delete =
+ rx_reor_tbl_ptr;
+ }
+ }
+ rx_reor_tbl_ptr = rx_reor_tbl_ptr->pnext;
+ }
+ }
+ }
+
+ if ((last_rx_ba_to_delete == MNULL) &&
+ (cfg->param.del_ba.direction & DELBA_TX)) {
+ wlan_request_ralist_lock(pmpriv);
+ tx_ba_stream_tbl_ptr = (TxBAStreamTbl *)util_peek_list(
+ pmadapter->pmoal_handle, &pmpriv->tx_ba_stream_tbl_ptr,
+ MNULL, MNULL);
+
+ if (tx_ba_stream_tbl_ptr) {
+ while (tx_ba_stream_tbl_ptr !=
+ (TxBAStreamTbl *)&pmpriv->tx_ba_stream_tbl_ptr) {
+ if (tx_ba_stream_tbl_ptr->ba_status ==
+ BA_STREAM_SETUP_COMPLETE) {
+ if (((tid == DELBA_ALL_TIDS) ||
+ (tid ==
+ tx_ba_stream_tbl_ptr->tid)) &&
+ (!memcmp(pmadapter, peer_address,
+ zero_mac,
+ MLAN_MAC_ADDR_LENGTH) ||
+ !memcmp(pmadapter, peer_address,
+ tx_ba_stream_tbl_ptr->ra,
+ MLAN_MAC_ADDR_LENGTH))) {
+ /* Found TX BA to delete */
+ last_tx_ba_to_delete =
+ tx_ba_stream_tbl_ptr;
+ }
+ }
+ tx_ba_stream_tbl_ptr =
+ tx_ba_stream_tbl_ptr->pnext;
+ }
+ }
+ wlan_release_ralist_lock(pmpriv);
+ }
+
+ if (cfg->param.del_ba.direction & DELBA_TX) {
+ if (last_rx_ba_to_delete)
+ ret = wlan_send_delba_to_entry_in_txbastream_tbl(
+ pmpriv, MNULL, tid, peer_address, MNULL);
+ else
+ ret = wlan_send_delba_to_entry_in_txbastream_tbl(
+ pmpriv, pioctl_req, tid, peer_address,
+ last_tx_ba_to_delete);
+ }
+ if (last_rx_ba_to_delete) {
+ ret = wlan_send_delba_to_entry_in_reorder_tbl(
+ pmpriv, pioctl_req, tid, peer_address,
+ last_rx_ba_to_delete);
+ }
+
+ LEAVE();
+ return ret;
+}
+
+/**
+ * @brief IOCTL to reject addba req
+ *
+ * @param pmadapter A pointer to mlan_adapter structure
+ * @param pioctl_req A pointer to ioctl request buffer
+ *
+ * @return MLAN_STATUS_SUCCESS --success, otherwise fail
+ */
+static mlan_status wlan_11n_ioctl_rejectaddbareq(pmlan_adapter pmadapter,
+ pmlan_ioctl_req pioctl_req)
+{
+ mlan_status ret = MLAN_STATUS_SUCCESS;
+ mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index];
+ mlan_ds_11n_cfg *cfg = MNULL;
+ t_u16 cmd_action = 0;
+
+ ENTER();
+
+ cfg = (mlan_ds_11n_cfg *)pioctl_req->pbuf;
+ if (pioctl_req->action == MLAN_ACT_SET)
+ cmd_action = HostCmd_ACT_GEN_SET;
+ else
+ cmd_action = HostCmd_ACT_GEN_GET;
+
+ /* Send command to firmware */
+ ret = wlan_prepare_cmd(pmpriv, HostCmd_CMD_REJECT_ADDBA_REQ, cmd_action,
+ 0, (t_void *)pioctl_req,
+ &cfg->param.reject_addba_req);
+
+ if (ret == MLAN_STATUS_SUCCESS)
+ ret = MLAN_STATUS_PENDING;
+
+ LEAVE();
+ return ret;
+}
+
+/**
+ * @brief This function will send DELBA to entries in the priv's
+ * Tx BA stream table
+ *
+ * @param priv A pointer to mlan_private
+ * @param tid TID
+ *
+ * @return N/A
+ */
+static void wlan_send_delba_txbastream_tbl(pmlan_private priv, t_u8 tid)
+{
+ pmlan_adapter pmadapter = priv->adapter;
+ TxBAStreamTbl *tx_ba_stream_tbl_ptr;
+
+ ENTER();
+
+ wlan_request_ralist_lock(priv);
+ tx_ba_stream_tbl_ptr =
+ (TxBAStreamTbl *)util_peek_list(pmadapter->pmoal_handle,
+ &priv->tx_ba_stream_tbl_ptr,
+ MNULL, MNULL);
+ if (!tx_ba_stream_tbl_ptr) {
+ wlan_release_ralist_lock(priv);
+ LEAVE();
+ return;
+ }
+
+ while (tx_ba_stream_tbl_ptr !=
+ (TxBAStreamTbl *)&priv->tx_ba_stream_tbl_ptr) {
+ if (tx_ba_stream_tbl_ptr->ba_status ==
+ BA_STREAM_SETUP_COMPLETE) {
+ if (tid == tx_ba_stream_tbl_ptr->tid) {
+ PRINTM(MIOCTL,
+ "Tx:Send delba to tid=%d, " MACSTR "\n",
+ tid, MAC2STR(tx_ba_stream_tbl_ptr->ra));
+ wlan_release_ralist_lock(priv);
+ wlan_send_delba(priv, MNULL,
+ tx_ba_stream_tbl_ptr->tid,
+ tx_ba_stream_tbl_ptr->ra, 1);
+ LEAVE();
+ return;
+ }
+ }
+ tx_ba_stream_tbl_ptr = tx_ba_stream_tbl_ptr->pnext;
+ }
+ wlan_release_ralist_lock(priv);
+
+ LEAVE();
+ return;
+}
+
+/**
+ * @brief update station list for the new aggr_prio_tbl setting
+ *
+ * @param priv A pointer to mlan_private structure
+ *
+ *
+ * @return N/A
+ */
+void wlan_update_all_stations_ampdu(mlan_private *priv)
+{
+ sta_node *sta_ptr;
+ mlan_adapter *pmadapter = priv->adapter;
+ int i = 0;
+
+ ENTER();
+ pmadapter->callbacks.moal_spin_lock(pmadapter->pmoal_handle,
+ priv->wmm.ra_list_spinlock);
+ sta_ptr = (sta_node *)util_peek_list(pmadapter->pmoal_handle,
+ &priv->sta_list, MNULL, MNULL);
+ if (!sta_ptr) {
+ pmadapter->callbacks.moal_spin_unlock(
+ pmadapter->pmoal_handle, priv->wmm.ra_list_spinlock);
+ LEAVE();
+ return;
+ }
+ while (sta_ptr != (sta_node *)&priv->sta_list) {
+ for (i = 0; i < MAX_NUM_TID; i++) {
+ if (sta_ptr->is_11n_enabled)
+ sta_ptr->ampdu_sta[i] =
+ priv->aggr_prio_tbl[i].ampdu_user;
+ }
+ sta_ptr = sta_ptr->pnext;
+ }
+ pmadapter->callbacks.moal_spin_unlock(pmadapter->pmoal_handle,
+ priv->wmm.ra_list_spinlock);
+ LEAVE();
+ return;
+}
+
+/**
+ * @brief Set/get aggr_prio_tbl
+ *
+ * @param pmadapter A pointer to mlan_adapter structure
+ * @param pioctl_req A pointer to ioctl request buffer
+ *
+ * @return MLAN_STATUS_SUCCESS --success, otherwise fail
+ */
+static mlan_status wlan_11n_ioctl_aggr_prio_tbl(pmlan_adapter pmadapter,
+ pmlan_ioctl_req pioctl_req)
+{
+ int i = 0;
+ mlan_status ret = MLAN_STATUS_SUCCESS;
+ mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index];
+ mlan_ds_11n_cfg *cfg = MNULL;
+
+ ENTER();
+
+ cfg = (mlan_ds_11n_cfg *)pioctl_req->pbuf;
+
+ if (pioctl_req->action == MLAN_ACT_GET) {
+ for (i = 0; i < MAX_NUM_TID; i++) {
+ cfg->param.aggr_prio_tbl.ampdu[i] =
+ pmpriv->aggr_prio_tbl[i].ampdu_user;
+ cfg->param.aggr_prio_tbl.amsdu[i] =
+ pmpriv->aggr_prio_tbl[i].amsdu;
+ }
+ } else {
+ for (i = 0; i < MAX_NUM_TID; i++) {
+ /* For AMPDU */
+ if ((cfg->param.aggr_prio_tbl.ampdu[i] >
+ HIGH_PRIO_TID) &&
+ (cfg->param.aggr_prio_tbl.ampdu[i] !=
+ BA_STREAM_NOT_ALLOWED)) {
+ pioctl_req->status_code =
+ MLAN_ERROR_INVALID_PARAMETER;
+ ret = MLAN_STATUS_FAILURE;
+ break;
+ }
+
+ pmpriv->aggr_prio_tbl[i].ampdu_ap =
+ pmpriv->aggr_prio_tbl[i].ampdu_user =
+ cfg->param.aggr_prio_tbl.ampdu[i];
+
+ /* For AMSDU */
+ if ((cfg->param.aggr_prio_tbl.amsdu[i] >
+ HIGH_PRIO_TID &&
+ cfg->param.aggr_prio_tbl.amsdu[i] !=
+ BA_STREAM_NOT_ALLOWED)) {
+ pioctl_req->status_code =
+ MLAN_ERROR_INVALID_PARAMETER;
+ ret = MLAN_STATUS_FAILURE;
+ break;
+ } else {
+ pmpriv->aggr_prio_tbl[i].amsdu =
+ cfg->param.aggr_prio_tbl.amsdu[i];
+ }
+ }
+ if (pmpriv->media_connected == MTRUE) {
+ for (i = 0; i < MAX_NUM_TID; i++) {
+ if (cfg->param.aggr_prio_tbl.ampdu[i] ==
+ BA_STREAM_NOT_ALLOWED) {
+ PRINTM(MIOCTL,
+ "Receive aggrpriotbl: BA not allowed tid=%d\n",
+ i);
+ wlan_send_delba_txbastream_tbl(pmpriv,
+ i);
+ }
+ }
+ wlan_update_all_stations_ampdu(pmpriv);
+ wlan_recv_event(pmpriv,
+ MLAN_EVENT_ID_DRV_DEFER_HANDLING,
+ MNULL);
+ }
+ }
+
+ LEAVE();
+ return ret;
+}
+
+/**
+ * @brief This function update all the tx_win_size
+ *
+ * @param pmadapter A pointer to mlan_adapter
+ *
+ *
+ * @return N/A
+ */
+void wlan_update_ampdu_txwinsize(pmlan_adapter pmadapter)
+{
+ t_u8 i;
+ t_u32 tx_win_size = 0;
+ pmlan_private priv = MNULL;
+
+ ENTER();
+
+ for (i = 0; i < pmadapter->priv_num; i++) {
+ if (pmadapter->priv[i]) {
+ priv = pmadapter->priv[i];
+ tx_win_size = priv->add_ba_param.tx_win_size;
+#ifdef STA_SUPPORT
+ if (priv->bss_type == MLAN_BSS_TYPE_STA)
+ priv->add_ba_param.tx_win_size =
+ MLAN_STA_AMPDU_DEF_TXWINSIZE;
+#endif
+#ifdef WIFI_DIRECT_SUPPORT
+ if (priv->bss_type == MLAN_BSS_TYPE_WIFIDIRECT)
+ priv->add_ba_param.tx_win_size =
+ MLAN_WFD_AMPDU_DEF_TXRXWINSIZE;
+#endif
+#ifdef UAP_SUPPORT
+ if (priv->bss_type == MLAN_BSS_TYPE_UAP)
+ priv->add_ba_param.tx_win_size =
+ MLAN_UAP_AMPDU_DEF_TXWINSIZE;
+#endif
+ if (pmadapter->coex_win_size &&
+ pmadapter->coex_tx_win_size)
+ priv->add_ba_param.tx_win_size =
+ pmadapter->coex_tx_win_size;
+
+ if (tx_win_size != priv->add_ba_param.tx_win_size) {
+ if (priv->media_connected == MTRUE) {
+ for (i = 0; i < MAX_NUM_TID; i++)
+ wlan_send_delba_txbastream_tbl(
+ priv, i);
+ wlan_recv_event(
+ priv,
+ MLAN_EVENT_ID_DRV_DEFER_HANDLING,
+ MNULL);
+ }
+ }
+ }
+ }
+ LEAVE();
+ return;
+}
+
+/**
+ * @brief Get supported MCS set
+ *
+ * @param pmadapter A pointer to mlan_adapter structure
+ * @param pioctl_req A pointer to ioctl request buffer
+ *
+ * @return MLAN_STATUS_SUCCESS --success, otherwise fail
+ */
+static mlan_status wlan_11n_ioctl_supported_mcs_set(pmlan_adapter pmadapter,
+ pmlan_ioctl_req pioctl_req)
+{
+ mlan_ds_11n_cfg *cfg = MNULL;
+ int rx_mcs_supp;
+ t_u8 mcs_set[NUM_MCS_FIELD];
+ mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index];
+
+ ENTER();
+
+ if (pioctl_req->action == MLAN_ACT_SET) {
+ PRINTM(MERROR, "Set operation is not supported\n");
+ pioctl_req->status_code = MLAN_ERROR_IOCTL_INVALID;
+ LEAVE();
+ return MLAN_STATUS_FAILURE;
+ }
+ rx_mcs_supp = GET_RXMCSSUPP(pmpriv->usr_dev_mcs_support);
+ /* Set MCS for 1x1/2x2*/
+ memset(pmadapter, (t_u8 *)mcs_set, 0xff, rx_mcs_supp);
+ /* Clear all the other values */
+ memset(pmadapter, (t_u8 *)&mcs_set[rx_mcs_supp], 0,
+ NUM_MCS_FIELD - rx_mcs_supp);
+ /* Set MCS32 with 40MHz support */
+ if ((ISSUPP_CHANWIDTH40(pmpriv->usr_dot_11n_dev_cap_bg) ||
+ ISSUPP_CHANWIDTH40(pmpriv->usr_dot_11n_dev_cap_a)) &&
+ !(pmpriv->curr_chan_flags & CHAN_FLAGS_NO_HT40PLUS &&
+ pmpriv->curr_chan_flags & CHAN_FLAGS_NO_HT40MINUS))
+ SETHT_MCS32(mcs_set);
+
+ cfg = (mlan_ds_11n_cfg *)pioctl_req->pbuf;
+ memcpy_ext(pmadapter, cfg->param.supported_mcs_set, mcs_set,
+ NUM_MCS_FIELD, NUM_MCS_FIELD);
+
+ LEAVE();
+ return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ * @brief This function checks if the given pointer is valid entry of
+ * Tx BA Stream table
+ *
+ * @param priv Pointer to mlan_private
+ * @param ptxtblptr Pointer to tx ba stream entry
+ *
+ * @return MTRUE or MFALSE
+ */
+static int wlan_is_txbastreamptr_valid(mlan_private *priv,
+ TxBAStreamTbl *ptxtblptr)
+{
+ TxBAStreamTbl *ptx_tbl;
+
+ ENTER();
+
+ ptx_tbl = (TxBAStreamTbl *)util_peek_list(priv->adapter->pmoal_handle,
+ &priv->tx_ba_stream_tbl_ptr,
+ MNULL, MNULL);
+ if (!ptx_tbl) {
+ LEAVE();
+ return MFALSE;
+ }
+
+ while (ptx_tbl != (TxBAStreamTbl *)&priv->tx_ba_stream_tbl_ptr) {
+ if (ptx_tbl == ptxtblptr) {
+ LEAVE();
+ return MTRUE;
+ }
+ ptx_tbl = ptx_tbl->pnext;
+ }
+ LEAVE();
+ return MFALSE;
+}
+
+/**
+ * @brief This function will return the pointer to a entry in BA Stream
+ * table which matches the ba_status requested
+ *
+ * @param priv A pointer to mlan_private
+ * @param ba_status Current status of the BA stream
+ *
+ * @return A pointer to first entry matching status in BA stream
+ * NULL if not found
+ */
+static TxBAStreamTbl *wlan_11n_get_txbastream_status(mlan_private *priv,
+ baStatus_e ba_status)
+{
+ TxBAStreamTbl *ptx_tbl;
+
+ ENTER();
+
+ ptx_tbl = (TxBAStreamTbl *)util_peek_list(priv->adapter->pmoal_handle,
+ &priv->tx_ba_stream_tbl_ptr,
+ MNULL, MNULL);
+ if (!ptx_tbl) {
+ LEAVE();
+ return MNULL;
+ }
+
+ while (ptx_tbl != (TxBAStreamTbl *)&priv->tx_ba_stream_tbl_ptr) {
+ if (ptx_tbl->ba_status == ba_status) {
+ LEAVE();
+ return ptx_tbl;
+ }
+ ptx_tbl = ptx_tbl->pnext;
+ }
+
+ LEAVE();
+ return MNULL;
+}
+
+/********************************************************
+ Global Functions
+********************************************************/
+
+#ifdef STA_SUPPORT
+/**
+ * @brief This function fills the cap info
+ *
+ * @param priv A pointer to mlan_private structure
+ * @param pht_cap A pointer to MrvlIETypes_HTCap_t structure
+ * @param bands Band configuration
+ *
+ * @return N/A
+ */
+static void wlan_fill_cap_info(mlan_private *priv, HTCap_t *ht_cap, t_u8 bands)
+{
+ t_u32 usr_dot_11n_dev_cap;
+
+ ENTER();
+
+ if (bands & BAND_A)
+ usr_dot_11n_dev_cap = priv->usr_dot_11n_dev_cap_a;
+ else
+ usr_dot_11n_dev_cap = priv->usr_dot_11n_dev_cap_bg;
+
+ if (ISSUPP_CHANWIDTH40(usr_dot_11n_dev_cap))
+ SETHT_SUPPCHANWIDTH(ht_cap->ht_cap_info);
+ else
+ RESETHT_SUPPCHANWIDTH(ht_cap->ht_cap_info);
+
+ if (ISSUPP_GREENFIELD(usr_dot_11n_dev_cap))
+ SETHT_GREENFIELD(ht_cap->ht_cap_info);
+ else
+ RESETHT_GREENFIELD(ht_cap->ht_cap_info);
+
+ if (ISSUPP_SHORTGI20(usr_dot_11n_dev_cap))
+ SETHT_SHORTGI20(ht_cap->ht_cap_info);
+ else
+ RESETHT_SHORTGI20(ht_cap->ht_cap_info);
+
+ if (ISSUPP_SHORTGI40(usr_dot_11n_dev_cap))
+ SETHT_SHORTGI40(ht_cap->ht_cap_info);
+ else
+ RESETHT_SHORTGI40(ht_cap->ht_cap_info);
+ if (ISSUPP_RXSTBC(usr_dot_11n_dev_cap))
+ SETHT_RXSTBC(ht_cap->ht_cap_info, 1);
+ else
+ RESETHT_RXSTBC(ht_cap->ht_cap_info);
+
+ if (ISENABLED_40MHZ_INTOLARENT(usr_dot_11n_dev_cap))
+ SETHT_40MHZ_INTOLARANT(ht_cap->ht_cap_info);
+ else
+ RESETHT_40MHZ_INTOLARANT(ht_cap->ht_cap_info);
+
+ /** if current channel only allow 20Mhz, we should cler 40Mhz support */
+ if (priv->curr_chan_flags & CHAN_FLAGS_NO_HT40PLUS &&
+ priv->curr_chan_flags & CHAN_FLAGS_NO_HT40MINUS) {
+ RESETHT_SUPPCHANWIDTH(ht_cap->ht_cap_info);
+ RESETHT_SHORTGI40(ht_cap->ht_cap_info);
+ RESETHT_40MHZ_INTOLARANT(ht_cap->ht_cap_info);
+ }
+ /* No user config for LDPC coding capability yet */
+ if (ISSUPP_RXLDPC(usr_dot_11n_dev_cap))
+ SETHT_LDPCCODINGCAP(ht_cap->ht_cap_info);
+ else
+ RESETHT_LDPCCODINGCAP(ht_cap->ht_cap_info);
+
+ /* No user config for TX STBC yet */
+ if (ISSUPP_TXSTBC(usr_dot_11n_dev_cap))
+ SETHT_TXSTBC(ht_cap->ht_cap_info);
+ else
+ RESETHT_TXSTBC(ht_cap->ht_cap_info);
+
+ /* No user config for Delayed BACK yet */
+ RESETHT_DELAYEDBACK(ht_cap->ht_cap_info);
+
+ /* Need change to support 8k AMSDU receive */
+ RESETHT_MAXAMSDU(ht_cap->ht_cap_info);
+ /* SM power save */
+ if (ISSUPP_MIMOPS(priv->adapter->hw_dot_11n_dev_cap))
+ RESETHT_SM_POWERSAVE(ht_cap->ht_cap_info); /* Enable HT SMPS*/
+ else
+ SETHT_STATIC_SMPS(ht_cap->ht_cap_info); /* Disable HT SMPS */
+
+ LEAVE();
+}
+
+/**
+ * @brief This function clear the bit in cap info which we don't support
+ *
+ * @param priv A pointer to mlan_private structure
+ * @param pht_cap A pointer to MrvlIETypes_HTCap_t structure
+ * @param bands Band configuration
+ *
+ * @return N/A
+ */
+static void wlan_reset_cap_info(mlan_private *priv, HTCap_t *ht_cap, t_u8 bands)
+{
+ t_u32 usr_dot_11n_dev_cap;
+
+ ENTER();
+
+ if (bands & BAND_A)
+ usr_dot_11n_dev_cap = priv->usr_dot_11n_dev_cap_a;
+ else
+ usr_dot_11n_dev_cap = priv->usr_dot_11n_dev_cap_bg;
+
+ if (!ISSUPP_CHANWIDTH40(usr_dot_11n_dev_cap))
+ RESETHT_SUPPCHANWIDTH(ht_cap->ht_cap_info);
+
+ if (!ISSUPP_GREENFIELD(usr_dot_11n_dev_cap))
+ RESETHT_GREENFIELD(ht_cap->ht_cap_info);
+
+ if (!ISSUPP_SHORTGI20(usr_dot_11n_dev_cap))
+ RESETHT_SHORTGI20(ht_cap->ht_cap_info);
+
+ if (!ISSUPP_SHORTGI40(usr_dot_11n_dev_cap))
+ RESETHT_SHORTGI40(ht_cap->ht_cap_info);
+ if (!ISSUPP_RXSTBC(usr_dot_11n_dev_cap))
+ RESETHT_RXSTBC(ht_cap->ht_cap_info);
+
+ if (!ISENABLED_40MHZ_INTOLARENT(usr_dot_11n_dev_cap))
+ RESETHT_40MHZ_INTOLARANT(ht_cap->ht_cap_info);
+
+ /** if current channel only allow 20Mhz, we should cler 40Mhz support */
+ if (priv->curr_chan_flags & CHAN_FLAGS_NO_HT40PLUS &&
+ priv->curr_chan_flags & CHAN_FLAGS_NO_HT40MINUS) {
+ RESETHT_SUPPCHANWIDTH(ht_cap->ht_cap_info);
+ RESETHT_SHORTGI40(ht_cap->ht_cap_info);
+ RESETHT_40MHZ_INTOLARANT(ht_cap->ht_cap_info);
+ }
+ /* No user config for LDPC coding capability yet */
+ if (!ISSUPP_RXLDPC(usr_dot_11n_dev_cap))
+ RESETHT_LDPCCODINGCAP(ht_cap->ht_cap_info);
+
+ /* No user config for TX STBC yet */
+ if (!ISSUPP_TXSTBC(usr_dot_11n_dev_cap))
+ RESETHT_TXSTBC(ht_cap->ht_cap_info);
+
+ /* No user config for Delayed BACK yet */
+ RESETHT_DELAYEDBACK(ht_cap->ht_cap_info);
+
+ /* Need change to support 8k AMSDU receive */
+ RESETHT_MAXAMSDU(ht_cap->ht_cap_info);
+ /* SM power save */
+ if (!ISSUPP_MIMOPS(priv->adapter->hw_dot_11n_dev_cap))
+ SETHT_STATIC_SMPS(ht_cap->ht_cap_info); /* Disable HT SMPS */
+
+ LEAVE();
+}
+
+/**
+ * @brief This function fills the HT cap tlv
+ *
+ * @param priv A pointer to mlan_private structure
+ * @param pht_cap A pointer to MrvlIETypes_HTCap_t structure
+ * @param bands Band configuration
+ * @param fill A flag for fill the htcap info
+ *
+ * @return N/A
+ */
+void wlan_fill_ht_cap_tlv(mlan_private *priv, MrvlIETypes_HTCap_t *pht_cap,
+ t_u16 bands, t_u8 fill)
+{
+ mlan_adapter *pmadapter = priv->adapter;
+ int rx_mcs_supp;
+ t_u32 usr_dot_11n_dev_cap;
+
+ ENTER();
+
+ if (bands & BAND_A)
+ usr_dot_11n_dev_cap = priv->usr_dot_11n_dev_cap_a;
+ else
+ usr_dot_11n_dev_cap = priv->usr_dot_11n_dev_cap_bg;
+
+ /* Fill HT cap info */
+ if (fill)
+ wlan_fill_cap_info(priv, &pht_cap->ht_cap, bands);
+ else
+ wlan_reset_cap_info(priv, &pht_cap->ht_cap, bands);
+
+ pht_cap->ht_cap.ht_cap_info =
+ wlan_cpu_to_le16(pht_cap->ht_cap.ht_cap_info);
+
+ /* Set ampdu param */
+ SETAMPDU_SIZE(pht_cap->ht_cap.ampdu_param, AMPDU_FACTOR_64K);
+ SETAMPDU_SPACING(pht_cap->ht_cap.ampdu_param, 0);
+
+ rx_mcs_supp = GET_RXMCSSUPP(priv->usr_dev_mcs_support);
+#if defined(PCIE9098) || defined(SD9098) || defined(USB9098) || \
+ defined(PCIE9097) || defined(SD9097) || defined(USB9097)
+ if (IS_CARD9098(pmadapter->card_type) ||
+ IS_CARD9097(pmadapter->card_type)) {
+ if (bands & BAND_A)
+ rx_mcs_supp = MIN(
+ rx_mcs_supp,
+ GET_RXMCSSUPP(pmadapter->user_htstream >> 8));
+ else
+ rx_mcs_supp =
+ MIN(rx_mcs_supp,
+ GET_RXMCSSUPP(pmadapter->user_htstream));
+ }
+#endif
+ memset(pmadapter, (t_u8 *)pht_cap->ht_cap.supported_mcs_set, 0xff,
+ rx_mcs_supp);
+ /* Clear all the other values to get the minimum mcs set btw STA and AP
+ */
+ memset(pmadapter,
+ (t_u8 *)&pht_cap->ht_cap.supported_mcs_set[rx_mcs_supp], 0,
+ NUM_MCS_FIELD - rx_mcs_supp);
+ /* Set MCS32 with 40MHz support */
+ /* if current channel only support 20MHz, we should not set 40Mz
+ * supprot*/
+ if (ISSUPP_CHANWIDTH40(usr_dot_11n_dev_cap) &&
+ !(priv->curr_chan_flags & CHAN_FLAGS_NO_HT40PLUS &&
+ priv->curr_chan_flags & CHAN_FLAGS_NO_HT40MINUS))
+ SETHT_MCS32(pht_cap->ht_cap.supported_mcs_set);
+
+ /* Clear RD responder bit */
+ RESETHT_EXTCAP_RDG(pht_cap->ht_cap.ht_ext_cap);
+ pht_cap->ht_cap.ht_ext_cap =
+ wlan_cpu_to_le16(pht_cap->ht_cap.ht_ext_cap);
+
+ /* Set Tx BF cap */
+ pht_cap->ht_cap.tx_bf_cap = wlan_cpu_to_le32(priv->tx_bf_cap);
+
+ LEAVE();
+ return;
+}
+
+/**
+ * @brief This function fills the HT cap ie
+ *
+ * @param priv A pointer to mlan_private structure
+ * @param pht_cap A pointer to IEEEtypes_HTCap_t structure
+ * @param bands Band configuration
+ *
+ * @return N/A
+ */
+void wlan_fill_ht_cap_ie(mlan_private *priv, IEEEtypes_HTCap_t *pht_cap,
+ t_u16 bands)
+{
+ mlan_adapter *pmadapter = priv->adapter;
+ int rx_mcs_supp;
+ t_u32 usr_dot_11n_dev_cap;
+
+ ENTER();
+
+ pht_cap->ieee_hdr.element_id = HT_CAPABILITY;
+ pht_cap->ieee_hdr.len = sizeof(HTCap_t);
+ if (bands & BAND_A)
+ usr_dot_11n_dev_cap = priv->usr_dot_11n_dev_cap_a;
+ else
+ usr_dot_11n_dev_cap = priv->usr_dot_11n_dev_cap_bg;
+
+ /* Fill HT cap info */
+ wlan_fill_cap_info(priv, &pht_cap->ht_cap, bands);
+
+ /* Set ampdu param */
+ SETAMPDU_SIZE(pht_cap->ht_cap.ampdu_param, AMPDU_FACTOR_64K);
+ SETAMPDU_SPACING(pht_cap->ht_cap.ampdu_param, 0);
+
+ rx_mcs_supp = GET_RXMCSSUPP(priv->usr_dev_mcs_support);
+#if defined(PCIE9098) || defined(SD9098) || defined(USB9098) || \
+ defined(PCIE9097) || defined(SD9097) || defined(USB9097)
+ if (IS_CARD9098(pmadapter->card_type) ||
+ IS_CARD9097(pmadapter->card_type)) {
+ if (bands & BAND_A)
+ rx_mcs_supp = MIN(
+ rx_mcs_supp,
+ GET_RXMCSSUPP(pmadapter->user_htstream >> 8));
+ else
+ rx_mcs_supp =
+ MIN(rx_mcs_supp,
+ GET_RXMCSSUPP(pmadapter->user_htstream));
+ }
+#endif
+ memset(pmadapter, (t_u8 *)pht_cap->ht_cap.supported_mcs_set, 0xff,
+ rx_mcs_supp);
+ /* Clear all the other values to get the minimum mcs set btw STA and AP
+ */
+ memset(pmadapter,
+ (t_u8 *)&pht_cap->ht_cap.supported_mcs_set[rx_mcs_supp], 0,
+ NUM_MCS_FIELD - rx_mcs_supp);
+ /* Set MCS32 with 40MHz support */
+ /* if current channel only support 20MHz, we should not set 40Mz
+ * supprot*/
+ if (ISSUPP_CHANWIDTH40(usr_dot_11n_dev_cap) &&
+ !(priv->curr_chan_flags & CHAN_FLAGS_NO_HT40PLUS &&
+ priv->curr_chan_flags & CHAN_FLAGS_NO_HT40MINUS))
+ SETHT_MCS32(pht_cap->ht_cap.supported_mcs_set);
+
+ /* Clear RD responder bit */
+ RESETHT_EXTCAP_RDG(pht_cap->ht_cap.ht_ext_cap);
+
+ /* Set Tx BF cap */
+ pht_cap->ht_cap.tx_bf_cap = priv->tx_bf_cap;
+
+ LEAVE();
+ return;
+}
+#endif /* STA_SUPPORT */
+
+/**
+ * @brief This function prints the 802.11n device capability
+ *
+ * @param pmadapter A pointer to mlan_adapter structure
+ * @param cap Capability value
+ *
+ * @return N/A
+ */
+void wlan_show_dot11ndevcap(pmlan_adapter pmadapter, t_u32 cap)
+{
+ ENTER();
+
+ PRINTM(MINFO, "GET_HW_SPEC: Maximum MSDU length = %s octets\n",
+ (ISSUPP_MAXAMSDU(cap) ? "7935" : "3839"));
+ PRINTM(MINFO, "GET_HW_SPEC: Beam forming %s\n",
+ (ISSUPP_BEAMFORMING(cap) ? "supported" : "not supported"));
+ PRINTM(MINFO, "GET_HW_SPEC: Greenfield preamble %s\n",
+ (ISSUPP_GREENFIELD(cap) ? "supported" : "not supported"));
+ PRINTM(MINFO, "GET_HW_SPEC: AMPDU %s\n",
+ (ISSUPP_AMPDU(cap) ? "supported" : "not supported"));
+ PRINTM(MINFO, "GET_HW_SPEC: MIMO Power Save %s\n",
+ (ISSUPP_MIMOPS(cap) ? "supported" : "not supported"));
+ PRINTM(MINFO, "GET_HW_SPEC: Rx STBC %s\n",
+ (ISSUPP_RXSTBC(cap) ? "supported" : "not supported"));
+ PRINTM(MINFO, "GET_HW_SPEC: Tx STBC %s\n",
+ (ISSUPP_TXSTBC(cap) ? "supported" : "not supported"));
+ PRINTM(MINFO, "GET_HW_SPEC: Short GI for 40 Mhz %s\n",
+ (ISSUPP_SHORTGI40(cap) ? "supported" : "not supported"));
+ PRINTM(MINFO, "GET_HW_SPEC: Short GI for 20 Mhz %s\n",
+ (ISSUPP_SHORTGI20(cap) ? "supported" : "not supported"));
+ PRINTM(MINFO, "GET_HW_SPEC: LDPC coded packet receive %s\n",
+ (ISSUPP_RXLDPC(cap) ? "supported" : "not supported"));
+
+ PRINTM(MINFO, "GET_HW_SPEC: Number of Tx BA streams supported = %d\n",
+ ISSUPP_GETTXBASTREAM(cap));
+ PRINTM(MINFO, "GET_HW_SPEC: 40 Mhz channel width %s\n",
+ (ISSUPP_CHANWIDTH40(cap) ? "supported" : "not supported"));
+ PRINTM(MINFO, "GET_HW_SPEC: 20 Mhz channel width %s\n",
+ (ISSUPP_CHANWIDTH20(cap) ? "supported" : "not supported"));
+ PRINTM(MINFO, "GET_HW_SPEC: 10 Mhz channel width %s\n",
+ (ISSUPP_CHANWIDTH10(cap) ? "supported" : "not supported"));
+
+ if (ISSUPP_RXANTENNAA(cap))
+ PRINTM(MINFO, "GET_HW_SPEC: Presence of Rx antenna A\n");
+ if (ISSUPP_RXANTENNAB(cap))
+ PRINTM(MINFO, "GET_HW_SPEC: Presence of Rx antenna B\n");
+ if (ISSUPP_RXANTENNAC(cap))
+ PRINTM(MINFO, "GET_HW_SPEC: Presence of Rx antenna C\n");
+ if (ISSUPP_RXANTENNAD(cap))
+ PRINTM(MINFO, "GET_HW_SPEC: Presence of Rx antenna D\n");
+ if (ISSUPP_TXANTENNAA(cap))
+ PRINTM(MINFO, "GET_HW_SPEC: Presence of Tx antenna A\n");
+ if (ISSUPP_TXANTENNAB(cap))
+ PRINTM(MINFO, "GET_HW_SPEC: Presence of Tx antenna B\n");
+ if (ISSUPP_TXANTENNAC(cap))
+ PRINTM(MINFO, "GET_HW_SPEC: Presence of Tx antenna C\n");
+ if (ISSUPP_TXANTENNAD(cap))
+ PRINTM(MINFO, "GET_HW_SPEC: Presence of Tx antenna D\n");
+
+ LEAVE();
+ return;
+}
+
+/**
+ * @brief This function prints the 802.11n device MCS
+ *
+ * @param pmadapter A pointer to mlan_adapter structure
+ * @param support Support value
+ *
+ * @return N/A
+ */
+void wlan_show_devmcssupport(pmlan_adapter pmadapter, t_u8 support)
+{
+ ENTER();
+
+ PRINTM(MINFO, "GET_HW_SPEC: MCSs for %dx%d MIMO\n",
+ GET_RXMCSSUPP(support), GET_TXMCSSUPP(support));
+
+ LEAVE();
+ return;
+}
+
+/**
+ * @brief This function handles the command response of
+ * delete a block ack request
+ *
+ * @param priv A pointer to mlan_private structure
+ * @param resp A pointer to HostCmd_DS_COMMAND
+ *
+ * @return MLAN_STATUS_SUCCESS
+ */
+mlan_status wlan_ret_11n_delba(mlan_private *priv, HostCmd_DS_COMMAND *resp)
+{
+ int tid;
+ TxBAStreamTbl *ptx_ba_tbl;
+ HostCmd_DS_11N_DELBA *pdel_ba =
+ (HostCmd_DS_11N_DELBA *)&resp->params.del_ba;
+
+ ENTER();
+
+ pdel_ba->del_ba_param_set = wlan_le16_to_cpu(pdel_ba->del_ba_param_set);
+ pdel_ba->reason_code = wlan_le16_to_cpu(pdel_ba->reason_code);
+
+ tid = pdel_ba->del_ba_param_set >> DELBA_TID_POS;
+ if (pdel_ba->del_result == BA_RESULT_SUCCESS) {
+ mlan_11n_delete_bastream_tbl(
+ priv, tid, pdel_ba->peer_mac_addr, TYPE_DELBA_SENT,
+ INITIATOR_BIT(pdel_ba->del_ba_param_set), 0);
+ wlan_request_ralist_lock(priv);
+ ptx_ba_tbl = wlan_11n_get_txbastream_status(
+ priv, BA_STREAM_SETUP_INPROGRESS);
+ wlan_release_ralist_lock(priv);
+ if (ptx_ba_tbl)
+ wlan_send_addba(priv, ptx_ba_tbl->tid, ptx_ba_tbl->ra);
+ } else { /*
+ * In case of failure, recreate
+ * the deleted stream in case
+ * we initiated the ADDBA
+ */
+ if (INITIATOR_BIT(pdel_ba->del_ba_param_set)) {
+ wlan_request_ralist_lock(priv);
+ if (!wlan_11n_get_txbastream_tbl(
+ priv, tid, pdel_ba->peer_mac_addr, MFALSE))
+ wlan_11n_create_txbastream_tbl(
+ priv, pdel_ba->peer_mac_addr, tid,
+ BA_STREAM_SETUP_INPROGRESS);
+ ptx_ba_tbl = wlan_11n_get_txbastream_status(
+ priv, BA_STREAM_SETUP_INPROGRESS);
+ wlan_release_ralist_lock(priv);
+ if (ptx_ba_tbl) {
+ mlan_11n_delete_bastream_tbl(
+ priv, ptx_ba_tbl->tid, ptx_ba_tbl->ra,
+ TYPE_DELBA_SENT, MTRUE, 0);
+ }
+ }
+ }
+
+ LEAVE();
+ return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ * @brief This function handles the command response of
+ * add a block ack request
+ *
+ * @param priv A pointer to mlan_private structure
+ * @param resp A pointer to HostCmd_DS_COMMAND
+ *
+ * @return MLAN_STATUS_SUCCESS
+ */
+mlan_status wlan_ret_11n_addba_req(mlan_private *priv, HostCmd_DS_COMMAND *resp)
+{
+ t_u8 tid;
+ HostCmd_DS_11N_ADDBA_RSP *padd_ba_rsp =
+ (HostCmd_DS_11N_ADDBA_RSP *)&resp->params.add_ba_rsp;
+ TxBAStreamTbl *ptx_ba_tbl;
+ raListTbl *ra_list = MNULL;
+ int tid_down;
+
+ ENTER();
+
+ padd_ba_rsp->block_ack_param_set =
+ wlan_le16_to_cpu(padd_ba_rsp->block_ack_param_set);
+ padd_ba_rsp->block_ack_tmo =
+ wlan_le16_to_cpu(padd_ba_rsp->block_ack_tmo);
+ padd_ba_rsp->ssn = (wlan_le16_to_cpu(padd_ba_rsp->ssn)) & SSN_MASK;
+ padd_ba_rsp->status_code = wlan_le16_to_cpu(padd_ba_rsp->status_code);
+
+ tid = (padd_ba_rsp->block_ack_param_set & BLOCKACKPARAM_TID_MASK) >>
+ BLOCKACKPARAM_TID_POS;
+ tid_down = wlan_get_wmm_tid_down(priv, tid);
+ ra_list = wlan_wmm_get_ralist_node(priv, tid_down,
+ padd_ba_rsp->peer_mac_addr);
+ if (padd_ba_rsp->status_code == BA_RESULT_SUCCESS) {
+ ptx_ba_tbl = wlan_11n_get_txbastream_tbl(
+ priv, tid, padd_ba_rsp->peer_mac_addr, MTRUE);
+ if (ptx_ba_tbl) {
+ PRINTM(MCMND,
+ "ADDBA REQ: " MACSTR
+ " tid=%d ssn=%d win_size=%d,amsdu=%d\n",
+ MAC2STR(padd_ba_rsp->peer_mac_addr), tid,
+ padd_ba_rsp->ssn,
+ ((padd_ba_rsp->block_ack_param_set &
+ BLOCKACKPARAM_WINSIZE_MASK) >>
+ BLOCKACKPARAM_WINSIZE_POS),
+ padd_ba_rsp->block_ack_param_set &
+ BLOCKACKPARAM_AMSDU_SUPP_MASK);
+ ptx_ba_tbl->ba_status = BA_STREAM_SETUP_COMPLETE;
+ if ((padd_ba_rsp->block_ack_param_set &
+ BLOCKACKPARAM_AMSDU_SUPP_MASK) &&
+ priv->add_ba_param.tx_amsdu &&
+ (priv->aggr_prio_tbl[tid].amsdu !=
+ BA_STREAM_NOT_ALLOWED))
+ ptx_ba_tbl->amsdu = MTRUE;
+ else
+ ptx_ba_tbl->amsdu = MFALSE;
+ if (ra_list) {
+ ra_list->amsdu_in_ampdu = ptx_ba_tbl->amsdu;
+ ra_list->ba_status = BA_STREAM_SETUP_COMPLETE;
+ }
+ } else {
+ PRINTM(MERROR, "BA stream not created\n");
+ }
+ } else {
+ if (ra_list) {
+ ra_list->amsdu_in_ampdu = MFALSE;
+ ra_list->ba_status = BA_STREAM_NOT_SETUP;
+ }
+ mlan_11n_delete_bastream_tbl(priv, tid,
+ padd_ba_rsp->peer_mac_addr,
+ TYPE_DELBA_SENT, MTRUE, 0);
+ if (padd_ba_rsp->add_rsp_result != BA_RESULT_TIMEOUT) {
+#ifdef UAP_SUPPORT
+ if (GET_BSS_ROLE(priv) == MLAN_BSS_ROLE_UAP)
+ disable_station_ampdu(
+ priv, tid, padd_ba_rsp->peer_mac_addr);
+#endif /* UAP_SUPPORT */
+ priv->aggr_prio_tbl[tid].ampdu_ap =
+ BA_STREAM_NOT_ALLOWED;
+
+ } else {
+ if (ra_list) {
+ ra_list->packet_count = 0;
+ ra_list->ba_packet_threshold =
+ wlan_get_random_ba_threshold(
+ priv->adapter);
+ }
+ }
+ }
+
+ LEAVE();
+ return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ * @brief This function restore tx_pause flag
+ *
+ * @param priv A pointer to mlan_private structure
+ * @param flag MTRUE/MFALSE;
+ *
+ * @return N/A
+ */
+void wlan_set_tx_pause_flag(mlan_private *priv, t_u8 flag)
+{
+ mlan_private *pmpriv = MNULL;
+ t_u8 i;
+ for (i = 0; i < priv->adapter->priv_num; i++) {
+ pmpriv = priv->adapter->priv[i];
+ if (pmpriv)
+ pmpriv->tx_pause = flag;
+ }
+}
+
+/**
+ * @brief This function prepares command of reconfigure tx buf
+ *
+ * @param priv A pointer to mlan_private structure
+ * @param cmd A pointer to HostCmd_DS_COMMAND structure
+ * @param cmd_action The action: GET or SET
+ * @param pdata_buf A pointer to data buffer
+ *
+ * @return MLAN_STATUS_SUCCESS
+ */
+mlan_status wlan_cmd_recfg_tx_buf(mlan_private *priv, HostCmd_DS_COMMAND *cmd,
+ int cmd_action, void *pdata_buf)
+{
+ HostCmd_DS_TXBUF_CFG *ptx_buf = &cmd->params.tx_buf;
+ t_u16 action = (t_u16)cmd_action;
+ t_u16 buf_size = *((t_u16 *)pdata_buf);
+
+ ENTER();
+ cmd->command = wlan_cpu_to_le16(HostCmd_CMD_RECONFIGURE_TX_BUFF);
+ cmd->size = wlan_cpu_to_le16(sizeof(HostCmd_DS_TXBUF_CFG) + S_DS_GEN);
+ ptx_buf->action = wlan_cpu_to_le16(action);
+ switch (action) {
+ case HostCmd_ACT_GEN_SET:
+ PRINTM(MCMND, "set tx_buf = %d\n", buf_size);
+ ptx_buf->buff_size = wlan_cpu_to_le16(buf_size);
+ /** stop tx traffic */
+ wlan_set_tx_pause_flag(priv, MTRUE);
+ break;
+ case HostCmd_ACT_GEN_GET:
+ default:
+ ptx_buf->buff_size = 0;
+ break;
+ }
+ LEAVE();
+ return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ * @brief This function prepares command of amsdu aggr control
+ *
+ * @param priv A pointer to mlan_private structure
+ * @param cmd A pointer to HostCmd_DS_COMMAND structure
+ * @param cmd_action The action: GET or SET
+ * @param pdata_buf A pointer to data buffer
+ *
+ * @return MLAN_STATUS_SUCCESS
+ */
+mlan_status wlan_cmd_amsdu_aggr_ctrl(mlan_private *priv,
+ HostCmd_DS_COMMAND *cmd, int cmd_action,
+ void *pdata_buf)
+{
+ HostCmd_DS_AMSDU_AGGR_CTRL *pamsdu_ctrl = &cmd->params.amsdu_aggr_ctrl;
+ t_u16 action = (t_u16)cmd_action;
+ mlan_ds_11n_amsdu_aggr_ctrl *aa_ctrl =
+ (mlan_ds_11n_amsdu_aggr_ctrl *)pdata_buf;
+
+ ENTER();
+
+ cmd->command = wlan_cpu_to_le16(HostCmd_CMD_AMSDU_AGGR_CTRL);
+ cmd->size =
+ wlan_cpu_to_le16(sizeof(HostCmd_DS_AMSDU_AGGR_CTRL) + S_DS_GEN);
+ pamsdu_ctrl->action = wlan_cpu_to_le16(action);
+ switch (action) {
+ case HostCmd_ACT_GEN_SET:
+ pamsdu_ctrl->enable = wlan_cpu_to_le16(aa_ctrl->enable);
+ pamsdu_ctrl->curr_buf_size = 0;
+ break;
+ case HostCmd_ACT_GEN_GET:
+ default:
+ pamsdu_ctrl->curr_buf_size = 0;
+ break;
+ }
+ LEAVE();
+ return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ * @brief This function handles the command response of amsdu aggr ctrl
+ *
+ * @param pmpriv A pointer to mlan_private structure
+ * @param resp A pointer to HostCmd_DS_COMMAND
+ * @param pioctl_buf A pointer to mlan_ioctl_req structure
+ *
+ * @return MLAN_STATUS_SUCCESS
+ */
+mlan_status wlan_ret_amsdu_aggr_ctrl(pmlan_private pmpriv,
+ HostCmd_DS_COMMAND *resp,
+ mlan_ioctl_req *pioctl_buf)
+{
+ mlan_ds_11n_cfg *cfg = MNULL;
+ HostCmd_DS_AMSDU_AGGR_CTRL *amsdu_ctrl = &resp->params.amsdu_aggr_ctrl;
+
+ ENTER();
+
+ if (pioctl_buf) {
+ cfg = (mlan_ds_11n_cfg *)pioctl_buf->pbuf;
+ cfg->param.amsdu_aggr_ctrl.enable =
+ wlan_le16_to_cpu(amsdu_ctrl->enable);
+ cfg->param.amsdu_aggr_ctrl.curr_buf_size =
+ wlan_le16_to_cpu(amsdu_ctrl->curr_buf_size);
+ }
+ LEAVE();
+ return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ * @brief This function prepares 11n cfg command
+ *
+ * @param pmpriv A pointer to mlan_private structure
+ * @param cmd A pointer to HostCmd_DS_COMMAND structure
+ * @param cmd_action the action: GET or SET
+ * @param pdata_buf A pointer to data buffer
+ * @return MLAN_STATUS_SUCCESS
+ */
+mlan_status wlan_cmd_11n_cfg(pmlan_private pmpriv, HostCmd_DS_COMMAND *cmd,
+ t_u16 cmd_action, t_void *pdata_buf)
+{
+ HostCmd_DS_11N_CFG *htcfg = &cmd->params.htcfg;
+ mlan_ds_11n_tx_cfg *txcfg = (mlan_ds_11n_tx_cfg *)pdata_buf;
+
+ ENTER();
+ cmd->command = wlan_cpu_to_le16(HostCmd_CMD_11N_CFG);
+ cmd->size = wlan_cpu_to_le16(sizeof(HostCmd_DS_11N_CFG) + S_DS_GEN);
+ htcfg->action = wlan_cpu_to_le16(cmd_action);
+ htcfg->ht_tx_cap = wlan_cpu_to_le16(txcfg->httxcap);
+ htcfg->ht_tx_info = wlan_cpu_to_le16(txcfg->httxinfo);
+ htcfg->misc_config = wlan_cpu_to_le16(txcfg->misc_cfg);
+ LEAVE();
+ return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ * @brief This function handles the command response of 11ncfg
+ *
+ * @param pmpriv A pointer to mlan_private structure
+ * @param resp A pointer to HostCmd_DS_COMMAND
+ * @param pioctl_buf A pointer to mlan_ioctl_req structure
+ *
+ * @return MLAN_STATUS_SUCCESS
+ */
+mlan_status wlan_ret_11n_cfg(pmlan_private pmpriv, HostCmd_DS_COMMAND *resp,
+ mlan_ioctl_req *pioctl_buf)
+{
+ mlan_ds_11n_cfg *cfg = MNULL;
+ HostCmd_DS_11N_CFG *htcfg = &resp->params.htcfg;
+
+ ENTER();
+ if (pioctl_buf &&
+ (wlan_le16_to_cpu(htcfg->action) == HostCmd_ACT_GEN_GET)) {
+ cfg = (mlan_ds_11n_cfg *)pioctl_buf->pbuf;
+ cfg->param.tx_cfg.httxcap = wlan_le16_to_cpu(htcfg->ht_tx_cap);
+ cfg->param.tx_cfg.httxinfo =
+ wlan_le16_to_cpu(htcfg->ht_tx_info);
+ cfg->param.tx_cfg.misc_cfg =
+ wlan_le16_to_cpu(htcfg->misc_config);
+ }
+ LEAVE();
+ return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ * @brief This function prepares reject addba req command
+ *
+ * @param pmpriv A pointer to mlan_private structure
+ * @param cmd A pointer to HostCmd_DS_COMMAND structure
+ * @param cmd_action the action: GET or SET
+ * @param pdata_buf A pointer to data buffer
+ * @return MLAN_STATUS_SUCCESS
+ */
+mlan_status wlan_cmd_reject_addba_req(pmlan_private pmpriv,
+ HostCmd_DS_COMMAND *cmd, t_u16 cmd_action,
+ t_void *pdata_buf)
+{
+ HostCmd_DS_REJECT_ADDBA_REQ *preject_addba_req =
+ &cmd->params.rejectaddbareq;
+ mlan_ds_reject_addba_req *prejaddbareq =
+ (mlan_ds_reject_addba_req *)pdata_buf;
+
+ ENTER();
+ cmd->command = wlan_cpu_to_le16(HostCmd_CMD_REJECT_ADDBA_REQ);
+ cmd->size = wlan_cpu_to_le16(sizeof(HostCmd_DS_REJECT_ADDBA_REQ) +
+ S_DS_GEN);
+ preject_addba_req->action = wlan_cpu_to_le16(cmd_action);
+ preject_addba_req->conditions =
+ wlan_cpu_to_le32(prejaddbareq->conditions);
+ LEAVE();
+ return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ * @brief This function handles the command response of reject addba req
+ *
+ * @param pmpriv A pointer to mlan_private structure
+ * @param resp A pointer to HostCmd_DS_COMMAND
+ * @param pioctl_buf A pointer to mlan_ioctl_req structure
+ *
+ * @return MLAN_STATUS_SUCCESS
+ */
+mlan_status wlan_ret_reject_addba_req(pmlan_private pmpriv,
+ HostCmd_DS_COMMAND *resp,
+ mlan_ioctl_req *pioctl_buf)
+{
+ mlan_ds_11n_cfg *cfg = MNULL;
+ HostCmd_DS_REJECT_ADDBA_REQ *preject_addba_req =
+ &resp->params.rejectaddbareq;
+
+ ENTER();
+ if (pioctl_buf && (wlan_le16_to_cpu(preject_addba_req->action) ==
+ HostCmd_ACT_GEN_GET)) {
+ cfg = (mlan_ds_11n_cfg *)pioctl_buf->pbuf;
+ cfg->param.reject_addba_req.conditions =
+ wlan_le32_to_cpu(preject_addba_req->conditions);
+ }
+ LEAVE();
+ return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ * @brief This function prepares TX BF configuration command
+ *
+ * @param pmpriv A pointer to mlan_private structure
+ * @param cmd A pointer to HostCmd_DS_COMMAND structure
+ * @param cmd_action The action: GET or SET
+ * @param pdata_buf A pointer to data buffer
+ * @return MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ */
+mlan_status wlan_cmd_tx_bf_cfg(pmlan_private pmpriv, HostCmd_DS_COMMAND *cmd,
+ t_u16 cmd_action, t_void *pdata_buf)
+{
+ pmlan_adapter pmadapter = pmpriv->adapter;
+ HostCmd_DS_TX_BF_CFG *txbfcfg = &cmd->params.tx_bf_cfg;
+ mlan_ds_11n_tx_bf_cfg *txbf = (mlan_ds_11n_tx_bf_cfg *)pdata_buf;
+
+ ENTER();
+
+ cmd->command = wlan_cpu_to_le16(HostCmd_CMD_TX_BF_CFG);
+ cmd->size = wlan_cpu_to_le16(sizeof(HostCmd_DS_TX_BF_CFG) + S_DS_GEN);
+
+ if (txbf->bf_action == SET_GET_BF_PERIODICITY) {
+ memcpy_ext(pmadapter, txbfcfg->body.bf_periodicity.peer_mac,
+ txbf->body.bf_periodicity[0].peer_mac,
+ MLAN_MAC_ADDR_LENGTH, MLAN_MAC_ADDR_LENGTH);
+ }
+ txbfcfg->action = wlan_cpu_to_le16(txbf->action);
+ txbfcfg->bf_action = wlan_cpu_to_le16(txbf->bf_action);
+ if (cmd_action == HostCmd_ACT_GEN_SET) {
+ switch (txbf->bf_action) {
+ case BF_GLOBAL_CONFIGURATION:
+ txbfcfg->body.bf_global_cfg.bf_enbl =
+ txbf->body.bf_global_cfg.bf_enbl;
+ txbfcfg->body.bf_global_cfg.sounding_enbl =
+ txbf->body.bf_global_cfg.sounding_enbl;
+ txbfcfg->body.bf_global_cfg.fb_type =
+ txbf->body.bf_global_cfg.fb_type;
+ txbfcfg->body.bf_global_cfg.snr_threshold =
+ txbf->body.bf_global_cfg.snr_threshold;
+ txbfcfg->body.bf_global_cfg.sounding_interval =
+ wlan_cpu_to_le16(txbf->body.bf_global_cfg
+ .sounding_interval);
+ txbfcfg->body.bf_global_cfg.bf_mode =
+ txbf->body.bf_global_cfg.bf_mode;
+ break;
+ case TRIGGER_SOUNDING_FOR_PEER:
+ memcpy_ext(pmadapter,
+ txbfcfg->body.bf_sound_args.peer_mac,
+ txbf->body.bf_sound[0].peer_mac,
+ MLAN_MAC_ADDR_LENGTH, MLAN_MAC_ADDR_LENGTH);
+ break;
+ case SET_GET_BF_PERIODICITY:
+ txbfcfg->body.bf_periodicity.interval =
+ wlan_cpu_to_le16(
+ txbf->body.bf_periodicity->interval);
+ break;
+ case TX_BF_FOR_PEER_ENBL:
+ memcpy_ext(pmadapter, txbfcfg->body.tx_bf_peer.peer_mac,
+ txbf->body.tx_bf_peer[0].peer_mac,
+ MLAN_MAC_ADDR_LENGTH, MLAN_MAC_ADDR_LENGTH);
+ txbfcfg->body.tx_bf_peer.bf_enbl =
+ txbf->body.tx_bf_peer[0].bf_enbl;
+ txbfcfg->body.tx_bf_peer.sounding_enbl =
+ txbf->body.tx_bf_peer[0].sounding_enbl;
+ txbfcfg->body.tx_bf_peer.fb_type =
+ txbf->body.tx_bf_peer[0].fb_type;
+ break;
+ case SET_SNR_THR_PEER:
+ memcpy_ext(pmadapter, txbfcfg->body.bf_snr.peer_mac,
+ txbf->body.bf_snr[0].peer_mac,
+ MLAN_MAC_ADDR_LENGTH, MLAN_MAC_ADDR_LENGTH);
+ txbfcfg->body.bf_snr.snr = txbf->body.bf_snr[0].snr;
+ break;
+ default:
+ LEAVE();
+ return MLAN_STATUS_FAILURE;
+ }
+ }
+
+ LEAVE();
+ return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ * @brief This function handles the command response
+ * of TX BF configuration
+ *
+ * @param pmpriv A pointer to mlan_private structure
+ * @param resp A pointer to HostCmd_DS_COMMAND
+ * @param pioctl_buf A pointer to mlan_ioctl_req structure
+ *
+ * @return MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ */
+mlan_status wlan_ret_tx_bf_cfg(pmlan_private pmpriv, HostCmd_DS_COMMAND *resp,
+ mlan_ioctl_req *pioctl_buf)
+{
+ pmlan_adapter pmadapter = pmpriv->adapter;
+ HostCmd_DS_TX_BF_CFG *txbfcfg = &resp->params.tx_bf_cfg;
+ mlan_ds_11n_cfg *cfg_11n = MNULL;
+ mlan_ds_11n_tx_bf_cfg *txbf = MNULL;
+ bf_peer_args *tx_bf_peer;
+ bf_snr_thr_t *bf_snr;
+ int i;
+
+ ENTER();
+
+ if (pioctl_buf) {
+ cfg_11n = (mlan_ds_11n_cfg *)pioctl_buf->pbuf;
+ txbf = (mlan_ds_11n_tx_bf_cfg *)&cfg_11n->param.tx_bf;
+ txbf->bf_action = wlan_le16_to_cpu(txbfcfg->bf_action);
+ switch (txbf->bf_action) {
+ case BF_GLOBAL_CONFIGURATION:
+ txbf->body.bf_global_cfg.bf_enbl =
+ txbfcfg->body.bf_global_cfg.bf_enbl;
+ txbf->body.bf_global_cfg.sounding_enbl =
+ txbfcfg->body.bf_global_cfg.sounding_enbl;
+ txbf->body.bf_global_cfg.fb_type =
+ txbfcfg->body.bf_global_cfg.fb_type;
+ txbf->body.bf_global_cfg.snr_threshold =
+ txbfcfg->body.bf_global_cfg.snr_threshold;
+ txbf->body.bf_global_cfg.sounding_interval =
+ wlan_le16_to_cpu(txbfcfg->body.bf_global_cfg
+ .sounding_interval);
+ txbf->body.bf_global_cfg.bf_mode =
+ txbfcfg->body.bf_global_cfg.bf_mode;
+ break;
+ case TRIGGER_SOUNDING_FOR_PEER:
+ memcpy_ext(pmadapter, txbf->body.bf_sound[0].peer_mac,
+ txbfcfg->body.bf_sound_args.peer_mac,
+ MLAN_MAC_ADDR_LENGTH, MLAN_MAC_ADDR_LENGTH);
+ txbf->body.bf_sound[0].status =
+ txbfcfg->body.bf_sound_args.status;
+ break;
+ case SET_GET_BF_PERIODICITY:
+ memcpy_ext(pmadapter,
+ txbf->body.bf_periodicity->peer_mac,
+ txbfcfg->body.bf_periodicity.peer_mac,
+ MLAN_MAC_ADDR_LENGTH, MLAN_MAC_ADDR_LENGTH);
+ txbf->body.bf_periodicity->interval = wlan_le16_to_cpu(
+ txbfcfg->body.bf_periodicity.interval);
+ break;
+ case TX_BF_FOR_PEER_ENBL:
+ txbf->no_of_peers = *(t_u8 *)&txbfcfg->body;
+ tx_bf_peer = (bf_peer_args *)((t_u8 *)&txbfcfg->body +
+ sizeof(t_u8));
+ for (i = 0; i < txbf->no_of_peers; i++) {
+ memcpy_ext(pmadapter,
+ txbf->body.tx_bf_peer[i].peer_mac,
+ (t_u8 *)tx_bf_peer->peer_mac,
+ MLAN_MAC_ADDR_LENGTH,
+ MLAN_MAC_ADDR_LENGTH);
+ txbf->body.tx_bf_peer[i].bf_enbl =
+ tx_bf_peer->bf_enbl;
+ txbf->body.tx_bf_peer[i].sounding_enbl =
+ tx_bf_peer->sounding_enbl;
+ txbf->body.tx_bf_peer[i].fb_type =
+ tx_bf_peer->fb_type;
+ tx_bf_peer++;
+ }
+ break;
+ case SET_SNR_THR_PEER:
+ txbf->no_of_peers = *(t_u8 *)&txbfcfg->body;
+ bf_snr = (bf_snr_thr_t *)((t_u8 *)&txbfcfg->body +
+ sizeof(t_u8));
+ for (i = 0; i < txbf->no_of_peers; i++) {
+ memcpy_ext(pmadapter,
+ txbf->body.bf_snr[i].peer_mac,
+ (t_u8 *)bf_snr->peer_mac,
+ MLAN_MAC_ADDR_LENGTH,
+ MLAN_MAC_ADDR_LENGTH);
+ txbf->body.bf_snr[i].snr = bf_snr->snr;
+ bf_snr++;
+ }
+ break;
+ default:
+ LEAVE();
+ return MLAN_STATUS_FAILURE;
+ }
+ }
+
+ LEAVE();
+ return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ * @brief Get second channel offset
+ *
+ * @param chan channel num
+ * @return second channel offset
+ */
+t_u8 wlan_get_second_channel_offset(int chan)
+{
+ t_u8 chan2Offset = SEC_CHAN_NONE;
+
+ 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:
+ chan2Offset = SEC_CHAN_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:
+ chan2Offset = SEC_CHAN_BELOW;
+ break;
+ case 165:
+ /* Special Case: 20Mhz-only Channel */
+ chan2Offset = SEC_CHAN_NONE;
+ break;
+ }
+ return chan2Offset;
+}
+
+#ifdef STA_SUPPORT
+/**
+ * @brief validate the channel offset for Infra/Ad-hoc band configuration
+ *
+ * @param pmpriv A pointer to mlan_private structure
+ * @param band band
+ * @param chan primary channel
+ * @param chan_bw channel bandwidth
+ *
+ * @return channel offset (NO_SEC_CHANNEL, SEC_CHANNEL_ABOVE,
+ * SEC_CHANNEL_BELOW)
+ */
+t_u8 wlan_validate_chan_offset(mlan_private *pmpriv, t_u16 band, t_u32 chan,
+ t_u8 chan_bw)
+{
+ t_u8 chan_offset;
+ pmlan_adapter pmadapter = pmpriv->adapter;
+
+ if (chan_bw == CHANNEL_BW_40MHZ_ABOVE)
+ chan_offset = SEC_CHAN_ABOVE;
+ else if (chan_bw == CHANNEL_BW_40MHZ_BELOW)
+ chan_offset = SEC_CHAN_BELOW;
+ else
+ chan_offset = SEC_CHAN_NONE;
+
+ /* validation */
+ if (chan_offset != SEC_CHAN_NONE) {
+ if (band & BAND_GN) {
+ if ((chan == 1) || (chan == 2) || (chan == 3) ||
+ (chan == 4))
+ chan_offset = SEC_CHAN_ABOVE;
+ else if ((chan == 10) || (chan == 11) || (chan == 12) ||
+ (chan == 13))
+ chan_offset = SEC_CHAN_BELOW;
+
+ /* check if channel 12 is supported in the region */
+ if (!wlan_find_cfp_by_band_and_channel(pmadapter, band,
+ 12))
+ if ((chan == 8) || (chan == 9))
+ chan_offset = SEC_CHAN_BELOW;
+ } else if (band & BAND_AN)
+ chan_offset = wlan_get_second_channel_offset(chan);
+ }
+ return chan_offset;
+}
+
+/**
+ * @brief This function check if ht40 is allowed in current region
+ *
+ * @param pmpriv A pointer to mlan_private structure
+ * @param pbss_desc A pointer to BSSDescriptor_t structure
+ *
+ * @return MTRUE/MFALSE
+ */
+static int wlan_check_chan_width_ht40_by_region(mlan_private *pmpriv,
+ BSSDescriptor_t *pbss_desc)
+{
+ pmlan_adapter pmadapter = pmpriv->adapter;
+ int i = 0;
+ int cover_pri_chan = MFALSE;
+ t_u8 pri_chan;
+ t_u8 chan_offset;
+ t_u8 num_cfp;
+
+ ENTER();
+
+ if (pbss_desc->pht_info == MNULL) {
+ PRINTM(MERROR, "ht_info pointer NULL, force use HT20\n");
+ LEAVE();
+ return MFALSE;
+ }
+ if (pmpriv->curr_chan_flags & CHAN_FLAGS_NO_HT40PLUS &&
+ pmpriv->curr_chan_flags & CHAN_FLAGS_NO_HT40MINUS) {
+ LEAVE();
+ return MFALSE;
+ }
+
+ pri_chan = pbss_desc->pht_info->ht_info.pri_chan;
+ chan_offset = GET_SECONDARYCHAN(pbss_desc->pht_info->ht_info.field2);
+ if ((chan_offset == SEC_CHAN_ABOVE) &&
+ (pmpriv->curr_chan_flags & CHAN_FLAGS_NO_HT40PLUS)) {
+ pmpriv->curr_chan_flags |=
+ CHAN_FLAGS_NO_HT40MINUS | CHAN_FLAGS_NO_80MHZ;
+ return MFALSE;
+ }
+ if ((chan_offset == SEC_CHAN_BELOW) &&
+ (pmpriv->curr_chan_flags & CHAN_FLAGS_NO_HT40MINUS)) {
+ pmpriv->curr_chan_flags |=
+ CHAN_FLAGS_NO_HT40PLUS | CHAN_FLAGS_NO_80MHZ;
+ return MFALSE;
+ }
+ if (pmpriv->curr_chan_flags & CHAN_FLAGS_MAX)
+ return MTRUE;
+
+ num_cfp = pmadapter->region_channel[0].num_cfp;
+
+ if ((pbss_desc->bss_band & (BAND_B | BAND_G)) &&
+ pmadapter->region_channel[0].valid) {
+ for (i = 0; i < num_cfp; i++) {
+ if (pri_chan ==
+ pmadapter->region_channel[0].pcfp[i].channel) {
+ cover_pri_chan = MTRUE;
+ break;
+ }
+ }
+ if (!cover_pri_chan) {
+ PRINTM(MERROR, "Invalid channel, force use HT20\n");
+ LEAVE();
+ return MFALSE;
+ }
+
+ if (chan_offset == SEC_CHAN_ABOVE) {
+ if (pri_chan > num_cfp - 4) {
+ PRINTM(MERROR,
+ "Invalid second channel offset, force use HT20\n");
+ LEAVE();
+ return MFALSE;
+ }
+ }
+ }
+ LEAVE();
+ return MTRUE;
+}
+
+/**
+ * @brief This function append the 802_11N tlv
+ *
+ * @param pmpriv A pointer to mlan_private structure
+ * @param pbss_desc A pointer to BSSDescriptor_t structure
+ * @param ppbuffer A Pointer to command buffer pointer
+ *
+ * @return bytes added to the buffer
+ */
+int wlan_cmd_append_11n_tlv(mlan_private *pmpriv, BSSDescriptor_t *pbss_desc,
+ t_u8 **ppbuffer)
+{
+ pmlan_adapter pmadapter = pmpriv->adapter;
+ MrvlIETypes_HTCap_t *pht_cap;
+ MrvlIEtypes_ChanListParamSet_t *pchan_list;
+ MrvlIETypes_2040BSSCo_t *p2040_bss_co;
+ MrvlIETypes_ExtCap_t *pext_cap;
+ t_u32 usr_dot_11n_dev_cap, orig_usr_dot_11n_dev_cap = 0;
+ t_u32 usr_vht_cap_info;
+ t_u8 usr_dot_11ac_bw;
+ int ret_len = 0;
+
+ ENTER();
+
+ /* Null Checks */
+ if (ppbuffer == MNULL) {
+ LEAVE();
+ return 0;
+ }
+ if (*ppbuffer == MNULL) {
+ LEAVE();
+ return 0;
+ }
+ if (pbss_desc == MNULL) {
+ LEAVE();
+ return 0;
+ }
+
+ if (pbss_desc->bss_band & BAND_A)
+ usr_dot_11n_dev_cap = pmpriv->usr_dot_11n_dev_cap_a;
+ else
+ usr_dot_11n_dev_cap = pmpriv->usr_dot_11n_dev_cap_bg;
+
+ if (pbss_desc->bss_band & BAND_A)
+ usr_vht_cap_info = pmpriv->usr_dot_11ac_dev_cap_a;
+ else
+ usr_vht_cap_info = pmpriv->usr_dot_11ac_dev_cap_bg;
+ if (pmpriv->bss_mode == MLAN_BSS_MODE_IBSS)
+ usr_dot_11ac_bw = BW_FOLLOW_VHTCAP;
+ else
+ usr_dot_11ac_bw = pmpriv->usr_dot_11ac_bw;
+ if ((pbss_desc->bss_band & (BAND_B | BAND_G | BAND_A)) &&
+ ISSUPP_CHANWIDTH40(usr_dot_11n_dev_cap) &&
+ !wlan_check_chan_width_ht40_by_region(pmpriv, pbss_desc)) {
+ orig_usr_dot_11n_dev_cap = usr_dot_11n_dev_cap;
+ RESETSUPP_CHANWIDTH40(usr_dot_11n_dev_cap);
+ RESET_40MHZ_INTOLARENT(usr_dot_11n_dev_cap);
+ RESETSUPP_SHORTGI40(usr_dot_11n_dev_cap);
+ pmpriv->usr_dot_11n_dev_cap_bg = usr_dot_11n_dev_cap;
+ pbss_desc->curr_bandwidth = BW_20MHZ;
+ }
+ if (pbss_desc->pht_cap) {
+ pht_cap = (MrvlIETypes_HTCap_t *)*ppbuffer;
+ memset(pmadapter, pht_cap, 0, sizeof(MrvlIETypes_HTCap_t));
+ pht_cap->header.type = wlan_cpu_to_le16(HT_CAPABILITY);
+ pht_cap->header.len = sizeof(HTCap_t);
+ memcpy_ext(pmadapter,
+ (t_u8 *)pht_cap + sizeof(MrvlIEtypesHeader_t),
+ (t_u8 *)pbss_desc->pht_cap +
+ sizeof(IEEEtypes_Header_t),
+ pht_cap->header.len, pht_cap->header.len);
+
+ pht_cap->ht_cap.ht_cap_info =
+ wlan_le16_to_cpu(pht_cap->ht_cap.ht_cap_info);
+ pht_cap->ht_cap.ht_ext_cap =
+ wlan_le16_to_cpu(pht_cap->ht_cap.ht_ext_cap);
+ wlan_fill_ht_cap_tlv(pmpriv, pht_cap, pbss_desc->bss_band,
+ MTRUE);
+
+ /** check if need support 80+80MHZ */
+ /** reset the 2 spatial stream rate for 80 + 80 Mhz */
+ if (wlan_is_80_80_support(pmpriv, pbss_desc))
+ pht_cap->ht_cap.supported_mcs_set[1] = 0;
+ HEXDUMP("HT_CAPABILITIES IE", (t_u8 *)pht_cap,
+ sizeof(MrvlIETypes_HTCap_t));
+ *ppbuffer += sizeof(MrvlIETypes_HTCap_t);
+ ret_len += sizeof(MrvlIETypes_HTCap_t);
+ pht_cap->header.len = wlan_cpu_to_le16(pht_cap->header.len);
+ } else {
+ // AP don't support 11N
+ LEAVE();
+ return 0;
+ }
+
+ if (pbss_desc->pht_info) {
+ pchan_list = (MrvlIEtypes_ChanListParamSet_t *)*ppbuffer;
+ memset(pmadapter, pchan_list, 0,
+ sizeof(MrvlIEtypes_ChanListParamSet_t));
+ pchan_list->header.type = wlan_cpu_to_le16(TLV_TYPE_CHANLIST);
+ pchan_list->header.len =
+ sizeof(MrvlIEtypes_ChanListParamSet_t) -
+ sizeof(MrvlIEtypesHeader_t);
+ pchan_list->chan_scan_param[0].chan_number =
+ pbss_desc->pht_info->ht_info.pri_chan;
+ pchan_list->chan_scan_param[0].bandcfg.chanBand =
+ wlan_band_to_radio_type((t_u8)pbss_desc->bss_band);
+ /* support the VHT if the network to be join has the VHT
+ * operation */
+ if (ISSUPP_11ACENABLED(pmadapter->fw_cap_info) &&
+ (usr_dot_11ac_bw == BW_FOLLOW_VHTCAP) &&
+ (!(pmpriv->curr_chan_flags & CHAN_FLAGS_NO_80MHZ)) &&
+ wlan_11ac_bandconfig_allowed(pmpriv, pbss_desc->bss_band) &&
+ pbss_desc->pvht_oprat &&
+ pbss_desc->pvht_oprat->chan_width == VHT_OPER_CHWD_80MHZ) {
+ pchan_list->chan_scan_param[0].bandcfg.chanWidth =
+ CHAN_BW_80MHZ;
+ pchan_list->chan_scan_param[0].bandcfg.chan2Offset =
+ GET_SECONDARYCHAN(
+ pbss_desc->pht_info->ht_info.field2);
+ pbss_desc->curr_bandwidth = BW_80MHZ;
+ } else if (ISSUPP_CHANWIDTH40(usr_dot_11n_dev_cap) &&
+ ISALLOWED_CHANWIDTH40(
+ pbss_desc->pht_info->ht_info.field2) &&
+ wlan_check_chan_width_ht40_by_region(pmpriv,
+ pbss_desc)) {
+ pchan_list->chan_scan_param[0].bandcfg.chan2Offset =
+ GET_SECONDARYCHAN(
+ pbss_desc->pht_info->ht_info.field2);
+ pbss_desc->curr_bandwidth = BW_40MHZ;
+ pchan_list->chan_scan_param[0].bandcfg.chanWidth =
+ CHAN_BW_40MHZ;
+ }
+ pchan_list->chan_scan_param[0].bandcfg.scanMode =
+ SCAN_MODE_USER;
+ HEXDUMP("ChanList", (t_u8 *)pchan_list,
+ sizeof(MrvlIEtypes_ChanListParamSet_t));
+ HEXDUMP("pht_info", (t_u8 *)pbss_desc->pht_info,
+ sizeof(MrvlIETypes_HTInfo_t) - 2);
+ *ppbuffer += sizeof(MrvlIEtypes_ChanListParamSet_t);
+ ret_len += sizeof(MrvlIEtypes_ChanListParamSet_t);
+ pchan_list->header.len =
+ wlan_cpu_to_le16(pchan_list->header.len);
+ }
+
+ if (pbss_desc->pbss_co_2040) {
+ p2040_bss_co = (MrvlIETypes_2040BSSCo_t *)*ppbuffer;
+ memset(pmadapter, p2040_bss_co, 0,
+ sizeof(MrvlIETypes_2040BSSCo_t));
+ p2040_bss_co->header.type = wlan_cpu_to_le16(BSSCO_2040);
+ p2040_bss_co->header.len = sizeof(BSSCo2040_t);
+
+ memcpy_ext(pmadapter,
+ (t_u8 *)p2040_bss_co + sizeof(MrvlIEtypesHeader_t),
+ (t_u8 *)pbss_desc->pbss_co_2040 +
+ sizeof(IEEEtypes_Header_t),
+ p2040_bss_co->header.len, p2040_bss_co->header.len);
+
+ HEXDUMP("20/40 BSS Coexistence IE", (t_u8 *)p2040_bss_co,
+ sizeof(MrvlIETypes_2040BSSCo_t));
+ *ppbuffer += sizeof(MrvlIETypes_2040BSSCo_t);
+ ret_len += sizeof(MrvlIETypes_2040BSSCo_t);
+ p2040_bss_co->header.len =
+ wlan_cpu_to_le16(p2040_bss_co->header.len);
+ }
+
+ if (pbss_desc->pext_cap) {
+ pext_cap = (MrvlIETypes_ExtCap_t *)*ppbuffer;
+ memset(pmadapter, pext_cap, 0, sizeof(MrvlIETypes_ExtCap_t));
+ pext_cap->header.type = wlan_cpu_to_le16(EXT_CAPABILITY);
+ pext_cap->header.len = sizeof(ExtCap_t);
+
+ memcpy_ext(pmadapter,
+ (t_u8 *)pext_cap + sizeof(MrvlIEtypesHeader_t),
+ (t_u8 *)&pmpriv->ext_cap, sizeof(ExtCap_t),
+ pext_cap->header.len);
+ if (!pmadapter->ecsa_enable)
+ RESET_EXTCAP_EXT_CHANNEL_SWITCH(pext_cap->ext_cap);
+ else
+ SET_EXTCAP_EXT_CHANNEL_SWITCH(pext_cap->ext_cap);
+
+ HEXDUMP("Extended Capabilities IE", (t_u8 *)pext_cap,
+ sizeof(MrvlIETypes_ExtCap_t));
+ *ppbuffer += sizeof(MrvlIETypes_ExtCap_t);
+ ret_len += sizeof(MrvlIETypes_ExtCap_t);
+ pext_cap->header.len = wlan_cpu_to_le16(pext_cap->header.len);
+ } else if (wlan_is_ext_capa_support(pmpriv) ||
+ (pmpriv->config_bands & BAND_AAC)) {
+ wlan_add_ext_capa_info_ie(pmpriv, pbss_desc, ppbuffer);
+ ret_len += sizeof(MrvlIETypes_ExtCap_t);
+ }
+ PRINTM(MCMND, "curr_bandwidth=%d\n", pbss_desc->curr_bandwidth);
+ if (orig_usr_dot_11n_dev_cap)
+ pmpriv->usr_dot_11n_dev_cap_bg = orig_usr_dot_11n_dev_cap;
+
+ LEAVE();
+ return ret_len;
+}
+
+#endif /* STA_SUPPORT */
+
+/**
+ * @brief 11n configuration handler
+ *
+ * @param pmadapter A pointer to mlan_adapter structure
+ * @param pioctl_req A pointer to ioctl request buffer
+ *
+ * @return MLAN_STATUS_SUCCESS --success, otherwise fail
+ */
+mlan_status wlan_11n_cfg_ioctl(pmlan_adapter pmadapter,
+ pmlan_ioctl_req pioctl_req)
+{
+ mlan_status status = MLAN_STATUS_SUCCESS;
+ mlan_ds_11n_cfg *cfg = MNULL;
+
+ ENTER();
+
+ if (pioctl_req->buf_len < sizeof(mlan_ds_11n_cfg)) {
+ PRINTM(MINFO, "MLAN bss IOCTL length is too short.\n");
+ pioctl_req->data_read_written = 0;
+ pioctl_req->buf_len_needed = sizeof(mlan_ds_11n_cfg);
+ pioctl_req->status_code = MLAN_ERROR_INVALID_PARAMETER;
+ LEAVE();
+ return MLAN_STATUS_RESOURCE;
+ }
+ cfg = (mlan_ds_11n_cfg *)pioctl_req->pbuf;
+ switch (cfg->sub_command) {
+ case MLAN_OID_11N_CFG_TX:
+ status = wlan_11n_ioctl_httxcfg(pmadapter, pioctl_req);
+ break;
+ case MLAN_OID_11N_HTCAP_CFG:
+ status = wlan_11n_ioctl_htusrcfg(pmadapter, pioctl_req);
+ break;
+ case MLAN_OID_11N_CFG_AGGR_PRIO_TBL:
+ status = wlan_11n_ioctl_aggr_prio_tbl(pmadapter, pioctl_req);
+ break;
+ case MLAN_OID_11N_CFG_ADDBA_REJECT:
+ status = wlan_11n_ioctl_addba_reject(pmadapter, pioctl_req);
+ break;
+ case MLAN_OID_11N_CFG_ADDBA_PARAM:
+ status = wlan_11n_ioctl_addba_param(pmadapter, pioctl_req);
+ break;
+ case MLAN_OID_11N_CFG_DELBA:
+ status = wlan_11n_ioctl_delba(pmadapter, pioctl_req);
+ break;
+ case MLAN_OID_11N_CFG_REJECT_ADDBA_REQ:
+ status = wlan_11n_ioctl_rejectaddbareq(pmadapter, pioctl_req);
+ break;
+ case MLAN_OID_11N_CFG_MAX_TX_BUF_SIZE:
+ status = wlan_11n_ioctl_max_tx_buf_size(pmadapter, pioctl_req);
+ break;
+ case MLAN_OID_11N_CFG_AMSDU_AGGR_CTRL:
+ status = wlan_11n_ioctl_amsdu_aggr_ctrl(pmadapter, pioctl_req);
+ break;
+ case MLAN_OID_11N_CFG_SUPPORTED_MCS_SET:
+ status =
+ wlan_11n_ioctl_supported_mcs_set(pmadapter, pioctl_req);
+ break;
+ case MLAN_OID_11N_CFG_TX_BF_CAP:
+ status = wlan_11n_ioctl_tx_bf_cap(pmadapter, pioctl_req);
+ break;
+ case MLAN_OID_11N_CFG_TX_BF_CFG:
+ status = wlan_11n_ioctl_tx_bf_cfg(pmadapter, pioctl_req);
+ break;
+ case MLAN_OID_11N_CFG_STREAM_CFG:
+ status = wlan_11n_ioctl_stream_cfg(pmadapter, pioctl_req);
+ break;
+ case MLAN_OID_11N_CFG_COEX_RX_WINSIZE:
+ status = wlan_11n_ioctl_coex_rx_winsize(pmadapter, pioctl_req);
+ break;
+ case MLAN_OID_11N_CFG_IBSS_AMPDU_PARAM:
+ status = wlan_11n_ioctl_ibss_ampdu_param(pmadapter, pioctl_req);
+ break;
+ case MLAN_OID_11N_CFG_MIN_BA_THRESHOLD:
+ status = wlan_11n_ioctl_min_ba_threshold_cfg(pmadapter,
+ pioctl_req);
+ break;
+ default:
+ pioctl_req->status_code = MLAN_ERROR_IOCTL_INVALID;
+ status = MLAN_STATUS_FAILURE;
+ break;
+ }
+ LEAVE();
+ return status;
+}
+
+/**
+ * @brief This function will delete the given entry in Tx BA Stream table
+ *
+ * @param priv Pointer to mlan_private
+ * @param ptx_tbl Pointer to tx ba stream entry to delete
+ *
+ * @return N/A
+ */
+void wlan_11n_delete_txbastream_tbl_entry(mlan_private *priv,
+ TxBAStreamTbl *ptx_tbl)
+{
+ pmlan_adapter pmadapter = priv->adapter;
+
+ ENTER();
+
+ if (!ptx_tbl || !wlan_is_txbastreamptr_valid(priv, ptx_tbl))
+ goto exit;
+ PRINTM(MINFO, "Delete BA stream table entry: %p\n", ptx_tbl);
+ util_unlink_list(pmadapter->pmoal_handle, &priv->tx_ba_stream_tbl_ptr,
+ (pmlan_linked_list)ptx_tbl, MNULL, MNULL);
+ pmadapter->callbacks.moal_mfree(pmadapter->pmoal_handle,
+ (t_u8 *)ptx_tbl);
+exit:
+ LEAVE();
+}
+
+/**
+ * @brief This function will delete all the entries in Tx BA Stream table
+ *
+ * @param priv A pointer to mlan_private
+ *
+ * @return N/A
+ */
+void wlan_11n_deleteall_txbastream_tbl(mlan_private *priv)
+{
+ int i;
+ TxBAStreamTbl *del_tbl_ptr = MNULL;
+
+ ENTER();
+
+ wlan_request_ralist_lock(priv);
+ while ((del_tbl_ptr = (TxBAStreamTbl *)util_peek_list(
+ priv->adapter->pmoal_handle,
+ &priv->tx_ba_stream_tbl_ptr, MNULL, MNULL))) {
+ wlan_11n_delete_txbastream_tbl_entry(priv, del_tbl_ptr);
+ }
+
+ util_init_list((pmlan_linked_list)&priv->tx_ba_stream_tbl_ptr);
+ wlan_release_ralist_lock(priv);
+ for (i = 0; i < MAX_NUM_TID; ++i) {
+ priv->aggr_prio_tbl[i].ampdu_ap =
+ priv->aggr_prio_tbl[i].ampdu_user;
+ }
+
+ LEAVE();
+}
+
+/**
+ * @brief This function will return the pointer to an entry in BA Stream
+ * table which matches the give RA/TID pair
+ *
+ * @param priv A pointer to mlan_private
+ * @param tid TID to find in reordering table
+ * @param ra RA to find in reordering table
+ * @param lock flag for request the spin_lock
+ *
+ * @return A pointer to first entry matching RA/TID in BA stream
+ * NULL if not found
+ */
+TxBAStreamTbl *wlan_11n_get_txbastream_tbl(mlan_private *priv, int tid,
+ t_u8 *ra, int lock)
+{
+ TxBAStreamTbl *ptx_tbl;
+ pmlan_adapter pmadapter = priv->adapter;
+
+ ENTER();
+
+ if (lock)
+ wlan_request_ralist_lock(priv);
+ ptx_tbl = (TxBAStreamTbl *)util_peek_list(pmadapter->pmoal_handle,
+ &priv->tx_ba_stream_tbl_ptr,
+ MNULL, MNULL);
+ if (!ptx_tbl) {
+ if (lock)
+ wlan_release_ralist_lock(priv);
+ LEAVE();
+ return MNULL;
+ }
+
+ while (ptx_tbl != (TxBAStreamTbl *)&priv->tx_ba_stream_tbl_ptr) {
+ PRINTM(MDAT_D, "get_txbastream_tbl TID %d\n", ptx_tbl->tid);
+ DBG_HEXDUMP(MDAT_D, "RA", ptx_tbl->ra, MLAN_MAC_ADDR_LENGTH);
+
+ if ((!memcmp(pmadapter, ptx_tbl->ra, ra,
+ MLAN_MAC_ADDR_LENGTH)) &&
+ (ptx_tbl->tid == tid)) {
+ if (lock)
+ wlan_release_ralist_lock(priv);
+ LEAVE();
+ return ptx_tbl;
+ }
+
+ ptx_tbl = ptx_tbl->pnext;
+ }
+ if (lock)
+ wlan_release_ralist_lock(priv);
+ LEAVE();
+ return MNULL;
+}
+
+/**
+ * @brief This function will create a entry in tx ba stream table for the
+ * given RA/TID.
+ *
+ * @param priv A pointer to mlan_private
+ * @param ra RA to find in reordering table
+ * @param tid TID to find in reordering table
+ * @param ba_status BA stream status to create the stream with
+ *
+ * @return N/A
+ */
+void wlan_11n_create_txbastream_tbl(mlan_private *priv, t_u8 *ra, int tid,
+ baStatus_e ba_status)
+{
+ TxBAStreamTbl *new_node = MNULL;
+ pmlan_adapter pmadapter = priv->adapter;
+ raListTbl *ra_list = MNULL;
+ int tid_down;
+
+ ENTER();
+
+ PRINTM(MDAT_D, "create_txbastream_tbl TID %d\n", tid);
+ DBG_HEXDUMP(MDAT_D, "RA", ra, MLAN_MAC_ADDR_LENGTH);
+
+ if (pmadapter->callbacks.moal_malloc(
+ pmadapter->pmoal_handle, sizeof(TxBAStreamTbl),
+ MLAN_MEM_DEF, (t_u8 **)&new_node)) {
+ PRINTM(MERROR,
+ "wlan_11n_create_txbastream_tbl Failed to allocate new_node\n");
+ LEAVE();
+ return;
+ }
+ tid_down = wlan_get_wmm_tid_down(priv, tid);
+ ra_list = wlan_wmm_get_ralist_node(priv, tid_down, ra);
+ if (ra_list) {
+ ra_list->amsdu_in_ampdu = MFALSE;
+ ra_list->ba_status = ba_status;
+ }
+ util_init_list((pmlan_linked_list)new_node);
+
+ new_node->tid = tid;
+ new_node->ba_status = ba_status;
+ memcpy_ext(pmadapter, new_node->ra, ra, MLAN_MAC_ADDR_LENGTH,
+ MLAN_MAC_ADDR_LENGTH);
+
+ util_enqueue_list_tail(pmadapter->pmoal_handle,
+ &priv->tx_ba_stream_tbl_ptr,
+ (pmlan_linked_list)new_node, MNULL, MNULL);
+
+ LEAVE();
+}
+
+/**
+ * @brief This function will send a block ack to given tid/ra
+ *
+ * @param priv A pointer to mlan_private
+ * @param tid TID to send the ADDBA
+ * @param peer_mac MAC address to send the ADDBA
+ *
+ * @return MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ */
+int wlan_send_addba(mlan_private *priv, int tid, t_u8 *peer_mac)
+{
+ HostCmd_DS_11N_ADDBA_REQ add_ba_req;
+ static t_u8 dialog_tok;
+ mlan_status ret;
+
+ ENTER();
+
+ PRINTM(MCMND, "Send addba: TID %d\n", tid);
+ DBG_HEXDUMP(MCMD_D, "Send addba RA", peer_mac, MLAN_MAC_ADDR_LENGTH);
+
+ add_ba_req.block_ack_param_set = (t_u16)(
+ (tid << BLOCKACKPARAM_TID_POS) |
+ (priv->add_ba_param.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))
+ add_ba_req.block_ack_param_set |= BLOCKACKPARAM_AMSDU_SUPP_MASK;
+ add_ba_req.block_ack_tmo = (t_u16)priv->add_ba_param.timeout;
+
+ ++dialog_tok;
+
+ if (dialog_tok == 0)
+ dialog_tok = 1;
+
+ add_ba_req.dialog_token = dialog_tok;
+ memcpy_ext(priv->adapter, &add_ba_req.peer_mac_addr, peer_mac,
+ MLAN_MAC_ADDR_LENGTH, MLAN_MAC_ADDR_LENGTH);
+
+ /* We don't wait for the response of this command */
+ ret = wlan_prepare_cmd(priv, HostCmd_CMD_11N_ADDBA_REQ, 0, 0, MNULL,
+ &add_ba_req);
+
+ LEAVE();
+ return ret;
+}
+
+/**
+ * @brief This function will delete a block ack to given tid/ra
+ *
+ * @param priv A pointer to mlan_private
+ * @param pioctl_req A pointer to ioctl request buffer
+ * @param tid TID to send the ADDBA
+ * @param peer_mac MAC address to send the ADDBA
+ * @param initiator MTRUE if we have initiated ADDBA, MFALSE otherwise
+ *
+ * @return MLAN_STATUS_PENDING --success, otherwise fail
+ */
+int wlan_send_delba(mlan_private *priv, pmlan_ioctl_req pioctl_req, int tid,
+ t_u8 *peer_mac, int initiator)
+{
+ HostCmd_DS_11N_DELBA delba;
+ mlan_status ret;
+
+ ENTER();
+
+ memset(priv->adapter, &delba, 0, sizeof(delba));
+ delba.del_ba_param_set = (tid << DELBA_TID_POS);
+
+ if (initiator)
+ DELBA_INITIATOR(delba.del_ba_param_set);
+ else
+ DELBA_RECIPIENT(delba.del_ba_param_set);
+
+ memcpy_ext(priv->adapter, &delba.peer_mac_addr, peer_mac,
+ MLAN_MAC_ADDR_LENGTH, MLAN_MAC_ADDR_LENGTH);
+
+ ret = wlan_prepare_cmd(priv, HostCmd_CMD_11N_DELBA, HostCmd_ACT_GEN_SET,
+ 0, (t_void *)pioctl_req, (t_void *)&delba);
+
+ if (ret == MLAN_STATUS_SUCCESS)
+ ret = MLAN_STATUS_PENDING;
+
+ LEAVE();
+ return ret;
+}
+
+/**
+ * @brief This function handles the command response of
+ * delete a block ack request
+ *
+ * @param priv A pointer to mlan_private structure
+ * @param del_ba A pointer to command response buffer
+ *
+ * @return N/A
+ */
+void wlan_11n_delete_bastream(mlan_private *priv, t_u8 *del_ba)
+{
+ HostCmd_DS_11N_DELBA *pdel_ba = (HostCmd_DS_11N_DELBA *)del_ba;
+ int tid;
+
+ ENTER();
+
+ DBG_HEXDUMP(MCMD_D, "Delba:", (t_u8 *)pdel_ba, 20);
+ pdel_ba->del_ba_param_set = wlan_le16_to_cpu(pdel_ba->del_ba_param_set);
+ pdel_ba->reason_code = wlan_le16_to_cpu(pdel_ba->reason_code);
+
+ tid = pdel_ba->del_ba_param_set >> DELBA_TID_POS;
+
+ mlan_11n_delete_bastream_tbl(priv, tid, pdel_ba->peer_mac_addr,
+ TYPE_DELBA_RECEIVE,
+ INITIATOR_BIT(pdel_ba->del_ba_param_set),
+ pdel_ba->reason_code);
+
+ LEAVE();
+}
+
+/**
+ * @brief Get Rx reordering table
+ *
+ * @param priv A pointer to mlan_private structure
+ * @param buf A pointer to rx_reorder_tbl structure
+ * @return number of rx reorder table entry
+ */
+int wlan_get_rxreorder_tbl(mlan_private *priv, rx_reorder_tbl *buf)
+{
+ int i;
+ rx_reorder_tbl *ptbl = buf;
+ RxReorderTbl *rx_reorder_tbl_ptr;
+ int count = 0;
+ ENTER();
+ priv->adapter->callbacks.moal_spin_lock(priv->adapter->pmoal_handle,
+ priv->rx_reorder_tbl_ptr.plock);
+ rx_reorder_tbl_ptr =
+ (RxReorderTbl *)util_peek_list(priv->adapter->pmoal_handle,
+ &priv->rx_reorder_tbl_ptr, MNULL,
+ MNULL);
+ if (!rx_reorder_tbl_ptr) {
+ priv->adapter->callbacks.moal_spin_unlock(
+ priv->adapter->pmoal_handle,
+ priv->rx_reorder_tbl_ptr.plock);
+ LEAVE();
+ return count;
+ }
+ while (rx_reorder_tbl_ptr !=
+ (RxReorderTbl *)&priv->rx_reorder_tbl_ptr) {
+ ptbl->tid = (t_u16)rx_reorder_tbl_ptr->tid;
+ memcpy_ext(priv->adapter, ptbl->ta, rx_reorder_tbl_ptr->ta,
+ MLAN_MAC_ADDR_LENGTH, MLAN_MAC_ADDR_LENGTH);
+ ptbl->start_win = rx_reorder_tbl_ptr->start_win;
+ ptbl->win_size = rx_reorder_tbl_ptr->win_size;
+ ptbl->amsdu = rx_reorder_tbl_ptr->amsdu;
+ for (i = 0; i < rx_reorder_tbl_ptr->win_size; ++i) {
+ if (rx_reorder_tbl_ptr->rx_reorder_ptr[i])
+ ptbl->buffer[i] = MTRUE;
+ else
+ ptbl->buffer[i] = MFALSE;
+ }
+ rx_reorder_tbl_ptr = rx_reorder_tbl_ptr->pnext;
+ ptbl++;
+ count++;
+ if (count >= MLAN_MAX_RX_BASTREAM_SUPPORTED)
+ break;
+ }
+ priv->adapter->callbacks.moal_spin_unlock(
+ priv->adapter->pmoal_handle, priv->rx_reorder_tbl_ptr.plock);
+ LEAVE();
+ return count;
+}
+
+/**
+ * @brief Get transmit BA stream table
+ *
+ * @param priv A pointer to mlan_private structure
+ * @param buf A pointer to tx_ba_stream_tbl structure
+ * @return number of ba stream table entry
+ */
+int wlan_get_txbastream_tbl(mlan_private *priv, tx_ba_stream_tbl *buf)
+{
+ TxBAStreamTbl *ptxtbl;
+ tx_ba_stream_tbl *ptbl = buf;
+ int count = 0;
+ t_u32 bastream_max = 0;
+
+ ENTER();
+
+ wlan_request_ralist_lock(priv);
+ ptxtbl = (TxBAStreamTbl *)util_peek_list(priv->adapter->pmoal_handle,
+ &priv->tx_ba_stream_tbl_ptr,
+ MNULL, MNULL);
+ if (!ptxtbl) {
+ wlan_release_ralist_lock(priv);
+ LEAVE();
+ return count;
+ }
+ bastream_max = ISSUPP_GETTXBASTREAM(priv->adapter->hw_dot_11n_dev_cap);
+ if (bastream_max == 0)
+ bastream_max = MLAN_MAX_TX_BASTREAM_DEFAULT;
+
+ while (ptxtbl != (TxBAStreamTbl *)&priv->tx_ba_stream_tbl_ptr) {
+ ptbl->tid = (t_u16)ptxtbl->tid;
+ PRINTM(MINFO, "tid=%d\n", ptbl->tid);
+ memcpy_ext(priv->adapter, ptbl->ra, ptxtbl->ra,
+ MLAN_MAC_ADDR_LENGTH, MLAN_MAC_ADDR_LENGTH);
+ ptbl->amsdu = ptxtbl->amsdu;
+ ptxtbl = ptxtbl->pnext;
+ ptbl++;
+ count++;
+ if (count >= bastream_max)
+ break;
+ }
+ wlan_release_ralist_lock(priv);
+ LEAVE();
+ return count;
+}
+
+/**
+ * @brief This function check if 11AC is allowed in bandcfg
+ *
+ * @param pmpriv A pointer to mlan_private structure
+ * @param bss_band bss band
+ *
+ * @return 0--not allowed, other value allowed
+ */
+t_u8 wlan_11n_bandconfig_allowed(mlan_private *pmpriv, t_u8 bss_band)
+{
+ if (pmpriv->bss_mode == MLAN_BSS_MODE_IBSS) {
+ if (bss_band & BAND_G)
+ return (pmpriv->adapter->adhoc_start_band & BAND_GN);
+ else if (bss_band & BAND_A)
+ return (pmpriv->adapter->adhoc_start_band & BAND_AN);
+ } else {
+ if (bss_band & BAND_G)
+ return (pmpriv->config_bands & BAND_GN);
+ else if (bss_band & BAND_A)
+ return (pmpriv->config_bands & BAND_AN);
+ }
+ return 0;
+}
+
+/**
+ * @brief This function cleans up txbastream_tbl for specific station
+ *
+ * @param priv A pointer to mlan_private
+ * @param ra RA to find in txbastream_tbl
+ * @return N/A
+ */
+void wlan_11n_cleanup_txbastream_tbl(mlan_private *priv, t_u8 *ra)
+{
+ TxBAStreamTbl *ptx_tbl = MNULL;
+ t_u8 i;
+ ENTER();
+
+ wlan_request_ralist_lock(priv);
+ for (i = 0; i < MAX_NUM_TID; ++i) {
+ ptx_tbl = wlan_11n_get_txbastream_tbl(priv, i, ra, MFALSE);
+ if (ptx_tbl)
+ wlan_11n_delete_txbastream_tbl_entry(priv, ptx_tbl);
+ }
+ wlan_release_ralist_lock(priv);
+ LEAVE();
+ return;
+}
+
+void wlan_update_11n_cap(mlan_private *pmpriv)
+{
+ mlan_adapter *pmadapter = pmpriv->adapter;
+
+ pmpriv->usr_dev_mcs_support = pmadapter->hw_dev_mcs_support;
+ pmpriv->usr_dot_11n_dev_cap_bg =
+ pmadapter->hw_dot_11n_dev_cap & DEFAULT_11N_CAP_MASK_BG;
+ pmpriv->usr_dot_11n_dev_cap_a =
+ pmadapter->hw_dot_11n_dev_cap & DEFAULT_11N_CAP_MASK_A;
+}
diff --git a/drivers/net/wireless/nxp/mxm_wifiex/wlan_src/mlan/mlan_11n.h b/drivers/net/wireless/nxp/mxm_wifiex/wlan_src/mlan/mlan_11n.h
new file mode 100644
index 000000000000..9e3de59c5542
--- /dev/null
+++ b/drivers/net/wireless/nxp/mxm_wifiex/wlan_src/mlan/mlan_11n.h
@@ -0,0 +1,408 @@
+/** @file mlan_11n.h
+ *
+ * @brief Interface for the 802.11n mlan_11n module implemented in mlan_11n.c
+ *
+ * Driver interface functions and type declarations for the 11n module
+ * implemented in mlan_11n.c.
+ *
+ *
+ * Copyright 2014-2020 NXP
+ *
+ * This software file (the File) is distributed by NXP
+ * under the terms of the GNU General Public License Version 2, June 1991
+ * (the License). You may use, redistribute and/or modify the 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.
+ *
+ */
+
+/********************************************************
+Change log:
+ 12/01/2008: initial version
+********************************************************/
+
+#ifndef _MLAN_11N_H_
+#define _MLAN_11N_H_
+
+#include "mlan_11n_aggr.h"
+#include "mlan_11n_rxreorder.h"
+#include "mlan_wmm.h"
+
+/** Print the 802.11n device capability */
+void wlan_show_dot11ndevcap(pmlan_adapter pmadapter, t_u32 cap);
+/** Print the 802.11n device MCS */
+void wlan_show_devmcssupport(pmlan_adapter pmadapter, t_u8 support);
+/** Handle the command response of a delete block ack request */
+mlan_status wlan_ret_11n_delba(mlan_private *priv, HostCmd_DS_COMMAND *resp);
+/** Handle the command response of an add block ack request */
+mlan_status wlan_ret_11n_addba_req(mlan_private *priv,
+ HostCmd_DS_COMMAND *resp);
+/** Handle the command response of 11ncfg command */
+mlan_status wlan_ret_11n_cfg(pmlan_private pmpriv, HostCmd_DS_COMMAND *resp,
+ mlan_ioctl_req *pioctl_buf);
+/** Prepare 11ncfg command */
+mlan_status wlan_cmd_11n_cfg(pmlan_private pmpriv, HostCmd_DS_COMMAND *cmd,
+ t_u16 cmd_action, t_void *pdata_buf);
+/** Prepare reject addba requst command */
+mlan_status wlan_cmd_reject_addba_req(pmlan_private pmpriv,
+ HostCmd_DS_COMMAND *cmd, t_u16 cmd_action,
+ t_void *pdata_buf);
+/** Handle the command response of rejecting addba request */
+mlan_status wlan_ret_reject_addba_req(pmlan_private pmpriv,
+ HostCmd_DS_COMMAND *resp,
+ mlan_ioctl_req *pioctl_buf);
+/** Prepare TX BF configuration command */
+mlan_status wlan_cmd_tx_bf_cfg(pmlan_private pmpriv, HostCmd_DS_COMMAND *cmd,
+ t_u16 cmd_action, t_void *pdata_buf);
+/** Handle the command response TX BF configuration */
+mlan_status wlan_ret_tx_bf_cfg(pmlan_private pmpriv, HostCmd_DS_COMMAND *resp,
+ mlan_ioctl_req *pioctl_buf);
+#ifdef STA_SUPPORT
+t_u8 wlan_11n_bandconfig_allowed(mlan_private *pmpriv, t_u8 bss_band);
+/** Append the 802_11N tlv */
+int wlan_cmd_append_11n_tlv(mlan_private *pmpriv, BSSDescriptor_t *pbss_desc,
+ t_u8 **ppbuffer);
+/** wlan fill HT cap tlv */
+void wlan_fill_ht_cap_tlv(mlan_private *priv, MrvlIETypes_HTCap_t *pht_cap,
+ t_u16 band, t_u8 fill);
+/** wlan fill HT cap IE */
+void wlan_fill_ht_cap_ie(mlan_private *priv, IEEEtypes_HTCap_t *pht_cap,
+ t_u16 bands);
+#endif /* STA_SUPPORT */
+/** Miscellaneous configuration handler */
+mlan_status wlan_11n_cfg_ioctl(pmlan_adapter pmadapter,
+ pmlan_ioctl_req pioctl_req);
+/** Delete Tx BA stream table entry */
+void wlan_11n_delete_txbastream_tbl_entry(mlan_private *priv,
+ TxBAStreamTbl *ptx_tbl);
+/** Delete all Tx BA stream table entries */
+void wlan_11n_deleteall_txbastream_tbl(mlan_private *priv);
+/** Get Tx BA stream table */
+TxBAStreamTbl *wlan_11n_get_txbastream_tbl(mlan_private *priv, int tid,
+ t_u8 *ra, int lock);
+/** Create Tx BA stream table */
+void wlan_11n_create_txbastream_tbl(mlan_private *priv, t_u8 *ra, int tid,
+ baStatus_e ba_status);
+/** Send ADD BA request */
+int wlan_send_addba(mlan_private *priv, int tid, t_u8 *peer_mac);
+/** Send DEL BA request */
+int wlan_send_delba(mlan_private *priv, pmlan_ioctl_req pioctl_req, int tid,
+ t_u8 *peer_mac, int initiator);
+/** This function handles the command response of delete a block ack request*/
+void wlan_11n_delete_bastream(mlan_private *priv, t_u8 *del_ba);
+/** get rx reorder table */
+int wlan_get_rxreorder_tbl(mlan_private *priv, rx_reorder_tbl *buf);
+/** get tx ba stream table */
+int wlan_get_txbastream_tbl(mlan_private *priv, tx_ba_stream_tbl *buf);
+/** send delba */
+void wlan_11n_delba(mlan_private *priv, int tid);
+/** update amdpdu tx win size */
+void wlan_update_ampdu_txwinsize(pmlan_adapter pmadapter);
+/** Minimum number of AMSDU */
+#define MIN_NUM_AMSDU 2
+/** AMSDU Aggr control cmd resp */
+mlan_status wlan_ret_amsdu_aggr_ctrl(pmlan_private pmpriv,
+ HostCmd_DS_COMMAND *resp,
+ mlan_ioctl_req *pioctl_buf);
+void wlan_set_tx_pause_flag(mlan_private *priv, t_u8 flag);
+/** reconfigure tx buf size */
+mlan_status wlan_cmd_recfg_tx_buf(mlan_private *priv, HostCmd_DS_COMMAND *cmd,
+ int cmd_action, void *pdata_buf);
+/** AMSDU aggr control cmd */
+mlan_status wlan_cmd_amsdu_aggr_ctrl(mlan_private *priv,
+ HostCmd_DS_COMMAND *cmd, int cmd_action,
+ void *pdata_buf);
+
+t_u8 wlan_validate_chan_offset(mlan_private *pmpriv, t_u16 band, t_u32 chan,
+ t_u8 chan_bw);
+/** get channel offset */
+t_u8 wlan_get_second_channel_offset(int chan);
+
+void wlan_update_11n_cap(mlan_private *pmpriv);
+
+/** clean up txbastream_tbl */
+void wlan_11n_cleanup_txbastream_tbl(mlan_private *priv, t_u8 *ra);
+/**
+ * @brief This function checks whether a station has 11N enabled or not
+ *
+ * @param priv A pointer to mlan_private
+ * @param mac station mac address
+ * @return MTRUE or MFALSE
+ */
+static INLINE t_u8 is_station_11n_enabled(mlan_private *priv, t_u8 *mac)
+{
+ sta_node *sta_ptr = MNULL;
+ sta_ptr = wlan_get_station_entry(priv, mac);
+ if (sta_ptr)
+ return (sta_ptr->is_11n_enabled) ? MTRUE : MFALSE;
+ return MFALSE;
+}
+
+/**
+ * @brief This function get station max amsdu size
+ *
+ * @param priv A pointer to mlan_private
+ * @param mac station mac address
+ * @return max amsdu size statio supported
+ */
+static INLINE t_u16 get_station_max_amsdu_size(mlan_private *priv, t_u8 *mac)
+{
+ sta_node *sta_ptr = MNULL;
+ sta_ptr = wlan_get_station_entry(priv, mac);
+ if (sta_ptr)
+ return sta_ptr->max_amsdu;
+ return 0;
+}
+
+/**
+ * @brief This function checks whether a station allows AMPDU or not
+ *
+ * @param priv A pointer to mlan_private
+ * @param ptr A pointer to RA list table
+ * @param tid TID value for ptr
+ * @return MTRUE or MFALSE
+ */
+static INLINE t_u8 is_station_ampdu_allowed(mlan_private *priv, raListTbl *ptr,
+ int tid)
+{
+ sta_node *sta_ptr = MNULL;
+ sta_ptr = wlan_get_station_entry(priv, ptr->ra);
+ if (sta_ptr) {
+ if (GET_BSS_ROLE(priv) == MLAN_BSS_ROLE_UAP) {
+ if (priv->sec_info.wapi_enabled &&
+ !sta_ptr->wapi_key_on)
+ return MFALSE;
+ }
+ return (sta_ptr->ampdu_sta[tid] != BA_STREAM_NOT_ALLOWED) ?
+ MTRUE :
+ MFALSE;
+ }
+ return MFALSE;
+}
+
+/**
+ * @brief This function disable station ampdu for specific tid
+ *
+ * @param priv A pointer to mlan_private
+ * @param tid tid index
+ * @param ra station mac address
+ * @return N/A
+ */
+static INLINE void disable_station_ampdu(mlan_private *priv, t_u8 tid, t_u8 *ra)
+{
+ sta_node *sta_ptr = MNULL;
+ sta_ptr = wlan_get_station_entry(priv, ra);
+ if (sta_ptr)
+ sta_ptr->ampdu_sta[tid] = BA_STREAM_NOT_ALLOWED;
+ return;
+}
+
+/**
+ * @brief This function reset station ampdu for specific id to user setting.
+ *
+ * @param priv A pointer to mlan_private
+ * @param tid tid index
+ * @param ra station mac address
+ * @return N/A
+ */
+static INLINE void reset_station_ampdu(mlan_private *priv, t_u8 tid, t_u8 *ra)
+{
+ sta_node *sta_ptr = MNULL;
+ sta_ptr = wlan_get_station_entry(priv, ra);
+ if (sta_ptr)
+ sta_ptr->ampdu_sta[tid] = priv->aggr_prio_tbl[tid].ampdu_user;
+ return;
+}
+
+#define IS_BG_RATE (priv->bitmap_rates[0] || priv->bitmap_rates[1])
+/**
+ * @brief This function checks whether AMPDU is allowed or not
+ *
+ * @param priv A pointer to mlan_private
+ * @param ptr A pointer to RA list table
+ * @param tid TID value for ptr
+ *
+ * @return MTRUE or MFALSE
+ */
+static INLINE t_u8 wlan_is_ampdu_allowed(mlan_private *priv, raListTbl *ptr,
+ int tid)
+{
+ if ((!priv->is_data_rate_auto) && IS_BG_RATE)
+ return MFALSE;
+#ifdef UAP_SUPPORT
+ if (GET_BSS_ROLE(priv) == MLAN_BSS_ROLE_UAP)
+ return is_station_ampdu_allowed(priv, ptr, tid);
+#endif /* UAP_SUPPORT */
+ if (priv->sec_info.wapi_enabled && !priv->sec_info.wapi_key_on)
+ return MFALSE;
+ return (priv->aggr_prio_tbl[tid].ampdu_ap != BA_STREAM_NOT_ALLOWED) ?
+ MTRUE :
+ MFALSE;
+}
+
+#define BA_RSSI_HIGH_THRESHOLD -70
+
+static INLINE void wlan_update_station_del_ba_count(mlan_private *priv,
+ raListTbl *ptr)
+{
+ sta_node *sta_ptr = MNULL;
+ t_s8 rssi;
+ sta_ptr = wlan_get_station_entry(priv, ptr->ra);
+ if (sta_ptr) {
+ rssi = sta_ptr->snr - sta_ptr->nf;
+ if (rssi > BA_RSSI_HIGH_THRESHOLD)
+ ptr->del_ba_count = 0;
+ }
+ return;
+}
+
+static INLINE void wlan_update_del_ba_count(mlan_private *priv, raListTbl *ptr)
+{
+ t_s8 rssi;
+#ifdef UAP_802_11N
+#ifdef UAP_SUPPORT
+ if (GET_BSS_ROLE(priv) == MLAN_BSS_ROLE_UAP)
+ return wlan_update_station_del_ba_count(priv, ptr);
+#endif /* UAP_SUPPORT */
+#endif /* UAP_802_11N */
+ rssi = priv->snr - priv->nf;
+ if (rssi > BA_RSSI_HIGH_THRESHOLD)
+ ptr->del_ba_count = 0;
+}
+
+/**
+ * @brief This function checks whether AMSDU is allowed or not
+ *
+ * @param priv A pointer to mlan_private
+ * @param ptr A pointer to RA list table
+ * @param tid TID value for ptr
+ *
+ * @return MTRUE or MFALSE
+ */
+static INLINE t_u8 wlan_is_amsdu_allowed(mlan_private *priv, raListTbl *ptr,
+ int tid)
+{
+#ifdef UAP_SUPPORT
+ sta_node *sta_ptr = MNULL;
+#endif
+ if (priv->amsdu_disable)
+ return MFALSE;
+#ifdef UAP_SUPPORT
+ if (GET_BSS_ROLE(priv) == MLAN_BSS_ROLE_UAP) {
+ sta_ptr = wlan_get_station_entry(priv, ptr->ra);
+ if (sta_ptr) {
+ if (priv->sec_info.wapi_enabled &&
+ !sta_ptr->wapi_key_on)
+ return MFALSE;
+ }
+ }
+#endif /* UAP_SUPPORT */
+#define TXRATE_BITMAP_INDEX_MCS0_7 2
+ return ((priv->aggr_prio_tbl[tid].amsdu != BA_STREAM_NOT_ALLOWED) &&
+ ((priv->is_data_rate_auto) ||
+ !(((priv->bitmap_rates[TXRATE_BITMAP_INDEX_MCS0_7]) & 0x03) ||
+ IS_BG_RATE))) ?
+ MTRUE :
+ MFALSE;
+}
+
+/**
+ * @brief This function checks whether a BA stream is available or not
+ *
+ * @param priv A pointer to mlan_private
+ *
+ * @return MTRUE or MFALSE
+ */
+static INLINE t_u8 wlan_is_bastream_avail(mlan_private *priv)
+{
+ mlan_private *pmpriv = MNULL;
+ t_u8 i = 0;
+ t_u32 bastream_num = 0;
+ t_u32 bastream_max = 0;
+ for (i = 0; i < priv->adapter->priv_num; i++) {
+ pmpriv = priv->adapter->priv[i];
+ if (pmpriv)
+ bastream_num += wlan_wmm_list_len(
+ (pmlan_list_head)&pmpriv->tx_ba_stream_tbl_ptr);
+ }
+ bastream_max = ISSUPP_GETTXBASTREAM(priv->adapter->hw_dot_11n_dev_cap);
+ if (bastream_max == 0)
+ bastream_max = MLAN_MAX_TX_BASTREAM_DEFAULT;
+ return (bastream_num < bastream_max) ? MTRUE : MFALSE;
+}
+
+/**
+ * @brief This function finds the stream to delete
+ *
+ * @param priv A pointer to mlan_private
+ * @param ptr A pointer to RA list table
+ * @param ptr_tid TID value of ptr
+ * @param ptid A pointer to TID of stream to delete, if return MTRUE
+ * @param ra RA of stream to delete, if return MTRUE
+ *
+ * @return MTRUE or MFALSE
+ */
+static INLINE t_u8 wlan_find_stream_to_delete(mlan_private *priv,
+ raListTbl *ptr, int ptr_tid,
+ int *ptid, t_u8 *ra)
+{
+ int tid;
+ t_u8 ret = MFALSE;
+ TxBAStreamTbl *ptx_tbl;
+
+ ENTER();
+
+ ptx_tbl = (TxBAStreamTbl *)util_peek_list(priv->adapter->pmoal_handle,
+ &priv->tx_ba_stream_tbl_ptr,
+ MNULL, MNULL);
+ if (!ptx_tbl) {
+ LEAVE();
+ return ret;
+ }
+
+ tid = priv->aggr_prio_tbl[ptr_tid].ampdu_user;
+
+ while (ptx_tbl != (TxBAStreamTbl *)&priv->tx_ba_stream_tbl_ptr) {
+ if (tid > priv->aggr_prio_tbl[ptx_tbl->tid].ampdu_user) {
+ tid = priv->aggr_prio_tbl[ptx_tbl->tid].ampdu_user;
+ *ptid = ptx_tbl->tid;
+ memcpy_ext(priv->adapter, ra, ptx_tbl->ra,
+ MLAN_MAC_ADDR_LENGTH, MLAN_MAC_ADDR_LENGTH);
+ ret = MTRUE;
+ }
+
+ ptx_tbl = ptx_tbl->pnext;
+ }
+ LEAVE();
+ return ret;
+}
+
+/**
+ * @brief This function checks whether 11n is supported
+ *
+ * @param priv A pointer to mlan_private
+ * @param ra Address of the receiver STA
+ *
+ * @return MTRUE or MFALSE
+ */
+static INLINE int wlan_is_11n_enabled(mlan_private *priv, t_u8 *ra)
+{
+ int ret = MFALSE;
+ ENTER();
+#ifdef UAP_SUPPORT
+ if (GET_BSS_ROLE(priv) == MLAN_BSS_ROLE_UAP) {
+ if ((!(ra[0] & 0x01)) && (priv->is_11n_enabled))
+ ret = is_station_11n_enabled(priv, ra);
+ }
+#endif /* UAP_SUPPORT */
+ LEAVE();
+ return ret;
+}
+#endif /* !_MLAN_11N_H_ */
diff --git a/drivers/net/wireless/nxp/mxm_wifiex/wlan_src/mlan/mlan_11n_aggr.c b/drivers/net/wireless/nxp/mxm_wifiex/wlan_src/mlan/mlan_11n_aggr.c
new file mode 100644
index 000000000000..17cd78d02eb0
--- /dev/null
+++ b/drivers/net/wireless/nxp/mxm_wifiex/wlan_src/mlan/mlan_11n_aggr.c
@@ -0,0 +1,603 @@
+/** @file mlan_11n_aggr.c
+ *
+ * @brief This file contains functions for 11n Aggregation.
+ *
+ *
+ * Copyright 2014-2020 NXP
+ *
+ * This software file (the File) is distributed by NXP
+ * under the terms of the GNU General Public License Version 2, June 1991
+ * (the License). You may use, redistribute and/or modify the 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.
+ *
+ */
+
+/********************************************************
+Change log:
+ 11/10/2008: initial version
+********************************************************/
+
+#include "mlan.h"
+#include "mlan_join.h"
+#include "mlan_util.h"
+#include "mlan_fw.h"
+#include "mlan_main.h"
+#include "mlan_wmm.h"
+#include "mlan_11n.h"
+#include "mlan_11n_aggr.h"
+
+/********************************************************
+ Local Variables
+********************************************************/
+
+/********************************************************
+ Global Variables
+********************************************************/
+
+/********************************************************
+ Local Functions
+********************************************************/
+/**
+ * @brief Aggregate individual packets into one AMSDU packet
+ *
+ * @param pmadapter A pointer to mlan_adapter structure
+ * @param amsdu_buf A pointer to packet buffer
+ * @param data A pointer to aggregated data packet being formed
+ * @param pkt_len Length of current packet to aggregate
+ * @param pad Pad
+ *
+ * @return Final packet size
+ */
+static int wlan_11n_form_amsdu_pkt(pmlan_adapter pmadapter, t_u8 *amsdu_buf,
+ t_u8 *data, int pkt_len, int *pad)
+{
+ int dt_offset, amsdu_buf_offset;
+ Rfc1042Hdr_t 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
+ */
+ };
+
+ ENTER();
+
+ memcpy_ext(pmadapter, amsdu_buf, data, (MLAN_MAC_ADDR_LENGTH)*2,
+ (MLAN_MAC_ADDR_LENGTH)*2);
+ dt_offset = amsdu_buf_offset = (MLAN_MAC_ADDR_LENGTH)*2;
+
+ snap.snap_type = *(t_u16 *)(data + dt_offset);
+ dt_offset += sizeof(t_u16);
+ *(t_u16 *)(amsdu_buf + amsdu_buf_offset) =
+ mlan_htons(pkt_len + LLC_SNAP_LEN -
+ ((2 * MLAN_MAC_ADDR_LENGTH) + sizeof(t_u16)));
+ amsdu_buf_offset += sizeof(t_u16);
+ memcpy_ext(pmadapter, amsdu_buf + amsdu_buf_offset, &snap, LLC_SNAP_LEN,
+ LLC_SNAP_LEN);
+ amsdu_buf_offset += LLC_SNAP_LEN;
+
+ memcpy_ext(pmadapter, amsdu_buf + amsdu_buf_offset, data + dt_offset,
+ pkt_len - dt_offset, pkt_len - dt_offset);
+ *pad = (((pkt_len + LLC_SNAP_LEN) & 3)) ?
+ (4 - (((pkt_len + LLC_SNAP_LEN)) & 3)) :
+ 0;
+
+ LEAVE();
+ return pkt_len + LLC_SNAP_LEN + *pad;
+}
+
+/**
+ * @brief Add TxPD to AMSDU header
+ *
+ * @param priv A pointer to mlan_private structure
+ * @param mbuf Pointer to buffer where the TxPD will be formed
+ *
+ * @return N/A
+ */
+static void wlan_11n_form_amsdu_txpd(mlan_private *priv, mlan_buffer *mbuf)
+{
+ TxPD *ptx_pd;
+ mlan_adapter *pmadapter = priv->adapter;
+
+ ENTER();
+
+ ptx_pd = (TxPD *)mbuf->pbuf;
+ memset(pmadapter, ptx_pd, 0, sizeof(TxPD));
+
+ /*
+ * Original priority has been overwritten
+ */
+ ptx_pd->priority = (t_u8)mbuf->priority;
+ ptx_pd->pkt_delay_2ms =
+ wlan_wmm_compute_driver_packet_delay(priv, mbuf);
+ ptx_pd->bss_num = GET_BSS_NUM(priv);
+ ptx_pd->bss_type = priv->bss_type;
+ /* Always zero as the data is followed by TxPD */
+ ptx_pd->tx_pkt_offset = sizeof(TxPD);
+ ptx_pd->tx_pkt_type = PKT_TYPE_AMSDU;
+ if (ptx_pd->tx_control == 0)
+ /* TxCtrl set by user or default */
+ ptx_pd->tx_control = priv->pkt_tx_ctrl;
+
+ endian_convert_TxPD(ptx_pd);
+
+ LEAVE();
+}
+
+/**
+ * @brief Update the TxPktLength field in TxPD after the complete AMSDU
+ * packet is formed
+ *
+ * @param priv A pointer to mlan_private structure
+ * @param mbuf TxPD buffer
+ *
+ * @return N/A
+ */
+static INLINE void wlan_11n_update_pktlen_amsdu_txpd(mlan_private *priv,
+ pmlan_buffer mbuf)
+{
+ TxPD *ptx_pd;
+ ENTER();
+
+ ptx_pd = (TxPD *)mbuf->pbuf;
+ ptx_pd->tx_pkt_length =
+ (t_u16)wlan_cpu_to_le16(mbuf->data_len - sizeof(TxPD));
+#ifdef STA_SUPPORT
+ if ((GET_BSS_ROLE(priv) == MLAN_BSS_ROLE_STA) &&
+ (priv->adapter->pps_uapsd_mode)) {
+ if (MTRUE == wlan_check_last_packet_indication(priv)) {
+ priv->adapter->tx_lock_flag = MTRUE;
+ ptx_pd->flags |= MRVDRV_TxPD_POWER_MGMT_LAST_PACKET;
+ }
+ }
+#endif /* STA_SUPPORT */
+ LEAVE();
+}
+
+/**
+ * @brief Get number of aggregated packets
+ *
+ * @param data A pointer to packet data
+ * @param total_pkt_len Total packet length
+ *
+ * @return Number of packets
+ */
+static int wlan_11n_get_num_aggrpkts(t_u8 *data, int total_pkt_len)
+{
+ int pkt_count = 0, pkt_len, pad;
+ t_u8 hdr_len = sizeof(Eth803Hdr_t);
+
+ ENTER();
+ while (total_pkt_len >= hdr_len) {
+ /* Length will be in network format, change it to host */
+ pkt_len = mlan_ntohs(
+ (*(t_u16 *)(data + (2 * MLAN_MAC_ADDR_LENGTH))));
+ if (pkt_len > total_pkt_len) {
+ PRINTM(MERROR, "Error in packet length.\n");
+ break;
+ }
+
+ pad = (((pkt_len + sizeof(Eth803Hdr_t)) & 3)) ?
+ (4 - ((pkt_len + sizeof(Eth803Hdr_t)) & 3)) :
+ 0;
+ data += pkt_len + pad + sizeof(Eth803Hdr_t);
+ total_pkt_len -= pkt_len + pad + sizeof(Eth803Hdr_t);
+ ++pkt_count;
+ }
+ LEAVE();
+ return pkt_count;
+}
+
+/********************************************************
+ Global Functions
+********************************************************/
+
+/**
+ * @brief Deaggregate the received AMSDU packet
+ *
+ * @param priv A pointer to mlan_private structure
+ * @param pmbuf A pointer to aggregated data packet
+ *
+ * @return MLAN_STATUS_SUCCESS --success, otherwise fail
+ */
+mlan_status wlan_11n_deaggregate_pkt(mlan_private *priv, pmlan_buffer pmbuf)
+{
+ t_u16 pkt_len;
+ int total_pkt_len;
+ t_u8 *data;
+ mlan_adapter *pmadapter = priv->adapter;
+ t_u32 max_rx_data_size = MLAN_RX_DATA_BUF_SIZE;
+ int pad;
+ mlan_status ret = MLAN_STATUS_FAILURE;
+ RxPacketHdr_t *prx_pkt;
+ mlan_buffer *daggr_mbuf = MNULL;
+ t_u8 rfc1042_eth_hdr[MLAN_MAC_ADDR_LENGTH] = {0xaa, 0xaa, 0x03,
+ 0x00, 0x00, 0x00};
+ t_u8 hdr_len = sizeof(Eth803Hdr_t);
+ t_u8 eapol_type[2] = {0x88, 0x8e};
+
+ ENTER();
+
+ data = (t_u8 *)(pmbuf->pbuf + pmbuf->data_offset);
+ total_pkt_len = pmbuf->data_len;
+
+ /* Sanity test */
+#if defined(USB)
+ if (IS_USB(pmadapter->card_type) &&
+ pmadapter->pcard_usb->usb_rx_deaggr.aggr_ctrl.enable) {
+ max_rx_data_size =
+ pmadapter->pcard_usb->usb_rx_deaggr.aggr_ctrl.aggr_max;
+ if (pmadapter->pcard_usb->usb_rx_deaggr.aggr_ctrl.aggr_mode ==
+ MLAN_USB_AGGR_MODE_NUM) {
+ max_rx_data_size *=
+ MAX(MLAN_USB_MAX_PKT_SIZE,
+ pmadapter->pcard_usb->usb_rx_deaggr
+ .aggr_ctrl.aggr_align);
+ max_rx_data_size =
+ MAX(max_rx_data_size, MLAN_RX_DATA_BUF_SIZE);
+ }
+ }
+#endif
+ if (total_pkt_len > max_rx_data_size) {
+ PRINTM(MERROR,
+ "Total packet length greater than tx buffer"
+ " size %d\n",
+ total_pkt_len);
+ goto done;
+ }
+
+ pmbuf->use_count = wlan_11n_get_num_aggrpkts(data, total_pkt_len);
+
+ // rx_trace 7
+ if (pmadapter->tp_state_on)
+ pmadapter->callbacks.moal_tp_accounting(
+ pmadapter->pmoal_handle, pmbuf, 7 /*RX_DROP_P3*/);
+ if (pmadapter->tp_state_drop_point == 7 /*RX_DROP_P3*/)
+ goto done;
+
+ while (total_pkt_len >= hdr_len) {
+ prx_pkt = (RxPacketHdr_t *)data;
+ /* Length will be in network format, change it to host */
+ pkt_len = mlan_ntohs(
+ (*(t_u16 *)(data + (2 * MLAN_MAC_ADDR_LENGTH))));
+ if (pkt_len > total_pkt_len) {
+ PRINTM(MERROR,
+ "Error in packet length: total_pkt_len = %d, pkt_len = %d\n",
+ total_pkt_len, pkt_len);
+ ret = MLAN_STATUS_FAILURE;
+ break;
+ }
+
+ pad = (((pkt_len + sizeof(Eth803Hdr_t)) & 3)) ?
+ (4 - ((pkt_len + sizeof(Eth803Hdr_t)) & 3)) :
+ 0;
+
+ total_pkt_len -= pkt_len + pad + sizeof(Eth803Hdr_t);
+
+ if (memcmp(pmadapter, &prx_pkt->rfc1042_hdr, rfc1042_eth_hdr,
+ sizeof(rfc1042_eth_hdr)) == 0) {
+ memmove(pmadapter, data + LLC_SNAP_LEN, data,
+ (2 * MLAN_MAC_ADDR_LENGTH));
+ data += LLC_SNAP_LEN;
+ pkt_len += sizeof(Eth803Hdr_t) - LLC_SNAP_LEN;
+ } else {
+ *(t_u16 *)(data + (2 * MLAN_MAC_ADDR_LENGTH)) =
+ (t_u16)0;
+ pkt_len += sizeof(Eth803Hdr_t);
+ }
+ daggr_mbuf = wlan_alloc_mlan_buffer(pmadapter,
+ pkt_len + MLAN_NET_IP_ALIGN,
+ 0, MOAL_ALLOC_MLAN_BUFFER);
+ if (daggr_mbuf == MNULL) {
+ PRINTM(MERROR, "Error allocating daggr mlan_buffer\n");
+ ret = MLAN_STATUS_FAILURE;
+ break;
+ }
+ daggr_mbuf->data_offset += MLAN_NET_IP_ALIGN;
+ daggr_mbuf->bss_index = pmbuf->bss_index;
+ daggr_mbuf->buf_type = pmbuf->buf_type;
+ daggr_mbuf->data_len = pkt_len;
+ daggr_mbuf->in_ts_sec = pmbuf->in_ts_sec;
+ daggr_mbuf->in_ts_usec = pmbuf->in_ts_usec;
+ daggr_mbuf->pparent = pmbuf;
+ daggr_mbuf->priority = pmbuf->priority;
+ memcpy_ext(pmadapter,
+ daggr_mbuf->pbuf + daggr_mbuf->data_offset, data,
+ pkt_len, daggr_mbuf->data_len);
+
+#ifdef UAP_SUPPORT
+ if (GET_BSS_ROLE(priv) == MLAN_BSS_ROLE_UAP) {
+ ret = wlan_uap_recv_packet(priv, daggr_mbuf);
+ } else {
+#endif /* UAP_SUPPORT */
+ /** send EAPOL from AMSDU pkt to firmware */
+ if (priv->sec_info.ewpa_enabled &&
+ (!memcmp(pmadapter,
+ daggr_mbuf->pbuf +
+ daggr_mbuf->data_offset +
+ MLAN_ETHER_PKT_TYPE_OFFSET,
+ eapol_type, sizeof(eapol_type)))) {
+ ret = wlan_prepare_cmd(
+ priv, HostCmd_CMD_802_11_EAPOL_PKT, 0,
+ 0, MNULL, daggr_mbuf);
+ if (ret == MLAN_STATUS_SUCCESS)
+ wlan_recv_event(
+ priv,
+ MLAN_EVENT_ID_DRV_DEFER_HANDLING,
+ MNULL);
+ wlan_free_mlan_buffer(pmadapter, daggr_mbuf);
+ data += pkt_len + pad;
+ continue;
+ }
+
+ ret = pmadapter->callbacks.moal_recv_packet(
+ pmadapter->pmoal_handle, daggr_mbuf);
+#ifdef UAP_SUPPORT
+ }
+#endif /* UAP_SUPPORT */
+ switch (ret) {
+ case MLAN_STATUS_PENDING:
+ break;
+ case MLAN_STATUS_FAILURE:
+ PRINTM(MERROR, "Deaggr, send to moal failed\n");
+ daggr_mbuf->status_code = MLAN_ERROR_PKT_INVALID;
+ /* fall through */
+ case MLAN_STATUS_SUCCESS:
+ wlan_recv_packet_complete(pmadapter, daggr_mbuf, ret);
+ break;
+ default:
+ break;
+ }
+
+ data += pkt_len + pad;
+ }
+
+done:
+ priv->msdu_in_rx_amsdu_cnt += pmbuf->use_count;
+ priv->amsdu_rx_cnt++;
+ /** we should free the aggr buffer after deaggr */
+ pmadapter->ops.data_complete(pmadapter, pmbuf, ret);
+ LEAVE();
+ return ret;
+}
+
+/**
+ * @brief Aggregate multiple packets into one single AMSDU packet
+ *
+ * @param priv A pointer to mlan_private structure
+ * @param pra_list Pointer to the RA List table containing the pointers
+ * to packets.
+ * @param headroom Any interface specific headroom that may be need. TxPD
+ * will be formed leaving this headroom.
+ * @param ptrindex Pointer index
+ *
+ * @return Final packet size or MLAN_STATUS_FAILURE
+ */
+int wlan_11n_aggregate_pkt(mlan_private *priv, raListTbl *pra_list,
+ int headroom, int ptrindex)
+{
+ int pkt_size = 0;
+ pmlan_adapter pmadapter = priv->adapter;
+ mlan_buffer *pmbuf_aggr, *pmbuf_src;
+ t_u8 *data;
+ int pad = 0;
+ mlan_status ret = MLAN_STATUS_SUCCESS;
+#ifdef DEBUG_LEVEL1
+ t_u32 sec = 0, usec = 0;
+#endif
+ mlan_tx_param tx_param;
+#ifdef STA_SUPPORT
+ TxPD *ptx_pd = MNULL;
+#endif
+ t_u32 max_amsdu_size = MIN(pra_list->max_amsdu, pmadapter->tx_buf_size);
+ ENTER();
+
+ PRINTM(MDAT_D, "Handling Aggr packet\n");
+
+ pmbuf_src = (pmlan_buffer)util_peek_list(
+ pmadapter->pmoal_handle, &pra_list->buf_head, MNULL, MNULL);
+ if (pmbuf_src) {
+ pmbuf_aggr = wlan_alloc_mlan_buffer(pmadapter,
+ pmadapter->tx_buf_size, 0,
+ MOAL_MALLOC_BUFFER);
+ if (!pmbuf_aggr) {
+ PRINTM(MERROR, "Error allocating mlan_buffer\n");
+ pmadapter->callbacks.moal_spin_unlock(
+ pmadapter->pmoal_handle,
+ priv->wmm.ra_list_spinlock);
+ LEAVE();
+ return MLAN_STATUS_FAILURE;
+ }
+
+ data = pmbuf_aggr->pbuf + headroom;
+ pmbuf_aggr->bss_index = pmbuf_src->bss_index;
+ pmbuf_aggr->buf_type = pmbuf_src->buf_type;
+ pmbuf_aggr->priority = pmbuf_src->priority;
+ pmbuf_aggr->pbuf = data;
+ pmbuf_aggr->data_offset = 0;
+ pmbuf_aggr->in_ts_sec = pmbuf_src->in_ts_sec;
+ pmbuf_aggr->in_ts_usec = pmbuf_src->in_ts_usec;
+ if (pmbuf_src->flags & MLAN_BUF_FLAG_TCP_ACK)
+ pmbuf_aggr->flags |= MLAN_BUF_FLAG_TCP_ACK;
+
+ /* Form AMSDU */
+ wlan_11n_form_amsdu_txpd(priv, pmbuf_aggr);
+ pkt_size = sizeof(TxPD);
+#ifdef STA_SUPPORT
+ if (GET_BSS_ROLE(priv) == MLAN_BSS_ROLE_STA)
+ ptx_pd = (TxPD *)pmbuf_aggr->pbuf;
+#endif
+ priv->msdu_in_tx_amsdu_cnt++;
+ } else {
+ pmadapter->callbacks.moal_spin_unlock(
+ pmadapter->pmoal_handle, priv->wmm.ra_list_spinlock);
+ goto exit;
+ }
+
+ while (pmbuf_src && ((pkt_size + (pmbuf_src->data_len + LLC_SNAP_LEN) +
+ headroom) <= max_amsdu_size)) {
+ pmbuf_src =
+ (pmlan_buffer)util_dequeue_list(pmadapter->pmoal_handle,
+ &pra_list->buf_head,
+ MNULL, MNULL);
+ /* Collects TP statistics */
+ if (pmadapter->tp_state_on && (pkt_size > sizeof(TxPD)))
+ pmadapter->callbacks.moal_tp_accounting(
+ pmadapter->pmoal_handle, pmbuf_src->pdesc, 3);
+ pra_list->total_pkts--;
+
+ /* decrement for every PDU taken from the list */
+ priv->wmm.pkts_queued[ptrindex]--;
+ util_scalar_decrement(pmadapter->pmoal_handle,
+ &priv->wmm.tx_pkts_queued, MNULL, MNULL);
+
+ pmadapter->callbacks.moal_spin_unlock(
+ pmadapter->pmoal_handle, priv->wmm.ra_list_spinlock);
+
+ if (pmbuf_src) {
+ pkt_size += wlan_11n_form_amsdu_pkt(
+ pmadapter, (data + pkt_size),
+ pmbuf_src->pbuf + pmbuf_src->data_offset,
+ pmbuf_src->data_len, &pad);
+
+ DBG_HEXDUMP(MDAT_D, "pmbuf_src", pmbuf_src,
+ sizeof(mlan_buffer));
+ wlan_write_data_complete(pmadapter, pmbuf_src,
+ MLAN_STATUS_SUCCESS);
+ }
+
+ pmadapter->callbacks.moal_spin_lock(pmadapter->pmoal_handle,
+ priv->wmm.ra_list_spinlock);
+
+ if (!wlan_is_ralist_valid(priv, pra_list, ptrindex)) {
+ pmadapter->callbacks.moal_spin_unlock(
+ pmadapter->pmoal_handle,
+ priv->wmm.ra_list_spinlock);
+ LEAVE();
+ return MLAN_STATUS_FAILURE;
+ }
+
+ pmbuf_src =
+ (pmlan_buffer)util_peek_list(pmadapter->pmoal_handle,
+ &pra_list->buf_head, MNULL,
+ MNULL);
+ priv->msdu_in_tx_amsdu_cnt++;
+ }
+
+ pmadapter->callbacks.moal_spin_unlock(pmadapter->pmoal_handle,
+ priv->wmm.ra_list_spinlock);
+
+ /* Last AMSDU packet does not need padding */
+ pkt_size -= pad;
+ pmbuf_aggr->data_len = pkt_size;
+ wlan_11n_update_pktlen_amsdu_txpd(priv, pmbuf_aggr);
+ pmbuf_aggr->data_len += headroom;
+ pmbuf_aggr->pbuf = data - headroom;
+ tx_param.next_pkt_len =
+ ((pmbuf_src) ? pmbuf_src->data_len + sizeof(TxPD) : 0);
+ /* Collects TP statistics */
+ if (pmadapter->tp_state_on)
+ pmadapter->callbacks.moal_tp_accounting(pmadapter->pmoal_handle,
+ pmbuf_aggr, 4);
+
+ /* Drop Tx packets at drop point 4 */
+ if (pmadapter->tp_state_drop_point == 4) {
+ wlan_write_data_complete(pmadapter, pmbuf_aggr, ret);
+ goto exit;
+ } else
+ ret = pmadapter->ops.host_to_card(priv, MLAN_TYPE_DATA,
+ pmbuf_aggr, &tx_param);
+ switch (ret) {
+#ifdef USB
+ case MLAN_STATUS_PRESOURCE:
+ PRINTM(MINFO, "MLAN_STATUS_PRESOURCE is returned\n");
+ break;
+#endif
+ case MLAN_STATUS_RESOURCE:
+ pmadapter->callbacks.moal_spin_lock(pmadapter->pmoal_handle,
+ priv->wmm.ra_list_spinlock);
+
+ if (!wlan_is_ralist_valid(priv, pra_list, ptrindex)) {
+ pmadapter->callbacks.moal_spin_unlock(
+ pmadapter->pmoal_handle,
+ priv->wmm.ra_list_spinlock);
+ pmbuf_aggr->status_code = MLAN_ERROR_PKT_INVALID;
+ wlan_write_data_complete(pmadapter, pmbuf_aggr,
+ MLAN_STATUS_FAILURE);
+ LEAVE();
+ return MLAN_STATUS_FAILURE;
+ }
+#ifdef STA_SUPPORT
+ /* reset tx_lock_flag */
+ if ((GET_BSS_ROLE(priv) == MLAN_BSS_ROLE_STA) &&
+ pmadapter->pps_uapsd_mode &&
+ (pmadapter->tx_lock_flag == MTRUE)) {
+ pmadapter->tx_lock_flag = MFALSE;
+ if (ptx_pd != MNULL)
+ ptx_pd->flags = 0;
+ }
+#endif
+ util_enqueue_list_head(pmadapter->pmoal_handle,
+ &pra_list->buf_head,
+ (pmlan_linked_list)pmbuf_aggr, MNULL,
+ MNULL);
+
+ pra_list->total_pkts++;
+
+ /* add back only one: aggregated packet is requeued as one */
+ priv->wmm.pkts_queued[ptrindex]++;
+ util_scalar_increment(pmadapter->pmoal_handle,
+ &priv->wmm.tx_pkts_queued, MNULL, MNULL);
+ pmbuf_aggr->flags |= MLAN_BUF_FLAG_REQUEUED_PKT;
+ pmadapter->callbacks.moal_spin_unlock(
+ pmadapter->pmoal_handle, priv->wmm.ra_list_spinlock);
+ PRINTM(MINFO, "MLAN_STATUS_RESOURCE is returned\n");
+ pmbuf_aggr->status_code = MLAN_ERROR_PKT_INVALID;
+ break;
+ case MLAN_STATUS_FAILURE:
+ pmbuf_aggr->status_code = MLAN_ERROR_DATA_TX_FAIL;
+ pmadapter->dbg.num_tx_host_to_card_failure++;
+ wlan_write_data_complete(pmadapter, pmbuf_aggr, ret);
+ goto exit;
+ case MLAN_STATUS_PENDING:
+ break;
+ case MLAN_STATUS_SUCCESS:
+ wlan_write_data_complete(pmadapter, pmbuf_aggr, ret);
+ break;
+ default:
+ break;
+ }
+ if (ret != MLAN_STATUS_RESOURCE) {
+ pmadapter->callbacks.moal_spin_lock(pmadapter->pmoal_handle,
+ priv->wmm.ra_list_spinlock);
+ if (wlan_is_ralist_valid(priv, pra_list, ptrindex)) {
+ priv->wmm.packets_out[ptrindex]++;
+ priv->wmm.tid_tbl_ptr[ptrindex].ra_list_curr = pra_list;
+ }
+ pmadapter->bssprio_tbl[priv->bss_priority].bssprio_cur =
+ pmadapter->bssprio_tbl[priv->bss_priority]
+ .bssprio_cur->pnext;
+ pmadapter->callbacks.moal_spin_unlock(
+ pmadapter->pmoal_handle, priv->wmm.ra_list_spinlock);
+ }
+ PRINTM_GET_SYS_TIME(MDATA, &sec, &usec);
+ PRINTM_NETINTF(MDATA, priv);
+ PRINTM(MDATA, "%lu.%06lu : Data => FW\n", sec, usec);
+ priv->amsdu_tx_cnt++;
+
+exit:
+ LEAVE();
+ return pkt_size + headroom;
+}
diff --git a/drivers/net/wireless/nxp/mxm_wifiex/wlan_src/mlan/mlan_11n_aggr.h b/drivers/net/wireless/nxp/mxm_wifiex/wlan_src/mlan/mlan_11n_aggr.h
new file mode 100644
index 000000000000..96a278312ac2
--- /dev/null
+++ b/drivers/net/wireless/nxp/mxm_wifiex/wlan_src/mlan/mlan_11n_aggr.h
@@ -0,0 +1,38 @@
+/** @file mlan_11n_aggr.h
+ *
+ * @brief This file contains related macros, enum, and struct
+ * of 11n aggregation functionalities
+ *
+ *
+ * Copyright 2014-2020 NXP
+ *
+ * This software file (the File) is distributed by NXP
+ * under the terms of the GNU General Public License Version 2, June 1991
+ * (the License). You may use, redistribute and/or modify the 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.
+ *
+ */
+
+/********************************************************
+Change log:
+ 11/10/2008: initial version
+********************************************************/
+
+#ifndef _MLAN_11N_AGGR_H_
+#define _MLAN_11N_AGGR_H_
+
+/** Aggregate 11N packets */
+mlan_status wlan_11n_deaggregate_pkt(pmlan_private priv, pmlan_buffer pmbuf);
+/** Deaggregate 11N packets */
+int wlan_11n_aggregate_pkt(mlan_private *priv, raListTbl *ptr, int headroom,
+ int ptrindex);
+
+#endif /* !_MLAN_11N_AGGR_H_ */
diff --git a/drivers/net/wireless/nxp/mxm_wifiex/wlan_src/mlan/mlan_11n_rxreorder.c b/drivers/net/wireless/nxp/mxm_wifiex/wlan_src/mlan/mlan_11n_rxreorder.c
new file mode 100644
index 000000000000..68dbd07d9f68
--- /dev/null
+++ b/drivers/net/wireless/nxp/mxm_wifiex/wlan_src/mlan/mlan_11n_rxreorder.c
@@ -0,0 +1,1497 @@
+/** @file mlan_11n_rxreorder.c
+ *
+ * @brief This file contains the handling of RxReordering in wlan
+ * driver.
+ *
+ *
+ * Copyright 2014-2020 NXP
+ *
+ * This software file (the File) is distributed by NXP
+ * under the terms of the GNU General Public License Version 2, June 1991
+ * (the License). You may use, redistribute and/or modify the 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.
+ *
+ */
+
+/********************************************************
+Change log:
+ 11/10/2008: initial version
+********************************************************/
+
+#include "mlan.h"
+#include "mlan_join.h"
+#include "mlan_util.h"
+#include "mlan_fw.h"
+#include "mlan_main.h"
+#include "mlan_wmm.h"
+#include "mlan_11n.h"
+#include "mlan_11n_rxreorder.h"
+
+/********************************************************
+ Local Variables
+********************************************************/
+
+/********************************************************
+ Global Variables
+********************************************************/
+
+/********************************************************
+ Local Functions
+********************************************************/
+/**
+ * @brief This function will dispatch amsdu packet and
+ * forward it to kernel/upper layer
+ *
+ * @param priv A pointer to mlan_private
+ * @param pmbuf A pointer to the received buffer
+ *
+ * @return MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ */
+static mlan_status wlan_11n_dispatch_amsdu_pkt(mlan_private *priv,
+ pmlan_buffer pmbuf)
+{
+ RxPD *prx_pd;
+ prx_pd = (RxPD *)(pmbuf->pbuf + pmbuf->data_offset);
+
+ ENTER();
+ if (prx_pd->rx_pkt_type == PKT_TYPE_AMSDU) {
+ pmbuf->data_len = prx_pd->rx_pkt_length;
+ pmbuf->data_offset += prx_pd->rx_pkt_offset;
+ wlan_11n_deaggregate_pkt(priv, pmbuf);
+ LEAVE();
+ return MLAN_STATUS_SUCCESS;
+ }
+ LEAVE();
+ return MLAN_STATUS_FAILURE;
+}
+
+/**
+ * @brief This function will process the rx packet and
+ * forward it to kernel/upper layer
+ *
+ * @param priv A pointer to mlan_private
+ * @param payload A pointer to rx packet payload
+ *
+ * @return MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ */
+static mlan_status wlan_11n_dispatch_pkt(t_void *priv, t_void *payload)
+{
+ mlan_status ret = MLAN_STATUS_SUCCESS;
+#ifdef STA_SUPPORT
+ pmlan_adapter pmadapter = ((pmlan_private)priv)->adapter;
+#endif
+ ENTER();
+ if (payload == (t_void *)RX_PKT_DROPPED_IN_FW) {
+ LEAVE();
+ return ret;
+ }
+#ifdef UAP_SUPPORT
+ if (GET_BSS_ROLE((mlan_private *)priv) == MLAN_BSS_ROLE_UAP) {
+ if (MLAN_STATUS_SUCCESS ==
+ wlan_11n_dispatch_amsdu_pkt((mlan_private *)priv,
+ (pmlan_buffer)payload)) {
+ LEAVE();
+ return ret;
+ }
+ ret = wlan_process_uap_rx_packet(priv, (pmlan_buffer)payload);
+ LEAVE();
+ return ret;
+ }
+#endif /* UAP_SUPPORT */
+
+#ifdef STA_SUPPORT
+ if (MLAN_STATUS_SUCCESS ==
+ wlan_11n_dispatch_amsdu_pkt((mlan_private *)priv,
+ (pmlan_buffer)payload)) {
+ LEAVE();
+ return ret;
+ }
+ ret = wlan_process_rx_packet(pmadapter, (pmlan_buffer)payload);
+#endif /* STA_SUPPORT */
+ LEAVE();
+ return ret;
+}
+
+/**
+ * @brief This function restarts the reordering timeout timer
+ *
+ * @param pmadapter A pointer to mlan_adapter
+ * @param rx_reor_tbl_ptr A pointer to structure RxReorderTbl
+ *
+ * @return N/A
+ */
+static void mlan_11n_rxreorder_timer_restart(pmlan_adapter pmadapter,
+ RxReorderTbl *rx_reor_tbl_ptr)
+{
+ t_u16 min_flush_time = 0;
+ ENTER();
+
+ if (rx_reor_tbl_ptr->win_size >= 32)
+ min_flush_time = MIN_FLUSH_TIMER_15_MS;
+ else
+ min_flush_time = MIN_FLUSH_TIMER_MS;
+
+ if (rx_reor_tbl_ptr->timer_context.timer_is_set)
+ pmadapter->callbacks.moal_stop_timer(
+ pmadapter->pmoal_handle,
+ rx_reor_tbl_ptr->timer_context.timer);
+
+ pmadapter->callbacks.moal_start_timer(
+ pmadapter->pmoal_handle, rx_reor_tbl_ptr->timer_context.timer,
+ MFALSE, (rx_reor_tbl_ptr->win_size * min_flush_time));
+
+ rx_reor_tbl_ptr->timer_context.timer_is_set = MTRUE;
+ LEAVE();
+}
+
+/**
+ * @brief This function dispatches all the packets in the buffer.
+ * There could be holes in the buffer.
+ *
+ * @param priv A pointer to mlan_private
+ * @param rx_reor_tbl_ptr A pointer to structure RxReorderTbl
+ * @param start_win Start window
+ *
+ * @return MLAN_STATUS_SUCCESS
+ */
+static mlan_status wlan_11n_dispatch_pkt_until_start_win(
+ t_void *priv, RxReorderTbl *rx_reor_tbl_ptr, int start_win)
+{
+ int no_pkt_to_send, i, xchg;
+ mlan_status ret = MLAN_STATUS_SUCCESS;
+ void *rx_tmp_ptr = MNULL;
+ mlan_private *pmpriv = (mlan_private *)priv;
+
+ ENTER();
+
+ no_pkt_to_send = (start_win > rx_reor_tbl_ptr->start_win) ?
+ MIN((start_win - rx_reor_tbl_ptr->start_win),
+ rx_reor_tbl_ptr->win_size) :
+ rx_reor_tbl_ptr->win_size;
+
+ for (i = 0; i < no_pkt_to_send; ++i) {
+ pmpriv->adapter->callbacks.moal_spin_lock(
+ pmpriv->adapter->pmoal_handle, pmpriv->rx_pkt_lock);
+ rx_tmp_ptr = MNULL;
+ if (rx_reor_tbl_ptr->rx_reorder_ptr[i]) {
+ rx_tmp_ptr = rx_reor_tbl_ptr->rx_reorder_ptr[i];
+ rx_reor_tbl_ptr->rx_reorder_ptr[i] = MNULL;
+ }
+ pmpriv->adapter->callbacks.moal_spin_unlock(
+ pmpriv->adapter->pmoal_handle, pmpriv->rx_pkt_lock);
+ if (rx_tmp_ptr)
+ wlan_11n_dispatch_pkt(priv, rx_tmp_ptr);
+ }
+
+ pmpriv->adapter->callbacks.moal_spin_lock(pmpriv->adapter->pmoal_handle,
+ pmpriv->rx_pkt_lock);
+ /*
+ * We don't have a circular buffer, hence use rotation to simulate
+ * circular buffer
+ */
+ xchg = rx_reor_tbl_ptr->win_size - no_pkt_to_send;
+ for (i = 0; i < xchg; ++i) {
+ rx_reor_tbl_ptr->rx_reorder_ptr[i] =
+ rx_reor_tbl_ptr->rx_reorder_ptr[no_pkt_to_send + i];
+ rx_reor_tbl_ptr->rx_reorder_ptr[no_pkt_to_send + i] = MNULL;
+ }
+
+ rx_reor_tbl_ptr->start_win = start_win;
+ pmpriv->adapter->callbacks.moal_spin_unlock(
+ pmpriv->adapter->pmoal_handle, pmpriv->rx_pkt_lock);
+
+ LEAVE();
+ return ret;
+}
+
+/**
+ * @brief This function will display the rxReorder table
+ *
+ * @param pmadapter A pointer to mlan_adapter structure
+ * @param rx_reor_tbl_ptr A pointer to structure RxReorderTbl
+ *
+ * @return N/A
+ */
+static t_void wlan_11n_display_tbl_ptr(pmlan_adapter pmadapter,
+ RxReorderTbl *rx_reor_tbl_ptr)
+{
+ ENTER();
+
+ DBG_HEXDUMP(MDAT_D, "Reorder ptr", rx_reor_tbl_ptr->rx_reorder_ptr,
+ sizeof(t_void *) * rx_reor_tbl_ptr->win_size);
+
+ LEAVE();
+}
+
+/**
+ * @brief This function will dispatch all packets sequentially
+ * from start_win until a hole is found and adjust the
+ * start_win appropriately
+ *
+ * @param priv A pointer to mlan_private
+ * @param rx_reor_tbl_ptr A pointer to structure RxReorderTbl
+ *
+ * @return MLAN_STATUS_SUCCESS
+ */
+static mlan_status wlan_11n_scan_and_dispatch(t_void *priv,
+ RxReorderTbl *rx_reor_tbl_ptr)
+{
+ int i, j, xchg;
+ mlan_status ret = MLAN_STATUS_SUCCESS;
+ void *rx_tmp_ptr = MNULL;
+ mlan_private *pmpriv = (mlan_private *)priv;
+
+ ENTER();
+
+ for (i = 0; i < rx_reor_tbl_ptr->win_size; ++i) {
+ pmpriv->adapter->callbacks.moal_spin_lock(
+ pmpriv->adapter->pmoal_handle, pmpriv->rx_pkt_lock);
+ if (!rx_reor_tbl_ptr->rx_reorder_ptr[i]) {
+ pmpriv->adapter->callbacks.moal_spin_unlock(
+ pmpriv->adapter->pmoal_handle,
+ pmpriv->rx_pkt_lock);
+ break;
+ }
+ rx_tmp_ptr = rx_reor_tbl_ptr->rx_reorder_ptr[i];
+ rx_reor_tbl_ptr->rx_reorder_ptr[i] = MNULL;
+ pmpriv->adapter->callbacks.moal_spin_unlock(
+ pmpriv->adapter->pmoal_handle, pmpriv->rx_pkt_lock);
+ wlan_11n_dispatch_pkt(priv, rx_tmp_ptr);
+ }
+
+ pmpriv->adapter->callbacks.moal_spin_lock(pmpriv->adapter->pmoal_handle,
+ pmpriv->rx_pkt_lock);
+ /*
+ * We don't have a circular buffer, hence use rotation to simulate
+ * circular buffer
+ */
+ if (i > 0) {
+ xchg = rx_reor_tbl_ptr->win_size - i;
+ for (j = 0; j < xchg; ++j) {
+ rx_reor_tbl_ptr->rx_reorder_ptr[j] =
+ rx_reor_tbl_ptr->rx_reorder_ptr[i + j];
+ rx_reor_tbl_ptr->rx_reorder_ptr[i + j] = MNULL;
+ }
+ }
+
+ rx_reor_tbl_ptr->start_win =
+ (rx_reor_tbl_ptr->start_win + i) & (MAX_TID_VALUE - 1);
+
+ pmpriv->adapter->callbacks.moal_spin_unlock(
+ pmpriv->adapter->pmoal_handle, pmpriv->rx_pkt_lock);
+ LEAVE();
+ return ret;
+}
+
+/**
+ * @brief This function delete rxreorder table's entry
+ * and free the memory
+ *
+ * @param priv A pointer to mlan_private
+ * @param rx_reor_tbl_ptr A pointer to structure RxReorderTbl
+ *
+ * @return N/A
+ */
+static t_void wlan_11n_delete_rxreorder_tbl_entry(mlan_private *priv,
+ RxReorderTbl *rx_reor_tbl_ptr)
+{
+ pmlan_adapter pmadapter = priv->adapter;
+
+ ENTER();
+
+ if (!rx_reor_tbl_ptr) {
+ LEAVE();
+ return;
+ }
+ mlan_block_rx_process(pmadapter, MTRUE);
+
+ wlan_11n_dispatch_pkt_until_start_win(
+ priv, rx_reor_tbl_ptr,
+ (rx_reor_tbl_ptr->start_win + rx_reor_tbl_ptr->win_size) &
+ (MAX_TID_VALUE - 1));
+
+ if (rx_reor_tbl_ptr->timer_context.timer) {
+ if (rx_reor_tbl_ptr->timer_context.timer_is_set) {
+ priv->adapter->callbacks.moal_stop_timer(
+ pmadapter->pmoal_handle,
+ rx_reor_tbl_ptr->timer_context.timer);
+ rx_reor_tbl_ptr->timer_context.timer_is_set = MFALSE;
+ }
+ priv->adapter->callbacks.moal_free_timer(
+ pmadapter->pmoal_handle,
+ rx_reor_tbl_ptr->timer_context.timer);
+ rx_reor_tbl_ptr->timer_context.timer = MNULL;
+ }
+
+ PRINTM(MDAT_D, "Delete rx_reor_tbl_ptr: %p\n", rx_reor_tbl_ptr);
+ util_unlink_list(pmadapter->pmoal_handle, &priv->rx_reorder_tbl_ptr,
+ (pmlan_linked_list)rx_reor_tbl_ptr,
+ pmadapter->callbacks.moal_spin_lock,
+ pmadapter->callbacks.moal_spin_unlock);
+
+ pmadapter->callbacks.moal_mfree(
+ pmadapter->pmoal_handle,
+ (t_u8 *)rx_reor_tbl_ptr->rx_reorder_ptr);
+ pmadapter->callbacks.moal_mfree(pmadapter->pmoal_handle,
+ (t_u8 *)rx_reor_tbl_ptr);
+ mlan_block_rx_process(pmadapter, MFALSE);
+
+ LEAVE();
+}
+
+/**
+ * @brief This function returns the last used sequence number
+ *
+ * @param rx_reorder_tbl_ptr A pointer to structure RxReorderTbl
+ *
+ * @return Last used sequence number
+ */
+static int wlan_11n_find_last_seqnum(RxReorderTbl *rx_reorder_tbl_ptr)
+{
+ int i;
+
+ ENTER();
+ for (i = (rx_reorder_tbl_ptr->win_size - 1); i >= 0; --i) {
+ if (rx_reorder_tbl_ptr->rx_reorder_ptr[i]) {
+ LEAVE();
+ return i;
+ }
+ }
+ LEAVE();
+ return -1;
+}
+
+/**
+ * @brief This function flushes all data
+ *
+ * @param priv A pointer to mlan_private structure
+ * @param rx_reor_tbl_ptr A pointer to RxReorderTbl
+ *
+ * @return N/A
+ */
+static t_void wlan_start_flush_data(mlan_private *priv,
+ RxReorderTbl *rx_reor_tbl_ptr)
+{
+ int startWin;
+
+ ENTER();
+ wlan_11n_display_tbl_ptr(priv->adapter, rx_reor_tbl_ptr);
+
+ startWin = wlan_11n_find_last_seqnum(rx_reor_tbl_ptr);
+ if (startWin >= 0) {
+ PRINTM(MINFO, "Flush data %d\n", startWin);
+ wlan_11n_dispatch_pkt_until_start_win(
+ priv, rx_reor_tbl_ptr,
+ ((rx_reor_tbl_ptr->start_win + startWin + 1) &
+ (MAX_TID_VALUE - 1)));
+ }
+ wlan_11n_display_tbl_ptr(priv->adapter, rx_reor_tbl_ptr);
+ LEAVE();
+}
+
+/**
+ * @brief This function set the flag to flushes data
+ *
+ * @param context Reorder context pointer
+ *
+ * @return N/A
+ */
+static t_void wlan_flush_data(t_void *context)
+{
+ reorder_tmr_cnxt_t *reorder_cnxt = (reorder_tmr_cnxt_t *)context;
+ ENTER();
+ /* Set the flag to flush data */
+ reorder_cnxt->priv->adapter->flush_data = MTRUE;
+ reorder_cnxt->ptr->flush_data = MTRUE;
+ reorder_cnxt->timer_is_set = MFALSE;
+ wlan_recv_event(reorder_cnxt->priv, MLAN_EVENT_ID_DRV_DEFER_RX_WORK,
+ MNULL);
+ LEAVE();
+}
+
+/**
+ * @brief This function will create a entry in rx reordering table for the
+ * given ta/tid and will initialize it with seq_num, win_size
+ *
+ * @param priv A pointer to mlan_private
+ * @param ta ta to find in reordering table
+ * @param tid tid to find in reordering table
+ * @param win_size win_size for the give ta/tid pair.
+ * @param seq_num Starting sequence number for current entry.
+ *
+ * @return N/A
+ */
+static t_void wlan_11n_create_rxreorder_tbl(mlan_private *priv, t_u8 *ta,
+ int tid, int win_size, int seq_num)
+{
+ int i;
+ pmlan_adapter pmadapter = priv->adapter;
+ RxReorderTbl *rx_reor_tbl_ptr, *new_node;
+ sta_node *sta_ptr = MNULL;
+ t_u16 last_seq = 0;
+
+ ENTER();
+
+ /*
+ * If we get a TID, ta pair which is already present dispatch all the
+ * the packets and move the window size until the ssn
+ */
+ rx_reor_tbl_ptr = wlan_11n_get_rxreorder_tbl(priv, tid, ta);
+ if (rx_reor_tbl_ptr) {
+ PRINTM(MCMND, "%s: delete %p old_size=%d, win_size=%d\n",
+ __func__, rx_reor_tbl_ptr, rx_reor_tbl_ptr->win_size,
+ win_size);
+ wlan_11n_delete_rxreorder_tbl_entry(priv, rx_reor_tbl_ptr);
+ }
+ mlan_block_rx_process(pmadapter, MTRUE);
+ PRINTM(MCMND, "%s: seq_num %d, tid %d, ta " MACSTR ", win_size %d\n",
+ __func__, seq_num, tid, MAC2STR(ta), win_size);
+ if (pmadapter->callbacks.moal_malloc(pmadapter->pmoal_handle,
+ sizeof(RxReorderTbl), MLAN_MEM_DEF,
+ (t_u8 **)&new_node)) {
+ PRINTM(MERROR, "Rx reorder memory allocation failed\n");
+ mlan_block_rx_process(pmadapter, MFALSE);
+ LEAVE();
+ return;
+ }
+
+ util_init_list((pmlan_linked_list)new_node);
+ if (pmadapter->callbacks.moal_malloc(
+ pmadapter->pmoal_handle, sizeof(pmlan_buffer) * win_size,
+ MLAN_MEM_DEF, (t_u8 **)&new_node->rx_reorder_ptr)) {
+ PRINTM(MERROR, "Rx reorder table memory allocation"
+ "failed\n");
+ pmadapter->callbacks.moal_mfree(pmadapter->pmoal_handle,
+ (t_u8 *)new_node);
+ mlan_block_rx_process(pmadapter, MFALSE);
+ LEAVE();
+ return;
+ }
+ PRINTM(MDAT_D, "Create ReorderPtr: %p start_win=%d last_seq=%d\n",
+ new_node, new_node->start_win, last_seq);
+ new_node->timer_context.ptr = new_node;
+ new_node->timer_context.priv = priv;
+ new_node->timer_context.timer_is_set = MFALSE;
+ pmadapter->callbacks.moal_init_timer(pmadapter->pmoal_handle,
+ &new_node->timer_context.timer,
+ wlan_flush_data,
+ &new_node->timer_context);
+ util_enqueue_list_tail(pmadapter->pmoal_handle,
+ &priv->rx_reorder_tbl_ptr,
+ (pmlan_linked_list)new_node,
+ pmadapter->callbacks.moal_spin_lock,
+ pmadapter->callbacks.moal_spin_unlock);
+ new_node->tid = tid;
+ memcpy_ext(pmadapter, new_node->ta, ta, MLAN_MAC_ADDR_LENGTH,
+ MLAN_MAC_ADDR_LENGTH);
+ new_node->start_win = seq_num;
+ new_node->pkt_count = 0;
+ if (queuing_ra_based(priv)) {
+ if (GET_BSS_ROLE(priv) == MLAN_BSS_ROLE_UAP) {
+ sta_ptr = wlan_get_station_entry(priv, ta);
+ if (sta_ptr)
+ last_seq = sta_ptr->rx_seq[tid];
+ }
+ PRINTM(MINFO, "UAP/ADHOC:last_seq=%d start_win=%d\n", last_seq,
+ new_node->start_win);
+ } else {
+ last_seq = priv->rx_seq[tid];
+ }
+ new_node->last_seq = last_seq;
+ new_node->win_size = win_size;
+ new_node->force_no_drop = MFALSE;
+ new_node->check_start_win = MTRUE;
+ new_node->ba_status = BA_STREAM_SETUP_INPROGRESS;
+ for (i = 0; i < win_size; ++i)
+ new_node->rx_reorder_ptr[i] = MNULL;
+ mlan_block_rx_process(pmadapter, MFALSE);
+ LEAVE();
+}
+
+/********************************************************
+ Global Functions
+********************************************************/
+
+/**
+ * @brief This function will return the pointer to a entry in rx reordering
+ * table which matches the give TA/TID pair
+ *
+ * @param priv A pointer to mlan_private
+ * @param ta ta to find in reordering table
+ * @param tid tid to find in reordering table
+ *
+ * @return A pointer to structure RxReorderTbl
+ */
+RxReorderTbl *wlan_11n_get_rxreorder_tbl(mlan_private *priv, int tid, t_u8 *ta)
+{
+ RxReorderTbl *rx_reor_tbl_ptr;
+
+ ENTER();
+
+ rx_reor_tbl_ptr =
+ (RxReorderTbl *)util_peek_list(priv->adapter->pmoal_handle,
+ &priv->rx_reorder_tbl_ptr, MNULL,
+ MNULL);
+ if (!rx_reor_tbl_ptr) {
+ LEAVE();
+ return MNULL;
+ }
+
+ while (rx_reor_tbl_ptr != (RxReorderTbl *)&priv->rx_reorder_tbl_ptr) {
+ if ((!memcmp(priv->adapter, rx_reor_tbl_ptr->ta, ta,
+ MLAN_MAC_ADDR_LENGTH)) &&
+ (rx_reor_tbl_ptr->tid == tid)) {
+ LEAVE();
+ return rx_reor_tbl_ptr;
+ }
+
+ rx_reor_tbl_ptr = rx_reor_tbl_ptr->pnext;
+ }
+
+ LEAVE();
+ return MNULL;
+}
+
+/**
+ * @brief This function prepares command for adding a block ack
+ * request.
+ *
+ * @param priv A pointer to mlan_private structure
+ * @param cmd A pointer to HostCmd_DS_COMMAND structure
+ * @param pdata_buf A pointer to data buffer
+ *
+ * @return MLAN_STATUS_SUCCESS
+ */
+mlan_status wlan_cmd_11n_addba_req(mlan_private *priv, HostCmd_DS_COMMAND *cmd,
+ t_void *pdata_buf)
+{
+ HostCmd_DS_11N_ADDBA_REQ *padd_ba_req =
+ (HostCmd_DS_11N_ADDBA_REQ *)&cmd->params.add_ba_req;
+ ENTER();
+
+ cmd->command = wlan_cpu_to_le16(HostCmd_CMD_11N_ADDBA_REQ);
+ cmd->size =
+ wlan_cpu_to_le16(sizeof(HostCmd_DS_11N_ADDBA_REQ) + S_DS_GEN);
+
+ memcpy_ext(priv->adapter, padd_ba_req, pdata_buf,
+ sizeof(HostCmd_DS_11N_ADDBA_REQ),
+ sizeof(HostCmd_DS_11N_ADDBA_REQ));
+ padd_ba_req->block_ack_param_set =
+ wlan_cpu_to_le16(padd_ba_req->block_ack_param_set);
+ padd_ba_req->block_ack_tmo =
+ wlan_cpu_to_le16(padd_ba_req->block_ack_tmo);
+ padd_ba_req->ssn = wlan_cpu_to_le16(padd_ba_req->ssn);
+ padd_ba_req->add_req_result = 0;
+
+ LEAVE();
+ return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ * @brief This function check if AMPDU Rx allowed
+ *
+ * @param priv A pointer to mlan_private structure
+ * @param tid TID
+ *
+ * @return MTRUE/MFALSE
+ */
+t_u8 wlan_is_addba_reject(mlan_private *priv, t_u8 tid)
+{
+#ifdef STA_SUPPORT
+#endif
+ return priv->addba_reject[tid];
+}
+/**
+ * @brief This function prepares command for adding a block ack
+ * response.
+ *
+ * @param priv A pointer to mlan_private structure
+ * @param cmd A pointer to HostCmd_DS_COMMAND structure
+ * @param pdata_buf A pointer to data buffer
+ *
+ * @return MLAN_STATUS_SUCCESS
+ */
+mlan_status wlan_cmd_11n_addba_rspgen(mlan_private *priv,
+ HostCmd_DS_COMMAND *cmd, void *pdata_buf)
+{
+ HostCmd_DS_11N_ADDBA_RSP *padd_ba_rsp =
+ (HostCmd_DS_11N_ADDBA_RSP *)&cmd->params.add_ba_rsp;
+ HostCmd_DS_11N_ADDBA_REQ *pevt_addba_req =
+ (HostCmd_DS_11N_ADDBA_REQ *)pdata_buf;
+ t_u8 tid = 0;
+ int win_size = 0;
+
+ ENTER();
+
+ pevt_addba_req->block_ack_param_set =
+ wlan_le16_to_cpu(pevt_addba_req->block_ack_param_set);
+ pevt_addba_req->block_ack_tmo =
+ wlan_le16_to_cpu(pevt_addba_req->block_ack_tmo);
+ pevt_addba_req->ssn = wlan_le16_to_cpu(pevt_addba_req->ssn);
+
+ cmd->command = wlan_cpu_to_le16(HostCmd_CMD_11N_ADDBA_RSP);
+ cmd->size =
+ wlan_cpu_to_le16(sizeof(HostCmd_DS_11N_ADDBA_RSP) + S_DS_GEN);
+
+ memcpy_ext(priv->adapter, padd_ba_rsp->peer_mac_addr,
+ pevt_addba_req->peer_mac_addr, MLAN_MAC_ADDR_LENGTH,
+ MLAN_MAC_ADDR_LENGTH);
+ padd_ba_rsp->dialog_token = pevt_addba_req->dialog_token;
+ padd_ba_rsp->block_ack_tmo =
+ wlan_cpu_to_le16(pevt_addba_req->block_ack_tmo);
+ padd_ba_rsp->ssn = wlan_cpu_to_le16(pevt_addba_req->ssn);
+ padd_ba_rsp->add_rsp_result = 0;
+
+ padd_ba_rsp->block_ack_param_set = pevt_addba_req->block_ack_param_set;
+ tid = (padd_ba_rsp->block_ack_param_set & BLOCKACKPARAM_TID_MASK) >>
+ BLOCKACKPARAM_TID_POS;
+ if (wlan_is_addba_reject(priv, tid)
+#ifdef STA_SUPPORT
+ || ((GET_BSS_ROLE(priv) == MLAN_BSS_ROLE_STA) &&
+ priv->wps.session_enable)
+#endif
+#ifdef UAP_SUPPORT
+ || ((GET_BSS_ROLE(priv) == MLAN_BSS_ROLE_UAP) &&
+ (util_scalar_read(priv->adapter->pmoal_handle,
+ &priv->adapter->pending_bridge_pkts,
+ priv->adapter->callbacks.moal_spin_lock,
+ priv->adapter->callbacks.moal_spin_unlock) >
+ RX_LOW_THRESHOLD))
+#endif
+ )
+ padd_ba_rsp->status_code =
+ wlan_cpu_to_le16(ADDBA_RSP_STATUS_DECLINED);
+ else
+ padd_ba_rsp->status_code =
+ wlan_cpu_to_le16(ADDBA_RSP_STATUS_ACCEPT);
+ padd_ba_rsp->block_ack_param_set &= ~BLOCKACKPARAM_WINSIZE_MASK;
+ if (!priv->add_ba_param.rx_amsdu)
+ /* We do not support AMSDU inside AMPDU, hence reset the bit */
+ padd_ba_rsp->block_ack_param_set &=
+ ~BLOCKACKPARAM_AMSDU_SUPP_MASK;
+
+ padd_ba_rsp->block_ack_param_set |=
+ (priv->add_ba_param.rx_win_size << BLOCKACKPARAM_WINSIZE_POS);
+ win_size = (padd_ba_rsp->block_ack_param_set &
+ BLOCKACKPARAM_WINSIZE_MASK) >>
+ BLOCKACKPARAM_WINSIZE_POS;
+
+ if (win_size == 0)
+ padd_ba_rsp->status_code =
+ wlan_cpu_to_le16(ADDBA_RSP_STATUS_DECLINED);
+
+ padd_ba_rsp->block_ack_param_set =
+ wlan_cpu_to_le16(padd_ba_rsp->block_ack_param_set);
+
+ if (padd_ba_rsp->status_code ==
+ wlan_cpu_to_le16(ADDBA_RSP_STATUS_ACCEPT))
+ wlan_11n_create_rxreorder_tbl(priv,
+ pevt_addba_req->peer_mac_addr,
+ tid, win_size,
+ pevt_addba_req->ssn);
+ LEAVE();
+ return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ * @brief This function prepares command for deleting a block ack
+ * request.
+ *
+ * @param priv A pointer to mlan_private structure
+ * @param cmd A pointer to HostCmd_DS_COMMAND structure
+ * @param pdata_buf A pointer to data buffer
+ *
+ * @return MLAN_STATUS_SUCCESS
+ */
+mlan_status wlan_cmd_11n_delba(mlan_private *priv, HostCmd_DS_COMMAND *cmd,
+ void *pdata_buf)
+{
+ HostCmd_DS_11N_DELBA *pdel_ba =
+ (HostCmd_DS_11N_DELBA *)&cmd->params.del_ba;
+
+ ENTER();
+
+ cmd->command = wlan_cpu_to_le16(HostCmd_CMD_11N_DELBA);
+ cmd->size = wlan_cpu_to_le16(sizeof(HostCmd_DS_11N_DELBA) + S_DS_GEN);
+
+ memcpy_ext(priv->adapter, pdel_ba, pdata_buf,
+ sizeof(HostCmd_DS_11N_DELBA), sizeof(HostCmd_DS_11N_DELBA));
+ pdel_ba->del_ba_param_set = wlan_cpu_to_le16(pdel_ba->del_ba_param_set);
+ pdel_ba->reason_code = wlan_cpu_to_le16(pdel_ba->reason_code);
+ pdel_ba->del_result = 0;
+
+ LEAVE();
+ return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ * @brief This function will identify if RxReodering is needed for the packet
+ * and will do the reordering if required before sending it to kernel
+ *
+ * @param priv A pointer to mlan_private
+ * @param seq_num Seqence number of the current packet
+ * @param tid Tid of the current packet
+ * @param ta Transmiter address of the current packet
+ * @param pkt_type Packetype for the current packet (to identify if its a BAR)
+ * @param payload Pointer to the payload
+ *
+ * @return MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ */
+mlan_status mlan_11n_rxreorder_pkt(void *priv, t_u16 seq_num, t_u16 tid,
+ t_u8 *ta, t_u8 pkt_type, void *payload)
+{
+ RxReorderTbl *rx_reor_tbl_ptr;
+ int prev_start_win, start_win, end_win, win_size;
+ mlan_status ret = MLAN_STATUS_SUCCESS;
+ pmlan_adapter pmadapter = ((mlan_private *)priv)->adapter;
+
+ ENTER();
+
+ rx_reor_tbl_ptr =
+ wlan_11n_get_rxreorder_tbl((mlan_private *)priv, tid, ta);
+ if (!rx_reor_tbl_ptr || rx_reor_tbl_ptr->win_size <= 1) {
+ if (pkt_type != PKT_TYPE_BAR)
+ wlan_11n_dispatch_pkt(priv, payload);
+
+ LEAVE();
+ return ret;
+
+ } else {
+ if (rx_reor_tbl_ptr->flush_data) {
+ rx_reor_tbl_ptr->flush_data = MFALSE;
+ wlan_start_flush_data(priv, rx_reor_tbl_ptr);
+ }
+ if ((pkt_type == PKT_TYPE_AMSDU) && !rx_reor_tbl_ptr->amsdu) {
+ wlan_11n_dispatch_pkt(priv, payload);
+ LEAVE();
+ return ret;
+ }
+ if (pkt_type == PKT_TYPE_BAR)
+ PRINTM(MDAT_D, "BAR ");
+ if (pkt_type == PKT_TYPE_AMSDU)
+ PRINTM(MDAT_D, "AMSDU ");
+
+ if (rx_reor_tbl_ptr->check_start_win) {
+ if (seq_num == rx_reor_tbl_ptr->start_win)
+ rx_reor_tbl_ptr->check_start_win = MFALSE;
+ else {
+ rx_reor_tbl_ptr->pkt_count++;
+ if (rx_reor_tbl_ptr->pkt_count <
+ (rx_reor_tbl_ptr->win_size / 2)) {
+ if (rx_reor_tbl_ptr->last_seq ==
+ seq_num) {
+ /** drop duplicate packet */
+ ret = MLAN_STATUS_FAILURE;
+ } else {
+ /** forward the packet to kernel
+ */
+ rx_reor_tbl_ptr->last_seq =
+ seq_num;
+ if (pkt_type != PKT_TYPE_BAR)
+ wlan_11n_dispatch_pkt(
+ priv, payload);
+ }
+ LEAVE();
+ return ret;
+ }
+ rx_reor_tbl_ptr->check_start_win = MFALSE;
+ if ((seq_num != rx_reor_tbl_ptr->start_win) &&
+ (rx_reor_tbl_ptr->last_seq !=
+ DEFAULT_SEQ_NUM)) {
+ end_win = (rx_reor_tbl_ptr->start_win +
+ rx_reor_tbl_ptr->win_size -
+ 1) &
+ (MAX_TID_VALUE - 1);
+ if (((end_win >
+ rx_reor_tbl_ptr->start_win) &&
+ (rx_reor_tbl_ptr->last_seq >=
+ rx_reor_tbl_ptr->start_win) &&
+ (rx_reor_tbl_ptr->last_seq <
+ end_win)) ||
+ ((end_win <
+ rx_reor_tbl_ptr->start_win) &&
+ ((rx_reor_tbl_ptr->last_seq >=
+ rx_reor_tbl_ptr->start_win) ||
+ (rx_reor_tbl_ptr->last_seq <
+ end_win)))) {
+ PRINTM(MDAT_D,
+ "Update start_win: last_seq=%d, start_win=%d seq_num=%d\n",
+ rx_reor_tbl_ptr->last_seq,
+ rx_reor_tbl_ptr
+ ->start_win,
+ seq_num);
+ rx_reor_tbl_ptr->start_win =
+ rx_reor_tbl_ptr
+ ->last_seq +
+ 1;
+ } else if ((seq_num <
+ rx_reor_tbl_ptr->start_win) &&
+ (seq_num >
+ rx_reor_tbl_ptr->last_seq)) {
+ PRINTM(MDAT_D,
+ "Update start_win: last_seq=%d, start_win=%d seq_num=%d\n",
+ rx_reor_tbl_ptr->last_seq,
+ rx_reor_tbl_ptr
+ ->start_win,
+ seq_num);
+ rx_reor_tbl_ptr->start_win =
+ rx_reor_tbl_ptr
+ ->last_seq +
+ 1;
+ }
+ }
+ }
+ }
+ if (rx_reor_tbl_ptr->force_no_drop) {
+ wlan_11n_dispatch_pkt_until_start_win(
+ priv, rx_reor_tbl_ptr,
+ (rx_reor_tbl_ptr->start_win +
+ rx_reor_tbl_ptr->win_size) &
+ (MAX_TID_VALUE - 1));
+ if (pkt_type != PKT_TYPE_BAR)
+ rx_reor_tbl_ptr->start_win = seq_num;
+ mlan_11n_rxreorder_timer_restart(pmadapter,
+ rx_reor_tbl_ptr);
+ }
+
+ prev_start_win = start_win = rx_reor_tbl_ptr->start_win;
+ win_size = rx_reor_tbl_ptr->win_size;
+ end_win = ((start_win + win_size) - 1) & (MAX_TID_VALUE - 1);
+
+ PRINTM(MDAT_D, "TID %d, TA " MACSTR "\n", tid, MAC2STR(ta));
+ PRINTM(MDAT_D,
+ "1:seq_num %d start_win %d win_size %d end_win %d\n",
+ seq_num, start_win, win_size, end_win);
+ /*
+ * If seq_num is less then starting win then ignore and drop
+ * the packet
+ */
+ if (rx_reor_tbl_ptr->force_no_drop) {
+ PRINTM(MDAT_D, "No drop packet\n");
+ rx_reor_tbl_ptr->force_no_drop = MFALSE;
+ } else {
+ /* Wrap */
+ if ((start_win + TWOPOW11) > (MAX_TID_VALUE - 1)) {
+ if (seq_num >= ((start_win + (TWOPOW11)) &
+ (MAX_TID_VALUE - 1)) &&
+ (seq_num < start_win)) {
+ if (pkt_type == PKT_TYPE_BAR)
+ PRINTM(MDAT_D,
+ "BAR: start_win=%d, end_win=%d, seq_num=%d\n",
+ start_win, end_win,
+ seq_num);
+ ret = MLAN_STATUS_FAILURE;
+ goto done;
+ }
+ } else if ((seq_num < start_win) ||
+ (seq_num >= (start_win + (TWOPOW11)))) {
+ if (pkt_type == PKT_TYPE_BAR)
+ PRINTM(MDAT_D,
+ "BAR: start_win=%d, end_win=%d, seq_num=%d\n",
+ start_win, end_win, seq_num);
+ ret = MLAN_STATUS_FAILURE;
+ 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);
+
+ PRINTM(MDAT_D,
+ "2:seq_num %d start_win %d win_size %d end_win %d\n",
+ seq_num, start_win, win_size, end_win);
+
+ 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 (((seq_num - win_size) + 1) >= 0)
+ start_win = (end_win - win_size) + 1;
+ else
+ start_win =
+ (MAX_TID_VALUE - (win_size - seq_num)) +
+ 1;
+ ret = wlan_11n_dispatch_pkt_until_start_win(
+ priv, rx_reor_tbl_ptr, start_win);
+ if (ret)
+ goto done;
+ }
+
+ PRINTM(MDAT_D,
+ "3:seq_num %d start_win %d win_size %d"
+ " end_win %d\n",
+ seq_num, start_win, win_size, end_win);
+ if (pkt_type != PKT_TYPE_BAR) {
+ if (seq_num >= start_win) {
+ if (rx_reor_tbl_ptr->rx_reorder_ptr[seq_num -
+ start_win]) {
+ PRINTM(MDAT_D, "Drop Duplicate Pkt\n");
+ ret = MLAN_STATUS_FAILURE;
+ goto done;
+ }
+ rx_reor_tbl_ptr
+ ->rx_reorder_ptr[seq_num - start_win] =
+ payload;
+ } else { /* Wrap condition */
+ if (rx_reor_tbl_ptr
+ ->rx_reorder_ptr[(seq_num +
+ (MAX_TID_VALUE)) -
+ start_win]) {
+ PRINTM(MDAT_D, "Drop Duplicate Pkt\n");
+ ret = MLAN_STATUS_FAILURE;
+ goto done;
+ }
+ rx_reor_tbl_ptr
+ ->rx_reorder_ptr[(seq_num +
+ (MAX_TID_VALUE)) -
+ start_win] = payload;
+ }
+ }
+
+ wlan_11n_display_tbl_ptr(pmadapter, rx_reor_tbl_ptr);
+
+ /*
+ * Dispatch all packets sequentially from start_win until a
+ * hole is found and adjust the start_win appropriately
+ */
+ ret = wlan_11n_scan_and_dispatch(priv, rx_reor_tbl_ptr);
+
+ wlan_11n_display_tbl_ptr(pmadapter, rx_reor_tbl_ptr);
+ }
+
+done:
+ if (!rx_reor_tbl_ptr->timer_context.timer_is_set ||
+ (prev_start_win != rx_reor_tbl_ptr->start_win)) {
+ mlan_11n_rxreorder_timer_restart(pmadapter, rx_reor_tbl_ptr);
+ }
+
+ LEAVE();
+ return ret;
+}
+
+/**
+ * @brief This function will delete an entry for a given tid/ta pair. tid/ta
+ * are taken from delba_event body
+ *
+ * @param priv A pointer to mlan_private
+ * @param tid tid to send delba
+ * @param peer_mac MAC address to send delba
+ * @param type TYPE_DELBA_SENT or TYPE_DELBA_RECEIVE
+ * @param initiator MTRUE if we are initiator of ADDBA, MFALSE otherwise
+ * @param reason_code delete ba reason
+ *
+ * @return N/A
+ */
+void mlan_11n_delete_bastream_tbl(mlan_private *priv, int tid, t_u8 *peer_mac,
+ t_u8 type, int initiator, t_u16 reason_code)
+{
+ RxReorderTbl *rx_reor_tbl_ptr;
+ TxBAStreamTbl *ptxtbl;
+ t_u8 cleanup_rx_reorder_tbl;
+ raListTbl *ra_list = MNULL;
+ int tid_down;
+
+ ENTER();
+
+ if (type == TYPE_DELBA_RECEIVE)
+ cleanup_rx_reorder_tbl = (initiator) ? MTRUE : MFALSE;
+ else
+ cleanup_rx_reorder_tbl = (initiator) ? MFALSE : MTRUE;
+
+ PRINTM(MEVENT,
+ "delete_bastream_tbl: " MACSTR " tid=%d, type=%d"
+ "initiator=%d reason=%d\n",
+ MAC2STR(peer_mac), tid, type, initiator, reason_code);
+
+ if (cleanup_rx_reorder_tbl) {
+ rx_reor_tbl_ptr =
+ wlan_11n_get_rxreorder_tbl(priv, tid, peer_mac);
+ if (!rx_reor_tbl_ptr) {
+ PRINTM(MWARN, "TID, TA not found in table!\n");
+ LEAVE();
+ return;
+ }
+ wlan_11n_delete_rxreorder_tbl_entry(priv, rx_reor_tbl_ptr);
+ } else {
+ wlan_request_ralist_lock(priv);
+ ptxtbl = wlan_11n_get_txbastream_tbl(priv, tid, peer_mac,
+ MFALSE);
+ if (!ptxtbl) {
+ PRINTM(MWARN, "TID, RA not found in table!\n");
+ wlan_release_ralist_lock(priv);
+ LEAVE();
+ return;
+ }
+ wlan_11n_delete_txbastream_tbl_entry(priv, ptxtbl);
+ wlan_release_ralist_lock(priv);
+ tid_down = wlan_get_wmm_tid_down(priv, tid);
+ ra_list = wlan_wmm_get_ralist_node(priv, tid_down, peer_mac);
+ if (ra_list) {
+ ra_list->amsdu_in_ampdu = MFALSE;
+ ra_list->ba_status = BA_STREAM_NOT_SETUP;
+ if (type == TYPE_DELBA_RECEIVE) {
+ if (reason_code == REASON_CODE_STA_TIMEOUT)
+ ra_list->del_ba_count = 0;
+ else
+ ra_list->del_ba_count++;
+ ra_list->packet_count = 0;
+/** after delba, we will try to set up BA again after sending 1k packets*/
+#define MIN_BA_SETUP_PACKET_REQIRED 1024
+ ra_list->ba_packet_threshold =
+ MIN_BA_SETUP_PACKET_REQIRED +
+ wlan_get_random_ba_threshold(
+ priv->adapter);
+ }
+ }
+ }
+
+ LEAVE();
+}
+
+/**
+ * @brief This function handles the command response of
+ * a block ack response
+ *
+ * @param priv A pointer to mlan_private structure
+ * @param resp A pointer to HostCmd_DS_COMMAND
+ *
+ * @return MLAN_STATUS_SUCCESS
+ */
+mlan_status wlan_ret_11n_addba_resp(mlan_private *priv,
+ HostCmd_DS_COMMAND *resp)
+{
+ HostCmd_DS_11N_ADDBA_RSP *padd_ba_rsp =
+ (HostCmd_DS_11N_ADDBA_RSP *)&resp->params.add_ba_rsp;
+ int tid;
+ RxReorderTbl *rx_reor_tbl_ptr = MNULL;
+
+ ENTER();
+
+ padd_ba_rsp->status_code = wlan_le16_to_cpu(padd_ba_rsp->status_code);
+ padd_ba_rsp->block_ack_param_set =
+ wlan_le16_to_cpu(padd_ba_rsp->block_ack_param_set);
+ padd_ba_rsp->block_ack_tmo =
+ wlan_le16_to_cpu(padd_ba_rsp->block_ack_tmo);
+ padd_ba_rsp->ssn = wlan_le16_to_cpu(padd_ba_rsp->ssn);
+
+ tid = (padd_ba_rsp->block_ack_param_set & BLOCKACKPARAM_TID_MASK) >>
+ BLOCKACKPARAM_TID_POS;
+ /* Check if we had rejected the ADDBA, if yes then do not create the
+ * stream
+ */
+ if (padd_ba_rsp->status_code == BA_RESULT_SUCCESS) {
+ PRINTM(MCMND,
+ "ADDBA RSP: " MACSTR
+ " tid=%d ssn=%d win_size=%d,amsdu=%d\n",
+ MAC2STR(padd_ba_rsp->peer_mac_addr), tid,
+ padd_ba_rsp->ssn,
+ ((padd_ba_rsp->block_ack_param_set &
+ BLOCKACKPARAM_WINSIZE_MASK) >>
+ BLOCKACKPARAM_WINSIZE_POS),
+ padd_ba_rsp->block_ack_param_set &
+ BLOCKACKPARAM_AMSDU_SUPP_MASK);
+
+ rx_reor_tbl_ptr = wlan_11n_get_rxreorder_tbl(
+ priv, tid, padd_ba_rsp->peer_mac_addr);
+ if (rx_reor_tbl_ptr) {
+ rx_reor_tbl_ptr->ba_status = BA_STREAM_SETUP_COMPLETE;
+ if ((padd_ba_rsp->block_ack_param_set &
+ BLOCKACKPARAM_AMSDU_SUPP_MASK) &&
+ priv->add_ba_param.rx_amsdu)
+ rx_reor_tbl_ptr->amsdu = MTRUE;
+ else
+ rx_reor_tbl_ptr->amsdu = MFALSE;
+ }
+ } else {
+ PRINTM(MCMND, "ADDBA RSP: Failed(" MACSTR " tid=%d)\n",
+ MAC2STR(padd_ba_rsp->peer_mac_addr), tid);
+ rx_reor_tbl_ptr = wlan_11n_get_rxreorder_tbl(
+ priv, tid, padd_ba_rsp->peer_mac_addr);
+ if (rx_reor_tbl_ptr)
+ wlan_11n_delete_rxreorder_tbl_entry(priv,
+ rx_reor_tbl_ptr);
+ }
+
+ LEAVE();
+ return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ * @brief This function handles ba_stream_timeout event
+ *
+ * @param priv A pointer to mlan_private
+ * @param event A pointer to structure HostCmd_DS_11N_BATIMEOUT
+ *
+ * @return N/A
+ */
+void wlan_11n_ba_stream_timeout(mlan_private *priv,
+ HostCmd_DS_11N_BATIMEOUT *event)
+{
+ HostCmd_DS_11N_DELBA delba;
+
+ ENTER();
+
+ DBG_HEXDUMP(MCMD_D, "Event:", (t_u8 *)event, 20);
+
+ memset(priv->adapter, &delba, 0, sizeof(HostCmd_DS_11N_DELBA));
+ memcpy_ext(priv->adapter, delba.peer_mac_addr, event->peer_mac_addr,
+ MLAN_MAC_ADDR_LENGTH, MLAN_MAC_ADDR_LENGTH);
+
+ delba.del_ba_param_set |= (t_u16)event->tid << DELBA_TID_POS;
+ delba.del_ba_param_set |= (t_u16)event->origninator
+ << DELBA_INITIATOR_POS;
+ delba.reason_code = REASON_CODE_STA_TIMEOUT;
+ wlan_prepare_cmd(priv, HostCmd_CMD_11N_DELBA, 0, 0, MNULL, &delba);
+
+ LEAVE();
+ return;
+}
+
+/**
+ * @brief This function cleans up reorder tbl
+ *
+ * @param priv A pointer to mlan_private
+ *
+ * @return N/A
+ */
+void wlan_11n_cleanup_reorder_tbl(mlan_private *priv)
+{
+ RxReorderTbl *del_tbl_ptr;
+
+ ENTER();
+
+ while ((del_tbl_ptr = (RxReorderTbl *)util_peek_list(
+ priv->adapter->pmoal_handle, &priv->rx_reorder_tbl_ptr,
+ priv->adapter->callbacks.moal_spin_lock,
+ priv->adapter->callbacks.moal_spin_unlock))) {
+ wlan_11n_delete_rxreorder_tbl_entry(priv, del_tbl_ptr);
+ }
+
+ util_init_list((pmlan_linked_list)&priv->rx_reorder_tbl_ptr);
+
+ memset(priv->adapter, priv->rx_seq, 0xff, sizeof(priv->rx_seq));
+ LEAVE();
+}
+
+/**
+ * @brief This function handle the rxba_sync event
+ *
+ * @param priv A pointer to mlan_private
+ * @param event_buf A pointer to event buf
+ * @param len event_buf length
+ * @return N/A
+ */
+void wlan_11n_rxba_sync_event(mlan_private *priv, t_u8 *event_buf, t_u16 len)
+{
+ MrvlIEtypes_RxBaSync_t *tlv_rxba = (MrvlIEtypes_RxBaSync_t *)event_buf;
+ t_u16 tlv_type, tlv_len;
+ RxReorderTbl *rx_reor_tbl_ptr = MNULL;
+ t_u8 i, j;
+ t_u16 seq_num = 0;
+ int tlv_buf_left = len;
+ ENTER();
+
+ DBG_HEXDUMP(MEVT_D, "RXBA_SYNC_EVT", event_buf, len);
+ while (tlv_buf_left >= sizeof(MrvlIEtypes_RxBaSync_t)) {
+ tlv_type = wlan_le16_to_cpu(tlv_rxba->header.type);
+ tlv_len = wlan_le16_to_cpu(tlv_rxba->header.len);
+ if (tlv_type != TLV_TYPE_RXBA_SYNC) {
+ PRINTM(MERROR, "Wrong TLV id=0x%x\n", tlv_type);
+ goto done;
+ }
+ tlv_rxba->seq_num = wlan_le16_to_cpu(tlv_rxba->seq_num);
+ tlv_rxba->bitmap_len = wlan_le16_to_cpu(tlv_rxba->bitmap_len);
+ PRINTM(MEVENT, MACSTR " tid=%d seq_num=%d bitmap_len=%d\n",
+ MAC2STR(tlv_rxba->mac), tlv_rxba->tid, tlv_rxba->seq_num,
+ tlv_rxba->bitmap_len);
+ rx_reor_tbl_ptr = wlan_11n_get_rxreorder_tbl(
+ priv, tlv_rxba->tid, tlv_rxba->mac);
+ if (!rx_reor_tbl_ptr) {
+ PRINTM(MEVENT, "Can not find rx_reorder_tbl\n");
+ goto done;
+ }
+ if (rx_reor_tbl_ptr->force_no_drop) {
+ PRINTM(MEVENT, "Ignore RXBA_SYNC_EVT in resume\n");
+ goto done;
+ }
+ for (i = 0; i < tlv_rxba->bitmap_len; i++) {
+ for (j = 0; j < 8; j++) {
+ if (tlv_rxba->bitmap[i] & (1 << j)) {
+ seq_num = (tlv_rxba->seq_num + i * 8 +
+ j) &
+ (MAX_TID_VALUE - 1);
+ PRINTM(MEVENT,
+ "Fw dropped packet, seq=%d start_win=%d, win_size=%d\n",
+ seq_num,
+ rx_reor_tbl_ptr->start_win,
+ rx_reor_tbl_ptr->win_size);
+ if (MLAN_STATUS_SUCCESS !=
+ mlan_11n_rxreorder_pkt(
+ priv, seq_num,
+ tlv_rxba->tid,
+ tlv_rxba->mac, 0,
+ (t_void *)
+ RX_PKT_DROPPED_IN_FW)) {
+ PRINTM(MERROR,
+ "Fail to handle dropped packet, seq=%d\n",
+ seq_num);
+ }
+ }
+ }
+ }
+ tlv_buf_left -= (sizeof(MrvlIEtypesHeader_t) + tlv_len);
+ tlv_rxba =
+ (MrvlIEtypes_RxBaSync_t *)((t_u8 *)tlv_rxba + tlv_len +
+ sizeof(MrvlIEtypesHeader_t));
+ }
+done:
+ LEAVE();
+ return;
+}
+
+/**
+ * @brief This function cleans up reorder tbl for specific station
+ *
+ * @param priv A pointer to mlan_private
+ * @param ta ta to find in reordering table
+ * @return N/A
+ */
+void wlan_cleanup_reorder_tbl(mlan_private *priv, t_u8 *ta)
+{
+ RxReorderTbl *rx_reor_tbl_ptr = MNULL;
+ t_u8 i;
+ ENTER();
+ for (i = 0; i < MAX_NUM_TID; ++i) {
+ rx_reor_tbl_ptr = wlan_11n_get_rxreorder_tbl(priv, i, ta);
+ if (rx_reor_tbl_ptr)
+ wlan_11n_delete_rxreorder_tbl_entry(priv,
+ rx_reor_tbl_ptr);
+ }
+ LEAVE();
+ return;
+}
+
+/**
+ * @brief This function will set force_no_drop flag in rxreorder_tbl.
+ *
+ * @param priv A pointer to mlan_private
+ * @param flag MTRUE/MFALSE
+ *
+ * @return N/A
+ */
+void wlan_set_rxreorder_tbl_no_drop_flag(mlan_private *priv, t_u8 flag)
+{
+ RxReorderTbl *rx_reor_tbl_ptr;
+
+ ENTER();
+
+ rx_reor_tbl_ptr = (RxReorderTbl *)util_peek_list(
+ priv->adapter->pmoal_handle, &priv->rx_reorder_tbl_ptr,
+ priv->adapter->callbacks.moal_spin_lock,
+ priv->adapter->callbacks.moal_spin_unlock);
+ if (!rx_reor_tbl_ptr) {
+ LEAVE();
+ return;
+ }
+
+ while (rx_reor_tbl_ptr != (RxReorderTbl *)&priv->rx_reorder_tbl_ptr) {
+ rx_reor_tbl_ptr->force_no_drop = flag;
+ rx_reor_tbl_ptr = rx_reor_tbl_ptr->pnext;
+ }
+
+ LEAVE();
+ return;
+}
+
+/**
+ * @brief This function update all the rx_reorder_tbl's force_no_drop flag
+ *
+ * @param pmadapter A pointer to mlan_adapter
+ * @param flag MTRUE/MFALSE
+ * @return N/A
+ */
+void wlan_update_rxreorder_tbl(pmlan_adapter pmadapter, t_u8 flag)
+{
+ t_u8 i;
+ pmlan_private priv = MNULL;
+ for (i = 0; i < pmadapter->priv_num; i++) {
+ if (pmadapter->priv[i]) {
+ priv = pmadapter->priv[i];
+ wlan_set_rxreorder_tbl_no_drop_flag(priv, flag);
+ }
+ }
+ return;
+}
+
+/**
+ * @brief This function will flush the data in rxreorder_tbl.
+ * which has flush_data flag on.
+ *
+ * @param priv A pointer to mlan_private
+ *
+ * @return N/A
+ */
+void wlan_flush_priv_rxreorder_tbl(mlan_private *priv)
+{
+ RxReorderTbl *rx_reor_tbl_ptr;
+
+ ENTER();
+
+ rx_reor_tbl_ptr = (RxReorderTbl *)util_peek_list(
+ priv->adapter->pmoal_handle, &priv->rx_reorder_tbl_ptr,
+ priv->adapter->callbacks.moal_spin_lock,
+ priv->adapter->callbacks.moal_spin_unlock);
+ if (!rx_reor_tbl_ptr) {
+ LEAVE();
+ return;
+ }
+
+ while (rx_reor_tbl_ptr != (RxReorderTbl *)&priv->rx_reorder_tbl_ptr) {
+ if (rx_reor_tbl_ptr->flush_data) {
+ rx_reor_tbl_ptr->flush_data = MFALSE;
+ wlan_start_flush_data(priv, rx_reor_tbl_ptr);
+ }
+ rx_reor_tbl_ptr = rx_reor_tbl_ptr->pnext;
+ }
+
+ LEAVE();
+ return;
+}
+
+/**
+ * @brief This function update all the rx_reorder_tbl's force_no_drop flag
+ *
+ * @param pmadapter A pointer to mlan_adapter
+ * @return N/A
+ */
+void wlan_flush_rxreorder_tbl(pmlan_adapter pmadapter)
+{
+ t_u8 i;
+ pmlan_private priv = MNULL;
+ for (i = 0; i < pmadapter->priv_num; i++) {
+ if (pmadapter->priv[i]) {
+ priv = pmadapter->priv[i];
+ wlan_flush_priv_rxreorder_tbl(priv);
+ }
+ }
+ return;
+}
+
+/**
+ * @brief This function update all the rx_win_size based on coex flag
+ *
+ * @param pmadapter A pointer to mlan_adapter
+ * @param coex_flag coex flag
+ *
+ * @return N/A
+ */
+void wlan_update_ampdu_rxwinsize(pmlan_adapter pmadapter, t_u8 coex_flag)
+{
+ t_u8 i;
+ t_u32 rx_win_size = 0;
+ pmlan_private priv = MNULL;
+
+ ENTER();
+ if (!pmadapter->coex_rx_winsize) {
+ LEAVE();
+ return;
+ }
+ PRINTM(MEVENT, "Update rxwinsize %d\n", coex_flag);
+ for (i = 0; i < pmadapter->priv_num; i++) {
+ if (pmadapter->priv[i]) {
+ priv = pmadapter->priv[i];
+ rx_win_size = priv->add_ba_param.rx_win_size;
+ if (coex_flag == MTRUE) {
+#ifdef STA_SUPPORT
+ if (priv->bss_type == MLAN_BSS_TYPE_STA)
+ priv->add_ba_param.rx_win_size =
+ MLAN_STA_COEX_AMPDU_DEF_RXWINSIZE;
+#endif
+#ifdef WIFI_DIRECT_SUPPORT
+ if (priv->bss_type == MLAN_BSS_TYPE_WIFIDIRECT)
+ priv->add_ba_param.rx_win_size =
+ MLAN_WFD_COEX_AMPDU_DEF_RXWINSIZE;
+#endif
+#ifdef UAP_SUPPORT
+ if (priv->bss_type == MLAN_BSS_TYPE_UAP)
+ priv->add_ba_param.rx_win_size =
+ MLAN_UAP_COEX_AMPDU_DEF_RXWINSIZE;
+#endif
+
+ } else {
+ priv->add_ba_param.rx_win_size =
+ priv->user_rxwinsize;
+ }
+ if (pmadapter->coex_win_size &&
+ pmadapter->coex_rx_win_size)
+ priv->add_ba_param.rx_win_size =
+ pmadapter->coex_rx_win_size;
+ if (rx_win_size != priv->add_ba_param.rx_win_size) {
+ if (priv->media_connected == MTRUE) {
+ for (i = 0; i < MAX_NUM_TID; i++)
+ wlan_11n_delba(priv, i);
+ wlan_recv_event(
+ priv,
+ MLAN_EVENT_ID_DRV_DEFER_HANDLING,
+ MNULL);
+ }
+ }
+ }
+ }
+ LEAVE();
+ return;
+}
+
+/**
+ * @brief check coex for
+ *
+ * @param pmadapter A pointer to mlan_adapter
+ *
+ * @return N/A
+ */
+void wlan_coex_ampdu_rxwinsize(pmlan_adapter pmadapter)
+{
+ t_u8 i;
+ pmlan_private priv = MNULL;
+ t_u8 count = 0;
+ for (i = 0; i < pmadapter->priv_num; i++) {
+ if (pmadapter->priv[i]) {
+ priv = pmadapter->priv[i];
+#ifdef STA_SUPPORT
+ if (GET_BSS_ROLE((mlan_private *)priv) ==
+ MLAN_BSS_ROLE_STA) {
+ if (priv->media_connected == MTRUE)
+ count++;
+ }
+#endif
+#ifdef UAP_SUPPORT
+ if (GET_BSS_ROLE((mlan_private *)priv) ==
+ MLAN_BSS_ROLE_UAP) {
+ if (priv->uap_bss_started)
+ count++;
+ }
+#endif
+ }
+ if (count >= 2)
+ break;
+ }
+ if (count >= 2)
+ wlan_update_ampdu_rxwinsize(pmadapter, MTRUE);
+ else
+ wlan_update_ampdu_rxwinsize(pmadapter, MFALSE);
+ return;
+}
diff --git a/drivers/net/wireless/nxp/mxm_wifiex/wlan_src/mlan/mlan_11n_rxreorder.h b/drivers/net/wireless/nxp/mxm_wifiex/wlan_src/mlan/mlan_11n_rxreorder.h
new file mode 100644
index 000000000000..7cab4350b1be
--- /dev/null
+++ b/drivers/net/wireless/nxp/mxm_wifiex/wlan_src/mlan/mlan_11n_rxreorder.h
@@ -0,0 +1,104 @@
+/** @file mlan_11n_rxreorder.h
+ *
+ * @brief This file contains related macros, enum, and struct
+ * of 11n RxReordering functionalities
+ *
+ *
+ * Copyright 2014-2020 NXP
+ *
+ * This software file (the File) is distributed by NXP
+ * under the terms of the GNU General Public License Version 2, June 1991
+ * (the License). You may use, redistribute and/or modify the 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.
+ *
+ */
+
+/********************************************************
+Change log:
+ 11/10/2008: initial version
+********************************************************/
+
+#ifndef _MLAN_11N_RXREORDER_H_
+#define _MLAN_11N_RXREORDER_H_
+
+/** Max value a TID can take = 2^12 = 4096 */
+#define MAX_TID_VALUE (2 << 11)
+/** 2^11 = 2048 */
+#define TWOPOW11 (2 << 10)
+
+/** Tid Mask used for extracting TID from BlockAckParamSet */
+#define BLOCKACKPARAM_TID_MASK 0x3C
+/** Tid position in BlockAckParamSet */
+#define BLOCKACKPARAM_TID_POS 2
+/** WinSize Mask used for extracting WinSize from BlockAckParamSet */
+#define BLOCKACKPARAM_WINSIZE_MASK 0xffc0
+/** WinSize Mask used for extracting WinSize from BlockAckParamSet */
+#define BLOCKACKPARAM_AMSDU_SUPP_MASK 0x1
+/** WinSize position in BlockAckParamSet */
+#define BLOCKACKPARAM_WINSIZE_POS 6
+/** Position of TID in DelBA Param set */
+#define DELBA_TID_POS 12
+/** Position of INITIATOR in DelBA Param set */
+#define DELBA_INITIATOR_POS 11
+/** Reason code: Requested from peer STA as it does not want to
+ * use the mechanism */
+#define REASON_CODE_STA_DONT_WANT 37
+/** Reason code: Requested from peer STA due to timeout*/
+#define REASON_CODE_STA_TIMEOUT 39
+/** Type: send delba command */
+#define TYPE_DELBA_SENT 1
+/** Type: recieve delba command */
+#define TYPE_DELBA_RECEIVE 2
+/** Set Initiator Bit */
+#define DELBA_INITIATOR(paramset) (paramset = (paramset | (1 << 11)))
+/** Reset Initiator Bit for recipient */
+#define DELBA_RECIPIENT(paramset) (paramset = (paramset & ~(1 << 11)))
+/** Immediate block ack */
+#define IMMEDIATE_BLOCK_ACK 0x2
+
+/** The request has been declined */
+#define ADDBA_RSP_STATUS_DECLINED 37
+/** ADDBA response status : Reject */
+#define ADDBA_RSP_STATUS_REJECT 1
+/** ADDBA response status : Accept */
+#define ADDBA_RSP_STATUS_ACCEPT 0
+
+/** DEFAULT SEQ NUM */
+#define DEFAULT_SEQ_NUM 0xffff
+
+/** Indicate packet has been dropped in FW */
+#define RX_PKT_DROPPED_IN_FW 0xffffffff
+
+mlan_status mlan_11n_rxreorder_pkt(void *priv, t_u16 seqNum, t_u16 tid,
+ t_u8 *ta, t_u8 pkttype, void *payload);
+void mlan_11n_delete_bastream_tbl(mlan_private *priv, int tid,
+ t_u8 *PeerMACAddr, t_u8 type, int initiator,
+ t_u16 reason_code);
+void wlan_11n_ba_stream_timeout(mlan_private *priv,
+ HostCmd_DS_11N_BATIMEOUT *event);
+mlan_status wlan_ret_11n_addba_resp(mlan_private *priv,
+ HostCmd_DS_COMMAND *resp);
+mlan_status wlan_cmd_11n_delba(mlan_private *priv, HostCmd_DS_COMMAND *cmd,
+ void *pdata_buf);
+mlan_status wlan_cmd_11n_addba_rspgen(mlan_private *priv,
+ HostCmd_DS_COMMAND *cmd, void *pdata_buf);
+mlan_status wlan_cmd_11n_addba_req(mlan_private *priv, HostCmd_DS_COMMAND *cmd,
+ void *pdata_buf);
+void wlan_11n_cleanup_reorder_tbl(mlan_private *priv);
+RxReorderTbl *wlan_11n_get_rxreorder_tbl(mlan_private *priv, int tid, t_u8 *ta);
+void wlan_11n_rxba_sync_event(mlan_private *priv, t_u8 *event_buf, t_u16 len);
+void wlan_update_rxreorder_tbl(pmlan_adapter pmadapter, t_u8 flag);
+void wlan_flush_rxreorder_tbl(pmlan_adapter pmadapter);
+void wlan_coex_ampdu_rxwinsize(pmlan_adapter pmadapter);
+
+/** clean up reorder_tbl */
+void wlan_cleanup_reorder_tbl(mlan_private *priv, t_u8 *ta);
+#endif /* _MLAN_11N_RXREORDER_H_ */
diff --git a/drivers/net/wireless/nxp/mxm_wifiex/wlan_src/mlan/mlan_cfp.c b/drivers/net/wireless/nxp/mxm_wifiex/wlan_src/mlan/mlan_cfp.c
new file mode 100644
index 000000000000..6ad3cca77be2
--- /dev/null
+++ b/drivers/net/wireless/nxp/mxm_wifiex/wlan_src/mlan/mlan_cfp.c
@@ -0,0 +1,3608 @@
+/**
+ * @file mlan_cfp.c
+ *
+ * @brief This file contains WLAN client mode channel, frequency and power
+ * related code
+ *
+ *
+ * Copyright 2014-2020 NXP
+ *
+ * This software file (the File) is distributed by NXP
+ * under the terms of the GNU General Public License Version 2, June 1991
+ * (the License). You may use, redistribute and/or modify the 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.
+ *
+ */
+
+/*************************************************************
+ * Change Log:
+ * 04/16/2009: initial version
+ ************************************************************/
+
+#include "mlan.h"
+#include "mlan_util.h"
+#include "mlan_fw.h"
+#include "mlan_join.h"
+#include "mlan_main.h"
+
+/********************************************************
+ * Local Variables
+ ********************************************************/
+
+/** 100mW */
+#define WLAN_TX_PWR_DEFAULT 20
+/** 100mW */
+#define WLAN_TX_PWR_00_DEFAULT 20
+/** 100mW */
+#define WLAN_TX_PWR_US_DEFAULT 20
+/** 100mW */
+#define WLAN_TX_PWR_JP_BG_DEFAULT 20
+/** 200mW */
+#define WLAN_TX_PWR_JP_A_DEFAULT 23
+/** 100mW */
+#define WLAN_TX_PWR_FR_100MW 20
+/** 10mW */
+#define WLAN_TX_PWR_FR_10MW 10
+/** 100mW */
+#define WLAN_TX_PWR_EMEA_DEFAULT 20
+/** 2000mW */
+#define WLAN_TX_PWR_CN_2000MW 33
+/** 200mW */
+#define WLAN_TX_PWR_200MW 23
+/** 1000mW */
+#define WLAN_TX_PWR_1000MW 30
+/** 30mW */
+#define WLAN_TX_PWR_SP_30MW 14
+/** 60mW */
+#define WLAN_TX_PWR_SP_60MW 17
+/** 25mW */
+#define WLAN_TX_PWR_25MW 14
+/** 250mW */
+#define WLAN_TX_PWR_250MW 24
+
+/** Region code mapping */
+typedef struct _country_code_mapping {
+ /** Region */
+ t_u8 country_code[COUNTRY_CODE_LEN];
+ /** Code for B/G CFP table */
+ t_u8 cfp_code_bg;
+ /** Code for A CFP table */
+ t_u8 cfp_code_a;
+} country_code_mapping_t;
+
+#define EU_CFP_CODE_BG 0x30
+#define EU_CFP_CODE_A 0x30
+
+/** Region code mapping table */
+static country_code_mapping_t country_code_mapping[] = {
+ {"WW", 0x00, 0x00}, /* World */
+ {"US", 0x10, 0x10}, /* US FCC */
+ {"CA", 0x10, 0x20}, /* IC Canada */
+ {"SG", 0x10, 0x10}, /* Singapore */
+ {"EU", 0x30, 0x30}, /* ETSI */
+ {"AU", 0x30, 0x30}, /* Australia */
+ {"KR", 0x30, 0x30}, /* Republic Of Korea */
+ {"JP", 0xFF, 0x40}, /* Japan */
+ {"CN", 0x30, 0x50}, /* China */
+ {"BR", 0x01, 0x09}, /* Brazil */
+ {"RU", 0x30, 0x0f}, /* Russia */
+ {"IN", 0x10, 0x06}, /* India */
+ {"MY", 0x30, 0x06}, /* Malaysia */
+ {"NZ", 0x30, 0x30}, /* New Zeland */
+ {"MX", 0x10, 0x07}, /* Mexico */
+};
+
+/** Country code for ETSI */
+static t_u8 eu_country_code_table[][COUNTRY_CODE_LEN] = {
+ "AL", "AD", "AT", "AU", "BY", "BE", "BA", "BG", "HR", "CY", "CZ", "DK",
+ "EE", "FI", "FR", "MK", "DE", "GR", "HU", "IS", "IE", "IT", "KR", "LV",
+ "LI", "LT", "LU", "MT", "MD", "MC", "ME", "NL", "NO", "PL", "RO", "RU",
+ "SM", "RS", "SI", "SK", "ES", "SE", "CH", "TR", "UA", "UK", "GB", "NZ"};
+
+/**
+ * The structure for Channel-Frequency-Power table
+ */
+typedef struct _cfp_table {
+ /** Region or Code */
+ t_u8 code;
+ /** Frequency/Power */
+ chan_freq_power_t *cfp;
+ /** No of CFP flag */
+ int cfp_no;
+} cfp_table_t;
+
+/* Format { Channel, Frequency (MHz), MaxTxPower } */
+/** Band : 'B/G', Region: World Wide Safe */
+static chan_freq_power_t channel_freq_power_00_BG[] = {
+ {1, 2412, WLAN_TX_PWR_00_DEFAULT, MFALSE, {0x1c, 0}},
+ {2, 2417, WLAN_TX_PWR_00_DEFAULT, MFALSE, {0x1c, 0}},
+ {3, 2422, WLAN_TX_PWR_00_DEFAULT, MFALSE, {0x1c, 0}},
+ {4, 2427, WLAN_TX_PWR_00_DEFAULT, MFALSE, {0x1c, 0}},
+ {5, 2432, WLAN_TX_PWR_00_DEFAULT, MFALSE, {0x1c, 0}},
+ {6, 2437, WLAN_TX_PWR_00_DEFAULT, MFALSE, {0x1c, 0}},
+ {7, 2442, WLAN_TX_PWR_00_DEFAULT, MFALSE, {0x1c, 0}},
+ {8, 2447, WLAN_TX_PWR_00_DEFAULT, MFALSE, {0x1c, 0}},
+ {9, 2452, WLAN_TX_PWR_00_DEFAULT, MFALSE, {0x1c, 0}},
+ {10, 2457, WLAN_TX_PWR_00_DEFAULT, MFALSE, {0x1c, 0}},
+ {11, 2462, WLAN_TX_PWR_00_DEFAULT, MFALSE, {0x1c, 0}},
+ {12, 2467, WLAN_TX_PWR_00_DEFAULT, MTRUE, {0x1f, 0}},
+ {13, 2472, WLAN_TX_PWR_00_DEFAULT, MTRUE, {0x1f, 0}}};
+/* Format { Channel, Frequency (MHz), MaxTxPower } */
+/** Band: 'B/G', Region: USA FCC/Canada IC */
+static chan_freq_power_t channel_freq_power_US_BG[] = {
+ {1, 2412, WLAN_TX_PWR_US_DEFAULT, MFALSE},
+ {2, 2417, WLAN_TX_PWR_US_DEFAULT, MFALSE},
+ {3, 2422, WLAN_TX_PWR_US_DEFAULT, MFALSE},
+ {4, 2427, WLAN_TX_PWR_US_DEFAULT, MFALSE},
+ {5, 2432, WLAN_TX_PWR_US_DEFAULT, MFALSE},
+ {6, 2437, WLAN_TX_PWR_US_DEFAULT, MFALSE},
+ {7, 2442, WLAN_TX_PWR_US_DEFAULT, MFALSE},
+ {8, 2447, WLAN_TX_PWR_US_DEFAULT, MFALSE},
+ {9, 2452, WLAN_TX_PWR_US_DEFAULT, MFALSE},
+ {10, 2457, WLAN_TX_PWR_US_DEFAULT, MFALSE},
+ {11, 2462, WLAN_TX_PWR_US_DEFAULT, MFALSE}};
+
+/** Band: 'B/G', Region: Europe ETSI/China */
+static chan_freq_power_t channel_freq_power_EU_BG[] = {
+ {1, 2412, WLAN_TX_PWR_EMEA_DEFAULT, MFALSE},
+ {2, 2417, WLAN_TX_PWR_EMEA_DEFAULT, MFALSE},
+ {3, 2422, WLAN_TX_PWR_EMEA_DEFAULT, MFALSE},
+ {4, 2427, WLAN_TX_PWR_EMEA_DEFAULT, MFALSE},
+ {5, 2432, WLAN_TX_PWR_EMEA_DEFAULT, MFALSE},
+ {6, 2437, WLAN_TX_PWR_EMEA_DEFAULT, MFALSE},
+ {7, 2442, WLAN_TX_PWR_EMEA_DEFAULT, MFALSE},
+ {8, 2447, WLAN_TX_PWR_EMEA_DEFAULT, MFALSE},
+ {9, 2452, WLAN_TX_PWR_EMEA_DEFAULT, MFALSE},
+ {10, 2457, WLAN_TX_PWR_EMEA_DEFAULT, MFALSE},
+ {11, 2462, WLAN_TX_PWR_EMEA_DEFAULT, MFALSE},
+ {12, 2467, WLAN_TX_PWR_EMEA_DEFAULT, MFALSE},
+ {13, 2472, WLAN_TX_PWR_EMEA_DEFAULT, MFALSE}};
+
+/** Band: 'B/G', Region: Japan */
+static chan_freq_power_t channel_freq_power_JPN41_BG[] = {
+ {1, 2412, WLAN_TX_PWR_JP_BG_DEFAULT, MFALSE},
+ {2, 2417, WLAN_TX_PWR_JP_BG_DEFAULT, MFALSE},
+ {3, 2422, WLAN_TX_PWR_JP_BG_DEFAULT, MFALSE},
+ {4, 2427, WLAN_TX_PWR_JP_BG_DEFAULT, MFALSE},
+ {5, 2432, WLAN_TX_PWR_JP_BG_DEFAULT, MFALSE},
+ {6, 2437, WLAN_TX_PWR_JP_BG_DEFAULT, MFALSE},
+ {7, 2442, WLAN_TX_PWR_JP_BG_DEFAULT, MFALSE},
+ {8, 2447, WLAN_TX_PWR_JP_BG_DEFAULT, MFALSE},
+ {9, 2452, WLAN_TX_PWR_JP_BG_DEFAULT, MFALSE},
+ {10, 2457, WLAN_TX_PWR_JP_BG_DEFAULT, MFALSE},
+ {11, 2462, WLAN_TX_PWR_JP_BG_DEFAULT, MFALSE},
+ {12, 2467, WLAN_TX_PWR_JP_BG_DEFAULT, MFALSE},
+ {13, 2472, WLAN_TX_PWR_JP_BG_DEFAULT, MFALSE}};
+
+/** Band: 'B/G', Region: Japan */
+static chan_freq_power_t channel_freq_power_JPN40_BG[] = {
+ {14, 2484, WLAN_TX_PWR_JP_BG_DEFAULT, MFALSE}};
+
+/** Band: 'B/G', Region: Japan */
+static chan_freq_power_t channel_freq_power_JPNFE_BG[] = {
+ {1, 2412, WLAN_TX_PWR_JP_BG_DEFAULT, MFALSE},
+ {2, 2417, WLAN_TX_PWR_JP_BG_DEFAULT, MFALSE},
+ {3, 2422, WLAN_TX_PWR_JP_BG_DEFAULT, MFALSE},
+ {4, 2427, WLAN_TX_PWR_JP_BG_DEFAULT, MFALSE},
+ {5, 2432, WLAN_TX_PWR_JP_BG_DEFAULT, MFALSE},
+ {6, 2437, WLAN_TX_PWR_JP_BG_DEFAULT, MFALSE},
+ {7, 2442, WLAN_TX_PWR_JP_BG_DEFAULT, MFALSE},
+ {8, 2447, WLAN_TX_PWR_JP_BG_DEFAULT, MFALSE},
+ {9, 2452, WLAN_TX_PWR_JP_BG_DEFAULT, MFALSE},
+ {10, 2457, WLAN_TX_PWR_JP_BG_DEFAULT, MFALSE},
+ {11, 2462, WLAN_TX_PWR_JP_BG_DEFAULT, MFALSE},
+ {12, 2467, WLAN_TX_PWR_JP_BG_DEFAULT, MTRUE},
+ {13, 2472, WLAN_TX_PWR_JP_BG_DEFAULT, MTRUE}};
+
+/** Band : 'B/G', Region: Brazil */
+static chan_freq_power_t channel_freq_power_BR_BG[] = {
+ {1, 2412, WLAN_TX_PWR_1000MW, MFALSE},
+ {2, 2417, WLAN_TX_PWR_1000MW, MFALSE},
+ {3, 2422, WLAN_TX_PWR_1000MW, MFALSE},
+ {4, 2427, WLAN_TX_PWR_1000MW, MFALSE},
+ {5, 2432, WLAN_TX_PWR_1000MW, MFALSE},
+ {6, 2437, WLAN_TX_PWR_1000MW, MFALSE},
+ {7, 2442, WLAN_TX_PWR_1000MW, MFALSE},
+ {8, 2447, WLAN_TX_PWR_1000MW, MFALSE},
+ {9, 2452, WLAN_TX_PWR_1000MW, MFALSE},
+ {10, 2457, WLAN_TX_PWR_1000MW, MFALSE},
+ {11, 2462, WLAN_TX_PWR_1000MW, MFALSE},
+ {12, 2467, WLAN_TX_PWR_1000MW, MFALSE},
+ {13, 2472, WLAN_TX_PWR_1000MW, MFALSE},
+};
+
+/** Band : 'B/G', Region: Special */
+static chan_freq_power_t channel_freq_power_SPECIAL_BG[] = {
+ {1, 2412, WLAN_TX_PWR_JP_BG_DEFAULT, MFALSE},
+ {2, 2417, WLAN_TX_PWR_JP_BG_DEFAULT, MFALSE},
+ {3, 2422, WLAN_TX_PWR_JP_BG_DEFAULT, MFALSE},
+ {4, 2427, WLAN_TX_PWR_JP_BG_DEFAULT, MFALSE},
+ {5, 2432, WLAN_TX_PWR_JP_BG_DEFAULT, MFALSE},
+ {6, 2437, WLAN_TX_PWR_JP_BG_DEFAULT, MFALSE},
+ {7, 2442, WLAN_TX_PWR_JP_BG_DEFAULT, MFALSE},
+ {8, 2447, WLAN_TX_PWR_JP_BG_DEFAULT, MFALSE},
+ {9, 2452, WLAN_TX_PWR_JP_BG_DEFAULT, MFALSE},
+ {10, 2457, WLAN_TX_PWR_JP_BG_DEFAULT, MFALSE},
+ {11, 2462, WLAN_TX_PWR_JP_BG_DEFAULT, MFALSE},
+ {12, 2467, WLAN_TX_PWR_JP_BG_DEFAULT, MFALSE},
+ {13, 2472, WLAN_TX_PWR_JP_BG_DEFAULT, MFALSE},
+ {14, 2484, WLAN_TX_PWR_JP_BG_DEFAULT, MFALSE}};
+
+/**
+ * The 2.4GHz CFP tables
+ */
+static cfp_table_t cfp_table_BG[] = {
+ {
+ 0x01, /* Brazil */
+ channel_freq_power_BR_BG,
+ NELEMENTS(channel_freq_power_BR_BG),
+ },
+ {
+ 0x00, /* World FCC */
+ channel_freq_power_00_BG,
+ NELEMENTS(channel_freq_power_00_BG),
+ },
+ {
+ 0x10, /* US FCC */
+ channel_freq_power_US_BG,
+ NELEMENTS(channel_freq_power_US_BG),
+ },
+ {
+ 0x20, /* CANADA IC */
+ channel_freq_power_US_BG,
+ NELEMENTS(channel_freq_power_US_BG),
+ },
+ {
+ 0x30, /* EU */
+ channel_freq_power_EU_BG,
+ NELEMENTS(channel_freq_power_EU_BG),
+ },
+ {
+ 0x40, /* JAPAN */
+ channel_freq_power_JPN40_BG,
+ NELEMENTS(channel_freq_power_JPN40_BG),
+ },
+ {
+ 0x41, /* JAPAN */
+ channel_freq_power_JPN41_BG,
+ NELEMENTS(channel_freq_power_JPN41_BG),
+ },
+ {
+ 0x50, /* China */
+ channel_freq_power_EU_BG,
+ NELEMENTS(channel_freq_power_EU_BG),
+ },
+ {
+ 0xfe, /* JAPAN */
+ channel_freq_power_JPNFE_BG,
+ NELEMENTS(channel_freq_power_JPNFE_BG),
+ },
+ {
+ 0xff, /* Special */
+ channel_freq_power_SPECIAL_BG,
+ NELEMENTS(channel_freq_power_SPECIAL_BG),
+ },
+ /* Add new region here */
+};
+
+/** Number of the CFP tables for 2.4GHz */
+#define MLAN_CFP_TABLE_SIZE_BG (NELEMENTS(cfp_table_BG))
+
+/* Format { Channel, Frequency (MHz), MaxTxPower, DFS } */
+/** Band: 'A', Region: World Wide Safe */
+static chan_freq_power_t channel_freq_power_00_A[] = {
+ {36, 5180, WLAN_TX_PWR_00_DEFAULT, MFALSE, {0x10, 0}},
+ {40, 5200, WLAN_TX_PWR_00_DEFAULT, MFALSE, {0x10, 0}},
+ {44, 5220, WLAN_TX_PWR_00_DEFAULT, MFALSE, {0x10, 0}},
+ {48, 5240, WLAN_TX_PWR_00_DEFAULT, MFALSE, {0x10, 0}},
+ {52, 5260, WLAN_TX_PWR_00_DEFAULT, MTRUE, {0x13, 0}},
+ {56, 5280, WLAN_TX_PWR_00_DEFAULT, MTRUE, {0x13, 0}},
+ {60, 5300, WLAN_TX_PWR_00_DEFAULT, MTRUE, {0x13, 0}},
+ {64, 5320, WLAN_TX_PWR_00_DEFAULT, MTRUE, {0x13, 0}},
+ {100, 5500, WLAN_TX_PWR_00_DEFAULT, MTRUE, {0x13, 0}},
+ {104, 5520, WLAN_TX_PWR_00_DEFAULT, MTRUE, {0x13, 0}},
+ {108, 5540, WLAN_TX_PWR_00_DEFAULT, MTRUE, {0x13, 0}},
+ {112, 5560, WLAN_TX_PWR_00_DEFAULT, MTRUE, {0x13, 0}},
+ {116, 5580, WLAN_TX_PWR_00_DEFAULT, MTRUE, {0x13, 0}},
+ {120, 5600, WLAN_TX_PWR_00_DEFAULT, MTRUE, {0x13, 0}},
+ {124, 5620, WLAN_TX_PWR_00_DEFAULT, MTRUE, {0x13, 0}},
+ {128, 5640, WLAN_TX_PWR_00_DEFAULT, MTRUE, {0x13, 0}},
+ {132, 5660, WLAN_TX_PWR_00_DEFAULT, MTRUE, {0x13, 0}},
+ {136, 5680, WLAN_TX_PWR_00_DEFAULT, MTRUE, {0x13, 0}},
+ {140, 5700, WLAN_TX_PWR_00_DEFAULT, MTRUE, {0x13, 0}},
+ {144, 5720, WLAN_TX_PWR_00_DEFAULT, MTRUE, {0x13, 0}},
+ {149, 5745, WLAN_TX_PWR_00_DEFAULT, MTRUE, {0x13, 0}},
+ {153, 5765, WLAN_TX_PWR_00_DEFAULT, MTRUE, {0x13, 0}},
+ {157, 5785, WLAN_TX_PWR_00_DEFAULT, MTRUE, {0x13, 0}},
+ {161, 5805, WLAN_TX_PWR_00_DEFAULT, MTRUE, {0x13, 0}},
+ {165, 5825, WLAN_TX_PWR_00_DEFAULT, MTRUE, {0x13, 0}}};
+/* Format { Channel, Frequency (MHz), MaxTxPower, DFS } */
+/** Band: 'A', Region: USA FCC */
+static chan_freq_power_t channel_freq_power_A[] = {
+ {36, 5180, WLAN_TX_PWR_US_DEFAULT, MFALSE},
+ {40, 5200, WLAN_TX_PWR_US_DEFAULT, MFALSE},
+ {44, 5220, WLAN_TX_PWR_US_DEFAULT, MFALSE},
+ {48, 5240, WLAN_TX_PWR_US_DEFAULT, MFALSE},
+ {52, 5260, WLAN_TX_PWR_US_DEFAULT, MTRUE},
+ {56, 5280, WLAN_TX_PWR_US_DEFAULT, MTRUE},
+ {60, 5300, WLAN_TX_PWR_US_DEFAULT, MTRUE},
+ {64, 5320, WLAN_TX_PWR_US_DEFAULT, MTRUE},
+ {100, 5500, WLAN_TX_PWR_US_DEFAULT, MTRUE},
+ {104, 5520, WLAN_TX_PWR_US_DEFAULT, MTRUE},
+ {108, 5540, WLAN_TX_PWR_US_DEFAULT, MTRUE},
+ {112, 5560, WLAN_TX_PWR_US_DEFAULT, MTRUE},
+ {116, 5580, WLAN_TX_PWR_US_DEFAULT, MTRUE},
+ {120, 5600, WLAN_TX_PWR_US_DEFAULT, MTRUE},
+ {124, 5620, WLAN_TX_PWR_US_DEFAULT, MTRUE},
+ {128, 5640, WLAN_TX_PWR_US_DEFAULT, MTRUE},
+ {132, 5660, WLAN_TX_PWR_US_DEFAULT, MTRUE},
+ {136, 5680, WLAN_TX_PWR_US_DEFAULT, MTRUE},
+ {140, 5700, WLAN_TX_PWR_US_DEFAULT, MTRUE},
+ {144, 5720, WLAN_TX_PWR_US_DEFAULT, MTRUE},
+ {149, 5745, WLAN_TX_PWR_US_DEFAULT, MFALSE},
+ {153, 5765, WLAN_TX_PWR_US_DEFAULT, MFALSE},
+ {157, 5785, WLAN_TX_PWR_US_DEFAULT, MFALSE},
+ {161, 5805, WLAN_TX_PWR_US_DEFAULT, MFALSE},
+ {165, 5825, WLAN_TX_PWR_US_DEFAULT, MFALSE}};
+
+/** Band: 'A', Region: Canada IC */
+static chan_freq_power_t channel_freq_power_CAN_A[] = {
+ {36, 5180, WLAN_TX_PWR_US_DEFAULT, MFALSE},
+ {40, 5200, WLAN_TX_PWR_US_DEFAULT, MFALSE},
+ {44, 5220, WLAN_TX_PWR_US_DEFAULT, MFALSE},
+ {48, 5240, WLAN_TX_PWR_US_DEFAULT, MFALSE},
+ {52, 5260, WLAN_TX_PWR_US_DEFAULT, MTRUE},
+ {56, 5280, WLAN_TX_PWR_US_DEFAULT, MTRUE},
+ {60, 5300, WLAN_TX_PWR_US_DEFAULT, MTRUE},
+ {64, 5320, WLAN_TX_PWR_US_DEFAULT, MTRUE},
+ {100, 5500, WLAN_TX_PWR_US_DEFAULT, MTRUE},
+ {104, 5520, WLAN_TX_PWR_US_DEFAULT, MTRUE},
+ {108, 5540, WLAN_TX_PWR_US_DEFAULT, MTRUE},
+ {112, 5560, WLAN_TX_PWR_US_DEFAULT, MTRUE},
+ {116, 5580, WLAN_TX_PWR_US_DEFAULT, MTRUE},
+ {132, 5660, WLAN_TX_PWR_US_DEFAULT, MTRUE},
+ {136, 5680, WLAN_TX_PWR_US_DEFAULT, MTRUE},
+ {140, 5700, WLAN_TX_PWR_US_DEFAULT, MTRUE},
+ {144, 5720, WLAN_TX_PWR_US_DEFAULT, MTRUE},
+ {149, 5745, WLAN_TX_PWR_US_DEFAULT, MFALSE},
+ {153, 5765, WLAN_TX_PWR_US_DEFAULT, MFALSE},
+ {157, 5785, WLAN_TX_PWR_US_DEFAULT, MFALSE},
+ {161, 5805, WLAN_TX_PWR_US_DEFAULT, MFALSE},
+ {165, 5825, WLAN_TX_PWR_US_DEFAULT, MFALSE}};
+
+/** Band: 'A', Region: Europe ETSI */
+static chan_freq_power_t channel_freq_power_EU_A[] = {
+ {36, 5180, WLAN_TX_PWR_EMEA_DEFAULT, MFALSE},
+ {40, 5200, WLAN_TX_PWR_EMEA_DEFAULT, MFALSE},
+ {44, 5220, WLAN_TX_PWR_EMEA_DEFAULT, MFALSE},
+ {48, 5240, WLAN_TX_PWR_EMEA_DEFAULT, MFALSE},
+ {52, 5260, WLAN_TX_PWR_EMEA_DEFAULT, MTRUE},
+ {56, 5280, WLAN_TX_PWR_EMEA_DEFAULT, MTRUE},
+ {60, 5300, WLAN_TX_PWR_EMEA_DEFAULT, MTRUE},
+ {64, 5320, WLAN_TX_PWR_EMEA_DEFAULT, MTRUE},
+ {100, 5500, WLAN_TX_PWR_EMEA_DEFAULT, MTRUE},
+ {104, 5520, WLAN_TX_PWR_EMEA_DEFAULT, MTRUE},
+ {108, 5540, WLAN_TX_PWR_EMEA_DEFAULT, MTRUE},
+ {112, 5560, WLAN_TX_PWR_EMEA_DEFAULT, MTRUE},
+ {116, 5580, WLAN_TX_PWR_EMEA_DEFAULT, MTRUE},
+ {120, 5600, WLAN_TX_PWR_EMEA_DEFAULT, MTRUE},
+ {124, 5620, WLAN_TX_PWR_EMEA_DEFAULT, MTRUE},
+ {128, 5640, WLAN_TX_PWR_EMEA_DEFAULT, MTRUE},
+ {132, 5660, WLAN_TX_PWR_EMEA_DEFAULT, MTRUE},
+ {136, 5680, WLAN_TX_PWR_EMEA_DEFAULT, MTRUE},
+ {140, 5700, WLAN_TX_PWR_EMEA_DEFAULT, MTRUE},
+ {149, 5745, WLAN_TX_PWR_EMEA_DEFAULT, MFALSE},
+ {153, 5765, WLAN_TX_PWR_EMEA_DEFAULT, MFALSE},
+ {157, 5785, WLAN_TX_PWR_EMEA_DEFAULT, MFALSE},
+ {161, 5805, WLAN_TX_PWR_EMEA_DEFAULT, MFALSE},
+ {165, 5825, WLAN_TX_PWR_EMEA_DEFAULT, MFALSE}};
+
+/** Band: 'A', Region: Japan */
+static chan_freq_power_t channel_freq_power_JPN_A[] = {
+ {36, 5180, WLAN_TX_PWR_JP_A_DEFAULT, MFALSE},
+ {40, 5200, WLAN_TX_PWR_JP_A_DEFAULT, MFALSE},
+ {44, 5220, WLAN_TX_PWR_JP_A_DEFAULT, MFALSE},
+ {48, 5240, WLAN_TX_PWR_JP_A_DEFAULT, MFALSE},
+ {52, 5260, WLAN_TX_PWR_JP_A_DEFAULT, MTRUE},
+ {56, 5280, WLAN_TX_PWR_JP_A_DEFAULT, MTRUE},
+ {60, 5300, WLAN_TX_PWR_JP_A_DEFAULT, MTRUE},
+ {64, 5320, WLAN_TX_PWR_JP_A_DEFAULT, MTRUE},
+ {100, 5500, WLAN_TX_PWR_JP_A_DEFAULT, MTRUE},
+ {104, 5520, WLAN_TX_PWR_JP_A_DEFAULT, MTRUE},
+ {108, 5540, WLAN_TX_PWR_JP_A_DEFAULT, MTRUE},
+ {112, 5560, WLAN_TX_PWR_JP_A_DEFAULT, MTRUE},
+ {116, 5580, WLAN_TX_PWR_JP_A_DEFAULT, MTRUE},
+ {120, 5600, WLAN_TX_PWR_JP_A_DEFAULT, MTRUE},
+ {124, 5620, WLAN_TX_PWR_JP_A_DEFAULT, MTRUE},
+ {128, 5640, WLAN_TX_PWR_JP_A_DEFAULT, MTRUE},
+ {132, 5660, WLAN_TX_PWR_JP_A_DEFAULT, MTRUE},
+ {136, 5680, WLAN_TX_PWR_JP_A_DEFAULT, MTRUE},
+ {140, 5700, WLAN_TX_PWR_JP_A_DEFAULT, MTRUE},
+ {144, 5720, WLAN_TX_PWR_JP_A_DEFAULT, MTRUE}};
+
+/** Band: 'A', Region: China */
+static chan_freq_power_t channel_freq_power_CN_A[] = {
+ {36, 5180, WLAN_TX_PWR_200MW, MFALSE},
+ {40, 5200, WLAN_TX_PWR_200MW, MFALSE},
+ {44, 5220, WLAN_TX_PWR_200MW, MFALSE},
+ {48, 5240, WLAN_TX_PWR_200MW, MFALSE},
+ {52, 5260, WLAN_TX_PWR_200MW, MTRUE},
+ {56, 5280, WLAN_TX_PWR_200MW, MTRUE},
+ {60, 5300, WLAN_TX_PWR_200MW, MTRUE},
+ {64, 5320, WLAN_TX_PWR_200MW, MTRUE},
+ {149, 5745, WLAN_TX_PWR_CN_2000MW, MFALSE},
+ {153, 5765, WLAN_TX_PWR_CN_2000MW, MFALSE},
+ {157, 5785, WLAN_TX_PWR_CN_2000MW, MFALSE},
+ {161, 5805, WLAN_TX_PWR_CN_2000MW, MFALSE},
+ {165, 5825, WLAN_TX_PWR_CN_2000MW, MFALSE}};
+
+/** Band: 'A', NULL */
+static chan_freq_power_t channel_freq_power_NULL_A[] = {};
+
+/** Band: 'A', Region: Spain/Austria/Brazil */
+static chan_freq_power_t channel_freq_power_SPN2_A[] = {
+ {36, 5180, WLAN_TX_PWR_200MW, MFALSE},
+ {40, 5200, WLAN_TX_PWR_200MW, MFALSE},
+ {44, 5220, WLAN_TX_PWR_200MW, MFALSE},
+ {48, 5240, WLAN_TX_PWR_200MW, MFALSE},
+ {52, 5260, WLAN_TX_PWR_200MW, MTRUE},
+ {56, 5280, WLAN_TX_PWR_200MW, MTRUE},
+ {60, 5300, WLAN_TX_PWR_200MW, MTRUE},
+ {64, 5320, WLAN_TX_PWR_200MW, MTRUE},
+};
+
+/** Band: 'A', Region: Brazil */
+static chan_freq_power_t channel_freq_power_BR1_A[] = {
+ {100, 5500, WLAN_TX_PWR_250MW, MTRUE},
+ {104, 5520, WLAN_TX_PWR_250MW, MTRUE},
+ {108, 5540, WLAN_TX_PWR_250MW, MTRUE},
+ {112, 5560, WLAN_TX_PWR_250MW, MTRUE},
+ {116, 5580, WLAN_TX_PWR_250MW, MTRUE},
+ {120, 5600, WLAN_TX_PWR_250MW, MTRUE},
+ {124, 5620, WLAN_TX_PWR_250MW, MTRUE},
+ {128, 5640, WLAN_TX_PWR_250MW, MTRUE},
+ {132, 5660, WLAN_TX_PWR_250MW, MTRUE},
+ {136, 5680, WLAN_TX_PWR_250MW, MTRUE},
+ {140, 5700, WLAN_TX_PWR_250MW, MTRUE},
+};
+
+/** Band: 'A', Region: Brazil */
+static chan_freq_power_t channel_freq_power_BR2_A[] = {
+ {149, 5745, WLAN_TX_PWR_1000MW, MFALSE},
+ {153, 5765, WLAN_TX_PWR_1000MW, MFALSE},
+ {157, 5785, WLAN_TX_PWR_1000MW, MFALSE},
+ {161, 5805, WLAN_TX_PWR_1000MW, MFALSE},
+ {165, 5825, WLAN_TX_PWR_1000MW, MFALSE}};
+
+/** Band: 'A', Region: Russia */
+static chan_freq_power_t channel_freq_power_RU_A[] = {
+ {36, 5180, WLAN_TX_PWR_DEFAULT, MFALSE},
+ {40, 5200, WLAN_TX_PWR_DEFAULT, MFALSE},
+ {44, 5220, WLAN_TX_PWR_DEFAULT, MFALSE},
+ {48, 5240, WLAN_TX_PWR_DEFAULT, MFALSE},
+ {52, 5260, WLAN_TX_PWR_DEFAULT, MFALSE},
+ {56, 5280, WLAN_TX_PWR_DEFAULT, MFALSE},
+ {60, 5300, WLAN_TX_PWR_DEFAULT, MFALSE},
+ {64, 5320, WLAN_TX_PWR_DEFAULT, MFALSE},
+ {132, 5660, WLAN_TX_PWR_DEFAULT, MFALSE},
+ {136, 5680, WLAN_TX_PWR_DEFAULT, MFALSE},
+ {140, 5700, WLAN_TX_PWR_DEFAULT, MFALSE},
+ {149, 5745, WLAN_TX_PWR_DEFAULT, MFALSE},
+ {153, 5765, WLAN_TX_PWR_DEFAULT, MFALSE},
+ {157, 5785, WLAN_TX_PWR_DEFAULT, MFALSE},
+ {161, 5805, WLAN_TX_PWR_DEFAULT, MFALSE},
+};
+
+/** Band: 'A', Region: Mexico */
+static chan_freq_power_t channel_freq_power_MX_A[] = {
+ {36, 5180, WLAN_TX_PWR_EMEA_DEFAULT, MFALSE},
+ {40, 5200, WLAN_TX_PWR_EMEA_DEFAULT, MFALSE},
+ {44, 5220, WLAN_TX_PWR_EMEA_DEFAULT, MFALSE},
+ {48, 5240, WLAN_TX_PWR_EMEA_DEFAULT, MFALSE},
+ {52, 5260, WLAN_TX_PWR_EMEA_DEFAULT, MTRUE},
+ {56, 5280, WLAN_TX_PWR_EMEA_DEFAULT, MTRUE},
+ {60, 5300, WLAN_TX_PWR_EMEA_DEFAULT, MTRUE},
+ {64, 5320, WLAN_TX_PWR_EMEA_DEFAULT, MTRUE},
+ {100, 5500, WLAN_TX_PWR_EMEA_DEFAULT, MTRUE},
+ {104, 5520, WLAN_TX_PWR_EMEA_DEFAULT, MTRUE},
+ {108, 5540, WLAN_TX_PWR_EMEA_DEFAULT, MTRUE},
+ {112, 5560, WLAN_TX_PWR_EMEA_DEFAULT, MTRUE},
+ {116, 5580, WLAN_TX_PWR_EMEA_DEFAULT, MTRUE},
+ {132, 5660, WLAN_TX_PWR_EMEA_DEFAULT, MTRUE},
+ {136, 5680, WLAN_TX_PWR_EMEA_DEFAULT, MTRUE},
+ {140, 5700, WLAN_TX_PWR_EMEA_DEFAULT, MTRUE},
+ {149, 5745, WLAN_TX_PWR_EMEA_DEFAULT, MFALSE},
+ {153, 5765, WLAN_TX_PWR_EMEA_DEFAULT, MFALSE},
+ {157, 5785, WLAN_TX_PWR_EMEA_DEFAULT, MFALSE},
+ {161, 5805, WLAN_TX_PWR_EMEA_DEFAULT, MFALSE},
+ {165, 5825, WLAN_TX_PWR_EMEA_DEFAULT, MFALSE}};
+
+/** Band: 'A', Code: 1, Low band (5150-5250 MHz) channels */
+static chan_freq_power_t channel_freq_power_low_band[] = {
+ {36, 5180, WLAN_TX_PWR_DEFAULT, MFALSE},
+ {40, 5200, WLAN_TX_PWR_DEFAULT, MFALSE},
+ {44, 5220, WLAN_TX_PWR_DEFAULT, MFALSE},
+ {48, 5240, WLAN_TX_PWR_DEFAULT, MFALSE},
+};
+
+/** Band: 'A', Code: 2, Lower middle band (5250-5350 MHz) channels */
+static chan_freq_power_t channel_freq_power_lower_middle_band[] = {
+ {52, 5260, WLAN_TX_PWR_DEFAULT, MTRUE},
+ {56, 5280, WLAN_TX_PWR_DEFAULT, MTRUE},
+ {60, 5300, WLAN_TX_PWR_DEFAULT, MTRUE},
+ {64, 5320, WLAN_TX_PWR_DEFAULT, MTRUE},
+};
+
+/** Band: 'A', Code: 3, Upper middle band (5470-5725 MHz) channels */
+static chan_freq_power_t channel_freq_power_upper_middle_band[] = {
+ {100, 5500, WLAN_TX_PWR_DEFAULT, MTRUE},
+ {104, 5520, WLAN_TX_PWR_DEFAULT, MTRUE},
+ {108, 5540, WLAN_TX_PWR_DEFAULT, MTRUE},
+ {112, 5560, WLAN_TX_PWR_DEFAULT, MTRUE},
+ {116, 5580, WLAN_TX_PWR_DEFAULT, MTRUE},
+ {120, 5600, WLAN_TX_PWR_DEFAULT, MTRUE},
+ {124, 5620, WLAN_TX_PWR_DEFAULT, MTRUE},
+ {128, 5640, WLAN_TX_PWR_DEFAULT, MTRUE},
+ {132, 5660, WLAN_TX_PWR_DEFAULT, MTRUE},
+ {136, 5680, WLAN_TX_PWR_DEFAULT, MTRUE},
+ {140, 5700, WLAN_TX_PWR_DEFAULT, MTRUE},
+};
+
+/** Band: 'A', Code: 4, High band (5725-5850 MHz) channels */
+static chan_freq_power_t channel_freq_power_high_band[] = {
+ {149, 5745, WLAN_TX_PWR_DEFAULT, MFALSE},
+ {153, 5765, WLAN_TX_PWR_DEFAULT, MFALSE},
+ {157, 5785, WLAN_TX_PWR_DEFAULT, MFALSE},
+ {161, 5805, WLAN_TX_PWR_DEFAULT, MFALSE},
+ {165, 5825, WLAN_TX_PWR_DEFAULT, MFALSE}};
+
+/** Band: 'A', Code: 5, Low band (5150-5250 MHz) and
+ * High band (5725-5850 MHz) channels
+ */
+static chan_freq_power_t channel_freq_power_low_high_band[] = {
+ {36, 5180, WLAN_TX_PWR_DEFAULT, MFALSE},
+ {40, 5200, WLAN_TX_PWR_DEFAULT, MFALSE},
+ {44, 5220, WLAN_TX_PWR_DEFAULT, MFALSE},
+ {48, 5240, WLAN_TX_PWR_DEFAULT, MFALSE},
+ {149, 5745, WLAN_TX_PWR_DEFAULT, MFALSE},
+ {153, 5765, WLAN_TX_PWR_DEFAULT, MFALSE},
+ {157, 5785, WLAN_TX_PWR_DEFAULT, MFALSE},
+ {161, 5805, WLAN_TX_PWR_DEFAULT, MFALSE},
+ {165, 5825, WLAN_TX_PWR_DEFAULT, MFALSE}};
+
+/** Band: 'A', Code: 6, Low band (5150-5250 MHz) and
+ * mid low (5260-5320) and High band (5725-5850 MHz) channels
+ */
+static chan_freq_power_t channel_freq_power_low_middle_high_band[] = {
+ {36, 5180, WLAN_TX_PWR_DEFAULT, MFALSE},
+ {40, 5200, WLAN_TX_PWR_DEFAULT, MFALSE},
+ {44, 5220, WLAN_TX_PWR_DEFAULT, MFALSE},
+ {48, 5240, WLAN_TX_PWR_DEFAULT, MFALSE},
+ {52, 5260, WLAN_TX_PWR_DEFAULT, MFALSE},
+ {56, 5280, WLAN_TX_PWR_DEFAULT, MFALSE},
+ {60, 5300, WLAN_TX_PWR_DEFAULT, MFALSE},
+ {64, 5320, WLAN_TX_PWR_DEFAULT, MFALSE},
+ {149, 5745, WLAN_TX_PWR_DEFAULT, MFALSE},
+ {153, 5765, WLAN_TX_PWR_DEFAULT, MFALSE},
+ {157, 5785, WLAN_TX_PWR_DEFAULT, MFALSE},
+ {161, 5805, WLAN_TX_PWR_DEFAULT, MFALSE},
+ {165, 5825, WLAN_TX_PWR_DEFAULT, MFALSE}};
+
+/**
+ * The 5GHz CFP tables
+ */
+static cfp_table_t cfp_table_A[] = {
+ {0x1, /* Low band (5150-5250 MHz) channels */
+ channel_freq_power_low_band, NELEMENTS(channel_freq_power_low_band)},
+ {0x2, /* Lower middle band (5250-5350 MHz) channels */
+ channel_freq_power_lower_middle_band,
+ NELEMENTS(channel_freq_power_lower_middle_band)},
+ {0x3, /* Upper middle band (5470-5725 MHz) channels */
+ channel_freq_power_upper_middle_band,
+ NELEMENTS(channel_freq_power_upper_middle_band)},
+ {0x4, /* High band (5725-5850 MHz) channels */
+ channel_freq_power_high_band, NELEMENTS(channel_freq_power_high_band)},
+ {0x5, /* Low band (5150-5250 MHz) and
+ * High band (5725-5850 MHz) channels
+ */
+ channel_freq_power_low_high_band,
+ NELEMENTS(channel_freq_power_low_high_band)},
+ {0x6, /* Low band (5150-5250 MHz)
+ * Mid band (5260-5320) and
+ * High band (5725-5850 MHz) channels
+ */
+ channel_freq_power_low_middle_high_band,
+ NELEMENTS(channel_freq_power_low_middle_high_band)},
+ {
+ 0x07, /* Mexico */
+ channel_freq_power_MX_A,
+ NELEMENTS(channel_freq_power_MX_A),
+ },
+
+ {
+ 0x09, /* SPAIN/Austria/Brazil */
+ channel_freq_power_SPN2_A,
+ NELEMENTS(channel_freq_power_SPN2_A),
+ },
+ {
+ 0x0c, /* Brazil */
+ channel_freq_power_BR1_A,
+ NELEMENTS(channel_freq_power_BR1_A),
+ },
+ {
+ 0x0e, /* Brazil */
+ channel_freq_power_BR2_A,
+ NELEMENTS(channel_freq_power_BR2_A),
+ },
+ {
+ 0x0f, /* Russia */
+ channel_freq_power_RU_A,
+ NELEMENTS(channel_freq_power_RU_A),
+ },
+ {
+ 0x00, /* World */
+ channel_freq_power_00_A,
+ NELEMENTS(channel_freq_power_00_A),
+ },
+ {
+ 0x10, /* US FCC */
+ channel_freq_power_A,
+ NELEMENTS(channel_freq_power_A),
+ },
+ {
+ 0x20, /* CANADA IC */
+ channel_freq_power_CAN_A,
+ NELEMENTS(channel_freq_power_CAN_A),
+ },
+ {
+ 0x30, /* EU */
+ channel_freq_power_EU_A,
+ NELEMENTS(channel_freq_power_EU_A),
+ },
+ {
+ 0x40, /* JAPAN */
+ channel_freq_power_JPN_A,
+ NELEMENTS(channel_freq_power_JPN_A),
+ },
+ {
+ 0x41, /* JAPAN */
+ channel_freq_power_JPN_A,
+ NELEMENTS(channel_freq_power_JPN_A),
+ },
+ {
+ 0x50, /* China */
+ channel_freq_power_CN_A,
+ NELEMENTS(channel_freq_power_CN_A),
+ },
+ {
+ 0xfe, /* JAPAN */
+ channel_freq_power_NULL_A,
+ NELEMENTS(channel_freq_power_NULL_A),
+ },
+ {
+ 0xff, /* Special */
+ channel_freq_power_JPN_A,
+ NELEMENTS(channel_freq_power_JPN_A),
+ },
+ /* Add new region here */
+};
+/** Number of the CFP tables for 5GHz */
+#define MLAN_CFP_TABLE_SIZE_A (NELEMENTS(cfp_table_A))
+
+enum { RATEID_DBPSK1Mbps, //(0)
+ RATEID_DQPSK2Mbps, //(1)
+ RATEID_CCK5_5Mbps, //(2)
+ RATEID_CCK11Mbps, //(3)
+ RATEID_CCK22Mbps, //(4)
+ RATEID_OFDM6Mbps, //(5)
+ RATEID_OFDM9Mbps, //(6)
+ RATEID_OFDM12Mbps, //(7)
+ RATEID_OFDM18Mbps, //(8)
+ RATEID_OFDM24Mbps, //(9)
+ RATEID_OFDM36Mbps, //(10)
+ RATEID_OFDM48Mbps, //(11)
+ RATEID_OFDM54Mbps, //(12)
+ RATEID_OFDM72Mbps, //(13)
+};
+
+static const t_u8 rateUnit_500Kbps[] = {
+ (10 / 5), /* 1Mbps */
+ (20 / 5), /* 2Mbps */
+
+ (55 / 5), /* 5.5Mbps */
+ (110 / 5), /* 11Mbps */
+ (10 / 5), /* 22Mbps, intentionally set to 1Mbps
+ * because it's not available
+ */
+
+ (60 / 5), /* 6Mbps */
+ (90 / 5), /* 9Mbps */
+ (120 / 5), /* 12Mbps */
+ (180 / 5), /* 18Mbps */
+ (240 / 5), /* 24Mbps */
+ (360 / 5), /* 36Mbps */
+ (480 / 5), /* 48Mbps */
+ (540 / 5), /* 54Mbps */
+ (60 / 5), /* 72Mbps, intentionally set to 6Mbps
+ * because it's not available
+ */
+};
+
+typedef struct _rate_map {
+ /** Rate, in 0.5Mbps */
+ t_u32 rate;
+ /** Mrvl rate id, refer to RATEID_XXX in FW */
+ t_u32 id;
+ /** nss: 0-nss1, 1-nss2 */
+ t_u8 nss;
+} rate_map;
+
+/** If user configure to 1x1 or we found peer device only support 1x1,
+ * then we need skip the nss1 part when map to Mrvl rate.
+ */
+const rate_map rate_map_table_2x2[] = {
+ /* LG <--> Mrvl rate idx */
+ {2, 0, 0}, // RATEID_DBPSK1Mbps
+ {4, 1, 0}, // RATEID_DQPSK2Mbps
+ {11, 2, 0}, // RATEID_CCK5_5Mbps
+ {22, 3, 0}, // RATEID_CCK11Mbps
+ {44, 4, 0}, // RATEID_CCK22Mbps
+ {12, 5, 0}, // RATEID_OFDM6Mbps
+ {18, 6, 0}, // RATEID_OFDM9Mbps
+ {24, 7, 0}, // RATEID_OFDM12Mbps
+ {36, 8, 0}, // RATEID_OFDM18Mbps
+ {48, 9, 0}, // RATEID_OFDM24Mbps
+ {72, 10, 0}, // RATEID_OFDM36Mbps
+ {96, 11, 0}, // RATEID_OFDM48Mbps
+ {108, 12, 0}, // RATEID_OFDM54Mbps
+ {144, 13, 0}, // RATEID_OFDM72Mbps
+
+ /* HT bw20 <--> Mrvl rate idx - nss2 */
+ {26, 22, 1}, // RATEID_MCS8_13Mbps
+ {52, 23, 1}, // RATEID_MCS9_26Mbps
+ {78, 24, 1}, // RATEID_MCS10_39Mbps
+ {104, 25, 1}, // RATEID_MCS11_52Mbps
+ {156, 26, 1}, // RATEID_MCS12_78Mbps
+ {208, 27, 1}, // RATEID_MCS13_104Mbps
+ {234, 28, 1}, // RATEID_MCS14_117Mbps
+ {260, 29, 1}, // RATEID_MCS15_130Mbps
+ /* HT bw20 <--> Mrvl rate idx - nss1 */
+ {13, 14, 0}, // RATEID_MCS0_6d5Mbps
+ {26, 15, 0}, // RATEID_MCS1_13Mbps
+ {39, 16, 0}, // RATEID_MCS2_19d5Mbps
+ {52, 17, 0}, // RATEID_MCS3_26Mbps
+ {78, 18, 0}, // RATEID_MCS4_39Mbps
+ {104, 19, 0}, // RATEID_MCS5_52Mbps
+ {117, 20, 0}, // RATEID_MCS6_58d5Mbps
+ {130, 21, 0}, // RATEID_MCS7_65Mbps
+
+ /* HT bw40<--> Mrvl rate idx - nss2 */
+ {54, 39, 1}, // RATEID_MCS8BW40_27Mbps
+ {108, 40, 1}, // RATEID_MCS9BW40_54Mbps
+ {162, 41, 1}, // RATEID_MCS10BW40_81Mbps
+ {216, 42, 1}, // RATEID_MCS11BW40_108Mbps
+ {324, 43, 1}, // RATEID_MCS12BW40_162Mbps
+ {432, 44, 1}, // RATEID_MCS13BW40_216Mbps
+ {486, 45, 1}, // RATEID_MCS14BW40_243Mbps
+ {540, 46, 1}, // RATEID_MCS15BW40_270Mbps
+ /* HT bw40<--> Mrvl rate idx - nss1 */
+ {12, 30, 0}, // RATEID_MCS32BW40_6Mbps
+ {27, 31, 0}, // RATEID_MCS0BW40_13d5Mbps
+ {54, 32, 0}, // RATEID_MCS1BW40_27Mbps
+ {81, 33, 0}, // RATEID_MCS2BW40_40d5Mbps
+ {108, 34, 0}, // RATEID_MCS3BW40_54Mbps
+ {162, 35, 0}, // RATEID_MCS4BW40_81Mbps
+ {216, 36, 0}, // RATEID_MCS5BW40_108Mbps
+ {243, 37, 0}, // RATEID_MCS6BW40_121d5Mbps
+ {270, 38, 0}, // RATEID_MCS7BW40_135Mbps
+
+ /* VHT bw20<--> Mrvl rate idx - nss2 */
+ {26, 57, 1}, // RATEID_VHT_MCS0_2SS_BW20 13 Mbps
+ {52, 58, 1}, // RATEID_VHT_MCS1_2SS_BW20 26 Mbps
+ {78, 59, 1}, // RATEID_VHT_MCS2_2SS_BW20 39 Mbps
+ {104, 60, 1}, // RATEID_VHT_MCS3_2SS_BW20 52 Mbps
+ {156, 61, 1}, // RATEID_VHT_MCS4_2SS_BW20 78 Mbps
+ {208, 62, 1}, // RATEID_VHT_MCS5_2SS_BW20 104 Mbps
+ {234, 63, 1}, // RATEID_VHT_MCS6_2SS_BW20 117 Mbps
+ {260, 64, 1}, // RATEID_VHT_MCS7_2SS_BW20 130 Mbps
+ {312, 65, 1}, // RATEID_VHT_MCS8_2SS_BW20 156 Mbps
+ {0, 66, 1}, // RATEID_VHT_MCS9_2SS_BW20 173.3 Mbps(INVALID)
+ /* VHT bw20<--> Mrvl rate idx - nss1 */
+ {13, 47, 0}, // RATEID_VHT_MCS0_1SS_BW20 6.5 Mbps
+ {26, 48, 0}, // RATEID_VHT_MCS1_1SS_BW20 13 Mbps
+ {39, 49, 0}, // RATEID_VHT_MCS2_1SS_BW20 19.5 Mbps
+ {52, 50, 0}, // RATEID_VHT_MCS3_1SS_BW20 26 Mbps
+ {78, 51, 0}, // RATEID_VHT_MCS4_1SS_BW20 39 Mbps
+ {104, 52, 0}, // RATEID_VHT_MCS5_1SS_BW20 52 Mbps
+ {117, 53, 0}, // RATEID_VHT_MCS6_1SS_BW20 58.5 Mbps
+ {130, 54, 0}, // RATEID_VHT_MCS7_1SS_BW20 65 Mbps
+ {156, 55, 0}, // RATEID_VHT_MCS8_1SS_BW20 78 Mbps
+ {0, 56, 0}, // RATEID_VHT_MCS9_1SS_BW20 86.7 Mbps(INVALID)
+
+ /* VHT bw40<--> Mrvl rate idx - nss2 */
+ {54, 77, 1}, // RATEID_VHT_MCS0_2SS_BW40 27 Mbps
+ {108, 78, 1}, // RATEID_VHT_MCS1_2SS_BW40 54 Mbps
+ {162, 79, 1}, // RATEID_VHT_MCS2_2SS_BW40 81 Mbps
+ {216, 80, 1}, // RATEID_VHT_MCS3_2SS_BW40 108 Mbps
+ {324, 81, 1}, // RATEID_VHT_MCS4_2SS_BW40 162 Mbps
+ {432, 82, 1}, // RATEID_VHT_MCS5_2SS_BW40 216 Mbps
+ {486, 83, 1}, // RATEID_VHT_MCS6_2SS_BW40 243 Mbps
+ {540, 84, 1}, // RATEID_VHT_MCS7_2SS_BW40 270 Mbps
+ {648, 85, 1}, // RATEID_VHT_MCS8_2SS_BW40 324 Mbps
+ {720, 86, 1}, // RATEID_VHT_MCS9_2SS_BW40 360 Mbps
+ /* VHT bw40<--> Mrvl rate idx - nss1 */
+ {27, 67, 0}, // RATEID_VHT_MCS0_1SS_BW40 13.5 Mbps
+ {54, 68, 0}, // RATEID_VHT_MCS1_1SS_BW40 27 Mbps
+ {81, 69, 0}, // RATEID_VHT_MCS2_1SS_BW40 40.5 Mbps
+ {108, 70, 0}, // RATEID_VHT_MCS3_1SS_BW40 54 Mbps
+ {162, 71, 0}, // RATEID_VHT_MCS4_1SS_BW40 81 Mbps
+ {216, 72, 0}, // RATEID_VHT_MCS5_1SS_BW40 108 Mbps
+ {243, 73, 0}, // RATEID_VHT_MCS6_1SS_BW40 121.5 Mbps
+ {270, 74, 0}, // RATEID_VHT_MCS7_1SS_BW40 135 Mbps
+ {324, 75, 0}, // RATEID_VHT_MCS8_1SS_BW40 162 Mbps
+ {360, 76, 0}, // RATEID_VHT_MCS9_1SS_BW40 180 Mbps
+
+ /* VHT bw80<--> Mrvl rate idx - nss2 */
+ {117, 97, 1}, // RATEID_VHT_MCS0_2SS_BW80 58.5 Mbps
+ {234, 98, 1}, // RATEID_VHT_MCS1_2SS_BW80 117 Mbps
+ {350, 99, 1}, // RATEID_VHT_MCS2_2SS_BW80 175 Mbps
+ {468, 100, 1}, // RATEID_VHT_MCS3_2SS_BW80 234 Mbps
+ {702, 101, 1}, // RATEID_VHT_MCS4_2SS_BW80 351 Mbps
+ {936, 102, 1}, // RATEID_VHT_MCS5_2SS_BW80 468 Mbps
+ {1053, 103, 1}, // RATEID_VHT_MCS6_2SS_BW80 526.5 Mbps
+ {1170, 104, 1}, // RATEID_VHT_MCS7_2SS_BW80 585 Mbps
+ {1404, 105, 1}, // RATEID_VHT_MCS8_2SS_BW80 702 Mbps
+ {1560, 106, 1}, // RATEID_VHT_MCS9_2SS_BW80 780 Mbps
+ /* VHT bw80<--> Mrvl rate idx - nss1 */
+ {58, 87, 0}, // RATEID_VHT_MCS0_1SS_BW80 29.3 Mbps, 29.3x2 could
+ // correspond to 58
+ {59, 87, 0}, // RATEID_VHT_MCS0_1SS_BW80 29.3 Mbps, 29.3*2 could
+ // correspond to 59 too
+ {117, 88, 0}, // RATEID_VHT_MCS1_1SS_BW80 58.5 Mbps
+ {175, 89, 0}, // RATEID_VHT_MCS2_1SS_BW80 87.8 Mbps, 87.8x2 could
+ // correspond to 175
+ {176, 89, 0}, // RATEID_VHT_MCS2_1SS_BW80 87.8 Mbps, 87.8x2 could
+ // correspond to 176 too
+ {234, 90, 0}, // RATEID_VHT_MCS3_1SS_BW80 117 Mbps
+ {351, 91, 0}, // RATEID_VHT_MCS4_1SS_BW80 175.5 Mbps
+ {468, 92, 0}, // RATEID_VHT_MCS5_1SS_BW80 234 Mbps
+ {526, 93, 0}, // RATEID_VHT_MCS6_1SS_BW80 263.3 Mbps, 263.3x2 could
+ // correspond to 526
+ {527, 93, 0}, // RATEID_VHT_MCS6_1SS_BW80 263.3 Mbps, 263.3x2 could
+ // correspond to 527 too
+ {585, 94, 0}, // RATEID_VHT_MCS7_1SS_BW80 292.5 Mbps
+ {702, 95, 0}, // RATEID_VHT_MCS8_1SS_BW80 351 Mbps
+ {780, 96, 0}, // RATEID_VHT_MCS9_1SS_BW80 390 Mbps
+};
+
+/** rate_map_table_1x1 is based on rate_map_table_2x2 and remove nss2 part.
+ * For the chip who only support 1x1, Mrvl rate idx define is different with 2x2
+ * in FW We need redefine a bitrate to Mrvl rate idx table for 1x1 chip.
+ */
+const rate_map rate_map_table_1x1[] = {
+ /* LG <--> Mrvl rate idx */
+ {2, 0, 0}, // RATEID_DBPSK1Mbps
+ {4, 1, 0}, // RATEID_DQPSK2Mbps
+ {11, 2, 0}, // RATEID_CCK5_5Mbps
+ {22, 3, 0}, // RATEID_CCK11Mbps
+ {44, 4, 0}, // RATEID_CCK22Mbps
+ {12, 5, 0}, // RATEID_OFDM6Mbps
+ {18, 6, 0}, // RATEID_OFDM9Mbps
+ {24, 7, 0}, // RATEID_OFDM12Mbps
+ {36, 8, 0}, // RATEID_OFDM18Mbps
+ {48, 9, 0}, // RATEID_OFDM24Mbps
+ {72, 10, 0}, // RATEID_OFDM36Mbps
+ {96, 11, 0}, // RATEID_OFDM48Mbps
+ {108, 12, 0}, // RATEID_OFDM54Mbps
+ {144, 13, 0}, // RATEID_OFDM72Mbps
+
+ /* HT bw20 <--> Mrvl rate idx */
+ {13, 14, 0}, // RATEID_MCS0_6d5Mbps
+ {26, 15, 0}, // RATEID_MCS1_13Mbps
+ {39, 16, 0}, // RATEID_MCS2_19d5Mbps
+ {52, 17, 0}, // RATEID_MCS3_26Mbps
+ {78, 18, 0}, // RATEID_MCS4_39Mbps
+ {104, 19, 0}, // RATEID_MCS5_52Mbps
+ {117, 20, 0}, // RATEID_MCS6_58d5Mbps
+ {130, 21, 0}, // RATEID_MCS7_65Mbps
+
+ /* HT bw40<--> Mrvl rate idx */
+ {12, 22, 0}, // RATEID_MCS32BW40_6Mbps, for 1x1 start from 22
+ {27, 23, 0}, // RATEID_MCS0BW40_13d5Mbps
+ {54, 24, 0}, // RATEID_MCS1BW40_27Mbps
+ {81, 25, 0}, // RATEID_MCS2BW40_40d5Mbps
+ {108, 26, 0}, // RATEID_MCS3BW40_54Mbps
+ {162, 27, 0}, // RATEID_MCS4BW40_81Mbps
+ {216, 28, 0}, // RATEID_MCS5BW40_108Mbps
+ {243, 29, 0}, // RATEID_MCS6BW40_121d5Mbps
+ {270, 30, 0}, // RATEID_MCS7BW40_135Mbps
+
+ /* VHT bw20<--> Mrvl rate idx */
+ {13, 31, 0}, // RATEID_VHT_MCS0_1SS_BW20 6.5 Mbps
+ {26, 32, 0}, // RATEID_VHT_MCS1_1SS_BW20 13 Mbps
+ {39, 33, 0}, // RATEID_VHT_MCS2_1SS_BW20 19.5 Mbps
+ {52, 34, 0}, // RATEID_VHT_MCS3_1SS_BW20 26 Mbps
+ {78, 35, 0}, // RATEID_VHT_MCS4_1SS_BW20 39 Mbps
+ {104, 36, 0}, // RATEID_VHT_MCS5_1SS_BW20 52 Mbps
+ {117, 37, 0}, // RATEID_VHT_MCS6_1SS_BW20 58.5 Mbps
+ {130, 38, 0}, // RATEID_VHT_MCS7_1SS_BW20 65 Mbps
+ {156, 39, 0}, // RATEID_VHT_MCS8_1SS_BW20 78 Mbps
+ {0, 40, 0}, // RATEID_VHT_MCS9_1SS_BW20 86.7 Mbps(INVALID)
+
+ /* VHT bw40<--> Mrvl rate idx */
+ {27, 41, 0}, // RATEID_VHT_MCS0_1SS_BW40 13.5 Mbps
+ {54, 42, 0}, // RATEID_VHT_MCS1_1SS_BW40 27 Mbps
+ {81, 43, 0}, // RATEID_VHT_MCS2_1SS_BW40 40.5 Mbps
+ {108, 44, 0}, // RATEID_VHT_MCS3_1SS_BW40 54 Mbps
+ {162, 45, 0}, // RATEID_VHT_MCS4_1SS_BW40 81 Mbps
+ {216, 46, 0}, // RATEID_VHT_MCS5_1SS_BW40 108 Mbps
+ {243, 47, 0}, // RATEID_VHT_MCS6_1SS_BW40 121.5 Mbps
+ {270, 48, 0}, // RATEID_VHT_MCS7_1SS_BW40 135 Mbps
+ {324, 49, 0}, // RATEID_VHT_MCS8_1SS_BW40 162 Mbps
+ {360, 50, 0}, // RATEID_VHT_MCS9_1SS_BW40 180 Mbps
+
+ /* VHT bw80<--> Mrvl rate idx */
+ {58, 51, 0}, // RATEID_VHT_MCS0_1SS_BW80 29.3 Mbps, 29.3x2 could
+ // correspond to 58
+ {59, 51, 0}, // RATEID_VHT_MCS0_1SS_BW80 29.3 Mbps, 29.3x2 could
+ // correspond to 59 too
+ {117, 52, 0}, // RATEID_VHT_MCS1_1SS_BW80 58.5 Mbps
+ {175, 53, 0}, // RATEID_VHT_MCS2_1SS_BW80 87.8 Mbps, 87.8x2 could
+ // correspond to 175
+ {176, 53, 0}, // RATEID_VHT_MCS2_1SS_BW80 87.8 Mbps, 87.8x2 could
+ // correspond to 176 too
+ {234, 54, 0}, // RATEID_VHT_MCS3_1SS_BW80 117 Mbps
+ {351, 55, 0}, // RATEID_VHT_MCS4_1SS_BW80 175.5 Mbps
+ {468, 56, 0}, // RATEID_VHT_MCS5_1SS_BW80 234 Mbps
+ {526, 57, 0}, // RATEID_VHT_MCS6_1SS_BW80 263.3 Mbps, 263.3x2 could
+ // correspond to 526
+ {527, 57, 0}, // RATEID_VHT_MCS6_1SS_BW80 263.3 Mbps, 263.3x2 could
+ // correspond to 527 too
+ {585, 58, 0}, // RATEID_VHT_MCS7_1SS_BW80 292.5 Mbps
+ {702, 59, 0}, // RATEID_VHT_MCS8_1SS_BW80 351 Mbps
+ {780, 60, 0}, // RATEID_VHT_MCS9_1SS_BW80 390 Mbps
+};
+
+/********************************************************
+ * Global Variables
+ ********************************************************/
+/**
+ * The table to keep region code
+ */
+
+t_u16 region_code_index[MRVDRV_MAX_REGION_CODE] = {0x00, 0x10, 0x20, 0x30, 0x40,
+ 0x41, 0x50, 0xfe, 0xff};
+
+/** The table to keep CFP code for BG */
+t_u16 cfp_code_index_bg[MRVDRV_MAX_CFP_CODE_BG] = {};
+/** The table to keep CFP code for A */
+t_u16 cfp_code_index_a[MRVDRV_MAX_CFP_CODE_A] = {0x1, 0x2, 0x3, 0x4, 0x5};
+
+/**
+ * The rates supported for ad-hoc B mode
+ */
+t_u8 AdhocRates_B[B_SUPPORTED_RATES] = {0x82, 0x84, 0x8b, 0x96, 0};
+
+/**
+ * The rates supported for ad-hoc G mode
+ */
+t_u8 AdhocRates_G[G_SUPPORTED_RATES] = {0x8c, 0x12, 0x98, 0x24, 0xb0,
+ 0x48, 0x60, 0x6c, 0x00};
+
+/**
+ * The rates supported for ad-hoc BG mode
+ */
+t_u8 AdhocRates_BG[BG_SUPPORTED_RATES] = {0x82, 0x84, 0x8b, 0x96, 0x0c,
+ 0x12, 0x18, 0x24, 0x30, 0x48,
+ 0x60, 0x6c, 0x00};
+
+/**
+ * The rates supported in A mode for ad-hoc
+ */
+t_u8 AdhocRates_A[A_SUPPORTED_RATES] = {0x8c, 0x12, 0x98, 0x24, 0xb0,
+ 0x48, 0x60, 0x6c, 0x00};
+
+/**
+ * The rates supported in A mode (used for BAND_A)
+ */
+t_u8 SupportedRates_A[A_SUPPORTED_RATES] = {0x0c, 0x12, 0x18, 0x24, 0xb0,
+ 0x48, 0x60, 0x6c, 0x00};
+
+/**
+ * The rates supported by the card
+ */
+t_u16 WlanDataRates[WLAN_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};
+
+/**
+ * The rates supported in B mode
+ */
+t_u8 SupportedRates_B[B_SUPPORTED_RATES] = {0x02, 0x04, 0x0b, 0x16, 0x00};
+
+/**
+ * The rates supported in G mode (BAND_G, BAND_G|BAND_GN)
+ */
+t_u8 SupportedRates_G[G_SUPPORTED_RATES] = {0x0c, 0x12, 0x18, 0x24, 0x30,
+ 0x48, 0x60, 0x6c, 0x00};
+
+/**
+ * The rates supported in BG mode (BAND_B|BAND_G, BAND_B|BAND_G|BAND_GN)
+ */
+t_u8 SupportedRates_BG[BG_SUPPORTED_RATES] = {0x02, 0x04, 0x0b, 0x0c, 0x12,
+ 0x16, 0x18, 0x24, 0x30, 0x48,
+ 0x60, 0x6c, 0x00};
+
+/**
+ * The rates supported in N mode
+ */
+t_u8 SupportedRates_N[N_SUPPORTED_RATES] = {0x02, 0x04, 0};
+
+#define MCS_NUM_AX 12
+// for MCS0/MCS1/MCS3/MCS4 have 4 additional DCM=1 value
+// note: the value in the table is 2 multiplier of the actual rate
+t_u16 ax_mcs_rate_nss1[12][MCS_NUM_AX + 4] = {
+ {0x90, 0x48, 0x120, 0x90, 0x1B0, 0x240, 0x120, 0x360, 0x1B0, 0x481,
+ 0x511, 0x5A1, 0x6C1, 0x781, 0x871, 0x962}, /*SG 160M*/
+ {0x88, 0x44, 0x110, 0x88, 0x198, 0x220, 0x110, 0x330, 0x198, 0x440,
+ 0x4C9, 0x551, 0x661, 0x716, 0x7F9, 0x8DC}, /*MG 160M*/
+ {0x7A, 0x3D, 0xF5, 0x7A, 0x16F, 0x1EA, 0xF5, 0x2DF, 0x16F, 0x3D4, 0x44E,
+ 0x4C9, 0x5BE, 0x661, 0x72D, 0x7F9}, /*LG 160M*/
+ {0x48, 0x24, 0x90, 0x48, 0xD8, 0x120, 0x90, 0x1B0, 0xD8, 0x240, 0x288,
+ 0x2D0, 0x360, 0x3C0, 0x438, 0x4B0}, /*SG 80M*/
+ {0x44, 0x22, 0x88, 0x44, 0xCC, 0x110, 0x88, 0x198, 0xCC, 0x220, 0x264,
+ 0x2A8, 0x330, 0x38B, 0x3FC, 0x46E}, /*MG 80M*/
+ {0x3D, 0x1E, 0x7A, 0x3D, 0xB7, 0xF5, 0x7A, 0x16F, 0xB7, 0x1EA, 0x227,
+ 0x264, 0x2DF, 0x330, 0x396, 0x3FC}, /*LG 80M*/
+ {0x22, 0x11, 0x44, 0x22, 0x67, 0x89, 0x44, 0xCE, 0x67, 0x113, 0x135,
+ 0x158, 0x19D, 0x1CA, 0x204, 0x23D}, /*SG 40M*/
+ {0x20, 0x10, 0x41, 0x20, 0x61, 0x82, 0x41, 0xC3, 0x61, 0x104, 0x124,
+ 0x145, 0x186, 0x1B1, 0x1E7, 0x21D}, /*MG 40M*/
+ {0x1D, 0xE, 0x3A, 0x1D, 0x57, 0x75, 0x3A, 0xAF, 0x57, 0xEA, 0x107,
+ 0x124, 0x15F, 0x186, 0x1B6, 0x1E7}, /*LG 40M*/
+ {0x11, 0x8, 0x22, 0x11, 0x33, 0x44, 0x22, 0x67, 0x33, 0x89, 0x9A, 0xAC,
+ 0xCE, 0xE5, 0x102, 0x11E}, /*SG 20M*/
+ {0x10, 0x8, 0x20, 0x10, 0x30, 0x41, 0x20, 0x61, 0x30, 0x82, 0x92, 0xA2,
+ 0xC3, 0xD8, 0xF3, 0x10E}, /*MG 20M*/
+ {0xE, 0x7, 0x1D, 0xE, 0x2B, 0x3A, 0x1D, 0x57, 0x2B, 0x75, 0x83, 0x92,
+ 0xAF, 0xC3, 0xDB, 0xF3} /*LG 20M*/
+};
+
+// note: the value in the table is 2 multiplier of the actual rate
+t_u16 ax_tone_ru_rate_nss1[9][MCS_NUM_AX + 4] = {
+ {0x8, 0x4, 0xF, 0x8, 0x17, 0x1E, 0xF, 0x2D, 0x17, 0x3C, 0x44, 0x4B,
+ 0x5A, 0x64, 0x71, 0x7D}, /*SG 106-tone*/
+ {0x7, 0x4, 0xF, 0x7, 0x16, 0x1D, 0xF, 0x2B, 0x16, 0x39, 0x40, 0x47,
+ 0x55, 0x5F, 0x6B, 0x76}, /*MG 106-tone*/
+ {0x7, 0x3, 0xD, 0x6, 0x14, 0x1A, 0xD, 0x27, 0x14, 0x33, 0x3A, 0x40,
+ 0x4D, 0x55, 0x60, 0x6B}, /*LG 106-tone*/
+ {0x4, 0x2, 0x7, 0x4, 0xB, 0xF, 0x7, 0x16, 0xB, 0x1D, 0x20, 0x22, 0x2B,
+ 0x2F, 0x35, 0x3B}, /*SG 52-tone*/
+ {0x4, 0x2, 0x7, 0x4, 0xA, 0xE, 0x7, 0x14, 0xA, 0x1B, 0x1E, 0x22, 0x28,
+ 0x2D, 0x32, 0x38}, /*MG 52-tone*/
+ {0x3, 0x2, 0x6, 0x3, 0x9, 0xC, 0x6, 0x12, 0x9, 0x18, 0x1B, 0x1E, 0x24,
+ 0x28, 0x2D, 0x32}, /*LG 52-tone*/
+ {0x2, 0x1, 0x4, 0x2, 0x6, 0x7, 0x4, 0xB, 0x5, 0xE, 0x10, 0x12, 0x15,
+ 0x18, 0x1A, 0x1D}, /*SG 26-tone*/
+ {0x2, 0x1, 0x4, 0x2, 0x5, 0x6, 0x4, 0xA, 0x5, 0xD, 0xF, 0x11, 0x14,
+ 0x16, 0x19, 0x1C}, /*MG 26-tone*/
+ {0x2, 0x1, 0x3, 0x2, 0x5, 0x6, 0x3, 0x9, 0x4, 0xC, 0xE, 0xF, 0x12, 0x14,
+ 0x17, 0x19} /*LG 26-tone*/
+};
+
+// note: the value in the table is 2 multiplier of the actual rate
+t_u16 ax_mcs_rate_nss2[12][MCS_NUM_AX + 4] = {
+ {0x120, 0x90, 0x240, 0x120, 0x360, 0x481, 0x240, 0x61C, 0x360, 0x901,
+ 0xA22, 0xB42, 0xD82, 0xF03, 0x10E3, 0x12C3}, /*SG 160M*/
+ {0x110, 0x88, 0x220, 0x110, 0x330, 0x440, 0x220, 0x661, 0x330, 0x881,
+ 0x992, 0xAA2, 0xCAC, 0xE2D, 0xFF3, 0x11B9}, /*MG 160M*/
+ {0xF5, 0x7A, 0x1EA, 0xF5, 0x2DF, 0x3D4, 0x1EA, 0x5BE, 0x2DF, 0x7A8,
+ 0x1134, 0x992, 0xB7C, 0xCC2, 0xE5B, 0xFF3}, /*LG 160M*/
+ {0x90, 0x48, 0x120, 0x90, 0x1B0, 0x240, 0x120, 0x360, 0x1B0, 0x481,
+ 0x511, 0x5A1, 0x6C1, 0x781, 0x871, 0x962}, /*SG 80M*/
+ {0x88, 0x44, 0x110, 0x88, 0x198, 0x220, 0x110, 0x330, 0x198, 0x440,
+ 0x4C9, 0x551, 0x661, 0x716, 0x7F9, 0x8DC}, /*MG 80M*/
+ {0x7A, 0x3D, 0xF5, 0x7A, 0x16F, 0x1EA, 0xF5, 0x2DF, 0x16F, 0x3D4, 0x44E,
+ 0x4C9, 0x5BE, 0x661, 0x72D, 0x7F9}, /*LG 80M*/
+ {0x44, 0x22, 0x89, 0x44, 0xCE, 0x113, 0x89, 0x19D, 0xCE, 0x226, 0x26B,
+ 0x2B0, 0x339, 0x395, 0x408, 0x47B}, /*SG 40M*/
+ {0x41, 0x20, 0x82, 0x41, 0xC3, 0x104, 0x82, 0x186, 0xC3, 0x208, 0x249,
+ 0x28A, 0x30C, 0x362, 0x3CE, 0x43B}, /*MG 40M*/
+ {0x3A, 0x1D, 0x75, 0x3A, 0xAF, 0xEA, 0x75, 0x15F, 0xAF, 0x1D4, 0x20E,
+ 0x249, 0x2BE, 0x30C, 0x36D, 0x3CF}, /*LG 40M*/
+ {0x22, 0x11, 0x44, 0x22, 0x67, 0x89, 0x44, 0xCE, 0x67, 0x113, 0x135,
+ 0x158, 0x19D, 0x1CA, 0x204, 0x23D}, /*SG 20M*/
+ {0x20, 0x10, 0x41, 0x20, 0x61, 0x82, 0x41, 0xC3, 0x61, 0x104, 0x124,
+ 0x145, 0x186, 0x1B1, 0x1E7, 0x21D}, /*MG 20M*/
+ {0x1D, 0xE, 0x3A, 0x1D, 0x57, 0x75, 0x3A, 0xAF, 0x57, 0xEA, 0x107,
+ 0x124, 0x15F, 0x186, 0x1B6, 0x1E7} /*LG 20M*/
+};
+
+// note: the value in the table is 2 multiplier of the actual rate
+t_u16 ax_tone_ru_rate_nss2[9][MCS_NUM_AX + 4] = {
+ {0xF, 0x8, 0x1E, 0xF, 0x2D, 0x3C, 0x1E, 0x5A, 0x2D, 0x78, 0x87, 0x96,
+ 0xB4, 0xC8, 0xE1, 0xFA}, /*SG 106-tone*/
+ {0xE, 0x7, 0x1D, 0xE, 0x2B, 0x39, 0x1D, 0x55, 0x2B, 0x72, 0x80, 0x8E,
+ 0xAA, 0xBD, 0xD5, 0xED}, /*MG 106-tone*/
+ {0xD, 0x7, 0x1A, 0xD, 0x27, 0x33, 0x1A, 0x4D, 0x27, 0x66, 0x73, 0x80,
+ 0x99, 0xAA, 0xC0, 0xD5}, /*LG 106-tone*/
+ {0x7, 0x4, 0xF, 0x7, 0x16, 0x1D, 0xF, 0x2A, 0x16, 0x39, 0x40, 0x47,
+ 0x55, 0x5F, 0x6A, 0x76}, /*SG 52-tone*/
+ {0x7, 0x4, 0xE, 0x7, 0x14, 0x1B, 0xE, 0x28, 0x14, 0x36, 0x3C, 0x43,
+ 0x50, 0x59, 0x64, 0x70}, /*MG 52-tone*/
+ {0x6, 0x3, 0xC, 0x6, 0x12, 0x18, 0xC, 0x24, 0x12, 0x30, 0x36, 0x3C,
+ 0x48, 0x50, 0x5A, 0x64}, /*LG 52-tone*/
+ {0x4, 0x2, 0x7, 0x4, 0xB, 0xF, 0x7, 0x16, 0xB, 0x1D, 0x20, 0x22, 0x2B,
+ 0x2F, 0x35, 0x3B}, /*SG 26-tone*/
+ {0x4, 0x2, 0x7, 0x4, 0xA, 0xE, 0x7, 0x14, 0xA, 0x1B, 0x1E, 0x22, 0x28,
+ 0x2D, 0x32, 0x38}, /*MG 26-tone*/
+ {0x3, 0x2, 0x6, 0x3, 0x9, 0xC, 0x6, 0x12, 0x9, 0x18, 0x1B, 0x1E, 0x24,
+ 0x28, 0x2D, 0x32} /*LG 26-tone*/
+};
+
+/********************************************************
+ * Local Functions
+ ********************************************************/
+/**
+ * @brief Find a character in a string.
+ *
+ * @param pmadapter A pointer to mlan_adapter structure
+ * @param s A pointer to string
+ * @param c Character to be located
+ * @param n The length of string
+ *
+ * @return A pointer to the first occurrence of c in string, or MNULL if
+ * c is not found.
+ */
+static void *wlan_memchr(pmlan_adapter pmadapter, void *s, int c, int n)
+{
+ const t_u8 *p = (t_u8 *)s;
+
+ ENTER();
+
+ while (n--) {
+ if ((t_u8)c == *p++) {
+ LEAVE();
+ return (void *)(p - 1);
+ }
+ }
+
+ LEAVE();
+ return MNULL;
+}
+
+/**
+ * @brief This function finds the CFP in
+ * cfp_table_BG/A based on region/code and band parameter.
+ *
+ * @param pmadapter A pointer to mlan_adapter structure
+ * @param region The region code
+ * @param band The band
+ * @param cfp_no A pointer to CFP number
+ *
+ * @return A pointer to CFP
+ */
+static chan_freq_power_t *wlan_get_region_cfp_table(pmlan_adapter pmadapter,
+ t_u8 region, t_u8 band,
+ int *cfp_no)
+{
+ t_u32 i;
+ t_u8 cfp_bg, cfp_a;
+
+ ENTER();
+
+ cfp_bg = cfp_a = region;
+ if (!region) {
+ /* Invalid region code, use CFP code */
+ cfp_bg = pmadapter->cfp_code_bg;
+ cfp_a = pmadapter->cfp_code_a;
+ }
+
+ if (band & (BAND_B | BAND_G | BAND_GN | BAND_GAC)) {
+ /* Return the FW cfp table for requested region code, if
+ * available. If region is not forced and the requested region
+ * code is different, simply return the corresponding
+ * pre-defined table.
+ */
+ if (pmadapter->otp_region && pmadapter->cfp_otp_bg) {
+ if (pmadapter->otp_region->force_reg ||
+ (cfp_bg ==
+ (t_u8)pmadapter->otp_region->region_code)) {
+ *cfp_no = pmadapter->tx_power_table_bg_rows;
+ LEAVE();
+ return pmadapter->cfp_otp_bg;
+ }
+ }
+ for (i = 0; i < MLAN_CFP_TABLE_SIZE_BG; i++) {
+ PRINTM(MINFO, "cfp_table_BG[%d].code=%d\n", i,
+ cfp_table_BG[i].code);
+ /* Check if region/code matches for BG bands */
+ if (cfp_table_BG[i].code == cfp_bg) {
+ /* Select by band */
+ *cfp_no = cfp_table_BG[i].cfp_no;
+ LEAVE();
+ return cfp_table_BG[i].cfp;
+ }
+ }
+ }
+ if (band & (BAND_A | BAND_AN | BAND_AAC)) {
+ /* Return the FW cfp table for requested region code */
+ if (pmadapter->otp_region && pmadapter->cfp_otp_a) {
+ if (pmadapter->otp_region->force_reg ||
+ (cfp_a ==
+ (t_u8)pmadapter->otp_region->region_code)) {
+ *cfp_no = pmadapter->tx_power_table_a_rows;
+ LEAVE();
+ return pmadapter->cfp_otp_a;
+ }
+ }
+ for (i = 0; i < MLAN_CFP_TABLE_SIZE_A; i++) {
+ PRINTM(MINFO, "cfp_table_A[%d].code=%d\n", i,
+ cfp_table_A[i].code);
+ /* Check if region/code matches for A bands */
+ if (cfp_table_A[i].code == cfp_a) {
+ /* Select by band */
+ *cfp_no = cfp_table_A[i].cfp_no;
+ LEAVE();
+ return cfp_table_A[i].cfp;
+ }
+ }
+ }
+
+ if (!region)
+ PRINTM(MERROR, "Error Band[0x%x] or code[BG:%#x, A:%#x]\n",
+ band, cfp_bg, cfp_a);
+ else
+ PRINTM(MERROR, "Error Band[0x%x] or region[%#x]\n", band,
+ region);
+
+ LEAVE();
+ return MNULL;
+}
+
+/**
+ * @brief This function copies dynamic CFP elements from one table to another.
+ * Only copy elements where channel numbers match.
+ *
+ * @param pmadapter A pointer to mlan_adapter structure
+ * @param cfp Destination table
+ * @param num_cfp Number of elements in dest table
+ * @param cfp_src Source table
+ * @param num_cfp_src Number of elements in source table
+ */
+static t_void wlan_cfp_copy_dynamic(pmlan_adapter pmadapter,
+ chan_freq_power_t *cfp, t_u8 num_cfp,
+ chan_freq_power_t *cfp_src,
+ t_u8 num_cfp_src)
+{
+ int i, j;
+
+ ENTER();
+
+ if (cfp == cfp_src) {
+ LEAVE();
+ return;
+ }
+
+ /* first clear dest dynamic blacklisted entries */
+ for (i = 0; i < num_cfp; i++) {
+ cfp[i].dynamic.blacklist = MFALSE;
+ cfp[i].dynamic.flags = 0;
+ }
+
+ /* copy dynamic blacklisted entries from source where channels match */
+ if (cfp_src) {
+ for (i = 0; i < num_cfp; i++)
+ for (j = 0; j < num_cfp_src; j++)
+ if (cfp[i].channel == cfp_src[j].channel) {
+ cfp[i].dynamic.blacklist =
+ cfp_src[j].dynamic.blacklist;
+ cfp[i].dynamic.flags =
+ cfp_src[j].dynamic.flags;
+ break;
+ }
+ }
+
+ LEAVE();
+}
+
+/********************************************************
+ * Global Functions
+ ********************************************************/
+/**
+ * @brief This function converts region string to integer code
+ *
+ * @param pmadapter A pointer to mlan_adapter structure
+ * @param country_code Country string
+ * @param cfp_bg Pointer to buffer
+ * @param cfp_a Pointer to buffer
+ *
+ * @return MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ */
+mlan_status wlan_misc_country_2_cfp_table_code(pmlan_adapter pmadapter,
+ t_u8 *country_code, t_u8 *cfp_bg,
+ t_u8 *cfp_a)
+{
+ t_u8 i;
+
+ ENTER();
+
+ /* Look for code in mapping table */
+ for (i = 0; i < NELEMENTS(country_code_mapping); i++) {
+ if (!memcmp(pmadapter, country_code_mapping[i].country_code,
+ country_code, COUNTRY_CODE_LEN - 1)) {
+ *cfp_bg = country_code_mapping[i].cfp_code_bg;
+ *cfp_a = country_code_mapping[i].cfp_code_a;
+ LEAVE();
+ return MLAN_STATUS_SUCCESS;
+ }
+ }
+
+ /* If still not found, look for code in EU country code table */
+ for (i = 0; i < NELEMENTS(eu_country_code_table); i++) {
+ if (!memcmp(pmadapter, eu_country_code_table[i], country_code,
+ COUNTRY_CODE_LEN - 1)) {
+ *cfp_bg = EU_CFP_CODE_BG;
+ *cfp_a = EU_CFP_CODE_A;
+ LEAVE();
+ return MLAN_STATUS_SUCCESS;
+ }
+ }
+
+ LEAVE();
+ return MLAN_STATUS_FAILURE;
+}
+
+/**
+ * @brief This function finds if given country code is in EU table
+ *
+ * @param pmadapter A pointer to mlan_adapter structure
+ * @param country_code Country string
+ *
+ * @return MTRUE or MFALSE
+ */
+t_bool wlan_is_etsi_country(pmlan_adapter pmadapter, t_u8 *country_code)
+{
+ t_u8 i;
+
+ ENTER();
+
+ /* Look for code in EU country code table */
+ for (i = 0; i < NELEMENTS(eu_country_code_table); i++) {
+ if (!memcmp(pmadapter, eu_country_code_table[i], country_code,
+ COUNTRY_CODE_LEN - 1)) {
+ LEAVE();
+ return MTRUE;
+ }
+ }
+
+ LEAVE();
+ return MFALSE;
+}
+
+#define BAND_MASK_5G 0x03
+#define ANTENNA_OFFSET 2
+/**
+ * @brief This function adjust the antenna index
+ *
+ * V16_FW_API: Bit0: ant A, Bit 1:ant B, Bit0 & Bit 1: A+B
+ * 8887: case1: 0 - 2.4G ant A, 1- 2.4G antB, 2-- 5G ant C
+ * case2: 0 - 2.4G ant A, 1- 2.4G antB, 0x80- 5G antA, 0x81-5G ant B
+ * @param priv A pointer to mlan_private structure
+ * @param prx_pd A pointer to the RxPD structure
+ *
+ * @return MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ */
+t_u8 wlan_adjust_antenna(pmlan_private priv, RxPD *prx_pd)
+{
+ t_u8 antenna = prx_pd->antenna;
+#if defined(SD8887) || defined(SD8987)
+ t_u32 rx_channel = (prx_pd->rx_info & RXPD_CHAN_MASK) >> 5;
+#endif
+ if (prx_pd->antenna == 0xff)
+ return 0;
+ if (priv->adapter->pcard_info->v16_fw_api) {
+ if ((antenna & MBIT(0)) && (antenna & MBIT(1)))
+ antenna = 2;
+ else if (antenna & MBIT(1))
+ antenna = 1;
+ else if (antenna & MBIT(0))
+ antenna = 0;
+ }
+
+#if defined(SD8887) || defined(SD8987)
+ if (MFALSE
+#ifdef SD8887
+ || IS_SD8887(priv->adapter->card_type)
+#endif
+#ifdef SD8987
+ || IS_SD8987(priv->adapter->card_type)
+#endif
+ ) {
+ if ((priv->adapter->antinfo & ANT_DIVERSITY_2G) &&
+ (priv->adapter->antinfo & ANT_DIVERSITY_5G)) {
+#define MAX_2G_CHAN 14
+ if (rx_channel > MAX_2G_CHAN)
+ antenna += ANTENNA_OFFSET;
+ }
+ }
+#endif
+
+ return antenna;
+}
+
+/**
+ * @brief This function adjust the rate index
+ *
+ * @param priv A pointer to mlan_private structure
+ * @param rx_rate rx rate
+ * @param rate_info rate info
+ * @return rate index
+ */
+t_u16 wlan_adjust_data_rate(mlan_private *priv, t_u8 rx_rate, t_u8 rate_info)
+{
+ t_u16 rate_index = 0;
+ t_u8 bw = 0;
+ t_u8 nss = 0;
+ t_bool sgi_enable = 0;
+ t_u8 gi = 0;
+#define MAX_MCS_NUM_AX 12
+
+#define MAX_MCS_NUM_SUPP 16
+#define MAX_MCS_NUM_AC 10
+#define RATE_INDEX_MCS0 12
+ bw = (rate_info & 0xC) >> 2;
+ sgi_enable = (rate_info & 0x10) >> 4;
+ if ((rate_info & 0x3) == 0) {
+ rate_index = (rx_rate > MLAN_RATE_INDEX_OFDM0) ? rx_rate - 1 :
+ rx_rate;
+ } else if ((rate_info & 0x03) == 1) {
+ rate_index = RATE_INDEX_MCS0 +
+ MAX_MCS_NUM_SUPP * 2 * sgi_enable +
+ MAX_MCS_NUM_SUPP * bw + rx_rate;
+ } else if ((rate_info & 0x3) == 2) {
+ if (IS_STREAM_2X2(priv->adapter->feature_control))
+ nss = rx_rate >> 4; // 0:NSS1, 1:NSS2
+ rate_index = RATE_INDEX_MCS0 + MAX_MCS_NUM_SUPP * 4 +
+ MAX_MCS_NUM_AC * 6 * sgi_enable +
+ MAX_MCS_NUM_AC * 2 * bw + MAX_MCS_NUM_AC * nss +
+ (rx_rate & 0x0f);
+ } else if ((rate_info & 0x3) == 3) {
+ gi = (rate_info & 0x10) >> 4 | (rate_info & 0x80) >> 6;
+ if (IS_STREAM_2X2(priv->adapter->feature_control))
+ nss = rx_rate >> 4; // 0:NSS1, 1:NSS2
+ rate_index = RATE_INDEX_MCS0 + MAX_MCS_NUM_SUPP * 4 +
+ MAX_MCS_NUM_AC * 12 + MAX_MCS_NUM_AX * 6 * gi +
+ MAX_MCS_NUM_AX * 2 * bw + MAX_MCS_NUM_AX * nss +
+ (rx_rate & 0x0f);
+ }
+ return rate_index;
+}
+
+#ifdef STA_SUPPORT
+#endif /* STA_SUPPORT */
+
+/**
+ * @brief Use index to get the data rate
+ *
+ * @param pmadapter A pointer to mlan_adapter structure
+ * @param index The index of data rate
+ * @param tx_rate_info Tx rate info
+ * @param ext_rate_info Extend tx rate info
+ *
+ * @return Data rate or 0
+ */
+t_u32 wlan_index_to_data_rate(pmlan_adapter pmadapter, t_u8 index,
+ t_u8 tx_rate_info, t_u8 ext_rate_info)
+{
+#define MCS_NUM_SUPP 16
+ t_u16 mcs_rate[4][MCS_NUM_SUPP] = {
+ {0x1b, 0x36, 0x51, 0x6c, 0xa2, 0xd8, 0xf3, 0x10e, 0x36, 0x6c,
+ 0xa2, 0xd8, 0x144, 0x1b0, 0x1e6, 0x21c}, /*LG 40M*/
+ {0x1e, 0x3c, 0x5a, 0x78, 0xb4, 0xf0, 0x10e, 0x12c, 0x3c, 0x78,
+ 0xb4, 0xf0, 0x168, 0x1e0, 0x21c, 0x258}, /*SG 40M */
+ {0x0d, 0x1a, 0x27, 0x34, 0x4e, 0x68, 0x75, 0x82, 0x1a, 0x34,
+ 0x4e, 0x68, 0x9c, 0xd0, 0xea, 0x104}, /*LG 20M */
+ {0x0e, 0x1c, 0x2b, 0x39, 0x56, 0x73, 0x82, 0x90, 0x1c, 0x39,
+ 0x56, 0x73, 0xad, 0xe7, 0x104, 0x120}}; /*SG 20M */
+
+#define MCS_NUM_AC 10
+ /* NSS 1. note: the value in the table is 2 multiplier of the actual
+ * rate in other words, it is in the unit of 500 Kbs
+ */
+ t_u16 ac_mcs_rate_nss1[8][MCS_NUM_AC] = {
+ {0x75, 0xEA, 0x15F, 0x1D4, 0x2BE, 0x3A8, 0x41D, 0x492, 0x57C,
+ 0x618}, /* LG 160M*/
+ {0x82, 0x104, 0x186, 0x208, 0x30C, 0x410, 0x492, 0x514, 0x618,
+ 0x6C6}, /* SG 160M*/
+ {0x3B, 0x75, 0xB0, 0xEA, 0x15F, 0x1D4, 0x20F, 0x249, 0x2BE,
+ 0x30C}, /* LG 80M */
+ {0x41, 0x82, 0xC3, 0x104, 0x186, 0x208, 0x249, 0x28A, 0x30C,
+ 0x363}, /* SG 80M */
+ {0x1B, 0x36, 0x51, 0x6C, 0xA2, 0xD8, 0xF3, 0x10E, 0x144,
+ 0x168}, /* LG 40M */
+ {0x1E, 0x3C, 0x5A, 0x78, 0xB4, 0xF0, 0x10E, 0x12C, 0x168,
+ 0x190}, /* SG 40M */
+ {0xD, 0x1A, 0x27, 0x34, 0x4E, 0x68, 0x75, 0x82, 0x9C,
+ 0x00}, /* LG 20M */
+ {0xF, 0x1D, 0x2C, 0x3A, 0x57, 0x74, 0x82, 0x91, 0xAE,
+ 0x00}, /* SG 20M */
+ };
+ /* NSS 2. note: the value in the table is 2 multiplier of the actual
+ * rate
+ */
+ t_u16 ac_mcs_rate_nss2[8][MCS_NUM_AC] = {
+ {0xEA, 0x1D4, 0x2BE, 0x3A8, 0x57C, 0x750, 0x83A, 0x924, 0xAF8,
+ 0xC30}, /*LG 160M*/
+ {0x104, 0x208, 0x30C, 0x410, 0x618, 0x820, 0x924, 0xA28, 0xC30,
+ 0xD8B}, /*SG 160M*/
+
+ {0x75, 0xEA, 0x15F, 0x1D4, 0x2BE, 0x3A8, 0x41D, 0x492, 0x57C,
+ 0x618}, /*LG 80M*/
+ {0x82, 0x104, 0x186, 0x208, 0x30C, 0x410, 0x492, 0x514, 0x618,
+ 0x6C6}, /*SG 80M*/
+ {0x36, 0x6C, 0xA2, 0xD8, 0x144, 0x1B0, 0x1E6, 0x21C, 0x288,
+ 0x2D0}, /*LG 40M*/
+ {0x3C, 0x78, 0xB4, 0xF0, 0x168, 0x1E0, 0x21C, 0x258, 0x2D0,
+ 0x320}, /*SG 40M*/
+ {0x1A, 0x34, 0x4A, 0x68, 0x9C, 0xD0, 0xEA, 0x104, 0x138,
+ 0x00}, /*LG 20M*/
+ {0x1D, 0x3A, 0x57, 0x74, 0xAE, 0xE6, 0x104, 0x121, 0x15B,
+ 0x00}, /*SG 20M*/
+ };
+
+ t_u32 rate = 0;
+ t_u8 mcs_index = 0;
+ t_u8 he_dcm = 0;
+ t_u8 he_tone = 0;
+ t_u8 stbc = 0;
+
+ t_u8 bw = 0;
+ t_u8 gi = 0;
+
+ ENTER();
+
+ PRINTM(MINFO, "%s:index=%d, tx_rate_info=%d, ext_rate_info=%d\n",
+ __func__, index, tx_rate_info, ext_rate_info);
+
+ if ((tx_rate_info & 0x3) == MLAN_RATE_FORMAT_VHT) {
+ /* VHT rate */
+ mcs_index = index & 0xF;
+
+ if (mcs_index > 9)
+ mcs_index = 9;
+
+ /* 20M: bw=0, 40M: bw=1, 80M: bw=2, 160M: bw=3 */
+ bw = (tx_rate_info & 0xC) >> 2;
+ /* LGI: gi =0, SGI: gi = 1 */
+ gi = (tx_rate_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 ((tx_rate_info & 0x3) == MLAN_RATE_FORMAT_HE) {
+ /* VHT rate */
+ mcs_index = index & 0xF;
+ he_dcm = ext_rate_info & MBIT(0);
+
+ if (mcs_index > MCS_NUM_AX - 1)
+ mcs_index = MCS_NUM_AX - 1;
+
+ /* 20M: bw=0, 40M: bw=1, 80M: bw=2, 160M: bw=3 */
+ bw = (tx_rate_info & (MBIT(3) | MBIT(2))) >> 2;
+ /* BIT7:BIT4 0:0= 0.8us,0:1= 0.8us, 1:0=1.6us, 1:1=3.2us or
+ * 0.8us
+ */
+ gi = (tx_rate_info & MBIT(4)) >> 4 |
+ (tx_rate_info & MBIT(7)) >> 6;
+ /* STBC: BIT5 in tx rate info */
+ stbc = (tx_rate_info & MBIT(5)) >> 5;
+
+ if (gi > 3) {
+ PRINTM(MERROR, "Invalid gi value");
+ return 0;
+ }
+
+ if ((gi == 3) && stbc && he_dcm) {
+ gi = 0;
+ stbc = 0;
+ he_dcm = 0;
+ }
+ /* map to gi 0:0.8us,1:1.6us 2:3.2us*/
+ if (gi > 0)
+ gi = gi - 1;
+
+ // TODO: hardcode he_tone here, wait for FW value ready.
+ he_tone = 4;
+
+ // he_tone = (ext_rate_info & 0xE) >> 1;
+
+ if ((index >> 4) == 1) {
+ switch (mcs_index) {
+ case 0:
+ case 1:
+ // #if 0
+ // if (he_tone < 3) {
+ // rate =
+ //ax_tone_ru_rate_nss2[3*(2-he_tone)+gi][mcs_index*2
+ //+ he_dcm];
+ // } else {
+ // #endif
+ rate = ax_mcs_rate_nss2[3 * (3 - bw) + gi]
+ [mcs_index * 2 + he_dcm];
+ break;
+ case 2:
+ // #if 0
+ // if (he_tone < 3) {
+ // rate =
+ //ax_tone_ru_rate_nss2[3*(2-he_tone)+gi][mcs_index*2];
+ // } else {
+ // #endif
+ rate = ax_mcs_rate_nss2[3 * (3 - bw) + gi]
+ [mcs_index * 2];
+ break;
+ case 3:
+ case 4:
+ // #if 0
+ // if (he_tone < 3) {
+ // rate =
+ //ax_tone_ru_rate_nss2[3*(2-he_tone)+gi][mcs_index*2
+ //- 1 + he_dcm];
+ // } else {
+ // #endif
+ rate = ax_mcs_rate_nss2[3 * (3 - bw) + gi]
+ [mcs_index * 2 - 1 +
+ he_dcm];
+ break;
+
+ default:
+ // #if 0
+ // if (he_tone < 3) {
+ // rate =
+ //ax_tone_ru_rate_nss2[3*(2-he_tone)+gi][mcs_index
+ //+ 4];
+ // } else {
+ // #endif
+ rate = ax_mcs_rate_nss2[3 * (3 - bw) + gi]
+ [mcs_index + 4];
+ break;
+ }
+ } else {
+ switch (mcs_index) {
+ case 0:
+ case 1:
+ // #if 0
+ // if (he_tone < 3) {
+ // rate =
+ //ax_tone_ru_rate_nss1[3*(2-he_tone)+gi][mcs_index*2
+ //+ he_dcm];
+ // } else {
+ // #endif
+ rate = ax_mcs_rate_nss1[3 * (3 - bw) + gi]
+ [mcs_index * 2 + he_dcm];
+ break;
+ case 2:
+ // #if 0
+ // if (he_tone < 3) {
+ // rate =
+ //ax_tone_ru_rate_nss1[3*(2-he_tone)+gi][mcs_index*2];
+ // } else {
+ // #endif
+ rate = ax_mcs_rate_nss1[3 * (3 - bw) + gi]
+ [mcs_index * 2];
+ break;
+ case 3:
+ case 4:
+ // #if 0
+ // if (he_tone < 3) {
+ // rate =
+ //ax_tone_ru_rate_nss1[3*(2-he_tone)+gi][mcs_index*2
+ //- 1 + he_dcm];
+ // } else {
+ // #endif
+ rate = ax_mcs_rate_nss1[3 * (3 - bw) + gi]
+ [mcs_index * 2 - 1 +
+ he_dcm];
+ break;
+
+ default:
+ // #if 0
+ // if (he_tone < 3) {
+ // rate =
+ //ax_tone_ru_rate_nss1[3*(2-he_tone)+gi][mcs_index
+ //+ 4];
+ // } else {
+ // #endif
+ rate = ax_mcs_rate_nss1[3 * (3 - bw) + gi]
+ [mcs_index + 4];
+ break;
+ }
+ }
+ } else if ((tx_rate_info & 0x3) == MLAN_RATE_FORMAT_HT) {
+ /* HT rate */
+ /* 20M: bw=0, 40M: bw=1 */
+ bw = (tx_rate_info & 0xC) >> 2;
+ /* LGI: gi =0, SGI: gi = 1 */
+ gi = (tx_rate_info & 0x10) >> 4;
+ if (index == MLAN_RATE_BITMAP_MCS0) {
+ if (gi == 1)
+ rate = 0x0D; /* MCS 32 SGI rate */
+ else
+ rate = 0x0C; /* MCS 32 LGI rate */
+ } else if (index < MCS_NUM_SUPP) {
+ if (bw <= 1)
+ rate = mcs_rate[2 * (1 - bw) + gi][index];
+ else
+ rate = WlanDataRates[0];
+ } else
+ rate = WlanDataRates[0];
+ } else {
+ /* 11n non HT rates */
+ if (index >= WLAN_SUPPORTED_RATES_EXT)
+ index = 0;
+ rate = WlanDataRates[index];
+ }
+ LEAVE();
+ return rate;
+}
+
+/**
+ * @brief Use rate to get the index
+ *
+ * @param pmadapter A pointer to mlan_adapter structure
+ * @param rate Data rate
+ *
+ * @return Index or 0
+ */
+t_u8 wlan_data_rate_to_index(pmlan_adapter pmadapter, t_u32 rate)
+{
+ t_u16 *ptr;
+
+ ENTER();
+ if (rate) {
+ ptr = wlan_memchr(pmadapter, WlanDataRates, (t_u8)rate,
+ sizeof(WlanDataRates));
+ if (ptr) {
+ LEAVE();
+ return (t_u8)(ptr - WlanDataRates);
+ }
+ }
+ LEAVE();
+ return 0;
+}
+
+/**
+ * @brief Get active data rates
+ *
+ * @param pmpriv A pointer to mlan_private structure
+ * @param bss_mode The specified BSS mode (Infra/IBSS)
+ * @param config_bands The specified band configuration
+ * @param rates The buf to return the active rates
+ *
+ * @return The number of Rates
+ */
+t_u32 wlan_get_active_data_rates(mlan_private *pmpriv, t_u32 bss_mode,
+ t_u16 config_bands, WLAN_802_11_RATES rates)
+{
+ t_u32 k;
+
+ ENTER();
+
+ if (pmpriv->media_connected != MTRUE) {
+ k = wlan_get_supported_rates(pmpriv, bss_mode, config_bands,
+ rates);
+ } else {
+ k = wlan_copy_rates(rates, 0,
+ pmpriv->curr_bss_params.data_rates,
+ pmpriv->curr_bss_params.num_of_rates);
+ }
+
+ LEAVE();
+ return k;
+}
+
+#ifdef STA_SUPPORT
+/**
+ * @brief This function search through all the regions cfp table to find the
+ * channel, if the channel is found then gets the MIN txpower of the channel
+ * present in all the regions.
+ *
+ * @param pmpriv A pointer to mlan_private structure
+ * @param channel Channel number.
+ *
+ * @return The Tx power
+ */
+t_u8 wlan_get_txpwr_of_chan_from_cfp(mlan_private *pmpriv, t_u8 channel)
+{
+ t_u8 i = 0;
+ t_u8 j = 0;
+ t_u8 tx_power = 0;
+ t_u32 cfp_no;
+ chan_freq_power_t *cfp = MNULL;
+ chan_freq_power_t *cfp_a = MNULL;
+ t_u32 cfp_no_a;
+
+ ENTER();
+
+ for (i = 0; i < MLAN_CFP_TABLE_SIZE_BG; i++) {
+ /* Get CFP */
+ cfp = cfp_table_BG[i].cfp;
+ cfp_no = cfp_table_BG[i].cfp_no;
+ /* Find matching channel and get Tx power */
+ for (j = 0; j < cfp_no; j++) {
+ if ((cfp + j)->channel == channel) {
+ if (tx_power != 0)
+ tx_power = MIN(tx_power,
+ (cfp + j)->max_tx_power);
+ else
+ tx_power =
+ (t_u8)(cfp + j)->max_tx_power;
+ break;
+ }
+ }
+ }
+
+ for (i = 0; i < MLAN_CFP_TABLE_SIZE_A; i++) {
+ /* Get CFP */
+ cfp_a = cfp_table_A[i].cfp;
+ cfp_no_a = cfp_table_A[i].cfp_no;
+ for (j = 0; j < cfp_no_a; j++) {
+ if ((cfp_a + j)->channel == channel) {
+ if (tx_power != 0)
+ tx_power =
+ MIN(tx_power,
+ (cfp_a + j)->max_tx_power);
+ else
+ tx_power = (t_u8)(
+ (cfp_a + j)->max_tx_power);
+ break;
+ }
+ }
+ }
+
+ LEAVE();
+ return tx_power;
+}
+
+/**
+ * @brief Get the channel frequency power info for a specific channel
+ *
+ * @param pmadapter A pointer to mlan_adapter structure
+ * @param band It can be BAND_A, BAND_G or BAND_B
+ * @param channel The channel to search for
+ * @param region_channel A pointer to region_chan_t structure
+ *
+ * @return A pointer to chan_freq_power_t structure or
+ * MNULL if not found.
+ */
+
+chan_freq_power_t *
+wlan_get_cfp_by_band_and_channel(pmlan_adapter pmadapter, t_u8 band,
+ t_u16 channel, region_chan_t *region_channel)
+{
+ region_chan_t *rc;
+ chan_freq_power_t *cfp = MNULL;
+ int i, j;
+
+ ENTER();
+
+ for (j = 0; !cfp && (j < MAX_REGION_CHANNEL_NUM); j++) {
+ rc = &region_channel[j];
+
+ if (!rc->valid || !rc->pcfp)
+ continue;
+ switch (rc->band) {
+ case BAND_A:
+ switch (band) {
+ case BAND_AN:
+ case BAND_A | BAND_AN:
+ case BAND_A | BAND_AN | BAND_AAC:
+ /* Fall Through */
+ case BAND_A: /* Matching BAND_A */
+ break;
+
+ default:
+ continue;
+ }
+ break;
+ case BAND_B:
+ case BAND_G:
+ switch (band) {
+ case BAND_GN:
+ case BAND_B | BAND_G | BAND_GN:
+ case BAND_G | BAND_GN:
+ case BAND_GN | BAND_GAC:
+ case BAND_B | BAND_G | BAND_GN | BAND_GAC:
+ case BAND_G | BAND_GN | BAND_GAC:
+ case BAND_B | BAND_G:
+ /* Fall Through */
+ case BAND_B: /* Matching BAND_B/G */
+ /* Fall Through */
+ case BAND_G:
+ /* Fall Through */
+ case 0:
+ break;
+ default:
+ continue;
+ }
+ break;
+ default:
+ continue;
+ }
+ if (channel == FIRST_VALID_CHANNEL)
+ cfp = &rc->pcfp[0];
+ else {
+ for (i = 0; i < rc->num_cfp; i++) {
+ if (rc->pcfp[i].channel == channel) {
+ cfp = &rc->pcfp[i];
+ break;
+ }
+ }
+ }
+ }
+
+ if (!cfp && channel)
+ PRINTM(MCMND, "%s: can not find cfp by band %d & channel %d\n",
+ __func__, band, channel);
+
+ LEAVE();
+ return cfp;
+}
+
+/**
+ * @brief Find the channel frequency power info for a specific channel
+ *
+ * @param pmadapter A pointer to mlan_adapter structure
+ * @param band It can be BAND_A, BAND_G or BAND_B
+ * @param channel The channel to search for
+ *
+ * @return A pointer to chan_freq_power_t structure or MNULL if not
+ * found.
+ */
+chan_freq_power_t *wlan_find_cfp_by_band_and_channel(mlan_adapter *pmadapter,
+ t_u8 band, t_u16 channel)
+{
+ chan_freq_power_t *cfp = MNULL;
+
+ ENTER();
+
+ /* Any station(s) with 11D enabled */
+ if (wlan_count_priv_cond(pmadapter, wlan_11d_is_enabled,
+ wlan_is_station) > 0)
+ cfp = wlan_get_cfp_by_band_and_channel(
+ pmadapter, band, channel, pmadapter->universal_channel);
+ else
+ cfp = wlan_get_cfp_by_band_and_channel(
+ pmadapter, band, channel, pmadapter->region_channel);
+
+ LEAVE();
+ return cfp;
+}
+
+/**
+ * @brief Find the channel frequency power info for a specific frequency
+ *
+ * @param pmadapter A pointer to mlan_adapter structure
+ * @param band It can be BAND_A, BAND_G or BAND_B
+ * @param freq The frequency to search for
+ *
+ * @return Pointer to chan_freq_power_t structure; MNULL if not found
+ */
+chan_freq_power_t *wlan_find_cfp_by_band_and_freq(mlan_adapter *pmadapter,
+ t_u8 band, t_u32 freq)
+{
+ chan_freq_power_t *cfp = MNULL;
+ region_chan_t *rc;
+ int i, j;
+
+ ENTER();
+
+ for (j = 0; !cfp && (j < MAX_REGION_CHANNEL_NUM); j++) {
+ rc = &pmadapter->region_channel[j];
+
+ /* Any station(s) with 11D enabled */
+ if (wlan_count_priv_cond(pmadapter, wlan_11d_is_enabled,
+ wlan_is_station) > 0)
+ rc = &pmadapter->universal_channel[j];
+
+ if (!rc->valid || !rc->pcfp)
+ continue;
+ switch (rc->band) {
+ case BAND_A:
+ switch (band) {
+ case BAND_AN:
+ case BAND_A | BAND_AN:
+ case BAND_A | BAND_AN | BAND_AAC:
+ /* Fall Through */
+ case BAND_A: /* Matching BAND_A */
+ break;
+ default:
+ continue;
+ }
+ break;
+ case BAND_B:
+ case BAND_G:
+ switch (band) {
+ case BAND_GN:
+ case BAND_B | BAND_G | BAND_GN:
+ case BAND_G | BAND_GN:
+ case BAND_GN | BAND_GAC:
+ case BAND_B | BAND_G | BAND_GN | BAND_GAC:
+ case BAND_G | BAND_GN | BAND_GAC:
+ case BAND_B | BAND_G:
+ /* Fall Through */
+ case BAND_B:
+ /* Fall Through */
+ case BAND_G:
+ /* Fall Through */
+ case 0:
+ break;
+ default:
+ continue;
+ }
+ break;
+ default:
+ continue;
+ }
+ for (i = 0; i < rc->num_cfp; i++) {
+ if (rc->pcfp[i].freq == freq) {
+ cfp = &rc->pcfp[i];
+ break;
+ }
+ }
+ }
+
+ if (!cfp && freq)
+ PRINTM(MERROR, "%s: cannot find cfp by band %d & freq %d\n",
+ __func__, band, freq);
+
+ LEAVE();
+ return cfp;
+}
+#endif /* STA_SUPPORT */
+
+/**
+ * @brief Check if Rate Auto
+ *
+ * @param pmpriv A pointer to mlan_private structure
+ *
+ * @return MTRUE or MFALSE
+ */
+t_u8 wlan_is_rate_auto(mlan_private *pmpriv)
+{
+ t_u32 i;
+ int rate_num = 0;
+
+ ENTER();
+
+ for (i = 0; i < NELEMENTS(pmpriv->bitmap_rates); i++)
+ if (pmpriv->bitmap_rates[i])
+ rate_num++;
+
+ LEAVE();
+ if (rate_num > 1)
+ return MTRUE;
+ else
+ return MFALSE;
+}
+
+/**
+ * @brief Covert Rate Bitmap to Rate index
+ *
+ * @param pmadapter Pointer to mlan_adapter structure
+ * @param rate_bitmap Pointer to rate bitmap
+ * @param size Size of the bitmap array
+ *
+ * @return Rate index
+ */
+int wlan_get_rate_index(pmlan_adapter pmadapter, t_u16 *rate_bitmap, int size)
+{
+ int i;
+
+ ENTER();
+
+ for (i = 0; i < size * 8; i++) {
+ if (rate_bitmap[i / 16] & (1 << (i % 16))) {
+ LEAVE();
+ return i;
+ }
+ }
+
+ LEAVE();
+ return -1;
+}
+
+/**
+ * @brief Get supported data rates
+ *
+ * @param pmpriv A pointer to mlan_private structure
+ * @param bss_mode The specified BSS mode (Infra/IBSS)
+ * @param config_bands The specified band configuration
+ * @param rates The buf to return the supported rates
+ *
+ * @return The number of Rates
+ */
+t_u32 wlan_get_supported_rates(mlan_private *pmpriv, t_u32 bss_mode,
+ t_u16 config_bands, WLAN_802_11_RATES rates)
+{
+ t_u32 k = 0;
+
+ ENTER();
+
+ if (bss_mode == MLAN_BSS_MODE_INFRA) {
+ /* Infra. mode */
+ switch (config_bands) {
+ case (t_u8)BAND_B:
+ PRINTM(MINFO, "Infra Band=%d SupportedRates_B\n",
+ config_bands);
+ k = wlan_copy_rates(rates, k, SupportedRates_B,
+ sizeof(SupportedRates_B));
+ break;
+ case (t_u8)BAND_G:
+ case BAND_G | BAND_GN:
+ case BAND_G | BAND_GN | BAND_GAC:
+ case BAND_G | BAND_GN | BAND_GAC | BAND_GAX:
+ PRINTM(MINFO, "Infra band=%d SupportedRates_G\n",
+ config_bands);
+ k = wlan_copy_rates(rates, k, SupportedRates_G,
+ sizeof(SupportedRates_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_A | BAND_B | BAND_G | BAND_GN | BAND_AN | BAND_AAC |
+ BAND_GAC:
+ case BAND_A | BAND_B | BAND_G | BAND_GN | BAND_AN | BAND_AAC |
+ BAND_AAX:
+ case BAND_A | BAND_B | BAND_G | BAND_GN | BAND_AN | BAND_AAC |
+ BAND_GAC | BAND_AAX | BAND_GAX:
+ case BAND_B | BAND_G | BAND_GN:
+ case BAND_B | BAND_G | BAND_GN | BAND_GAC:
+ case BAND_B | BAND_G | BAND_GN | BAND_GAC | BAND_GAX:
+ PRINTM(MINFO, "Infra band=%d SupportedRates_BG\n",
+ config_bands);
+#ifdef WIFI_DIRECT_SUPPORT
+ if (pmpriv->bss_type == MLAN_BSS_TYPE_WIFIDIRECT)
+ k = wlan_copy_rates(rates, k, SupportedRates_G,
+ sizeof(SupportedRates_G));
+ else
+ k = wlan_copy_rates(rates, k, SupportedRates_BG,
+ sizeof(SupportedRates_BG));
+#else
+ k = wlan_copy_rates(rates, k, SupportedRates_BG,
+ sizeof(SupportedRates_BG));
+#endif
+ break;
+ case BAND_A:
+ case BAND_A | BAND_G:
+ PRINTM(MINFO, "Infra band=%d SupportedRates_A\n",
+ config_bands);
+ k = wlan_copy_rates(rates, k, SupportedRates_A,
+ sizeof(SupportedRates_A));
+ break;
+ case BAND_AN:
+ case BAND_A | BAND_AN:
+ case BAND_A | BAND_G | BAND_AN | BAND_GN:
+ case BAND_A | BAND_AN | BAND_AAC:
+ case BAND_A | BAND_G | BAND_AN | BAND_GN | BAND_AAC:
+ case BAND_A | BAND_AN | BAND_AAC | BAND_AAX:
+ case BAND_A | BAND_G | BAND_AN | BAND_GN | BAND_AAC | BAND_AAX:
+ PRINTM(MINFO, "Infra band=%d SupportedRates_A\n",
+ config_bands);
+ k = wlan_copy_rates(rates, k, SupportedRates_A,
+ sizeof(SupportedRates_A));
+ break;
+ case BAND_GN:
+ case BAND_GN | BAND_GAC:
+ case BAND_GN | BAND_GAC | BAND_GAX:
+ PRINTM(MINFO, "Infra band=%d SupportedRates_N\n",
+ config_bands);
+ k = wlan_copy_rates(rates, k, SupportedRates_N,
+ sizeof(SupportedRates_N));
+ break;
+ }
+ } else {
+ /* Ad-hoc mode */
+ switch (config_bands) {
+ case (t_u8)BAND_B:
+ PRINTM(MINFO, "Band: Adhoc B\n");
+ k = wlan_copy_rates(rates, k, AdhocRates_B,
+ sizeof(AdhocRates_B));
+ break;
+ case (t_u8)BAND_G:
+ PRINTM(MINFO, "Band: Adhoc G only\n");
+ k = wlan_copy_rates(rates, k, AdhocRates_G,
+ sizeof(AdhocRates_G));
+ break;
+ case BAND_B | BAND_G:
+ PRINTM(MINFO, "Band: Adhoc BG\n");
+ k = wlan_copy_rates(rates, k, AdhocRates_BG,
+ sizeof(AdhocRates_BG));
+ break;
+ case BAND_A:
+ case BAND_A | BAND_AN | BAND_AAC:
+ case BAND_A | BAND_AN | BAND_AAC | BAND_AAX:
+
+ PRINTM(MINFO, "Band: Adhoc A\n");
+ k = wlan_copy_rates(rates, k, AdhocRates_A,
+ sizeof(AdhocRates_A));
+ break;
+ }
+ }
+
+ LEAVE();
+ return k;
+}
+
+#define COUNTRY_ID_US 0
+#define COUNTRY_ID_JP 1
+#define COUNTRY_ID_CN 2
+#define COUNTRY_ID_EU 3
+typedef struct _oper_bw_chan {
+ /*non-global operating class*/
+ t_u8 oper_class;
+ /*global operating class*/
+ t_u8 global_oper_class;
+ /*bandwidth 0-20M 1-40M 2-80M 3-160M*/
+ t_u8 bandwidth;
+ /*channel list*/
+ t_u8 channel_list[13];
+} oper_bw_chan;
+
+/** oper class table for US*/
+static oper_bw_chan oper_bw_chan_us[] = {
+ /** non-Global oper class, global oper class, bandwidth, channel list*/
+ {1, 115, 0, {36, 40, 44, 48}},
+ {2, 118, 0, {52, 56, 60, 64}},
+ {3, 124, 0, {149, 153, 157, 161}},
+ {4,
+ 121,
+ 0,
+ {100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140, 144}},
+ {5, 125, 0, {149, 153, 157, 161, 165}},
+ {12, 81, 0, {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11}},
+ {22, 116, 1, {36, 44}},
+ {23, 119, 1, {52, 60}},
+ {24, 122, 1, {100, 108, 116, 124, 132, 140}},
+ {25, 126, 1, {149, 157}},
+ {26, 126, 1, {149, 157}},
+ {27, 117, 1, {40, 48}},
+ {28, 120, 1, {56, 64}},
+ {29, 123, 1, {104, 112, 120, 128, 136, 144}},
+ {30, 127, 1, {153, 161}},
+ {31, 127, 1, {153, 161}},
+ {32, 83, 1, {1, 2, 3, 4, 5, 6, 7}},
+ {33, 84, 1, {5, 6, 7, 8, 9, 10, 11}},
+ {128, 128, 2, {42, 58, 106, 122, 138, 155}},
+ {129, 129, 3, {50, 114}},
+ {130, 130, 2, {42, 58, 106, 122, 138, 155}},
+};
+/** oper class table for EU*/
+static oper_bw_chan oper_bw_chan_eu[] = {
+ /** non-global oper class,global oper class, bandwidth, channel list*/
+ {1, 115, 0, {36, 40, 44, 48}},
+ {2, 118, 0, {52, 56, 60, 64}},
+ {3, 121, 0, {100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140}},
+ {4, 81, 0, {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13}},
+ {5, 116, 1, {36, 44}},
+ {6, 119, 1, {52, 60}},
+ {7, 122, 1, {100, 108, 116, 124, 132}},
+ {8, 117, 1, {40, 48}},
+ {9, 120, 1, {56, 64}},
+ {10, 123, 1, {104, 112, 120, 128, 136}},
+ {11, 83, 1, {1, 2, 3, 4, 5, 6, 7, 8, 9}},
+ {12, 84, 1, {5, 6, 7, 8, 9, 10, 11, 12, 13}},
+ {17, 125, 0, {149, 153, 157, 161, 165, 169}},
+ {128, 128, 2, {42, 58, 106, 122, 138, 155}},
+ {129, 129, 3, {50, 114}},
+ {130, 130, 2, {42, 58, 106, 122, 138, 155}},
+};
+/** oper class table for Japan*/
+static oper_bw_chan oper_bw_chan_jp[] = {
+ /** non-Global oper class,global oper class, bandwidth, channel list*/
+ {1, 115, 0, {34, 38, 42, 46, 36, 40, 44, 48}},
+ {30, 81, 0, {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13}},
+ {31, 82, 0, {14}},
+ {32, 118, 0, {52, 56, 60, 64}},
+ {33, 118, 0, {52, 56, 60, 64}},
+ {34, 121, 0, {100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140}},
+ {35, 121, 0, {100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140}},
+ {36, 116, 1, {36, 44}},
+ {37, 119, 1, {52, 60}},
+ {38, 119, 1, {52, 60}},
+ {39, 122, 1, {100, 108, 116, 124, 132}},
+ {40, 122, 1, {100, 108, 116, 124, 132}},
+ {41, 117, 1, {40, 48}},
+ {42, 120, 1, {56, 64}},
+ {43, 120, 1, {56, 64}},
+ {44, 123, 1, {104, 112, 120, 128, 136}},
+ {45, 123, 1, {104, 112, 120, 128, 136}},
+ {56, 83, 1, {1, 2, 3, 4, 5, 6, 7, 8, 9}},
+ {57, 84, 1, {5, 6, 7, 8, 9, 10, 11, 12, 13}},
+ {58, 121, 0, {100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140}},
+ {128, 128, 2, {42, 58, 106, 122, 138, 155}},
+ {129, 129, 3, {50, 114}},
+ {130, 130, 2, {42, 58, 106, 122, 138, 155}},
+};
+/** oper class table for China*/
+static oper_bw_chan oper_bw_chan_cn[] = {
+ /** non-Global oper class,global oper class, bandwidth, channel list*/
+ {1, 115, 0, {36, 40, 44, 48}},
+ {2, 118, 0, {52, 56, 60, 64}},
+ {3, 125, 0, {149, 153, 157, 161, 165}},
+ {4, 116, 1, {36, 44}},
+ {5, 119, 1, {52, 60}},
+ {6, 126, 1, {149, 157}},
+ {7, 81, 0, {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13}},
+ {8, 83, 0, {1, 2, 3, 4, 5, 6, 7, 8, 9}},
+ {9, 84, 1, {5, 6, 7, 8, 9, 10, 11, 12, 13}},
+ {128, 128, 2, {42, 58, 106, 122, 138, 155}},
+ {129, 129, 3, {50, 114}},
+ {130, 130, 2, {42, 58, 106, 122, 138, 155}},
+};
+
+/**
+ * @brief Get non-global operaing class table according to country
+ *
+ * @param pmpriv A pointer to mlan_private structure
+ * @param arraysize A pointer to table size
+ *
+ * @return A pointer to oper_bw_chan
+ */
+oper_bw_chan *wlan_get_nonglobal_operclass_table(mlan_private *pmpriv,
+ int *arraysize)
+{
+ t_u8 country_code[][COUNTRY_CODE_LEN] = {"US", "JP", "CN"};
+ int country_id = 0;
+ oper_bw_chan *poper_bw_chan = MNULL;
+
+ ENTER();
+
+ for (country_id = 0; country_id < 3; country_id++)
+ if (!memcmp(pmpriv->adapter, pmpriv->adapter->country_code,
+ country_code[country_id], COUNTRY_CODE_LEN - 1))
+ break;
+ if (country_id >= 3)
+ country_id = COUNTRY_ID_US; /*Set default to US*/
+ if (wlan_is_etsi_country(pmpriv->adapter,
+ pmpriv->adapter->country_code))
+ country_id = COUNTRY_ID_EU; /** Country in EU */
+
+ switch (country_id) {
+ case COUNTRY_ID_US:
+ poper_bw_chan = oper_bw_chan_us;
+ *arraysize = sizeof(oper_bw_chan_us);
+ break;
+ case COUNTRY_ID_JP:
+ poper_bw_chan = oper_bw_chan_jp;
+ *arraysize = sizeof(oper_bw_chan_jp);
+ break;
+ case COUNTRY_ID_CN:
+ poper_bw_chan = oper_bw_chan_cn;
+ *arraysize = sizeof(oper_bw_chan_cn);
+ break;
+ case COUNTRY_ID_EU:
+ poper_bw_chan = oper_bw_chan_eu;
+ *arraysize = sizeof(oper_bw_chan_eu);
+ break;
+ default:
+ PRINTM(MERROR, "Country not support!\n");
+ break;
+ }
+
+ LEAVE();
+ return poper_bw_chan;
+}
+
+/**
+ * @brief Check validation of given channel and oper class
+ *
+ * @param pmpriv A pointer to mlan_private structure
+ * @param channel Channel number
+ * @param oper_class operating class
+ *
+ * @return MLAN_STATUS_PENDING --success, otherwise fail
+ */
+mlan_status wlan_check_operclass_validation(mlan_private *pmpriv, t_u8 channel,
+ t_u8 oper_class)
+{
+ int arraysize = 0, i = 0, channum = 0;
+ oper_bw_chan *poper_bw_chan = MNULL;
+ t_u8 center_freq_idx = 0;
+ t_u8 center_freqs[] = {42, 50, 58, 106, 114, 122, 138, 155};
+
+ ENTER();
+
+ for (i = 0; i < sizeof(center_freqs); i++) {
+ if (channel == center_freqs[i]) {
+ PRINTM(MERROR, "Invalid channel number %d!\n", channel);
+ LEAVE();
+ return MLAN_STATUS_FAILURE;
+ }
+ }
+ if (oper_class <= 0 || oper_class > 130) {
+ PRINTM(MERROR, "Invalid operating class!\n");
+ LEAVE();
+ return MLAN_STATUS_FAILURE;
+ }
+ if (oper_class >= 128) {
+ center_freq_idx = wlan_get_center_freq_idx(
+ pmpriv, BAND_AAC, channel, CHANNEL_BW_80MHZ);
+ channel = center_freq_idx;
+ }
+ poper_bw_chan = wlan_get_nonglobal_operclass_table(pmpriv, &arraysize);
+
+ if (!poper_bw_chan) {
+ PRINTM(MCMND, "Operating class table do not find!\n");
+ LEAVE();
+ return MLAN_STATUS_FAILURE;
+ }
+
+ for (i = 0; i < arraysize / sizeof(oper_bw_chan); i++) {
+ if (poper_bw_chan[i].oper_class == oper_class ||
+ poper_bw_chan[i].global_oper_class == oper_class) {
+ for (channum = 0;
+ channum < sizeof(poper_bw_chan[i].channel_list);
+ channum++) {
+ if (poper_bw_chan[i].channel_list[channum] &&
+ poper_bw_chan[i].channel_list[channum] ==
+ channel) {
+ LEAVE();
+ return MLAN_STATUS_SUCCESS;
+ }
+ }
+ }
+ }
+
+ PRINTM(MCMND, "Operating class %d do not match channel %d!\n",
+ oper_class, channel);
+ LEAVE();
+ return MLAN_STATUS_FAILURE;
+}
+
+/**
+ * @brief Get current operating class from channel and bandwidth
+ *
+ * @param pmpriv A pointer to mlan_private structure
+ * @param channel Channel number
+ * @param bw Bandwidth
+ * @param oper_class A pointer to current operating class
+ *
+ * @return MLAN_STATUS_PENDING --success, otherwise fail
+ */
+mlan_status wlan_get_curr_oper_class(mlan_private *pmpriv, t_u8 channel,
+ t_u8 bw, t_u8 *oper_class)
+{
+ oper_bw_chan *poper_bw_chan = MNULL;
+ t_u8 center_freq_idx = 0;
+ t_u8 center_freqs[] = {42, 50, 58, 106, 114, 122, 138, 155};
+ int i = 0, arraysize = 0, channum = 0;
+
+ ENTER();
+
+ poper_bw_chan = wlan_get_nonglobal_operclass_table(pmpriv, &arraysize);
+
+ if (!poper_bw_chan) {
+ PRINTM(MCMND, "Operating class table do not find!\n");
+ LEAVE();
+ return MLAN_STATUS_FAILURE;
+ }
+ for (i = 0; i < sizeof(center_freqs); i++) {
+ if (channel == center_freqs[i]) {
+ PRINTM(MERROR, "Invalid channel number %d!\n", channel);
+ LEAVE();
+ return MLAN_STATUS_FAILURE;
+ }
+ }
+ if (bw == BW_80MHZ) {
+ center_freq_idx = wlan_get_center_freq_idx(
+ pmpriv, BAND_AAC, channel, CHANNEL_BW_80MHZ);
+ channel = center_freq_idx;
+ }
+
+ for (i = 0; i < arraysize / sizeof(oper_bw_chan); i++) {
+ if (poper_bw_chan[i].bandwidth == bw) {
+ for (channum = 0;
+ channum < sizeof(poper_bw_chan[i].channel_list);
+ channum++) {
+ if (poper_bw_chan[i].channel_list[channum] &&
+ poper_bw_chan[i].channel_list[channum] ==
+ channel) {
+ *oper_class =
+ poper_bw_chan[i].oper_class;
+ return MLAN_STATUS_SUCCESS;
+ }
+ }
+ }
+ }
+
+ PRINTM(MCMND, "Operating class not find!\n");
+ LEAVE();
+ return MLAN_STATUS_FAILURE;
+}
+
+/**
+ * @brief Add Supported operating classes IE
+ *
+ * @param pmpriv A pointer to mlan_private structure
+ * @param pptlv_out A pointer to TLV to fill in
+ * @param curr_oper_class Current operating class
+ *
+ * @return Length
+ */
+int wlan_add_supported_oper_class_ie(mlan_private *pmpriv, t_u8 **pptlv_out,
+ t_u8 curr_oper_class)
+{
+ t_u8 oper_class_us[] = {1, 2, 3, 4, 5, 12, 22, 23, 24, 25, 26,
+ 27, 28, 29, 30, 31, 32, 33, 128, 129, 130};
+ t_u8 oper_class_eu[] = {1, 2, 3, 4, 5, 6, 7, 8,
+ 9, 10, 11, 12, 17, 128, 129, 130};
+ t_u8 oper_class_jp[] = {1, 30, 31, 32, 33, 34, 35, 36,
+ 37, 38, 39, 40, 41, 42, 43, 44,
+ 45, 56, 57, 58, 128, 129, 130};
+ t_u8 oper_class_cn[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 128, 129, 130};
+ t_u8 country_code[][COUNTRY_CODE_LEN] = {"US", "JP", "CN"};
+ int country_id = 0, ret = 0;
+ MrvlIETypes_SuppOperClass_t *poper_class = MNULL;
+
+ ENTER();
+
+ for (country_id = 0; country_id < 3; country_id++)
+ if (!memcmp(pmpriv->adapter, pmpriv->adapter->country_code,
+ country_code[country_id], COUNTRY_CODE_LEN - 1))
+ break;
+ if (country_id >= 3)
+ country_id = COUNTRY_ID_US; /*Set default to US*/
+ if (wlan_is_etsi_country(pmpriv->adapter,
+ pmpriv->adapter->country_code))
+ country_id = COUNTRY_ID_EU; /** Country in EU */
+ poper_class = (MrvlIETypes_SuppOperClass_t *)*pptlv_out;
+ memset(pmpriv->adapter, poper_class, 0,
+ sizeof(MrvlIETypes_SuppOperClass_t));
+ poper_class->header.type = wlan_cpu_to_le16(REGULATORY_CLASS);
+ if (country_id == COUNTRY_ID_US) {
+ poper_class->header.len = sizeof(oper_class_us);
+ memcpy_ext(pmpriv->adapter, &poper_class->oper_class,
+ oper_class_us, sizeof(oper_class_us),
+ poper_class->header.len);
+ } else if (country_id == COUNTRY_ID_JP) {
+ poper_class->header.len = sizeof(oper_class_jp);
+ memcpy_ext(pmpriv->adapter, &poper_class->oper_class,
+ oper_class_jp, sizeof(oper_class_jp),
+ poper_class->header.len);
+ } else if (country_id == COUNTRY_ID_CN) {
+ poper_class->header.len = sizeof(oper_class_cn);
+ memcpy_ext(pmpriv->adapter, &poper_class->oper_class,
+ oper_class_cn, sizeof(oper_class_cn),
+ poper_class->header.len);
+ } else if (country_id == COUNTRY_ID_EU) {
+ poper_class->header.len = sizeof(oper_class_eu);
+ memcpy_ext(pmpriv->adapter, &poper_class->oper_class,
+ oper_class_eu, sizeof(oper_class_eu),
+ poper_class->header.len);
+ }
+ poper_class->current_oper_class = curr_oper_class;
+ poper_class->header.len += sizeof(poper_class->current_oper_class);
+ DBG_HEXDUMP(MCMD_D, "Operating class", (t_u8 *)poper_class,
+ sizeof(MrvlIEtypesHeader_t) + poper_class->header.len);
+ ret = sizeof(MrvlIEtypesHeader_t) + poper_class->header.len;
+ *pptlv_out += ret;
+ poper_class->header.len = wlan_cpu_to_le16(poper_class->header.len);
+
+ LEAVE();
+ return ret;
+}
+
+/**
+ * @brief This function sets region table.
+ *
+ * @param pmpriv A pointer to mlan_private structure
+ * @param region The region code
+ * @param band The band
+ *
+ * @return MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ */
+mlan_status wlan_set_regiontable(mlan_private *pmpriv, t_u8 region, t_u8 band)
+{
+ mlan_adapter *pmadapter = pmpriv->adapter;
+ int i = 0, j;
+ chan_freq_power_t *cfp;
+ int cfp_no;
+ region_chan_t region_chan_old[MAX_REGION_CHANNEL_NUM];
+ t_u8 cfp_code_bg = region;
+ t_u8 cfp_code_a = region;
+
+ ENTER();
+
+ memcpy_ext(pmadapter, region_chan_old, pmadapter->region_channel,
+ sizeof(pmadapter->region_channel), sizeof(region_chan_old));
+ memset(pmadapter, pmadapter->region_channel, 0,
+ sizeof(pmadapter->region_channel));
+
+ if (band & (BAND_B | BAND_G | BAND_GN)) {
+ if (pmadapter->cfp_code_bg)
+ cfp_code_bg = pmadapter->cfp_code_bg;
+ PRINTM(MCMND, "%s: 2.4G 0x%x\n", __func__, cfp_code_bg);
+ cfp = wlan_get_region_cfp_table(pmadapter, cfp_code_bg,
+ BAND_G | BAND_B | BAND_GN,
+ &cfp_no);
+ if (cfp) {
+ pmadapter->region_channel[i].num_cfp = (t_u8)cfp_no;
+ pmadapter->region_channel[i].pcfp = cfp;
+ } else {
+ PRINTM(MERROR, "wrong region code %#x in Band B-G\n",
+ region);
+ LEAVE();
+ return MLAN_STATUS_FAILURE;
+ }
+ pmadapter->region_channel[i].valid = MTRUE;
+ pmadapter->region_channel[i].region = region;
+ if (band & BAND_GN)
+ pmadapter->region_channel[i].band = BAND_G;
+ else
+ pmadapter->region_channel[i].band =
+ (band & BAND_G) ? BAND_G : BAND_B;
+
+ for (j = 0; j < MAX_REGION_CHANNEL_NUM; j++) {
+ if (region_chan_old[j].band & (BAND_B | BAND_G))
+ break;
+ }
+
+ if ((j < MAX_REGION_CHANNEL_NUM) &&
+ (region_chan_old[j].valid == MTRUE)) {
+ wlan_cfp_copy_dynamic(pmadapter, cfp, cfp_no,
+ region_chan_old[j].pcfp,
+ region_chan_old[j].num_cfp);
+ } else if (region) {
+ wlan_cfp_copy_dynamic(pmadapter, cfp, cfp_no, MNULL, 0);
+ }
+ i++;
+ }
+ if (band & (BAND_A | BAND_AN | BAND_AAC)) {
+ if (pmadapter->cfp_code_bg)
+ cfp_code_a = pmadapter->cfp_code_a;
+ PRINTM(MCMND, "%s: 5G 0x%x\n", __func__, cfp_code_a);
+ cfp = wlan_get_region_cfp_table(pmadapter, cfp_code_a, BAND_A,
+ &cfp_no);
+ if (cfp) {
+ pmadapter->region_channel[i].num_cfp = (t_u8)cfp_no;
+ pmadapter->region_channel[i].pcfp = cfp;
+ } else {
+ PRINTM(MERROR, "wrong region code %#x in Band A\n",
+ region);
+ LEAVE();
+ return MLAN_STATUS_FAILURE;
+ }
+ pmadapter->region_channel[i].valid = MTRUE;
+ pmadapter->region_channel[i].region = region;
+ pmadapter->region_channel[i].band = BAND_A;
+
+ for (j = 0; j < MAX_REGION_CHANNEL_NUM; j++) {
+ if (region_chan_old[j].band & BAND_A)
+ break;
+ }
+ if ((j < MAX_REGION_CHANNEL_NUM) && region_chan_old[j].valid) {
+ wlan_cfp_copy_dynamic(pmadapter, cfp, cfp_no,
+ region_chan_old[j].pcfp,
+ region_chan_old[j].num_cfp);
+ } else if (region) {
+ wlan_cfp_copy_dynamic(pmadapter, cfp, cfp_no, MNULL, 0);
+ }
+ }
+ LEAVE();
+ return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ * @brief Get if radar detection is enabled or not on a certain channel
+ *
+ * @param priv Private driver information structure
+ * @param chnl Channel to determine radar detection requirements
+ *
+ * @return
+ * - MTRUE if radar detection is required
+ * - MFALSE otherwise
+ */
+t_bool wlan_get_cfp_radar_detect(mlan_private *priv, t_u8 chnl)
+{
+ int i, j;
+ t_bool required = MFALSE;
+ chan_freq_power_t *pcfp = MNULL;
+
+ ENTER();
+
+ /*get the cfp table first*/
+ for (i = 0; i < MAX_REGION_CHANNEL_NUM; i++) {
+ if (priv->adapter->region_channel[i].band == BAND_A) {
+ pcfp = priv->adapter->region_channel[i].pcfp;
+ break;
+ }
+ }
+
+ if (!pcfp) {
+ /* This means operation in BAND-A is not support, we can
+ * just return false here, it's harmless
+ */
+ goto done;
+ }
+
+ /*get the radar detection requirements according to chan num*/
+ for (j = 0; j < priv->adapter->region_channel[i].num_cfp; j++) {
+ if (pcfp[j].channel == chnl) {
+ required = pcfp[j].passive_scan_or_radar_detect;
+ break;
+ }
+ }
+
+done:
+ LEAVE();
+ return required;
+}
+
+/**
+ * @brief Get if scan type is passive or not on a certain channel for b/g band
+ *
+ * @param priv Private driver information structure
+ * @param chnl Channel to determine scan type
+ *
+ * @return
+ * - MTRUE if scan type is passive
+ * - MFALSE otherwise
+ */
+
+t_bool wlan_bg_scan_type_is_passive(mlan_private *priv, t_u8 chnl)
+{
+ int i, j;
+ t_bool passive = MFALSE;
+ chan_freq_power_t *pcfp = MNULL;
+
+ ENTER();
+
+ /*get the cfp table first*/
+ for (i = 0; i < MAX_REGION_CHANNEL_NUM; i++) {
+ if (priv->adapter->region_channel[i].band & (BAND_B | BAND_G)) {
+ pcfp = priv->adapter->region_channel[i].pcfp;
+ break;
+ }
+ }
+
+ if (!pcfp) {
+ /*This means operation in BAND-B or BAND_G is not support, we
+ * can just return false here
+ */
+ goto done;
+ }
+
+ /*get the bg scan type according to chan num*/
+ for (j = 0; j < priv->adapter->region_channel[i].num_cfp; j++) {
+ if (pcfp[j].channel == chnl) {
+ passive = pcfp[j].passive_scan_or_radar_detect;
+ break;
+ }
+ }
+
+done:
+ LEAVE();
+ return passive;
+}
+
+/**
+ * @brief Get if a channel is NO_IR (passive) or not
+ *
+ * @param priv Private driver information structure
+ * @param band Band to check
+ * @param chan Channel to check
+ *
+ * @return
+ * - MTRUE if channel is passive
+ * - MFALSE otherwise
+ */
+
+t_bool wlan_is_chan_passive(mlan_private *priv, t_u8 band, t_u8 chan)
+{
+ int i, j;
+ t_bool passive = MFALSE;
+ chan_freq_power_t *pcfp = MNULL;
+
+ ENTER();
+
+ /* get the cfp table first */
+ for (i = 0; i < MAX_REGION_CHANNEL_NUM; i++) {
+ if (priv->adapter->region_channel[i].band & band) {
+ pcfp = priv->adapter->region_channel[i].pcfp;
+ break;
+ }
+ }
+
+ if (pcfp) {
+ /* check table according to chan num */
+ for (j = 0; j < priv->adapter->region_channel[i].num_cfp; j++) {
+ if (pcfp[j].channel == chan) {
+ if (pcfp[j].dynamic.flags & NXP_CHANNEL_PASSIVE)
+ passive = MTRUE;
+ break;
+ }
+ }
+ }
+
+ LEAVE();
+ return passive;
+}
+
+/**
+ * @brief Get if a channel is disabled or not
+ *
+ * @param priv Private driver information structure
+ * @param band Band to check
+ * @param chan Channel to check
+ *
+ * @return
+ * - MTRUE if channel is disabled
+ * - MFALSE otherwise
+ */
+
+t_bool wlan_is_chan_disabled(mlan_private *priv, t_u8 band, t_u8 chan)
+{
+ int i, j;
+ t_bool disabled = MFALSE;
+ chan_freq_power_t *pcfp = MNULL;
+
+ ENTER();
+
+ /* get the cfp table first */
+ for (i = 0; i < MAX_REGION_CHANNEL_NUM; i++) {
+ if (priv->adapter->region_channel[i].band & band) {
+ pcfp = priv->adapter->region_channel[i].pcfp;
+ break;
+ }
+ }
+
+ if (pcfp) {
+ /* check table according to chan num */
+ for (j = 0; j < priv->adapter->region_channel[i].num_cfp; j++) {
+ if (pcfp[j].channel == chan) {
+ if (pcfp[j].dynamic.flags &
+ NXP_CHANNEL_DISABLED)
+ disabled = MTRUE;
+ break;
+ }
+ }
+ }
+
+ LEAVE();
+ return disabled;
+}
+
+/**
+ * @brief Get if a channel is blacklisted or not
+ *
+ * @param priv Private driver information structure
+ * @param band Band to check
+ * @param chan Channel to check
+ *
+ * @return
+ * - MTRUE if channel is blacklisted
+ * - MFALSE otherwise
+ */
+
+t_bool wlan_is_chan_blacklisted(mlan_private *priv, t_u8 band, t_u8 chan)
+{
+ int i, j;
+ t_bool blacklist = MFALSE;
+ chan_freq_power_t *pcfp = MNULL;
+
+ ENTER();
+
+ /*get the cfp table first*/
+ for (i = 0; i < MAX_REGION_CHANNEL_NUM; i++) {
+ if (priv->adapter->region_channel[i].band & band) {
+ pcfp = priv->adapter->region_channel[i].pcfp;
+ break;
+ }
+ }
+
+ if (pcfp) {
+ /*check table according to chan num*/
+ for (j = 0; j < priv->adapter->region_channel[i].num_cfp; j++) {
+ if (pcfp[j].channel == chan) {
+ blacklist = pcfp[j].dynamic.blacklist;
+ break;
+ }
+ }
+ }
+
+ LEAVE();
+ return blacklist;
+}
+
+/**
+ * @brief Set a channel as blacklisted or not
+ *
+ * @param priv Private driver information structure
+ * @param band Band to check
+ * @param chan Channel to check
+ * @param bl Blacklist if MTRUE
+ *
+ * @return
+ * - MTRUE if channel setting is updated
+ * - MFALSE otherwise
+ */
+
+t_bool wlan_set_chan_blacklist(mlan_private *priv, t_u8 band, t_u8 chan,
+ t_bool bl)
+{
+ int i, j;
+ t_bool set_bl = MFALSE;
+ chan_freq_power_t *pcfp = MNULL;
+
+ ENTER();
+
+ /*get the cfp table first*/
+ for (i = 0; i < MAX_REGION_CHANNEL_NUM; i++) {
+ if (priv->adapter->region_channel[i].band & band) {
+ pcfp = priv->adapter->region_channel[i].pcfp;
+ break;
+ }
+ }
+
+ if (pcfp) {
+ /*check table according to chan num*/
+ for (j = 0; j < priv->adapter->region_channel[i].num_cfp; j++) {
+ if (pcfp[j].channel == chan) {
+ pcfp[j].dynamic.blacklist = bl;
+ set_bl = MTRUE;
+ break;
+ }
+ }
+ }
+
+ LEAVE();
+ return set_bl;
+}
+
+/**
+ * @brief Convert rateid in IEEE format to MRVL format
+ *
+ * @param priv Private driver information structure
+ * @param IeeeMacRate Rate in terms of IEEE format
+ * @param pmbuf A pointer to packet buffer
+ *
+ * @return
+ * Rate ID in terms of MRVL format
+ */
+t_u8 wlan_ieee_rateid_to_mrvl_rateid(mlan_private *priv, t_u16 IeeeMacRate,
+ t_u8 *dst_mac)
+{
+ /* Set default rate ID to RATEID_DBPSK1Mbps */
+ t_u8 mrvlRATEID = 0;
+ const rate_map *rate_tbl = rate_map_table_1x1;
+ t_u32 cnt = sizeof(rate_map_table_1x1) / sizeof(rate_map);
+ t_u8 skip_nss2 = MTRUE;
+ t_u32 i = 0;
+ IEEEtypes_HTCap_t *htcap = MNULL;
+ t_u8 tx_mcs_supp = GET_TXMCSSUPP(priv->usr_dev_mcs_support);
+#ifdef UAP_SUPPORT
+ psta_node sta_ptr = MNULL;
+#endif
+
+ ENTER();
+
+ if (priv->adapter->hw_dev_mcs_support == HT_STREAM_MODE_2X2) {
+ rate_tbl = rate_map_table_2x2;
+ cnt = sizeof(rate_map_table_2x2) / sizeof(rate_map);
+ }
+
+#ifdef UAP_SUPPORT
+ if (priv->bss_role == MLAN_BSS_ROLE_UAP) {
+ if (!dst_mac) {
+ LEAVE();
+ return mrvlRATEID;
+ }
+ sta_ptr = (sta_node *)util_peek_list(
+ priv->adapter->pmoal_handle, &priv->sta_list,
+ priv->adapter->callbacks.moal_spin_lock,
+ priv->adapter->callbacks.moal_spin_unlock);
+ if (!sta_ptr) {
+ LEAVE();
+ return mrvlRATEID;
+ }
+ while (sta_ptr != (sta_node *)&priv->sta_list) {
+ if (memcmp(priv->adapter, dst_mac, sta_ptr->mac_addr,
+ MLAN_MAC_ADDR_LENGTH)) {
+ htcap = &(sta_ptr->HTcap);
+ break;
+ }
+ sta_ptr = sta_ptr->pnext;
+ }
+ }
+#endif
+#ifdef STA_SUPPORT
+ if (priv->bss_role == MLAN_BSS_ROLE_STA)
+ htcap = priv->curr_bss_params.bss_descriptor.pht_cap;
+#endif
+ if (htcap) {
+ /* If user configure tx to 2x2 and peer device rx is 2x2 */
+ if (tx_mcs_supp >= 2 && htcap->ht_cap.supported_mcs_set[1])
+ skip_nss2 = MFALSE;
+ }
+
+ for (i = 0; i < cnt; i++) {
+ if (rate_tbl[i].nss && skip_nss2)
+ continue;
+ if (rate_tbl[i].rate == IeeeMacRate) {
+ mrvlRATEID = rate_tbl[i].id;
+ break;
+ }
+ }
+
+ return mrvlRATEID;
+}
+
+/**
+ * @brief Convert rateid in MRVL format to IEEE format
+ *
+ * @param IeeeMacRate Rate in terms of MRVL format
+ *
+ * @return
+ * Rate ID in terms of IEEE format
+ */
+t_u8 wlan_mrvl_rateid_to_ieee_rateid(t_u8 rate)
+{
+ return rateUnit_500Kbps[rate];
+}
+
+/**
+ * @brief Update CFP tables and power tables from FW
+ *
+ * @param priv Private driver information structure
+ * @param buf Pointer to the buffer holding TLV data
+ * from 0x242 command response.
+ * @param buf_left bufsize
+ *
+ * @return
+ * None
+ */
+void wlan_add_fw_cfp_tables(pmlan_private pmpriv, t_u8 *buf, t_u16 buf_left)
+{
+ mlan_adapter *pmadapter = pmpriv->adapter;
+ mlan_callbacks *pcb = (mlan_callbacks *)&pmadapter->callbacks;
+ MrvlIEtypesHeader_t *head;
+ t_u16 tlv;
+ t_u16 tlv_buf_len;
+ t_u16 tlv_buf_left;
+ t_u16 i;
+ int k = 0, rows, cols;
+ t_u16 max_tx_pwr_bg = WLAN_TX_PWR_DEFAULT;
+ t_u16 max_tx_pwr_a = WLAN_TX_PWR_DEFAULT;
+ t_u8 *tlv_buf;
+ t_u8 *data;
+ t_u8 *tmp;
+ mlan_status ret;
+
+ ENTER();
+
+ if (!buf) {
+ PRINTM(MERROR, "CFP table update failed!\n");
+ goto out;
+ }
+ if (pmadapter->otp_region)
+ wlan_free_fw_cfp_tables(pmadapter);
+ pmadapter->tx_power_table_bg_rows = FW_CFP_TABLE_MAX_ROWS_BG;
+ pmadapter->tx_power_table_bg_cols = FW_CFP_TABLE_MAX_COLS_BG;
+ pmadapter->tx_power_table_a_rows = FW_CFP_TABLE_MAX_ROWS_A;
+ pmadapter->tx_power_table_a_cols = FW_CFP_TABLE_MAX_COLS_A;
+ tlv_buf = (t_u8 *)buf;
+ tlv_buf_left = buf_left;
+
+ while (tlv_buf_left >= sizeof(*head)) {
+ head = (MrvlIEtypesHeader_t *)tlv_buf;
+ tlv = wlan_le16_to_cpu(head->type);
+ tlv_buf_len = wlan_le16_to_cpu(head->len);
+
+ if (tlv_buf_left < (sizeof(*head) + tlv_buf_len))
+ break;
+ data = (t_u8 *)head + sizeof(*head);
+
+ switch (tlv) {
+ case TLV_TYPE_REGION_INFO:
+ /* Skip adding fw region info if it already exists or
+ * if this TLV has no set data
+ */
+ if (*data == 0)
+ break;
+ if (pmadapter->otp_region)
+ break;
+
+ ret = pcb->moal_malloc(pmadapter->pmoal_handle,
+ sizeof(otp_region_info_t),
+ MLAN_MEM_DEF,
+ (t_u8 **)&pmadapter->otp_region);
+ if (ret != MLAN_STATUS_SUCCESS ||
+ !pmadapter->otp_region) {
+ PRINTM(MERROR,
+ "Memory allocation for the otp region info struct failed!\n");
+ break;
+ }
+ /* Save region info values from OTP in the otp_region
+ * structure
+ */
+ memcpy_ext(pmadapter, pmadapter->otp_region, data,
+ sizeof(otp_region_info_t),
+ sizeof(otp_region_info_t));
+ data += sizeof(otp_region_info_t);
+ /* Get pre-defined cfp tables corresponding to the
+ * region code in OTP
+ */
+ for (i = 0; i < MLAN_CFP_TABLE_SIZE_BG; i++) {
+ if (cfp_table_BG[i].code ==
+ pmadapter->otp_region->region_code) {
+ max_tx_pwr_bg = (cfp_table_BG[i].cfp)
+ ->max_tx_power;
+ break;
+ }
+ }
+ for (i = 0; i < MLAN_CFP_TABLE_SIZE_A; i++) {
+ if (cfp_table_A[i].code ==
+ pmadapter->otp_region->region_code) {
+ max_tx_pwr_a = (cfp_table_A[i].cfp)
+ ->max_tx_power;
+ break;
+ }
+ }
+ /* Update the region code and the country code in
+ * pmadapter
+ */
+ pmadapter->region_code =
+ pmadapter->otp_region->region_code;
+ pmadapter->country_code[0] =
+ pmadapter->otp_region->country_code[0];
+ pmadapter->country_code[1] =
+ pmadapter->otp_region->country_code[1];
+ pmadapter->country_code[2] = '\0';
+ pmadapter->domain_reg.country_code[0] =
+ pmadapter->otp_region->country_code[0];
+ pmadapter->domain_reg.country_code[1] =
+ pmadapter->otp_region->country_code[1];
+ pmadapter->domain_reg.country_code[2] = '\0';
+ pmadapter->cfp_code_bg =
+ pmadapter->otp_region->region_code;
+ pmadapter->cfp_code_a =
+ pmadapter->otp_region->region_code;
+ break;
+ case TLV_TYPE_CHAN_ATTR_CFG:
+ /* Skip adding fw cfp tables if they already exist or
+ * if this TLV has no set data
+ */
+ if (*data == 0)
+ break;
+ if (pmadapter->cfp_otp_bg || pmadapter->cfp_otp_a) {
+ break;
+ }
+
+ ret = pcb->moal_malloc(
+ pmadapter->pmoal_handle,
+ pmadapter->tx_power_table_bg_rows *
+ sizeof(chan_freq_power_t),
+ MLAN_MEM_DEF, (t_u8 **)&pmadapter->cfp_otp_bg);
+ if (ret != MLAN_STATUS_SUCCESS ||
+ !pmadapter->cfp_otp_bg) {
+ PRINTM(MERROR,
+ "Memory allocation for storing otp bg table data failed!\n");
+ break;
+ }
+ /* Save channel usability flags from OTP data in the fw
+ * cfp bg table and set frequency and max_tx_power
+ * values
+ */
+ for (i = 0; i < pmadapter->tx_power_table_bg_rows;
+ i++) {
+ (pmadapter->cfp_otp_bg + i)->channel = *data;
+ if (*data == 14)
+ (pmadapter->cfp_otp_bg + i)->freq =
+ 2484;
+ else
+ (pmadapter->cfp_otp_bg + i)->freq =
+ 2412 + 5 * (*data - 1);
+ (pmadapter->cfp_otp_bg + i)->max_tx_power =
+ max_tx_pwr_bg;
+ data++;
+ (pmadapter->cfp_otp_bg + i)->dynamic.flags =
+ *data;
+ if (*data & NXP_CHANNEL_DFS)
+ (pmadapter->cfp_otp_bg + i)
+ ->passive_scan_or_radar_detect =
+ MTRUE;
+ data++;
+ }
+ ret = pcb->moal_malloc(
+ pmadapter->pmoal_handle,
+ pmadapter->tx_power_table_a_rows *
+ sizeof(chan_freq_power_t),
+ MLAN_MEM_DEF, (t_u8 **)&pmadapter->cfp_otp_a);
+ if (ret != MLAN_STATUS_SUCCESS ||
+ !pmadapter->cfp_otp_a) {
+ PRINTM(MERROR,
+ "Memory allocation for storing otp a table data failed!\n");
+ break;
+ }
+ /* Save channel usability flags from OTP data in the fw
+ * cfp a table and set frequency and max_tx_power values
+ */
+ for (i = 0; i < pmadapter->tx_power_table_a_rows; i++) {
+ (pmadapter->cfp_otp_a + i)->channel = *data;
+ if (*data < 183)
+ /* 5GHz channels */
+ (pmadapter->cfp_otp_a + i)->freq =
+ 5035 + 5 * (*data - 7);
+ else
+ /* 4GHz channels */
+ (pmadapter->cfp_otp_a + i)->freq =
+ 4915 + 5 * (*data - 183);
+ (pmadapter->cfp_otp_a + i)->max_tx_power =
+ max_tx_pwr_a;
+ data++;
+ (pmadapter->cfp_otp_a + i)->dynamic.flags =
+ *data;
+ if (*data & NXP_CHANNEL_DFS)
+ (pmadapter->cfp_otp_a + i)
+ ->passive_scan_or_radar_detect =
+ MTRUE;
+ data++;
+ }
+ break;
+ case TLV_TYPE_POWER_TABLE:
+ /* Skip adding fw power tables if this TLV has no data
+ * or if they already exists but force reg rule is set
+ * in the otp
+ */
+ if (*data == 0)
+ break;
+ if (pmadapter->otp_region &&
+ pmadapter->otp_region->force_reg &&
+ pmadapter->tx_power_table_bg)
+ break;
+
+ /* Save the tlv data in power tables for band BG and A
+ */
+ tmp = data;
+ i = 0;
+ while ((i <
+ pmadapter->tx_power_table_bg_rows *
+ pmadapter->tx_power_table_bg_cols) &&
+ (i < tlv_buf_len) && (*tmp != 36)) {
+ i++;
+ tmp++;
+ }
+ if (!pmadapter->tx_power_table_bg) {
+ ret = pcb->moal_malloc(
+ pmadapter->pmoal_handle, i,
+ MLAN_MEM_DEF,
+ (t_u8 **)&pmadapter->tx_power_table_bg);
+ if (ret != MLAN_STATUS_SUCCESS ||
+ !pmadapter->tx_power_table_bg) {
+ PRINTM(MERROR,
+ "Memory allocation for the BG-band power table failed!\n");
+ break;
+ }
+ }
+ memcpy_ext(pmadapter, pmadapter->tx_power_table_bg,
+ data, i, i);
+ pmadapter->tx_power_table_bg_size = i;
+ data += i;
+ i = 0;
+ while ((i < pmadapter->tx_power_table_a_rows *
+ pmadapter->tx_power_table_a_cols) &&
+ (i < (tlv_buf_len -
+ pmadapter->tx_power_table_bg_size))) {
+ i++;
+ }
+ if (!pmadapter->tx_power_table_a) {
+ ret = pcb->moal_malloc(
+ pmadapter->pmoal_handle, i,
+ MLAN_MEM_DEF,
+ (t_u8 **)&pmadapter->tx_power_table_a);
+ if (ret != MLAN_STATUS_SUCCESS ||
+ !pmadapter->tx_power_table_a) {
+ PRINTM(MERROR,
+ "Memory allocation for the A-band power table failed!\n");
+ break;
+ }
+ }
+ memcpy_ext(pmadapter, pmadapter->tx_power_table_a, data,
+ i, i);
+ pmadapter->tx_power_table_a_size = i;
+ break;
+ case TLV_TYPE_POWER_TABLE_ATTR:
+ pmadapter->tx_power_table_bg_rows =
+ ((power_table_attr_t *)data)->rows_2g;
+ pmadapter->tx_power_table_bg_cols =
+ ((power_table_attr_t *)data)->cols_2g;
+ pmadapter->tx_power_table_a_rows =
+ ((power_table_attr_t *)data)->rows_5g;
+ pmadapter->tx_power_table_a_cols =
+ ((power_table_attr_t *)data)->cols_5g;
+ break;
+ default:
+ break;
+ }
+ tlv_buf += (sizeof(*head) + tlv_buf_len);
+ tlv_buf_left -= (sizeof(*head) + tlv_buf_len);
+ }
+ if (!pmadapter->cfp_otp_bg || !pmadapter->tx_power_table_bg)
+ goto out;
+ /* Set remaining flags for BG */
+ rows = pmadapter->tx_power_table_bg_rows;
+ cols = pmadapter->tx_power_table_bg_cols;
+
+ for (i = 0; i < rows; i++) {
+ k = (i * cols) + 1;
+ if ((pmadapter->cfp_otp_bg + i)->dynamic.flags &
+ NXP_CHANNEL_DISABLED)
+ continue;
+
+ if (pmadapter->tx_power_table_bg[k + MOD_CCK] == 0)
+ (pmadapter->cfp_otp_bg + i)->dynamic.flags |=
+ NXP_CHANNEL_NO_CCK;
+
+ if (pmadapter->tx_power_table_bg[k + MOD_OFDM_PSK] == 0 &&
+ pmadapter->tx_power_table_bg[k + MOD_OFDM_QAM16] == 0 &&
+ pmadapter->tx_power_table_bg[k + MOD_OFDM_QAM64] == 0) {
+ (pmadapter->cfp_otp_bg + i)->dynamic.flags |=
+ NXP_CHANNEL_NO_OFDM;
+ }
+ }
+
+out:
+ LEAVE();
+}
+
+/**
+ * @brief This function deallocates otp cfp and power tables memory.
+ *
+ * @param pmadapter A pointer to mlan_adapter structure
+ */
+void wlan_free_fw_cfp_tables(mlan_adapter *pmadapter)
+{
+ pmlan_callbacks pcb;
+
+ ENTER();
+
+ pcb = &pmadapter->callbacks;
+ if (pmadapter->otp_region)
+ pcb->moal_mfree(pmadapter->pmoal_handle,
+ (t_u8 *)pmadapter->otp_region);
+ if (pmadapter->cfp_otp_bg)
+ pcb->moal_mfree(pmadapter->pmoal_handle,
+ (t_u8 *)pmadapter->cfp_otp_bg);
+ if (pmadapter->tx_power_table_bg)
+ pcb->moal_mfree(pmadapter->pmoal_handle,
+ (t_u8 *)pmadapter->tx_power_table_bg);
+ pmadapter->otp_region = MNULL;
+ pmadapter->cfp_otp_bg = MNULL;
+ pmadapter->tx_power_table_bg = MNULL;
+ pmadapter->tx_power_table_bg_size = 0;
+ if (pmadapter->cfp_otp_a)
+ pcb->moal_mfree(pmadapter->pmoal_handle,
+ (t_u8 *)pmadapter->cfp_otp_a);
+ if (pmadapter->tx_power_table_a)
+ pcb->moal_mfree(pmadapter->pmoal_handle,
+ (t_u8 *)pmadapter->tx_power_table_a);
+ pmadapter->cfp_otp_a = MNULL;
+ pmadapter->tx_power_table_a = MNULL;
+ pmadapter->tx_power_table_a_size = 0;
+ LEAVE();
+}
+
+/**
+ * @brief Get DFS chan list
+ *
+ * @param pmadapter Pointer to mlan_adapter
+ * @param pioctl_req Pointer to mlan_ioctl_req
+ *
+ * @return MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ */
+mlan_status wlan_get_cfp_table(pmlan_adapter pmadapter,
+ pmlan_ioctl_req pioctl_req)
+{
+ mlan_ds_misc_cfg *ds_misc_cfg = MNULL;
+ mlan_status ret = MLAN_STATUS_FAILURE;
+ chan_freq_power_t *cfp = MNULL;
+ t_u32 cfp_no = 0;
+
+ ENTER();
+ if (pioctl_req) {
+ ds_misc_cfg = (mlan_ds_misc_cfg *)pioctl_req->pbuf;
+ if (pioctl_req->action == MLAN_ACT_GET) {
+ cfp = wlan_get_region_cfp_table(
+ pmadapter, pmadapter->region_code,
+ ds_misc_cfg->param.cfp.band, &cfp_no);
+ if (cfp) {
+ ds_misc_cfg->param.cfp.num_chan = cfp_no;
+ memcpy_ext(pmadapter,
+ ds_misc_cfg->param.cfp.cfp_tbl, cfp,
+ cfp_no * sizeof(chan_freq_power_t),
+ cfp_no * sizeof(chan_freq_power_t));
+ }
+ ret = MLAN_STATUS_SUCCESS;
+ }
+ }
+ LEAVE();
+ return ret;
+}
+
+/**
+ * @brief Get power tables and cfp tables for set region code
+ * into the IOCTL request buffer
+ *
+ * @param pmadapter Private mlan adapter structure
+ * @param pioctl_req Pointer to the IOCTL request structure
+ *
+ * @return success, otherwise fail
+ *
+ */
+mlan_status wlan_get_cfpinfo(pmlan_adapter pmadapter,
+ pmlan_ioctl_req pioctl_req)
+{
+ chan_freq_power_t *cfp_bg = MNULL;
+ t_u32 cfp_no_bg = 0;
+ chan_freq_power_t *cfp_a = MNULL;
+ t_u32 cfp_no_a = 0;
+ t_u8 cfp_code_a = pmadapter->region_code;
+ t_u8 cfp_code_bg = pmadapter->region_code;
+ t_u32 len = 0, size = 0;
+ t_u8 *req_buf, *tmp;
+ mlan_status ret = MLAN_STATUS_SUCCESS;
+
+ ENTER();
+
+ if (!pioctl_req || !pioctl_req->pbuf) {
+ PRINTM(MERROR, "MLAN IOCTL information is not present!\n");
+ ret = MLAN_STATUS_FAILURE;
+ goto out;
+ }
+ /* Calculate the total response size required to return region,
+ * country codes, cfp tables and power tables
+ */
+ size = sizeof(pmadapter->country_code) + sizeof(pmadapter->region_code);
+ /* Add size to store region, country and environment codes */
+ size += sizeof(t_u32);
+ if (pmadapter->cfp_code_bg)
+ cfp_code_bg = pmadapter->cfp_code_bg;
+
+ /* Get cfp table and its size corresponding to the region code */
+ cfp_bg = wlan_get_region_cfp_table(pmadapter, cfp_code_bg,
+ BAND_G | BAND_B, &cfp_no_bg);
+ size += cfp_no_bg * sizeof(chan_freq_power_t);
+ if (pmadapter->cfp_code_a)
+ cfp_code_a = pmadapter->cfp_code_a;
+ cfp_a = wlan_get_region_cfp_table(pmadapter, cfp_code_a, BAND_A,
+ &cfp_no_a);
+ size += cfp_no_a * sizeof(chan_freq_power_t);
+ if (pmadapter->otp_region)
+ size += sizeof(pmadapter->otp_region->environment);
+
+ /* Get power table size */
+ if (pmadapter->tx_power_table_bg) {
+ size += pmadapter->tx_power_table_bg_size;
+ /* Add size to store table size, rows and cols */
+ size += 3 * sizeof(t_u32);
+ }
+ if (pmadapter->tx_power_table_a) {
+ size += pmadapter->tx_power_table_a_size;
+ size += 3 * sizeof(t_u32);
+ }
+ /* Check information buffer length of MLAN IOCTL */
+ if (pioctl_req->buf_len < size) {
+ PRINTM(MWARN,
+ "MLAN IOCTL information buffer length is too short.\n");
+ pioctl_req->buf_len_needed = size;
+ pioctl_req->status_code = MLAN_ERROR_INVALID_PARAMETER;
+ ret = MLAN_STATUS_RESOURCE;
+ goto out;
+ }
+ /* Copy the total size of region code, country code and environment
+ * in first four bytes of the IOCTL request buffer and then copy
+ * codes respectively in following bytes
+ */
+ req_buf = (t_u8 *)pioctl_req->pbuf;
+ size = sizeof(pmadapter->country_code) + sizeof(pmadapter->region_code);
+ if (pmadapter->otp_region)
+ size += sizeof(pmadapter->otp_region->environment);
+ tmp = (t_u8 *)&size;
+ memcpy_ext(pmadapter, req_buf, tmp, sizeof(size), sizeof(size));
+ len += sizeof(size);
+ memcpy_ext(pmadapter, req_buf + len, &pmadapter->region_code,
+ sizeof(pmadapter->region_code),
+ sizeof(pmadapter->region_code));
+ len += sizeof(pmadapter->region_code);
+ memcpy_ext(pmadapter, req_buf + len, &pmadapter->country_code,
+ sizeof(pmadapter->country_code),
+ sizeof(pmadapter->country_code));
+ len += sizeof(pmadapter->country_code);
+ if (pmadapter->otp_region) {
+ memcpy_ext(pmadapter, req_buf + len,
+ &pmadapter->otp_region->environment,
+ sizeof(pmadapter->otp_region->environment),
+ sizeof(pmadapter->otp_region->environment));
+ len += sizeof(pmadapter->otp_region->environment);
+ }
+ /* copy the cfp table size followed by the entire table */
+ if (!cfp_bg)
+ goto out;
+ size = cfp_no_bg * sizeof(chan_freq_power_t);
+ memcpy_ext(pmadapter, req_buf + len, tmp, sizeof(size), sizeof(size));
+ len += sizeof(size);
+ memcpy_ext(pmadapter, req_buf + len, cfp_bg, size, size);
+ len += size;
+ if (!cfp_a)
+ goto out;
+ size = cfp_no_a * sizeof(chan_freq_power_t);
+ memcpy_ext(pmadapter, req_buf + len, tmp, sizeof(size), sizeof(size));
+ len += sizeof(size);
+ memcpy_ext(pmadapter, req_buf + len, cfp_a, size, size);
+ len += size;
+ /* Copy the size of the power table, number of rows, number of cols
+ * and the entire power table
+ */
+ if (!pmadapter->tx_power_table_bg)
+ goto out;
+ size = pmadapter->tx_power_table_bg_size;
+ memcpy_ext(pmadapter, req_buf + len, tmp, sizeof(size), sizeof(size));
+ len += sizeof(size);
+
+ /* No. of rows */
+ size = pmadapter->tx_power_table_bg_rows;
+ memcpy_ext(pmadapter, req_buf + len, tmp, sizeof(size), sizeof(size));
+ len += sizeof(size);
+
+ /* No. of cols */
+ size = pmadapter->tx_power_table_bg_size /
+ pmadapter->tx_power_table_bg_rows;
+ memcpy_ext(pmadapter, req_buf + len, tmp, sizeof(size), sizeof(size));
+ len += sizeof(size);
+ memcpy_ext(pmadapter, req_buf + len, pmadapter->tx_power_table_bg,
+ pmadapter->tx_power_table_bg_size,
+ pmadapter->tx_power_table_bg_size);
+ len += pmadapter->tx_power_table_bg_size;
+ if (!pmadapter->tx_power_table_a)
+ goto out;
+ size = pmadapter->tx_power_table_a_size;
+ memcpy_ext(pmadapter, req_buf + len, tmp, sizeof(size), sizeof(size));
+ len += sizeof(size);
+
+ /* No. of rows */
+ size = pmadapter->tx_power_table_a_rows;
+ memcpy_ext(pmadapter, req_buf + len, tmp, sizeof(size), sizeof(size));
+ len += sizeof(size);
+
+ /* No. of cols */
+ size = pmadapter->tx_power_table_a_size /
+ pmadapter->tx_power_table_a_rows;
+ memcpy_ext(pmadapter, req_buf + len, tmp, sizeof(size), sizeof(size));
+ len += sizeof(size);
+ memcpy_ext(pmadapter, req_buf + len, pmadapter->tx_power_table_a,
+ pmadapter->tx_power_table_a_size,
+ pmadapter->tx_power_table_a_size);
+ len += pmadapter->tx_power_table_a_size;
+out:
+ if (pioctl_req)
+ pioctl_req->data_read_written = len;
+
+ LEAVE();
+ return ret;
+}
diff --git a/drivers/net/wireless/nxp/mxm_wifiex/wlan_src/mlan/mlan_cmdevt.c b/drivers/net/wireless/nxp/mxm_wifiex/wlan_src/mlan/mlan_cmdevt.c
new file mode 100644
index 000000000000..6393ae6045f7
--- /dev/null
+++ b/drivers/net/wireless/nxp/mxm_wifiex/wlan_src/mlan/mlan_cmdevt.c
@@ -0,0 +1,8377 @@
+/**
+ * @file mlan_cmdevt.c
+ *
+ * @brief This file contains the handling of CMD/EVENT in MLAN
+ *
+ *
+ * Copyright 2014-2020 NXP
+ *
+ * This software file (the File) is distributed by NXP
+ * under the terms of the GNU General Public License Version 2, June 1991
+ * (the License). You may use, redistribute and/or modify the 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.
+ *
+ */
+
+/*************************************************************
+Change Log:
+ 05/12/2009: initial version
+************************************************************/
+#include "mlan.h"
+#ifdef STA_SUPPORT
+#include "mlan_join.h"
+#endif
+#include "mlan_util.h"
+#include "mlan_fw.h"
+#include "mlan_main.h"
+#include "mlan_wmm.h"
+#include "mlan_11n.h"
+#include "mlan_11ac.h"
+#include "mlan_11ax.h"
+#include "mlan_11h.h"
+#ifdef SDIO
+#include "mlan_sdio.h"
+#endif /* SDIO */
+#ifdef PCIE
+#include "mlan_pcie.h"
+#endif /* PCIE */
+#include "mlan_init.h"
+
+/********************************************************
+ Local Variables
+********************************************************/
+
+/*******************************************************
+ Global Variables
+********************************************************/
+
+/********************************************************
+ Local Functions
+********************************************************/
+#ifdef STA_SUPPORT
+/**
+ * @brief This function inserts scan command node to scan_pending_q.
+ *
+ * @param pmpriv A pointer to mlan_private structure
+ * @param pcmd_node A pointer to cmd_ctrl_node structure
+ * @return N/A
+ */
+static t_void wlan_queue_scan_cmd(mlan_private *pmpriv,
+ cmd_ctrl_node *pcmd_node)
+{
+ mlan_adapter *pmadapter = pmpriv->adapter;
+
+ ENTER();
+
+ if (pcmd_node == MNULL)
+ goto done;
+ pcmd_node->cmd_flag |= CMD_F_SCAN;
+
+ util_enqueue_list_tail(pmadapter->pmoal_handle,
+ &pmadapter->scan_pending_q,
+ (pmlan_linked_list)pcmd_node, MNULL, MNULL);
+
+done:
+ LEAVE();
+}
+
+/**
+ * @brief Internal function used to flush the scan pending queue
+ *
+ * @param pmadapter A pointer to mlan_adapter structure
+ *
+ * @return N/A
+ */
+void wlan_check_scan_queue(pmlan_adapter pmadapter)
+{
+ cmd_ctrl_node *pcmd_node = MNULL;
+ t_u16 num = 0;
+
+ pcmd_node = (cmd_ctrl_node *)util_peek_list(pmadapter->pmoal_handle,
+ &pmadapter->scan_pending_q,
+ MNULL, MNULL);
+ if (!pcmd_node) {
+ PRINTM(MERROR, "No pending scan command\n");
+ return;
+ }
+ while (pcmd_node != (cmd_ctrl_node *)&pmadapter->scan_pending_q) {
+ num++;
+ pcmd_node = pcmd_node->pnext;
+ }
+ PRINTM(MERROR, "num_pending_scan=%d\n", num);
+}
+#endif
+
+/**
+ * @brief This function will dump the pending commands id
+ *
+ * @param pmadapter A pointer to mlan_adapter
+ *
+ * @return N/A
+ */
+static void wlan_dump_pending_commands(pmlan_adapter pmadapter)
+{
+ cmd_ctrl_node *pcmd_node = MNULL;
+ HostCmd_DS_COMMAND *pcmd;
+
+ ENTER();
+ wlan_request_cmd_lock(pmadapter);
+ pcmd_node = (cmd_ctrl_node *)util_peek_list(pmadapter->pmoal_handle,
+ &pmadapter->cmd_pending_q,
+ MNULL, MNULL);
+ if (!pcmd_node) {
+ wlan_release_cmd_lock(pmadapter);
+ LEAVE();
+ return;
+ }
+ while (pcmd_node != (cmd_ctrl_node *)&pmadapter->cmd_pending_q) {
+ pcmd = (HostCmd_DS_COMMAND *)(pcmd_node->cmdbuf->pbuf +
+ pcmd_node->cmdbuf->data_offset);
+ PRINTM(MERROR, "pending command id: 0x%x ioctl_buf=%p\n",
+ wlan_le16_to_cpu(pcmd->command), pcmd_node->pioctl_buf);
+ pcmd_node = pcmd_node->pnext;
+ }
+#ifdef STA_SUPPORT
+ wlan_check_scan_queue(pmadapter);
+#endif
+ wlan_release_cmd_lock(pmadapter);
+ LEAVE();
+ return;
+}
+
+#define REASON_CODE_NO_CMD_NODE 1
+#define REASON_CODE_CMD_TIMEOUT 2
+#define REASON_CODE_CMD_TO_CARD_FAILURE 3
+#define REASON_CODE_EXT_SCAN_TIMEOUT 4
+/**
+ * @brief This function dump debug info
+ *
+ * @return N/A
+ */
+t_void wlan_dump_info(mlan_adapter *pmadapter, t_u8 reason)
+{
+ cmd_ctrl_node *pcmd_node = MNULL;
+#ifdef DEBUG_LEVEL1
+ t_u32 sec = 0, usec = 0;
+#endif
+ t_u8 i;
+#ifdef SDIO
+ t_u8 j;
+ t_u8 mp_aggr_pkt_limit = SDIO_MP_AGGR_DEF_PKT_LIMIT;
+#endif
+ t_u16 cmd_id, cmd_act;
+ mlan_private *pmpriv = MNULL;
+
+ ENTER();
+
+ PRINTM(MERROR, "------------Dump info-----------\n", reason);
+ switch (reason) {
+ case REASON_CODE_NO_CMD_NODE:
+ pmadapter->dbg.num_no_cmd_node++;
+ PRINTM(MERROR, "No Free command node\n");
+ break;
+ case REASON_CODE_CMD_TIMEOUT:
+ PRINTM(MERROR, "Commmand Timeout\n");
+ break;
+ case REASON_CODE_CMD_TO_CARD_FAILURE:
+ PRINTM(MERROR, "Command to card failure\n");
+ break;
+ case REASON_CODE_EXT_SCAN_TIMEOUT:
+ PRINTM(MERROR, "EXT_SCAN_STATUS event Timeout\n");
+ break;
+ default:
+ break;
+ }
+ if ((reason == REASON_CODE_NO_CMD_NODE) &&
+ (pmadapter->dbg.num_no_cmd_node > 1)) {
+ if (pmadapter->dbg.num_no_cmd_node >= 5)
+ wlan_recv_event(wlan_get_priv(pmadapter,
+ MLAN_BSS_ROLE_ANY),
+ MLAN_EVENT_ID_DRV_DBG_DUMP, MNULL);
+ LEAVE();
+ return;
+ }
+ wlan_dump_pending_commands(pmadapter);
+ if (reason != REASON_CODE_CMD_TIMEOUT) {
+ if (!pmadapter->curr_cmd) {
+ PRINTM(MERROR, "CurCmd Empty\n");
+ } else {
+ pcmd_node = pmadapter->curr_cmd;
+ cmd_id = pmadapter->dbg.last_cmd_id
+ [pmadapter->dbg.last_cmd_index];
+ cmd_act = pmadapter->dbg.last_cmd_act
+ [pmadapter->dbg.last_cmd_index];
+ PRINTM_GET_SYS_TIME(MERROR, &sec, &usec);
+ PRINTM(MERROR,
+ "Current cmd id (%lu.%06lu) = 0x%x, act = 0x%x\n",
+ sec, usec, cmd_id, cmd_act);
+#if defined(SDIO) || defined(PCIE)
+ if (!IS_USB(pmadapter->card_type) &&
+ pcmd_node->cmdbuf) {
+ t_u8 *pcmd_buf;
+ pcmd_buf = pcmd_node->cmdbuf->pbuf +
+ pcmd_node->cmdbuf->data_offset +
+ pmadapter->ops.intf_header_len;
+ for (i = 0; i < 16; i++)
+ PRINTM(MERROR, "%02x ", *pcmd_buf++);
+ PRINTM(MERROR, "\n");
+ }
+#endif
+ pmpriv = pcmd_node->priv;
+ if (pmpriv)
+ PRINTM(MERROR, "BSS type = %d BSS role= %d\n",
+ pmpriv->bss_type, pmpriv->bss_role);
+ }
+ }
+ PRINTM(MERROR, "mlan_processing =%d\n", pmadapter->mlan_processing);
+ PRINTM(MERROR, "main_lock_flag =%d\n", pmadapter->main_lock_flag);
+ PRINTM(MERROR, "main_process_cnt =%d\n", pmadapter->main_process_cnt);
+ PRINTM(MERROR, "delay_task_flag =%d\n", pmadapter->delay_task_flag);
+ PRINTM(MERROR, "mlan_rx_processing =%d\n",
+ pmadapter->mlan_rx_processing);
+ PRINTM(MERROR, "rx_pkts_queued=%d\n", pmadapter->rx_pkts_queued);
+ PRINTM(MERROR, "more_task_flag = %d\n", pmadapter->more_task_flag);
+ PRINTM(MERROR, "num_cmd_timeout = %d\n", pmadapter->num_cmd_timeout);
+ PRINTM(MERROR, "last_cmd_index = %d\n", pmadapter->dbg.last_cmd_index);
+ PRINTM(MERROR, "last_cmd_id = ");
+ for (i = 0; i < DBG_CMD_NUM; i++)
+ PRINTM(MERROR, "0x%x ", pmadapter->dbg.last_cmd_id[i]);
+ PRINTM(MERROR, "\n");
+ PRINTM(MERROR, "last_cmd_act = ");
+ for (i = 0; i < DBG_CMD_NUM; i++)
+ PRINTM(MERROR, "0x%x ", pmadapter->dbg.last_cmd_act[i]);
+ PRINTM(MERROR, "\n");
+ PRINTM(MERROR, "last_cmd_resp_index = %d\n",
+ pmadapter->dbg.last_cmd_resp_index);
+ PRINTM(MERROR, "last_cmd_resp_id = ");
+ for (i = 0; i < DBG_CMD_NUM; i++)
+ PRINTM(MERROR, "0x%x ", pmadapter->dbg.last_cmd_resp_id[i]);
+ PRINTM(MERROR, "\n");
+ PRINTM(MERROR, "last_event_index = %d\n",
+ pmadapter->dbg.last_event_index);
+ PRINTM(MERROR, "last_event = ");
+ for (i = 0; i < DBG_CMD_NUM; i++)
+ PRINTM(MERROR, "0x%x ", pmadapter->dbg.last_event[i]);
+ PRINTM(MERROR, "\n");
+
+ PRINTM(MERROR, "num_data_h2c_failure = %d\n",
+ pmadapter->dbg.num_tx_host_to_card_failure);
+ PRINTM(MERROR, "num_cmd_h2c_failure = %d\n",
+ pmadapter->dbg.num_cmd_host_to_card_failure);
+#ifdef SDIO
+ if (IS_SD(pmadapter->card_type)) {
+ PRINTM(MERROR, "num_data_c2h_failure = %d\n",
+ pmadapter->dbg.num_rx_card_to_host_failure);
+ PRINTM(MERROR, "num_cmdevt_c2h_failure = %d\n",
+ pmadapter->dbg.num_cmdevt_card_to_host_failure);
+ PRINTM(MERROR, "num_int_read_failure = %d\n",
+ pmadapter->dbg.num_int_read_failure);
+ PRINTM(MERROR, "last_int_status = %d\n",
+ pmadapter->dbg.last_int_status);
+ }
+#endif
+ PRINTM(MERROR, "num_alloc_buffer_failure = %d\n",
+ pmadapter->dbg.num_alloc_buffer_failure);
+ PRINTM(MERROR, "num_pkt_dropped = %d\n",
+ pmadapter->dbg.num_pkt_dropped);
+ PRINTM(MERROR, "num_no_cmd_node = %d\n",
+ pmadapter->dbg.num_no_cmd_node);
+ PRINTM(MERROR, "num_event_deauth = %d\n",
+ pmadapter->dbg.num_event_deauth);
+ PRINTM(MERROR, "num_event_disassoc = %d\n",
+ pmadapter->dbg.num_event_disassoc);
+ PRINTM(MERROR, "num_event_link_lost = %d\n",
+ pmadapter->dbg.num_event_link_lost);
+ PRINTM(MERROR, "num_cmd_deauth = %d\n", pmadapter->dbg.num_cmd_deauth);
+ PRINTM(MERROR, "num_cmd_assoc_success = %d\n",
+ pmadapter->dbg.num_cmd_assoc_success);
+ PRINTM(MERROR, "num_cmd_assoc_failure = %d\n",
+ pmadapter->dbg.num_cmd_assoc_failure);
+ PRINTM(MERROR, "num_cons_assoc_failure = %d\n",
+ pmadapter->dbg.num_cons_assoc_failure);
+ PRINTM(MERROR, "cmd_resp_received=%d\n", pmadapter->cmd_resp_received);
+ PRINTM(MERROR, "event_received=%d\n", pmadapter->event_received);
+
+ PRINTM(MERROR, "max_tx_buf_size=%d\n", pmadapter->max_tx_buf_size);
+ PRINTM(MERROR, "tx_buf_size=%d\n", pmadapter->tx_buf_size);
+ PRINTM(MERROR, "curr_tx_buf_size=%d\n", pmadapter->curr_tx_buf_size);
+
+ PRINTM(MERROR, "data_sent=%d cmd_sent=%d\n", pmadapter->data_sent,
+ pmadapter->cmd_sent);
+
+ PRINTM(MERROR, "ps_mode=%d ps_state=%d\n", pmadapter->ps_mode,
+ pmadapter->ps_state);
+ PRINTM(MERROR, "wakeup_dev_req=%d wakeup_tries=%d wakeup_timeout=%d\n",
+ pmadapter->pm_wakeup_card_req, pmadapter->pm_wakeup_fw_try,
+ pmadapter->pm_wakeup_timeout);
+ PRINTM(MERROR, "hs_configured=%d hs_activated=%d\n",
+ pmadapter->is_hs_configured, pmadapter->hs_activated);
+ PRINTM(MERROR, "pps_uapsd_mode=%d sleep_pd=%d\n",
+ pmadapter->pps_uapsd_mode, pmadapter->sleep_period.period);
+ PRINTM(MERROR, "tx_lock_flag = %d\n", pmadapter->tx_lock_flag);
+ PRINTM(MERROR, "scan_processing = %d\n", pmadapter->scan_processing);
+#ifdef SDIO
+ if (IS_SD(pmadapter->card_type)) {
+ PRINTM(MERROR, "mp_rd_bitmap=0x%x curr_rd_port=0x%x\n",
+ pmadapter->pcard_sd->mp_rd_bitmap,
+ pmadapter->pcard_sd->curr_rd_port);
+ PRINTM(MERROR, "mp_wr_bitmap=0x%x curr_wr_port=0x%x\n",
+ pmadapter->pcard_sd->mp_wr_bitmap,
+ pmadapter->pcard_sd->curr_wr_port);
+ PRINTM(MERROR, "mp_invalid_update=%d\n",
+ pmadapter->pcard_sd->mp_invalid_update);
+ PRINTM(MERROR, "last_recv_wr_bitmap=0x%x last_mp_index=%d\n",
+ pmadapter->pcard_sd->last_recv_wr_bitmap,
+ pmadapter->pcard_sd->last_mp_index);
+ for (i = 0; i < SDIO_MP_DBG_NUM; i++) {
+ PRINTM(MERROR,
+ "mp_wr_bitmap: 0x%x mp_wr_ports=0x%x len=%d curr_wr_port=0x%x\n",
+ pmadapter->pcard_sd->last_mp_wr_bitmap[i],
+ pmadapter->pcard_sd->last_mp_wr_ports[i],
+ pmadapter->pcard_sd->last_mp_wr_len[i],
+ pmadapter->pcard_sd->last_curr_wr_port[i]);
+ for (j = 0; j < mp_aggr_pkt_limit; j++) {
+ PRINTM(MERROR, "0x%02x ",
+ pmadapter->pcard_sd->last_mp_wr_info
+ [i * mp_aggr_pkt_limit + j]);
+ }
+ PRINTM(MERROR, "\n");
+ }
+ }
+#endif
+#ifdef PCIE
+ if (IS_PCIE(pmadapter->card_type)) {
+ PRINTM(MERROR, "txbd_rdptr=0x%x txbd_wrptr=0x%x\n",
+ pmadapter->pcard_pcie->txbd_rdptr,
+ pmadapter->pcard_pcie->txbd_wrptr);
+ PRINTM(MERROR, "rxbd_rdptr=0x%x rxbd_wrptr=0x%x\n",
+ pmadapter->pcard_pcie->rxbd_rdptr,
+ pmadapter->pcard_pcie->rxbd_wrptr);
+ PRINTM(MERROR, "evtbd_rdptr=0x%x evt_wrptr=0x%x\n",
+ pmadapter->pcard_pcie->evtbd_rdptr,
+ pmadapter->pcard_pcie->evtbd_wrptr);
+ PRINTM(MERROR, "last_wr_index:%d\n",
+ pmadapter->pcard_pcie->txbd_wrptr &
+ (MLAN_MAX_TXRX_BD - 1));
+ PRINTM(MERROR, "Tx pkt size:\n");
+ for (i = 0; i < MLAN_MAX_TXRX_BD; i++) {
+ PRINTM(MERROR, "%04d ",
+ pmadapter->pcard_pcie->last_tx_pkt_size[i]);
+ if (((i + 1) % 16) == 0)
+ PRINTM(MERROR, "\n");
+ }
+ }
+#endif
+ for (i = 0; i < pmadapter->priv_num; ++i) {
+ if (pmadapter->priv[i])
+ wlan_dump_ralist(pmadapter->priv[i]);
+ }
+ if (reason != REASON_CODE_CMD_TIMEOUT) {
+ if ((pmadapter->dbg.num_no_cmd_node >= 5) ||
+ (pmadapter->pm_wakeup_card_req &&
+ pmadapter->pm_wakeup_fw_try) ||
+ (reason == REASON_CODE_EXT_SCAN_TIMEOUT)) {
+ if (pmpriv)
+ wlan_recv_event(pmpriv,
+ MLAN_EVENT_ID_DRV_DBG_DUMP,
+ MNULL);
+ else
+ wlan_recv_event(
+ wlan_get_priv(pmadapter,
+ MLAN_BSS_ROLE_ANY),
+ MLAN_EVENT_ID_DRV_DBG_DUMP, MNULL);
+ }
+ }
+ PRINTM(MERROR, "-------- Dump info End---------\n", reason);
+ LEAVE();
+ return;
+}
+
+/**
+ * @brief This function convert a given character to hex
+ *
+ * @param chr Character to be converted
+ *
+ * @return The converted hex if chr is a valid hex, else 0
+ */
+static t_u32 wlan_hexval(t_u8 chr)
+{
+ if (chr >= '0' && chr <= '9')
+ return chr - '0';
+ if (chr >= 'A' && chr <= 'F')
+ return chr - 'A' + 10;
+ if (chr >= 'a' && chr <= 'f')
+ return chr - 'a' + 10;
+
+ return 0;
+}
+
+/**
+ * @brief This function convert a given string to hex
+ *
+ * @param a A pointer to string to be converted
+ *
+ * @return The converted hex value if param a is a valid hex, else
+ * 0
+ */
+int wlan_atox(t_u8 *a)
+{
+ int i = 0;
+
+ ENTER();
+
+ while (wlan_isxdigit(*a))
+ i = i * 16 + wlan_hexval(*a++);
+
+ LEAVE();
+ return i;
+}
+
+/**
+ * @brief This function parse cal data from ASCII to hex
+ *
+ * @param src A pointer to source data
+ * @param len Source data length
+ * @param dst A pointer to a buf to store the parsed data
+ *
+ * @return The parsed hex data length
+ */
+static t_u32 wlan_parse_cal_cfg(t_u8 *src, t_size len, t_u8 *dst)
+{
+ t_u8 *ptr;
+ t_u8 *dptr;
+
+ ENTER();
+ ptr = src;
+ dptr = dst;
+
+ while (ptr - src < len) {
+ if (*ptr && (wlan_isspace(*ptr) || *ptr == '\t')) {
+ ptr++;
+ continue;
+ }
+
+ if (wlan_isxdigit(*ptr)) {
+ *dptr++ = wlan_atox(ptr);
+ ptr += 2;
+ } else {
+ ptr++;
+ }
+ }
+ LEAVE();
+ return dptr - dst;
+}
+
+/**
+ * @brief This function finds first occurrence of a char in a string
+ *
+ * @param s A pointer to the string to be searched
+ * @param c The character to search for
+ *
+ * @return Location of the first occurrence of the char
+ * if found, else NULL
+ */
+t_u8 *wlan_strchr(t_u8 *s, int c)
+{
+ t_u8 *pos = s;
+ while (*pos != '\0') {
+ if (*pos == (t_u8)c)
+ return pos;
+ pos++;
+ }
+ return MNULL;
+}
+
+#define CFG_TYPE_HOSTCMD 0
+#define CFG_TYPE_DPDFILE 1
+
+/**
+ * @brief WOAL parse ASCII format raw data to hex format
+ *
+ * @param pmpriv MOAL handle
+ * @param cfg_type Conf file type
+ * @param data Source data
+ * @param size data length
+ * @return MLAN_STATUS_SUCCESS--success, otherwise--fail
+ */
+static t_u32 wlan_process_hostcmd_cfg(pmlan_private pmpriv, t_u16 cfg_type,
+ t_u8 *data, t_size size)
+{
+ mlan_status ret = MLAN_STATUS_SUCCESS;
+ t_u8 *pos = data;
+ t_u8 *intf_s, *intf_e;
+ t_u8 *buf = MNULL;
+ t_u8 *ptr = MNULL;
+ t_u32 cmd_len = 0;
+ t_u8 start_raw = MFALSE;
+ mlan_ds_misc_cmd *hostcmd;
+ HostCmd_DS_GEN *pcmd = MNULL;
+ HostCmd_DS_802_11_CFG_DATA *pcfg_cmd = MNULL;
+ mlan_adapter *pmadapter = MNULL;
+ mlan_callbacks *pcb = MNULL;
+ t_u8 hostcmd_flag = MFALSE;
+
+ ENTER();
+ if (!pmpriv) {
+ PRINTM(MERROR, "pmpriv is NULL\n");
+ LEAVE();
+ return MLAN_STATUS_FAILURE;
+ }
+ pmadapter = pmpriv->adapter;
+ pcb = (mlan_callbacks *)&pmadapter->callbacks;
+ ret = pcb->moal_malloc(pmadapter->pmoal_handle,
+ sizeof(mlan_ds_misc_cmd), MLAN_MEM_DEF,
+ (t_u8 **)&hostcmd);
+ if (ret || !hostcmd) {
+ PRINTM(MERROR, "Could not allocate buffer space!\n");
+ LEAVE();
+ return ret;
+ }
+ buf = hostcmd->cmd;
+ ptr = buf;
+ while ((pos - data) < size) {
+ while (*pos == ' ' || *pos == '\t')
+ pos++;
+ if (*pos == '#') { /* Line comment */
+ while (*pos != '\n')
+ pos++;
+ pos++;
+ }
+ if ((*pos == '\r' && *(pos + 1) == '\n') || *pos == '\n' ||
+ *pos == '\0') {
+ pos++;
+ continue; /* Needn't process this line */
+ }
+
+ if (*pos == '}') {
+ if (cfg_type == CFG_TYPE_DPDFILE && pcmd) {
+ /* Fill command head for DPD RAW data conf */
+ hostcmd->len = ptr - buf;
+ pcmd->command =
+ wlan_cpu_to_le16(HostCmd_CMD_CFG_DATA);
+ pcmd->size = wlan_cpu_to_le16(hostcmd->len);
+ pcfg_cmd = (HostCmd_DS_802_11_CFG_DATA
+ *)((t_u8 *)pcmd + S_DS_GEN);
+ pcfg_cmd->action =
+ wlan_cpu_to_le16(HostCmd_ACT_GEN_SET);
+ pcfg_cmd->type = wlan_cpu_to_le16(OID_TYPE_DPD);
+ pcfg_cmd->data_len = wlan_cpu_to_le16(
+ hostcmd->len - S_DS_GEN -
+ sizeof(HostCmd_DS_802_11_CFG_DATA));
+ pcmd = MNULL;
+ pcfg_cmd = MNULL;
+ } else {
+ /* For hostcmd data conf */
+ cmd_len = *((t_u16 *)(buf + sizeof(t_u16)));
+ hostcmd->len = cmd_len;
+ }
+ ret = wlan_prepare_cmd(pmpriv, 0, 0, 0, MNULL,
+ (t_void *)hostcmd);
+ memset(pmadapter, buf, 0, MRVDRV_SIZE_OF_CMD_BUFFER);
+ ptr = buf;
+ start_raw = MFALSE;
+ pos++;
+ continue;
+ }
+
+ if (start_raw == MFALSE) {
+ intf_s = wlan_strchr(pos, '=');
+ if (intf_s) {
+ if (*(intf_s + 1) == '=')
+ hostcmd_flag = MTRUE;
+ intf_e = wlan_strchr(intf_s, '{');
+ } else
+ intf_e = MNULL;
+
+ if (intf_s && intf_e) {
+ start_raw = MTRUE;
+ pos = intf_e + 1;
+ /* Reserve command head for DPD RAW data conf */
+ if (cfg_type == CFG_TYPE_DPDFILE &&
+ !hostcmd_flag) {
+ pcmd = (HostCmd_DS_GEN *)ptr;
+ ptr += S_DS_GEN +
+ sizeof(HostCmd_DS_802_11_CFG_DATA);
+ }
+ continue;
+ }
+ }
+
+ if (start_raw) {
+ /* Raw data block exists */
+ while (*pos != '\n') {
+ if ((*pos <= 'f' && *pos >= 'a') ||
+ (*pos <= 'F' && *pos >= 'A') ||
+ (*pos <= '9' && *pos >= '0')) {
+ *ptr++ = wlan_atox(pos);
+ pos += 2;
+ } else
+ pos++;
+ }
+ }
+ }
+ pcb->moal_mfree(pmadapter->pmoal_handle, (t_u8 *)hostcmd);
+ LEAVE();
+ return ret;
+}
+
+/**
+ * @brief This function initializes the command node.
+ *
+ * @param pmpriv A pointer to mlan_private structure
+ * @param pcmd_node A pointer to cmd_ctrl_node structure
+ * @param cmd_no cmd id
+ * @param pioctl_buf A pointer to MLAN IOCTL Request buffer
+ * @param pdata_buf A pointer to information buffer
+ *
+ * @return N/A
+ */
+static void wlan_init_cmd_node(pmlan_private pmpriv, cmd_ctrl_node *pcmd_node,
+ t_u32 cmd_no, t_void *pioctl_buf,
+ t_void *pdata_buf)
+{
+ mlan_adapter *pmadapter = pmpriv->adapter;
+
+ ENTER();
+
+ if (pcmd_node == MNULL) {
+ LEAVE();
+ return;
+ }
+ pcmd_node->priv = pmpriv;
+ pcmd_node->cmd_no = cmd_no;
+ pcmd_node->pioctl_buf = pioctl_buf;
+ pcmd_node->pdata_buf = pdata_buf;
+
+#ifdef USB
+ if (IS_USB(pmadapter->card_type)) {
+ pcmd_node->cmdbuf =
+ wlan_alloc_mlan_buffer(pmadapter,
+ MRVDRV_SIZE_OF_CMD_BUFFER, 0,
+ MOAL_MALLOC_BUFFER);
+ if (!pcmd_node->cmdbuf) {
+ PRINTM(MERROR, "Failed to allocate cmd_buffer\n");
+ LEAVE();
+ return;
+ }
+ }
+#endif /* USB */
+#if defined(SDIO) || defined(PCIE)
+ if (!IS_USB(pmadapter->card_type))
+ pcmd_node->cmdbuf = pcmd_node->pmbuf;
+#endif
+
+ /* Make sure head_ptr for cmd buf is Align */
+ pcmd_node->cmdbuf->data_offset = 0;
+ memset(pmadapter, pcmd_node->cmdbuf->pbuf, 0,
+ MRVDRV_SIZE_OF_CMD_BUFFER);
+
+ /* Prepare mlan_buffer for command sending */
+ pcmd_node->cmdbuf->buf_type = MLAN_BUF_TYPE_CMD;
+#ifdef USB
+ if (IS_USB(pmadapter->card_type))
+ pcmd_node->cmdbuf->data_offset += MLAN_TYPE_LEN;
+#endif
+#if defined(SDIO) || defined(PCIE)
+ if (!IS_USB(pmadapter->card_type))
+ pcmd_node->cmdbuf->data_offset +=
+ pmadapter->ops.intf_header_len;
+#endif
+
+ LEAVE();
+}
+
+/**
+ * @brief This function gets a free command node if available in
+ * command free queue.
+ *
+ * @param pmadapter A pointer to mlan_adapter structure
+ *
+ * @return cmd_ctrl_node A pointer to cmd_ctrl_node structure or MNULL
+ */
+static cmd_ctrl_node *wlan_get_cmd_node(mlan_adapter *pmadapter)
+{
+ cmd_ctrl_node *pcmd_node;
+
+ ENTER();
+
+ if (pmadapter == MNULL) {
+ LEAVE();
+ return MNULL;
+ }
+ wlan_request_cmd_lock(pmadapter);
+ if (util_peek_list(pmadapter->pmoal_handle, &pmadapter->cmd_free_q,
+ MNULL, MNULL)) {
+ pcmd_node = (cmd_ctrl_node *)util_dequeue_list(
+ pmadapter->pmoal_handle, &pmadapter->cmd_free_q, MNULL,
+ MNULL);
+ } else {
+ PRINTM(MERROR,
+ "GET_CMD_NODE: cmd_ctrl_node is not available\n");
+ pcmd_node = MNULL;
+ }
+ wlan_release_cmd_lock(pmadapter);
+ LEAVE();
+ return pcmd_node;
+}
+
+/**
+ * @brief This function cleans command node.
+ *
+ * @param pmadapter A pointer to mlan_adapter structure
+ * @param pcmd_node A pointer to cmd_ctrl_node structure
+ *
+ * @return N/A
+ */
+static t_void wlan_clean_cmd_node(pmlan_adapter pmadapter,
+ cmd_ctrl_node *pcmd_node)
+{
+ ENTER();
+
+ if (pcmd_node == MNULL) {
+ LEAVE();
+ return;
+ }
+ pcmd_node->cmd_no = 0;
+ pcmd_node->cmd_flag = 0;
+ pcmd_node->pioctl_buf = MNULL;
+ pcmd_node->pdata_buf = MNULL;
+
+#ifdef USB
+ if (IS_USB(pmadapter->card_type) && pcmd_node->cmdbuf) {
+ wlan_free_mlan_buffer(pmadapter, pcmd_node->cmdbuf);
+ pcmd_node->cmdbuf = MNULL;
+ }
+#endif
+
+ if (pcmd_node->respbuf) {
+ pmadapter->ops.cmdrsp_complete(pmadapter, pcmd_node->respbuf,
+ MLAN_STATUS_SUCCESS);
+ pcmd_node->respbuf = MNULL;
+ }
+
+ LEAVE();
+ return;
+}
+
+#ifdef STA_SUPPORT
+/**
+ * @brief This function will return the pointer to the first entry in
+ * pending cmd which is scan command
+ *
+ * @param pmadapter A pointer to mlan_adapter
+ *
+ * @return A pointer to first entry match pioctl_req
+ */
+static cmd_ctrl_node *wlan_get_pending_scan_cmd(pmlan_adapter pmadapter)
+{
+ cmd_ctrl_node *pcmd_node = MNULL;
+
+ ENTER();
+
+ pcmd_node = (cmd_ctrl_node *)util_peek_list(pmadapter->pmoal_handle,
+ &pmadapter->cmd_pending_q,
+ MNULL, MNULL);
+ if (!pcmd_node) {
+ LEAVE();
+ return MNULL;
+ }
+ while (pcmd_node != (cmd_ctrl_node *)&pmadapter->cmd_pending_q) {
+ if (pcmd_node->cmd_flag & CMD_F_SCAN) {
+ LEAVE();
+ return pcmd_node;
+ }
+ pcmd_node = pcmd_node->pnext;
+ }
+ LEAVE();
+ return MNULL;
+}
+#endif
+
+/**
+ * @brief This function will return the pointer to the first entry in
+ * pending cmd which matches the given pioctl_req
+ *
+ * @param pmadapter A pointer to mlan_adapter
+ * @param pioctl_req A pointer to mlan_ioctl_req buf
+ *
+ * @return A pointer to first entry match pioctl_req
+ */
+static cmd_ctrl_node *wlan_get_pending_ioctl_cmd(pmlan_adapter pmadapter,
+ pmlan_ioctl_req pioctl_req)
+{
+ cmd_ctrl_node *pcmd_node = MNULL;
+
+ ENTER();
+
+ pcmd_node = (cmd_ctrl_node *)util_peek_list(pmadapter->pmoal_handle,
+ &pmadapter->cmd_pending_q,
+ MNULL, MNULL);
+ if (!pcmd_node) {
+ LEAVE();
+ return MNULL;
+ }
+ while (pcmd_node != (cmd_ctrl_node *)&pmadapter->cmd_pending_q) {
+ if (pcmd_node->pioctl_buf &&
+ (pcmd_node->pioctl_buf == pioctl_req)) {
+ LEAVE();
+ return pcmd_node;
+ }
+ pcmd_node = pcmd_node->pnext;
+ }
+ LEAVE();
+ return MNULL;
+}
+
+/**
+ * @brief This function will return the pointer to the first entry in
+ * pending cmd which matches the given bss_index
+ *
+ * @param pmadapter A pointer to mlan_adapter
+ * @param bss_index bss_index
+ *
+ * @return A pointer to first entry match pioctl_req
+ */
+static cmd_ctrl_node *wlan_get_bss_pending_ioctl_cmd(pmlan_adapter pmadapter,
+ t_u32 bss_index)
+{
+ cmd_ctrl_node *pcmd_node = MNULL;
+ mlan_ioctl_req *pioctl_buf = MNULL;
+ ENTER();
+
+ pcmd_node = (cmd_ctrl_node *)util_peek_list(pmadapter->pmoal_handle,
+ &pmadapter->cmd_pending_q,
+ MNULL, MNULL);
+ if (!pcmd_node) {
+ LEAVE();
+ return MNULL;
+ }
+ while (pcmd_node != (cmd_ctrl_node *)&pmadapter->cmd_pending_q) {
+ if (pcmd_node->pioctl_buf) {
+ pioctl_buf = (mlan_ioctl_req *)pcmd_node->pioctl_buf;
+ if (pioctl_buf->bss_index == bss_index) {
+ LEAVE();
+ return pcmd_node;
+ }
+ }
+ pcmd_node = pcmd_node->pnext;
+ }
+ LEAVE();
+ return MNULL;
+}
+
+/**
+ * @brief This function handles the command response of host_cmd
+ *
+ * @param pmpriv A pointer to mlan_private structure
+ * @param resp A pointer to HostCmd_DS_COMMAND
+ * @param pioctl_buf A pointer to mlan_ioctl_req structure
+ *
+ * @return MLAN_STATUS_SUCCESS
+ */
+static mlan_status wlan_ret_host_cmd(pmlan_private pmpriv,
+ HostCmd_DS_COMMAND *resp,
+ mlan_ioctl_req *pioctl_buf)
+{
+ mlan_ds_misc_cfg *misc;
+ t_u16 size = wlan_le16_to_cpu(resp->size);
+
+ ENTER();
+
+ PRINTM(MINFO, "host command response size = %d\n", size);
+ size = MIN(size, MRVDRV_SIZE_OF_CMD_BUFFER);
+ if (pioctl_buf) {
+ misc = (mlan_ds_misc_cfg *)pioctl_buf->pbuf;
+ misc->param.hostcmd.len = size;
+ memcpy_ext(pmpriv->adapter, misc->param.hostcmd.cmd,
+ (void *)resp, size, MRVDRV_SIZE_OF_CMD_BUFFER);
+ }
+
+ LEAVE();
+ return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ * @brief This function sends host command to firmware.
+ *
+ * @param pmpriv A pointer to mlan_private structure
+ * @param cmd A pointer to HostCmd_DS_COMMAND structure
+ * @param pdata_buf A pointer to data buffer
+ * @return MLAN_STATUS_SUCCESS
+ */
+static mlan_status wlan_cmd_host_cmd(pmlan_private pmpriv,
+ HostCmd_DS_COMMAND *cmd, t_void *pdata_buf)
+{
+ mlan_ds_misc_cmd *pcmd_ptr = (mlan_ds_misc_cmd *)pdata_buf;
+
+ ENTER();
+
+ /* Copy the HOST command to command buffer */
+ memcpy_ext(pmpriv->adapter, (void *)cmd, pcmd_ptr->cmd, pcmd_ptr->len,
+ MRVDRV_SIZE_OF_CMD_BUFFER);
+ PRINTM(MINFO, "Host command size = %d\n", pcmd_ptr->len);
+ LEAVE();
+ return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ * @brief This function get the cmd timeout value
+ *
+ * @param cmd_id cmd id
+ *
+ * @return timeout value for this command
+ */
+static t_u16 wlan_get_cmd_timeout(t_u16 cmd_id)
+{
+ t_u16 timeout;
+ ENTER();
+ switch (cmd_id) {
+ case HostCmd_CMD_802_11_SCAN:
+ case HostCmd_CMD_802_11_SCAN_EXT:
+ timeout = MRVDRV_TIMER_10S * 2;
+ break;
+ case HostCmd_CMD_FUNC_INIT:
+ case HostCmd_CMD_FUNC_SHUTDOWN:
+ case HostCmd_CMD_802_11_ASSOCIATE:
+ case HostCmd_CMD_802_11_DEAUTHENTICATE:
+ case HostCmd_CMD_802_11_DISASSOCIATE:
+ case HostCmd_CMD_802_11_AD_HOC_START:
+ case HostCmd_CMD_802_11_AD_HOC_JOIN:
+ case HostCmd_CMD_802_11_AD_HOC_STOP:
+ case HostCmd_CMD_11N_ADDBA_REQ:
+ case HostCmd_CMD_11N_ADDBA_RSP:
+ case HostCmd_CMD_11N_DELBA:
+ case HostCmd_CMD_802_11_REMAIN_ON_CHANNEL:
+ case HostCmd_CMD_SUPPLICANT_PMK:
+ case HostCmd_CMD_SUPPLICANT_PROFILE:
+ case HostCmd_CMD_SOFT_RESET:
+#ifdef UAP_SUPPORT
+ case HOST_CMD_APCMD_SYS_RESET:
+ case HOST_CMD_APCMD_BSS_START:
+ case HOST_CMD_APCMD_BSS_STOP:
+ case HOST_CMD_APCMD_STA_DEAUTH:
+#endif
+ case HostCMD_APCMD_ACS_SCAN:
+ timeout = MRVDRV_TIMER_5S;
+ break;
+ default:
+ timeout = MRVDRV_TIMER_1S * 2;
+ break;
+ }
+ LEAVE();
+ return timeout;
+}
+
+/**
+ * @brief This function downloads a command to firmware.
+ *
+ * @param pmpriv A pointer to mlan_private structure
+ * @param pcmd_node A pointer to cmd_ctrl_node structure
+ *
+ * @return MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ */
+static mlan_status wlan_dnld_cmd_to_fw(mlan_private *pmpriv,
+ cmd_ctrl_node *pcmd_node)
+{
+ mlan_adapter *pmadapter = pmpriv->adapter;
+ mlan_callbacks *pcb = (mlan_callbacks *)&pmadapter->callbacks;
+ mlan_status ret = MLAN_STATUS_SUCCESS;
+ HostCmd_DS_COMMAND *pcmd;
+ mlan_ioctl_req *pioctl_buf = MNULL;
+ t_u16 cmd_code;
+ t_u16 cmd_size;
+ t_u32 age_ts_usec;
+#ifdef USB
+ t_u32 tmp;
+#endif
+#ifdef DEBUG_LEVEL1
+ t_u32 sec = 0, usec = 0;
+#endif
+ t_u16 timeout = 0;
+
+ ENTER();
+
+ if (pcmd_node)
+ if (pcmd_node->pioctl_buf != MNULL)
+ pioctl_buf = (mlan_ioctl_req *)pcmd_node->pioctl_buf;
+ if (!pmadapter || !pcmd_node) {
+ if (pioctl_buf)
+ pioctl_buf->status_code = MLAN_ERROR_CMD_DNLD_FAIL;
+ ret = MLAN_STATUS_FAILURE;
+ goto done;
+ }
+
+ pcmd = (HostCmd_DS_COMMAND *)(pcmd_node->cmdbuf->pbuf +
+ pcmd_node->cmdbuf->data_offset);
+
+ /* Sanity test */
+ if (pcmd == MNULL || pcmd->size == 0) {
+ PRINTM(MERROR,
+ "DNLD_CMD: pcmd is null or command size is zero, "
+ "Not sending\n");
+ if (pioctl_buf)
+ pioctl_buf->status_code = MLAN_ERROR_CMD_DNLD_FAIL;
+ wlan_request_cmd_lock(pmadapter);
+ wlan_insert_cmd_to_free_q(pmadapter, pcmd_node);
+ wlan_release_cmd_lock(pmadapter);
+ ret = MLAN_STATUS_FAILURE;
+ goto done;
+ }
+
+ /* Set command sequence number */
+ pmadapter->seq_num++;
+ pcmd->seq_num = wlan_cpu_to_le16(HostCmd_SET_SEQ_NO_BSS_INFO(
+ pmadapter->seq_num, pcmd_node->priv->bss_num,
+ pcmd_node->priv->bss_type));
+ cmd_code = wlan_le16_to_cpu(pcmd->command);
+ pcmd_node->cmd_no = cmd_code;
+ timeout = wlan_get_cmd_timeout(cmd_code);
+ cmd_size = wlan_le16_to_cpu(pcmd->size);
+
+ pcmd_node->cmdbuf->data_len = cmd_size;
+
+ wlan_request_cmd_lock(pmadapter);
+ pmadapter->curr_cmd = pcmd_node;
+ wlan_release_cmd_lock(pmadapter);
+
+ /* Save the last command id and action to debug log */
+ pmadapter->dbg.last_cmd_index =
+ (pmadapter->dbg.last_cmd_index + 1) % DBG_CMD_NUM;
+ pmadapter->dbg.last_cmd_id[pmadapter->dbg.last_cmd_index] = cmd_code;
+ pmadapter->dbg.last_cmd_act[pmadapter->dbg.last_cmd_index] =
+ wlan_le16_to_cpu(*(t_u16 *)((t_u8 *)pcmd + S_DS_GEN));
+ pmadapter->callbacks.moal_get_system_time(pmadapter->pmoal_handle,
+ &pmadapter->dnld_cmd_in_secs,
+ &age_ts_usec);
+
+#ifdef USB
+ if (IS_USB(pmadapter->card_type)) {
+ /* Add extra header for USB */
+ if (pcmd_node->cmdbuf->data_offset < MLAN_TYPE_LEN) {
+ PRINTM(MERROR,
+ "DNLD_CMD: data_offset is too small=%d\n",
+ pcmd_node->cmdbuf->data_offset);
+ if (pioctl_buf)
+ pioctl_buf->status_code =
+ MLAN_ERROR_CMD_DNLD_FAIL;
+
+ wlan_request_cmd_lock(pmadapter);
+ wlan_insert_cmd_to_free_q(pmadapter, pcmd_node);
+ pmadapter->curr_cmd = MNULL;
+ wlan_release_cmd_lock(pmadapter);
+ if (pmadapter->dbg.last_cmd_index)
+ pmadapter->dbg.last_cmd_index--;
+ else
+ pmadapter->dbg.last_cmd_index = DBG_CMD_NUM - 1;
+ ret = MLAN_STATUS_FAILURE;
+ goto done;
+ }
+ tmp = wlan_cpu_to_le32(MLAN_USB_TYPE_CMD);
+ memcpy_ext(pmadapter, (t_u8 *)pcmd - MLAN_TYPE_LEN,
+ (t_u8 *)&tmp, MLAN_TYPE_LEN, MLAN_TYPE_LEN);
+ pcmd_node->cmdbuf->data_offset -= MLAN_TYPE_LEN;
+ pcmd_node->cmdbuf->data_len += MLAN_TYPE_LEN;
+ }
+#endif
+
+ PRINTM_GET_SYS_TIME(MCMND, &sec, &usec);
+ PRINTM_NETINTF(MCMND, pmpriv);
+ PRINTM(MCMND,
+ "DNLD_CMD (%lu.%06lu): 0x%x, act 0x%x, len %d, seqno 0x%x timeout %d\n",
+ sec, usec, cmd_code,
+ wlan_le16_to_cpu(*(t_u16 *)((t_u8 *)pcmd + S_DS_GEN)), cmd_size,
+ wlan_le16_to_cpu(pcmd->seq_num), timeout);
+ DBG_HEXDUMP(MCMD_D, "DNLD_CMD", (t_u8 *)pcmd, cmd_size);
+
+#if defined(SDIO) || defined(PCIE)
+ if (!IS_USB(pmadapter->card_type)) {
+ pcmd_node->cmdbuf->data_offset -=
+ pmadapter->ops.intf_header_len;
+ pcmd_node->cmdbuf->data_len += pmadapter->ops.intf_header_len;
+ }
+#endif
+
+ /* Send the command to lower layer */
+ ret = pmadapter->ops.host_to_card(pmpriv, MLAN_TYPE_CMD,
+ pcmd_node->cmdbuf, MNULL);
+
+#ifdef USB
+ if (IS_USB(pmadapter->card_type) && (ret == MLAN_STATUS_PENDING))
+ pcmd_node->cmdbuf = MNULL;
+#endif
+
+ if (ret == MLAN_STATUS_FAILURE) {
+ PRINTM(MERROR, "DNLD_CMD: Host to Card Failed\n");
+ if (pcmd_node->pioctl_buf) {
+ pioctl_buf = (mlan_ioctl_req *)pcmd_node->pioctl_buf;
+ pioctl_buf->status_code = MLAN_ERROR_CMD_DNLD_FAIL;
+ }
+
+ wlan_request_cmd_lock(pmadapter);
+ wlan_insert_cmd_to_free_q(pmadapter, pmadapter->curr_cmd);
+ pmadapter->curr_cmd = MNULL;
+ wlan_release_cmd_lock(pmadapter);
+ if (pmadapter->dbg.last_cmd_index)
+ pmadapter->dbg.last_cmd_index--;
+ else
+ pmadapter->dbg.last_cmd_index = DBG_CMD_NUM - 1;
+
+ pmadapter->dbg.num_cmd_host_to_card_failure++;
+ wlan_dump_info(pmadapter, REASON_CODE_CMD_TO_CARD_FAILURE);
+ ret = MLAN_STATUS_FAILURE;
+ goto done;
+ }
+
+ /* Clear BSS_NO_BITS from HostCmd */
+ cmd_code &= HostCmd_CMD_ID_MASK;
+
+ /* For the command who has no command response, we should return here */
+ if (cmd_code == HostCmd_CMD_FW_DUMP_EVENT ||
+ cmd_code == HostCmd_CMD_SOFT_RESET) {
+ if (pcmd_node->pioctl_buf) {
+ PRINTM(MMSG,
+ "CMD(0x%x) has no cmd resp: free curr_cmd and do ioctl_complete\n",
+ cmd_code);
+ pioctl_buf = (mlan_ioctl_req *)pcmd_node->pioctl_buf;
+ wlan_request_cmd_lock(pmadapter);
+ wlan_insert_cmd_to_free_q(pmadapter,
+ pmadapter->curr_cmd);
+ pmadapter->curr_cmd = MNULL;
+ wlan_release_cmd_lock(pmadapter);
+ }
+ goto done;
+ }
+
+ /* Setup the timer after transmit command */
+ pcb->moal_start_timer(pmadapter->pmoal_handle,
+ pmadapter->pmlan_cmd_timer, MFALSE, timeout);
+
+ pmadapter->cmd_timer_is_set = MTRUE;
+
+ ret = MLAN_STATUS_SUCCESS;
+
+done:
+ LEAVE();
+ return ret;
+}
+
+/**
+ * @brief This function sends sleep confirm command to firmware.
+ *
+ * @param pmadapter A pointer to mlan_adapter structure
+ *
+ * @return MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ */
+static mlan_status wlan_dnld_sleep_confirm_cmd(mlan_adapter *pmadapter)
+{
+ mlan_status ret = MLAN_STATUS_SUCCESS;
+ static t_u32 i;
+#if defined(SDIO) || defined(PCIE)
+ t_u16 cmd_len = 0;
+#endif
+ opt_sleep_confirm_buffer *sleep_cfm_buf =
+ (opt_sleep_confirm_buffer *)(pmadapter->psleep_cfm->pbuf +
+ pmadapter->psleep_cfm->data_offset);
+ mlan_buffer *pmbuf = MNULL;
+ mlan_private *pmpriv = MNULL;
+
+ ENTER();
+
+ pmpriv = wlan_get_priv(pmadapter, MLAN_BSS_ROLE_ANY);
+ if (!pmpriv) {
+ LEAVE();
+ return MLAN_STATUS_FAILURE;
+ }
+#if defined(SDIO) || defined(PCIE)
+ if (!IS_USB(pmadapter->card_type)) {
+ cmd_len = sizeof(OPT_Confirm_Sleep);
+ pmbuf = pmadapter->psleep_cfm;
+ }
+#endif
+ pmadapter->seq_num++;
+ sleep_cfm_buf->ps_cfm_sleep.seq_num =
+ wlan_cpu_to_le16(HostCmd_SET_SEQ_NO_BSS_INFO(
+ pmadapter->seq_num, pmpriv->bss_num, pmpriv->bss_type));
+ DBG_HEXDUMP(MCMD_D, "SLEEP_CFM", &sleep_cfm_buf->ps_cfm_sleep,
+ sizeof(OPT_Confirm_Sleep));
+
+ /* Send sleep confirm command to firmware */
+#ifdef USB
+ if (IS_USB(pmadapter->card_type)) {
+ pmbuf = wlan_alloc_mlan_buffer(pmadapter,
+ sizeof(opt_sleep_confirm_buffer),
+ 0, MOAL_MALLOC_BUFFER);
+
+ if (!pmbuf) {
+ PRINTM(MERROR,
+ "Failed to allocate sleep confirm buffers\n");
+ LEAVE();
+ return MLAN_STATUS_FAILURE;
+ }
+ pmbuf->buf_type = MLAN_BUF_TYPE_CMD;
+ pmbuf->data_len = pmadapter->psleep_cfm->data_len;
+ memcpy_ext(pmadapter, pmbuf->pbuf + pmbuf->data_offset,
+ pmadapter->psleep_cfm->pbuf +
+ pmadapter->psleep_cfm->data_offset,
+ pmadapter->psleep_cfm->data_len, pmbuf->data_len);
+ }
+#endif /* USB */
+
+#if defined(SDIO) || defined(PCIE)
+ if (!IS_USB(pmadapter->card_type))
+ pmadapter->psleep_cfm->data_len =
+ cmd_len + pmadapter->ops.intf_header_len;
+#endif
+
+ if (pmbuf)
+ ret = pmadapter->ops.host_to_card(pmpriv, MLAN_TYPE_CMD, pmbuf,
+ MNULL);
+
+#ifdef USB
+ if (IS_USB(pmadapter->card_type) && (ret != MLAN_STATUS_PENDING))
+ wlan_free_mlan_buffer(pmadapter, pmbuf);
+#endif
+ if (ret == MLAN_STATUS_FAILURE) {
+ PRINTM(MERROR, "SLEEP_CFM: failed\n");
+ pmadapter->dbg.num_cmd_sleep_cfm_host_to_card_failure++;
+ goto done;
+ } else {
+ if (GET_BSS_ROLE(pmpriv) == MLAN_BSS_ROLE_UAP)
+ pmadapter->ps_state = PS_STATE_SLEEP_CFM;
+#ifdef STA_SUPPORT
+ if (GET_BSS_ROLE(pmpriv) == MLAN_BSS_ROLE_STA) {
+ if (!sleep_cfm_buf->ps_cfm_sleep.sleep_cfm.resp_ctrl) {
+ /* Response is not needed for sleep confirm
+ * command */
+ pmadapter->ps_state = PS_STATE_SLEEP;
+ } else {
+ pmadapter->ps_state = PS_STATE_SLEEP_CFM;
+ }
+
+ if (!sleep_cfm_buf->ps_cfm_sleep.sleep_cfm.resp_ctrl &&
+ (pmadapter->is_hs_configured &&
+ !pmadapter->sleep_period.period)) {
+ pmadapter->pm_wakeup_card_req = MTRUE;
+ wlan_host_sleep_activated_event(
+ wlan_get_priv(pmadapter,
+ MLAN_BSS_ROLE_STA),
+ MTRUE);
+ }
+ }
+#endif /* STA_SUPPORT */
+
+ PRINTM_NETINTF(MEVENT, pmpriv);
+#define NUM_SC_PER_LINE 16
+ if (++i % NUM_SC_PER_LINE == 0)
+ PRINTM(MEVENT, "+\n");
+ else
+ PRINTM(MEVENT, "+");
+ }
+
+done:
+ LEAVE();
+ return ret;
+}
+
+/********************************************************
+ Global Functions
+********************************************************/
+
+/**
+ * @brief Event handler
+ *
+ * @param priv A pointer to mlan_private structure
+ * @param event_id Event ID
+ * @param pmevent Event buffer
+ *
+ * @return MLAN_STATUS_SUCCESS
+ */
+mlan_status wlan_recv_event(pmlan_private priv, mlan_event_id event_id,
+ t_void *pmevent)
+{
+ pmlan_callbacks pcb = MNULL;
+
+ ENTER();
+
+ if (!priv) {
+ LEAVE();
+ return MLAN_STATUS_FAILURE;
+ }
+ pcb = &priv->adapter->callbacks;
+
+ if (pmevent)
+ /* The caller has provided the event. */
+ pcb->moal_recv_event(priv->adapter->pmoal_handle,
+ (pmlan_event)pmevent);
+ else {
+ mlan_event mevent;
+
+ memset(priv->adapter, &mevent, 0, sizeof(mlan_event));
+ mevent.bss_index = priv->bss_index;
+ mevent.event_id = event_id;
+ mevent.event_len = 0;
+
+ pcb->moal_recv_event(priv->adapter->pmoal_handle, &mevent);
+ }
+
+ LEAVE();
+ return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ * @brief This function allocates the command buffer and links
+ * it to command free queue.
+ *
+ * @param pmadapter A pointer to mlan_adapter structure
+ *
+ * @return MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ */
+mlan_status wlan_alloc_cmd_buffer(mlan_adapter *pmadapter)
+{
+ mlan_status ret = MLAN_STATUS_SUCCESS;
+ mlan_callbacks *pcb = (mlan_callbacks *)&pmadapter->callbacks;
+ cmd_ctrl_node *pcmd_array = MNULL;
+ t_u32 buf_size;
+ t_u32 i;
+
+ ENTER();
+
+ /* Allocate and initialize cmd_ctrl_node */
+ buf_size = sizeof(cmd_ctrl_node) * MRVDRV_NUM_OF_CMD_BUFFER;
+ ret = pcb->moal_malloc(pmadapter->pmoal_handle, buf_size,
+ MLAN_MEM_DEF | MLAN_MEM_DMA,
+ (t_u8 **)&pcmd_array);
+ if (ret != MLAN_STATUS_SUCCESS || !pcmd_array) {
+ PRINTM(MERROR,
+ "ALLOC_CMD_BUF: Failed to allocate pcmd_array\n");
+ ret = MLAN_STATUS_FAILURE;
+ goto done;
+ }
+
+ pmadapter->cmd_pool = pcmd_array;
+ memset(pmadapter, pmadapter->cmd_pool, 0, buf_size);
+
+#if defined(PCIE) || defined(SDIO)
+ if (!IS_USB(pmadapter->card_type)) {
+ /* Allocate and initialize command buffers */
+ for (i = 0; i < MRVDRV_NUM_OF_CMD_BUFFER; i++) {
+ pcmd_array[i].pmbuf = wlan_alloc_mlan_buffer(
+ pmadapter, MRVDRV_SIZE_OF_CMD_BUFFER, 0,
+ MOAL_MALLOC_BUFFER);
+ if (!pcmd_array[i].pmbuf) {
+ PRINTM(MERROR,
+ "ALLOC_CMD_BUF: Failed to allocate command buffer\n");
+ ret = MLAN_STATUS_FAILURE;
+ goto done;
+ }
+ }
+ }
+#endif
+ wlan_request_cmd_lock(pmadapter);
+ for (i = 0; i < MRVDRV_NUM_OF_CMD_BUFFER; i++)
+ wlan_insert_cmd_to_free_q(pmadapter, &pcmd_array[i]);
+ wlan_release_cmd_lock(pmadapter);
+ ret = MLAN_STATUS_SUCCESS;
+done:
+ LEAVE();
+ return ret;
+}
+
+/**
+ * @brief This function frees the command buffer.
+ *
+ * @param pmadapter A pointer to mlan_adapter structure
+ *
+ * @return MLAN_STATUS_SUCCESS
+ */
+mlan_status wlan_free_cmd_buffer(mlan_adapter *pmadapter)
+{
+ mlan_callbacks *pcb = (mlan_callbacks *)&pmadapter->callbacks;
+ cmd_ctrl_node *pcmd_array;
+ t_u32 i;
+
+ ENTER();
+
+ /* Need to check if cmd pool is allocated or not */
+ if (pmadapter->cmd_pool == MNULL) {
+ PRINTM(MINFO, "FREE_CMD_BUF: cmd_pool is Null\n");
+ goto done;
+ }
+
+ pcmd_array = pmadapter->cmd_pool;
+
+ /* Release shared memory buffers */
+ for (i = 0; i < MRVDRV_NUM_OF_CMD_BUFFER; i++) {
+#ifdef USB
+ if (IS_USB(pmadapter->card_type) && pcmd_array[i].cmdbuf) {
+ PRINTM(MINFO, "Free all the USB command buffer.\n");
+ wlan_free_mlan_buffer(pmadapter, pcmd_array[i].cmdbuf);
+ pcmd_array[i].cmdbuf = MNULL;
+ }
+#endif
+#if defined(SDIO) || defined(PCIE)
+ if (!IS_USB(pmadapter->card_type) && pcmd_array[i].pmbuf) {
+ PRINTM(MINFO, "Free all the command buffer.\n");
+ wlan_free_mlan_buffer(pmadapter, pcmd_array[i].pmbuf);
+ pcmd_array[i].pmbuf = MNULL;
+ }
+#endif
+ if (pcmd_array[i].respbuf) {
+#ifdef USB
+ if (IS_USB(pmadapter->card_type))
+ pmadapter->callbacks.moal_recv_complete(
+ pmadapter->pmoal_handle,
+ pcmd_array[i].respbuf,
+ pmadapter->rx_cmd_ep,
+ MLAN_STATUS_SUCCESS);
+#endif
+#if defined(SDIO) || defined(PCIE)
+ if (!IS_USB(pmadapter->card_type))
+ wlan_free_mlan_buffer(pmadapter,
+ pcmd_array[i].respbuf);
+#endif
+ pcmd_array[i].respbuf = MNULL;
+ }
+ }
+ /* Release cmd_ctrl_node */
+ if (pmadapter->cmd_pool) {
+ PRINTM(MINFO, "Free command pool.\n");
+ pcb->moal_mfree(pmadapter->pmoal_handle,
+ (t_u8 *)pmadapter->cmd_pool);
+ pmadapter->cmd_pool = MNULL;
+ }
+
+done:
+ LEAVE();
+ return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ * @brief This function handles events generated by firmware
+ *
+ * @param pmadapter A pointer to mlan_adapter structure
+ *
+ * @return MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ */
+mlan_status wlan_process_event(pmlan_adapter pmadapter)
+{
+ mlan_status ret = MLAN_STATUS_SUCCESS;
+ pmlan_private priv = wlan_get_priv(pmadapter, MLAN_BSS_ROLE_ANY);
+ pmlan_buffer pmbuf = pmadapter->pmlan_buffer_event;
+ t_u32 eventcause = pmadapter->event_cause;
+#ifdef DEBUG_LEVEL1
+ t_u32 in_ts_sec = 0, in_ts_usec = 0;
+#endif
+ ENTER();
+
+ /* Save the last event to debug log */
+ pmadapter->dbg.last_event_index =
+ (pmadapter->dbg.last_event_index + 1) % DBG_CMD_NUM;
+ pmadapter->dbg.last_event[pmadapter->dbg.last_event_index] =
+ (t_u16)eventcause;
+
+ if ((eventcause & EVENT_ID_MASK) == EVENT_RADAR_DETECTED) {
+ if (wlan_11h_dfs_event_preprocessing(pmadapter) ==
+ MLAN_STATUS_SUCCESS) {
+ memcpy_ext(pmadapter, (t_u8 *)&eventcause,
+ pmbuf->pbuf + pmbuf->data_offset,
+ sizeof(eventcause), sizeof(eventcause));
+ } else {
+ priv = wlan_get_priv_by_id(
+ pmadapter, EVENT_GET_BSS_NUM(eventcause),
+ EVENT_GET_BSS_TYPE(eventcause));
+ if (priv)
+ PRINTM_NETINTF(MEVENT, priv);
+ PRINTM(MERROR, "Error processing DFS Event: 0x%x\n",
+ eventcause);
+ goto done;
+ }
+ }
+ /* Get BSS number and corresponding priv */
+ priv = wlan_get_priv_by_id(pmadapter, EVENT_GET_BSS_NUM(eventcause),
+ EVENT_GET_BSS_TYPE(eventcause));
+ if (!priv)
+ priv = wlan_get_priv(pmadapter, MLAN_BSS_ROLE_ANY);
+ if (!priv) {
+ ret = MLAN_STATUS_FAILURE;
+ goto done;
+ }
+
+ /* Clear BSS_NO_BITS from event */
+ eventcause &= EVENT_ID_MASK;
+ pmadapter->event_cause = eventcause;
+
+ if (pmbuf) {
+ pmbuf->bss_index = priv->bss_index;
+ memcpy_ext(pmadapter, pmbuf->pbuf + pmbuf->data_offset,
+ (t_u8 *)&eventcause, sizeof(eventcause),
+ sizeof(eventcause));
+ }
+
+ if (eventcause != EVENT_PS_SLEEP && eventcause != EVENT_PS_AWAKE &&
+ eventcause != EVENT_FW_DUMP_INFO) {
+ PRINTM_GET_SYS_TIME(MEVENT, &in_ts_sec, &in_ts_usec);
+ PRINTM_NETINTF(MEVENT, priv);
+ PRINTM(MEVENT, "%lu.%06lu : Event: 0x%x\n", in_ts_sec,
+ in_ts_usec, eventcause);
+ }
+
+ ret = priv->ops.process_event(priv);
+done:
+ pmadapter->event_cause = 0;
+ pmadapter->pmlan_buffer_event = MNULL;
+ if (pmbuf)
+ pmadapter->ops.event_complete(pmadapter, pmbuf,
+ MLAN_STATUS_SUCCESS);
+
+ LEAVE();
+ return ret;
+}
+
+/**
+ * @brief This function requests a lock on command queue.
+ *
+ * @param pmadapter A pointer to mlan_adapter structure
+ *
+ * @return N/A
+ */
+t_void wlan_request_cmd_lock(mlan_adapter *pmadapter)
+{
+ mlan_callbacks *pcb = (mlan_callbacks *)&pmadapter->callbacks;
+
+ ENTER();
+
+ /* Call MOAL spin lock callback function */
+ pcb->moal_spin_lock(pmadapter->pmoal_handle, pmadapter->pmlan_cmd_lock);
+
+ LEAVE();
+ return;
+}
+
+/**
+ * @brief This function releases a lock on command queue.
+ *
+ * @param pmadapter A pointer to mlan_adapter structure
+ *
+ * @return N/A
+ */
+t_void wlan_release_cmd_lock(mlan_adapter *pmadapter)
+{
+ mlan_callbacks *pcb = (mlan_callbacks *)&pmadapter->callbacks;
+
+ ENTER();
+
+ /* Call MOAL spin unlock callback function */
+ pcb->moal_spin_unlock(pmadapter->pmoal_handle,
+ pmadapter->pmlan_cmd_lock);
+
+ LEAVE();
+ return;
+}
+
+/**
+ * @brief This function prepare the command before sending to firmware.
+ *
+ * @param pmpriv A pointer to mlan_private structure
+ * @param cmd_no Command number
+ * @param cmd_action Command action: GET or SET
+ * @param cmd_oid Cmd oid: treated as sub command
+ * @param pioctl_buf A pointer to MLAN IOCTL Request buffer
+ * @param pdata_buf A pointer to information buffer
+ *
+ * @return MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ */
+mlan_status wlan_prepare_cmd(mlan_private *pmpriv, t_u16 cmd_no,
+ t_u16 cmd_action, t_u32 cmd_oid,
+ t_void *pioctl_buf, t_void *pdata_buf)
+{
+ mlan_status ret = MLAN_STATUS_SUCCESS;
+ mlan_adapter *pmadapter = MNULL;
+ cmd_ctrl_node *pcmd_node = MNULL;
+ HostCmd_DS_COMMAND *cmd_ptr = MNULL;
+ pmlan_ioctl_req pioctl_req = (mlan_ioctl_req *)pioctl_buf;
+
+ ENTER();
+
+ if (!pmpriv) {
+ LEAVE();
+ return MLAN_STATUS_FAILURE;
+ }
+ pmadapter = pmpriv->adapter;
+
+ /* Sanity test */
+ if (!pmadapter || pmadapter->surprise_removed) {
+ PRINTM(MERROR, "PREP_CMD: Card is Removed\n");
+ if (pioctl_req)
+ pioctl_req->status_code = MLAN_ERROR_FW_NOT_READY;
+ ret = MLAN_STATUS_FAILURE;
+ goto done;
+ }
+
+ if (pmadapter->hw_status == WlanHardwareStatusReset) {
+ if ((cmd_no != HostCmd_CMD_FUNC_INIT)
+#ifdef PCIE
+ && (cmd_no != HostCmd_CMD_PCIE_HOST_BUF_DETAILS)
+#endif
+ ) {
+ PRINTM(MERROR, "PREP_CMD: FW is in reset state\n");
+ if (pioctl_req)
+ pioctl_req->status_code =
+ MLAN_ERROR_FW_NOT_READY;
+ ret = MLAN_STATUS_FAILURE;
+ goto done;
+ }
+ }
+
+ /* Get a new command node */
+ pcmd_node = wlan_get_cmd_node(pmadapter);
+
+ if (pcmd_node == MNULL) {
+ PRINTM(MERROR, "PREP_CMD: No free cmd node\n");
+ wlan_dump_info(pmadapter, REASON_CODE_NO_CMD_NODE);
+ if (pioctl_req)
+ pioctl_req->status_code = MLAN_ERROR_NO_MEM;
+ ret = MLAN_STATUS_FAILURE;
+ goto done;
+ }
+ /** reset num no cmd node */
+ pmadapter->dbg.num_no_cmd_node = 0;
+
+ /* Initialize the command node */
+ wlan_init_cmd_node(pmpriv, pcmd_node, cmd_no, pioctl_buf, pdata_buf);
+
+ if (pcmd_node->cmdbuf == MNULL) {
+ PRINTM(MERROR, "PREP_CMD: No free cmd buf\n");
+ if (pioctl_req)
+ pioctl_req->status_code = MLAN_ERROR_NO_MEM;
+ ret = MLAN_STATUS_FAILURE;
+ goto done;
+ }
+
+ cmd_ptr = (HostCmd_DS_COMMAND *)(pcmd_node->cmdbuf->pbuf +
+ pcmd_node->cmdbuf->data_offset);
+ cmd_ptr->command = cmd_no;
+ cmd_ptr->result = 0;
+
+ /* Prepare command */
+ if (cmd_no)
+ ret = pmpriv->ops.prepare_cmd(pmpriv, cmd_no, cmd_action,
+ cmd_oid, pioctl_buf, pdata_buf,
+ cmd_ptr);
+ else {
+ ret = wlan_cmd_host_cmd(pmpriv, cmd_ptr, pdata_buf);
+ pcmd_node->cmd_flag |= CMD_F_HOSTCMD;
+ }
+
+ /* Return error, since the command preparation failed */
+ if (ret != MLAN_STATUS_SUCCESS) {
+ PRINTM(MERROR, "PREP_CMD: Command 0x%x preparation failed\n",
+ cmd_no);
+ pcmd_node->pioctl_buf = MNULL;
+ if (pioctl_req)
+ pioctl_req->status_code = MLAN_ERROR_CMD_DNLD_FAIL;
+ wlan_request_cmd_lock(pmadapter);
+ wlan_insert_cmd_to_free_q(pmadapter, pcmd_node);
+ wlan_release_cmd_lock(pmadapter);
+ ret = MLAN_STATUS_FAILURE;
+ goto done;
+ }
+
+ wlan_request_cmd_lock(pmadapter);
+ /* Send command */
+#ifdef STA_SUPPORT
+ if (cmd_no == HostCmd_CMD_802_11_SCAN ||
+ cmd_no == HostCmd_CMD_802_11_SCAN_EXT) {
+ if (cmd_no == HostCmd_CMD_802_11_SCAN_EXT &&
+ pmadapter->ext_scan && pmadapter->ext_scan_enh &&
+ pmadapter->ext_scan_type == EXT_SCAN_ENHANCE) {
+ wlan_insert_cmd_to_pending_q(pmadapter, pcmd_node,
+ MFALSE);
+ } else
+ wlan_queue_scan_cmd(pmpriv, pcmd_node);
+ } else {
+#endif
+ if ((cmd_no == HostCmd_CMD_802_11_HS_CFG_ENH) &&
+ (cmd_action == HostCmd_ACT_GEN_SET) &&
+ (pmadapter->hs_cfg.conditions == HOST_SLEEP_CFG_CANCEL))
+ wlan_insert_cmd_to_pending_q(pmadapter, pcmd_node,
+ MFALSE);
+ else
+ wlan_insert_cmd_to_pending_q(pmadapter, pcmd_node,
+ MTRUE);
+#ifdef STA_SUPPORT
+ }
+#endif
+ wlan_release_cmd_lock(pmadapter);
+done:
+ LEAVE();
+ return ret;
+}
+
+/**
+ * @brief This function inserts command node to cmd_free_q
+ * after cleaning it.
+ *
+ * @param pmadapter A pointer to mlan_adapter structure
+ * @param pcmd_node A pointer to cmd_ctrl_node structure
+ *
+ * @return N/A
+ */
+t_void wlan_insert_cmd_to_free_q(mlan_adapter *pmadapter,
+ cmd_ctrl_node *pcmd_node)
+{
+ mlan_callbacks *pcb = (mlan_callbacks *)&pmadapter->callbacks;
+ mlan_ioctl_req *pioctl_req = MNULL;
+ ENTER();
+
+ if (pcmd_node == MNULL)
+ goto done;
+ if (pcmd_node->pioctl_buf) {
+ pioctl_req = (mlan_ioctl_req *)pcmd_node->pioctl_buf;
+ if (pioctl_req->status_code != MLAN_ERROR_NO_ERROR)
+ pcb->moal_ioctl_complete(pmadapter->pmoal_handle,
+ pioctl_req,
+ MLAN_STATUS_FAILURE);
+ else
+ pcb->moal_ioctl_complete(pmadapter->pmoal_handle,
+ pioctl_req,
+ MLAN_STATUS_SUCCESS);
+ }
+ /* Clean the node */
+ wlan_clean_cmd_node(pmadapter, pcmd_node);
+
+ /* Insert node into cmd_free_q */
+ util_enqueue_list_tail(pmadapter->pmoal_handle, &pmadapter->cmd_free_q,
+ (pmlan_linked_list)pcmd_node, MNULL, MNULL);
+done:
+ LEAVE();
+}
+
+/**
+ * @brief This function queues the command to cmd list.
+ *
+ * @param pmadapter A pointer to mlan_adapter structure
+ * @param pcmd_node A pointer to cmd_ctrl_node structure
+ * @param add_tail Specify if the cmd needs to be queued in the header or
+ * tail
+ *
+ * @return N/A
+ */
+t_void wlan_insert_cmd_to_pending_q(mlan_adapter *pmadapter,
+ cmd_ctrl_node *pcmd_node, t_u32 add_tail)
+{
+ HostCmd_DS_COMMAND *pcmd = MNULL;
+ t_u16 command;
+
+ ENTER();
+
+ if (pcmd_node == MNULL) {
+ PRINTM(MERROR, "QUEUE_CMD: pcmd_node is MNULL\n");
+ goto done;
+ }
+
+ pcmd = (HostCmd_DS_COMMAND *)(pcmd_node->cmdbuf->pbuf +
+ pcmd_node->cmdbuf->data_offset);
+
+ command = wlan_le16_to_cpu(pcmd->command);
+
+ /* Exit_PS command needs to be queued in the header always. */
+ if (command == HostCmd_CMD_802_11_PS_MODE_ENH) {
+ HostCmd_DS_802_11_PS_MODE_ENH *pm = &pcmd->params.psmode_enh;
+ if (wlan_le16_to_cpu(pm->action) == DIS_AUTO_PS) {
+ if (pmadapter->ps_state != PS_STATE_AWAKE)
+ add_tail = MFALSE;
+ }
+ }
+
+ if (add_tail) {
+ util_enqueue_list_tail(pmadapter->pmoal_handle,
+ &pmadapter->cmd_pending_q,
+ (pmlan_linked_list)pcmd_node, MNULL,
+ MNULL);
+ } else {
+ util_enqueue_list_head(pmadapter->pmoal_handle,
+ &pmadapter->cmd_pending_q,
+ (pmlan_linked_list)pcmd_node, MNULL,
+ MNULL);
+ }
+
+ PRINTM_NETINTF(MCMND, pcmd_node->priv);
+ PRINTM(MCMND, "QUEUE_CMD: cmd=0x%x is queued\n", command);
+
+done:
+ LEAVE();
+ return;
+}
+
+/**
+ * @brief This function executes next command in command
+ * pending queue. It will put firmware back to PS mode
+ * if applicable.
+ *
+ * @param pmadapter A pointer to mlan_adapter structure
+ *
+ * @return MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ */
+mlan_status wlan_exec_next_cmd(mlan_adapter *pmadapter)
+{
+ mlan_private *priv = MNULL;
+ cmd_ctrl_node *pcmd_node = MNULL;
+ mlan_status ret = MLAN_STATUS_SUCCESS;
+ HostCmd_DS_COMMAND *pcmd;
+
+ ENTER();
+
+ /* Sanity test */
+ if (pmadapter == MNULL) {
+ PRINTM(MERROR, "EXEC_NEXT_CMD: pmadapter is MNULL\n");
+ ret = MLAN_STATUS_FAILURE;
+ goto done;
+ }
+ /* Check if already in processing */
+ if (pmadapter->curr_cmd) {
+ PRINTM(MERROR,
+ "EXEC_NEXT_CMD: there is command in processing!\n");
+ ret = MLAN_STATUS_FAILURE;
+ goto done;
+ }
+
+ wlan_request_cmd_lock(pmadapter);
+ /* Check if any command is pending */
+ pcmd_node = (cmd_ctrl_node *)util_peek_list(pmadapter->pmoal_handle,
+ &pmadapter->cmd_pending_q,
+ MNULL, MNULL);
+
+ if (pcmd_node) {
+ pcmd = (HostCmd_DS_COMMAND *)(pcmd_node->cmdbuf->pbuf +
+ pcmd_node->cmdbuf->data_offset);
+ priv = pcmd_node->priv;
+
+ if (pmadapter->ps_state != PS_STATE_AWAKE) {
+ PRINTM(MERROR,
+ "Cannot send command in sleep state, this should not happen\n");
+ wlan_release_cmd_lock(pmadapter);
+ goto done;
+ }
+
+ util_unlink_list(pmadapter->pmoal_handle,
+ &pmadapter->cmd_pending_q,
+ (pmlan_linked_list)pcmd_node, MNULL, MNULL);
+ wlan_release_cmd_lock(pmadapter);
+ ret = wlan_dnld_cmd_to_fw(priv, pcmd_node);
+ priv = wlan_get_priv(pmadapter, MLAN_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 && (pcmd->command !=
+ wlan_cpu_to_le16(HostCmd_CMD_802_11_HS_CFG_ENH))) {
+ if (pmadapter->hs_activated == MTRUE) {
+ pmadapter->is_hs_configured = MFALSE;
+ wlan_host_sleep_activated_event(priv, MFALSE);
+ }
+ }
+ goto done;
+ } else {
+ wlan_release_cmd_lock(pmadapter);
+ }
+ ret = MLAN_STATUS_SUCCESS;
+done:
+ LEAVE();
+ return ret;
+}
+
+/**
+ * @brief This function handles the command response
+ *
+ * @param pmadapter A pointer to mlan_adapter structure
+ *
+ * @return MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ */
+mlan_status wlan_process_cmdresp(mlan_adapter *pmadapter)
+{
+ HostCmd_DS_COMMAND *resp = MNULL;
+ mlan_private *pmpriv = wlan_get_priv(pmadapter, MLAN_BSS_ROLE_ANY);
+ mlan_private *pmpriv_next = MNULL;
+ mlan_status ret = MLAN_STATUS_SUCCESS;
+ t_u16 orig_cmdresp_no;
+ t_u16 cmdresp_no;
+ t_u16 cmdresp_result;
+ mlan_ioctl_req *pioctl_buf = MNULL;
+ mlan_callbacks *pcb = (mlan_callbacks *)&pmadapter->callbacks;
+#ifdef DEBUG_LEVEL1
+ t_u32 sec = 0, usec = 0;
+#endif
+ t_u32 i;
+
+ ENTER();
+
+ if (pmadapter->curr_cmd)
+ if (pmadapter->curr_cmd->pioctl_buf != MNULL) {
+ pioctl_buf = (mlan_ioctl_req *)
+ pmadapter->curr_cmd->pioctl_buf;
+ }
+
+ if (!pmadapter->curr_cmd || !pmadapter->curr_cmd->respbuf) {
+ resp = (HostCmd_DS_COMMAND *)pmadapter->upld_buf;
+ resp->command = wlan_le16_to_cpu(resp->command);
+ PRINTM(MERROR, "CMD_RESP: No curr_cmd, 0x%x\n", resp->command);
+ if (pioctl_buf)
+ pioctl_buf->status_code = MLAN_ERROR_CMD_RESP_FAIL;
+ ret = MLAN_STATUS_FAILURE;
+ goto done;
+ }
+
+ DBG_HEXDUMP(MCMD_D, "CMD_RESP",
+ pmadapter->curr_cmd->respbuf->pbuf +
+ pmadapter->curr_cmd->respbuf->data_offset,
+ pmadapter->curr_cmd->respbuf->data_len);
+
+ resp = (HostCmd_DS_COMMAND *)(pmadapter->curr_cmd->respbuf->pbuf +
+ pmadapter->curr_cmd->respbuf->data_offset);
+ orig_cmdresp_no = wlan_le16_to_cpu(resp->command);
+ cmdresp_no = (orig_cmdresp_no & HostCmd_CMD_ID_MASK);
+ if (pmadapter->curr_cmd->cmd_no != cmdresp_no) {
+ PRINTM(MERROR, "cmdresp error: cmd=0x%x cmd_resp=0x%x\n",
+ pmadapter->curr_cmd->cmd_no, cmdresp_no);
+ ret = MLAN_STATUS_FAILURE;
+ goto done;
+ }
+ pmadapter->dnld_cmd_in_secs = 0;
+ /* Now we got response from FW, cancel the command timer */
+ if (pmadapter->cmd_timer_is_set) {
+ /* Cancel command timeout timer */
+ pcb->moal_stop_timer(pmadapter->pmoal_handle,
+ pmadapter->pmlan_cmd_timer);
+ /* Cancel command timeout timer */
+ pmadapter->cmd_timer_is_set = MFALSE;
+ }
+ pmadapter->num_cmd_timeout = 0;
+ wlan_request_cmd_lock(pmadapter);
+ if (pmadapter->curr_cmd->cmd_flag & CMD_F_CANCELED) {
+ cmd_ctrl_node *free_cmd = pmadapter->curr_cmd;
+ pmadapter->curr_cmd = MNULL;
+ PRINTM(MCMND, "CMD_RESP: 0x%x been canceled!\n",
+ wlan_le16_to_cpu(resp->command));
+ if (pioctl_buf)
+ pioctl_buf->status_code = MLAN_ERROR_CMD_CANCEL;
+ wlan_insert_cmd_to_free_q(pmadapter, free_cmd);
+ wlan_release_cmd_lock(pmadapter);
+ ret = MLAN_STATUS_FAILURE;
+ goto done;
+ } else {
+ wlan_release_cmd_lock(pmadapter);
+ }
+ if (pmadapter->curr_cmd->cmd_flag & CMD_F_HOSTCMD) {
+ /* Copy original response back to response buffer */
+ if (pmpriv)
+ wlan_ret_host_cmd(pmpriv, resp, pioctl_buf);
+ }
+ resp->size = wlan_le16_to_cpu(resp->size);
+ resp->seq_num = wlan_le16_to_cpu(resp->seq_num);
+ resp->result = wlan_le16_to_cpu(resp->result);
+
+ /* Get BSS number and corresponding priv */
+ pmpriv = wlan_get_priv_by_id(pmadapter,
+ HostCmd_GET_BSS_NO(resp->seq_num),
+ HostCmd_GET_BSS_TYPE(resp->seq_num));
+ if (!pmpriv)
+ pmpriv = wlan_get_priv(pmadapter, MLAN_BSS_ROLE_ANY);
+ /* Clear RET_BIT from HostCmd */
+ resp->command = (orig_cmdresp_no & HostCmd_CMD_ID_MASK);
+ if (!pmpriv) {
+ ret = MLAN_STATUS_FAILURE;
+ goto done;
+ }
+ cmdresp_no = resp->command;
+
+ cmdresp_result = resp->result;
+
+ /* Save the last command response to debug log */
+ pmadapter->dbg.last_cmd_resp_index =
+ (pmadapter->dbg.last_cmd_resp_index + 1) % DBG_CMD_NUM;
+ pmadapter->dbg.last_cmd_resp_id[pmadapter->dbg.last_cmd_resp_index] =
+ orig_cmdresp_no;
+
+ PRINTM_GET_SYS_TIME(MCMND, &sec, &usec);
+ PRINTM_NETINTF(MCMND, pmadapter->curr_cmd->priv);
+ PRINTM(MCMND,
+ "CMD_RESP (%lu.%06lu): 0x%x, result %d, len %d, seqno 0x%x\n",
+ sec, usec, orig_cmdresp_no, cmdresp_result, resp->size,
+ resp->seq_num);
+
+ if (!(orig_cmdresp_no & HostCmd_RET_BIT)) {
+ PRINTM(MERROR, "CMD_RESP: Invalid response to command!\n");
+ if (pioctl_buf)
+ pioctl_buf->status_code = MLAN_ERROR_FW_CMDRESP;
+ wlan_request_cmd_lock(pmadapter);
+ wlan_insert_cmd_to_free_q(pmadapter, pmadapter->curr_cmd);
+ pmadapter->curr_cmd = MNULL;
+ wlan_release_cmd_lock(pmadapter);
+ ret = MLAN_STATUS_FAILURE;
+ goto done;
+ }
+
+ if (pmadapter->curr_cmd->cmd_flag & CMD_F_HOSTCMD) {
+ pmadapter->curr_cmd->cmd_flag &= ~CMD_F_HOSTCMD;
+ if ((cmdresp_result == HostCmd_RESULT_OK) &&
+ (cmdresp_no == HostCmd_CMD_802_11_HS_CFG_ENH))
+ ret = wlan_ret_802_11_hs_cfg(pmpriv, resp, pioctl_buf);
+ } else {
+ /* handle response */
+ ret = pmpriv->ops.process_cmdresp(pmpriv, cmdresp_no, resp,
+ pioctl_buf);
+ }
+
+ /* Check init command response */
+ if (pmadapter->hw_status == WlanHardwareStatusInitializing ||
+ pmadapter->hw_status == WlanHardwareStatusGetHwSpec) {
+ if (ret == MLAN_STATUS_FAILURE) {
+#ifdef STA_SUPPORT
+ if (pmadapter->pwarm_reset_ioctl_req) {
+ /* warm reset failure */
+ pmadapter->pwarm_reset_ioctl_req->status_code =
+ MLAN_ERROR_CMD_RESP_FAIL;
+ pcb->moal_ioctl_complete(
+ pmadapter->pmoal_handle,
+ pmadapter->pwarm_reset_ioctl_req,
+ MLAN_STATUS_FAILURE);
+ pmadapter->pwarm_reset_ioctl_req = MNULL;
+ goto done;
+ }
+#endif
+ PRINTM(MERROR,
+ "cmd 0x%02x failed during initialization\n",
+ cmdresp_no);
+ wlan_init_fw_complete(pmadapter);
+ goto done;
+ }
+#ifdef STA_SUPPORT
+#ifdef PCIE
+ /* init adma write pointer */
+ if (IS_PCIE(pmadapter->card_type) &&
+ cmdresp_no == HostCmd_CMD_FUNC_SHUTDOWN &&
+ pmadapter->pwarm_reset_ioctl_req) {
+#if defined(PCIE9098) || defined(PCIE9097)
+ if (pmadapter->pcard_pcie->reg->use_adma)
+#endif
+ wlan_pcie_init_fw(pmadapter);
+ }
+#endif
+#endif
+ }
+
+ wlan_request_cmd_lock(pmadapter);
+ if (pmadapter->curr_cmd) {
+ cmd_ctrl_node *free_cmd = pmadapter->curr_cmd;
+ pioctl_buf = (mlan_ioctl_req *)pmadapter->curr_cmd->pioctl_buf;
+ pmadapter->curr_cmd = MNULL;
+ if (pioctl_buf && (ret == MLAN_STATUS_SUCCESS))
+ pioctl_buf->status_code = MLAN_ERROR_NO_ERROR;
+ else if (pioctl_buf && (ret == MLAN_STATUS_FAILURE) &&
+ !pioctl_buf->status_code)
+ pioctl_buf->status_code = MLAN_ERROR_CMD_RESP_FAIL;
+
+ /* Clean up and put current command back to cmd_free_q */
+ wlan_insert_cmd_to_free_q(pmadapter, free_cmd);
+ }
+ wlan_release_cmd_lock(pmadapter);
+
+ if ((pmadapter->hw_status == WlanHardwareStatusInitializing) &&
+ (pmadapter->last_init_cmd == cmdresp_no)) {
+ i = pmpriv->bss_index + 1;
+ while (i < pmadapter->priv_num &&
+ (!(pmpriv_next = pmadapter->priv[i]) ||
+ pmpriv_next->bss_virtual))
+ i++;
+ if (!pmpriv_next || i >= pmadapter->priv_num) {
+#ifdef STA_SUPPORT
+ if (pmadapter->pwarm_reset_ioctl_req) {
+ /* warm reset complete */
+ pmadapter->hw_status = WlanHardwareStatusReady;
+ pcb->moal_ioctl_complete(
+ pmadapter->pmoal_handle,
+ pmadapter->pwarm_reset_ioctl_req,
+ MLAN_STATUS_SUCCESS);
+ pmadapter->pwarm_reset_ioctl_req = MNULL;
+ goto done;
+ }
+#endif
+ pmadapter->hw_status = WlanHardwareStatusInitdone;
+ } else {
+ /* Issue init commands for the next interface */
+ ret = pmpriv_next->ops.init_cmd(pmpriv_next, MFALSE);
+ }
+ } else if ((pmadapter->hw_status == WlanHardwareStatusGetHwSpec) &&
+ (HostCmd_CMD_GET_HW_SPEC == cmdresp_no)) {
+ pmadapter->hw_status = WlanHardwareStatusGetHwSpecdone;
+ }
+done:
+ LEAVE();
+ return ret;
+}
+
+/**
+ * @brief This function handles the timeout of command sending.
+ * It will re-send the same command again.
+ *
+ * @param function_context A pointer to function_context
+ * @return N/A
+ */
+t_void wlan_cmd_timeout_func(t_void *function_context)
+{
+ mlan_adapter *pmadapter = (mlan_adapter *)function_context;
+ cmd_ctrl_node *pcmd_node = MNULL;
+ mlan_ioctl_req *pioctl_buf = MNULL;
+#ifdef DEBUG_LEVEL1
+ t_u32 sec = 0, usec = 0;
+#endif
+#if defined(SDIO) || defined(PCIE)
+ t_u8 i;
+#endif
+ mlan_private *pmpriv = MNULL;
+
+ ENTER();
+
+ pmadapter->cmd_timer_is_set = MFALSE;
+ if (!pmadapter->curr_cmd) {
+ if (pmadapter->ext_scan && pmadapter->ext_scan_enh &&
+ pmadapter->scan_processing) {
+ PRINTM(MMSG, "Ext scan enh timeout\n");
+ pmadapter->ext_scan_timeout = MTRUE;
+ wlan_dump_info(pmadapter, REASON_CODE_EXT_SCAN_TIMEOUT);
+ goto exit;
+ }
+ PRINTM(MWARN, "CurCmd Empty\n");
+ goto exit;
+ }
+ pmadapter->num_cmd_timeout++;
+ pcmd_node = pmadapter->curr_cmd;
+ if (pcmd_node->pioctl_buf != MNULL) {
+ pioctl_buf = (mlan_ioctl_req *)pcmd_node->pioctl_buf;
+ pioctl_buf->status_code = MLAN_ERROR_CMD_TIMEOUT;
+ }
+
+ pmadapter->dbg.timeout_cmd_id =
+ pmadapter->dbg.last_cmd_id[pmadapter->dbg.last_cmd_index];
+ pmadapter->dbg.timeout_cmd_act =
+ pmadapter->dbg.last_cmd_act[pmadapter->dbg.last_cmd_index];
+ PRINTM_GET_SYS_TIME(MERROR, &sec, &usec);
+ PRINTM(MERROR, "Timeout cmd id (%lu.%06lu) = 0x%x, act = 0x%x\n", sec,
+ usec, pmadapter->dbg.timeout_cmd_id,
+ pmadapter->dbg.timeout_cmd_act);
+#if defined(SDIO) || defined(PCIE)
+ if (!IS_USB(pmadapter->card_type) && pcmd_node->cmdbuf) {
+ t_u8 *pcmd_buf;
+ pcmd_buf = pcmd_node->cmdbuf->pbuf +
+ pcmd_node->cmdbuf->data_offset +
+ pmadapter->ops.intf_header_len;
+ for (i = 0; i < 16; i++)
+ PRINTM(MERROR, "%02x ", *pcmd_buf++);
+ PRINTM(MERROR, "\n");
+ }
+#endif
+#ifdef PCIE
+ if (IS_PCIE(pmadapter->card_type))
+ pmadapter->ops.debug_dump(pmadapter);
+#endif
+ pmpriv = pcmd_node->priv;
+ if (pmpriv)
+ PRINTM(MERROR, "BSS type = %d BSS role= %d\n", pmpriv->bss_type,
+ pmpriv->bss_role);
+ wlan_dump_info(pmadapter, REASON_CODE_CMD_TIMEOUT);
+
+ if (pmadapter->hw_status == WlanHardwareStatusInitializing ||
+ pmadapter->hw_status == WlanHardwareStatusGetHwSpec)
+ wlan_init_fw_complete(pmadapter);
+ else {
+ /* Signal MOAL to perform extra handling for debugging */
+ if (pmpriv) {
+ wlan_recv_event(pmpriv, MLAN_EVENT_ID_DRV_DBG_DUMP,
+ MNULL);
+ } else {
+ wlan_recv_event(wlan_get_priv(pmadapter,
+ MLAN_BSS_ROLE_ANY),
+ MLAN_EVENT_ID_DRV_DBG_DUMP, MNULL);
+ }
+ }
+
+exit:
+ LEAVE();
+ return;
+}
+
+#ifdef STA_SUPPORT
+/**
+ * @brief Internal function used to flush the scan pending queue
+ *
+ * @param pmadapter A pointer to mlan_adapter structure
+ *
+ * @return N/A
+ */
+t_void wlan_flush_scan_queue(pmlan_adapter pmadapter)
+{
+ cmd_ctrl_node *pcmd_node = MNULL;
+
+ ENTER();
+
+ wlan_request_cmd_lock(pmadapter);
+ while ((pcmd_node = (cmd_ctrl_node *)util_peek_list(
+ pmadapter->pmoal_handle, &pmadapter->scan_pending_q,
+ MNULL, MNULL))) {
+ util_unlink_list(pmadapter->pmoal_handle,
+ &pmadapter->scan_pending_q,
+ (pmlan_linked_list)pcmd_node, MNULL, MNULL);
+ pcmd_node->pioctl_buf = MNULL;
+ wlan_insert_cmd_to_free_q(pmadapter, pcmd_node);
+ }
+
+ pmadapter->scan_processing = MFALSE;
+ wlan_release_cmd_lock(pmadapter);
+
+ LEAVE();
+}
+
+/**
+ * @brief Cancel pending SCAN ioctl cmd.
+ *
+ * @param pmadapter A pointer to mlan_adapter
+ * @param pioctl_req A pointer to pmlan_ioctl_req
+ *
+ * @return MLAN_STATUS_SUCCESS/MLAN_STATUS_PENDING
+ */
+mlan_status wlan_cancel_pending_scan_cmd(pmlan_adapter pmadapter,
+ pmlan_ioctl_req pioctl_req)
+{
+ pmlan_callbacks pcb = &pmadapter->callbacks;
+ cmd_ctrl_node *pcmd_node = MNULL;
+ mlan_ioctl_req *pioctl_buf = MNULL;
+ pmlan_private priv = MNULL;
+ mlan_status status = MLAN_STATUS_SUCCESS;
+ ENTER();
+
+ PRINTM(MIOCTL, "Cancel scan command\n");
+ wlan_request_cmd_lock(pmadapter);
+ /* IOCTL will be completed, avoid calling IOCTL complete again from
+ * EVENT/CMDRESP */
+ if (pmadapter->pscan_ioctl_req) {
+ pioctl_buf = pmadapter->pscan_ioctl_req;
+ priv = pmadapter->priv[pioctl_buf->bss_index];
+ pmadapter->pscan_ioctl_req = MNULL;
+ pioctl_buf->status_code = MLAN_ERROR_CMD_CANCEL;
+ pcb->moal_ioctl_complete(pmadapter->pmoal_handle, pioctl_buf,
+ MLAN_STATUS_FAILURE);
+ }
+
+ if (pmadapter->curr_cmd && pmadapter->curr_cmd->pioctl_buf) {
+ pioctl_buf = (mlan_ioctl_req *)pmadapter->curr_cmd->pioctl_buf;
+ if (pioctl_buf->req_id == MLAN_IOCTL_SCAN) {
+ PRINTM(MIOCTL, "wlan_cancel_scan: current command\n");
+ pcmd_node = pmadapter->curr_cmd;
+ pcmd_node->pioctl_buf = MNULL;
+ pcmd_node->cmd_flag |= CMD_F_CANCELED;
+ pioctl_buf->status_code = MLAN_ERROR_CMD_CANCEL;
+ pcb->moal_ioctl_complete(pmadapter->pmoal_handle,
+ pioctl_buf,
+ MLAN_STATUS_FAILURE);
+ }
+ }
+ while ((pcmd_node = wlan_get_pending_scan_cmd(pmadapter)) != MNULL) {
+ PRINTM(MIOCTL,
+ "wlan_cancel_scan: find scan command in cmd_pending_q\n");
+ util_unlink_list(pmadapter->pmoal_handle,
+ &pmadapter->cmd_pending_q,
+ (pmlan_linked_list)pcmd_node, MNULL, MNULL);
+ wlan_insert_cmd_to_free_q(pmadapter, pcmd_node);
+ }
+ wlan_release_cmd_lock(pmadapter);
+ if (pmadapter->scan_processing &&
+ pmadapter->ext_scan_type == EXT_SCAN_ENHANCE) {
+ if (priv) {
+ if (MLAN_STATUS_FAILURE ==
+ wlan_prepare_cmd(priv, HostCmd_CMD_802_11_SCAN_EXT,
+ HostCmd_ACT_GEN_SET, 0, pioctl_req,
+ MNULL))
+ PRINTM(MERROR, "Failed to prepare command");
+ wlan_recv_event(priv, MLAN_EVENT_ID_DRV_DEFER_HANDLING,
+ MNULL);
+ status = MLAN_STATUS_PENDING;
+ }
+ } else
+ /* Cancel all pending scan command */
+ wlan_flush_scan_queue(pmadapter);
+ LEAVE();
+ return status;
+}
+#endif
+
+/**
+ * @brief Cancel all pending cmd.
+ *
+ * @param pmadapter A pointer to mlan_adapter
+ * @param flag MTRUE/MFALSE
+ *
+ * @return N/A
+ */
+t_void wlan_cancel_all_pending_cmd(pmlan_adapter pmadapter, t_u8 flag)
+{
+ cmd_ctrl_node *pcmd_node = MNULL;
+ pmlan_callbacks pcb = &pmadapter->callbacks;
+ mlan_ioctl_req *pioctl_buf = MNULL;
+#ifdef STA_SUPPORT
+ pmlan_private priv = MNULL;
+#endif
+ ENTER();
+ /* Cancel current cmd */
+ wlan_request_cmd_lock(pmadapter);
+#ifdef STA_SUPPORT
+ /* IOCTL will be completed, avoid calling IOCTL complete again from
+ * EVENT/CMDRESP */
+ if (pmadapter->pscan_ioctl_req) {
+ pioctl_buf = pmadapter->pscan_ioctl_req;
+ priv = pmadapter->priv[pioctl_buf->bss_index];
+ pmadapter->pscan_ioctl_req = MNULL;
+ pioctl_buf->status_code = MLAN_ERROR_CMD_CANCEL;
+ pcb->moal_ioctl_complete(pmadapter->pmoal_handle, pioctl_buf,
+ MLAN_STATUS_FAILURE);
+ }
+#endif
+ if (pmadapter->curr_cmd && flag) {
+ pcmd_node = pmadapter->curr_cmd;
+ if (pcmd_node->pioctl_buf) {
+ pioctl_buf = (mlan_ioctl_req *)pcmd_node->pioctl_buf;
+ pioctl_buf->status_code = MLAN_ERROR_CMD_CANCEL;
+ pcb->moal_ioctl_complete(pmadapter->pmoal_handle,
+ pioctl_buf,
+ MLAN_STATUS_FAILURE);
+ pcmd_node->pioctl_buf = MNULL;
+ }
+ pmadapter->curr_cmd = MNULL;
+ wlan_insert_cmd_to_free_q(pmadapter, pcmd_node);
+ }
+
+ /* Cancel all pending command */
+ while ((pcmd_node = (cmd_ctrl_node *)util_peek_list(
+ pmadapter->pmoal_handle, &pmadapter->cmd_pending_q,
+ MNULL, MNULL))) {
+ util_unlink_list(pmadapter->pmoal_handle,
+ &pmadapter->cmd_pending_q,
+ (pmlan_linked_list)pcmd_node, MNULL, MNULL);
+ if (pcmd_node->pioctl_buf) {
+ pioctl_buf = (mlan_ioctl_req *)pcmd_node->pioctl_buf;
+ pioctl_buf->status_code = MLAN_ERROR_CMD_CANCEL;
+ pcb->moal_ioctl_complete(pmadapter->pmoal_handle,
+ pioctl_buf,
+ MLAN_STATUS_FAILURE);
+ pcmd_node->pioctl_buf = MNULL;
+ }
+ wlan_insert_cmd_to_free_q(pmadapter, pcmd_node);
+ }
+ wlan_release_cmd_lock(pmadapter);
+#ifdef STA_SUPPORT
+ if (pmadapter->scan_processing &&
+ pmadapter->ext_scan_type == EXT_SCAN_ENHANCE) {
+ if (priv) {
+ if (MLAN_STATUS_FAILURE ==
+ wlan_prepare_cmd(priv, HostCmd_CMD_802_11_SCAN_EXT,
+ HostCmd_ACT_GEN_SET, 0, MNULL,
+ MNULL))
+ PRINTM(MERROR, "Failed to prepare command");
+ wlan_recv_event(priv, MLAN_EVENT_ID_DRV_DEFER_HANDLING,
+ MNULL);
+ }
+ } else
+ /* Cancel all pending scan command */
+ wlan_flush_scan_queue(pmadapter);
+#endif
+ LEAVE();
+}
+
+/**
+ * @brief Cancel specific bss's pending ioctl cmd.
+ *
+ * @param pmadapter A pointer to mlan_adapter
+ * @param bss_index BSS index
+ *
+ * @return N/A
+ */
+t_void wlan_cancel_bss_pending_cmd(pmlan_adapter pmadapter, t_u32 bss_index)
+{
+ pmlan_callbacks pcb = &pmadapter->callbacks;
+ cmd_ctrl_node *pcmd_node = MNULL;
+ mlan_ioctl_req *pioctl_buf = MNULL;
+#ifdef STA_SUPPORT
+ t_u8 flash_scan = MFALSE;
+#endif
+#ifdef STA_SUPPORT
+ pmlan_private priv = MNULL;
+#endif
+ ENTER();
+
+ PRINTM(MIOCTL, "MOAL Cancel BSS IOCTL: bss_index=%d\n", (int)bss_index);
+ wlan_request_cmd_lock(pmadapter);
+#ifdef STA_SUPPORT
+ if (pmadapter->pscan_ioctl_req &&
+ (pmadapter->pscan_ioctl_req->bss_index == bss_index)) {
+ /* IOCTL will be completed, avoid calling IOCTL complete again
+ * from EVENT/CMDRESP */
+ flash_scan = MTRUE;
+ pioctl_buf = pmadapter->pscan_ioctl_req;
+ priv = pmadapter->priv[pioctl_buf->bss_index];
+ pmadapter->pscan_ioctl_req = MNULL;
+ pioctl_buf->status_code = MLAN_ERROR_CMD_CANCEL;
+ pcb->moal_ioctl_complete(pmadapter->pmoal_handle, pioctl_buf,
+ MLAN_STATUS_FAILURE);
+ }
+#endif
+ if (pmadapter->curr_cmd && pmadapter->curr_cmd->pioctl_buf) {
+ pioctl_buf = (mlan_ioctl_req *)pmadapter->curr_cmd->pioctl_buf;
+ if (pioctl_buf->bss_index == bss_index) {
+ pcmd_node = pmadapter->curr_cmd;
+ pcmd_node->pioctl_buf = MNULL;
+ pcmd_node->cmd_flag |= CMD_F_CANCELED;
+#ifdef STA_SUPPORT
+ if (pioctl_buf->req_id == MLAN_IOCTL_SCAN)
+ flash_scan = MTRUE;
+#endif
+ pioctl_buf->status_code = MLAN_ERROR_CMD_CANCEL;
+ pcb->moal_ioctl_complete(pmadapter->pmoal_handle,
+ pioctl_buf,
+ MLAN_STATUS_FAILURE);
+ }
+ }
+ while ((pcmd_node = wlan_get_bss_pending_ioctl_cmd(
+ pmadapter, bss_index)) != MNULL) {
+ util_unlink_list(pmadapter->pmoal_handle,
+ &pmadapter->cmd_pending_q,
+ (pmlan_linked_list)pcmd_node, MNULL, MNULL);
+ pioctl_buf = (mlan_ioctl_req *)pcmd_node->pioctl_buf;
+ pcmd_node->pioctl_buf = MNULL;
+#ifdef STA_SUPPORT
+ if (pioctl_buf->req_id == MLAN_IOCTL_SCAN)
+ flash_scan = MTRUE;
+#endif
+ pioctl_buf->status_code = MLAN_ERROR_CMD_CANCEL;
+ pcb->moal_ioctl_complete(pmadapter->pmoal_handle, pioctl_buf,
+ MLAN_STATUS_FAILURE);
+ wlan_insert_cmd_to_free_q(pmadapter, pcmd_node);
+ }
+ wlan_release_cmd_lock(pmadapter);
+#ifdef STA_SUPPORT
+ if (flash_scan) {
+ if (pmadapter->scan_processing &&
+ pmadapter->ext_scan_type == EXT_SCAN_ENHANCE) {
+ if (priv) {
+ if (MLAN_STATUS_FAILURE ==
+ wlan_prepare_cmd(
+ priv, HostCmd_CMD_802_11_SCAN_EXT,
+ HostCmd_ACT_GEN_SET, 0, MNULL,
+ MNULL))
+ PRINTM(MERROR,
+ "failed to prepare command");
+ wlan_recv_event(
+ priv, MLAN_EVENT_ID_DRV_DEFER_HANDLING,
+ MNULL);
+ }
+ } else
+ /* Cancel all pending scan command */
+ wlan_flush_scan_queue(pmadapter);
+ }
+#endif
+ LEAVE();
+ return;
+}
+
+/**
+ * @brief Cancel pending ioctl cmd.
+ *
+ * @param pmadapter A pointer to mlan_adapter
+ * @param pioctl_req A pointer to mlan_ioctl_req buf
+ *
+ * @return N/A
+ */
+t_void wlan_cancel_pending_ioctl(pmlan_adapter pmadapter,
+ pmlan_ioctl_req pioctl_req)
+{
+ pmlan_callbacks pcb = &pmadapter->callbacks;
+ cmd_ctrl_node *pcmd_node = MNULL;
+ t_u8 find = MFALSE;
+#ifdef STA_SUPPORT
+ pmlan_private priv = MNULL;
+#endif
+
+ ENTER();
+
+ PRINTM(MIOCTL, "MOAL Cancel IOCTL: 0x%x sub_id=0x%x action=%d\n",
+ pioctl_req->req_id, *((t_u32 *)pioctl_req->pbuf),
+ (int)pioctl_req->action);
+
+ wlan_request_cmd_lock(pmadapter);
+#ifdef STA_SUPPORT
+ /* IOCTL will be completed, avoid calling IOCTL complete again from
+ * EVENT/CMDRESP */
+ if (pmadapter->pscan_ioctl_req == pioctl_req) {
+ priv = pmadapter->priv[pioctl_req->bss_index];
+ pmadapter->pscan_ioctl_req = MNULL;
+ find = MTRUE;
+ }
+#endif
+ if ((pmadapter->curr_cmd) &&
+ (pmadapter->curr_cmd->pioctl_buf == pioctl_req)) {
+ pcmd_node = pmadapter->curr_cmd;
+ pcmd_node->pioctl_buf = MNULL;
+ pcmd_node->cmd_flag |= CMD_F_CANCELED;
+ find = MTRUE;
+ }
+
+ while ((pcmd_node = wlan_get_pending_ioctl_cmd(pmadapter,
+ pioctl_req)) != MNULL) {
+ util_unlink_list(pmadapter->pmoal_handle,
+ &pmadapter->cmd_pending_q,
+ (pmlan_linked_list)pcmd_node, MNULL, MNULL);
+ pcmd_node->pioctl_buf = MNULL;
+ find = MTRUE;
+ wlan_insert_cmd_to_free_q(pmadapter, pcmd_node);
+ }
+ wlan_release_cmd_lock(pmadapter);
+#ifdef STA_SUPPORT
+ if (pioctl_req->req_id == MLAN_IOCTL_SCAN) {
+ if (pmadapter->scan_processing &&
+ pmadapter->ext_scan_type == EXT_SCAN_ENHANCE) {
+ if (priv) {
+ if (MLAN_STATUS_FAILURE ==
+ wlan_prepare_cmd(
+ priv, HostCmd_CMD_802_11_SCAN_EXT,
+ HostCmd_ACT_GEN_SET, 0, MNULL,
+ MNULL))
+ PRINTM(MERROR,
+ "Failed to prepare command");
+ wlan_recv_event(
+ priv, MLAN_EVENT_ID_DRV_DEFER_HANDLING,
+ MNULL);
+ }
+ } else
+ /* Cancel all pending scan command */
+ wlan_flush_scan_queue(pmadapter);
+ }
+#endif
+ if (find) {
+ pioctl_req->status_code = MLAN_ERROR_CMD_CANCEL;
+ pcb->moal_ioctl_complete(pmadapter->pmoal_handle, pioctl_req,
+ MLAN_STATUS_FAILURE);
+ }
+
+ LEAVE();
+ return;
+}
+
+/**
+ * @brief This function convert mlan_wifi_rate to wifi_rate.
+ *
+ * @param pmpriv A pointer to mlan_private structure
+ * @param pmlan_rate A pointer to mlan_wifi_rate structure
+ * @param prate A pointer to wifi_rate
+ *
+ * @return N/A
+ */
+t_void wlan_fill_hal_wifi_rate(pmlan_private pmpriv, mlan_wifi_rate *pmlan_rate,
+ wifi_rate *prate)
+{
+ t_u8 index = 0;
+ t_u8 rate_info = 0;
+
+ ENTER();
+
+ prate->preamble = pmlan_rate->preamble;
+ prate->nss = pmlan_rate->nss;
+ prate->bw = pmlan_rate->bw;
+ prate->rateMcsIdx = pmlan_rate->rateMcsIdx;
+ prate->reserved = 0;
+ prate->bitrate = wlan_le32_to_cpu(pmlan_rate->bitrate);
+
+ if (!prate->bitrate) {
+ index = prate->rateMcsIdx;
+ index |= prate->nss << 4;
+ if (prate->preamble == WIFI_PREAMBLE_HT)
+ rate_info = MLAN_RATE_FORMAT_HT;
+ else if (prate->preamble == WIFI_PREAMBLE_VHT)
+ rate_info = MLAN_RATE_FORMAT_VHT;
+ else
+ rate_info = MLAN_RATE_FORMAT_LG;
+ rate_info |= prate->bw << 2;
+ PRINTM(MCMND, "index=0x%x rate_info=0x%x\n", index, rate_info);
+ /** For rateMcsIdx, OFDM/CCK rate code would be as per ieee std
+ * in the units of 0.5mbps. HT/VHT it would be mcs index */
+ /** For bitrate, in 100kbps */
+ if (rate_info == MLAN_RATE_FORMAT_LG)
+ prate->bitrate = prate->rateMcsIdx * 5;
+ else
+ prate->bitrate =
+ wlan_index_to_data_rate(pmpriv->adapter, index,
+ rate_info, 0) *
+ 5;
+ PRINTM(MCMND, "bitrate(in 100kbps)=%d\n", prate->bitrate);
+ }
+
+ LEAVE();
+}
+
+/**
+ * @brief Handle the version_ext resp
+ *
+ * @param pmpriv A pointer to mlan_private structure
+ * @param resp A pointer to HostCmd_DS_COMMAND
+ * @param pioctl_buf A pointer to mlan_ioctl_req structure
+ *
+ * @return MLAN_STATUS_SUCCESS
+ */
+mlan_status wlan_ret_ver_ext(pmlan_private pmpriv, HostCmd_DS_COMMAND *resp,
+ mlan_ioctl_req *pioctl_buf)
+{
+ HostCmd_DS_VERSION_EXT *ver_ext = &resp->params.verext;
+ mlan_ds_get_info *info;
+ ENTER();
+ if (pioctl_buf) {
+ info = (mlan_ds_get_info *)pioctl_buf->pbuf;
+ info->param.ver_ext.version_str_sel = ver_ext->version_str_sel;
+ memcpy_ext(pmpriv->adapter, info->param.ver_ext.version_str,
+ ver_ext->version_str, sizeof(char) * 128,
+ sizeof(char) * MLAN_MAX_VER_STR_LEN);
+ }
+ LEAVE();
+ return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ * @brief Handle the rx mgmt forward registration resp
+ *
+ * @param pmpriv A pointer to mlan_private structure
+ * @param resp A pointer to HostCmd_DS_COMMAND
+ * @param pioctl_buf A pointer to mlan_ioctl_req structure
+ *
+ * @return MLAN_STATUS_SUCCESS
+ */
+mlan_status wlan_ret_rx_mgmt_ind(pmlan_private pmpriv, HostCmd_DS_COMMAND *resp,
+ mlan_ioctl_req *pioctl_buf)
+{
+ mlan_ds_misc_cfg *misc = MNULL;
+ ENTER();
+
+ if (pioctl_buf) {
+ misc = (mlan_ds_misc_cfg *)pioctl_buf->pbuf;
+ misc->param.mgmt_subtype_mask = wlan_le32_to_cpu(
+ resp->params.rx_mgmt_ind.mgmt_subtype_mask);
+ }
+
+ LEAVE();
+ return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ * @brief This function checks conditions and prepares to
+ * send sleep confirm command to firmware if OK.
+ *
+ * @param pmadapter A pointer to mlan_adapter structure
+ *
+ * @return N/A
+ */
+t_void wlan_check_ps_cond(mlan_adapter *pmadapter)
+{
+ ENTER();
+
+ if (!pmadapter->cmd_sent && !pmadapter->curr_cmd &&
+ !pmadapter->keep_wakeup && !wlan_is_tx_pending(pmadapter) &&
+ !IS_CARD_RX_RCVD(pmadapter)) {
+ wlan_dnld_sleep_confirm_cmd(pmadapter);
+ } else {
+ PRINTM(MCMND, "Delay Sleep Confirm (%s%s%s%s)\n",
+ (pmadapter->cmd_sent) ? "D" : "",
+ (pmadapter->curr_cmd) ? "C" : "",
+ (wlan_is_tx_pending(pmadapter)) ? "T" : "",
+ (IS_CARD_RX_RCVD(pmadapter)) ? "R" : "");
+ }
+
+ LEAVE();
+}
+
+/**
+ * @brief This function sends the HS_ACTIVATED event to the application
+ *
+ * @param priv A pointer to mlan_private structure
+ * @param activated MTRUE if activated, MFALSE if de-activated
+ *
+ * @return N/A
+ */
+t_void wlan_host_sleep_activated_event(pmlan_private priv, t_u8 activated)
+{
+ ENTER();
+
+ if (!priv) {
+ LEAVE();
+ return;
+ }
+
+ if (activated) {
+ if (priv->adapter->is_hs_configured) {
+ priv->adapter->hs_activated = MTRUE;
+ wlan_update_rxreorder_tbl(priv->adapter, MTRUE);
+ PRINTM(MEVENT, "hs_activated\n");
+ wlan_recv_event(priv, MLAN_EVENT_ID_DRV_HS_ACTIVATED,
+ MNULL);
+ } else
+ PRINTM(MWARN, "hs_activated: HS not configured !!!\n");
+ } else {
+ PRINTM(MEVENT, "hs_deactived\n");
+ priv->adapter->hs_activated = MFALSE;
+ wlan_recv_event(priv, MLAN_EVENT_ID_DRV_HS_DEACTIVATED, MNULL);
+ }
+
+ LEAVE();
+ return;
+}
+
+/**
+ * @brief This function sends the HS_WAKEUP event to the application
+ *
+ * @param priv A pointer to mlan_private structure
+ *
+ * @return N/A
+ */
+t_void wlan_host_sleep_wakeup_event(pmlan_private priv)
+{
+ ENTER();
+
+ if (priv->adapter->is_hs_configured)
+ wlan_recv_event(priv, MLAN_EVENT_ID_FW_HS_WAKEUP, MNULL);
+ else
+ PRINTM(MWARN, "hs_wakeup: Host Sleep not configured !!!\n");
+
+ LEAVE();
+}
+
+/**
+ * @brief This function handles the command response of hs_cfg
+ *
+ * @param pmpriv A pointer to mlan_private structure
+ * @param resp A pointer to HostCmd_DS_COMMAND
+ * @param pioctl_buf A pointer to mlan_ioctl_req structure
+ *
+ * @return MLAN_STATUS_SUCCESS
+ */
+mlan_status wlan_ret_802_11_hs_cfg(pmlan_private pmpriv,
+ HostCmd_DS_COMMAND *resp,
+ mlan_ioctl_req *pioctl_buf)
+{
+ pmlan_adapter pmadapter = pmpriv->adapter;
+ HostCmd_DS_802_11_HS_CFG_ENH *phs_cfg = &resp->params.opt_hs_cfg;
+
+ ENTER();
+
+ phs_cfg->params.hs_config.conditions =
+ wlan_le32_to_cpu(phs_cfg->params.hs_config.conditions);
+ phs_cfg->action = wlan_le16_to_cpu(phs_cfg->action);
+ PRINTM(MCMND,
+ "CMD_RESP: HS_CFG cmd reply result=%#x,"
+ " action=0x%x conditions=0x%x gpio=0x%x gap=0x%x\n",
+ resp->result, phs_cfg->action,
+ phs_cfg->params.hs_config.conditions,
+ phs_cfg->params.hs_config.gpio, phs_cfg->params.hs_config.gap);
+ if ((phs_cfg->action == HS_ACTIVATE &&
+ !pmadapter->pcard_info->supp_ps_handshake) ||
+ pmadapter->pcard_info->supp_ps_handshake) {
+ /* clean up curr_cmd to allow suspend */
+ if (pioctl_buf)
+ pioctl_buf->status_code = MLAN_ERROR_NO_ERROR;
+ /* Clean up and put current command back to cmd_free_q */
+ wlan_request_cmd_lock(pmadapter);
+ wlan_insert_cmd_to_free_q(pmadapter, pmadapter->curr_cmd);
+ pmadapter->curr_cmd = MNULL;
+ wlan_release_cmd_lock(pmadapter);
+ if (!pmadapter->pcard_info->supp_ps_handshake) {
+ wlan_host_sleep_activated_event(pmpriv, MTRUE);
+ goto done;
+ }
+ }
+ if (phs_cfg->params.hs_config.conditions != HOST_SLEEP_CFG_CANCEL) {
+ pmadapter->is_hs_configured = MTRUE;
+ if (pmadapter->pcard_info->supp_ps_handshake)
+ wlan_host_sleep_activated_event(pmpriv, MTRUE);
+ } else {
+ pmadapter->is_hs_configured = MFALSE;
+ if (pmadapter->hs_activated)
+ wlan_host_sleep_activated_event(pmpriv, MFALSE);
+ }
+
+done:
+ LEAVE();
+ return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ * @brief Perform hs related activities on receiving the power up interrupt
+ *
+ * @param pmadapter A pointer to the adapter structure
+ * @return N/A
+ */
+t_void wlan_process_hs_config(pmlan_adapter pmadapter)
+{
+ ENTER();
+ PRINTM(MINFO, "Recevie interrupt/data in HS mode\n");
+ if (pmadapter->hs_cfg.gap == HOST_SLEEP_CFG_GAP_FF)
+ pmadapter->ops.wakeup_card(pmadapter, MTRUE);
+ LEAVE();
+ return;
+}
+
+/**
+ * @brief Check sleep confirm command response and set the state to ASLEEP
+ *
+ * @param pmadapter A pointer to the adapter structure
+ * @param pbuf A pointer to the command response buffer
+ * @param upld_len Command response buffer length
+ * @return N/A
+ */
+void wlan_process_sleep_confirm_resp(pmlan_adapter pmadapter, t_u8 *pbuf,
+ t_u32 upld_len)
+{
+ HostCmd_DS_COMMAND *cmd;
+ pmlan_private pmpriv;
+
+ ENTER();
+
+ if (!upld_len) {
+ PRINTM(MERROR, "Command size is 0\n");
+ LEAVE();
+ return;
+ }
+ cmd = (HostCmd_DS_COMMAND *)pbuf;
+ cmd->result = wlan_le16_to_cpu(cmd->result);
+ cmd->command = wlan_le16_to_cpu(cmd->command);
+ cmd->seq_num = wlan_le16_to_cpu(cmd->seq_num);
+
+ pmpriv =
+ wlan_get_priv_by_id(pmadapter, HostCmd_GET_BSS_NO(cmd->seq_num),
+ HostCmd_GET_BSS_TYPE(cmd->seq_num));
+ /* Update sequence number */
+ cmd->seq_num = HostCmd_GET_SEQ_NO(cmd->seq_num);
+ /* Clear RET_BIT from HostCmd */
+ cmd->command &= HostCmd_CMD_ID_MASK;
+ if (!pmpriv)
+ pmpriv = wlan_get_priv(pmadapter, MLAN_BSS_ROLE_ANY);
+ if (cmd->command != HostCmd_CMD_802_11_PS_MODE_ENH) {
+ PRINTM(MERROR,
+ "Received unexpected response for command %x, result = %x\n",
+ cmd->command, cmd->result);
+ LEAVE();
+ return;
+ }
+ PRINTM_NETINTF(MEVENT, pmpriv);
+ PRINTM(MEVENT, "#\n");
+ if (cmd->result != MLAN_STATUS_SUCCESS) {
+ PRINTM(MERROR, "Sleep confirm command failed\n");
+ pmadapter->pm_wakeup_card_req = MFALSE;
+ pmadapter->ps_state = PS_STATE_AWAKE;
+ LEAVE();
+ return;
+ }
+ pmadapter->pm_wakeup_card_req = MTRUE;
+
+ if (pmadapter->is_hs_configured) {
+ wlan_host_sleep_activated_event(
+ wlan_get_priv(pmadapter, MLAN_BSS_ROLE_ANY), MTRUE);
+ }
+ pmadapter->ps_state = PS_STATE_SLEEP;
+ LEAVE();
+}
+
+/**
+ * @brief This function prepares command of power mode
+ *
+ * @param pmpriv A pointer to mlan_private structure
+ * @param cmd A pointer to HostCmd_DS_COMMAND structure
+ * @param cmd_action the action: GET or SET
+ * @param ps_bitmap PS bitmap
+ * @param pdata_buf A pointer to data buffer
+ * @return MLAN_STATUS_SUCCESS
+ */
+mlan_status wlan_cmd_enh_power_mode(pmlan_private pmpriv,
+ HostCmd_DS_COMMAND *cmd, t_u16 cmd_action,
+ t_u16 ps_bitmap, t_void *pdata_buf)
+{
+ HostCmd_DS_802_11_PS_MODE_ENH *psmode_enh = &cmd->params.psmode_enh;
+ t_u8 *tlv = MNULL;
+ t_u16 cmd_size = 0;
+
+ ENTER();
+
+ PRINTM(MCMND, "PS Command: action = 0x%x, bitmap = 0x%x\n", cmd_action,
+ ps_bitmap);
+
+ cmd->command = wlan_cpu_to_le16(HostCmd_CMD_802_11_PS_MODE_ENH);
+ if (cmd_action == DIS_AUTO_PS) {
+ psmode_enh->action = wlan_cpu_to_le16(DIS_AUTO_PS);
+ psmode_enh->params.ps_bitmap = wlan_cpu_to_le16(ps_bitmap);
+ cmd->size = wlan_cpu_to_le16(S_DS_GEN + AUTO_PS_FIX_SIZE);
+ } else if (cmd_action == GET_PS) {
+ psmode_enh->action = wlan_cpu_to_le16(GET_PS);
+ psmode_enh->params.ps_bitmap = wlan_cpu_to_le16(ps_bitmap);
+ cmd->size = wlan_cpu_to_le16(S_DS_GEN + AUTO_PS_FIX_SIZE);
+ } else if (cmd_action == EN_AUTO_PS) {
+ psmode_enh->action = wlan_cpu_to_le16(EN_AUTO_PS);
+ psmode_enh->params.auto_ps.ps_bitmap =
+ wlan_cpu_to_le16(ps_bitmap);
+ cmd_size = S_DS_GEN + AUTO_PS_FIX_SIZE;
+ tlv = (t_u8 *)cmd + cmd_size;
+ if (ps_bitmap & BITMAP_STA_PS) {
+ pmlan_adapter pmadapter = pmpriv->adapter;
+ MrvlIEtypes_ps_param_t *ps_tlv =
+ (MrvlIEtypes_ps_param_t *)tlv;
+ ps_param *ps_mode = &ps_tlv->param;
+ ps_tlv->header.type =
+ wlan_cpu_to_le16(TLV_TYPE_PS_PARAM);
+ ps_tlv->header.len = wlan_cpu_to_le16(
+ sizeof(MrvlIEtypes_ps_param_t) -
+ sizeof(MrvlIEtypesHeader_t));
+ cmd_size += sizeof(MrvlIEtypes_ps_param_t);
+ tlv += sizeof(MrvlIEtypes_ps_param_t);
+ ps_mode->null_pkt_interval =
+ wlan_cpu_to_le16(pmadapter->null_pkt_interval);
+ ps_mode->multiple_dtims =
+ wlan_cpu_to_le16(pmadapter->multiple_dtim);
+ ps_mode->bcn_miss_timeout =
+ wlan_cpu_to_le16(pmadapter->bcn_miss_time_out);
+ ps_mode->local_listen_interval = wlan_cpu_to_le16(
+ pmadapter->local_listen_interval);
+ ps_mode->delay_to_ps =
+ wlan_cpu_to_le16(pmadapter->delay_to_ps);
+ ps_mode->mode =
+ wlan_cpu_to_le16(pmadapter->enhanced_ps_mode);
+ }
+ if (ps_bitmap & BITMAP_BCN_TMO) {
+ MrvlIEtypes_bcn_timeout_t *bcn_tmo_tlv =
+ (MrvlIEtypes_bcn_timeout_t *)tlv;
+ mlan_ds_bcn_timeout *bcn_tmo =
+ (mlan_ds_bcn_timeout *)pdata_buf;
+ bcn_tmo_tlv->header.type =
+ wlan_cpu_to_le16(TLV_TYPE_BCN_TIMEOUT);
+ bcn_tmo_tlv->header.len = wlan_cpu_to_le16(
+ sizeof(MrvlIEtypes_bcn_timeout_t) -
+ sizeof(MrvlIEtypesHeader_t));
+ bcn_tmo_tlv->bcn_miss_tmo_window =
+ wlan_cpu_to_le16(bcn_tmo->bcn_miss_tmo_window);
+ bcn_tmo_tlv->bcn_miss_tmo_period =
+ wlan_cpu_to_le16(bcn_tmo->bcn_miss_tmo_period);
+ bcn_tmo_tlv->bcn_rq_tmo_window =
+ wlan_cpu_to_le16(bcn_tmo->bcn_rq_tmo_window);
+ bcn_tmo_tlv->bcn_rq_tmo_period =
+ wlan_cpu_to_le16(bcn_tmo->bcn_rq_tmo_period);
+ cmd_size += sizeof(MrvlIEtypes_bcn_timeout_t);
+ tlv += sizeof(MrvlIEtypes_bcn_timeout_t);
+
+ psmode_enh->params.auto_ps.ps_bitmap = wlan_cpu_to_le16(
+ (ps_bitmap & (~BITMAP_BCN_TMO)) |
+ BITMAP_STA_PS);
+ }
+ if (ps_bitmap & BITMAP_AUTO_DS) {
+ MrvlIEtypes_auto_ds_param_t *auto_ps_tlv =
+ (MrvlIEtypes_auto_ds_param_t *)tlv;
+ auto_ds_param *auto_ds = &auto_ps_tlv->param;
+ t_u16 idletime = 0;
+ auto_ps_tlv->header.type =
+ wlan_cpu_to_le16(TLV_TYPE_AUTO_DS_PARAM);
+ auto_ps_tlv->header.len = wlan_cpu_to_le16(
+ sizeof(MrvlIEtypes_auto_ds_param_t) -
+ sizeof(MrvlIEtypesHeader_t));
+ cmd_size += sizeof(MrvlIEtypes_auto_ds_param_t);
+ tlv += sizeof(MrvlIEtypes_auto_ds_param_t);
+ if (pdata_buf)
+ idletime =
+ ((mlan_ds_auto_ds *)pdata_buf)->idletime;
+ auto_ds->deep_sleep_timeout =
+ wlan_cpu_to_le16(idletime);
+ }
+#if defined(UAP_SUPPORT)
+ if (pdata_buf &&
+ (ps_bitmap & (BITMAP_UAP_INACT_PS | BITMAP_UAP_DTIM_PS))) {
+ mlan_ds_ps_mgmt *ps_mgmt = (mlan_ds_ps_mgmt *)pdata_buf;
+ MrvlIEtypes_sleep_param_t *sleep_tlv = MNULL;
+ MrvlIEtypes_inact_sleep_param_t *inact_tlv = MNULL;
+ if (ps_mgmt->flags & PS_FLAG_SLEEP_PARAM) {
+ sleep_tlv = (MrvlIEtypes_sleep_param_t *)tlv;
+ sleep_tlv->header.type = wlan_cpu_to_le16(
+ TLV_TYPE_AP_SLEEP_PARAM);
+ sleep_tlv->header.len = wlan_cpu_to_le16(
+ sizeof(MrvlIEtypes_sleep_param_t) -
+ sizeof(MrvlIEtypesHeader_t));
+ sleep_tlv->ctrl_bitmap = wlan_cpu_to_le32(
+ ps_mgmt->sleep_param.ctrl_bitmap);
+ sleep_tlv->min_sleep = wlan_cpu_to_le32(
+ ps_mgmt->sleep_param.min_sleep);
+ sleep_tlv->max_sleep = wlan_cpu_to_le32(
+ ps_mgmt->sleep_param.max_sleep);
+ cmd_size += sizeof(MrvlIEtypes_sleep_param_t);
+ tlv += sizeof(MrvlIEtypes_sleep_param_t);
+ }
+ if (ps_mgmt->flags & PS_FLAG_INACT_SLEEP_PARAM) {
+ inact_tlv =
+ (MrvlIEtypes_inact_sleep_param_t *)tlv;
+ inact_tlv->header.type = wlan_cpu_to_le16(
+ TLV_TYPE_AP_INACT_SLEEP_PARAM);
+ inact_tlv->header.len = wlan_cpu_to_le16(
+ sizeof(MrvlIEtypes_inact_sleep_param_t) -
+ sizeof(MrvlIEtypesHeader_t));
+ inact_tlv->inactivity_to = wlan_cpu_to_le32(
+ ps_mgmt->inact_param.inactivity_to);
+ inact_tlv->min_awake = wlan_cpu_to_le32(
+ ps_mgmt->inact_param.min_awake);
+ inact_tlv->max_awake = wlan_cpu_to_le32(
+ ps_mgmt->inact_param.max_awake);
+ cmd_size +=
+ sizeof(MrvlIEtypes_inact_sleep_param_t);
+ tlv += sizeof(MrvlIEtypes_inact_sleep_param_t);
+ }
+ }
+#endif
+ cmd->size = wlan_cpu_to_le16(cmd_size);
+ }
+
+ LEAVE();
+ return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ * @brief This function handles the command response of ps_mode_enh
+ *
+ * @param pmpriv A pointer to mlan_private structure
+ * @param resp A pointer to HostCmd_DS_COMMAND
+ * @param pioctl_buf A pointer to mlan_ioctl_req structure
+ *
+ * @return MLAN_STATUS_SUCCESS
+ */
+mlan_status wlan_ret_enh_power_mode(pmlan_private pmpriv,
+ HostCmd_DS_COMMAND *resp,
+ mlan_ioctl_req *pioctl_buf)
+{
+ pmlan_adapter pmadapter = pmpriv->adapter;
+ MrvlIEtypesHeader_t *mrvl_tlv = MNULL;
+ MrvlIEtypes_auto_ds_param_t *auto_ds_tlv = MNULL;
+ HostCmd_DS_802_11_PS_MODE_ENH *ps_mode = &resp->params.psmode_enh;
+
+ ENTER();
+
+ ps_mode->action = wlan_le16_to_cpu(ps_mode->action);
+ PRINTM(MINFO, "CMD_RESP: PS_MODE cmd reply result=%#x action=0x%X\n",
+ resp->result, ps_mode->action);
+ if (ps_mode->action == EN_AUTO_PS) {
+ ps_mode->params.auto_ps.ps_bitmap =
+ wlan_le16_to_cpu(ps_mode->params.auto_ps.ps_bitmap);
+ if (ps_mode->params.auto_ps.ps_bitmap & BITMAP_AUTO_DS) {
+ PRINTM(MCMND, "Enabled auto deep sleep\n");
+ pmpriv->adapter->is_deep_sleep = MTRUE;
+ mrvl_tlv = (MrvlIEtypesHeader_t *)((t_u8 *)ps_mode +
+ AUTO_PS_FIX_SIZE);
+ while (wlan_le16_to_cpu(mrvl_tlv->type) !=
+ TLV_TYPE_AUTO_DS_PARAM) {
+ mrvl_tlv =
+ (MrvlIEtypesHeader_t
+ *)((t_u8 *)mrvl_tlv +
+ wlan_le16_to_cpu(
+ mrvl_tlv->len) +
+ sizeof(MrvlIEtypesHeader_t));
+ }
+ auto_ds_tlv = (MrvlIEtypes_auto_ds_param_t *)mrvl_tlv;
+ pmpriv->adapter->idle_time = wlan_le16_to_cpu(
+ auto_ds_tlv->param.deep_sleep_timeout);
+ }
+ if (ps_mode->params.auto_ps.ps_bitmap & BITMAP_STA_PS) {
+ PRINTM(MCMND, "Enabled STA power save\n");
+ if (pmadapter->sleep_period.period) {
+ PRINTM(MCMND,
+ "Setting uapsd/pps mode to TRUE\n");
+ }
+ }
+#if defined(UAP_SUPPORT)
+ if (ps_mode->params.auto_ps.ps_bitmap &
+ (BITMAP_UAP_INACT_PS | BITMAP_UAP_DTIM_PS)) {
+ pmadapter->ps_mode = Wlan802_11PowerModePSP;
+ PRINTM(MCMND, "Enabled uAP power save\n");
+ }
+#endif
+ } else if (ps_mode->action == DIS_AUTO_PS) {
+ ps_mode->params.ps_bitmap =
+ wlan_cpu_to_le16(ps_mode->params.ps_bitmap);
+ if (ps_mode->params.ps_bitmap & BITMAP_AUTO_DS) {
+ pmpriv->adapter->is_deep_sleep = MFALSE;
+ PRINTM(MCMND, "Disabled auto deep sleep\n");
+ }
+ if (ps_mode->params.ps_bitmap & BITMAP_STA_PS) {
+ PRINTM(MCMND, "Disabled STA power save\n");
+ if (pmadapter->sleep_period.period) {
+ pmadapter->delay_null_pkt = MFALSE;
+ pmadapter->tx_lock_flag = MFALSE;
+ pmadapter->pps_uapsd_mode = MFALSE;
+ }
+ }
+#if defined(UAP_SUPPORT)
+ if (ps_mode->params.ps_bitmap &
+ (BITMAP_UAP_INACT_PS | BITMAP_UAP_DTIM_PS)) {
+ pmadapter->ps_mode = Wlan802_11PowerModeCAM;
+ PRINTM(MCMND, "Disabled uAP power save\n");
+ }
+#endif
+ } else if (ps_mode->action == GET_PS) {
+ ps_mode->params.ps_bitmap =
+ wlan_le16_to_cpu(ps_mode->params.ps_bitmap);
+ if (ps_mode->params.auto_ps.ps_bitmap &
+ (BITMAP_STA_PS | BITMAP_UAP_INACT_PS | BITMAP_UAP_DTIM_PS))
+ pmadapter->ps_mode = Wlan802_11PowerModePSP;
+ else
+ pmadapter->ps_mode = Wlan802_11PowerModeCAM;
+ PRINTM(MCMND, "ps_bitmap=0x%x\n", ps_mode->params.ps_bitmap);
+ if (pioctl_buf) {
+ mlan_ds_pm_cfg *pm_cfg =
+ (mlan_ds_pm_cfg *)pioctl_buf->pbuf;
+ if (pm_cfg->sub_command == MLAN_OID_PM_CFG_IEEE_PS) {
+ if (ps_mode->params.auto_ps.ps_bitmap &
+ BITMAP_STA_PS)
+ pm_cfg->param.ps_mode = 1;
+ else
+ pm_cfg->param.ps_mode = 0;
+ }
+#if defined(UAP_SUPPORT)
+ if (pm_cfg->sub_command == MLAN_OID_PM_CFG_PS_MODE) {
+ MrvlIEtypes_sleep_param_t *sleep_tlv = MNULL;
+ MrvlIEtypes_inact_sleep_param_t *inact_tlv =
+ MNULL;
+ MrvlIEtypesHeader_t *tlv = MNULL;
+ t_u16 tlv_type = 0;
+ t_u16 tlv_len = 0;
+ t_u16 tlv_buf_left = 0;
+ pm_cfg->param.ps_mgmt.flags = PS_FLAG_PS_MODE;
+ if (ps_mode->params.ps_bitmap &
+ BITMAP_UAP_INACT_PS)
+ pm_cfg->param.ps_mgmt.ps_mode =
+ PS_MODE_INACTIVITY;
+ else if (ps_mode->params.ps_bitmap &
+ BITMAP_UAP_DTIM_PS)
+ pm_cfg->param.ps_mgmt.ps_mode =
+ PS_MODE_PERIODIC_DTIM;
+ else
+ pm_cfg->param.ps_mgmt.ps_mode =
+ PS_MODE_DISABLE;
+ tlv_buf_left = resp->size -
+ (S_DS_GEN + AUTO_PS_FIX_SIZE);
+ tlv = (MrvlIEtypesHeader_t *)((t_u8 *)ps_mode +
+ AUTO_PS_FIX_SIZE);
+ while (tlv_buf_left >=
+ sizeof(MrvlIEtypesHeader_t)) {
+ tlv_type = wlan_le16_to_cpu(tlv->type);
+ tlv_len = wlan_le16_to_cpu(tlv->len);
+ switch (tlv_type) {
+ case TLV_TYPE_AP_SLEEP_PARAM:
+ sleep_tlv =
+ (MrvlIEtypes_sleep_param_t
+ *)tlv;
+ pm_cfg->param.ps_mgmt.flags |=
+ PS_FLAG_SLEEP_PARAM;
+ pm_cfg->param.ps_mgmt
+ .sleep_param
+ .ctrl_bitmap = wlan_le32_to_cpu(
+ sleep_tlv->ctrl_bitmap);
+ pm_cfg->param.ps_mgmt
+ .sleep_param
+ .min_sleep = wlan_le32_to_cpu(
+ sleep_tlv->min_sleep);
+ pm_cfg->param.ps_mgmt
+ .sleep_param
+ .max_sleep = wlan_le32_to_cpu(
+ sleep_tlv->max_sleep);
+ break;
+ case TLV_TYPE_AP_INACT_SLEEP_PARAM:
+ inact_tlv =
+ (MrvlIEtypes_inact_sleep_param_t
+ *)tlv;
+ pm_cfg->param.ps_mgmt.flags |=
+ PS_FLAG_INACT_SLEEP_PARAM;
+ pm_cfg->param.ps_mgmt
+ .inact_param
+ .inactivity_to = wlan_le32_to_cpu(
+ inact_tlv->inactivity_to);
+ pm_cfg->param.ps_mgmt
+ .inact_param
+ .min_awake = wlan_le32_to_cpu(
+ inact_tlv->min_awake);
+ pm_cfg->param.ps_mgmt
+ .inact_param
+ .max_awake = wlan_le32_to_cpu(
+ inact_tlv->max_awake);
+ break;
+ }
+ tlv_buf_left -=
+ tlv_len +
+ sizeof(MrvlIEtypesHeader_t);
+ tlv = (MrvlIEtypesHeader_t
+ *)((t_u8 *)tlv +
+ tlv_len +
+ sizeof(MrvlIEtypesHeader_t));
+ }
+ }
+#endif
+ }
+ }
+
+ LEAVE();
+ return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ * @brief This function handles the command response of tx rate query
+ *
+ * @param pmpriv A pointer to mlan_private structure
+ * @param resp A pointer to HostCmd_DS_COMMAND
+ * @param pioctl_buf A pointer to mlan_ioctl_req structure
+ *
+ * @return MLAN_STATUS_SUCCESS
+ */
+mlan_status wlan_ret_802_11_tx_rate_query(pmlan_private pmpriv,
+ HostCmd_DS_COMMAND *resp,
+ mlan_ioctl_req *pioctl_buf)
+{
+ mlan_adapter *pmadapter = pmpriv->adapter;
+ mlan_ds_rate *rate = MNULL;
+ ENTER();
+
+ pmpriv->tx_rate = resp->params.tx_rate.tx_rate;
+ pmpriv->tx_rate_info = resp->params.tx_rate.tx_rate_info;
+ if ((pmpriv->tx_rate_info & 0x3) == MLAN_RATE_FORMAT_HE)
+ pmpriv->ext_tx_rate_info =
+ resp->params.tx_rate.ext_tx_rate_info;
+ else
+ pmpriv->ext_tx_rate_info = 0;
+
+ if (!pmpriv->is_data_rate_auto) {
+ pmpriv->data_rate =
+ wlan_index_to_data_rate(pmadapter, pmpriv->tx_rate,
+ pmpriv->tx_rate_info,
+ pmpriv->ext_tx_rate_info);
+ }
+
+ if (pioctl_buf) {
+ rate = (mlan_ds_rate *)pioctl_buf->pbuf;
+ if (rate->sub_command == MLAN_OID_RATE_CFG) {
+ if (rate->param.rate_cfg.rate_type == MLAN_RATE_INDEX) {
+ if ((pmpriv->tx_rate_info & 0x3) ==
+ MLAN_RATE_FORMAT_VHT ||
+ ((pmpriv->tx_rate_info & 0x3) ==
+ MLAN_RATE_FORMAT_HE))
+
+ /* VHT rate */
+ rate->param.rate_cfg.rate =
+ (pmpriv->tx_rate) & 0xF;
+ else if ((pmpriv->tx_rate_info & 0x3) ==
+ MLAN_RATE_FORMAT_HT)
+ /* HT rate */
+ rate->param.rate_cfg.rate =
+ pmpriv->tx_rate +
+ MLAN_RATE_INDEX_MCS0;
+ else
+ /* LG rate */
+ /* For HostCmd_CMD_802_11_TX_RATE_QUERY,
+ * there is a hole (0x4) in rate table
+ * between HR/DSSS and OFDM rates,
+ * so minus 1 for OFDM rate index */
+ rate->param.rate_cfg.rate =
+ (pmpriv->tx_rate >
+ MLAN_RATE_INDEX_OFDM0) ?
+ pmpriv->tx_rate - 1 :
+ pmpriv->tx_rate;
+ } else {
+ /* rate_type = MLAN_RATE_VALUE */
+ rate->param.rate_cfg.rate =
+ wlan_index_to_data_rate(
+ pmadapter, pmpriv->tx_rate,
+ pmpriv->tx_rate_info,
+ pmpriv->ext_tx_rate_info);
+ }
+ } else if (rate->sub_command == MLAN_OID_GET_DATA_RATE) {
+ /* Tx rate info */
+ if ((pmpriv->tx_rate_info & 0x3) ==
+ MLAN_RATE_FORMAT_VHT ||
+ (pmpriv->tx_rate_info & 0x3) ==
+ MLAN_RATE_FORMAT_HE) {
+ /* AX/VHT rate */
+ rate->param.data_rate.tx_rate_format =
+ pmpriv->tx_rate_info & 0x3;
+ rate->param.data_rate.tx_ht_bw =
+ (pmpriv->tx_rate_info & 0xC) >> 2;
+ if ((pmpriv->tx_rate_info & 0x3) ==
+ MLAN_RATE_FORMAT_HE)
+ rate->param.data_rate.tx_ht_gi =
+ (pmpriv->tx_rate_info & 0x10) >>
+ 4 |
+ (pmpriv->tx_rate_info & 0x80) >>
+ 6;
+ else
+ rate->param.data_rate.tx_ht_gi =
+ (pmpriv->tx_rate_info & 0x10) >>
+ 4;
+ rate->param.data_rate.tx_nss =
+ ((pmpriv->tx_rate) >> 4) & 0x03;
+ rate->param.data_rate.tx_mcs_index =
+ (pmpriv->tx_rate) & 0xF;
+ if ((pmpriv->tx_rate_info & 0x3) ==
+ MLAN_RATE_FORMAT_VHT ||
+ (pmpriv->tx_rate_info & 0x3) ==
+ MLAN_RATE_FORMAT_HE)
+ rate->param.data_rate.tx_data_rate =
+ wlan_index_to_data_rate(
+ pmadapter,
+ pmpriv->tx_rate,
+ pmpriv->tx_rate_info,
+ pmpriv->ext_tx_rate_info);
+ } else if ((pmpriv->tx_rate_info & 0x3) ==
+ MLAN_RATE_FORMAT_HT) {
+ /* HT rate */
+ rate->param.data_rate.tx_rate_format =
+ MLAN_RATE_FORMAT_HT;
+ rate->param.data_rate.tx_ht_bw =
+ (pmpriv->tx_rate_info & 0xC) >> 2;
+
+ rate->param.data_rate.tx_ht_gi =
+ (pmpriv->tx_rate_info & 0x10) >> 4;
+ rate->param.data_rate.tx_mcs_index =
+ pmpriv->tx_rate;
+ rate->param.data_rate.tx_data_rate =
+ wlan_index_to_data_rate(
+ pmadapter, pmpriv->tx_rate,
+ pmpriv->tx_rate_info,
+ pmpriv->ext_tx_rate_info);
+ } else {
+ /* LG rate */
+ rate->param.data_rate.tx_rate_format =
+ MLAN_RATE_FORMAT_LG;
+ /* For HostCmd_CMD_802_11_TX_RATE_QUERY,
+ * there is a hole in rate table
+ * between HR/DSSS and OFDM rates,
+ * so minus 1 for OFDM rate index */
+ rate->param.data_rate.tx_data_rate =
+ (pmpriv->tx_rate >
+ MLAN_RATE_INDEX_OFDM0) ?
+ pmpriv->tx_rate - 1 :
+ pmpriv->tx_rate;
+ }
+
+ /* Rx rate info */
+ if ((pmpriv->rxpd_rate_info & 0x3) ==
+ MLAN_RATE_FORMAT_VHT ||
+ (pmpriv->rxpd_rate_info & 0x3) ==
+ MLAN_RATE_FORMAT_HE) {
+ /* VHT rate */
+ rate->param.data_rate.rx_rate_format =
+ pmpriv->rxpd_rate_info & 0x3;
+ rate->param.data_rate.rx_ht_bw =
+ (pmpriv->rxpd_rate_info & 0xC) >> 2;
+ if ((pmpriv->rxpd_rate_info & 0x3) ==
+ MLAN_RATE_FORMAT_HE)
+ rate->param.data_rate.rx_ht_gi =
+ (pmpriv->rxpd_rate_info &
+ 0x10) >>
+ 4 |
+ (pmpriv->rxpd_rate_info &
+ 0x80) >>
+ 6;
+ else
+ rate->param.data_rate.rx_ht_gi =
+ (pmpriv->rxpd_rate_info &
+ 0x10) >>
+ 4;
+ rate->param.data_rate.rx_nss =
+ ((pmpriv->rxpd_rate) >> 4) & 0x3;
+ rate->param.data_rate.rx_mcs_index =
+ (pmpriv->rxpd_rate) & 0xF;
+ if ((pmpriv->rxpd_rate_info & 0x3) ==
+ MLAN_RATE_FORMAT_VHT ||
+ (pmpriv->rxpd_rate_info & 0x3) ==
+ MLAN_RATE_FORMAT_HE)
+ rate->param.data_rate.rx_data_rate =
+ wlan_index_to_data_rate(
+ pmadapter,
+ pmpriv->rxpd_rate,
+ pmpriv->rxpd_rate_info,
+ pmpriv->rxpd_rx_info);
+ } else if ((pmpriv->rxpd_rate_info & 0x3) ==
+ MLAN_RATE_FORMAT_HT) {
+ /* HT rate */
+ rate->param.data_rate.rx_rate_format =
+ MLAN_RATE_FORMAT_HT;
+ rate->param.data_rate.rx_ht_bw =
+ (pmpriv->rxpd_rate_info & 0xC) >> 2;
+ rate->param.data_rate.rx_ht_gi =
+ (pmpriv->rxpd_rate_info & 0x10) >> 4;
+ rate->param.data_rate.rx_mcs_index =
+ pmpriv->rxpd_rate;
+ rate->param.data_rate.rx_data_rate =
+ wlan_index_to_data_rate(
+ pmadapter, pmpriv->rxpd_rate,
+ pmpriv->rxpd_rate_info, 0);
+ } else {
+ /* LG rate */
+ rate->param.data_rate.rx_rate_format =
+ MLAN_RATE_FORMAT_LG;
+ /* For rate index in RxPD,
+ * there is a hole in rate table
+ * between HR/DSSS and OFDM rates,
+ * so minus 1 for OFDM rate index */
+ rate->param.data_rate.rx_data_rate =
+ (pmpriv->rxpd_rate >
+ MLAN_RATE_INDEX_OFDM0) ?
+ pmpriv->rxpd_rate - 1 :
+ pmpriv->rxpd_rate;
+ }
+ }
+ pioctl_buf->data_read_written =
+ sizeof(mlan_data_rate) + MLAN_SUB_COMMAND_SIZE;
+ }
+ LEAVE();
+ return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ * @brief This function prepares command of robustcoex.
+ *
+ * @param pmpriv A pointer to mlan_private structure
+ * @param cmd A pointer to HostCmd_DS_COMMAND structure
+ * @param cmd_action The action: GET or SET
+ * @param pdata_buf A pointer to data buffer
+ *
+ * @return MLAN_STATUS_SUCCESS
+ */
+mlan_status wlan_cmd_robustcoex(pmlan_private pmpriv, HostCmd_DS_COMMAND *cmd,
+ t_u16 cmd_action, t_u16 *pdata_buf)
+{
+ HostCmd_DS_802_11_ROBUSTCOEX *rbstcx = &cmd->params.robustcoexparams;
+ mlan_ds_misc_robustcoex_params *robustcoex_params = MNULL;
+ MrvlIEtypes_RobustcoexSourceGPIO_t *tlv =
+ (MrvlIEtypes_RobustcoexSourceGPIO_t *)(rbstcx->tlv_buf);
+
+ ENTER();
+
+ cmd->command = wlan_cpu_to_le16(HostCmd_CMD_802_11_ROBUSTCOEX);
+ cmd->size = sizeof(HostCmd_DS_802_11_ROBUSTCOEX) + S_DS_GEN;
+ rbstcx->action = wlan_cpu_to_le16(cmd_action);
+ switch (cmd_action) {
+ case HostCmd_ACT_GEN_SET:
+ robustcoex_params = (mlan_ds_misc_robustcoex_params *)pdata_buf;
+ if (robustcoex_params->method == ROBUSTCOEX_GPIO_CFG) {
+ cmd->size += sizeof(MrvlIEtypes_RobustcoexSourceGPIO_t);
+ tlv->header.type =
+ wlan_cpu_to_le16(TLV_TYPE_ROBUSTCOEX);
+ tlv->header.len = wlan_cpu_to_le16(
+ sizeof(MrvlIEtypes_RobustcoexSourceGPIO_t) -
+ sizeof(MrvlIEtypesHeader_t));
+ tlv->enable = (t_u8)robustcoex_params->enable;
+ tlv->gpio_num = (t_u8)robustcoex_params->gpio_num;
+ tlv->gpio_polarity =
+ (t_u8)robustcoex_params->gpio_polarity;
+ }
+ break;
+ case HostCmd_ACT_GEN_GET:
+ default:
+ break;
+ }
+ cmd->size = wlan_cpu_to_le16(cmd->size);
+ LEAVE();
+ return MLAN_STATUS_SUCCESS;
+}
+
+#if defined(PCIE)
+/**
+ * @brief This function enables SSU support.
+ *
+ * @param pmpriv A pointer to mlan_private structure
+ * @param cmd A pointer to HostCmd_DS_COMMAND structure
+ * @param cmd_action The action: GET or SET
+ * @param pdata_buf A pointer to data buffer
+ *
+ * @return MLAN_STATUS_SUCCESS
+ */
+mlan_status wlan_cmd_ssu(pmlan_private pmpriv, HostCmd_DS_COMMAND *cmd,
+ t_u16 cmd_action, t_u16 *pdata_buf)
+{
+ HostCmd_DS_SSU_CFG *ssu_cfg_cmd = &cmd->params.ssu_params;
+ mlan_ds_ssu_params *ssu_params = MNULL;
+ mlan_status ret = MLAN_STATUS_SUCCESS;
+ mlan_adapter *pmadapter = pmpriv->adapter;
+
+ ENTER();
+
+ cmd->command = wlan_cpu_to_le16(HostCmd_CMD_SSU);
+ cmd->size = sizeof(HostCmd_DS_SSU_CFG) + S_DS_GEN;
+ ssu_cfg_cmd->action = wlan_cpu_to_le16(cmd_action);
+ switch (cmd_action) {
+ case HostCmd_ACT_GEN_SET:
+ case HostCmd_ACT_GEN_SET_DEFAULT:
+ ssu_params = (mlan_ds_ssu_params *)pdata_buf;
+ ssu_cfg_cmd->nskip = wlan_cpu_to_le32(ssu_params->nskip);
+ ssu_cfg_cmd->nsel = wlan_cpu_to_le32(ssu_params->nsel);
+ ssu_cfg_cmd->adcdownsample =
+ wlan_cpu_to_le32(ssu_params->adcdownsample);
+ ssu_cfg_cmd->mask_adc_pkt =
+ wlan_cpu_to_le32(ssu_params->mask_adc_pkt);
+ ssu_cfg_cmd->out_16bits =
+ wlan_cpu_to_le32(ssu_params->out_16bits);
+ ssu_cfg_cmd->spec_pwr_enable =
+ wlan_cpu_to_le32(ssu_params->spec_pwr_enable);
+ ssu_cfg_cmd->rate_deduction =
+ wlan_cpu_to_le32(ssu_params->rate_deduction);
+ ssu_cfg_cmd->n_pkt_avg =
+ wlan_cpu_to_le32(ssu_params->n_pkt_avg);
+ /* Initialize PCIE ring buffer */
+ ret = wlan_alloc_ssu_pcie_buf(pmadapter);
+ if (MLAN_STATUS_SUCCESS != ret) {
+ PRINTM(MERROR,
+ "Failed to allocate PCIE host buffers for SSU\n");
+ LEAVE();
+ return MLAN_STATUS_FAILURE;
+ }
+ ssu_cfg_cmd->buffer_base_addr[0] =
+ wlan_cpu_to_le32((t_u32)pmadapter->ssu_buf->buf_pa);
+ ssu_cfg_cmd->buffer_base_addr[1] = wlan_cpu_to_le32(
+ (t_u32)((t_u64)(pmadapter->ssu_buf->buf_pa >> 32)));
+ ssu_cfg_cmd->buffer_pool_size =
+ wlan_cpu_to_le32(MLAN_SSU_BUF_SIZE);
+ break;
+ case HostCmd_ACT_GEN_GET:
+ default:
+ break;
+ }
+ cmd->size = wlan_cpu_to_le16(cmd->size);
+ LEAVE();
+ return MLAN_STATUS_SUCCESS;
+}
+#endif
+
+/**
+ * @brief This function prepares command of dmcs config.
+ *
+ * @param pmpriv A pointer to mlan_private structure
+ * @param cmd A pointer to HostCmd_DS_COMMAND structure
+ * @param cmd_action The action: GET or SET
+ * @param pdata_buf A pointer to data buffer
+ *
+ * @return MLAN_STATUS_SUCCESS
+ */
+mlan_status wlan_cmd_dmcs_config(pmlan_private pmpriv, HostCmd_DS_COMMAND *cmd,
+ t_u16 cmd_action, t_void *pdata_buf)
+{
+ HostCmd_DS_DMCS_CFG *dmcs = &cmd->params.dmcs;
+ mlan_ds_misc_mapping_policy *dmcs_params = MNULL;
+ t_u8 *mapping_policy = (t_u8 *)dmcs->tlv_buf;
+
+ ENTER();
+
+ cmd->command = wlan_cpu_to_le16(HostCmd_CMD_DMCS_CONFIG);
+ cmd->size = sizeof(HostCmd_DS_DMCS_CFG) + S_DS_GEN;
+ dmcs->action = wlan_cpu_to_le16(cmd_action);
+ dmcs_params = (mlan_ds_misc_mapping_policy *)pdata_buf;
+ dmcs->subcmd = wlan_cpu_to_le16(dmcs_params->subcmd);
+ switch (dmcs->subcmd) {
+ case 0:
+ cmd->size += sizeof(t_u8);
+ *mapping_policy = dmcs_params->mapping_policy;
+ break;
+ case 1:
+ default:
+ break;
+ }
+ cmd->size = wlan_cpu_to_le16(cmd->size);
+ LEAVE();
+ return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ * @brief This function handles the command response of dmcs config
+ *
+ * @param pmpriv A pointer to mlan_private structure
+ * @param resp A pointer to HostCmd_DS_COMMAND
+ * @param pioctl_buf A pointer to mlan_ioctl_req structure
+ *
+ * @return MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ */
+mlan_status wlan_ret_dmcs_config(pmlan_private pmpriv, HostCmd_DS_COMMAND *resp,
+ mlan_ioctl_req *pioctl_buf)
+{
+ mlan_status ret = MLAN_STATUS_SUCCESS;
+ HostCmd_DS_DMCS_CFG *dmcs = &resp->params.dmcs;
+ MrvlIEtypes_DmcsStatus_t *dmcs_status;
+ mlan_ds_misc_cfg *cfg = MNULL;
+ t_u16 tlv_buf_left = 0;
+ t_u16 tlv_type = 0, tlv_len = 0;
+ MrvlIEtypesHeader_t *tlv = MNULL;
+ int i = 0;
+
+ ENTER();
+ if (pioctl_buf) {
+ cfg = (mlan_ds_misc_cfg *)pioctl_buf->pbuf;
+ tlv = (MrvlIEtypesHeader_t *)((t_u8 *)dmcs +
+ sizeof(HostCmd_DS_DMCS_CFG));
+ tlv_buf_left =
+ resp->size - (sizeof(HostCmd_DS_DMCS_CFG) + S_DS_GEN);
+ while (tlv_buf_left > sizeof(MrvlIEtypesHeader_t)) {
+ tlv_type = wlan_le16_to_cpu(tlv->type);
+ tlv_len = wlan_le16_to_cpu(tlv->len);
+ if (tlv_buf_left <
+ (tlv_len + sizeof(MrvlIEtypesHeader_t))) {
+ PRINTM(MERROR,
+ "Error while processing DMCS status tlv, bytes_left < TLV len\n");
+ ret = MLAN_STATUS_FAILURE;
+ break;
+ }
+ switch (tlv_type) {
+ case TLV_TYPE_DMCS_STATUS:
+ dmcs_status = (MrvlIEtypes_DmcsStatus_t *)tlv;
+ cfg->param.dmcs_status.mapping_policy =
+ dmcs_status->mapping_policy;
+ memset(pmpriv->adapter,
+ &cfg->param.dmcs_status.radio_status, 0,
+ sizeof(dmcsStatus_t));
+ for (i = 0; i < MAX_NUM_MAC; i++) {
+ memcpy_ext(
+ pmpriv->adapter,
+ &cfg->param.dmcs_status
+ .radio_status[i],
+ &dmcs_status->radio_status[i],
+ sizeof(dmcsStatus_t),
+ sizeof(dmcsStatus_t));
+ }
+ break;
+ default:
+ break;
+ }
+ tlv_buf_left -= tlv_len + sizeof(MrvlIEtypesHeader_t);
+ tlv = (MrvlIEtypesHeader_t
+ *)((t_u8 *)tlv + tlv_len +
+ sizeof(MrvlIEtypesHeader_t));
+ }
+ pioctl_buf->data_read_written =
+ sizeof(mlan_ds_misc_dmcs_status);
+ }
+ LEAVE();
+ return ret;
+}
+
+/**
+ * @brief This function prepares command of tx_rate_cfg.
+ *
+ * @param pmpriv A pointer to mlan_private structure
+ * @param cmd A pointer to HostCmd_DS_COMMAND structure
+ * @param cmd_action The action: GET or SET
+ * @param pdata_buf A pointer to data buffer
+ * @param pioctl_buf A pointer to ioctl buffer
+ *
+ * @return MLAN_STATUS_SUCCESS
+ */
+mlan_status wlan_cmd_tx_rate_cfg(pmlan_private pmpriv, HostCmd_DS_COMMAND *cmd,
+ t_u16 cmd_action, t_void *pdata_buf,
+ mlan_ioctl_req *pioctl_buf)
+{
+ HostCmd_DS_TX_RATE_CFG *rate_cfg =
+ (HostCmd_DS_TX_RATE_CFG *)&(cmd->params.tx_rate_cfg);
+ MrvlRateScope_t *rate_scope;
+ MrvlRateDropPattern_t *rate_drop;
+ MrvlIETypes_rate_setting_t *rate_setting_tlv;
+ mlan_ds_rate *ds_rate = MNULL;
+ t_u16 *pbitmap_rates = (t_u16 *)pdata_buf;
+
+ t_u32 i;
+
+ ENTER();
+
+ cmd->command = wlan_cpu_to_le16(HostCmd_CMD_TX_RATE_CFG);
+
+ rate_cfg->action = wlan_cpu_to_le16(cmd_action);
+
+ rate_scope = (MrvlRateScope_t *)rate_cfg->tlv_buf;
+ rate_scope->type = wlan_cpu_to_le16(TLV_TYPE_RATE_SCOPE);
+ rate_scope->length = wlan_cpu_to_le16(sizeof(MrvlRateScope_t) -
+ sizeof(MrvlIEtypesHeader_t));
+ if (pbitmap_rates != MNULL) {
+ rate_scope->hr_dsss_rate_bitmap =
+ wlan_cpu_to_le16(pbitmap_rates[0]);
+ rate_scope->ofdm_rate_bitmap =
+ wlan_cpu_to_le16(pbitmap_rates[1]);
+ for (i = 0; i < NELEMENTS(rate_scope->ht_mcs_rate_bitmap); i++)
+ rate_scope->ht_mcs_rate_bitmap[i] =
+ wlan_cpu_to_le16(pbitmap_rates[2 + i]);
+ for (i = 0; i < NELEMENTS(rate_scope->vht_mcs_rate_bitmap); i++)
+ rate_scope->vht_mcs_rate_bitmap[i] = wlan_cpu_to_le16(
+ pbitmap_rates
+ [2 +
+ NELEMENTS(
+ rate_scope->ht_mcs_rate_bitmap) +
+ i]);
+ if (IS_FW_SUPPORT_11AX(pmpriv->adapter)) {
+ for (i = 0;
+ i < NELEMENTS(rate_scope->he_mcs_rate_bitmap); i++)
+ rate_scope->he_mcs_rate_bitmap
+ [i] = wlan_cpu_to_le16(
+ pbitmap_rates
+ [2 +
+ NELEMENTS(
+ rate_scope
+ ->ht_mcs_rate_bitmap) +
+ NELEMENTS(
+ rate_scope
+ ->vht_mcs_rate_bitmap) +
+ i]);
+ } else {
+ rate_scope->length = wlan_cpu_to_le16(
+ sizeof(MrvlRateScope_t) -
+ sizeof(rate_scope->he_mcs_rate_bitmap) -
+ sizeof(MrvlIEtypesHeader_t));
+ }
+ } else {
+ rate_scope->hr_dsss_rate_bitmap =
+ wlan_cpu_to_le16(pmpriv->bitmap_rates[0]);
+ rate_scope->ofdm_rate_bitmap =
+ wlan_cpu_to_le16(pmpriv->bitmap_rates[1]);
+ for (i = 0; i < NELEMENTS(rate_scope->ht_mcs_rate_bitmap); i++)
+ rate_scope->ht_mcs_rate_bitmap[i] =
+ wlan_cpu_to_le16(pmpriv->bitmap_rates[2 + i]);
+ for (i = 0; i < NELEMENTS(rate_scope->vht_mcs_rate_bitmap); i++)
+ rate_scope->vht_mcs_rate_bitmap[i] = wlan_cpu_to_le16(
+ pmpriv->bitmap_rates
+ [2 +
+ NELEMENTS(
+ rate_scope->ht_mcs_rate_bitmap) +
+ i]);
+ if (IS_FW_SUPPORT_11AX(pmpriv->adapter)) {
+ for (i = 0;
+ i < NELEMENTS(rate_scope->vht_mcs_rate_bitmap);
+ i++)
+ rate_scope->he_mcs_rate_bitmap
+ [i] = wlan_cpu_to_le16(
+ pmpriv->bitmap_rates
+ [2 +
+ NELEMENTS(
+ rate_scope
+ ->ht_mcs_rate_bitmap) +
+ NELEMENTS(
+ rate_scope
+ ->vht_mcs_rate_bitmap) +
+ i]);
+ } else {
+ rate_scope->length = wlan_cpu_to_le16(
+ sizeof(MrvlRateScope_t) -
+ sizeof(rate_scope->he_mcs_rate_bitmap) -
+ sizeof(MrvlIEtypesHeader_t));
+ }
+ }
+
+ rate_drop =
+ (MrvlRateDropPattern_t *)((t_u8 *)rate_scope +
+ wlan_le16_to_cpu(rate_scope->length) +
+ sizeof(MrvlIEtypesHeader_t));
+ rate_drop->type = wlan_cpu_to_le16(TLV_TYPE_RATE_DROP_PATTERN);
+ rate_drop->length = wlan_cpu_to_le16(sizeof(rate_drop->rate_drop_mode));
+ rate_drop->rate_drop_mode = 0;
+
+ cmd->size = wlan_cpu_to_le16(
+ S_DS_GEN + sizeof(HostCmd_DS_TX_RATE_CFG) + rate_scope->length +
+ sizeof(MrvlIEtypesHeader_t) + sizeof(MrvlRateDropPattern_t));
+ if (pioctl_buf && pmpriv->adapter->pcard_info->v17_fw_api) {
+ ds_rate = (mlan_ds_rate *)pioctl_buf->pbuf;
+ rate_setting_tlv = (MrvlIETypes_rate_setting_t
+ *)((t_u8 *)rate_drop +
+ sizeof(MrvlRateDropPattern_t));
+ rate_setting_tlv->header.type =
+ wlan_cpu_to_le16(TLV_TYPE_TX_RATE_CFG);
+ rate_setting_tlv->header.len = wlan_cpu_to_le16(
+ sizeof(rate_setting_tlv->rate_setting));
+ rate_setting_tlv->rate_setting =
+ wlan_cpu_to_le16(ds_rate->param.rate_cfg.rate_setting);
+ PRINTM(MCMND, "he rate setting = %d\n",
+ rate_setting_tlv->rate_setting);
+ cmd->size = wlan_cpu_to_le16(
+ S_DS_GEN + sizeof(HostCmd_DS_TX_RATE_CFG) +
+ rate_scope->length + sizeof(MrvlIEtypesHeader_t) +
+ sizeof(MrvlRateDropPattern_t) +
+ sizeof(MrvlIETypes_rate_setting_t));
+ }
+ LEAVE();
+ return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ * @brief This function handles the command response of tx_rate_cfg
+ *
+ * @param pmpriv A pointer to mlan_private structure
+ * @param resp A pointer to HostCmd_DS_COMMAND
+ * @param pioctl_buf A pointer to mlan_ioctl_req structure
+ *
+ * @return MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ */
+mlan_status wlan_ret_tx_rate_cfg(pmlan_private pmpriv, HostCmd_DS_COMMAND *resp,
+ mlan_ioctl_req *pioctl_buf)
+{
+ mlan_adapter *pmadapter = pmpriv->adapter;
+ mlan_ds_rate *ds_rate = MNULL;
+ HostCmd_DS_TX_RATE_CFG *prate_cfg = MNULL;
+ MrvlRateScope_t *prate_scope;
+ MrvlIEtypesHeader_t *head = MNULL;
+ t_u16 tlv, tlv_buf_len = 0;
+ t_u8 *tlv_buf;
+ t_u32 i;
+ t_s32 index;
+ mlan_status ret = MLAN_STATUS_SUCCESS;
+ MrvlIETypes_rate_setting_t *rate_setting_tlv = MNULL;
+ t_u16 rate_setting = 0xffff;
+
+ ENTER();
+
+ if (resp == MNULL) {
+ LEAVE();
+ return MLAN_STATUS_FAILURE;
+ }
+ prate_cfg = (HostCmd_DS_TX_RATE_CFG *)&(resp->params.tx_rate_cfg);
+
+ tlv_buf = (t_u8 *)prate_cfg->tlv_buf;
+ if (tlv_buf) {
+ tlv_buf_len = resp->size -
+ (sizeof(HostCmd_DS_TX_RATE_CFG) + S_DS_GEN);
+ tlv_buf_len = wlan_le16_to_cpu(tlv_buf_len);
+ }
+
+ while (tlv_buf && tlv_buf_len > 0) {
+ tlv = (*tlv_buf);
+ tlv = tlv | (*(tlv_buf + 1) << 8);
+
+ switch (tlv) {
+ case TLV_TYPE_RATE_SCOPE:
+ prate_scope = (MrvlRateScope_t *)tlv_buf;
+ pmpriv->bitmap_rates[0] = wlan_le16_to_cpu(
+ prate_scope->hr_dsss_rate_bitmap);
+ pmpriv->bitmap_rates[1] =
+ wlan_le16_to_cpu(prate_scope->ofdm_rate_bitmap);
+ for (i = 0;
+ i < NELEMENTS(prate_scope->ht_mcs_rate_bitmap);
+ i++)
+ pmpriv->bitmap_rates[2 + i] = wlan_le16_to_cpu(
+ prate_scope->ht_mcs_rate_bitmap[i]);
+ for (i = 0;
+ i < NELEMENTS(prate_scope->vht_mcs_rate_bitmap);
+ i++)
+ pmpriv->bitmap_rates
+ [2 +
+ sizeof(prate_scope->ht_mcs_rate_bitmap) /
+ sizeof(t_u16) +
+ i] =
+ wlan_le16_to_cpu(
+ prate_scope
+ ->vht_mcs_rate_bitmap[i]);
+ if (IS_FW_SUPPORT_11AX(pmadapter)) {
+ for (i = 0;
+ i <
+ NELEMENTS(prate_scope->he_mcs_rate_bitmap);
+ i++)
+ pmpriv->bitmap_rates
+ [2 +
+ sizeof(prate_scope
+ ->ht_mcs_rate_bitmap) /
+ sizeof(t_u16) +
+ sizeof(prate_scope
+ ->vht_mcs_rate_bitmap) /
+ sizeof(t_u16) +
+ i] =
+ wlan_le16_to_cpu(
+ prate_scope
+ ->he_mcs_rate_bitmap
+ [i]);
+ }
+ break;
+ case TLV_TYPE_TX_RATE_CFG:
+ rate_setting_tlv =
+ (MrvlIETypes_rate_setting_t *)tlv_buf;
+ rate_setting = rate_setting_tlv->rate_setting;
+ break;
+ /* Add RATE_DROP tlv here */
+ }
+
+ head = (MrvlIEtypesHeader_t *)tlv_buf;
+ head->len = wlan_le16_to_cpu(head->len);
+ tlv_buf += head->len + sizeof(MrvlIEtypesHeader_t);
+ tlv_buf_len -= (head->len + sizeof(MrvlIEtypesHeader_t));
+ }
+
+ pmpriv->is_data_rate_auto = wlan_is_rate_auto(pmpriv);
+
+ if (pmpriv->is_data_rate_auto) {
+ pmpriv->data_rate = 0;
+ } else {
+ ret = wlan_prepare_cmd(pmpriv, HostCmd_CMD_802_11_TX_RATE_QUERY,
+ HostCmd_ACT_GEN_GET, 0, MNULL, MNULL);
+ }
+
+ if (pioctl_buf) {
+ ds_rate = (mlan_ds_rate *)pioctl_buf->pbuf;
+ if (ds_rate == MNULL) {
+ PRINTM(MERROR, "Request buffer not found!\n");
+ LEAVE();
+ return MLAN_STATUS_FAILURE;
+ }
+ if (pmpriv->is_data_rate_auto) {
+ ds_rate->param.rate_cfg.is_rate_auto = MTRUE;
+ ds_rate->param.rate_cfg.rate_format =
+ MLAN_RATE_FORMAT_AUTO;
+ } else {
+ ds_rate->param.rate_cfg.is_rate_auto = MFALSE;
+ /* check the LG rate */
+ index = wlan_get_rate_index(
+ pmadapter, &pmpriv->bitmap_rates[0], 4);
+ if (index != -1) {
+ if ((index >= MLAN_RATE_BITMAP_OFDM0) &&
+ (index <= MLAN_RATE_BITMAP_OFDM7))
+ index -= (MLAN_RATE_BITMAP_OFDM0 -
+ MLAN_RATE_INDEX_OFDM0);
+ ds_rate->param.rate_cfg.rate_format =
+ MLAN_RATE_FORMAT_LG;
+ ds_rate->param.rate_cfg.rate = index;
+ }
+ /* check the HT rate */
+ index = wlan_get_rate_index(
+ pmadapter, &pmpriv->bitmap_rates[2], 16);
+ if (index != -1) {
+ ds_rate->param.rate_cfg.rate_format =
+ MLAN_RATE_FORMAT_HT;
+ ds_rate->param.rate_cfg.rate = index;
+ }
+ /* check the VHT rate */
+ index = wlan_get_rate_index(
+ pmadapter, &pmpriv->bitmap_rates[10], 16);
+ if (index != -1) {
+ ds_rate->param.rate_cfg.rate_format =
+ MLAN_RATE_FORMAT_VHT;
+ ds_rate->param.rate_cfg.rate = index % 16;
+ ds_rate->param.rate_cfg.nss = index / 16;
+ ds_rate->param.rate_cfg.nss += MLAN_RATE_NSS1;
+ }
+ /* check the HE rate */
+ if (IS_FW_SUPPORT_11AX(pmadapter)) {
+ index = wlan_get_rate_index(
+ pmadapter, &pmpriv->bitmap_rates[18],
+ 16);
+ if (index != -1) {
+ ds_rate->param.rate_cfg.rate_format =
+ MLAN_RATE_FORMAT_HE;
+ ds_rate->param.rate_cfg.rate =
+ index % 16;
+ ds_rate->param.rate_cfg.nss =
+ index / 16;
+ ds_rate->param.rate_cfg.nss +=
+ MLAN_RATE_NSS1;
+ }
+ }
+ ds_rate->param.rate_cfg.rate_setting = rate_setting;
+ PRINTM(MINFO, "Rate index is %d\n",
+ ds_rate->param.rate_cfg.rate);
+ }
+ for (i = 0; i < MAX_BITMAP_RATES_SIZE; i++) {
+ ds_rate->param.rate_cfg.bitmap_rates[i] =
+ pmpriv->bitmap_rates[i];
+ }
+ }
+
+ LEAVE();
+ return ret;
+}
+
+/**
+ * @brief This function issues adapter specific commands
+ * to initialize firmware
+ *
+ * @param pmadapter A pointer to mlan_adapter structure
+ *
+ * @return MLAN_STATUS_PENDING or MLAN_STATUS_FAILURE
+ */
+mlan_status wlan_adapter_get_hw_spec(pmlan_adapter pmadapter)
+{
+ mlan_status ret = MLAN_STATUS_SUCCESS;
+ pmlan_private priv = wlan_get_priv(pmadapter, MLAN_BSS_ROLE_ANY);
+#if defined(SDIO)
+ /*
+ * This should be issued in the very first to config
+ * SDIO_GPIO interrupt mode.
+ */
+ if (IS_SD(pmadapter->card_type) &&
+ (wlan_set_sdio_gpio_int(priv) != MLAN_STATUS_SUCCESS)) {
+ ret = MLAN_STATUS_FAILURE;
+ goto done;
+ }
+#endif
+
+#ifdef PCIE
+ if (IS_PCIE(pmadapter->card_type) &&
+ (MLAN_STATUS_SUCCESS != wlan_set_pcie_buf_config(priv))) {
+ ret = MLAN_STATUS_FAILURE;
+ goto done;
+ }
+#endif
+
+ ret = wlan_prepare_cmd(priv, HostCmd_CMD_FUNC_INIT, HostCmd_ACT_GEN_SET,
+ 0, MNULL, MNULL);
+ if (ret) {
+ ret = MLAN_STATUS_FAILURE;
+ goto done;
+ }
+ /** DPD data dnld cmd prepare */
+ if ((pmadapter->pdpd_data) && (pmadapter->dpd_data_len > 0)) {
+ ret = wlan_process_hostcmd_cfg(priv, CFG_TYPE_DPDFILE,
+ pmadapter->pdpd_data,
+ pmadapter->dpd_data_len);
+ if (ret) {
+ ret = MLAN_STATUS_FAILURE;
+ goto done;
+ }
+ pmadapter->pdpd_data = MNULL;
+ pmadapter->dpd_data_len = 0;
+ }
+ if ((pmadapter->ptxpwr_data) && (pmadapter->txpwr_data_len > 0)) {
+ ret = wlan_process_hostcmd_cfg(priv, CFG_TYPE_HOSTCMD,
+ pmadapter->ptxpwr_data,
+ pmadapter->txpwr_data_len);
+ if (ret) {
+ ret = MLAN_STATUS_FAILURE;
+ goto done;
+ }
+ pmadapter->ptxpwr_data = MNULL;
+ pmadapter->txpwr_data_len = 0;
+ }
+ if (!pmadapter->pdpd_data &&
+ (pmadapter->dpd_data_len == UNKNOW_DPD_LENGTH)) {
+ ret = wlan_prepare_cmd(priv, HostCmd_CMD_CFG_DATA,
+ HostCmd_ACT_GEN_GET, OID_TYPE_DPD, MNULL,
+ MNULL);
+ if (ret) {
+ ret = MLAN_STATUS_FAILURE;
+ goto done;
+ }
+ }
+ /** Cal data dnld cmd prepare */
+ if ((pmadapter->pcal_data) && (pmadapter->cal_data_len > 0)) {
+ ret = wlan_prepare_cmd(priv, HostCmd_CMD_CFG_DATA,
+ HostCmd_ACT_GEN_SET, OID_TYPE_CAL, MNULL,
+ MNULL);
+ if (ret) {
+ ret = MLAN_STATUS_FAILURE;
+ goto done;
+ }
+ pmadapter->pcal_data = MNULL;
+ pmadapter->cal_data_len = 0;
+ }
+ /* Get FW region and cfp tables */
+ if (pmadapter->init_para.fw_region) {
+ ret = wlan_prepare_cmd(priv, HostCmd_CMD_CHAN_REGION_CFG,
+ HostCmd_ACT_GEN_GET, 0, MNULL, MNULL);
+ if (ret) {
+ ret = MLAN_STATUS_FAILURE;
+ goto done;
+ }
+ }
+ /*
+ * Get HW spec
+ */
+ ret = wlan_prepare_cmd(priv, HostCmd_CMD_GET_HW_SPEC,
+ HostCmd_ACT_GEN_GET, 0, MNULL, MNULL);
+ if (ret) {
+ ret = MLAN_STATUS_FAILURE;
+ goto done;
+ }
+ ret = MLAN_STATUS_PENDING;
+done:
+ LEAVE();
+ return ret;
+}
+
+/**
+ * @brief This function issues adapter specific commands
+ * to initialize firmware
+ *
+ * @param pmadapter A pointer to mlan_adapter structure
+ *
+ * @return MLAN_STATUS_PENDING or MLAN_STATUS_FAILURE
+ */
+mlan_status wlan_adapter_init_cmd(pmlan_adapter pmadapter)
+{
+ mlan_status ret = MLAN_STATUS_SUCCESS;
+ pmlan_private pmpriv = MNULL;
+#ifdef STA_SUPPORT
+ pmlan_private pmpriv_sta = MNULL;
+#endif
+ ENTER();
+
+ pmpriv = wlan_get_priv(pmadapter, MLAN_BSS_ROLE_ANY);
+#ifdef STA_SUPPORT
+ pmpriv_sta = wlan_get_priv(pmadapter, MLAN_BSS_ROLE_STA);
+#endif
+
+#ifdef SDIO
+ if (IS_SD(pmadapter->card_type)) {
+ }
+#endif
+
+ ret = wlan_prepare_cmd(pmpriv, HostCmd_CMD_RECONFIGURE_TX_BUFF,
+ HostCmd_ACT_GEN_SET, 0, MNULL,
+ &pmadapter->max_tx_buf_size);
+ if (ret) {
+ ret = MLAN_STATUS_FAILURE;
+ goto done;
+ }
+
+#if defined(STA_SUPPORT)
+ if (pmpriv_sta &&
+ (pmpriv_sta->state_11d.user_enable_11d == ENABLE_11D)) {
+ /* Send command to FW to enable 11d */
+ ret = wlan_prepare_cmd(pmpriv_sta, HostCmd_CMD_802_11_SNMP_MIB,
+ HostCmd_ACT_GEN_SET, Dot11D_i, MNULL,
+ &pmpriv_sta->state_11d.user_enable_11d);
+ if (ret) {
+ ret = MLAN_STATUS_FAILURE;
+ goto done;
+ }
+ }
+#endif
+
+#ifdef STA_SUPPORT
+ if (pmpriv_sta && (pmadapter->ps_mode == Wlan802_11PowerModePSP)) {
+ ret = wlan_prepare_cmd(pmpriv_sta,
+ HostCmd_CMD_802_11_PS_MODE_ENH,
+ EN_AUTO_PS, BITMAP_STA_PS, MNULL, MNULL);
+ if (ret) {
+ ret = MLAN_STATUS_FAILURE;
+ goto done;
+ }
+ }
+#endif
+
+ if (pmadapter->init_auto_ds) {
+ mlan_ds_auto_ds auto_ds;
+ /* Enable auto deep sleep */
+ auto_ds.idletime = pmadapter->idle_time;
+ ret = wlan_prepare_cmd(pmpriv, HostCmd_CMD_802_11_PS_MODE_ENH,
+ EN_AUTO_PS, BITMAP_AUTO_DS, MNULL,
+ &auto_ds);
+ if (ret) {
+ ret = MLAN_STATUS_FAILURE;
+ goto done;
+ }
+ }
+
+ if (pmadapter->init_para.indrstcfg != 0xffffffff) {
+ mlan_ds_ind_rst_cfg ind_rst_cfg;
+ ind_rst_cfg.ir_mode = pmadapter->init_para.indrstcfg & 0xff;
+ ind_rst_cfg.gpio_pin =
+ (pmadapter->init_para.indrstcfg & 0xff00) >> 8;
+ ret = wlan_prepare_cmd(pmpriv,
+ HostCmd_CMD_INDEPENDENT_RESET_CFG,
+ HostCmd_ACT_GEN_SET, 0, MNULL,
+ (t_void *)&ind_rst_cfg);
+ if (ret) {
+ ret = MLAN_STATUS_FAILURE;
+ goto done;
+ }
+ }
+
+ if (pmadapter->inact_tmo) {
+ ret = wlan_prepare_cmd(pmpriv,
+ HostCmd_CMD_802_11_PS_INACTIVITY_TIMEOUT,
+ HostCmd_ACT_GEN_SET, 0, MNULL,
+ &pmadapter->inact_tmo);
+ if (ret) {
+ ret = MLAN_STATUS_FAILURE;
+ goto done;
+ }
+ }
+ /* Send request to firmware */
+ ret = wlan_prepare_cmd(pmpriv, HostCmd_CMD_802_11_RF_ANTENNA,
+ HostCmd_ACT_GEN_GET, 0, MNULL, MNULL);
+ if (ret) {
+ ret = MLAN_STATUS_FAILURE;
+ goto done;
+ }
+ ret = MLAN_STATUS_PENDING;
+done:
+ LEAVE();
+ return ret;
+}
+
+#ifdef RX_PACKET_COALESCE
+mlan_status wlan_cmd_rx_pkt_coalesce_cfg(pmlan_private pmpriv,
+ HostCmd_DS_COMMAND *cmd,
+ t_u16 cmd_action, t_void *pdata_buf)
+{
+ mlan_ds_misc_rx_packet_coalesce *rx_pkt_cfg =
+ (mlan_ds_misc_rx_packet_coalesce *)pdata_buf;
+ HostCmd_DS_RX_PKT_COAL_CFG *prx_coal_cfg =
+ (HostCmd_DS_RX_PKT_COAL_CFG *)&cmd->params.rx_pkt_coal_cfg;
+
+ ENTER();
+
+ cmd->command = wlan_cpu_to_le16(HostCmd_CMD_RX_PKT_COALESCE_CFG);
+ prx_coal_cfg->action = wlan_cpu_to_le16(cmd_action);
+
+ if (cmd_action == HostCmd_ACT_GEN_SET) {
+ prx_coal_cfg->packet_threshold =
+ wlan_cpu_to_le32(rx_pkt_cfg->packet_threshold);
+ prx_coal_cfg->delay = wlan_cpu_to_le16(rx_pkt_cfg->delay);
+ PRINTM(MCMND,
+ "Set RX coal config: packet threshold=%d delay=%d\n",
+ rx_pkt_cfg->packet_threshold, rx_pkt_cfg->delay);
+ cmd->size = wlan_cpu_to_le16(
+ S_DS_GEN + sizeof(HostCmd_DS_RX_PKT_COAL_CFG));
+ } else {
+ cmd->size = wlan_cpu_to_le16(S_DS_GEN + sizeof(cmd_action));
+ }
+
+ LEAVE();
+ return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ * @brief This function handles the command response of RX_PACKET_COAL_CFG
+ *
+ * @param pmpriv A pointer to mlan_private structure
+ * @param resp A pointer to HostCmd_DS_COMMAND
+ * @param pioctl_buf A pointer to mlan_ioctl_req structure
+ *
+ * @return MLAN_STATUS_SUCCESS
+ */
+mlan_status wlan_ret_rx_pkt_coalesce_cfg(pmlan_private pmpriv,
+ const HostCmd_DS_COMMAND *resp,
+ mlan_ioctl_req *pioctl_buf)
+{
+ mlan_ds_misc_cfg *pcfg = MNULL;
+ const HostCmd_DS_RX_PKT_COAL_CFG *presp_cfg =
+ &resp->params.rx_pkt_coal_cfg;
+
+ ENTER();
+
+ if (pioctl_buf) {
+ pcfg = (mlan_ds_misc_cfg *)pioctl_buf->pbuf;
+ pcfg->param.rx_coalesce.packet_threshold =
+ wlan_le32_to_cpu(presp_cfg->packet_threshold);
+ pcfg->param.rx_coalesce.delay =
+ wlan_le16_to_cpu(presp_cfg->delay);
+ PRINTM(MCMND,
+ "Get rx pkt coalesce info: packet threshold=%d delay=%d\n",
+ pcfg->param.rx_coalesce.packet_threshold,
+ pcfg->param.rx_coalesce.delay);
+ pioctl_buf->buf_len = sizeof(mlan_ds_misc_rx_packet_coalesce);
+ }
+
+ LEAVE();
+ return MLAN_STATUS_SUCCESS;
+}
+
+#endif
+
+/**
+ * @brief This function download the vdll block.
+ *
+ * @param pmadapter A pointer to mlan_adapter structure
+ * @param block A pointer to VDLL block
+ * @param block_len The VDLL block length
+ *
+ * @return MLAN_STATUS_SUCCESS
+ */
+mlan_status wlan_download_vdll_block(mlan_adapter *pmadapter, t_u8 *block,
+ t_u16 block_len)
+{
+ mlan_status status = MLAN_STATUS_FAILURE;
+ mlan_status ret = MLAN_STATUS_PENDING;
+#if defined(SDIO) || defined(PCIE)
+ pvdll_dnld_ctrl ctrl = &pmadapter->vdll_ctrl;
+#endif
+ mlan_buffer *pmbuf = MNULL;
+ mlan_private *pmpriv = wlan_get_priv(pmadapter, MLAN_BSS_ROLE_ANY);
+ HostCmd_DS_GEN *cmd_hdr = MNULL;
+ t_u16 msg_len = block_len + sizeof(HostCmd_DS_GEN);
+#ifdef USB
+ t_u32 tmp;
+#endif
+ ENTER();
+#if defined(SDIO) || defined(PCIE)
+ if (!IS_USB(pmadapter->card_type)) {
+ pmbuf = ctrl->cmd_buf;
+ if (pmbuf)
+ pmbuf->data_offset += pmadapter->ops.intf_header_len;
+ }
+#endif
+#ifdef USB
+ if (IS_USB(pmadapter->card_type)) {
+ pmbuf = wlan_alloc_mlan_buffer(pmadapter,
+ MRVDRV_SIZE_OF_CMD_BUFFER, 0,
+ MOAL_MALLOC_BUFFER);
+ if (pmbuf) {
+ tmp = wlan_cpu_to_le32(MLAN_USB_TYPE_VDLL);
+ memcpy_ext(pmadapter,
+ (t_u8 *)(pmbuf->pbuf + pmbuf->data_offset),
+ (t_u8 *)&tmp, MLAN_TYPE_LEN, MLAN_TYPE_LEN);
+ pmbuf->data_offset += MLAN_TYPE_LEN;
+ }
+ }
+#endif
+ if (!pmbuf) {
+ PRINTM(MERROR, "dnld vdll: Fail to alloc vdll buf");
+ goto done;
+ }
+ cmd_hdr = (HostCmd_DS_GEN *)(pmbuf->pbuf + pmbuf->data_offset);
+ cmd_hdr->command = wlan_cpu_to_le16(HostCmd_CMD_VDLL);
+ cmd_hdr->seq_num = wlan_cpu_to_le16(0xFF00);
+ cmd_hdr->size = wlan_cpu_to_le16(msg_len);
+
+ pmadapter->callbacks.moal_memcpy_ext(pmadapter->pmoal_handle,
+ pmbuf->pbuf + pmbuf->data_offset +
+ sizeof(HostCmd_DS_GEN),
+ block, block_len, block_len);
+
+ pmbuf->data_len = msg_len;
+
+#if defined(SDIO) || defined(PCIE)
+ if (!IS_USB(pmadapter->card_type)) {
+ pmbuf->data_offset -= pmadapter->ops.intf_header_len;
+ pmbuf->data_len += pmadapter->ops.intf_header_len;
+ }
+#endif
+#ifdef USB
+ if (IS_USB(pmadapter->card_type)) {
+ pmbuf->data_offset -= MLAN_TYPE_LEN;
+ pmbuf->data_len += MLAN_TYPE_LEN;
+ }
+#endif
+ PRINTM_NETINTF(MCMND, pmpriv);
+ PRINTM(MCMND, "DNLD_VDLL : block_len=%d\n", block_len);
+
+ ret = pmadapter->ops.host_to_card(pmpriv, MLAN_TYPE_VDLL, pmbuf, MNULL);
+
+ if (ret == MLAN_STATUS_FAILURE)
+ PRINTM(MERROR, "DNLD_VDLL: Host to Card Failed\n");
+ else
+ status = MLAN_STATUS_SUCCESS;
+
+done:
+ if ((ret == MLAN_STATUS_FAILURE) || (ret == MLAN_STATUS_SUCCESS)) {
+#ifdef USB
+ if (IS_USB(pmadapter->card_type))
+ wlan_free_mlan_buffer(pmadapter, pmbuf);
+#endif
+ }
+ LEAVE();
+ return status;
+}
+
+/**
+ * @brief The function Get the VDLL image from moal
+ *
+ * @param pmadapter A pointer to mlan_adapter structure
+ * @param offset offset
+ *
+ * @return MLAN_STATUS_SUCCESS
+ *
+ */
+static mlan_status wlan_get_vdll_image(pmlan_adapter pmadapter, t_u32 vdll_len)
+{
+ mlan_status status = MLAN_STATUS_SUCCESS;
+ vdll_dnld_ctrl *ctrl = &pmadapter->vdll_ctrl;
+ pmlan_callbacks pcb = &pmadapter->callbacks;
+
+ ENTER();
+
+ if (ctrl->vdll_mem) {
+ PRINTM(MCMND, "VDLL mem is not empty: %p len=%d\n",
+ ctrl->vdll_mem, ctrl->vdll_len);
+ goto done;
+ }
+ if (pcb->moal_vmalloc && pcb->moal_vfree)
+ status = pcb->moal_vmalloc(pmadapter->pmoal_handle, vdll_len,
+ (t_u8 **)&ctrl->vdll_mem);
+ else
+ status = pcb->moal_malloc(pmadapter->pmoal_handle, vdll_len,
+ MLAN_MEM_DEF,
+ (t_u8 **)&ctrl->vdll_mem);
+
+ if (status != MLAN_STATUS_SUCCESS) {
+ PRINTM(MERROR, "VDLL: Fail to alloc vdll memory");
+ goto done;
+ }
+
+ if (MLAN_STATUS_SUCCESS !=
+ pcb->moal_get_vdll_data(pmadapter->pmoal_handle, vdll_len,
+ ctrl->vdll_mem)) {
+ PRINTM(MERROR, "VDLL: firmware image not available\n");
+ status = MLAN_STATUS_FAILURE;
+ if (pcb->moal_vmalloc && pcb->moal_vfree)
+ pcb->moal_vfree(pmadapter->pmoal_handle,
+ (t_u8 *)ctrl->vdll_mem);
+ else
+ pcb->moal_mfree(pmadapter->pmoal_handle,
+ (t_u8 *)ctrl->vdll_mem);
+ ctrl->vdll_mem = MNULL;
+ ctrl->vdll_len = 0;
+ goto done;
+ }
+ /*allocate a memory to store all VDLL images*/
+ ctrl->vdll_len = vdll_len;
+ PRINTM(MMSG, "VDLL image: len=%d\n", ctrl->vdll_len);
+done:
+ LEAVE();
+ return status;
+}
+
+/**
+ * @brief This function handle the multi_chan info event
+ *
+ * @param pmpriv A pointer to mlan_private structure
+ * @param pevent A pointer to event buffer
+ *
+ * @return MLAN_STATUS_SUCCESS
+ */
+mlan_status wlan_process_vdll_event(pmlan_private pmpriv, pmlan_buffer pevent)
+{
+ mlan_status status = MLAN_STATUS_SUCCESS;
+ vdll_ind *ind = MNULL;
+ t_u32 offset = 0;
+ t_u16 block_len = 0;
+ mlan_adapter *pmadapter = pmpriv->adapter;
+ vdll_dnld_ctrl *ctrl = &pmadapter->vdll_ctrl;
+
+ ENTER();
+ ind = (vdll_ind *)(pevent->pbuf + pevent->data_offset +
+ sizeof(mlan_event_id));
+ switch (wlan_le16_to_cpu(ind->type)) {
+ case VDLL_IND_TYPE_REQ:
+ offset = wlan_le32_to_cpu(ind->offset);
+ block_len = wlan_le16_to_cpu(ind->block_len);
+ PRINTM(MEVENT, "VDLL_IND: type=%d offset = 0x%x, len = %d\n",
+ wlan_le16_to_cpu(ind->type), offset, block_len);
+ if (offset <= ctrl->vdll_len) {
+ block_len = MIN(block_len, ctrl->vdll_len - offset);
+ if (!pmadapter->cmd_sent) {
+ status = wlan_download_vdll_block(
+ pmadapter, ctrl->vdll_mem + offset,
+ block_len);
+ if (status)
+ PRINTM(MERROR,
+ "Fail to download VDLL block\n");
+ } else {
+ PRINTM(MCMND,
+ "cmd_sent=1, delay download VDLL block\n");
+ ctrl->pending_block_len = block_len;
+ ctrl->pending_block = ctrl->vdll_mem + offset;
+ }
+ } else {
+ PRINTM(MERROR,
+ "Invalid VDLL req: offset=0x%x, len=%d, vdll_len=%d\n",
+ offset, block_len, ctrl->vdll_len);
+ }
+ break;
+
+ case VDLL_IND_TYPE_OFFSET:
+ offset = wlan_le32_to_cpu(ind->offset);
+ PRINTM(MEVENT, "VDLL_IND (OFFSET): offset=0x%x\n", offset);
+ wlan_get_vdll_image(pmadapter, offset);
+ break;
+ default:
+ PRINTM(MERROR, "unknow vdll ind type=%d\n", ind->type);
+ break;
+ }
+ LEAVE();
+ return status;
+}
+
+/**
+ * @brief This function prepares command of get_hw_spec.
+ *
+ * @param pmpriv A pointer to mlan_private structure
+ * @param pcmd A pointer to HostCmd_DS_COMMAND structure
+ *
+ * @return MLAN_STATUS_SUCCESS
+ */
+mlan_status wlan_cmd_get_hw_spec(pmlan_private pmpriv, HostCmd_DS_COMMAND *pcmd)
+{
+ HostCmd_DS_GET_HW_SPEC *hw_spec = &pcmd->params.hw_spec;
+
+ ENTER();
+
+ pcmd->command = wlan_cpu_to_le16(HostCmd_CMD_GET_HW_SPEC);
+ pcmd->size =
+ wlan_cpu_to_le16(sizeof(HostCmd_DS_GET_HW_SPEC) + S_DS_GEN);
+ memcpy_ext(pmpriv->adapter, hw_spec->permanent_addr, pmpriv->curr_addr,
+ MLAN_MAC_ADDR_LENGTH, MLAN_MAC_ADDR_LENGTH);
+
+ LEAVE();
+ return MLAN_STATUS_SUCCESS;
+}
+
+#ifdef SDIO
+/**
+ * @brief This function prepares command of sdio rx aggr command.
+ *
+ * @param pcmd A pointer to HostCmd_DS_COMMAND structure
+ * @param cmd_action Command action: GET or SET
+ * @param pdata_buf A pointer to new setting buf
+
+ * @return MLAN_STATUS_SUCCESS
+ */
+mlan_status wlan_cmd_sdio_rx_aggr_cfg(HostCmd_DS_COMMAND *pcmd,
+ t_u16 cmd_action, t_void *pdata_buf)
+{
+ HostCmd_DS_SDIO_SP_RX_AGGR_CFG *cfg = &pcmd->params.sdio_rx_aggr;
+
+ pcmd->command = wlan_cpu_to_le16(HostCmd_CMD_SDIO_SP_RX_AGGR_CFG);
+ pcmd->size = wlan_cpu_to_le16(sizeof(HostCmd_DS_SDIO_SP_RX_AGGR_CFG) +
+ S_DS_GEN);
+ cfg->action = cmd_action;
+ if (cmd_action == HostCmd_ACT_GEN_SET)
+ cfg->enable = *(t_u8 *)pdata_buf;
+ return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ * @brief This function handles the command response of sdio rx aggr command
+ *
+ * @param pmpriv A pointer to mlan_private structure
+ * @param resp A pointer to HostCmd_DS_COMMAND
+ *
+ * @return MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ */
+mlan_status wlan_ret_sdio_rx_aggr_cfg(pmlan_private pmpriv,
+ HostCmd_DS_COMMAND *resp)
+{
+ mlan_adapter *pmadapter = pmpriv->adapter;
+ HostCmd_DS_SDIO_SP_RX_AGGR_CFG *cfg = &resp->params.sdio_rx_aggr;
+
+ pmadapter->pcard_sd->sdio_rx_aggr_enable = cfg->enable;
+ pmadapter->pcard_sd->sdio_rx_block_size =
+ wlan_le16_to_cpu(cfg->sdio_block_size);
+ PRINTM(MMSG, "SDIO rx aggr: %d block_size=%d\n", cfg->enable,
+ pmadapter->pcard_sd->sdio_rx_block_size);
+ if (!pmadapter->pcard_sd->sdio_rx_block_size)
+ pmadapter->pcard_sd->sdio_rx_aggr_enable = MFALSE;
+ if (pmadapter->pcard_sd->sdio_rx_aggr_enable) {
+ pmadapter->pcard_sd->max_sp_rx_size = SDIO_CMD53_MAX_SIZE;
+ wlan_re_alloc_sdio_rx_mpa_buffer(pmadapter);
+ }
+ return MLAN_STATUS_SUCCESS;
+}
+#endif
+
+/**
+ * @brief This function prepares command of set_cfg_data.
+ *
+ * @param pmpriv A pointer to mlan_private strcture
+ * @param pcmd A pointer to HostCmd_DS_COMMAND structure
+ * @param cmd_action Command action: GET or SET
+ * @param pdata_buf A pointer to cal_data buf
+ *
+ * @return MLAN_STATUS_SUCCESS
+ */
+mlan_status wlan_cmd_cfg_data(pmlan_private pmpriv, HostCmd_DS_COMMAND *pcmd,
+ t_u16 cmd_action, t_u32 cmd_oid,
+ t_void *pdata_buf)
+{
+ mlan_status ret = MLAN_STATUS_SUCCESS;
+ HostCmd_DS_802_11_CFG_DATA *pcfg_data = &(pcmd->params.cfg_data);
+ pmlan_adapter pmadapter = pmpriv->adapter;
+ t_u32 len = 0;
+ t_u32 data_offset;
+ t_u8 *temp_pcmd = (t_u8 *)pcmd;
+
+ ENTER();
+
+ data_offset = S_DS_GEN + sizeof(HostCmd_DS_802_11_CFG_DATA);
+
+ if ((cmd_oid == OID_TYPE_CAL) && (pmadapter->pcal_data) &&
+ (pmadapter->cal_data_len > 0)) {
+ len = wlan_parse_cal_cfg((t_u8 *)pmadapter->pcal_data,
+ pmadapter->cal_data_len,
+ (t_u8 *)(temp_pcmd + data_offset));
+ }
+
+ pcfg_data->action = cmd_action;
+ pcfg_data->type = cmd_oid;
+ pcfg_data->data_len = len;
+
+ pcmd->command = HostCmd_CMD_CFG_DATA;
+ pcmd->size = pcfg_data->data_len + data_offset;
+
+ pcmd->command = wlan_cpu_to_le16(pcmd->command);
+ pcmd->size = wlan_cpu_to_le16(pcmd->size);
+
+ pcfg_data->action = wlan_cpu_to_le16(pcfg_data->action);
+ pcfg_data->type = wlan_cpu_to_le16(pcfg_data->type);
+ pcfg_data->data_len = wlan_cpu_to_le16(pcfg_data->data_len);
+
+ LEAVE();
+ return ret;
+}
+
+/**
+ * @brief This function handles the command response of set_cfg_data
+ *
+ * @param pmpriv A pointer to mlan_private structure
+ * @param resp A pointer to HostCmd_DS_COMMAND
+ * @param pioctl_buf A pointer to A pointer to mlan_ioctl_req
+ *
+ * @return MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ */
+mlan_status wlan_ret_cfg_data(IN pmlan_private pmpriv,
+ IN HostCmd_DS_COMMAND *resp,
+ IN t_void *pioctl_buf)
+{
+ mlan_status ret = MLAN_STATUS_SUCCESS;
+ t_u8 event_buf[100];
+ mlan_cmdresp_event *pevent = (mlan_cmdresp_event *)event_buf;
+ mlan_adapter *pmadapter = pmpriv->adapter;
+ HostCmd_DS_802_11_CFG_DATA *pcfg_data = &resp->params.cfg_data;
+ t_u16 action;
+ t_u16 type;
+
+ ENTER();
+
+ if (resp->result != HostCmd_RESULT_OK) {
+ PRINTM(MERROR, "CFG data cmd resp failed\n");
+ ret = MLAN_STATUS_FAILURE;
+ }
+
+ if (!pmadapter->pdpd_data &&
+ (pmadapter->dpd_data_len == UNKNOW_DPD_LENGTH) &&
+ pmadapter->hw_status == WlanHardwareStatusGetHwSpec) {
+ action = wlan_le16_to_cpu(pcfg_data->action);
+ type = wlan_le16_to_cpu(pcfg_data->type);
+ if (action == HostCmd_ACT_GEN_GET && (type == OID_TYPE_DPD)) {
+ pcfg_data->action =
+ wlan_cpu_to_le16(HostCmd_ACT_GEN_SET);
+ pevent->bss_index = pmpriv->bss_index;
+ pevent->event_id = MLAN_EVENT_ID_STORE_HOST_CMD_RESP;
+ pevent->resp = (t_u8 *)resp;
+ pevent->event_len = wlan_le16_to_cpu(resp->size);
+ wlan_recv_event(pmpriv,
+ MLAN_EVENT_ID_STORE_HOST_CMD_RESP,
+ (mlan_event *)pevent);
+ }
+ }
+
+ LEAVE();
+ return ret;
+}
+
+/**
+ * @brief This function prepares command of mac_control.
+ *
+ * @param pmpriv A pointer to mlan_private structure
+ * @param pcmd A pointer to HostCmd_DS_COMMAND structure
+ * @param cmd_action Command action
+ * @param pdata_buf A pointer to command information buffer
+ *
+ * @return MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ */
+mlan_status wlan_cmd_mac_control(pmlan_private pmpriv, HostCmd_DS_COMMAND *pcmd,
+ t_u16 cmd_action, t_void *pdata_buf)
+{
+ HostCmd_DS_MAC_CONTROL *pmac = &pcmd->params.mac_ctrl;
+ t_u32 action = *((t_u32 *)pdata_buf);
+
+ ENTER();
+
+ if (cmd_action != HostCmd_ACT_GEN_SET) {
+ PRINTM(MERROR, "wlan_cmd_mac_control(): support SET only.\n");
+ LEAVE();
+ return MLAN_STATUS_FAILURE;
+ }
+
+ pcmd->command = wlan_cpu_to_le16(HostCmd_CMD_MAC_CONTROL);
+ pcmd->size =
+ wlan_cpu_to_le16(sizeof(HostCmd_DS_MAC_CONTROL) + S_DS_GEN);
+ pmac->action = wlan_cpu_to_le32(action);
+
+ LEAVE();
+ return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ * @brief This function handles the command response of mac_control
+ *
+ * @param pmpriv A pointer to mlan_private structure
+ * @param resp A pointer to HostCmd_DS_COMMAND
+ * @param pioctl_buf A pointer to mlan_ioctl_req structure
+ *
+ * @return MLAN_STATUS_SUCCESS
+ */
+mlan_status wlan_ret_mac_control(pmlan_private pmpriv, HostCmd_DS_COMMAND *resp,
+ mlan_ioctl_req *pioctl_buf)
+{
+ ENTER();
+ LEAVE();
+ return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ * @brief This function handles the command response of get_hw_spec
+ *
+ * @param pmpriv A pointer to mlan_private structure
+ * @param resp A pointer to HostCmd_DS_COMMAND
+ * @param pioctl_buf A pointer to command buffer
+ *
+ * @return MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ */
+mlan_status wlan_ret_get_hw_spec(pmlan_private pmpriv, HostCmd_DS_COMMAND *resp,
+ t_void *pioctl_buf)
+{
+ HostCmd_DS_GET_HW_SPEC *hw_spec = &resp->params.hw_spec;
+ mlan_adapter *pmadapter = pmpriv->adapter;
+ mlan_status ret = MLAN_STATUS_SUCCESS;
+ t_u32 i;
+ t_u16 left_len;
+ t_u16 tlv_type = 0;
+ t_u16 tlv_len = 0;
+ MrvlIEtypes_fw_ver_info_t *api_rev = MNULL;
+ t_u16 api_id = 0;
+ MrvlIEtypesHeader_t *tlv = MNULL;
+ pmlan_ioctl_req pioctl_req = (mlan_ioctl_req *)pioctl_buf;
+ MrvlIEtypes_Max_Conn_t *tlv_max_conn = MNULL;
+ MrvlIEtypes_Extension_t *ext_tlv = MNULL;
+ MrvlIEtypes_fw_cap_info_t *fw_cap_tlv = MNULL;
+
+ ENTER();
+
+ pmadapter->fw_cap_info = wlan_le32_to_cpu(hw_spec->fw_cap_info);
+ pmadapter->fw_cap_info &= pmadapter->init_para.dev_cap_mask;
+
+ PRINTM(MMSG, "fw_cap_info=0x%x, dev_cap_mask=0x%x\n",
+ wlan_le32_to_cpu(hw_spec->fw_cap_info),
+ pmadapter->init_para.dev_cap_mask);
+#ifdef STA_SUPPORT
+ if (IS_SUPPORT_MULTI_BANDS(pmadapter))
+ pmadapter->fw_bands = (t_u8)GET_FW_DEFAULT_BANDS(pmadapter);
+ else
+ pmadapter->fw_bands = BAND_B;
+
+ if ((pmadapter->fw_bands & BAND_A) && (pmadapter->fw_bands & BAND_GN))
+ pmadapter->fw_bands |= BAND_AN;
+ if (!(pmadapter->fw_bands & BAND_G) && (pmadapter->fw_bands & BAND_GN))
+ pmadapter->fw_bands &= ~BAND_GN;
+
+ pmadapter->config_bands = pmadapter->fw_bands;
+ for (i = 0; i < pmadapter->priv_num; i++) {
+ if (pmadapter->priv[i])
+ pmadapter->priv[i]->config_bands = pmadapter->fw_bands;
+ }
+
+ if (pmadapter->fw_bands & BAND_A) {
+ if (pmadapter->fw_bands & BAND_AN) {
+ pmadapter->config_bands |= BAND_AN;
+ for (i = 0; i < pmadapter->priv_num; i++) {
+ if (pmadapter->priv[i])
+ pmadapter->priv[i]->config_bands |=
+ BAND_AN;
+ }
+ }
+ if (pmadapter->fw_bands & BAND_AAC) {
+ pmadapter->config_bands |= BAND_AAC;
+ for (i = 0; i < pmadapter->priv_num; i++) {
+ if (pmadapter->priv[i])
+ pmadapter->priv[i]->config_bands |=
+ BAND_AAC;
+ }
+ }
+ if (pmadapter->fw_bands & BAND_GAC) {
+ pmadapter->config_bands |= BAND_GAC;
+ for (i = 0; i < pmadapter->priv_num; i++) {
+ if (pmadapter->priv[i])
+ pmadapter->priv[i]->config_bands |=
+ BAND_GAC;
+ }
+ }
+ pmadapter->adhoc_start_band = BAND_A;
+ pmpriv->adhoc_channel = DEFAULT_AD_HOC_CHANNEL_A;
+ } else if (pmadapter->fw_bands & BAND_G) {
+ pmadapter->adhoc_start_band = BAND_G | BAND_B;
+ pmpriv->adhoc_channel = DEFAULT_AD_HOC_CHANNEL;
+ } else if (pmadapter->fw_bands & BAND_B) {
+ pmadapter->adhoc_start_band = BAND_B;
+ pmpriv->adhoc_channel = DEFAULT_AD_HOC_CHANNEL;
+ }
+#endif /* STA_SUPPORT */
+
+ pmadapter->fw_release_number =
+ wlan_le32_to_cpu(hw_spec->fw_release_number);
+ pmadapter->number_of_antenna =
+ wlan_le16_to_cpu(hw_spec->number_of_antenna) & 0x00ff;
+ pmadapter->antinfo =
+ (wlan_le16_to_cpu(hw_spec->number_of_antenna) & 0xff00) >> 8;
+ PRINTM(MCMND, "num_ant=%d, antinfo=0x%x\n",
+ pmadapter->number_of_antenna, pmadapter->antinfo);
+
+ PRINTM(MINFO, "GET_HW_SPEC: fw_release_number- 0x%X\n",
+ pmadapter->fw_release_number);
+ PRINTM(MINFO, "GET_HW_SPEC: Permanent addr- " MACSTR "\n",
+ MAC2STR(hw_spec->permanent_addr));
+ PRINTM(MINFO, "GET_HW_SPEC: hw_if_version=0x%X version=0x%X\n",
+ wlan_le16_to_cpu(hw_spec->hw_if_version),
+ wlan_le16_to_cpu(hw_spec->version));
+
+ if (pmpriv->curr_addr[0] == 0xff)
+ memmove(pmadapter, pmpriv->curr_addr, hw_spec->permanent_addr,
+ MLAN_MAC_ADDR_LENGTH);
+ memmove(pmadapter, pmadapter->permanent_addr, hw_spec->permanent_addr,
+ MLAN_MAC_ADDR_LENGTH);
+ pmadapter->hw_dot_11n_dev_cap =
+ wlan_le32_to_cpu(hw_spec->dot_11n_dev_cap);
+ pmadapter->hw_dev_mcs_support = hw_spec->dev_mcs_support;
+ for (i = 0; i < pmadapter->priv_num; i++) {
+ if (pmadapter->priv[i])
+ wlan_update_11n_cap(pmadapter->priv[i]);
+ }
+
+ wlan_show_dot11ndevcap(pmadapter, pmadapter->hw_dot_11n_dev_cap);
+ wlan_show_devmcssupport(pmadapter, pmadapter->hw_dev_mcs_support);
+#if defined(PCIE9098) || defined(SD9098) || defined(USB9098) || \
+ defined(PCIE9097) || defined(SD9097) || defined(USB9097)
+ pmadapter->user_htstream = pmadapter->hw_dev_mcs_support;
+ /** separate stream config for 2.4G and 5G, will be changed according to
+ * antenna cfg*/
+ if (pmadapter->fw_bands & BAND_A)
+ pmadapter->user_htstream |= (pmadapter->user_htstream << 8);
+ PRINTM(MCMND, "user_htstream=0x%x\n", pmadapter->user_htstream);
+#endif
+
+ if (ISSUPP_BEAMFORMING(pmadapter->hw_dot_11n_dev_cap)) {
+ PRINTM(MCMND, "Enable Beamforming\n");
+ for (i = 0; i < pmadapter->priv_num; i++) {
+ if (pmadapter->priv[i])
+ pmadapter->priv[i]->tx_bf_cap =
+ pmadapter->pcard_info
+ ->default_11n_tx_bf_cap;
+ }
+ }
+ pmadapter->hw_dot_11ac_dev_cap =
+ wlan_le32_to_cpu(hw_spec->Dot11acDevCap);
+ pmadapter->hw_dot_11ac_mcs_support =
+ wlan_le32_to_cpu(hw_spec->Dot11acMcsSupport);
+ for (i = 0; i < pmadapter->priv_num; i++) {
+ if (pmadapter->priv[i])
+ wlan_update_11ac_cap(pmadapter->priv[i]);
+ }
+ wlan_show_dot11acdevcap(pmadapter, pmadapter->hw_dot_11ac_dev_cap);
+ wlan_show_dot11acmcssupport(pmadapter,
+ pmadapter->hw_dot_11ac_mcs_support);
+
+#ifdef SDIO
+ if (IS_SD(pmadapter->card_type)) {
+ pmadapter->pcard_sd->mp_end_port =
+ wlan_le16_to_cpu(hw_spec->mp_end_port);
+
+ for (i = 1; i <= (unsigned)(MAX_PORT -
+ pmadapter->pcard_sd->mp_end_port);
+ i++)
+ pmadapter->pcard_sd->mp_data_port_mask &=
+ ~(1 << (MAX_PORT - i));
+ }
+#endif
+
+ pmadapter->max_mgmt_ie_index =
+ wlan_le16_to_cpu(hw_spec->mgmt_buf_count);
+ PRINTM(MCMND, "GET_HW_SPEC: mgmt IE count=%d\n",
+ pmadapter->max_mgmt_ie_index);
+ if (!pmadapter->max_mgmt_ie_index ||
+ pmadapter->max_mgmt_ie_index > MAX_MGMT_IE_INDEX)
+ pmadapter->max_mgmt_ie_index = MAX_MGMT_IE_INDEX;
+
+ pmadapter->region_code = wlan_le16_to_cpu(hw_spec->region_code);
+ for (i = 0; i < MRVDRV_MAX_REGION_CODE; i++) {
+ /* Use the region code to search for the index */
+ if (pmadapter->region_code == region_code_index[i])
+ break;
+ }
+ /* If it's unidentified region code, use the default */
+ if (i >= MRVDRV_MAX_REGION_CODE) {
+ pmadapter->region_code = MRVDRV_DEFAULT_REGION_CODE;
+ PRINTM(MWARN,
+ "unidentified region code, use the default (0x%02x)\n",
+ MRVDRV_DEFAULT_REGION_CODE);
+ }
+ /* Synchronize CFP code with region code */
+ pmadapter->cfp_code_bg = pmadapter->region_code;
+ pmadapter->cfp_code_a = pmadapter->region_code;
+
+ if (pmadapter->fw_cap_info & ENHANCE_EXT_SCAN_ENABLE)
+ pmadapter->ext_scan_enh = MTRUE;
+
+#ifdef SDIO
+ if (IS_SD(pmadapter->card_type)) {
+ if ((pmadapter->fw_cap_info & SDIO_SP_RX_AGGR_ENABLE) &&
+ pmadapter->pcard_sd->sdio_rx_aggr_enable) {
+ t_u8 sdio_sp_rx_aggr = MTRUE;
+ ret = wlan_prepare_cmd(pmpriv,
+ HostCmd_CMD_SDIO_SP_RX_AGGR_CFG,
+ HostCmd_ACT_GEN_SET, 0, MNULL,
+ &sdio_sp_rx_aggr);
+ if (ret) {
+ ret = MLAN_STATUS_FAILURE;
+ goto done;
+ }
+ } else {
+ pmadapter->pcard_sd->sdio_rx_aggr_enable = MFALSE;
+ PRINTM(MCMND, "FW: SDIO rx aggr disabled 0x%x\n",
+ pmadapter->fw_cap_info);
+ }
+ }
+#endif
+
+ if (wlan_set_regiontable(pmpriv, (t_u8)pmadapter->region_code,
+ pmadapter->fw_bands)) {
+ if (pioctl_req)
+ pioctl_req->status_code = MLAN_ERROR_CMD_SCAN_FAIL;
+ ret = MLAN_STATUS_FAILURE;
+ goto done;
+ }
+#ifdef STA_SUPPORT
+ if (wlan_11d_set_universaltable(pmpriv, pmadapter->fw_bands)) {
+ if (pioctl_req)
+ pioctl_req->status_code = MLAN_ERROR_CMD_SCAN_FAIL;
+ ret = MLAN_STATUS_FAILURE;
+ goto done;
+ }
+#endif /* STA_SUPPORT */
+ if (pmadapter->fw_cap_info & FW_CAPINFO_ECSA) {
+ t_u8 ecsa_enable = MTRUE;
+ pmadapter->ecsa_enable = MTRUE;
+ PRINTM(MCMND, "pmadapter->ecsa_enable=%d\n",
+ pmadapter->ecsa_enable);
+ ret = wlan_prepare_cmd(pmpriv, HostCmd_CMD_802_11_SNMP_MIB,
+ HostCmd_ACT_GEN_SET, ECSAEnable_i, MNULL,
+ &ecsa_enable);
+ if (ret) {
+ ret = MLAN_STATUS_FAILURE;
+ goto done;
+ }
+ }
+ if (pmadapter->fw_cap_info & FW_CAPINFO_GET_LOG) {
+ pmadapter->getlog_enable = MTRUE;
+ PRINTM(MCMND, "pmadapter->getlog_enable=%d\n",
+ pmadapter->getlog_enable);
+ }
+
+ left_len = resp->size - sizeof(HostCmd_DS_GET_HW_SPEC) - S_DS_GEN;
+ tlv = (MrvlIEtypesHeader_t *)((t_u8 *)hw_spec +
+ sizeof(HostCmd_DS_GET_HW_SPEC));
+ while (left_len > sizeof(MrvlIEtypesHeader_t)) {
+ tlv_type = wlan_le16_to_cpu(tlv->type);
+ tlv_len = wlan_le16_to_cpu(tlv->len);
+ switch (tlv_type) {
+ case TLV_TYPE_FW_VER_INFO:
+ api_rev = (MrvlIEtypes_fw_ver_info_t *)tlv;
+ api_id = wlan_le16_to_cpu(api_rev->api_id);
+ switch (api_id) {
+ case FW_API_VER_ID:
+ pmadapter->fw_ver = api_rev->major_ver;
+ pmadapter->fw_min_ver = api_rev->minor_ver;
+ PRINTM(MCMND, "fw ver=%d.%d\n",
+ api_rev->major_ver, api_rev->minor_ver);
+ break;
+ case UAP_FW_API_VER_ID:
+ pmadapter->uap_fw_ver = api_rev->major_ver;
+ PRINTM(MCMND, "uap fw ver=%d.%d\n",
+ api_rev->major_ver, api_rev->minor_ver);
+ break;
+ case CHANRPT_API_VER_ID:
+ pmadapter->chanrpt_param_bandcfg =
+ api_rev->minor_ver;
+ PRINTM(MCMND, "chanrpt api ver=%d.%d\n",
+ api_rev->major_ver, api_rev->minor_ver);
+ break;
+ default:
+ break;
+ }
+ break;
+ case TLV_TYPE_MAX_CONN:
+ tlv_max_conn = (MrvlIEtypes_Max_Conn_t *)tlv;
+ PRINTM(MMSG, "max_p2p_conn = %d, max_sta_conn = %d\n",
+ tlv_max_conn->max_p2p_conn,
+ tlv_max_conn->max_sta_conn);
+ if (tlv_max_conn->max_p2p_conn &&
+ tlv_max_conn->max_sta_conn)
+ pmadapter->max_sta_conn =
+ MIN(tlv_max_conn->max_sta_conn,
+ tlv_max_conn->max_p2p_conn);
+ else if (tlv_max_conn->max_sta_conn)
+ pmadapter->max_sta_conn =
+ tlv_max_conn->max_sta_conn;
+ else if (tlv_max_conn->max_p2p_conn)
+ pmadapter->max_sta_conn =
+ tlv_max_conn->max_p2p_conn;
+ else
+ pmadapter->max_sta_conn = 0;
+ break;
+ case TLV_TYPE_EXTENSION_ID:
+ ext_tlv = (MrvlIEtypes_Extension_t *)tlv;
+ if (ext_tlv->ext_id == HE_CAPABILITY) {
+ ext_tlv->type = tlv_type;
+ ext_tlv->len = tlv_len;
+ wlan_update_11ax_cap(
+ pmadapter,
+ (MrvlIEtypes_Extension_t *)ext_tlv);
+ }
+
+ break;
+ case TLV_TYPE_FW_CAP_INFO:
+ fw_cap_tlv = (MrvlIEtypes_fw_cap_info_t *)tlv;
+ pmadapter->fw_cap_info =
+ wlan_le32_to_cpu(fw_cap_tlv->fw_cap_info);
+ pmadapter->fw_cap_ext =
+ wlan_le32_to_cpu(fw_cap_tlv->fw_cap_ext);
+ PRINTM(MCMND, "fw_cap_info=0x%x fw_cap_ext=0x%x\n",
+ pmadapter->fw_cap_info, pmadapter->fw_cap_ext);
+ break;
+ default:
+ break;
+ }
+ left_len -= (sizeof(MrvlIEtypesHeader_t) + tlv_len);
+ tlv = (MrvlIEtypesHeader_t *)((t_u8 *)tlv + tlv_len +
+ sizeof(MrvlIEtypesHeader_t));
+ }
+done:
+ LEAVE();
+ return ret;
+}
+
+/**
+ * @brief This function prepares command of radio_control.
+ *
+ * @param pmpriv A pointer to mlan_private structure
+ * @param cmd A pointer to HostCmd_DS_COMMAND structure
+ * @param cmd_action The action: GET or SET
+ * @param pdata_buf A pointer to data buffer
+ *
+ * @return MLAN_STATUS_SUCCESS
+ */
+mlan_status wlan_cmd_802_11_radio_control(pmlan_private pmpriv,
+ HostCmd_DS_COMMAND *cmd,
+ t_u16 cmd_action, t_void *pdata_buf)
+{
+ HostCmd_DS_802_11_RADIO_CONTROL *pradio_control = &cmd->params.radio;
+ t_u32 radio_ctl;
+ ENTER();
+ cmd->size = wlan_cpu_to_le16((sizeof(HostCmd_DS_802_11_RADIO_CONTROL)) +
+ S_DS_GEN);
+ cmd->command = wlan_cpu_to_le16(HostCmd_CMD_802_11_RADIO_CONTROL);
+ pradio_control->action = wlan_cpu_to_le16(cmd_action);
+ memcpy_ext(pmpriv->adapter, &radio_ctl, pdata_buf, sizeof(t_u32),
+ sizeof(radio_ctl));
+ pradio_control->control = wlan_cpu_to_le16((t_u16)radio_ctl);
+ LEAVE();
+ return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ * @brief This function handles the command response of radio_control
+ *
+ * @param pmpriv A pointer to mlan_private structure
+ * @param resp A pointer to HostCmd_DS_COMMAND
+ * @param pioctl_buf A pointer to mlan_ioctl_req structure
+ *
+ * @return MLAN_STATUS_SUCCESS
+ */
+mlan_status wlan_ret_802_11_radio_control(pmlan_private pmpriv,
+ HostCmd_DS_COMMAND *resp,
+ mlan_ioctl_req *pioctl_buf)
+{
+ HostCmd_DS_802_11_RADIO_CONTROL *pradio_ctrl =
+ (HostCmd_DS_802_11_RADIO_CONTROL *)&resp->params.radio;
+ mlan_ds_radio_cfg *radio_cfg = MNULL;
+ mlan_adapter *pmadapter = pmpriv->adapter;
+
+ ENTER();
+ pmadapter->radio_on = wlan_le16_to_cpu(pradio_ctrl->control);
+ if (pioctl_buf) {
+ radio_cfg = (mlan_ds_radio_cfg *)pioctl_buf->pbuf;
+ radio_cfg->param.radio_on_off = (t_u32)pmadapter->radio_on;
+ pioctl_buf->data_read_written = sizeof(mlan_ds_radio_cfg);
+ }
+ LEAVE();
+ return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ * @brief This function prepares command of remain_on_channel.
+ *
+ * @param pmpriv A pointer to mlan_private structure
+ * @param cmd A pointer to HostCmd_DS_COMMAND structure
+ * @param cmd_action The action: GET or SET
+ * @param pdata_buf A pointer to data buffer
+ *
+ * @return MLAN_STATUS_SUCCESS
+ */
+mlan_status wlan_cmd_remain_on_channel(pmlan_private pmpriv,
+ HostCmd_DS_COMMAND *cmd,
+ t_u16 cmd_action, t_void *pdata_buf)
+{
+ HostCmd_DS_REMAIN_ON_CHANNEL *remain_channel =
+ &cmd->params.remain_on_chan;
+ mlan_ds_remain_chan *cfg = (mlan_ds_remain_chan *)pdata_buf;
+ ENTER();
+ cmd->size = wlan_cpu_to_le16((sizeof(HostCmd_DS_REMAIN_ON_CHANNEL)) +
+ S_DS_GEN);
+ cmd->command = wlan_cpu_to_le16(HostCmd_CMD_802_11_REMAIN_ON_CHANNEL);
+ remain_channel->action = cmd_action;
+ if (cmd_action == HostCmd_ACT_GEN_SET) {
+ if (cfg->remove) {
+ remain_channel->action = HostCmd_ACT_GEN_REMOVE;
+ } else {
+ remain_channel->bandcfg = cfg->bandcfg;
+ remain_channel->channel = cfg->channel;
+ remain_channel->remain_period =
+ wlan_cpu_to_le32(cfg->remain_period);
+ }
+ }
+ remain_channel->action = wlan_cpu_to_le16(remain_channel->action);
+
+ LEAVE();
+ return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ * @brief This function handles the command response of remain_on_channel
+ *
+ * @param pmpriv A pointer to mlan_private structure
+ * @param resp A pointer to HostCmd_DS_COMMAND
+ * @param pioctl_buf A pointer to mlan_ioctl_req structure
+ *
+ * @return MLAN_STATUS_SUCCESS
+ */
+mlan_status wlan_ret_remain_on_channel(pmlan_private pmpriv,
+ HostCmd_DS_COMMAND *resp,
+ mlan_ioctl_req *pioctl_buf)
+{
+ HostCmd_DS_REMAIN_ON_CHANNEL *remain_channel =
+ &resp->params.remain_on_chan;
+ mlan_ds_radio_cfg *radio_cfg = MNULL;
+
+ ENTER();
+ if (pioctl_buf) {
+ radio_cfg = (mlan_ds_radio_cfg *)pioctl_buf->pbuf;
+ radio_cfg->param.remain_chan.status = remain_channel->status;
+ radio_cfg->param.remain_chan.bandcfg = remain_channel->bandcfg;
+ radio_cfg->param.remain_chan.channel = remain_channel->channel;
+ radio_cfg->param.remain_chan.remain_period =
+ wlan_le32_to_cpu(remain_channel->remain_period);
+ pioctl_buf->data_read_written = sizeof(mlan_ds_radio_cfg);
+ }
+ LEAVE();
+ return MLAN_STATUS_SUCCESS;
+}
+
+#ifdef WIFI_DIRECT_SUPPORT
+/**
+ * @brief This function prepares command of wifi direct mode.
+ *
+ * @param pmpriv A pointer to mlan_private structure
+ * @param cmd A pointer to HostCmd_DS_COMMAND structure
+ * @param cmd_action The action: GET or SET
+ * @param pdata_buf A pointer to data buffer
+ *
+ * @return MLAN_STATUS_SUCCESS
+ */
+mlan_status wlan_cmd_wifi_direct_mode(pmlan_private pmpriv,
+ HostCmd_DS_COMMAND *cmd, t_u16 cmd_action,
+ t_void *pdata_buf)
+{
+ HostCmd_DS_WIFI_DIRECT_MODE *wfd_mode = &cmd->params.wifi_direct_mode;
+ t_u16 mode = *((t_u16 *)pdata_buf);
+ ENTER();
+ cmd->size = wlan_cpu_to_le16((sizeof(HostCmd_DS_WIFI_DIRECT_MODE)) +
+ S_DS_GEN);
+ cmd->command = wlan_cpu_to_le16(HOST_CMD_WIFI_DIRECT_MODE_CONFIG);
+ wfd_mode->action = wlan_cpu_to_le16(cmd_action);
+ if (cmd_action == HostCmd_ACT_GEN_SET)
+ wfd_mode->mode = wlan_cpu_to_le16(mode);
+
+ LEAVE();
+ return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ * @brief This function handles the command response of wifi direct mode
+ *
+ * @param pmpriv A pointer to mlan_private structure
+ * @param resp A pointer to HostCmd_DS_COMMAND
+ * @param pioctl_buf A pointer to mlan_ioctl_req structure
+ *
+ * @return MLAN_STATUS_SUCCESS
+ */
+mlan_status wlan_ret_wifi_direct_mode(pmlan_private pmpriv,
+ HostCmd_DS_COMMAND *resp,
+ mlan_ioctl_req *pioctl_buf)
+{
+ HostCmd_DS_WIFI_DIRECT_MODE *wfd_mode = &resp->params.wifi_direct_mode;
+ mlan_ds_bss *bss = MNULL;
+
+ ENTER();
+ if (pioctl_buf) {
+ bss = (mlan_ds_bss *)pioctl_buf->pbuf;
+ bss->param.wfd_mode = wlan_le16_to_cpu(wfd_mode->mode);
+ pioctl_buf->data_read_written = sizeof(mlan_ds_bss);
+ }
+ LEAVE();
+ return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ * @brief This function prepares command of p2p_params_config.
+ *
+ * @param pmpriv A pointer to mlan_private structure
+ * @param cmd A pointer to HostCmd_DS_COMMAND structure
+ * @param cmd_action The action: GET or SET
+ * @param pdata_buf A pointer to data buffer
+ *
+ * @return MLAN_STATUS_SUCCESS
+ */
+mlan_status wlan_cmd_p2p_params_config(pmlan_private pmpriv,
+ HostCmd_DS_COMMAND *cmd,
+ t_u16 cmd_action, t_void *pdata_buf)
+{
+ HostCmd_DS_WIFI_DIRECT_PARAM_CONFIG *p2p_config =
+ &cmd->params.p2p_params_config;
+ mlan_ds_wifi_direct_config *cfg =
+ (mlan_ds_wifi_direct_config *)pdata_buf;
+ MrvlIEtypes_NoA_setting_t *pnoa_tlv = MNULL;
+ MrvlIEtypes_OPP_PS_setting_t *popp_ps_tlv = MNULL;
+ t_u8 *tlv = MNULL;
+ ENTER();
+
+ cmd->size = sizeof(HostCmd_DS_WIFI_DIRECT_PARAM_CONFIG) + S_DS_GEN;
+ cmd->command = wlan_cpu_to_le16(HOST_CMD_P2P_PARAMS_CONFIG);
+ p2p_config->action = wlan_cpu_to_le16(cmd_action);
+ if (cmd_action == HostCmd_ACT_GEN_SET) {
+ tlv = (t_u8 *)p2p_config->tlv_buf;
+ if (cfg->flags & WIFI_DIRECT_NOA) {
+ pnoa_tlv = (MrvlIEtypes_NoA_setting_t *)tlv;
+ pnoa_tlv->header.type =
+ wlan_cpu_to_le16(TLV_TYPE_WIFI_DIRECT_NOA);
+ pnoa_tlv->header.len = wlan_cpu_to_le16(
+ sizeof(MrvlIEtypes_NoA_setting_t) -
+ sizeof(MrvlIEtypesHeader_t));
+ pnoa_tlv->enable = cfg->noa_enable;
+ pnoa_tlv->index = wlan_cpu_to_le16(cfg->index);
+ pnoa_tlv->noa_count = cfg->noa_count;
+ pnoa_tlv->noa_duration =
+ wlan_cpu_to_le32(cfg->noa_duration);
+ pnoa_tlv->noa_interval =
+ wlan_cpu_to_le32(cfg->noa_interval);
+ cmd->size += sizeof(MrvlIEtypes_NoA_setting_t);
+ tlv += sizeof(MrvlIEtypes_NoA_setting_t);
+ PRINTM(MCMND,
+ "Set NOA: enable=%d index=%d, count=%d, duration=%d interval=%d\n",
+ cfg->noa_enable, cfg->index, cfg->noa_count,
+ (int)cfg->noa_duration, (int)cfg->noa_interval);
+ }
+ if (cfg->flags & WIFI_DIRECT_OPP_PS) {
+ popp_ps_tlv = (MrvlIEtypes_OPP_PS_setting_t *)tlv;
+ popp_ps_tlv->header.type =
+ wlan_cpu_to_le16(TLV_TYPE_WIFI_DIRECT_OPP_PS);
+ popp_ps_tlv->header.len = wlan_cpu_to_le16(
+ sizeof(MrvlIEtypes_OPP_PS_setting_t) -
+ sizeof(MrvlIEtypesHeader_t));
+
+ popp_ps_tlv->enable = cfg->ct_window;
+ popp_ps_tlv->enable |= cfg->opp_ps_enable << 7;
+ cmd->size += sizeof(MrvlIEtypes_OPP_PS_setting_t);
+ PRINTM(MCMND, "Set OPP_PS: enable=%d ct_win=%d\n",
+ cfg->opp_ps_enable, cfg->ct_window);
+ }
+ } else if (cmd_action == HostCmd_ACT_GEN_GET) {
+ tlv = (t_u8 *)p2p_config->tlv_buf;
+ if (cfg->flags & WIFI_DIRECT_NOA) {
+ pnoa_tlv = (MrvlIEtypes_NoA_setting_t *)tlv;
+ pnoa_tlv->header.type =
+ wlan_cpu_to_le16(TLV_TYPE_WIFI_DIRECT_NOA);
+ pnoa_tlv->header.len = wlan_cpu_to_le16(
+ sizeof(MrvlIEtypes_NoA_setting_t) -
+ sizeof(MrvlIEtypesHeader_t));
+ cmd->size += sizeof(MrvlIEtypes_NoA_setting_t);
+ tlv += sizeof(MrvlIEtypes_NoA_setting_t);
+ }
+
+ if (cfg->flags & WIFI_DIRECT_OPP_PS) {
+ popp_ps_tlv = (MrvlIEtypes_OPP_PS_setting_t *)tlv;
+ popp_ps_tlv->header.type =
+ wlan_cpu_to_le16(TLV_TYPE_WIFI_DIRECT_OPP_PS);
+ popp_ps_tlv->header.len = wlan_cpu_to_le16(
+ sizeof(MrvlIEtypes_OPP_PS_setting_t) -
+ sizeof(MrvlIEtypesHeader_t));
+ cmd->size += sizeof(MrvlIEtypes_OPP_PS_setting_t);
+ }
+ }
+ cmd->size = wlan_cpu_to_le16(cmd->size);
+ LEAVE();
+ return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ * @brief This function handles the command response of p2p_params_config
+ *
+ * @param pmpriv A pointer to mlan_private structure
+ * @param resp A pointer to HostCmd_DS_COMMAND
+ * @param pioctl_buf A pointer to mlan_ioctl_req structure
+ *
+ * @return MLAN_STATUS_SUCCESS
+ */
+mlan_status wlan_ret_p2p_params_config(pmlan_private pmpriv,
+ HostCmd_DS_COMMAND *resp,
+ mlan_ioctl_req *pioctl_buf)
+{
+ HostCmd_DS_WIFI_DIRECT_PARAM_CONFIG *p2p_config =
+ &resp->params.p2p_params_config;
+ mlan_ds_misc_cfg *cfg = MNULL;
+ MrvlIEtypes_NoA_setting_t *pnoa_tlv = MNULL;
+ MrvlIEtypes_OPP_PS_setting_t *popp_ps_tlv = MNULL;
+ MrvlIEtypesHeader_t *tlv = MNULL;
+ t_u16 tlv_buf_left = 0;
+ t_u16 tlv_type = 0;
+ t_u16 tlv_len = 0;
+
+ ENTER();
+ if (wlan_le16_to_cpu(p2p_config->action) == HostCmd_ACT_GEN_GET) {
+ if (pioctl_buf) {
+ cfg = (mlan_ds_misc_cfg *)pioctl_buf->pbuf;
+ tlv = (MrvlIEtypesHeader_t *)(p2p_config->tlv_buf);
+ tlv_buf_left =
+ resp->size -
+ (sizeof(HostCmd_DS_WIFI_DIRECT_PARAM_CONFIG) +
+ S_DS_GEN);
+ while (tlv_buf_left >= sizeof(MrvlIEtypesHeader_t)) {
+ tlv_type = wlan_le16_to_cpu(tlv->type);
+ tlv_len = wlan_le16_to_cpu(tlv->len);
+ if (tlv_buf_left <
+ (tlv_len + sizeof(MrvlIEtypesHeader_t))) {
+ PRINTM(MERROR,
+ "Error processing p2p param config TLVs, bytes left < TLV length\n");
+ break;
+ }
+ switch (tlv_type) {
+ case TLV_TYPE_WIFI_DIRECT_NOA:
+ pnoa_tlv = (MrvlIEtypes_NoA_setting_t *)
+ tlv;
+ cfg->param.p2p_config.flags |=
+ WIFI_DIRECT_NOA;
+ cfg->param.p2p_config.noa_enable =
+ pnoa_tlv->enable;
+ cfg->param.p2p_config.index =
+ wlan_le16_to_cpu(
+ pnoa_tlv->index);
+ cfg->param.p2p_config.noa_count =
+ pnoa_tlv->noa_count;
+ cfg->param.p2p_config.noa_duration =
+ wlan_le32_to_cpu(
+ pnoa_tlv->noa_duration);
+ cfg->param.p2p_config.noa_interval =
+ wlan_le32_to_cpu(
+ pnoa_tlv->noa_interval);
+ PRINTM(MCMND,
+ "Get NOA: enable=%d index=%d, count=%d, duration=%d interval=%d\n",
+ cfg->param.p2p_config.noa_enable,
+ cfg->param.p2p_config.index,
+ cfg->param.p2p_config.noa_count,
+ (int)cfg->param.p2p_config
+ .noa_duration,
+ (int)cfg->param.p2p_config
+ .noa_interval);
+ break;
+ case TLV_TYPE_WIFI_DIRECT_OPP_PS:
+ popp_ps_tlv =
+ (MrvlIEtypes_OPP_PS_setting_t *)
+ tlv;
+ cfg->param.p2p_config.flags |=
+ WIFI_DIRECT_OPP_PS;
+ cfg->param.p2p_config.opp_ps_enable =
+ (popp_ps_tlv->enable & 0x80) >>
+ 7;
+ cfg->param.p2p_config.ct_window =
+ popp_ps_tlv->enable & 0x7f;
+ PRINTM(MCMND,
+ "Get OPP_PS: enable=%d ct_win=%d\n",
+ cfg->param.p2p_config
+ .opp_ps_enable,
+ cfg->param.p2p_config.ct_window);
+ break;
+ default:
+ break;
+ }
+ tlv_buf_left -=
+ tlv_len + sizeof(MrvlIEtypesHeader_t);
+ tlv = (MrvlIEtypesHeader_t
+ *)((t_u8 *)tlv + tlv_len +
+ sizeof(MrvlIEtypesHeader_t));
+ }
+ pioctl_buf->data_read_written =
+ sizeof(mlan_ds_wifi_direct_config);
+ }
+ }
+ LEAVE();
+ return MLAN_STATUS_SUCCESS;
+}
+#endif
+
+/**
+ * @brief This function prepares command of mimo switch configuration.
+ *
+ * @param pmpriv A pointer to mlan_private structure
+ * @param cmd A pointer to HostCmd_DS_COMMAND structure
+ * @param pdata_buf A pointer to data buffer
+ * @return MLAN_STATUS_SUCCESS
+ */
+mlan_status wlan_cmd_802_11_mimo_switch(pmlan_private pmpriv,
+ HostCmd_DS_COMMAND *cmd,
+ t_void *pdata_buf)
+{
+ HostCmd_DS_MIMO_SWITCH *mimo_switch_cmd = &cmd->params.mimo_switch;
+ mlan_ds_mimo_switch *pmimo_switch = (mlan_ds_mimo_switch *)pdata_buf;
+
+ ENTER();
+
+ cmd->command = wlan_cpu_to_le16(HostCmd_CMD_802_11_MIMO_SWITCH);
+ cmd->size =
+ wlan_cpu_to_le16((sizeof(HostCmd_DS_MIMO_SWITCH)) + S_DS_GEN);
+ mimo_switch_cmd->txpath_antmode = pmimo_switch->txpath_antmode;
+ mimo_switch_cmd->rxpath_antmode = pmimo_switch->rxpath_antmode;
+
+ LEAVE();
+ return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ * @brief This function prepares command of hs wakeup reason.
+ *
+ * @param pmpriv A pointer to mlan_private structure
+ * @param cmd A pointer to HostCmd_DS_COMMAND structure
+ * @param pdata_buf A pointer to data buffer
+ * @return MLAN_STATUS_SUCCESS
+ */
+mlan_status wlan_cmd_hs_wakeup_reason(pmlan_private pmpriv,
+ HostCmd_DS_COMMAND *cmd,
+ t_void *pdata_buf)
+{
+ ENTER();
+
+ cmd->command = wlan_cpu_to_le16(HostCmd_CMD_HS_WAKEUP_REASON);
+ cmd->size = wlan_cpu_to_le16((sizeof(HostCmd_DS_HS_WAKEUP_REASON)) +
+ S_DS_GEN);
+
+ LEAVE();
+ return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ * @brief This function handles the command response of
+ * hs wakeup reason
+ *
+ * @param pmpriv A pointer to mlan_private structure
+ * @param resp A pointer to HostCmd_DS_COMMAND
+ * @param pioctl_buf A pointer to command buffer
+ *
+ * @return MLAN_STATUS_SUCCESS
+ */
+mlan_status wlan_ret_hs_wakeup_reason(pmlan_private pmpriv,
+ HostCmd_DS_COMMAND *resp,
+ mlan_ioctl_req *pioctl_buf)
+{
+ HostCmd_DS_HS_WAKEUP_REASON *hs_wakeup_reason =
+ (HostCmd_DS_HS_WAKEUP_REASON *)&resp->params.hs_wakeup_reason;
+ mlan_ds_pm_cfg *pm_cfg = MNULL;
+
+ ENTER();
+
+ pm_cfg = (mlan_ds_pm_cfg *)pioctl_buf->pbuf;
+ pm_cfg->param.wakeup_reason.hs_wakeup_reason =
+ wlan_le16_to_cpu(hs_wakeup_reason->wakeup_reason);
+ pioctl_buf->data_read_written = sizeof(mlan_ds_pm_cfg);
+
+ LEAVE();
+ return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ * @brief This function prepares command of tx_rx_pkt_stats
+ *
+ * @param pmpriv A pointer to mlan_private structure
+ * @param cmd A pointer to HostCmd_DS_COMMAND structure
+ * @param pioctl_buf A pointer to mlan_ioctl_req structure
+ * @param pdata_buf A pointer to information buffer
+ * @return MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ */
+mlan_status wlan_cmd_tx_rx_pkt_stats(pmlan_private pmpriv,
+ HostCmd_DS_COMMAND *cmd,
+ pmlan_ioctl_req pioctl_buf,
+ t_void *pdata_buf)
+{
+ HostCmd_DS_TX_RX_HISTOGRAM *ptx_rx_histogram =
+ &cmd->params.tx_rx_histogram;
+ mlan_ds_misc_tx_rx_histogram *ptx_rx_pkt_stats =
+ (mlan_ds_misc_tx_rx_histogram *)pdata_buf;
+ mlan_status ret = MLAN_STATUS_SUCCESS;
+
+ ENTER();
+
+ if (!ptx_rx_pkt_stats) {
+ ret = MLAN_STATUS_FAILURE;
+ goto done;
+ }
+ cmd->command = wlan_cpu_to_le16(HOST_CMD_TX_RX_PKT_STATS);
+ cmd->size =
+ wlan_cpu_to_le16(sizeof(HostCmd_DS_TX_RX_HISTOGRAM) + S_DS_GEN);
+
+ ptx_rx_histogram->enable = ptx_rx_pkt_stats->enable;
+ ptx_rx_histogram->action = wlan_cpu_to_le16(ptx_rx_pkt_stats->action);
+done:
+ LEAVE();
+ return ret;
+}
+/**
+ * @brief This function handles the command response of tx_rx_pkt_stats
+ *
+ * @param pmpriv A pointer to mlan_private structure
+ * @param resp A pointer to HostCmd_DS_COMMAND
+ * @param pioctl_buf A pointer to mlan_ioctl_req structure
+ *
+ * @return MLAN_STATUS_SUCCESS
+ */
+mlan_status wlan_ret_tx_rx_pkt_stats(pmlan_private pmpriv,
+ HostCmd_DS_COMMAND *resp,
+ mlan_ioctl_req *pioctl_buf)
+{
+ HostCmd_DS_TX_RX_HISTOGRAM *ptx_rx_histogram =
+ &resp->params.tx_rx_histogram;
+ mlan_ds_misc_cfg *info;
+ t_u16 cmdsize = wlan_le16_to_cpu(resp->size), length;
+ t_u32 *pos, count = 0;
+
+ ENTER();
+
+ if (pioctl_buf) {
+ ptx_rx_histogram->action =
+ wlan_le16_to_cpu(ptx_rx_histogram->action);
+ info = (mlan_ds_misc_cfg *)pioctl_buf->pbuf;
+ length =
+ cmdsize - S_DS_GEN - sizeof(HostCmd_DS_TX_RX_HISTOGRAM);
+ if (length > 0) {
+ info->param.tx_rx_histogram.size = length;
+ memcpy_ext(pmpriv->adapter,
+ info->param.tx_rx_histogram.value,
+ (t_u8 *)ptx_rx_histogram +
+ sizeof(HostCmd_DS_TX_RX_HISTOGRAM),
+ length, info->param.tx_rx_histogram.size);
+ pos = (t_u32 *)info->param.tx_rx_histogram.value;
+ while (length - 4 * count) {
+ *pos = wlan_le32_to_cpu(*pos);
+ pos += 4;
+ count++;
+ }
+ }
+ }
+
+ LEAVE();
+ return MLAN_STATUS_SUCCESS;
+}
+
+/*
+ * @brief This function prepares command of cwmode control.
+ *
+ * @param pmpriv A pointer to mlan_private structure
+ * @param cmd A pointer to HostCmd_DS_COMMAND structure
+ * @param cmd_action The action: GET or SET
+ * @param pdata_buf A pointer to data buffer
+ *
+ * @return MLAN_STATUS_SUCCESS
+ */
+mlan_status wlan_cmd_cw_mode_ctrl(pmlan_private pmpriv, HostCmd_DS_COMMAND *cmd,
+ t_u16 cmd_action, t_void *pdata_buf)
+{
+ HostCmd_DS_CW_MODE_CTRL *cwmode_ctrl = &cmd->params.cwmode;
+ mlan_ds_cw_mode_ctrl *cw_mode = (mlan_ds_cw_mode_ctrl *)pdata_buf;
+ ENTER();
+ cmd->size =
+ wlan_cpu_to_le16((sizeof(HostCmd_DS_CW_MODE_CTRL)) + S_DS_GEN);
+ cmd->command = wlan_cpu_to_le16(HostCmd_CMD_CW_MODE_CTRL);
+ cwmode_ctrl->action = wlan_cpu_to_le16(cmd_action);
+
+ if (cmd_action == HostCmd_ACT_GEN_SET) {
+ cwmode_ctrl->mode = cw_mode->mode;
+ cwmode_ctrl->channel = cw_mode->channel;
+ cwmode_ctrl->chanInfo = cw_mode->chanInfo;
+ cwmode_ctrl->txPower = wlan_cpu_to_le16(cw_mode->txPower);
+ cwmode_ctrl->rateInfo = wlan_cpu_to_le32(cw_mode->rateInfo);
+ cwmode_ctrl->pktLength = wlan_cpu_to_le16(cw_mode->pktLength);
+ }
+ LEAVE();
+ return MLAN_STATUS_SUCCESS;
+}
+
+/*
+ * @brief This function handles the command response of cwmode_ctrl
+ *
+ * @param pmpriv A pointer to mlan_private structure
+ * @param resp A pointer to HostCmd_DS_COMMAND
+ * @param pioctl_buf A pointer to mlan_ioctl_req structure
+ *
+ * @return MLAN_STATUS_SUCCESS
+ */
+mlan_status wlan_ret_cw_mode_ctrl(pmlan_private pmpriv,
+ HostCmd_DS_COMMAND *resp,
+ mlan_ioctl_req *pioctl_buf)
+{
+ HostCmd_DS_CW_MODE_CTRL *cwmode_resp = &resp->params.cwmode;
+ mlan_ds_misc_cfg *misc = MNULL;
+
+ ENTER();
+ if (pioctl_buf) {
+ misc = (mlan_ds_misc_cfg *)pioctl_buf->pbuf;
+ misc->param.cwmode.mode = cwmode_resp->mode;
+ misc->param.cwmode.channel = cwmode_resp->channel;
+ misc->param.cwmode.chanInfo = cwmode_resp->chanInfo;
+ misc->param.cwmode.txPower =
+ wlan_le16_to_cpu(cwmode_resp->txPower);
+ misc->param.cwmode.rateInfo =
+ wlan_le32_to_cpu(cwmode_resp->rateInfo);
+ ;
+ misc->param.cwmode.pktLength =
+ wlan_le16_to_cpu(cwmode_resp->pktLength);
+ ;
+ pioctl_buf->data_read_written = sizeof(mlan_ds_misc_cfg);
+ }
+ LEAVE();
+ return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ * @brief This function prepares command of rf_antenna.
+ *
+ * @param pmpriv A pointer to mlan_private structure
+ * @param cmd A pointer to HostCmd_DS_COMMAND structure
+ * @param cmd_action The action: GET or SET
+ * @param pdata_buf A pointer to data buffer
+ *
+ * @return MLAN_STATUS_SUCCESS
+ */
+mlan_status wlan_cmd_802_11_rf_antenna(pmlan_private pmpriv,
+ HostCmd_DS_COMMAND *cmd,
+ t_u16 cmd_action, t_void *pdata_buf)
+{
+ HostCmd_DS_802_11_RF_ANTENNA *pantenna = &cmd->params.antenna;
+ mlan_ds_ant_cfg *ant_cfg = (mlan_ds_ant_cfg *)pdata_buf;
+ typedef struct _HostCmd_DS_802_11_RF_ANTENNA_1X1 {
+ /** Action */
+ t_u16 action;
+ /** Antenna or 0xffff (diversity) */
+ t_u16 antenna_mode;
+ /** Evaluate time */
+ t_u16 evaluate_time;
+ /** Current antenna */
+ t_u16 current_antenna;
+ } HostCmd_DS_802_11_RF_ANTENNA_1X1;
+ HostCmd_DS_802_11_RF_ANTENNA_1X1 *pantenna_1x1 =
+ (HostCmd_DS_802_11_RF_ANTENNA_1X1 *)&cmd->params.antenna;
+ mlan_ds_ant_cfg_1x1 *ant_cfg_1x1 = (mlan_ds_ant_cfg_1x1 *)pdata_buf;
+
+ ENTER();
+ cmd->command = wlan_cpu_to_le16(HostCmd_CMD_802_11_RF_ANTENNA);
+ if (!IS_STREAM_2X2(pmpriv->adapter->feature_control))
+ cmd->size = wlan_cpu_to_le16(
+ sizeof(HostCmd_DS_802_11_RF_ANTENNA_1X1) + S_DS_GEN);
+ else
+ cmd->size = wlan_cpu_to_le16(
+ sizeof(HostCmd_DS_802_11_RF_ANTENNA) + S_DS_GEN);
+
+ if (cmd_action == HostCmd_ACT_GEN_SET) {
+ if (IS_STREAM_2X2(pmpriv->adapter->feature_control)) {
+ pantenna->action_tx =
+ wlan_cpu_to_le16(HostCmd_ACT_SET_TX);
+ pantenna->tx_antenna_mode =
+ wlan_cpu_to_le16((t_u16)ant_cfg->tx_antenna);
+ pantenna->action_rx =
+ wlan_cpu_to_le16(HostCmd_ACT_SET_RX);
+ pantenna->rx_antenna_mode =
+ wlan_cpu_to_le16((t_u16)ant_cfg->rx_antenna);
+ } else {
+ pantenna_1x1->action =
+ wlan_cpu_to_le16(HostCmd_ACT_SET_BOTH);
+ pantenna_1x1->antenna_mode =
+ wlan_cpu_to_le16((t_u16)ant_cfg_1x1->antenna);
+ pantenna_1x1->evaluate_time = wlan_cpu_to_le16(
+ (t_u16)ant_cfg_1x1->evaluate_time);
+ }
+ } else {
+ if (IS_STREAM_2X2(pmpriv->adapter->feature_control)) {
+ pantenna->action_tx =
+ wlan_cpu_to_le16(HostCmd_ACT_GET_TX);
+ pantenna->action_rx =
+ wlan_cpu_to_le16(HostCmd_ACT_GET_RX);
+ } else {
+ pantenna_1x1->action =
+ wlan_cpu_to_le16(HostCmd_ACT_GET_BOTH);
+ }
+ }
+ LEAVE();
+ return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ * @brief This function handles the command response of rf_antenna
+ *
+ * @param pmpriv A pointer to mlan_private structure
+ * @param resp A pointer to HostCmd_DS_COMMAND
+ * @param pioctl_buf A pointer to mlan_ioctl_req structure
+ *
+ * @return MLAN_STATUS_SUCCESS
+ */
+mlan_status wlan_ret_802_11_rf_antenna(pmlan_private pmpriv,
+ HostCmd_DS_COMMAND *resp,
+ mlan_ioctl_req *pioctl_buf)
+{
+ HostCmd_DS_802_11_RF_ANTENNA *pantenna = &resp->params.antenna;
+ t_u16 tx_ant_mode = wlan_le16_to_cpu(pantenna->tx_antenna_mode);
+ t_u16 rx_ant_mode = wlan_le16_to_cpu(pantenna->rx_antenna_mode);
+#if defined(PCIE9098) || defined(SD9098) || defined(USB9098) || \
+ defined(PCIE9097) || defined(SD9097) || defined(USB9097)
+ mlan_adapter *pmadapter = pmpriv->adapter;
+#endif
+ typedef struct _HostCmd_DS_802_11_RF_ANTENNA_1X1 {
+ /** Action */
+ t_u16 action;
+ /** Antenna or 0xffff (diversity) */
+ t_u16 antenna_mode;
+ /** Evaluate time */
+ t_u16 evaluate_time;
+ /** Current antenna */
+ t_u16 current_antenna;
+ } HostCmd_DS_802_11_RF_ANTENNA_1X1;
+ HostCmd_DS_802_11_RF_ANTENNA_1X1 *pantenna_1x1 =
+ (HostCmd_DS_802_11_RF_ANTENNA_1X1 *)&resp->params.antenna;
+ t_u16 ant_mode = wlan_le16_to_cpu(pantenna_1x1->antenna_mode);
+ t_u16 evaluate_time = wlan_le16_to_cpu(pantenna_1x1->evaluate_time);
+ t_u16 current_antenna = wlan_le16_to_cpu(pantenna_1x1->current_antenna);
+ mlan_ds_radio_cfg *radio = MNULL;
+
+ ENTER();
+
+ if (IS_STREAM_2X2(pmpriv->adapter->feature_control)) {
+ PRINTM(MCMND,
+ "RF_ANT_RESP: Tx action = 0x%x, Tx Mode = 0x%04x"
+ " Rx action = 0x%x, Rx Mode = 0x%04x\n",
+ wlan_le16_to_cpu(pantenna->action_tx), tx_ant_mode,
+ wlan_le16_to_cpu(pantenna->action_rx), rx_ant_mode);
+#if defined(PCIE9098) || defined(SD9098) || defined(USB9098) || \
+ defined(PCIE9097) || defined(SD9097) || defined(USB9097)
+ if (IS_CARD9098(pmadapter->card_type) ||
+ IS_CARD9097(pmadapter->card_type)) {
+ tx_ant_mode &= 0x0303;
+ rx_ant_mode &= 0x0303;
+ /** 2G antcfg TX */
+ if (tx_ant_mode & 0x00FF) {
+ pmadapter->user_htstream &= ~0xF0;
+ pmadapter->user_htstream |=
+ (bitcount(tx_ant_mode & 0x00FF) << 4);
+ }
+ /* 5G antcfg tx */
+ if (tx_ant_mode & 0xFF00) {
+ pmadapter->user_htstream &= ~0xF000;
+ pmadapter->user_htstream |=
+ (bitcount(tx_ant_mode & 0xFF00) << 12);
+ }
+ /* 2G antcfg RX */
+ if (rx_ant_mode & 0x00FF) {
+ pmadapter->user_htstream &= ~0xF;
+ pmadapter->user_htstream |=
+ bitcount(rx_ant_mode & 0x00FF);
+ }
+ /* 5G antcfg RX */
+ if (rx_ant_mode & 0xFF00) {
+ pmadapter->user_htstream &= ~0xF00;
+ pmadapter->user_htstream |=
+ (bitcount(rx_ant_mode & 0xFF00) << 8);
+ }
+ PRINTM(MCMND,
+ "user_htstream=0x%x, tx_antenna=0x%x rx_antenna=0x%x\n",
+ pmadapter->user_htstream, tx_ant_mode,
+ rx_ant_mode);
+ }
+#endif
+ } else
+ PRINTM(MINFO,
+ "RF_ANT_RESP: action = 0x%x, Mode = 0x%04x, Evaluate time = %d, Current antenna = %d\n",
+ wlan_le16_to_cpu(pantenna_1x1->action), ant_mode,
+ evaluate_time, current_antenna);
+
+ if (pioctl_buf) {
+ radio = (mlan_ds_radio_cfg *)pioctl_buf->pbuf;
+ if (IS_STREAM_2X2(pmpriv->adapter->feature_control)) {
+ radio->param.ant_cfg.tx_antenna = tx_ant_mode;
+ radio->param.ant_cfg.rx_antenna = rx_ant_mode;
+ } else {
+ radio->param.ant_cfg_1x1.antenna = ant_mode;
+ radio->param.ant_cfg_1x1.evaluate_time = evaluate_time;
+ radio->param.ant_cfg_1x1.current_antenna =
+ current_antenna;
+ }
+ }
+
+ LEAVE();
+ return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ * @brief This function prepares command of reg_access.
+ *
+ * @param priv A pointer to mlan_priv register.
+ * @param cmd A pointer to HostCmd_DS_COMMAND structure
+ * @param cmd_action the action: GET or SET
+ * @param pdata_buf A pointer to data buffer
+ * @return MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ */
+mlan_status wlan_cmd_reg_access(pmlan_private pmpriv, HostCmd_DS_COMMAND *cmd,
+ t_u16 cmd_action, t_void *pdata_buf)
+{
+ mlan_ds_reg_rw *reg_rw;
+#if defined(PCIE9098) || defined(SD9098) || defined(USB9098) || \
+ defined(PCIE9097) || defined(USB9097) || defined(SD9097)
+ MrvlIEtypes_Reg_type_t *tlv;
+ mlan_adapter *pmadapter = pmpriv->adapter;
+#endif
+
+ ENTER();
+
+ reg_rw = (mlan_ds_reg_rw *)pdata_buf;
+ switch (cmd->command) {
+ case HostCmd_CMD_MAC_REG_ACCESS: {
+ HostCmd_DS_MAC_REG_ACCESS *mac_reg;
+ cmd->size = wlan_cpu_to_le16(sizeof(HostCmd_DS_MAC_REG_ACCESS) +
+ S_DS_GEN);
+ mac_reg = (HostCmd_DS_MAC_REG_ACCESS *)&cmd->params.mac_reg;
+ mac_reg->action = wlan_cpu_to_le16(cmd_action);
+ mac_reg->offset = wlan_cpu_to_le16((t_u16)reg_rw->offset);
+ mac_reg->value = wlan_cpu_to_le32(reg_rw->value);
+#if defined(PCIE9098) || defined(SD9098) || defined(USB9098) || \
+ defined(PCIE9097) || defined(USB9097) || defined(SD9097)
+ if ((reg_rw->type == MLAN_REG_MAC2) &&
+ (IS_CARD9098(pmadapter->card_type) ||
+ IS_CARD9097(pmadapter->card_type))) {
+ tlv = (MrvlIEtypes_Reg_type_t
+ *)((t_u8 *)cmd +
+ sizeof(HostCmd_DS_MAC_REG_ACCESS) +
+ S_DS_GEN);
+ tlv->header.type =
+ wlan_cpu_to_le16(TLV_TYPE_REG_ACCESS_CTRL);
+ tlv->header.len = wlan_cpu_to_le16(sizeof(t_u8));
+ tlv->type = MLAN_REG_MAC2;
+ cmd->size = wlan_cpu_to_le16(
+ sizeof(HostCmd_DS_MAC_REG_ACCESS) + S_DS_GEN +
+ sizeof(MrvlIEtypes_Reg_type_t));
+ }
+#endif
+ break;
+ }
+ case HostCmd_CMD_BBP_REG_ACCESS: {
+ HostCmd_DS_BBP_REG_ACCESS *bbp_reg;
+ cmd->size = wlan_cpu_to_le16(sizeof(HostCmd_DS_BBP_REG_ACCESS) +
+ S_DS_GEN);
+ bbp_reg = (HostCmd_DS_BBP_REG_ACCESS *)&cmd->params.bbp_reg;
+ bbp_reg->action = wlan_cpu_to_le16(cmd_action);
+ bbp_reg->offset = wlan_cpu_to_le16((t_u16)reg_rw->offset);
+ bbp_reg->value = (t_u8)reg_rw->value;
+#if defined(PCIE9098) || defined(SD9098) || defined(USB9098) || \
+ defined(PCIE9097) || defined(USB9097) || defined(SD9097)
+ if ((reg_rw->type == MLAN_REG_BBP2) &&
+ (IS_CARD9098(pmadapter->card_type) ||
+ IS_CARD9097(pmadapter->card_type))) {
+ tlv = (MrvlIEtypes_Reg_type_t
+ *)((t_u8 *)cmd +
+ sizeof(HostCmd_DS_BBP_REG_ACCESS) +
+ S_DS_GEN);
+ tlv->header.type =
+ wlan_cpu_to_le16(TLV_TYPE_REG_ACCESS_CTRL);
+ tlv->header.len = wlan_cpu_to_le16(sizeof(t_u8));
+ tlv->type = MLAN_REG_BBP2;
+ cmd->size = wlan_cpu_to_le16(
+ sizeof(HostCmd_DS_BBP_REG_ACCESS) + S_DS_GEN +
+ sizeof(MrvlIEtypes_Reg_type_t));
+ }
+#endif
+ break;
+ }
+ case HostCmd_CMD_RF_REG_ACCESS: {
+ HostCmd_DS_RF_REG_ACCESS *rf_reg;
+ cmd->size = wlan_cpu_to_le16(sizeof(HostCmd_DS_RF_REG_ACCESS) +
+ S_DS_GEN);
+ rf_reg = (HostCmd_DS_RF_REG_ACCESS *)&cmd->params.rf_reg;
+ rf_reg->action = wlan_cpu_to_le16(cmd_action);
+ rf_reg->offset = wlan_cpu_to_le16((t_u16)reg_rw->offset);
+ rf_reg->value = (t_u8)reg_rw->value;
+#if defined(PCIE9098) || defined(SD9098) || defined(USB9098) || \
+ defined(PCIE9097) || defined(USB9097) || defined(SD9097)
+ if ((reg_rw->type == MLAN_REG_RF2) &&
+ (IS_CARD9098(pmadapter->card_type) ||
+ IS_CARD9097(pmadapter->card_type))) {
+ tlv = (MrvlIEtypes_Reg_type_t
+ *)((t_u8 *)cmd +
+ sizeof(HostCmd_DS_RF_REG_ACCESS) +
+ S_DS_GEN);
+ tlv->header.type =
+ wlan_cpu_to_le16(TLV_TYPE_REG_ACCESS_CTRL);
+ tlv->header.len = wlan_cpu_to_le16(sizeof(t_u8));
+ tlv->type = MLAN_REG_RF2;
+ cmd->size = wlan_cpu_to_le16(
+ sizeof(HostCmd_DS_RF_REG_ACCESS) + S_DS_GEN +
+ sizeof(MrvlIEtypes_Reg_type_t));
+ }
+#endif
+ break;
+ }
+ case HostCmd_CMD_CAU_REG_ACCESS: {
+ HostCmd_DS_RF_REG_ACCESS *cau_reg;
+ cmd->size = wlan_cpu_to_le16(sizeof(HostCmd_DS_RF_REG_ACCESS) +
+ S_DS_GEN);
+ cau_reg = (HostCmd_DS_RF_REG_ACCESS *)&cmd->params.rf_reg;
+ cau_reg->action = wlan_cpu_to_le16(cmd_action);
+ cau_reg->offset = wlan_cpu_to_le16((t_u16)reg_rw->offset);
+ cau_reg->value = (t_u8)reg_rw->value;
+ break;
+ }
+ case HostCmd_CMD_TARGET_ACCESS: {
+ HostCmd_DS_TARGET_ACCESS *target;
+ cmd->size = wlan_cpu_to_le16(sizeof(HostCmd_DS_TARGET_ACCESS) +
+ S_DS_GEN);
+ target = (HostCmd_DS_TARGET_ACCESS *)&cmd->params.target;
+ target->action = wlan_cpu_to_le16(cmd_action);
+ target->csu_target = wlan_cpu_to_le16(MLAN_CSU_TARGET_PSU);
+ target->address = wlan_cpu_to_le16((t_u16)reg_rw->offset);
+ target->data = (t_u8)reg_rw->value;
+ break;
+ }
+ case HostCmd_CMD_802_11_EEPROM_ACCESS: {
+ mlan_ds_read_eeprom *rd_eeprom =
+ (mlan_ds_read_eeprom *)pdata_buf;
+ HostCmd_DS_802_11_EEPROM_ACCESS *cmd_eeprom =
+ (HostCmd_DS_802_11_EEPROM_ACCESS *)&cmd->params.eeprom;
+ cmd->size = wlan_cpu_to_le16(
+ sizeof(HostCmd_DS_802_11_EEPROM_ACCESS) + S_DS_GEN);
+ cmd_eeprom->action = wlan_cpu_to_le16(cmd_action);
+ cmd_eeprom->offset = wlan_cpu_to_le16(rd_eeprom->offset);
+ cmd_eeprom->byte_count =
+ wlan_cpu_to_le16(rd_eeprom->byte_count);
+ cmd_eeprom->value = 0;
+ break;
+ }
+ case HostCmd_CMD_BCA_REG_ACCESS: {
+ HostCmd_DS_BCA_REG_ACCESS *bca_reg;
+ cmd->size = wlan_cpu_to_le16(sizeof(HostCmd_DS_BCA_REG_ACCESS) +
+ S_DS_GEN);
+ bca_reg = (HostCmd_DS_BCA_REG_ACCESS *)&cmd->params.bca_reg;
+ bca_reg->action = wlan_cpu_to_le16(cmd_action);
+ bca_reg->offset = wlan_cpu_to_le16((t_u16)reg_rw->offset);
+ bca_reg->value = wlan_cpu_to_le32(reg_rw->value);
+#if defined(PCIE9098) || defined(SD9098) || defined(USB9098) || \
+ defined(PCIE9097) || defined(USB9097) || defined(SD9097)
+ if ((reg_rw->type == MLAN_REG_BCA2) &&
+ (IS_CARD9098(pmadapter->card_type) ||
+ IS_CARD9097(pmadapter->card_type))) {
+ tlv = (MrvlIEtypes_Reg_type_t
+ *)((t_u8 *)cmd +
+ sizeof(HostCmd_DS_BCA_REG_ACCESS) +
+ S_DS_GEN);
+ tlv->header.type =
+ wlan_cpu_to_le16(TLV_TYPE_REG_ACCESS_CTRL);
+ tlv->header.len = wlan_cpu_to_le16(sizeof(t_u8));
+ tlv->type = MLAN_REG_BCA2;
+ cmd->size = wlan_cpu_to_le16(
+ sizeof(HostCmd_DS_BCA_REG_ACCESS) + S_DS_GEN +
+ sizeof(MrvlIEtypes_Reg_type_t));
+ }
+#endif
+ break;
+ }
+ default:
+ LEAVE();
+ return MLAN_STATUS_FAILURE;
+ }
+ cmd->command = wlan_cpu_to_le16(cmd->command);
+
+ LEAVE();
+ return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ * @brief This function handles the command response of reg_access
+ *
+ * @param pmadapter A pointer to mlan_adapter structure
+ * @param type The type of reg access (MAC, BBP or RF)
+ * @param resp A pointer to HostCmd_DS_COMMAND
+ * @param pioctl_buf A pointer to command buffer
+ *
+ * @return MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ */
+mlan_status wlan_ret_reg_access(mlan_adapter *pmadapter, t_u16 type,
+ HostCmd_DS_COMMAND *resp,
+ mlan_ioctl_req *pioctl_buf)
+{
+ mlan_ds_reg_mem *reg_mem = MNULL;
+ mlan_ds_reg_rw *reg_rw = MNULL;
+
+ ENTER();
+
+ if (pioctl_buf) {
+ reg_mem = (mlan_ds_reg_mem *)pioctl_buf->pbuf;
+ reg_rw = &reg_mem->param.reg_rw;
+ switch (type) {
+ case HostCmd_CMD_MAC_REG_ACCESS: {
+ HostCmd_DS_MAC_REG_ACCESS *reg;
+ reg = (HostCmd_DS_MAC_REG_ACCESS *)&resp->params.mac_reg;
+ reg_rw->offset = (t_u32)wlan_le16_to_cpu(reg->offset);
+ reg_rw->value = wlan_le32_to_cpu(reg->value);
+ break;
+ }
+ case HostCmd_CMD_BBP_REG_ACCESS: {
+ HostCmd_DS_BBP_REG_ACCESS *reg;
+ reg = (HostCmd_DS_BBP_REG_ACCESS *)&resp->params.bbp_reg;
+ reg_rw->offset = (t_u32)wlan_le16_to_cpu(reg->offset);
+ reg_rw->value = (t_u32)reg->value;
+ break;
+ }
+
+ case HostCmd_CMD_RF_REG_ACCESS: {
+ HostCmd_DS_RF_REG_ACCESS *reg;
+ reg = (HostCmd_DS_RF_REG_ACCESS *)&resp->params.rf_reg;
+ reg_rw->offset = (t_u32)wlan_le16_to_cpu(reg->offset);
+ reg_rw->value = (t_u32)reg->value;
+ break;
+ }
+ case HostCmd_CMD_CAU_REG_ACCESS: {
+ HostCmd_DS_RF_REG_ACCESS *reg;
+ reg = (HostCmd_DS_RF_REG_ACCESS *)&resp->params.rf_reg;
+ reg_rw->offset = (t_u32)wlan_le16_to_cpu(reg->offset);
+ reg_rw->value = (t_u32)reg->value;
+ break;
+ }
+ case HostCmd_CMD_TARGET_ACCESS: {
+ HostCmd_DS_TARGET_ACCESS *reg;
+ reg = (HostCmd_DS_TARGET_ACCESS *)&resp->params.target;
+ reg_rw->offset = (t_u32)wlan_le16_to_cpu(reg->address);
+ reg_rw->value = (t_u32)reg->data;
+ break;
+ }
+ case HostCmd_CMD_802_11_EEPROM_ACCESS: {
+ mlan_ds_read_eeprom *eeprom = &reg_mem->param.rd_eeprom;
+ HostCmd_DS_802_11_EEPROM_ACCESS *cmd_eeprom =
+ (HostCmd_DS_802_11_EEPROM_ACCESS *)&resp->params
+ .eeprom;
+ cmd_eeprom->byte_count =
+ wlan_le16_to_cpu(cmd_eeprom->byte_count);
+ PRINTM(MINFO, "EEPROM read len=%x\n",
+ cmd_eeprom->byte_count);
+ if (eeprom->byte_count < cmd_eeprom->byte_count) {
+ eeprom->byte_count = 0;
+ PRINTM(MINFO,
+ "EEPROM read return length is too big\n");
+ pioctl_buf->status_code =
+ MLAN_ERROR_CMD_RESP_FAIL;
+ LEAVE();
+ return MLAN_STATUS_FAILURE;
+ }
+ eeprom->offset = wlan_le16_to_cpu(cmd_eeprom->offset);
+ eeprom->byte_count = cmd_eeprom->byte_count;
+ if (eeprom->byte_count > 0) {
+ memcpy_ext(pmadapter, &eeprom->value,
+ &cmd_eeprom->value,
+ eeprom->byte_count, MAX_EEPROM_DATA);
+ HEXDUMP("EEPROM", (char *)&eeprom->value,
+ MIN(MAX_EEPROM_DATA,
+ eeprom->byte_count));
+ }
+ break;
+ }
+ case HostCmd_CMD_BCA_REG_ACCESS: {
+ HostCmd_DS_BCA_REG_ACCESS *reg;
+ reg = (HostCmd_DS_BCA_REG_ACCESS *)&resp->params.bca_reg;
+ reg_rw->offset = (t_u32)wlan_le16_to_cpu(reg->offset);
+ reg_rw->value = wlan_le32_to_cpu(reg->value);
+ break;
+ }
+ default:
+ pioctl_buf->status_code = MLAN_ERROR_CMD_RESP_FAIL;
+ LEAVE();
+ return MLAN_STATUS_FAILURE;
+ }
+ }
+
+ LEAVE();
+ return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ * @brief This function prepares command of mem_access.
+ *
+ * @param cmd A pointer to HostCmd_DS_COMMAND structure
+ * @param cmd_action the action: GET or SET
+ * @param pdata_buf A pointer to data buffer
+ * @return MLAN_STATUS_SUCCESS
+ */
+mlan_status wlan_cmd_mem_access(HostCmd_DS_COMMAND *cmd, t_u16 cmd_action,
+ t_void *pdata_buf)
+{
+ mlan_ds_mem_rw *mem_rw = (mlan_ds_mem_rw *)pdata_buf;
+ HostCmd_DS_MEM_ACCESS *mem_access =
+ (HostCmd_DS_MEM_ACCESS *)&cmd->params.mem;
+
+ ENTER();
+
+ cmd->command = wlan_cpu_to_le16(HostCmd_CMD_MEM_ACCESS);
+ cmd->size = wlan_cpu_to_le16(sizeof(HostCmd_DS_MEM_ACCESS) + S_DS_GEN);
+
+ mem_access->action = wlan_cpu_to_le16(cmd_action);
+ mem_access->addr = wlan_cpu_to_le32(mem_rw->addr);
+ mem_access->value = wlan_cpu_to_le32(mem_rw->value);
+
+ LEAVE();
+ return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ * @brief This function handles the command response of mem_access
+ *
+ * @param pmpriv A pointer to mlan_private structure
+ * @param resp A pointer to HostCmd_DS_COMMAND
+ * @param pioctl_buf A pointer to command buffer
+ *
+ * @return MLAN_STATUS_SUCCESS
+ */
+mlan_status wlan_ret_mem_access(pmlan_private pmpriv, HostCmd_DS_COMMAND *resp,
+ mlan_ioctl_req *pioctl_buf)
+{
+ mlan_ds_reg_mem *reg_mem = MNULL;
+ mlan_ds_mem_rw *mem_rw = MNULL;
+ HostCmd_DS_MEM_ACCESS *mem = (HostCmd_DS_MEM_ACCESS *)&resp->params.mem;
+
+ ENTER();
+
+ if (pioctl_buf) {
+ reg_mem = (mlan_ds_reg_mem *)pioctl_buf->pbuf;
+ mem_rw = &reg_mem->param.mem_rw;
+
+ mem_rw->addr = wlan_le32_to_cpu(mem->addr);
+ mem_rw->value = wlan_le32_to_cpu(mem->value);
+ }
+
+ LEAVE();
+ return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ *
+ * @brief This function handles coex events generated by firmware
+ *
+ * @param priv A pointer to mlan_private structure
+ * @param pevent A pointer to event buf
+ *
+ * @return N/A
+ */
+void wlan_bt_coex_wlan_param_update_event(pmlan_private priv,
+ pmlan_buffer pevent)
+{
+ pmlan_adapter pmadapter = priv->adapter;
+ MrvlIEtypesHeader_t *tlv = MNULL;
+ MrvlIETypes_BtCoexAggrWinSize_t *pCoexWinsize = MNULL;
+ MrvlIEtypes_BtCoexScanTime_t *pScantlv = MNULL;
+ t_s32 len = pevent->data_len - sizeof(t_u32);
+ t_u8 *pCurrent_ptr = pevent->pbuf + pevent->data_offset + sizeof(t_u32);
+ t_u16 tlv_type, tlv_len;
+
+ ENTER();
+
+ while (len >= sizeof(MrvlIEtypesHeader_t)) {
+ tlv = (MrvlIEtypesHeader_t *)pCurrent_ptr;
+ tlv_len = wlan_le16_to_cpu(tlv->len);
+ tlv_type = wlan_le16_to_cpu(tlv->type);
+ if ((tlv_len + sizeof(MrvlIEtypesHeader_t)) > len)
+ break;
+ switch (tlv_type) {
+ case TLV_BTCOEX_WL_AGGR_WINSIZE:
+ pCoexWinsize = (MrvlIETypes_BtCoexAggrWinSize_t *)tlv;
+ pmadapter->coex_win_size = pCoexWinsize->coex_win_size;
+ pmadapter->coex_tx_win_size = pCoexWinsize->tx_win_size;
+ pmadapter->coex_rx_win_size = pCoexWinsize->rx_win_size;
+ wlan_coex_ampdu_rxwinsize(pmadapter);
+ wlan_update_ampdu_txwinsize(pmadapter);
+ break;
+ case TLV_BTCOEX_WL_SCANTIME:
+ pScantlv = (MrvlIEtypes_BtCoexScanTime_t *)tlv;
+ pmadapter->coex_scan = pScantlv->coex_scan;
+ pmadapter->coex_min_scan_time =
+ wlan_le16_to_cpu(pScantlv->min_scan_time);
+ pmadapter->coex_max_scan_time =
+ wlan_le16_to_cpu(pScantlv->max_scan_time);
+ break;
+ default:
+ break;
+ }
+ len -= tlv_len + sizeof(MrvlIEtypesHeader_t);
+ pCurrent_ptr += tlv_len + sizeof(MrvlIEtypesHeader_t);
+ }
+ PRINTM(MEVENT,
+ "coex_scan=%d min_scan=%d coex_win=%d, tx_win=%d rx_win=%d\n",
+ pmadapter->coex_scan, pmadapter->coex_min_scan_time,
+ pmadapter->coex_win_size, pmadapter->coex_tx_win_size,
+ pmadapter->coex_rx_win_size);
+
+ LEAVE();
+}
+
+/**
+ * @brief This function prepares command of supplicant pmk
+ *
+ * @param pmpriv A pointer to mlan_private structure
+ * @param cmd A pointer to HostCmd_DS_COMMAND structure
+ * @param cmd_action The action: GET or SET
+ * @param pdata_buf A pointer to data buffer
+ *
+ * @return MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ */
+mlan_status wlan_cmd_802_11_supplicant_pmk(pmlan_private pmpriv,
+ HostCmd_DS_COMMAND *cmd,
+ t_u16 cmd_action, t_void *pdata_buf)
+{
+ MrvlIEtypes_PMK_t *ppmk_tlv = MNULL;
+ MrvlIEtypes_Passphrase_t *ppassphrase_tlv = MNULL;
+ MrvlIEtypes_SAE_Password_t *psae_password_tlv = MNULL;
+ MrvlIEtypes_SsIdParamSet_t *pssid_tlv = MNULL;
+ MrvlIEtypes_Bssid_t *pbssid_tlv = MNULL;
+ HostCmd_DS_802_11_SUPPLICANT_PMK *pesupplicant_psk =
+ &cmd->params.esupplicant_psk;
+ t_u8 *ptlv_buffer = (t_u8 *)pesupplicant_psk->tlv_buffer;
+ mlan_ds_sec_cfg *sec = (mlan_ds_sec_cfg *)pdata_buf;
+ mlan_ds_passphrase *psk = MNULL;
+ t_u8 zero_mac[] = {0, 0, 0, 0, 0, 0};
+ t_u8 ssid_flag = 0, bssid_flag = 0, pmk_flag = 0, passphrase_flag = 0;
+ t_u8 sae_password_flag = 0;
+
+ ENTER();
+ psk = (mlan_ds_passphrase *)&sec->param.passphrase;
+
+ /*
+ * Parse the rest of the buf here
+ * 1) <ssid="valid ssid"> - This will get the passphrase, AKMP
+ * for specified ssid, if none specified then it will get all.
+ * Eg: iwpriv <mlanX> passphrase 0:ssid=nxp
+ * 2) <psk="psk">:<passphrase="passphare">:<bssid="00:50:43:ef:23:f3">
+ * <ssid="valid ssid"> - passphrase and psk cannot be provided to
+ * the same SSID, Takes one SSID at a time, If ssid= is present
+ * the it should contain a passphrase or psk. If no arguments are
+ * provided then AKMP=802.1x, and passphrase should be provided
+ * after association.
+ * End of each parameter should be followed by a ':'(except for the
+ * last parameter) as the delimiter. If ':' has to be used in
+ * an SSID then a '/' should be preceded to ':' as a escape.
+ * Eg:iwpriv <mlanX> passphrase
+ * "1:ssid=mrvl AP:psk=abcdefgh:bssid=00:50:43:ef:23:f3"
+ * iwpriv <mlanX> passphrase
+ * "1:ssid=nxp/: AP:psk=abcdefgd:bssid=00:50:43:ef:23:f3"
+ * iwpriv <mlanX> passphrase "1:ssid=mrvlAP:psk=abcdefgd"
+ * 3) <ssid="valid ssid"> - This will clear the passphrase
+ * for specified ssid, if none specified then it will clear all.
+ * Eg: iwpriv <mlanX> passphrase 2:ssid=nxp
+ */
+
+ /* -1 is for t_u8 TlvBuffer[1] as this should not be included */
+ cmd->size = sizeof(HostCmd_DS_802_11_SUPPLICANT_PMK) + S_DS_GEN - 1;
+ if (psk && memcmp(pmpriv->adapter, (t_u8 *)&psk->bssid, zero_mac,
+ sizeof(zero_mac))) {
+ pbssid_tlv = (MrvlIEtypes_Bssid_t *)ptlv_buffer;
+ pbssid_tlv->header.type = wlan_cpu_to_le16(TLV_TYPE_BSSID);
+ pbssid_tlv->header.len = MLAN_MAC_ADDR_LENGTH;
+ memcpy_ext(pmpriv->adapter, pbssid_tlv->bssid,
+ (t_u8 *)&psk->bssid, MLAN_MAC_ADDR_LENGTH,
+ MLAN_MAC_ADDR_LENGTH);
+ ptlv_buffer +=
+ (pbssid_tlv->header.len + sizeof(MrvlIEtypesHeader_t));
+ cmd->size +=
+ (pbssid_tlv->header.len + sizeof(MrvlIEtypesHeader_t));
+ pbssid_tlv->header.len =
+ wlan_cpu_to_le16(pbssid_tlv->header.len);
+ bssid_flag = 1;
+ }
+ if (psk && (psk->psk_type == MLAN_PSK_PMK)) {
+ ppmk_tlv = (MrvlIEtypes_PMK_t *)ptlv_buffer;
+ ppmk_tlv->header.type = wlan_cpu_to_le16(TLV_TYPE_PMK);
+ ppmk_tlv->header.len = MLAN_MAX_KEY_LENGTH;
+ memcpy_ext(pmpriv->adapter, ppmk_tlv->pmk, psk->psk.pmk.pmk,
+ MLAN_MAX_KEY_LENGTH, MLAN_MAX_KEY_LENGTH);
+ ptlv_buffer +=
+ (ppmk_tlv->header.len + sizeof(MrvlIEtypesHeader_t));
+ cmd->size +=
+ (ppmk_tlv->header.len + sizeof(MrvlIEtypesHeader_t));
+ ppmk_tlv->header.len = wlan_cpu_to_le16(ppmk_tlv->header.len);
+ pmk_flag = 1;
+ }
+ if (psk->ssid.ssid_len) {
+ pssid_tlv = (MrvlIEtypes_SsIdParamSet_t *)ptlv_buffer;
+ pssid_tlv->header.type = wlan_cpu_to_le16(TLV_TYPE_SSID);
+ pssid_tlv->header.len =
+ (t_u16)MIN(MLAN_MAX_SSID_LENGTH, psk->ssid.ssid_len);
+ memcpy_ext(pmpriv->adapter, (t_u8 *)pssid_tlv->ssid,
+ (t_u8 *)psk->ssid.ssid, psk->ssid.ssid_len,
+ MLAN_MAX_SSID_LENGTH);
+ ptlv_buffer +=
+ (pssid_tlv->header.len + sizeof(MrvlIEtypesHeader_t));
+ cmd->size +=
+ (pssid_tlv->header.len + sizeof(MrvlIEtypesHeader_t));
+ pssid_tlv->header.len = wlan_cpu_to_le16(pssid_tlv->header.len);
+ ssid_flag = 1;
+ }
+ if (psk->psk_type == MLAN_PSK_PASSPHRASE) {
+ ppassphrase_tlv = (MrvlIEtypes_Passphrase_t *)ptlv_buffer;
+ ppassphrase_tlv->header.type =
+ wlan_cpu_to_le16(TLV_TYPE_PASSPHRASE);
+ ppassphrase_tlv->header.len =
+ (t_u16)MIN(MLAN_MAX_PASSPHRASE_LENGTH,
+ psk->psk.passphrase.passphrase_len);
+ memcpy_ext(pmpriv->adapter, ppassphrase_tlv->passphrase,
+ psk->psk.passphrase.passphrase,
+ psk->psk.passphrase.passphrase_len,
+ MLAN_MAX_PASSPHRASE_LENGTH);
+ ptlv_buffer += (ppassphrase_tlv->header.len +
+ sizeof(MrvlIEtypesHeader_t));
+ cmd->size += (ppassphrase_tlv->header.len +
+ sizeof(MrvlIEtypesHeader_t));
+ ppassphrase_tlv->header.len =
+ wlan_cpu_to_le16(ppassphrase_tlv->header.len);
+ passphrase_flag = 1;
+ }
+ if (psk->psk_type == MLAN_PSK_SAE_PASSWORD) {
+ psae_password_tlv = (MrvlIEtypes_SAE_Password_t *)ptlv_buffer;
+ psae_password_tlv->header.type =
+ wlan_cpu_to_le16(TLV_TYPE_SAE_PASSWORD);
+ psae_password_tlv->header.len =
+ (t_u16)MIN(MLAN_MAX_SAE_PASSWORD_LENGTH,
+ psk->psk.sae_password.sae_password_len);
+ memcpy_ext(pmpriv->adapter, psae_password_tlv->sae_password,
+ psk->psk.sae_password.sae_password,
+ psk->psk.sae_password.sae_password_len,
+ MLAN_MAX_SAE_PASSWORD_LENGTH);
+ ptlv_buffer += (psae_password_tlv->header.len +
+ sizeof(MrvlIEtypesHeader_t));
+ cmd->size += (psae_password_tlv->header.len +
+ sizeof(MrvlIEtypesHeader_t));
+ psae_password_tlv->header.len =
+ wlan_cpu_to_le16(psae_password_tlv->header.len);
+ sae_password_flag = 1;
+ }
+ if ((cmd_action == HostCmd_ACT_GEN_SET) &&
+ ((ssid_flag || bssid_flag) && (!pmk_flag && !passphrase_flag) &&
+ (!pmk_flag && !sae_password_flag))) {
+ PRINTM(MERROR,
+ "Invalid case,ssid/bssid present without pmk, passphrase or sae password\n");
+ LEAVE();
+ return MLAN_STATUS_FAILURE;
+ }
+ cmd->command = wlan_cpu_to_le16(HostCmd_CMD_SUPPLICANT_PMK);
+ pesupplicant_psk->action = wlan_cpu_to_le16(cmd_action);
+ pesupplicant_psk->cache_result = 0;
+ cmd->size = wlan_cpu_to_le16(cmd->size);
+ LEAVE();
+ return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ * @brief Handle the supplicant pmk response
+ *
+ * @param pmpriv A pointer to mlan_private structure
+ * @param resp A pointer to HostCmd_DS_COMMAND
+ * @param pioctl_buf A pointer to mlan_ioctl_req structure
+ *
+ * @return MLAN_STATUS_SUCCESS MLAN_STATUS_FAILURE
+ */
+mlan_status wlan_ret_802_11_supplicant_pmk(pmlan_private pmpriv,
+ HostCmd_DS_COMMAND *resp,
+ mlan_ioctl_req *pioctl_buf)
+{
+ HostCmd_DS_802_11_SUPPLICANT_PMK *supplicant_pmk_resp =
+ &resp->params.esupplicant_psk;
+ mlan_ds_sec_cfg *sec_buf = MNULL;
+ mlan_ds_sec_cfg *sec = MNULL;
+ mlan_adapter *pmadapter = pmpriv->adapter;
+ pmlan_callbacks pcb = &pmadapter->callbacks;
+ MrvlIEtypes_PMK_t *ppmk_tlv = MNULL;
+ MrvlIEtypes_Passphrase_t *passphrase_tlv = MNULL;
+ MrvlIEtypes_SAE_Password_t *psae_password_tlv = MNULL;
+ MrvlIEtypes_SsIdParamSet_t *pssid_tlv = MNULL;
+ MrvlIEtypes_Bssid_t *pbssid_tlv = MNULL;
+ t_u8 *tlv_buf = (t_u8 *)supplicant_pmk_resp->tlv_buffer;
+ t_u16 action = wlan_le16_to_cpu(supplicant_pmk_resp->action);
+ int tlv_buf_len = 0;
+ t_u16 tlv;
+ mlan_status ret = MLAN_STATUS_SUCCESS;
+
+ ENTER();
+ tlv_buf_len = resp->size -
+ (sizeof(HostCmd_DS_802_11_SUPPLICANT_PMK) + S_DS_GEN - 1);
+
+ if (pioctl_buf) {
+ if (((mlan_ds_bss *)pioctl_buf->pbuf)->sub_command ==
+ MLAN_OID_BSS_FIND_BSS) {
+ ret = pcb->moal_malloc(pmadapter->pmoal_handle,
+ sizeof(mlan_ds_sec_cfg),
+ MLAN_MEM_DEF, (t_u8 **)&sec_buf);
+ if (ret || !sec_buf) {
+ PRINTM(MERROR, "Could not allocate sec_buf!\n");
+ LEAVE();
+ return ret;
+ }
+ sec = sec_buf;
+ } else {
+ sec = (mlan_ds_sec_cfg *)pioctl_buf->pbuf;
+ }
+ if (action == HostCmd_ACT_GEN_GET) {
+ while (tlv_buf_len > 0) {
+ tlv = (*tlv_buf) | (*(tlv_buf + 1) << 8);
+ if ((tlv != TLV_TYPE_SSID) &&
+ (tlv != TLV_TYPE_BSSID) &&
+ (tlv != TLV_TYPE_PASSPHRASE) &&
+ (tlv != TLV_TYPE_PMK) &&
+ (tlv != TLV_TYPE_SAE_PASSWORD))
+ break;
+ switch (tlv) {
+ case TLV_TYPE_SSID:
+ pssid_tlv =
+ (MrvlIEtypes_SsIdParamSet_t *)
+ tlv_buf;
+ pssid_tlv->header.len =
+ wlan_le16_to_cpu(
+ pssid_tlv->header.len);
+ memcpy_ext(
+ pmpriv->adapter,
+ sec->param.passphrase.ssid.ssid,
+ pssid_tlv->ssid,
+ pssid_tlv->header.len,
+ MLAN_MAX_SSID_LENGTH);
+ sec->param.passphrase.ssid.ssid_len =
+ MIN(MLAN_MAX_SSID_LENGTH,
+ pssid_tlv->header.len);
+ tlv_buf += pssid_tlv->header.len +
+ sizeof(MrvlIEtypesHeader_t);
+ tlv_buf_len -=
+ (pssid_tlv->header.len +
+ sizeof(MrvlIEtypesHeader_t));
+ break;
+ case TLV_TYPE_BSSID:
+ pbssid_tlv =
+ (MrvlIEtypes_Bssid_t *)tlv_buf;
+ pbssid_tlv->header.len =
+ wlan_le16_to_cpu(
+ pbssid_tlv->header.len);
+ memcpy_ext(pmpriv->adapter,
+ &sec->param.passphrase.bssid,
+ pbssid_tlv->bssid,
+ MLAN_MAC_ADDR_LENGTH,
+ MLAN_MAC_ADDR_LENGTH);
+ tlv_buf += pbssid_tlv->header.len +
+ sizeof(MrvlIEtypesHeader_t);
+ tlv_buf_len -=
+ (pbssid_tlv->header.len +
+ sizeof(MrvlIEtypesHeader_t));
+ break;
+ case TLV_TYPE_PASSPHRASE:
+ passphrase_tlv =
+ (MrvlIEtypes_Passphrase_t *)
+ tlv_buf;
+ passphrase_tlv->header
+ .len = wlan_le16_to_cpu(
+ passphrase_tlv->header.len);
+ sec->param.passphrase.psk_type =
+ MLAN_PSK_PASSPHRASE;
+ sec->param.passphrase.psk.passphrase
+ .passphrase_len =
+ passphrase_tlv->header.len;
+ memcpy_ext(
+ pmpriv->adapter,
+ sec->param.passphrase.psk
+ .passphrase.passphrase,
+ passphrase_tlv->passphrase,
+ passphrase_tlv->header.len,
+ MLAN_MAX_PASSPHRASE_LENGTH);
+ tlv_buf += passphrase_tlv->header.len +
+ sizeof(MrvlIEtypesHeader_t);
+ tlv_buf_len -=
+ (passphrase_tlv->header.len +
+ sizeof(MrvlIEtypesHeader_t));
+ break;
+ case TLV_TYPE_SAE_PASSWORD:
+ psae_password_tlv =
+ (MrvlIEtypes_SAE_Password_t *)
+ tlv_buf;
+ psae_password_tlv->header
+ .len = wlan_le16_to_cpu(
+ psae_password_tlv->header.len);
+ sec->param.passphrase.psk_type =
+ MLAN_PSK_SAE_PASSWORD;
+ sec->param.passphrase.psk.sae_password
+ .sae_password_len =
+ psae_password_tlv->header.len;
+ memcpy_ext(
+ pmpriv->adapter,
+ sec->param.passphrase.psk
+ .sae_password
+ .sae_password,
+ psae_password_tlv->sae_password,
+ psae_password_tlv->header.len,
+ MLAN_MAX_SAE_PASSWORD_LENGTH);
+ tlv_buf +=
+ psae_password_tlv->header.len +
+ sizeof(MrvlIEtypesHeader_t);
+ tlv_buf_len -=
+ (psae_password_tlv->header.len +
+ sizeof(MrvlIEtypesHeader_t));
+ break;
+ case TLV_TYPE_PMK:
+ ppmk_tlv = (MrvlIEtypes_PMK_t *)tlv_buf;
+ ppmk_tlv->header.len = wlan_le16_to_cpu(
+ ppmk_tlv->header.len);
+ sec->param.passphrase.psk_type =
+ MLAN_PSK_PMK;
+ memcpy_ext(pmpriv->adapter,
+ sec->param.passphrase.psk.pmk
+ .pmk,
+ ppmk_tlv->pmk,
+ ppmk_tlv->header.len,
+ MLAN_MAX_KEY_LENGTH);
+ tlv_buf += ppmk_tlv->header.len +
+ sizeof(MrvlIEtypesHeader_t);
+ tlv_buf_len -=
+ (ppmk_tlv->header.len +
+ sizeof(MrvlIEtypesHeader_t));
+ break;
+ }
+ }
+#ifdef STA_SUPPORT
+ if (GET_BSS_ROLE(pmpriv) == MLAN_BSS_ROLE_STA &&
+ ((mlan_ds_bss *)pioctl_buf->pbuf)->sub_command ==
+ MLAN_OID_BSS_FIND_BSS) {
+ wlan_set_ewpa_mode(pmpriv,
+ &sec->param.passphrase);
+ ret = wlan_find_bss(pmpriv, pioctl_buf);
+ }
+#endif
+
+ } else if (action == HostCmd_ACT_GEN_SET) {
+ PRINTM(MINFO, "Esupp PMK set: enable ewpa query\n");
+ pmpriv->ewpa_query = MTRUE;
+ }
+ if (sec_buf)
+ pcb->moal_mfree(pmadapter->pmoal_handle,
+ (t_u8 *)sec_buf);
+ }
+
+ LEAVE();
+ return ret;
+}
+
+/**
+ * @brief This function prepares command of independent reset.
+ *
+ * @param cmd A pointer to HostCmd_DS_COMMAND structure
+ * @param cmd_action the action: GET or SET
+ * @param pdata_buf A pointer to data buffer
+ * @return MLAN_STATUS_SUCCESS
+ */
+mlan_status wlan_cmd_ind_rst_cfg(HostCmd_DS_COMMAND *cmd, t_u16 cmd_action,
+ t_void *pdata_buf)
+{
+ mlan_ds_ind_rst_cfg *pdata_ind_rst = (mlan_ds_ind_rst_cfg *)pdata_buf;
+ HostCmd_DS_INDEPENDENT_RESET_CFG *ind_rst_cfg =
+ (HostCmd_DS_INDEPENDENT_RESET_CFG *)&cmd->params.ind_rst_cfg;
+
+ ENTER();
+
+ cmd->command = wlan_cpu_to_le16(HostCmd_CMD_INDEPENDENT_RESET_CFG);
+ cmd->size = wlan_cpu_to_le16(sizeof(HostCmd_DS_INDEPENDENT_RESET_CFG) +
+ S_DS_GEN);
+
+ ind_rst_cfg->action = wlan_cpu_to_le16(cmd_action);
+ if (cmd_action == HostCmd_ACT_GEN_SET) {
+ ind_rst_cfg->ir_mode = pdata_ind_rst->ir_mode;
+ ind_rst_cfg->gpio_pin = pdata_ind_rst->gpio_pin;
+ }
+
+ LEAVE();
+ return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ * @brief This function handles the command response of independent reset
+ *
+ * @param pmpriv A pointer to mlan_private structure
+ * @param resp A pointer to HostCmd_DS_COMMAND
+ * @param pioctl_buf A pointer to command buffer
+ *
+ * @return MLAN_STATUS_SUCCESS
+ */
+mlan_status wlan_ret_ind_rst_cfg(pmlan_private pmpriv, HostCmd_DS_COMMAND *resp,
+ mlan_ioctl_req *pioctl_buf)
+{
+ mlan_ds_misc_cfg *misc = MNULL;
+ const HostCmd_DS_INDEPENDENT_RESET_CFG *ind_rst_cfg =
+ (HostCmd_DS_INDEPENDENT_RESET_CFG *)&resp->params.ind_rst_cfg;
+
+ ENTER();
+
+ if (pioctl_buf) {
+ misc = (mlan_ds_misc_cfg *)pioctl_buf->pbuf;
+
+ if (wlan_le16_to_cpu(ind_rst_cfg->action) ==
+ HostCmd_ACT_GEN_GET) {
+ misc->param.ind_rst_cfg.ir_mode = ind_rst_cfg->ir_mode;
+ misc->param.ind_rst_cfg.gpio_pin =
+ ind_rst_cfg->gpio_pin;
+ }
+ }
+
+ LEAVE();
+ return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ * @brief This function prepares command of ps inactivity timeout.
+ *
+ * @param pmpriv A pointer to mlan_private structure
+ * @param cmd A pointer to HostCmd_DS_COMMAND structure
+ * @param cmd_action the action: GET or SET
+ * @param pdata_buf A pointer to data buffer
+ * @return MLAN_STATUS_SUCCESS
+ */
+mlan_status wlan_cmd_ps_inactivity_timeout(pmlan_private pmpriv,
+ HostCmd_DS_COMMAND *cmd,
+ t_u16 cmd_action, t_void *pdata_buf)
+{
+ t_u16 timeout = *((t_u16 *)pdata_buf);
+ HostCmd_DS_802_11_PS_INACTIVITY_TIMEOUT *ps_inact_tmo =
+ (HostCmd_DS_802_11_PS_INACTIVITY_TIMEOUT *)&cmd->params
+ .ps_inact_tmo;
+
+ ENTER();
+
+ cmd->command =
+ wlan_cpu_to_le16(HostCmd_CMD_802_11_PS_INACTIVITY_TIMEOUT);
+ cmd->size = wlan_cpu_to_le16(
+ sizeof(HostCmd_DS_802_11_PS_INACTIVITY_TIMEOUT) + S_DS_GEN);
+
+ ps_inact_tmo->action = wlan_cpu_to_le16(cmd_action);
+ if (cmd_action == HostCmd_ACT_GEN_SET)
+ ps_inact_tmo->inact_tmo = wlan_cpu_to_le16(timeout);
+
+ LEAVE();
+ return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ * @brief This function prepares command of HostCmd_CMD_GET_TSF
+ *
+ * @param pmpriv A pointer to mlan_private structure
+ * @param cmd A pointer to HostCmd_DS_COMMAND structure
+ * @param cmd_action The action: GET
+ * @return MLAN_STATUS_SUCCESS
+ */
+mlan_status wlan_cmd_get_tsf(pmlan_private pmpriv, HostCmd_DS_COMMAND *cmd,
+ t_u16 cmd_action)
+{
+ ENTER();
+
+ cmd->command = wlan_cpu_to_le16(HostCmd_CMD_GET_TSF);
+ cmd->size = wlan_cpu_to_le16((sizeof(HostCmd_DS_TSF)) + S_DS_GEN);
+
+ LEAVE();
+ return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ * @brief This function handles the command response of HostCmd_CMD_GET_TSF
+ *
+ * @param pmpriv A pointer to mlan_private structure
+ * @param resp A pointer to HostCmd_DS_COMMAND
+ * @param pioctl_buf A pointer to mlan_ioctl_req structure
+ *
+ * @return MLAN_STATUS_SUCCESS
+ */
+mlan_status wlan_ret_get_tsf(pmlan_private pmpriv, HostCmd_DS_COMMAND *resp,
+ mlan_ioctl_req *pioctl_buf)
+{
+ mlan_ds_misc_cfg *misc_cfg = MNULL;
+ HostCmd_DS_TSF *tsf_pointer = (HostCmd_DS_TSF *)&resp->params.tsf;
+
+ ENTER();
+ if (pioctl_buf) {
+ misc_cfg = (mlan_ds_misc_cfg *)pioctl_buf->pbuf;
+ misc_cfg->param.misc_tsf = wlan_le64_to_cpu(tsf_pointer->tsf);
+ }
+
+ LEAVE();
+ return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ * @brief This function handles the command response of chan_region_cfg
+ *
+ * @param pmpriv A pointer to mlan_private structure
+ * @param resp A pointer to HostCmd_DS_COMMAND
+ * @param pioctl_buf A pointer to command buffer
+ *
+ * @return MLAN_STATUS_SUCCESS
+ */
+mlan_status wlan_ret_chan_region_cfg(pmlan_private pmpriv,
+ HostCmd_DS_COMMAND *resp,
+ mlan_ioctl_req *pioctl_buf)
+{
+ mlan_adapter *pmadapter = pmpriv->adapter;
+ t_u16 action;
+ HostCmd_DS_CHAN_REGION_CFG *reg = MNULL;
+ t_u8 *tlv_buf = MNULL;
+ t_u16 tlv_buf_left;
+ mlan_ds_misc_cfg *misc_cfg = MNULL;
+ mlan_ds_misc_chnrgpwr_cfg *cfg = MNULL;
+ mlan_status ret = MLAN_STATUS_SUCCESS;
+
+ ENTER();
+
+ reg = (HostCmd_DS_CHAN_REGION_CFG *)&resp->params.reg_cfg;
+ if (!reg) {
+ ret = MLAN_STATUS_FAILURE;
+ goto done;
+ }
+
+ action = wlan_le16_to_cpu(reg->action);
+ if (action != HostCmd_ACT_GEN_GET) {
+ ret = MLAN_STATUS_FAILURE;
+ goto done;
+ }
+
+ tlv_buf = (t_u8 *)reg + sizeof(*reg);
+ tlv_buf_left = wlan_le16_to_cpu(resp->size) - S_DS_GEN - sizeof(*reg);
+
+ /* Add FW cfp tables and region info */
+ wlan_add_fw_cfp_tables(pmpriv, tlv_buf, tlv_buf_left);
+
+ if (!pioctl_buf)
+ goto done;
+
+ if (!pioctl_buf->pbuf) {
+ ret = MLAN_STATUS_FAILURE;
+ goto done;
+ }
+
+ misc_cfg = (mlan_ds_misc_cfg *)pioctl_buf->pbuf;
+
+ if (misc_cfg->sub_command == MLAN_OID_MISC_GET_REGIONPWR_CFG) {
+ cfg = (mlan_ds_misc_chnrgpwr_cfg *)&(
+ misc_cfg->param.rgchnpwr_cfg);
+ cfg->length = wlan_le16_to_cpu(resp->size);
+ memcpy_ext(pmpriv->adapter, cfg->chnrgpwr_buf, (t_u8 *)resp,
+ cfg->length, sizeof(cfg->chnrgpwr_buf));
+ } else {
+ memset(pmpriv->adapter, &misc_cfg->param.custom_reg_domain, 0,
+ sizeof(mlan_ds_custom_reg_domain));
+ if (pmadapter->otp_region)
+ memcpy_ext(pmpriv->adapter,
+ &misc_cfg->param.custom_reg_domain.region,
+ pmadapter->otp_region,
+ sizeof(otp_region_info_t),
+ sizeof(otp_region_info_t));
+ if (pmadapter->cfp_otp_bg) {
+ misc_cfg->param.custom_reg_domain.num_bg_chan =
+ pmadapter->tx_power_table_bg_rows;
+ memcpy_ext(pmpriv->adapter,
+ (t_u8 *)misc_cfg->param.custom_reg_domain
+ .cfp_tbl,
+ (t_u8 *)pmadapter->cfp_otp_bg,
+ pmadapter->tx_power_table_bg_rows *
+ sizeof(chan_freq_power_t),
+ pmadapter->tx_power_table_bg_rows *
+ sizeof(chan_freq_power_t));
+ }
+ if (pmadapter->cfp_otp_a) {
+ misc_cfg->param.custom_reg_domain.num_a_chan =
+ pmadapter->tx_power_table_a_rows;
+ memcpy_ext(pmpriv->adapter,
+ (t_u8 *)misc_cfg->param.custom_reg_domain
+ .cfp_tbl +
+ pmadapter->tx_power_table_bg_rows *
+ sizeof(chan_freq_power_t),
+ (t_u8 *)pmadapter->cfp_otp_a,
+ pmadapter->tx_power_table_a_rows *
+ sizeof(chan_freq_power_t),
+ pmadapter->tx_power_table_a_rows *
+ sizeof(chan_freq_power_t));
+ }
+ }
+done:
+ LEAVE();
+ return ret;
+}
+
+/**
+ * @brief This function prepares command of packet aggragation
+ *
+ * @param pmpriv A pointer to mlan_private structure
+ * @param cmd A pointer to HostCmd_DS_COMMAND structure
+ * @param cmd_action the action: GET or SET
+ * @param pdata_buf A pointer to data buffer
+ * @return MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ */
+mlan_status wlan_cmd_packet_aggr_ctrl(pmlan_private pmpriv,
+ HostCmd_DS_COMMAND *cmd, t_u16 cmd_action,
+ t_void *pdata_buf)
+{
+ HostCmd_DS_PACKET_AGGR_CTRL *aggr_ctrl = &cmd->params.aggr_ctrl;
+ mlan_ds_misc_aggr_ctrl *aggr = (mlan_ds_misc_aggr_ctrl *)pdata_buf;
+
+ ENTER();
+
+ cmd->command = wlan_cpu_to_le16(HostCmd_CMD_PACKET_AGGR_CTRL);
+ aggr_ctrl->action = wlan_cpu_to_le16(cmd_action);
+ cmd->size = wlan_cpu_to_le16(sizeof(HostCmd_DS_PACKET_AGGR_CTRL) +
+ S_DS_GEN);
+ aggr_ctrl->aggr_enable = 0;
+
+ if (aggr->tx.enable)
+ aggr_ctrl->aggr_enable |= MBIT(0);
+ aggr_ctrl->aggr_enable = wlan_cpu_to_le16(aggr_ctrl->aggr_enable);
+
+ LEAVE();
+ return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ * @brief This function handles the command response of
+ * packet aggregation
+ *
+ * @param pmpriv A pointer to mlan_private structure
+ * @param resp A pointer to HostCmd_DS_COMMAND
+ * @param pioctl_buf A pointer to command buffer
+ *
+ * @return MLAN_STATUS_SUCCESS
+ */
+mlan_status wlan_ret_packet_aggr_ctrl(pmlan_private pmpriv,
+ HostCmd_DS_COMMAND *resp,
+ mlan_ioctl_req *pioctl_buf)
+{
+ mlan_ds_misc_cfg *misc = MNULL;
+ HostCmd_DS_PACKET_AGGR_CTRL *aggr_ctrl = &resp->params.aggr_ctrl;
+ mlan_ds_misc_aggr_ctrl *aggr = MNULL;
+#if defined(USB)
+ mlan_adapter *pmadapter = pmpriv->adapter;
+ t_u8 i;
+ t_u8 change = 0;
+ usb_tx_aggr_params *pusb_tx_aggr = MNULL;
+#endif
+
+ ENTER();
+
+ aggr_ctrl->aggr_enable = wlan_le16_to_cpu(aggr_ctrl->aggr_enable);
+ aggr_ctrl->tx_aggr_max_size =
+ wlan_le16_to_cpu(aggr_ctrl->tx_aggr_max_size);
+ aggr_ctrl->tx_aggr_max_num =
+ wlan_le16_to_cpu(aggr_ctrl->tx_aggr_max_num);
+ aggr_ctrl->tx_aggr_align = wlan_le16_to_cpu(aggr_ctrl->tx_aggr_align);
+ PRINTM(MCMND, "enable=0x%x, tx_size=%d, tx_num=%d, tx_align=%d\n",
+ aggr_ctrl->aggr_enable, aggr_ctrl->tx_aggr_max_size,
+ aggr_ctrl->tx_aggr_max_num, aggr_ctrl->tx_aggr_align);
+#if defined(USB)
+ if (IS_USB(pmadapter->card_type)) {
+ if (aggr_ctrl->aggr_enable & MBIT(0)) {
+ if (!pmadapter->pcard_usb->usb_tx_aggr[0]
+ .aggr_ctrl.enable) {
+ pmadapter->pcard_usb->usb_tx_aggr[0]
+ .aggr_ctrl.enable = MTRUE;
+ change = MTRUE;
+ }
+
+ } else {
+ if (pmadapter->pcard_usb->usb_tx_aggr[0]
+ .aggr_ctrl.enable) {
+ pmadapter->pcard_usb->usb_tx_aggr[0]
+ .aggr_ctrl.enable = MFALSE;
+ change = MTRUE;
+ }
+ }
+ pmadapter->pcard_usb->usb_tx_aggr[0].aggr_ctrl.aggr_mode =
+ MLAN_USB_AGGR_MODE_LEN_V2;
+ pmadapter->pcard_usb->usb_tx_aggr[0].aggr_ctrl.aggr_align =
+ aggr_ctrl->tx_aggr_align;
+ pmadapter->pcard_usb->usb_tx_aggr[0].aggr_ctrl.aggr_max =
+ aggr_ctrl->tx_aggr_max_size;
+ pmadapter->pcard_usb->usb_tx_aggr[0].aggr_ctrl.aggr_tmo =
+ MLAN_USB_TX_AGGR_TIMEOUT_MSEC * 1000;
+ if (change) {
+ wlan_reset_usb_tx_aggr(pmadapter);
+ for (i = 0; i < pmadapter->priv_num; ++i) {
+ if (pmadapter->priv[i]) {
+ pusb_tx_aggr =
+ wlan_get_usb_tx_aggr_params(
+ pmadapter,
+ pmadapter->priv[i]
+ ->port);
+ if (pusb_tx_aggr &&
+ pusb_tx_aggr->aggr_ctrl.aggr_mode ==
+ MLAN_USB_AGGR_MODE_LEN_V2)
+ pmadapter->priv[i]->intf_hr_len =
+ MLAN_USB_TX_AGGR_HEADER;
+ else
+ pmadapter->priv[i]->intf_hr_len =
+ USB_INTF_HEADER_LEN;
+ }
+ }
+ }
+ }
+#endif
+ if (pioctl_buf) {
+ misc = (mlan_ds_misc_cfg *)pioctl_buf->pbuf;
+ aggr = (mlan_ds_misc_aggr_ctrl *)&(misc->param.aggr_params);
+ if (aggr_ctrl->aggr_enable & MBIT(0))
+ aggr->tx.enable = MTRUE;
+ else
+ aggr->tx.enable = MFALSE;
+ aggr->tx.aggr_align = aggr_ctrl->tx_aggr_align;
+ aggr->tx.aggr_max_size = aggr_ctrl->tx_aggr_max_size;
+ aggr->tx.aggr_max_num = aggr_ctrl->tx_aggr_max_num;
+#if defined(USB)
+ if (IS_USB(pmadapter->card_type))
+ aggr->tx.aggr_tmo = pmadapter->pcard_usb->usb_tx_aggr[0]
+ .aggr_ctrl.aggr_tmo;
+#endif
+ }
+ LEAVE();
+ return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ * @brief This function sends fw dump event command to firmware.
+ *
+ * @param pmpriv A pointer to mlan_private structure
+ * @param cmd Hostcmd ID
+ * @param cmd_action Command action
+ * @param pdata_buf A void pointer to information buffer
+ * @return N/A
+ */
+mlan_status wlan_cmd_fw_dump_event(pmlan_private pmpriv,
+ HostCmd_DS_COMMAND *cmd, t_u16 cmd_action,
+ t_void *pdata_buf)
+{
+ ENTER();
+
+ cmd->command = wlan_cpu_to_le16(HostCmd_CMD_FW_DUMP_EVENT);
+ cmd->size = S_DS_GEN;
+ cmd->size = wlan_cpu_to_le16(cmd->size);
+
+ LEAVE();
+ return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ * @brief This function prepares command of get link layer statistics.
+ *
+ * @param pmpriv A pointer to mlan_private structure
+ * @param cmd A pointer to HostCmd_DS_COMMAND structure
+ * @param cmd_action the action: GET or SET
+ * @param pdata_buf A pointer to data buffer
+ *
+ * @return MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ *
+ */
+mlan_status wlan_cmd_802_11_link_statistic(pmlan_private pmpriv,
+ HostCmd_DS_COMMAND *cmd,
+ t_u16 cmd_action,
+ mlan_ioctl_req *pioctl_buf)
+{
+ mlan_ds_get_info *info = (mlan_ds_get_info *)(pioctl_buf->pbuf);
+ HostCmd_DS_802_11_LINK_STATISTIC *ll_stat =
+ &cmd->params.get_link_statistic;
+ wifi_link_layer_params *ll_params = MNULL;
+
+ ENTER();
+
+ cmd->command = wlan_cpu_to_le16(HostCmd_CMD_802_11_LINK_STATS);
+ cmd->size = wlan_cpu_to_le16(S_DS_GEN +
+ sizeof(HostCmd_DS_802_11_LINK_STATISTIC));
+ ll_stat->action = wlan_cpu_to_le16(cmd_action);
+
+ switch (cmd_action) {
+ case HostCmd_ACT_GEN_SET:
+ ll_params =
+ (wifi_link_layer_params *)info->param.link_statistic;
+ ll_stat->mpdu_size_threshold =
+ wlan_cpu_to_le32(ll_params->mpdu_size_threshold);
+ ll_stat->aggressive_statistics_gathering = wlan_cpu_to_le32(
+ ll_params->aggressive_statistics_gathering);
+ break;
+ case HostCmd_ACT_GEN_GET:
+ /** ll_stat->stat_type = wlan_cpu_to_le16(stat_type); */
+ break;
+ default:
+ break;
+ }
+
+ LEAVE();
+ return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ * @brief This function fill link layer statistic from firmware
+ *
+ * @param priv A pointer to
+ * mlan_private structure
+ * @param link_statistic_ioctl_buf, A pointer to fill ioctl buffer
+ * @param resp A pointer to
+ * HostCmd_DS_COMMAND
+ *
+ * @return MLAN_STATUS_SUCCESS
+ */
+static void wlan_fill_link_statistic(mlan_private *priv,
+ char *link_statistic_ioctl_buf,
+ HostCmd_DS_COMMAND *resp)
+{
+ char *link_statistic = link_statistic_ioctl_buf;
+ wifi_radio_stat *radio_stat = MNULL;
+ wifi_iface_stat *iface_stat = MNULL;
+ mlan_wifi_iface_stat *fw_ifaceStat = MNULL;
+ mlan_wifi_radio_stat *fw_radioStat = MNULL;
+ t_u32 num_radio = 0;
+ int i = 0, chan_idx = 0, peerIdx = 0, rate_idx = 0;
+ t_u16 left_len = 0, tlv_type = 0, tlv_len = 0;
+ MrvlIEtypesHeader_t *tlv = MNULL;
+ HostCmd_DS_802_11_LINK_STATISTIC *plink_stat =
+ (HostCmd_DS_802_11_LINK_STATISTIC *)&resp->params
+ .get_link_statistic;
+
+ /* TLV parse */
+ left_len = resp->size - sizeof(HostCmd_DS_802_11_LINK_STATISTIC) -
+ S_DS_GEN;
+ tlv = (MrvlIEtypesHeader_t *)(plink_stat->value);
+ DBG_HEXDUMP(MCMD_D, "tlv:", (void *)tlv, 1024);
+ while (left_len > sizeof(MrvlIEtypesHeader_t)) {
+ tlv_type = wlan_le16_to_cpu(tlv->type);
+ tlv_len = wlan_le16_to_cpu(tlv->len);
+ switch (tlv_type) {
+ case TLV_TYPE_LL_STAT_IFACE:
+ fw_ifaceStat = (mlan_wifi_iface_stat
+ *)((t_u8 *)tlv +
+ sizeof(MrvlIEtypesHeader_t));
+ break;
+ case TLV_TYPE_LL_STAT_RADIO:
+ fw_radioStat = (mlan_wifi_radio_stat
+ *)((t_u8 *)tlv +
+ sizeof(MrvlIEtypesHeader_t));
+ num_radio = MAX_RADIO;
+ break;
+ default:
+ break;
+ }
+ left_len -= (sizeof(MrvlIEtypesHeader_t) + tlv_len);
+ tlv = (MrvlIEtypesHeader_t *)((t_u8 *)tlv + tlv_len +
+ sizeof(MrvlIEtypesHeader_t));
+ }
+
+ if (!fw_ifaceStat || !fw_radioStat) {
+ PRINTM(MERROR, "!fw_ifaceStat || !fw_radioStat\n");
+ return;
+ }
+
+ *((t_u32 *)link_statistic) = num_radio;
+ link_statistic += sizeof(num_radio);
+
+ /* Fill radio stats array*/
+ for (i = 0; i < num_radio; i++) {
+ radio_stat = (wifi_radio_stat *)link_statistic;
+ link_statistic += sizeof(wifi_radio_stat);
+
+ radio_stat->radio = wlan_le32_to_cpu(fw_radioStat[i].radio);
+
+ radio_stat->on_time = wlan_le32_to_cpu(fw_radioStat[i].on_time);
+ radio_stat->tx_time = wlan_le32_to_cpu(fw_radioStat[i].tx_time);
+ radio_stat->reserved0 =
+ wlan_le32_to_cpu(fw_radioStat[i].reserved0);
+ radio_stat->rx_time = wlan_le32_to_cpu(fw_radioStat[i].rx_time);
+ radio_stat->on_time_scan =
+ wlan_le32_to_cpu(fw_radioStat[i].on_time_scan);
+ radio_stat->on_time_nbd =
+ wlan_le32_to_cpu(fw_radioStat[i].on_time_nbd);
+ radio_stat->on_time_gscan =
+ wlan_le32_to_cpu(fw_radioStat[i].on_time_gscan);
+ radio_stat->on_time_roam_scan =
+ wlan_le32_to_cpu(fw_radioStat[i].on_time_roam_scan);
+ radio_stat->on_time_pno_scan =
+ wlan_le32_to_cpu(fw_radioStat[i].on_time_pno_scan);
+ radio_stat->on_time_hs20 =
+ wlan_le32_to_cpu(fw_radioStat[i].on_time_hs20);
+
+ radio_stat->num_channels =
+ wlan_le32_to_cpu(fw_radioStat[i].num_channels);
+ for (chan_idx = 0; chan_idx < radio_stat->num_channels;
+ chan_idx++) {
+ if (radio_stat->num_channels > MAX_NUM_CHAN) {
+ radio_stat->num_channels =
+ wlan_le32_to_cpu(MAX_NUM_CHAN);
+ PRINTM(MERROR,
+ "%s : radio_stat->num_channels=%d\n",
+ __func__, radio_stat->num_channels);
+ break;
+ }
+ radio_stat->channels[chan_idx].channel.width =
+ wlan_le32_to_cpu(fw_radioStat[i]
+ .channels[chan_idx]
+ .channel.width);
+ radio_stat->channels[chan_idx].channel.center_freq =
+ wlan_le32_to_cpu(fw_radioStat[i]
+ .channels[chan_idx]
+ .channel.center_freq);
+ radio_stat->channels[chan_idx].channel.center_freq0 =
+ wlan_le32_to_cpu(fw_radioStat[i]
+ .channels[chan_idx]
+ .channel.center_freq0);
+ radio_stat->channels[chan_idx].channel.center_freq1 =
+ wlan_le32_to_cpu(fw_radioStat[i]
+ .channels[chan_idx]
+ .channel.center_freq1);
+
+ radio_stat->channels[chan_idx]
+ .on_time = wlan_le32_to_cpu(
+ fw_radioStat[i].channels[chan_idx].on_time);
+ radio_stat->channels[chan_idx].cca_busy_time =
+ wlan_le32_to_cpu(fw_radioStat[i]
+ .channels[chan_idx]
+ .cca_busy_time);
+ }
+ }
+
+ /* Fill iface stats*/
+ iface_stat = (wifi_iface_stat *)link_statistic;
+
+ /* get wifi_interface_link_layer_info in driver, not in firmware */
+ if (priv->bss_role == MLAN_BSS_ROLE_STA) {
+ iface_stat->info.mode = MLAN_INTERFACE_STA;
+ if (priv->media_connected)
+ iface_stat->info.state = MLAN_ASSOCIATING;
+ else
+ iface_stat->info.state = MLAN_DISCONNECTED;
+ iface_stat->info.roaming = MLAN_ROAMING_IDLE;
+ iface_stat->info.capabilities = MLAN_CAPABILITY_QOS;
+ memcpy_ext(priv->adapter, iface_stat->info.ssid,
+ priv->curr_bss_params.bss_descriptor.ssid.ssid,
+ MLAN_MAX_SSID_LENGTH, MLAN_MAX_SSID_LENGTH);
+ memcpy_ext(priv->adapter, iface_stat->info.bssid,
+ priv->curr_bss_params.bss_descriptor.mac_address,
+ MLAN_MAC_ADDR_LENGTH, MLAN_MAC_ADDR_LENGTH);
+ } else {
+ iface_stat->info.mode = MLAN_INTERFACE_SOFTAP;
+ iface_stat->info.capabilities = MLAN_CAPABILITY_QOS;
+ }
+ memcpy_ext(priv->adapter, iface_stat->info.mac_addr, priv->curr_addr,
+ MLAN_MAC_ADDR_LENGTH, MLAN_MAC_ADDR_LENGTH);
+ memcpy_ext(priv->adapter, iface_stat->info.ap_country_str,
+ priv->adapter->country_code, COUNTRY_CODE_LEN,
+ COUNTRY_CODE_LEN);
+ memcpy_ext(priv->adapter, iface_stat->info.country_str,
+ priv->adapter->country_code, COUNTRY_CODE_LEN,
+ COUNTRY_CODE_LEN);
+
+ iface_stat->beacon_rx = wlan_le32_to_cpu(fw_ifaceStat->beacon_rx);
+ iface_stat->average_tsf_offset =
+ wlan_le64_to_cpu(fw_ifaceStat->average_tsf_offset);
+ iface_stat->leaky_ap_detected =
+ wlan_le32_to_cpu(fw_ifaceStat->leaky_ap_detected);
+ iface_stat->leaky_ap_avg_num_frames_leaked =
+ wlan_le32_to_cpu(fw_ifaceStat->leaky_ap_avg_num_frames_leaked);
+ iface_stat->leaky_ap_guard_time =
+ wlan_le32_to_cpu(fw_ifaceStat->leaky_ap_guard_time);
+
+ /* Value of iface_stat should be Reaccumulate by each peer */
+ iface_stat->mgmt_rx = wlan_le32_to_cpu(fw_ifaceStat->mgmt_rx);
+ iface_stat->mgmt_action_rx =
+ wlan_le32_to_cpu(fw_ifaceStat->mgmt_action_rx);
+ iface_stat->mgmt_action_tx =
+ wlan_le32_to_cpu(fw_ifaceStat->mgmt_action_tx);
+
+ iface_stat->rssi_mgmt = wlan_le32_to_cpu(fw_ifaceStat->rssi_mgmt);
+ iface_stat->rssi_data = wlan_le32_to_cpu(fw_ifaceStat->rssi_data);
+ iface_stat->rssi_ack = wlan_le32_to_cpu(fw_ifaceStat->rssi_ack);
+
+ for (i = WMM_AC_BK; i <= WMM_AC_VO; i++) {
+ iface_stat->ac[i].ac = i;
+ iface_stat->ac[i].tx_mpdu =
+ wlan_le32_to_cpu(fw_ifaceStat->ac[i].tx_mpdu);
+ iface_stat->ac[i].rx_mpdu =
+ wlan_le32_to_cpu(fw_ifaceStat->ac[i].rx_mpdu);
+ iface_stat->ac[i].tx_mcast =
+ wlan_le32_to_cpu(fw_ifaceStat->ac[i].tx_mcast);
+ iface_stat->ac[i].rx_mcast =
+ wlan_le32_to_cpu(fw_ifaceStat->ac[i].rx_mcast);
+ iface_stat->ac[i].rx_ampdu =
+ wlan_le32_to_cpu(fw_ifaceStat->ac[i].rx_ampdu);
+ iface_stat->ac[i].tx_ampdu =
+ wlan_le32_to_cpu(fw_ifaceStat->ac[i].tx_ampdu);
+ iface_stat->ac[i].mpdu_lost =
+ wlan_le32_to_cpu(fw_ifaceStat->ac[i].mpdu_lost);
+ iface_stat->ac[i].retries =
+ wlan_le32_to_cpu(fw_ifaceStat->ac[i].retries);
+ iface_stat->ac[i].retries_short =
+ wlan_le32_to_cpu(fw_ifaceStat->ac[i].retries_short);
+ iface_stat->ac[i].retries_long =
+ wlan_le32_to_cpu(fw_ifaceStat->ac[i].retries_long);
+ iface_stat->ac[i].contention_time_min = wlan_le32_to_cpu(
+ fw_ifaceStat->ac[i].contention_time_min);
+ iface_stat->ac[i].contention_time_max = wlan_le32_to_cpu(
+ fw_ifaceStat->ac[i].contention_time_max);
+ iface_stat->ac[i].contention_time_avg = wlan_le32_to_cpu(
+ fw_ifaceStat->ac[i].contention_time_avg);
+ iface_stat->ac[i].contention_num_samples = wlan_le32_to_cpu(
+ fw_ifaceStat->ac[i].contention_num_samples);
+ }
+
+ /* LL_STAT V3: STA-solution: support maxium 1 peers for AP*/
+ iface_stat->num_peers = wlan_le32_to_cpu(fw_ifaceStat->num_peers);
+ for (peerIdx = 0; peerIdx < iface_stat->num_peers; peerIdx++) {
+ iface_stat->peer_info[peerIdx].type =
+ fw_ifaceStat->peer_info[peerIdx].type;
+ memcpy_ext(priv->adapter,
+ iface_stat->peer_info[peerIdx].peer_mac_address,
+ fw_ifaceStat->peer_info[peerIdx].peer_mac_address,
+ MLAN_MAC_ADDR_LENGTH, MLAN_MAC_ADDR_LENGTH);
+ iface_stat->peer_info[peerIdx].capabilities = wlan_le32_to_cpu(
+ fw_ifaceStat->peer_info[peerIdx].capabilities);
+ iface_stat->peer_info[peerIdx].num_rate = wlan_le32_to_cpu(
+ fw_ifaceStat->peer_info[peerIdx].num_rate);
+
+ PRINTM(MINFO,
+ "bitrate tx_mpdu rx_mpdu mpdu_lost retries retries_short retries_long\n");
+ for (rate_idx = 0;
+ rate_idx < iface_stat->peer_info[peerIdx].num_rate;
+ rate_idx++) {
+ wlan_fill_hal_wifi_rate(priv,
+ &fw_ifaceStat
+ ->peer_info[peerIdx]
+ .rate_stats[rate_idx]
+ .rate,
+ &iface_stat->peer_info[peerIdx]
+ .rate_stats[rate_idx]
+ .rate);
+
+ iface_stat->peer_info[peerIdx]
+ .rate_stats[rate_idx]
+ .tx_mpdu = wlan_le32_to_cpu(
+ fw_ifaceStat->peer_info[peerIdx]
+ .rate_stats[rate_idx]
+ .tx_mpdu);
+ iface_stat->peer_info[peerIdx]
+ .rate_stats[rate_idx]
+ .rx_mpdu = wlan_le32_to_cpu(
+ fw_ifaceStat->peer_info[peerIdx]
+ .rate_stats[rate_idx]
+ .rx_mpdu);
+ iface_stat->peer_info[peerIdx]
+ .rate_stats[rate_idx]
+ .mpdu_lost = wlan_le32_to_cpu(
+ fw_ifaceStat->peer_info[peerIdx]
+ .rate_stats[rate_idx]
+ .mpdu_lost);
+ iface_stat->peer_info[peerIdx]
+ .rate_stats[rate_idx]
+ .retries = wlan_le32_to_cpu(
+ fw_ifaceStat->peer_info[peerIdx]
+ .rate_stats[rate_idx]
+ .retries);
+ iface_stat->peer_info[peerIdx]
+ .rate_stats[rate_idx]
+ .retries_short = wlan_le32_to_cpu(
+ fw_ifaceStat->peer_info[peerIdx]
+ .rate_stats[rate_idx]
+ .retries_short);
+ iface_stat->peer_info[peerIdx]
+ .rate_stats[rate_idx]
+ .retries_long = wlan_le32_to_cpu(
+ fw_ifaceStat->peer_info[peerIdx]
+ .rate_stats[rate_idx]
+ .retries_long);
+ PRINTM(MCMND,
+ "0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x\n",
+ iface_stat->peer_info[peerIdx]
+ .rate_stats[rate_idx]
+ .rate.bitrate,
+ iface_stat->peer_info[peerIdx]
+ .rate_stats[rate_idx]
+ .tx_mpdu,
+ iface_stat->peer_info[peerIdx]
+ .rate_stats[rate_idx]
+ .rx_mpdu,
+ iface_stat->peer_info[peerIdx]
+ .rate_stats[rate_idx]
+ .mpdu_lost,
+ iface_stat->peer_info[peerIdx]
+ .rate_stats[rate_idx]
+ .retries,
+ iface_stat->peer_info[peerIdx]
+ .rate_stats[rate_idx]
+ .retries_short,
+ iface_stat->peer_info[peerIdx]
+ .rate_stats[rate_idx]
+ .retries_long);
+ }
+ }
+}
+
+/**
+ * @brief This function handles the command response of get_link_statistic
+ *
+ * @param pmpriv A pointer to mlan_private structure
+ * @param resp A pointer to HostCmd_DS_COMMAND
+ * @param pioctl_buf A pointer to mlan_ioctl_req structure
+ *
+ * @return MLAN_STATUS_SUCCESS
+ */
+mlan_status wlan_ret_get_link_statistic(pmlan_private pmpriv,
+ HostCmd_DS_COMMAND *resp,
+ mlan_ioctl_req *pioctl_buf)
+{
+ mlan_ds_get_info *info;
+ t_u8 *link_statistic = MNULL;
+ t_u16 action = wlan_le16_to_cpu(resp->params.get_link_statistic.action);
+
+ ENTER();
+
+ if (pioctl_buf) {
+ info = (mlan_ds_get_info *)pioctl_buf->pbuf;
+ link_statistic = info->param.link_statistic;
+
+ switch (action) {
+ case HostCmd_ACT_GEN_GET:
+ wlan_fill_link_statistic(pmpriv, link_statistic, resp);
+ break;
+ case HostCmd_ACT_GEN_SET:
+ case HostCmd_ACT_GEN_REMOVE:
+ /* nothing to do */
+ break;
+ default:
+ break;
+ }
+ /* Indicate ioctl complete */
+ pioctl_buf->data_read_written =
+ BUF_MAXLEN + MLAN_SUB_COMMAND_SIZE;
+ }
+
+ LEAVE();
+ return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ * @brief This function sends boot sleep configure command to firmware.
+ *
+ * @param pmpriv A pointer to mlan_private structure
+ * @param cmd Hostcmd ID
+ * @param cmd_action Command action
+ * @param pdata_buf A void pointer to information buffer
+ * @return MLAN_STATUS_SUCCESS/ MLAN_STATUS_FAILURE
+ */
+mlan_status wlan_cmd_boot_sleep(pmlan_private pmpriv, HostCmd_DS_COMMAND *cmd,
+ t_u16 cmd_action, t_void *pdata_buf)
+{
+ HostCmd_DS_BOOT_SLEEP *boot_sleep = MNULL;
+ t_u16 enable = *(t_u16 *)pdata_buf;
+
+ ENTER();
+
+ cmd->command = wlan_cpu_to_le16(HostCmd_CMD_BOOT_SLEEP);
+ boot_sleep = &cmd->params.boot_sleep;
+ boot_sleep->action = wlan_cpu_to_le16(cmd_action);
+ boot_sleep->enable = wlan_cpu_to_le16(enable);
+
+ cmd->size = S_DS_GEN + sizeof(HostCmd_DS_BOOT_SLEEP);
+
+ LEAVE();
+ return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ * @brief This function handles the command response of boot sleep cfg
+ *
+ * @param pmpriv A pointer to mlan_private structure
+ * @param resp A pointer to HostCmd_DS_COMMAND
+ * @param pioctl_buf A pointer to mlan_ioctl_req structure
+ *
+ * @return MLAN_STATUS_SUCCESS
+ */
+mlan_status wlan_ret_boot_sleep(pmlan_private pmpriv, HostCmd_DS_COMMAND *resp,
+ mlan_ioctl_req *pioctl_buf)
+{
+ HostCmd_DS_BOOT_SLEEP *boot_sleep = &resp->params.boot_sleep;
+ mlan_ds_misc_cfg *cfg = (mlan_ds_misc_cfg *)pioctl_buf->pbuf;
+
+ ENTER();
+
+ cfg->param.boot_sleep = wlan_le16_to_cpu(boot_sleep->enable);
+ PRINTM(MCMND, "boot sleep cfg status %u", cfg->param.boot_sleep);
+
+ LEAVE();
+ return MLAN_STATUS_SUCCESS;
+}
+
+#if defined(DRV_EMBEDDED_AUTHENTICATOR) || defined(DRV_EMBEDDED_SUPPLICANT)
+
+/**
+ * @brief This function handles send crypto command
+ *
+ * @param pmpriv A pointer to mlan_private structure
+ * @param cmd Hostcmd ID
+ * @param cmd_action Command action
+ * @param pdata_buf A void pointer to information buffer
+ *
+ * @return MLAN_STATUS_SUCCESS
+ */
+mlan_status wlan_cmd_crypto(pmlan_private pmpriv, HostCmd_DS_COMMAND *cmd,
+ t_u16 cmd_action, t_u16 *pdata_buf)
+{
+ HostCmd_DS_CRYPTO *cry_cmd = &cmd->params.crypto_cmd;
+ mlan_ds_sup_cfg *cfg = (mlan_ds_sup_cfg *)pdata_buf;
+#if defined(DRV_EMBEDDED_AUTHENTICATOR) || defined(DRV_EMBEDDED_SUPPLICANT)
+ subcmd_prf_hmac_sha1_t *prf_hmac_sha1 = MNULL;
+ subcmd_hmac_sha1_t *hmac_sha1 = MNULL;
+ subcmd_hmac_sha256_t *hmac_sha256 = MNULL;
+ subcmd_sha256_t *sha256 = MNULL;
+ subcmd_rijndael_t *rijndael = MNULL;
+ subcmd_rc4_t *rc4 = MNULL;
+ subcmd_md5_t *md5 = MNULL;
+ subcmd_mrvl_f_t *mrvl_f = MNULL;
+ subcmd_sha256_kdf_t *sha256_kdf = MNULL;
+ t_u8 *ptlv = MNULL;
+ t_u8 tlv_bitmap = 0;
+ t_u32 i = 0;
+#endif
+ ENTER();
+
+ cmd->command = wlan_cpu_to_le16(HostCmd_CMD_CRYPTO);
+ cmd->size = S_DS_GEN + sizeof(HostCmd_DS_CRYPTO);
+ cry_cmd->action = wlan_cpu_to_le16(cmd_action);
+ cry_cmd->subCmdCode = cfg->sub_command;
+ switch (cfg->sub_command) {
+#if defined(DRV_EMBEDDED_AUTHENTICATOR) || defined(DRV_EMBEDDED_SUPPLICANT)
+ case HostCmd_CMD_CRYPTO_SUBCMD_PRF_HMAC_SHA1:
+ tlv_bitmap = BIT_TLV_TYPE_CRYPTO_KEY |
+ BIT_TLV_TYPE_CRYPTO_KEY_PREFIX |
+ BIT_TLV_TYPE_CRYPTO_KEY_DATA_BLK;
+ /* set subcmd start */
+ prf_hmac_sha1 = (subcmd_prf_hmac_sha1_t *)cry_cmd->subCmd;
+ prf_hmac_sha1->output_len = cfg->output_len;
+ /* set tlv start */
+ ptlv = prf_hmac_sha1->tlv;
+ cmd->size += sizeof(subcmd_prf_hmac_sha1_t);
+ break;
+ case HostCmd_CMD_CRYPTO_SUBCMD_HMAC_SHA1:
+ tlv_bitmap = BIT_TLV_TYPE_CRYPTO_KEY |
+ BIT_TLV_TYPE_CRYPTO_KEY_DATA_BLK;
+ /* set subcmd start */
+ hmac_sha1 = (subcmd_hmac_sha1_t *)cry_cmd->subCmd;
+ hmac_sha1->output_len = cfg->output_len;
+ hmac_sha1->data_blks_nr = cfg->data_blks_nr;
+ /* set tlv start */
+ ptlv = hmac_sha1->tlv;
+ cmd->size += sizeof(subcmd_hmac_sha1_t);
+ break;
+ case HostCmd_CMD_CRYPTO_SUBCMD_HMAC_SHA256:
+ tlv_bitmap = BIT_TLV_TYPE_CRYPTO_KEY |
+ BIT_TLV_TYPE_CRYPTO_KEY_DATA_BLK;
+ /* set subcmd start */
+ hmac_sha256 = (subcmd_hmac_sha256_t *)cry_cmd->subCmd;
+ hmac_sha256->output_len = cfg->output_len;
+ hmac_sha256->data_blks_nr = cfg->data_blks_nr;
+ /* set tlv start */
+ ptlv = hmac_sha256->tlv;
+ cmd->size += sizeof(subcmd_hmac_sha256_t);
+ break;
+ case HostCmd_CMD_CRYPTO_SUBCMD_SHA256:
+ tlv_bitmap = BIT_TLV_TYPE_CRYPTO_KEY_DATA_BLK;
+ /* set subcmd start */
+ sha256 = (subcmd_sha256_t *)cry_cmd->subCmd;
+ sha256->output_len = cfg->output_len;
+ sha256->data_blks_nr = cfg->data_blks_nr;
+ /* set tlv start */
+ ptlv = sha256->tlv;
+ cmd->size += sizeof(subcmd_sha256_t);
+ break;
+ case HostCmd_CMD_CRYPTO_SUBCMD_RIJNDAEL:
+ tlv_bitmap = BIT_TLV_TYPE_CRYPTO_KEY |
+ BIT_TLV_TYPE_CRYPTO_KEY_DATA_BLK;
+ /* set subcmd start */
+ rijndael = (subcmd_rijndael_t *)cry_cmd->subCmd;
+ rijndael->sub_action_code = cfg->sub_action_code;
+ rijndael->output_len = cfg->output_len;
+ /* set tlv start */
+ ptlv = rijndael->tlv;
+ cmd->size += sizeof(subcmd_rijndael_t);
+ break;
+ case HostCmd_CMD_CRYPTO_SUBCMD_RC4:
+ tlv_bitmap = BIT_TLV_TYPE_CRYPTO_KEY |
+ BIT_TLV_TYPE_CRYPTO_KEY_IV |
+ BIT_TLV_TYPE_CRYPTO_KEY_DATA_BLK;
+ /* set subcmd start */
+ rc4 = (subcmd_rc4_t *)cry_cmd->subCmd;
+ rc4->skip_bytes = cfg->skip_bytes;
+ rc4->output_len = cfg->output_len;
+ /* set tlv start */
+ ptlv = rc4->tlv;
+ cmd->size += sizeof(subcmd_rc4_t);
+ break;
+ case HostCmd_CMD_CRYPTO_SUBCMD_MD5:
+ tlv_bitmap = BIT_TLV_TYPE_CRYPTO_KEY |
+ BIT_TLV_TYPE_CRYPTO_KEY_DATA_BLK;
+ /* set subcmd start */
+ md5 = (subcmd_md5_t *)cry_cmd->subCmd;
+ md5->output_len = cfg->output_len;
+ /* set tlv start */
+ ptlv = md5->tlv;
+ cmd->size += sizeof(subcmd_md5_t);
+ break;
+ case HostCmd_CMD_CRYPTO_SUBCMD_MRVL_F:
+ tlv_bitmap = BIT_TLV_TYPE_CRYPTO_KEY |
+ BIT_TLV_TYPE_CRYPTO_KEY_DATA_BLK;
+ /* set subcmd start */
+ mrvl_f = (subcmd_mrvl_f_t *)cry_cmd->subCmd;
+ mrvl_f->iterations = cfg->iteration;
+ mrvl_f->count = cfg->count;
+ mrvl_f->output_len = cfg->output_len;
+ /* set tlv start */
+ ptlv = mrvl_f->tlv;
+ cmd->size += sizeof(subcmd_mrvl_f_t);
+ break;
+ case HostCmd_CMD_CRYPTO_SUBCMD_SHA256_KDF:
+ tlv_bitmap = BIT_TLV_TYPE_CRYPTO_KEY |
+ BIT_TLV_TYPE_CRYPTO_KEY_PREFIX |
+ BIT_TLV_TYPE_CRYPTO_KEY_DATA_BLK;
+ /* set subcmd start */
+ sha256_kdf = (subcmd_sha256_kdf_t *)cry_cmd->subCmd;
+ sha256_kdf->output_len = cfg->output_len;
+ /* set tlv start */
+ ptlv = sha256_kdf->tlv;
+ cmd->size += sizeof(subcmd_sha256_kdf_t);
+ break;
+#endif
+ default:
+ break;
+ }
+#if defined(DRV_EMBEDDED_AUTHENTICATOR) || defined(DRV_EMBEDDED_SUPPLICANT)
+ /* add tlv */
+ if (tlv_bitmap & BIT_TLV_TYPE_CRYPTO_KEY) {
+ ((MrvlIEParamSet_t *)ptlv)->Type =
+ wlan_cpu_to_le16(TLV_TYPE_CRYPTO_KEY);
+ ((MrvlIEParamSet_t *)ptlv)->Length =
+ wlan_cpu_to_le16(cfg->key_len);
+ memcpy_ext(pmpriv->adapter,
+ (t_u8 *)ptlv + sizeof(MrvlIEParamSet_t), cfg->key,
+ cfg->key_len, cfg->key_len);
+ cmd->size += cfg->key_len + sizeof(MrvlIEParamSet_t);
+ ptlv += cfg->key_len + sizeof(MrvlIEParamSet_t);
+ }
+
+ if (tlv_bitmap & BIT_TLV_TYPE_CRYPTO_KEY_PREFIX) {
+ ((MrvlIEParamSet_t *)ptlv)->Type =
+ wlan_cpu_to_le16(TLV_TYPE_CRYPTO_KEY_PREFIX);
+ ((MrvlIEParamSet_t *)ptlv)->Length =
+ wlan_cpu_to_le16(cfg->key_prefix_len);
+ memcpy_ext(pmpriv->adapter, ptlv + sizeof(MrvlIEParamSet_t),
+ cfg->key_prefix, cfg->key_prefix_len,
+ cfg->key_prefix_len);
+ cmd->size += cfg->key_prefix_len + sizeof(MrvlIEParamSet_t);
+ ptlv += cfg->key_prefix_len + sizeof(MrvlIEParamSet_t);
+ }
+
+ if (tlv_bitmap & BIT_TLV_TYPE_CRYPTO_KEY_IV) {
+ ((MrvlIEParamSet_t *)ptlv)->Type =
+ wlan_cpu_to_le16(TLV_TYPE_CRYPTO_KEY_IV);
+ ((MrvlIEParamSet_t *)ptlv)->Length =
+ wlan_cpu_to_le16(cfg->key_iv_len);
+ memcpy_ext(pmpriv->adapter, ptlv + sizeof(MrvlIEParamSet_t),
+ cfg->key_iv, cfg->key_iv_len, cfg->key_iv_len);
+ cmd->size += cfg->key_iv_len + sizeof(MrvlIEParamSet_t);
+ ptlv += cfg->key_iv_len + sizeof(MrvlIEParamSet_t);
+ }
+
+ if (tlv_bitmap & BIT_TLV_TYPE_CRYPTO_KEY_DATA_BLK) {
+ t_u16 data_blk_len = 0;
+ t_u8 *pdata_blk = MNULL;
+ for (i = 0; i < cfg->data_blks_nr; i++) {
+ data_blk_len = *(cfg->key_data_blk_len + i);
+ pdata_blk = *(cfg->key_data_blk + i);
+ ((MrvlIEParamSet_t *)ptlv)->Type =
+ wlan_cpu_to_le16(TLV_TYPE_CRYPTO_KEY_DATA_BLK);
+ ((MrvlIEParamSet_t *)ptlv)->Length =
+ wlan_cpu_to_le16(data_blk_len);
+ memcpy_ext(pmpriv->adapter,
+ ptlv + sizeof(MrvlIEParamSet_t), pdata_blk,
+ data_blk_len, data_blk_len);
+ cmd->size += data_blk_len + sizeof(MrvlIEParamSet_t);
+ ptlv += data_blk_len + sizeof(MrvlIEParamSet_t);
+ }
+ }
+#endif
+ HEXDUMP("HostCmd_DS_COMMAND wlan_cmd_crypto", cmd, cmd->size);
+
+ cmd->size = wlan_cpu_to_le16(cmd->size);
+ LEAVE();
+ return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ * @brief This function handles the command response of crypto command
+ *
+ * @param pmpriv A pointer to mlan_private structure
+ * @param resp A pointer to HostCmd_DS_COMMAND
+ * @param pioctl_buf A pointer to mlan_ioctl_req structure
+ *
+ * @return MLAN_STATUS_SUCCESS
+ */
+mlan_status wlan_ret_crypto(pmlan_private pmpriv, HostCmd_DS_COMMAND *resp,
+ mlan_ioctl_req *pioctl_buf)
+{
+ HostCmd_DS_CRYPTO *crypto_cmd = &resp->params.crypto_cmd;
+#if defined(DRV_EMBEDDED_AUTHENTICATOR) || defined(DRV_EMBEDDED_SUPPLICANT)
+ mlan_adapter *pmadapter = pmpriv->adapter;
+ mlan_callbacks *pcb = (pmlan_callbacks)&pmadapter->callbacks;
+ mlan_ds_sup_cfg *cfg = (mlan_ds_sup_cfg *)pioctl_buf->pbuf;
+#endif
+
+ ENTER();
+#if defined(DRV_EMBEDDED_AUTHENTICATOR) || defined(DRV_EMBEDDED_SUPPLICANT)
+ if (!cfg) {
+ PRINTM(MERROR, "wlan_ret_crypto cfg is null \n");
+ goto done;
+ }
+ if (resp->result == HostCmd_RESULT_OK) {
+ /* copy the result */
+ memcpy_ext(pmpriv->adapter, cfg->output,
+ (t_u8 *)crypto_cmd + sizeof(HostCmd_DS_CRYPTO) +
+ sizeof(cfg->output_len),
+ cfg->output_len, cfg->output_len);
+ }
+
+ /* Prevent the ioctl from completing when the cmd is freed */
+ if (cfg->call_back) {
+ pmadapter->curr_cmd->pioctl_buf = MNULL;
+ /* trigger wait q */
+ pcb->moal_notify_hostcmd_complete(pmadapter->pmoal_handle,
+ pmpriv->bss_index);
+ }
+#endif
+done:
+ LEAVE();
+ return MLAN_STATUS_SUCCESS;
+}
+#endif
+
+/**
+ * @brief This function prepares command of mac_address.
+ *
+ * @param pmpriv A pointer to mlan_private structure
+ * @param cmd A pointer to HostCmd_DS_COMMAND structure
+ * @param cmd_action The action: GET or SET
+ *
+ * @return MLAN_STATUS_SUCCESS
+ */
+mlan_status wlan_cmd_802_11_mac_address(pmlan_private pmpriv,
+ HostCmd_DS_COMMAND *cmd,
+ t_u16 cmd_action)
+{
+ ENTER();
+ cmd->command = wlan_cpu_to_le16(HostCmd_CMD_802_11_MAC_ADDRESS);
+ cmd->size = wlan_cpu_to_le16(sizeof(HostCmd_DS_802_11_MAC_ADDRESS) +
+ S_DS_GEN);
+ cmd->result = 0;
+
+ cmd->params.mac_addr.action = wlan_cpu_to_le16(cmd_action);
+
+ if (cmd_action == HostCmd_ACT_GEN_SET) {
+ memcpy_ext(pmpriv->adapter, cmd->params.mac_addr.mac_addr,
+ pmpriv->curr_addr, MLAN_MAC_ADDR_LENGTH,
+ MLAN_MAC_ADDR_LENGTH);
+ /* HEXDUMP("SET_CMD: MAC ADDRESS-", priv->CurrentAddr, 6); */
+ }
+ LEAVE();
+ return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ * @brief This function handles the command response of mac_address
+ *
+ * @param pmpriv A pointer to mlan_private structure
+ * @param resp A pointer to HostCmd_DS_COMMAND
+ * @param pioctl_buf A pointer to mlan_ioctl_req structure
+ *
+ * @return MLAN_STATUS_SUCCESS
+ */
+mlan_status wlan_ret_802_11_mac_address(pmlan_private pmpriv,
+ HostCmd_DS_COMMAND *resp,
+ mlan_ioctl_req *pioctl_buf)
+{
+ HostCmd_DS_802_11_MAC_ADDRESS *pmac_addr = &resp->params.mac_addr;
+ mlan_ds_bss *bss = MNULL;
+
+ ENTER();
+
+ memcpy_ext(pmpriv->adapter, pmpriv->curr_addr, pmac_addr->mac_addr,
+ MLAN_MAC_ADDR_LENGTH, MLAN_MAC_ADDR_LENGTH);
+
+ PRINTM(MINFO, "MAC address: " MACSTR "\n", MAC2STR(pmpriv->curr_addr));
+ if (pioctl_buf) {
+ bss = (mlan_ds_bss *)pioctl_buf->pbuf;
+ memcpy_ext(pmpriv->adapter, &bss->param.mac_addr,
+ pmpriv->curr_addr, MLAN_MAC_ADDR_LENGTH,
+ MLAN_MAC_ADDR_LENGTH);
+ pioctl_buf->data_read_written =
+ MLAN_MAC_ADDR_LENGTH + MLAN_SUB_COMMAND_SIZE;
+ }
+ LEAVE();
+ return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ * @brief This function prepares command of Rx abort cfg
+ *
+ * @param pmpriv A pointer to mlan_private structure
+ * @param cmd A pointer to HostCmd_DS_COMMAND structure
+ * @param cmd_action the action: GET or SET
+ * @param pdata_buf A pointer to data buffer
+ * @return MLAN_STATUS_SUCCESS
+ */
+mlan_status wlan_cmd_rxabortcfg(pmlan_private pmpriv, HostCmd_DS_COMMAND *cmd,
+ t_u16 cmd_action, t_void *pdata_buf)
+{
+ HostCmd_DS_CMD_RX_ABORT_CFG *cfg_cmd =
+ (HostCmd_DS_CMD_RX_ABORT_CFG *)&cmd->params.rx_abort_cfg;
+ mlan_ds_misc_rx_abort_cfg *cfg = (mlan_ds_misc_rx_abort_cfg *)pdata_buf;
+
+ ENTER();
+
+ cmd->command = wlan_cpu_to_le16(HostCmd_CMD_RX_ABORT_CFG);
+ cmd->size = wlan_cpu_to_le16(sizeof(HostCmd_DS_CMD_RX_ABORT_CFG) +
+ S_DS_GEN);
+ cfg_cmd->action = wlan_cpu_to_le16(cmd_action);
+
+ if (cmd_action == HostCmd_ACT_GEN_SET) {
+ cfg_cmd->enable = (t_u8)cfg->enable;
+ cfg_cmd->rssi_threshold = (t_s8)cfg->rssi_threshold;
+ }
+
+ LEAVE();
+ return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ * @brief This function handles the command response of Rx Abort Cfg
+ *
+ * @param pmpriv A pointer to mlan_private structure
+ * @param resp A pointer to HostCmd_DS_COMMAND
+ * @param pioctl_buf A pointer to mlan_ioctl_req structure
+ *
+ * @return MLAN_STATUS_SUCCESS
+ */
+mlan_status wlan_ret_rxabortcfg(pmlan_private pmpriv, HostCmd_DS_COMMAND *resp,
+ mlan_ioctl_req *pioctl_buf)
+{
+ HostCmd_DS_CMD_RX_ABORT_CFG *cfg_cmd =
+ (HostCmd_DS_CMD_RX_ABORT_CFG *)&resp->params.rx_abort_cfg;
+ mlan_ds_misc_cfg *misc_cfg = MNULL;
+
+ ENTER();
+
+ if (pioctl_buf) {
+ misc_cfg = (mlan_ds_misc_cfg *)pioctl_buf->pbuf;
+ misc_cfg->param.rx_abort_cfg.enable = (t_u8)cfg_cmd->enable;
+ misc_cfg->param.rx_abort_cfg.rssi_threshold =
+ (t_s8)cfg_cmd->rssi_threshold;
+ }
+ LEAVE();
+ return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ * @brief This function prepares command of Rx abort cfg ext
+ *
+ * @param pmpriv A pointer to mlan_private structure
+ * @param cmd A pointer to HostCmd_DS_COMMAND structure
+ * @param cmd_action the action: GET or SET
+ * @param pdata_buf A pointer to data buffer
+ * @return MLAN_STATUS_SUCCESS
+ */
+mlan_status wlan_cmd_rxabortcfg_ext(pmlan_private pmpriv,
+ HostCmd_DS_COMMAND *cmd, t_u16 cmd_action,
+ t_void *pdata_buf)
+{
+ HostCmd_DS_CMD_RX_ABORT_CFG_EXT *cfg_cmd =
+ (HostCmd_DS_CMD_RX_ABORT_CFG_EXT *)&cmd->params.rx_abort_cfg_ext;
+ mlan_ds_misc_rx_abort_cfg_ext *cfg =
+ (mlan_ds_misc_rx_abort_cfg_ext *)pdata_buf;
+
+ ENTER();
+
+ cmd->command = wlan_cpu_to_le16(HostCmd_CMD_RX_ABORT_CFG_EXT);
+ cmd->size = wlan_cpu_to_le16(sizeof(HostCmd_DS_CMD_RX_ABORT_CFG_EXT) +
+ S_DS_GEN);
+ cfg_cmd->action = wlan_cpu_to_le16(cmd_action);
+
+ if (cmd_action == HostCmd_ACT_GEN_SET) {
+ cfg_cmd->enable = (t_u8)cfg->enable;
+ cfg_cmd->rssi_margin = (t_s8)cfg->rssi_margin;
+ cfg_cmd->ceil_rssi_threshold = (t_s8)cfg->ceil_rssi_threshold;
+ }
+
+ LEAVE();
+ return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ * @brief This function handles the command response of Rx Abort Cfg ext
+ *
+ * @param pmpriv A pointer to mlan_private structure
+ * @param resp A pointer to HostCmd_DS_COMMAND
+ * @param pioctl_buf A pointer to mlan_ioctl_req structure
+ *
+ * @return MLAN_STATUS_SUCCESS
+ */
+mlan_status wlan_ret_rxabortcfg_ext(pmlan_private pmpriv,
+ HostCmd_DS_COMMAND *resp,
+ mlan_ioctl_req *pioctl_buf)
+{
+ HostCmd_DS_CMD_RX_ABORT_CFG_EXT *cfg_cmd =
+ (HostCmd_DS_CMD_RX_ABORT_CFG_EXT *)&resp->params
+ .rx_abort_cfg_ext;
+ mlan_ds_misc_cfg *misc_cfg = MNULL;
+
+ ENTER();
+
+ if (pioctl_buf) {
+ misc_cfg = (mlan_ds_misc_cfg *)pioctl_buf->pbuf;
+ misc_cfg->param.rx_abort_cfg_ext.enable = cfg_cmd->enable;
+ misc_cfg->param.rx_abort_cfg_ext.rssi_margin =
+ cfg_cmd->rssi_margin;
+ misc_cfg->param.rx_abort_cfg_ext.ceil_rssi_threshold =
+ cfg_cmd->ceil_rssi_threshold;
+ }
+ LEAVE();
+ return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ * @brief This function prepares command of Dot11mc unassoc ftm cfg
+ *
+ * @param pmpriv A pointer to mlan_private structure
+ * @param cmd A pointer to HostCmd_DS_COMMAND structure
+ * @param cmd_action the action: GET or SET
+ * @param pdata_buf A pointer to data buffer
+ * @return MLAN_STATUS_SUCCESS
+ */
+mlan_status wlan_cmd_dot11mc_unassoc_ftm_cfg(pmlan_private pmpriv,
+ HostCmd_DS_COMMAND *cmd,
+ t_u16 cmd_action,
+ t_void *pdata_buf)
+{
+ HostCmd_DS_CMD_DOT11MC_UNASSOC_FTM_CFG *cfg_cmd =
+ (HostCmd_DS_CMD_DOT11MC_UNASSOC_FTM_CFG *)&cmd->params
+ .dot11mc_unassoc_ftm_cfg;
+ mlan_ds_misc_dot11mc_unassoc_ftm_cfg *cfg =
+ (mlan_ds_misc_dot11mc_unassoc_ftm_cfg *)pdata_buf;
+
+ ENTER();
+
+ cmd->command = wlan_cpu_to_le16(HostCmd_CMD_DOT11MC_UNASSOC_FTM_CFG);
+ cmd->size = wlan_cpu_to_le16(
+ sizeof(HostCmd_DS_CMD_DOT11MC_UNASSOC_FTM_CFG) + S_DS_GEN);
+ cfg_cmd->action = wlan_cpu_to_le16(cmd_action);
+
+ if (cmd_action == HostCmd_ACT_GEN_SET) {
+ cfg_cmd->state = wlan_cpu_to_le16(cfg->state);
+ }
+
+ LEAVE();
+ return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ * @brief This function handles the command response of Dot11mc unassoc ftm cfg
+ *
+ * @param pmpriv A pointer to mlan_private structure
+ * @param resp A pointer to HostCmd_DS_COMMAND
+ * @param pioctl_buf A pointer to mlan_ioctl_req structure
+ *
+ * @return MLAN_STATUS_SUCCESS
+ */
+mlan_status wlan_ret_dot11mc_unassoc_ftm_cfg(pmlan_private pmpriv,
+ HostCmd_DS_COMMAND *resp,
+ mlan_ioctl_req *pioctl_buf)
+{
+ HostCmd_DS_CMD_DOT11MC_UNASSOC_FTM_CFG *cfg_cmd =
+ (HostCmd_DS_CMD_DOT11MC_UNASSOC_FTM_CFG *)&resp->params
+ .dot11mc_unassoc_ftm_cfg;
+ mlan_ds_misc_cfg *misc_cfg = MNULL;
+
+ ENTER();
+
+ if (pioctl_buf) {
+ misc_cfg = (mlan_ds_misc_cfg *)pioctl_buf->pbuf;
+ misc_cfg->param.dot11mc_unassoc_ftm_cfg.state =
+ wlan_le16_to_cpu(cfg_cmd->state);
+ }
+ LEAVE();
+ return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ * @brief This function prepares command of Tx ampdu prot mode
+ *
+ * @param pmpriv A pointer to mlan_private structure
+ * @param cmd A pointer to HostCmd_DS_COMMAND structure
+ * @param cmd_action the action: GET or SET
+ * @param pdata_buf A pointer to data buffer
+ * @return MLAN_STATUS_SUCCESS
+ */
+mlan_status wlan_cmd_tx_ampdu_prot_mode(pmlan_private pmpriv,
+ HostCmd_DS_COMMAND *cmd,
+ t_u16 cmd_action, t_void *pdata_buf)
+{
+ HostCmd_DS_CMD_TX_AMPDU_PROT_MODE *cfg_cmd =
+ (HostCmd_DS_CMD_TX_AMPDU_PROT_MODE *)&cmd->params
+ .tx_ampdu_prot_mode;
+ mlan_ds_misc_tx_ampdu_prot_mode *cfg =
+ (mlan_ds_misc_tx_ampdu_prot_mode *)pdata_buf;
+
+ ENTER();
+
+ cmd->command = wlan_cpu_to_le16(HostCmd_CMD_TX_AMPDU_PROT_MODE);
+ cmd->size = wlan_cpu_to_le16(sizeof(HostCmd_DS_CMD_TX_AMPDU_PROT_MODE) +
+ S_DS_GEN);
+ cfg_cmd->action = wlan_cpu_to_le16(cmd_action);
+
+ if (cmd_action == HostCmd_ACT_GEN_SET) {
+ cfg_cmd->mode = wlan_cpu_to_le16(cfg->mode);
+ }
+
+ LEAVE();
+ return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ * @brief This function handles the command response of Tx ampdu prot mode
+ *
+ * @param pmpriv A pointer to mlan_private structure
+ * @param resp A pointer to HostCmd_DS_COMMAND
+ * @param pioctl_buf A pointer to mlan_ioctl_req structure
+ *
+ * @return MLAN_STATUS_SUCCESS
+ */
+mlan_status wlan_ret_tx_ampdu_prot_mode(pmlan_private pmpriv,
+ HostCmd_DS_COMMAND *resp,
+ mlan_ioctl_req *pioctl_buf)
+{
+ HostCmd_DS_CMD_TX_AMPDU_PROT_MODE *cfg_cmd =
+ (HostCmd_DS_CMD_TX_AMPDU_PROT_MODE *)&resp->params
+ .tx_ampdu_prot_mode;
+ mlan_ds_misc_cfg *misc_cfg = MNULL;
+
+ ENTER();
+
+ if (pioctl_buf) {
+ misc_cfg = (mlan_ds_misc_cfg *)pioctl_buf->pbuf;
+ misc_cfg->param.tx_ampdu_prot_mode.mode =
+ wlan_le16_to_cpu(cfg_cmd->mode);
+ }
+ LEAVE();
+ return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ * @brief This function prepares command of Rate Adapt cfg
+ *
+ * @param pmpriv A pointer to mlan_private structure
+ * @param cmd A pointer to HostCmd_DS_COMMAND structure
+ * @param cmd_action the action: GET or SET
+ * @param pdata_buf A pointer to data buffer
+ * @return MLAN_STATUS_SUCCESS
+ */
+mlan_status wlan_cmd_rate_adapt_cfg(pmlan_private pmpriv,
+ HostCmd_DS_COMMAND *cmd, t_u16 cmd_action,
+ t_void *pdata_buf)
+{
+ HostCmd_DS_CMD_RATE_ADAPT_CFG *cfg_cmd =
+ (HostCmd_DS_CMD_RATE_ADAPT_CFG *)&cmd->params.rate_adapt_cfg;
+ mlan_ds_misc_rate_adapt_cfg *cfg =
+ (mlan_ds_misc_rate_adapt_cfg *)pdata_buf;
+
+ ENTER();
+
+ cmd->command = wlan_cpu_to_le16(HostCmd_CMD_RATE_ADAPT_CFG);
+ cmd->size = wlan_cpu_to_le16(sizeof(HostCmd_DS_CMD_RATE_ADAPT_CFG) +
+ S_DS_GEN);
+ cfg_cmd->action = wlan_cpu_to_le16(cmd_action);
+
+ if (cmd_action == HostCmd_ACT_GEN_SET) {
+ cfg_cmd->sr_rateadapt = (t_u8)cfg->sr_rateadapt;
+ cfg_cmd->ra_low_thresh = (t_u8)cfg->ra_low_thresh;
+ cfg_cmd->ra_high_thresh = (t_u8)cfg->ra_high_thresh;
+ cfg_cmd->ra_interval = wlan_cpu_to_le16(cfg->ra_interval);
+ }
+
+ LEAVE();
+ return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ * @brief This function handles the command response of Rate Adapt Cfg
+ *
+ * @param pmpriv A pointer to mlan_private structure
+ * @param resp A pointer to HostCmd_DS_COMMAND
+ * @param pioctl_buf A pointer to mlan_ioctl_req structure
+ *
+ * @return MLAN_STATUS_SUCCESS
+ */
+mlan_status wlan_ret_rate_adapt_cfg(pmlan_private pmpriv,
+ HostCmd_DS_COMMAND *resp,
+ mlan_ioctl_req *pioctl_buf)
+{
+ HostCmd_DS_CMD_RATE_ADAPT_CFG *cfg_cmd =
+ (HostCmd_DS_CMD_RATE_ADAPT_CFG *)&resp->params.rate_adapt_cfg;
+ mlan_ds_misc_cfg *misc_cfg = MNULL;
+
+ ENTER();
+
+ if (pioctl_buf) {
+ misc_cfg = (mlan_ds_misc_cfg *)pioctl_buf->pbuf;
+ misc_cfg->param.rate_adapt_cfg.sr_rateadapt =
+ (t_u8)cfg_cmd->sr_rateadapt;
+ misc_cfg->param.rate_adapt_cfg.ra_low_thresh =
+ (t_u8)cfg_cmd->ra_low_thresh;
+ misc_cfg->param.rate_adapt_cfg.ra_high_thresh =
+ (t_u8)cfg_cmd->ra_high_thresh;
+ misc_cfg->param.rate_adapt_cfg.ra_interval =
+ wlan_le16_to_cpu(cfg_cmd->ra_interval);
+ }
+ LEAVE();
+ return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ * @brief This function prepares command of CCK Desense cfg
+ *
+ * @param pmpriv A pointer to mlan_private structure
+ * @param cmd A pointer to HostCmd_DS_COMMAND structure
+ * @param cmd_action the action: GET or SET
+ * @param pdata_buf A pointer to data buffer
+ * @return MLAN_STATUS_SUCCESS
+ */
+mlan_status wlan_cmd_cck_desense_cfg(pmlan_private pmpriv,
+ HostCmd_DS_COMMAND *cmd, t_u16 cmd_action,
+ t_void *pdata_buf)
+{
+ HostCmd_DS_CMD_CCK_DESENSE_CFG *cfg_cmd =
+ (HostCmd_DS_CMD_CCK_DESENSE_CFG *)&cmd->params.cck_desense_cfg;
+ mlan_ds_misc_cck_desense_cfg *cfg =
+ (mlan_ds_misc_cck_desense_cfg *)pdata_buf;
+
+ ENTER();
+
+ cmd->command = wlan_cpu_to_le16(HostCmd_CMD_CCK_DESENSE_CFG);
+ cmd->size = wlan_cpu_to_le16(sizeof(HostCmd_DS_CMD_CCK_DESENSE_CFG) +
+ S_DS_GEN);
+ cfg_cmd->action = wlan_cpu_to_le16(cmd_action);
+
+ if (cmd_action == HostCmd_ACT_GEN_SET) {
+ cfg_cmd->mode = wlan_cpu_to_le16(cfg->mode);
+ cfg_cmd->margin = (t_s8)cfg->margin;
+ cfg_cmd->ceil_thresh = (t_s8)cfg->ceil_thresh;
+ cfg_cmd->num_on_intervals = (t_u8)cfg->num_on_intervals;
+ cfg_cmd->num_off_intervals = (t_u8)cfg->num_off_intervals;
+ }
+
+ LEAVE();
+ return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ * @brief This function handles the command response of CCK Desense Cfg
+ *
+ * @param pmpriv A pointer to mlan_private structure
+ * @param resp A pointer to HostCmd_DS_COMMAND
+ * @param pioctl_buf A pointer to mlan_ioctl_req structure
+ *
+ * @return MLAN_STATUS_SUCCESS
+ */
+mlan_status wlan_ret_cck_desense_cfg(pmlan_private pmpriv,
+ HostCmd_DS_COMMAND *resp,
+ mlan_ioctl_req *pioctl_buf)
+{
+ HostCmd_DS_CMD_CCK_DESENSE_CFG *cfg_cmd =
+ (HostCmd_DS_CMD_CCK_DESENSE_CFG *)&resp->params.cck_desense_cfg;
+ mlan_ds_misc_cfg *misc_cfg = MNULL;
+
+ ENTER();
+
+ if (pioctl_buf) {
+ misc_cfg = (mlan_ds_misc_cfg *)pioctl_buf->pbuf;
+ misc_cfg->param.cck_desense_cfg.mode =
+ wlan_le16_to_cpu(cfg_cmd->mode);
+ misc_cfg->param.cck_desense_cfg.margin = (t_s8)cfg_cmd->margin;
+ misc_cfg->param.cck_desense_cfg.ceil_thresh =
+ (t_s8)cfg_cmd->ceil_thresh;
+ misc_cfg->param.cck_desense_cfg.num_on_intervals =
+ (t_u8)cfg_cmd->num_on_intervals;
+ misc_cfg->param.cck_desense_cfg.num_off_intervals =
+ (t_u8)cfg_cmd->num_off_intervals;
+ }
+ LEAVE();
+ return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ * @brief This function sends dynamic bandwidth command to firmware.
+ *
+ * @param pmpriv A pointer to mlan_private structure
+ * @param cmd Hostcmd ID
+ * @param cmd_action Command action
+ * @param pdata_buf A void pointer to information buffer
+ * @return N/A
+ */
+mlan_status wlan_cmd_config_dyn_bw(pmlan_private pmpriv,
+ HostCmd_DS_COMMAND *cmd, t_u16 cmd_action,
+ t_void *pdata_buf)
+{
+ HostCmd_DS_DYN_BW *dyn_bw_cmd = &cmd->params.dyn_bw;
+
+ ENTER();
+
+ cmd->command = wlan_cpu_to_le16(HostCmd_CMD_DYN_BW);
+ cmd->size = S_DS_GEN + sizeof(HostCmd_DS_DYN_BW);
+ dyn_bw_cmd->action = wlan_cpu_to_le16(cmd_action);
+ dyn_bw_cmd->dyn_bw = wlan_cpu_to_le16(*(t_u16 *)pdata_buf);
+ cmd->size = wlan_cpu_to_le16(cmd->size);
+
+ LEAVE();
+ return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ * @brief This function handles the command response of dyn_bw
+ *
+ * @param pmpriv A pointer to mlan_private structure
+ * @param resp A pointer to HostCmd_DS_COMMAND
+ * @param pioctl_buf A pointer to mlan_ioctl_req structure
+ *
+ * @return MLAN_STATUS_SUCCESS
+ */
+mlan_status wlan_ret_dyn_bw(pmlan_private pmpriv, HostCmd_DS_COMMAND *resp,
+ mlan_ioctl_req *pioctl_buf)
+{
+ mlan_ds_misc_cfg *cfg = MNULL;
+ HostCmd_DS_DYN_BW *dyn_bw = &resp->params.dyn_bw;
+
+ ENTER();
+ if (pioctl_buf &&
+ (wlan_le16_to_cpu(dyn_bw->action) == HostCmd_ACT_GEN_GET)) {
+ cfg = (mlan_ds_misc_cfg *)pioctl_buf->pbuf;
+ cfg->param.dyn_bw = wlan_le16_to_cpu(dyn_bw->dyn_bw);
+ PRINTM(MCMND, "Get dynamic bandwidth 0x%x\n",
+ cfg->param.dyn_bw);
+ }
+ LEAVE();
+ return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ * @brief This function prepares command of CHAN_TRPC_CONFIG
+ *
+ * @param pmpriv A pointer to mlan_private structure
+ * @param cmd A pointer to HostCmd_DS_COMMAND structure
+ * @param cmd_action the action: GET or SET
+ * @param pdata_buf A pointer to data buffer
+ * @return MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ */
+mlan_status wlan_cmd_get_chan_trpc_config(pmlan_private pmpriv,
+ HostCmd_DS_COMMAND *cmd,
+ t_u16 cmd_action, t_void *pdata_buf)
+{
+ HostCmd_DS_CHANNEL_TRPC_CONFIG *trpc_cfg = &cmd->params.ch_trpc_config;
+ mlan_ds_misc_chan_trpc_cfg *cfg =
+ (mlan_ds_misc_chan_trpc_cfg *)pdata_buf;
+
+ ENTER();
+
+ cmd->command = wlan_cpu_to_le16(HostCmd_CHANNEL_TRPC_CONFIG);
+ trpc_cfg->action = wlan_cpu_to_le16(cmd_action);
+ cmd->size = wlan_cpu_to_le16(sizeof(HostCmd_DS_CHANNEL_TRPC_CONFIG) +
+ S_DS_GEN);
+ trpc_cfg->sub_band = wlan_cpu_to_le16(cfg->sub_band);
+ LEAVE();
+ return MLAN_STATUS_SUCCESS;
+}
+/**
+ * @brief This function prepares command of LOW_POWER_MODE_CFG
+ *
+ * @param pmpriv A pointer to mlan_private structure
+ * @param cmd A pointer to HostCmd_DS_COMMAND structure
+ * @param cmd_action the action: GET or SET
+ * @param pdata_buf A pointer to data buffer
+ * @return MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ */
+mlan_status wlan_cmd_set_get_low_power_mode_cfg(pmlan_private pmpriv,
+ HostCmd_DS_COMMAND *cmd,
+ t_u16 cmd_action,
+ t_void *pdata_buf)
+{
+ HostCmd_DS_LOW_POWER_MODE_CFG *lpm_cfg = &cmd->params.lpm_cfg;
+ t_u16 lpm = *(t_u16 *)pdata_buf;
+
+ ENTER();
+
+ cmd->command = wlan_cpu_to_le16(HostCmd_CMD_LOW_POWER_MODE_CFG);
+ cmd->size = wlan_cpu_to_le16(sizeof(HostCmd_DS_LOW_POWER_MODE_CFG) +
+ S_DS_GEN);
+ lpm_cfg->action = wlan_cpu_to_le16(cmd_action);
+
+ if (cmd_action == HostCmd_ACT_GEN_SET)
+ lpm_cfg->lpm = wlan_cpu_to_le16(lpm);
+
+ LEAVE();
+ return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ * @brief This function handles the command response of low power mode
+ *
+ * @param pmpriv A pointer to mlan_private structure
+ * @param resp A pointer to HostCmd_DS_COMMAND
+ * @param pioctl_buf A pointer to command buffer
+ *
+ * @return MLAN_STATUS_SUCCESS
+
+ */
+mlan_status wlan_ret_set_get_low_power_mode_cfg(pmlan_private pmpriv,
+ HostCmd_DS_COMMAND *resp,
+ mlan_ioctl_req *pioctl_buf)
+{
+ mlan_ds_power_cfg *cfg = MNULL;
+ HostCmd_DS_LOW_POWER_MODE_CFG *lpm_cfg = &resp->params.lpm_cfg;
+
+ ENTER();
+
+ if (pioctl_buf &&
+ (wlan_le16_to_cpu(lpm_cfg->action) == HostCmd_ACT_GEN_GET)) {
+ cfg = (mlan_ds_power_cfg *)pioctl_buf->pbuf;
+ cfg->param.lpm = wlan_le16_to_cpu(lpm_cfg->lpm);
+ PRINTM(MCMND, "Get low power mode %d\n", cfg->param.lpm);
+ }
+
+ LEAVE();
+ return MLAN_STATUS_SUCCESS;
+}
+/**
+ * @brief This function handles the command response of
+ * packet aggregation
+ *
+ * @param pmpriv A pointer to mlan_private structure
+ * @param resp A pointer to HostCmd_DS_COMMAND
+ * @param pioctl_buf A pointer to command buffer
+ *
+ * @return MLAN_STATUS_SUCCESS
+ */
+mlan_status wlan_ret_get_chan_trpc_config(pmlan_private pmpriv,
+ HostCmd_DS_COMMAND *resp,
+ mlan_ioctl_req *pioctl_buf)
+{
+ mlan_ds_misc_cfg *misc = MNULL;
+ HostCmd_DS_CHANNEL_TRPC_CONFIG *trpc_cfg = &resp->params.ch_trpc_config;
+ mlan_ds_misc_chan_trpc_cfg *cfg = MNULL;
+ mlan_adapter *pmadapter = pmpriv->adapter;
+
+ ENTER();
+ if (pioctl_buf) {
+ misc = (mlan_ds_misc_cfg *)pioctl_buf->pbuf;
+ cfg = (mlan_ds_misc_chan_trpc_cfg *)&(misc->param.trpc_cfg);
+ cfg->sub_band = wlan_le16_to_cpu(trpc_cfg->sub_band);
+ cfg->length = wlan_le16_to_cpu(resp->size);
+ memcpy_ext(pmadapter, cfg->trpc_buf, (t_u8 *)resp, cfg->length,
+ sizeof(cfg->trpc_buf));
+ }
+ LEAVE();
+ return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ * @brief This function prepares command of RANGE_EXT
+ *
+ * @param pmpriv A pointer to mlan_private structure
+ * @param cmd A pointer to HostCmd_DS_COMMAND structure
+ * @param cmd_action the action: GET or SET
+ * @param pdata_buf A pointer to data buffer
+ * @return MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ */
+mlan_status wlan_cmd_range_ext(pmlan_private pmpriv, HostCmd_DS_COMMAND *cmd,
+ t_u16 cmd_action, t_void *pdata_buf)
+{
+ HostCmd_DS_RANGE_EXT *range_ext = &cmd->params.range_ext;
+ t_u8 mode = *(t_u8 *)pdata_buf;
+
+ ENTER();
+
+ cmd->command = wlan_cpu_to_le16(HostCmd_CMD_RANGE_EXT);
+ cmd->size = wlan_cpu_to_le16(sizeof(HostCmd_DS_RANGE_EXT) + S_DS_GEN);
+ range_ext->action = wlan_cpu_to_le16(cmd_action);
+
+ if (cmd_action == HostCmd_ACT_GEN_SET)
+ range_ext->mode = mode;
+
+ LEAVE();
+ return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ * @brief This function handles the command response of RANGE_EXT
+ *
+ * @param pmpriv A pointer to mlan_private structure
+ * @param resp A pointer to HostCmd_DS_COMMAND
+ * @param pioctl_buf A pointer to command buffer
+ *
+ * @return MLAN_STATUS_SUCCESS
+ */
+mlan_status wlan_ret_range_ext(pmlan_private pmpriv, HostCmd_DS_COMMAND *resp,
+ mlan_ioctl_req *pioctl_buf)
+{
+ mlan_ds_misc_cfg *misc_cfg = MNULL;
+ HostCmd_DS_RANGE_EXT *range_ext = &resp->params.range_ext;
+
+ ENTER();
+
+ if (pioctl_buf &&
+ (wlan_le16_to_cpu(range_ext->action) == HostCmd_ACT_GEN_GET)) {
+ misc_cfg = (mlan_ds_misc_cfg *)pioctl_buf->pbuf;
+ misc_cfg->param.range_ext_mode = range_ext->mode;
+ PRINTM(MCMND, "Get range ext mode %d\n",
+ misc_cfg->param.range_ext_mode);
+ }
+
+ LEAVE();
+ return MLAN_STATUS_SUCCESS;
+}
diff --git a/drivers/net/wireless/nxp/mxm_wifiex/wlan_src/mlan/mlan_decl.h b/drivers/net/wireless/nxp/mxm_wifiex/wlan_src/mlan/mlan_decl.h
new file mode 100644
index 000000000000..7d0b75cc3c54
--- /dev/null
+++ b/drivers/net/wireless/nxp/mxm_wifiex/wlan_src/mlan/mlan_decl.h
@@ -0,0 +1,1988 @@
+/** @file mlan_decl.h
+ *
+ * @brief This file declares the generic data structures and APIs.
+ *
+ *
+ * Copyright 2014-2020 NXP
+ *
+ * This software file (the File) is distributed by NXP
+ * under the terms of the GNU General Public License Version 2, June 1991
+ * (the License). You may use, redistribute and/or modify the 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 _MLAN_DECL_H_
+#define _MLAN_DECL_H_
+
+/** MLAN release version */
+#define MLAN_RELEASE_VERSION "215.p2"
+
+/** Re-define generic data types for MLAN/MOAL */
+/** Signed char (1-byte) */
+typedef signed char t_s8, *t_ps8;
+/** Unsigned char (1-byte) */
+typedef unsigned char t_u8, *t_pu8;
+/** Signed short (2-bytes) */
+typedef short t_s16, *t_ps16;
+/** Unsigned short (2-bytes) */
+typedef unsigned short t_u16, *t_pu16;
+/** Signed long (4-bytes) */
+typedef int t_s32, *t_ps32;
+/** Unsigned long (4-bytes) */
+typedef unsigned int t_u32, *t_pu32;
+/** Signed long long 8-bytes) */
+typedef long long t_s64, *t_ps64;
+/** Unsigned long long 8-bytes) */
+typedef unsigned long long t_u64, *t_pu64;
+/** Void pointer (4-bytes) */
+typedef void t_void, *t_pvoid;
+/** Size type */
+typedef t_u32 t_size;
+/** Boolean type */
+typedef t_u8 t_bool;
+
+#ifdef MLAN_64BIT
+/** Pointer type (64-bit) */
+typedef t_u64 t_ptr;
+/** Signed value (64-bit) */
+typedef t_s64 t_sval;
+#else
+/** Pointer type (32-bit) */
+typedef t_u32 t_ptr;
+/** Signed value (32-bit) */
+typedef t_s32 t_sval;
+#endif
+
+/** Constants below */
+
+#ifdef __GNUC__
+/** Structure packing begins */
+#define MLAN_PACK_START
+/** Structure packeing end */
+#define MLAN_PACK_END __attribute__((packed))
+#else /* !__GNUC__ */
+#ifdef PRAGMA_PACK
+/** Structure packing begins */
+#define MLAN_PACK_START
+/** Structure packeing end */
+#define MLAN_PACK_END
+#else /* !PRAGMA_PACK */
+/** Structure packing begins */
+#define MLAN_PACK_START __packed
+/** Structure packing end */
+#define MLAN_PACK_END
+#endif /* PRAGMA_PACK */
+#endif /* __GNUC__ */
+
+#ifndef INLINE
+#ifdef __GNUC__
+/** inline directive */
+#define INLINE inline
+#else
+/** inline directive */
+#define INLINE __inline
+#endif
+#endif
+
+/** MLAN TRUE */
+#define MTRUE (1)
+/** MLAN FALSE */
+#define MFALSE (0)
+
+#ifndef MACSTR
+/** MAC address security format */
+#define MACSTR "%02x:XX:XX:XX:%02x:%02x"
+#endif
+
+#ifndef MAC2STR
+/** MAC address security print arguments */
+#define MAC2STR(a) (a)[0], (a)[4], (a)[5]
+#endif
+
+#ifndef FULL_MACSTR
+#define FULL_MACSTR "%02x:%02x:%02x:%02x:%02x:%02x"
+#endif
+#ifndef FULL_MAC2STR
+#define FULL_MAC2STR(a) (a)[0], (a)[1], (a)[2], (a)[3], (a)[4], (a)[5]
+#endif
+
+/** Macros for Data Alignment : size */
+#define ALIGN_SZ(p, a) (((p) + ((a)-1)) & ~((a)-1))
+
+/** Macros for Data Alignment : address */
+#define ALIGN_ADDR(p, a) \
+ ((((t_ptr)(p)) + (((t_ptr)(a)) - 1)) & ~(((t_ptr)(a)) - 1))
+
+/** Return the byte offset of a field in the given structure */
+#define MLAN_FIELD_OFFSET(type, field) ((t_u32)(t_ptr) & (((type *)0)->field))
+/** Return aligned offset */
+#define OFFSET_ALIGN_ADDR(p, a) (t_u32)(ALIGN_ADDR(p, a) - (t_ptr)p)
+
+#if defined(WIFI_DIRECT_SUPPORT)
+/** Maximum BSS numbers */
+#define MLAN_MAX_BSS_NUM (16)
+#else
+/** Maximum BSS numbers */
+#define MLAN_MAX_BSS_NUM (2)
+#endif
+
+/** NET IP alignment */
+#define MLAN_NET_IP_ALIGN 2
+
+/** DMA alignment */
+/* SDIO3.0 Inrevium Adapter require 32 bit DMA alignment */
+#define DMA_ALIGNMENT 32
+
+/** max size of TxPD */
+#define MAX_TXPD_SIZE 32
+
+/** Minimum data header length */
+#define MLAN_MIN_DATA_HEADER_LEN (DMA_ALIGNMENT + MAX_TXPD_SIZE)
+
+/** rx data header length */
+#define MLAN_RX_HEADER_LEN MLAN_MIN_DATA_HEADER_LEN
+
+/** This is current limit on Maximum Tx AMPDU allowed */
+#define MLAN_MAX_TX_BASTREAM_SUPPORTED 16
+#define MLAN_MAX_TX_BASTREAM_DEFAULT 2
+/** This is current limit on Maximum Rx AMPDU allowed */
+#define MLAN_MAX_RX_BASTREAM_SUPPORTED 16
+
+#ifdef STA_SUPPORT
+/** Default Win size attached during ADDBA request */
+#define MLAN_STA_AMPDU_DEF_TXWINSIZE 64
+/** Default Win size attached during ADDBA response */
+#define MLAN_STA_AMPDU_DEF_RXWINSIZE 64
+/** RX winsize for COEX */
+#define MLAN_STA_COEX_AMPDU_DEF_RXWINSIZE 16
+#endif /* STA_SUPPORT */
+#ifdef UAP_SUPPORT
+/** Default Win size attached during ADDBA request */
+#define MLAN_UAP_AMPDU_DEF_TXWINSIZE 64
+/** Default Win size attached during ADDBA response */
+#define MLAN_UAP_AMPDU_DEF_RXWINSIZE 64
+/** RX winsize for COEX */
+#define MLAN_UAP_COEX_AMPDU_DEF_RXWINSIZE 16
+#endif /* UAP_SUPPORT */
+
+#ifdef WIFI_DIRECT_SUPPORT
+/** WFD use the same window size for tx/rx */
+#define MLAN_WFD_AMPDU_DEF_TXRXWINSIZE 64
+/** RX winsize for COEX */
+#define MLAN_WFD_COEX_AMPDU_DEF_RXWINSIZE 16
+#endif
+
+/** Block ack timeout value */
+#define MLAN_DEFAULT_BLOCK_ACK_TIMEOUT 0xffff
+/** Maximum Tx Win size configured for ADDBA request [10 bits] */
+#define MLAN_AMPDU_MAX_TXWINSIZE 0x3ff
+/** Maximum Rx Win size configured for ADDBA request [10 bits] */
+#define MLAN_AMPDU_MAX_RXWINSIZE 0x3ff
+
+/** Rate index for HR/DSSS 0 */
+#define MLAN_RATE_INDEX_HRDSSS0 0
+/** Rate index for HR/DSSS 3 */
+#define MLAN_RATE_INDEX_HRDSSS3 3
+/** Rate index for OFDM 0 */
+#define MLAN_RATE_INDEX_OFDM0 4
+/** Rate index for OFDM 7 */
+#define MLAN_RATE_INDEX_OFDM7 11
+/** Rate index for MCS 0 */
+#define MLAN_RATE_INDEX_MCS0 0
+/** Rate index for MCS 2 */
+#define MLAN_RATE_INDEX_MCS2 2
+/** Rate index for MCS 4 */
+#define MLAN_RATE_INDEX_MCS4 4
+/** Rate index for MCS 7 */
+#define MLAN_RATE_INDEX_MCS7 7
+/** Rate index for MCS 9 */
+#define MLAN_RATE_INDEX_MCS9 9
+/** Rate index for MCS11 */
+#define MLAN_RATE_INDEX_MCS11 11
+/** Rate index for MCS15 */
+#define MLAN_RATE_INDEX_MCS15 15
+/** Rate index for MCS 32 */
+#define MLAN_RATE_INDEX_MCS32 32
+/** Rate index for MCS 127 */
+#define MLAN_RATE_INDEX_MCS127 127
+#define MLAN_RATE_NSS1 1
+#define MLAN_RATE_NSS2 2
+
+/** Rate bitmap for OFDM 0 */
+#define MLAN_RATE_BITMAP_OFDM0 16
+/** Rate bitmap for OFDM 7 */
+#define MLAN_RATE_BITMAP_OFDM7 23
+/** Rate bitmap for MCS 0 */
+#define MLAN_RATE_BITMAP_MCS0 32
+/** Rate bitmap for MCS 127 */
+#define MLAN_RATE_BITMAP_MCS127 159
+#define MLAN_RATE_BITMAP_NSS1_MCS0 160
+#define MLAN_RATE_BITMAP_NSS1_MCS9 169
+#define MLAN_RATE_BITMAP_NSS2_MCS0 176
+#define MLAN_RATE_BITMAP_NSS2_MCS9 185
+
+/** MU beamformer */
+#define DEFALUT_11AC_CAP_BEAMFORMING_RESET_MASK (MBIT(19))
+
+/** Size of rx data buffer 4096+256 */
+#define MLAN_RX_DATA_BUF_SIZE 4352
+
+/** Size of command buffer */
+/** because cal_data_size 2.4 k */
+#define MRVDRV_SIZE_OF_CMD_BUFFER (4 * 1024)
+/** Size of rx command buffer */
+#define MLAN_RX_CMD_BUF_SIZE MRVDRV_SIZE_OF_CMD_BUFFER
+/** Upload size */
+#define WLAN_UPLD_SIZE MRVDRV_SIZE_OF_CMD_BUFFER
+
+#if defined(PCIE)
+#define MLAN_SSU_MAX_PKT_SIZE (283 * 4)
+#define MLAN_SSU_HEADER_SIZE 256
+/**
+ * Size of DMA buffer to collect 10ms SSU data:
+ * 2500 spectral packets, plus header
+ */
+#define MLAN_SSU_BUF_SIZE_1MS (MLAN_SSU_MAX_PKT_SIZE * 250)
+#define MLAN_SSU_BUF_SIZE (MLAN_SSU_HEADER_SIZE + MLAN_SSU_BUF_SIZE_1MS * 10)
+#define MLAN_SSU_BUF_SIZE_HOST (MLAN_SSU_BUF_SIZE)
+#endif
+
+/** driver initial the fw reset */
+#define FW_RELOAD_SDIO_INBAND_RESET 1
+/** out band reset trigger reset, no interface re-emulation */
+#define FW_RELOAD_NO_EMULATION 2
+/** out band reset with interface re-emulation */
+#define FW_RELOAD_WITH_EMULATION 3
+#ifdef PCIE
+/** pcie card reset */
+#define FW_RELOAD_PCIE_RESET 4
+#endif
+
+#ifdef USB
+#define MLAN_USB_BLOCK_SIZE (512)
+#define MLAN_USB_AGGR_MODE_NUM (0)
+#define MLAN_USB_AGGR_MODE_LEN (1)
+#define MLAN_USB_AGGR_MODE_LEN_V2 (2)
+#define MLAN_USB_TX_AGGR_MAX_LEN (16000)
+#define MLAN_USB_TX_AGGR_MAX_NUM 10
+#define MLAN_USB_TX_AGGR_V2_ALIGN 4
+#define MLAN_USB_TX_AGGR_HEADER 4
+#define MLAN_USB_MAX_PKT_SIZE (MLAN_USB_BLOCK_SIZE * 4)
+
+#define MLAN_USB_RX_ALIGN_SIZE MLAN_USB_BLOCK_SIZE
+#define MLAN_USB_RX_MAX_AGGR_NUM (8)
+#define MLAN_USB_RX_DEAGGR_TIMEOUT_USEC (200)
+
+#define MLAN_USB_TX_AGGR_ALIGN (MLAN_USB_BLOCK_SIZE * 4)
+#define MLAN_USB_TX_MAX_AGGR_NUM (8)
+#define MLAN_USB_TX_MAX_AGGR_SIZE \
+ (MLAN_USB_BLOCK_SIZE * 4 * MLAN_USB_TX_MAX_AGGR_NUM)
+#define MLAN_USB_TX_MIN_AGGR_TIMEOUT (1)
+#define MLAN_USB_TX_MAX_AGGR_TIMEOUT (4)
+#define MLAN_USB_TX_AGGR_TIMEOUT_MSEC MLAN_USB_TX_MIN_AGGR_TIMEOUT
+#define MLAN_USB_TX_AGGR_TIMEOUT_DYN (0xFFFF)
+#endif /*USB*/
+
+/** MLAN MAC Address Length */
+#define MLAN_MAC_ADDR_LENGTH (6)
+/** MLAN 802.11 MAC Address */
+typedef t_u8 mlan_802_11_mac_addr[MLAN_MAC_ADDR_LENGTH];
+
+/** MLAN Maximum SSID Length */
+#define MLAN_MAX_SSID_LENGTH (32)
+
+/** RTS/FRAG related defines */
+/** Minimum RTS value */
+#define MLAN_RTS_MIN_VALUE (0)
+/** Maximum RTS value */
+#define MLAN_RTS_MAX_VALUE (2347)
+/** Minimum FRAG value */
+#define MLAN_FRAG_MIN_VALUE (256)
+/** Maximum FRAG value */
+#define MLAN_FRAG_MAX_VALUE (2346)
+
+/** Minimum tx retry count */
+#define MLAN_TX_RETRY_MIN (0)
+/** Maximum tx retry count */
+#define MLAN_TX_RETRY_MAX (14)
+
+/** max Wmm AC queues */
+#define MAX_AC_QUEUES 4
+
+#ifdef SDIO
+/** define SDIO block size for data Tx/Rx */
+/* We support up to 480-byte block size due to FW buffer limitation. */
+#define MLAN_SDIO_BLOCK_SIZE 256
+
+/** define SDIO block size for firmware download */
+#define MLAN_SDIO_BLOCK_SIZE_FW_DNLD MLAN_SDIO_BLOCK_SIZE
+
+/** define allocated buffer size */
+#define ALLOC_BUF_SIZE MLAN_RX_DATA_BUF_SIZE
+/** SDIO MP aggr pkt limit */
+#define SDIO_MP_AGGR_DEF_PKT_LIMIT (16)
+/** max SDIO MP aggr pkt limit */
+#define SDIO_MP_AGGR_DEF_PKT_LIMIT_MAX (16)
+
+/** SDIO IO Port mask */
+#define MLAN_SDIO_IO_PORT_MASK 0xfffff
+/** SDIO Block/Byte mode mask */
+#define MLAN_SDIO_BYTE_MODE_MASK 0x80000000
+#endif /* SDIO */
+
+/** SD Interface */
+#define INTF_SD MBIT(0)
+#define IS_SD(ct) (ct & (INTF_SD << 8))
+/** PCIE Interface */
+#define INTF_PCIE MBIT(1)
+#define IS_PCIE(ct) (ct & (INTF_PCIE << 8))
+/** USB Interface */
+#define INTF_USB MBIT(2)
+#define IS_USB(ct) (ct & (INTF_USB << 8))
+
+/** 8887 card type */
+#define CARD_TYPE_8887 0x01
+/** 8897 card type */
+#define CARD_TYPE_8897 0x02
+/** 8977 card type */
+#define CARD_TYPE_8977 0x03
+/** 8997 card type */
+#define CARD_TYPE_8997 0x04
+/** 8987 card type */
+#define CARD_TYPE_8987 0x05
+/** 9098 card type */
+#define CARD_TYPE_9098 0x06
+/** 9097 card type */
+#define CARD_TYPE_9097 0x07
+/** 8978 card type */
+#define CARD_TYPE_8978 0x08
+
+/** 9098 A0 reverion num */
+#define CHIP_9098_REV_A0 1
+#define CHIP_9098_REV_A1 2
+/** 9097 CHIP REV */
+#define CHIP_9097_REV_B0 1
+
+#define INTF_MASK 0xff
+#define CARD_TYPE_MASK 0xff
+
+#ifdef SDIO
+/** SD8887 card type */
+#define CARD_TYPE_SD8887 (CARD_TYPE_8887 | (INTF_SD << 8))
+/** SD8897 card type */
+#define CARD_TYPE_SD8897 (CARD_TYPE_8897 | (INTF_SD << 8))
+/** SD8977 card type */
+#define CARD_TYPE_SD8977 (CARD_TYPE_8977 | (INTF_SD << 8))
+/** SD8978 card type */
+#define CARD_TYPE_SD8978 (CARD_TYPE_8978 | (INTF_SD << 8))
+/** SD8997 card type */
+#define CARD_TYPE_SD8997 (CARD_TYPE_8997 | (INTF_SD << 8))
+/** SD8987 card type */
+#define CARD_TYPE_SD8987 (CARD_TYPE_8987 | (INTF_SD << 8))
+/** SD9097 card type */
+#define CARD_TYPE_SD9097 (CARD_TYPE_9097 | (INTF_SD << 8))
+/** SD9098 card type */
+#define CARD_TYPE_SD9098 (CARD_TYPE_9098 | (INTF_SD << 8))
+
+#define IS_SD8887(ct) (CARD_TYPE_SD8887 == (ct))
+#define IS_SD8897(ct) (CARD_TYPE_SD8897 == (ct))
+#define IS_SD8977(ct) (CARD_TYPE_SD8977 == (ct))
+#define IS_SD8978(ct) (CARD_TYPE_SD8978 == (ct))
+#define IS_SD8997(ct) (CARD_TYPE_SD8997 == (ct))
+#define IS_SD8987(ct) (CARD_TYPE_SD8987 == (ct))
+#define IS_SD9097(ct) (CARD_TYPE_SD9097 == (ct))
+#define IS_SD9098(ct) (CARD_TYPE_SD9098 == (ct))
+
+/** SD8887 Card */
+#define CARD_SD8887 "SD8887"
+/** SD8897 Card */
+#define CARD_SD8897 "SD8897"
+/** SD8977 Card */
+#define CARD_SD8977 "SD8977"
+/** SD8978 Card */
+#define CARD_SD8978 "SD8978"
+/** SD8997 Card */
+#define CARD_SD8997 "SD8997"
+/** SD8987 Card */
+#define CARD_SD8987 "SD8987"
+/** SD9097 Card */
+#define CARD_SD9097 "SD9097"
+/** SD9098 Card */
+#define CARD_SD9098 "SD9098"
+#endif
+
+#ifdef PCIE
+/** PCIE8897 card type */
+#define CARD_TYPE_PCIE8897 (CARD_TYPE_8897 | (INTF_PCIE << 8))
+/** PCIE8997 card type */
+#define CARD_TYPE_PCIE8997 (CARD_TYPE_8997 | (INTF_PCIE << 8))
+/** PCIE9097 card type */
+#define CARD_TYPE_PCIE9097 (CARD_TYPE_9097 | (INTF_PCIE << 8))
+/** PCIE9098 card type */
+#define CARD_TYPE_PCIE9098 (CARD_TYPE_9098 | (INTF_PCIE << 8))
+
+#define IS_PCIE8897(ct) (CARD_TYPE_PCIE8897 == (ct))
+#define IS_PCIE8997(ct) (CARD_TYPE_PCIE8997 == (ct))
+#define IS_PCIE9097(ct) (CARD_TYPE_PCIE9097 == (ct))
+#define IS_PCIE9098(ct) (CARD_TYPE_PCIE9098 == (ct))
+
+/** PCIE8897 Card */
+#define CARD_PCIE8897 "PCIE8897"
+/** PCIE8997 Card */
+#define CARD_PCIE8997 "PCIE8997"
+/** PCIE9097 Card */
+#define CARD_PCIE9097 "PCIE9097"
+/** PCIE9000S Card */
+#define CARD_PCIE9000S "PCIE9000S"
+/** PCIE9098 Card */
+#define CARD_PCIE9098 "PCIE9098"
+#endif
+
+#ifdef USB
+/** USB8897 card type */
+#define CARD_TYPE_USB8897 (CARD_TYPE_8897 | (INTF_USB << 8))
+/** USB8997 card type */
+#define CARD_TYPE_USB8997 (CARD_TYPE_8997 | (INTF_USB << 8))
+/** USB8978 card type */
+#define CARD_TYPE_USB8978 (CARD_TYPE_8978 | (INTF_USB << 8))
+/** USB9098 card type */
+#define CARD_TYPE_USB9098 (CARD_TYPE_9098 | (INTF_USB << 8))
+/** USB9097 card type */
+#define CARD_TYPE_USB9097 (CARD_TYPE_9097 | (INTF_USB << 8))
+
+#define IS_USB8897(ct) (CARD_TYPE_USB8897 == (ct))
+#define IS_USB8997(ct) (CARD_TYPE_USB8997 == (ct))
+#define IS_USB8978(ct) (CARD_TYPE_USB8978 == (ct))
+#define IS_USB9098(ct) (CARD_TYPE_USB9098 == (ct))
+#define IS_USB9097(ct) (CARD_TYPE_USB9097 == (ct))
+
+/** USB8897 Card */
+#define CARD_USB8897 "USB8897"
+/** USB8997 Card */
+#define CARD_USB8997 "USB8997"
+/** USB8978 Card */
+#define CARD_USB8978 "USB8978"
+/** USB9098 Card */
+#define CARD_USB9098 "USB9098"
+/** USB9097 Card */
+#define CARD_USB9097 "USB9097"
+#endif
+
+#define IS_CARD8887(ct) (CARD_TYPE_8887 == ((ct)&0xf))
+#define IS_CARD8897(ct) (CARD_TYPE_8897 == ((ct)&0xf))
+#define IS_CARD8977(ct) (CARD_TYPE_8977 == ((ct)&0xf))
+#define IS_CARD8997(ct) (CARD_TYPE_8997 == ((ct)&0xf))
+#define IS_CARD8987(ct) (CARD_TYPE_8987 == ((ct)&0xf))
+#define IS_CARD9098(ct) (CARD_TYPE_9098 == ((ct)&0xf))
+#define IS_CARD9097(ct) (CARD_TYPE_9097 == ((ct)&0xf))
+
+typedef struct _card_type_entry {
+ t_u16 card_type;
+ t_u16 func_id;
+ char *name;
+} card_type_entry;
+
+#if defined(SDIO) || defined(PCIE)
+/** Max retry number of IO write */
+#define MAX_WRITE_IOMEM_RETRY 2
+#endif /* SDIO || PCIE */
+
+#ifdef PCIE
+typedef enum {
+ PCIE_INT_MODE_LEGACY = 0,
+ PCIE_INT_MODE_MSI,
+ PCIE_INT_MODE_MSIX,
+ PCIE_INT_MODE_MAX,
+} PCIE_INT_MODE;
+#endif /* PCIE */
+
+/** IN parameter */
+#define IN
+/** OUT parameter */
+#define OUT
+
+/** BIT value */
+#define MBIT(x) (((t_u32)1) << (x))
+
+/** Buffer flag for requeued packet */
+#define MLAN_BUF_FLAG_REQUEUED_PKT MBIT(0)
+/** Buffer flag for transmit buf from moal */
+#define MLAN_BUF_FLAG_MOAL_TX_BUF MBIT(1)
+/** Buffer flag for malloc mlan_buffer */
+#define MLAN_BUF_FLAG_MALLOC_BUF MBIT(2)
+
+/** Buffer flag for bridge packet */
+#define MLAN_BUF_FLAG_BRIDGE_BUF MBIT(3)
+
+#ifdef USB
+/** Buffer flag for deaggregated rx packet */
+#define MLAN_BUF_FLAG_RX_DEAGGR MBIT(5)
+
+/** Buffer flag for sleep confirm resp packet */
+#define MLAN_BUF_FLAG_SLEEPCFM_RESP MBIT(6)
+
+/** Buffer flag for USB TX AGGR */
+#define MLAN_BUF_FLAG_USB_TX_AGGR MBIT(7)
+#endif
+
+/** Buffer flag for TCP_ACK */
+#define MLAN_BUF_FLAG_TCP_ACK MBIT(9)
+
+/** Buffer flag for TX_STATUS */
+#define MLAN_BUF_FLAG_TX_STATUS MBIT(10)
+
+/** Buffer flag for NULL data packet */
+#define MLAN_BUF_FLAG_NULL_PKT MBIT(12)
+/** Buffer flag for Diag pkt */
+#define MLAN_BUF_FLAG_DIAG_BUF MBIT(13)
+
+#define MLAN_BUF_FLAG_TX_CTRL MBIT(14)
+
+#ifdef DEBUG_LEVEL1
+/** Debug level bit definition */
+#define MMSG MBIT(0)
+#define MFATAL MBIT(1)
+#define MERROR MBIT(2)
+#define MDATA MBIT(3)
+#define MCMND MBIT(4)
+#define MEVENT MBIT(5)
+#define MINTR MBIT(6)
+#define MIOCTL MBIT(7)
+
+#define MREG_D MBIT(9)
+
+#define MMPA_D MBIT(15)
+#define MDAT_D MBIT(16)
+#define MCMD_D MBIT(17)
+#define MEVT_D MBIT(18)
+#define MFW_D MBIT(19)
+#define MIF_D MBIT(20)
+
+#define MENTRY MBIT(28)
+#define MWARN MBIT(29)
+#define MINFO MBIT(30)
+#define MHEX_DUMP MBIT(31)
+#endif /* DEBUG_LEVEL1 */
+
+/** Memory allocation type: DMA */
+#define MLAN_MEM_DMA MBIT(0)
+
+/** Default memory allocation flag */
+#define MLAN_MEM_DEF 0
+
+/** mlan_status */
+typedef enum _mlan_status {
+ MLAN_STATUS_FAILURE = 0xffffffff,
+ MLAN_STATUS_SUCCESS = 0,
+ MLAN_STATUS_PENDING,
+ MLAN_STATUS_RESOURCE,
+#ifdef USB
+ /* Status pending and no resource */
+ MLAN_STATUS_PRESOURCE,
+#endif
+ MLAN_STATUS_COMPLETE,
+ MLAN_STATUS_FILE_ERR,
+} mlan_status;
+
+/** mlan_error_code */
+typedef enum _mlan_error_code {
+ /** No error */
+ MLAN_ERROR_NO_ERROR = 0,
+ /** Firmware/device errors below (MSB=0) */
+ MLAN_ERROR_FW_NOT_READY = 0x00000001,
+ MLAN_ERROR_FW_BUSY = 0x00000002,
+ MLAN_ERROR_FW_CMDRESP = 0x00000003,
+ MLAN_ERROR_DATA_TX_FAIL = 0x00000004,
+ MLAN_ERROR_DATA_RX_FAIL = 0x00000005,
+ /** Driver errors below (MSB=1) */
+ MLAN_ERROR_PKT_SIZE_INVALID = 0x80000001,
+ MLAN_ERROR_PKT_TIMEOUT = 0x80000002,
+ MLAN_ERROR_PKT_INVALID = 0x80000003,
+ MLAN_ERROR_CMD_INVALID = 0x80000004,
+ MLAN_ERROR_CMD_TIMEOUT = 0x80000005,
+ MLAN_ERROR_CMD_DNLD_FAIL = 0x80000006,
+ MLAN_ERROR_CMD_CANCEL = 0x80000007,
+ MLAN_ERROR_CMD_RESP_FAIL = 0x80000008,
+ MLAN_ERROR_CMD_ASSOC_FAIL = 0x80000009,
+ MLAN_ERROR_CMD_SCAN_FAIL = 0x8000000A,
+ MLAN_ERROR_IOCTL_INVALID = 0x8000000B,
+ MLAN_ERROR_IOCTL_FAIL = 0x8000000C,
+ MLAN_ERROR_EVENT_UNKNOWN = 0x8000000D,
+ MLAN_ERROR_INVALID_PARAMETER = 0x8000000E,
+ MLAN_ERROR_NO_MEM = 0x8000000F,
+ /** More to add */
+} mlan_error_code;
+
+/** mlan_buf_type */
+typedef enum _mlan_buf_type {
+ MLAN_BUF_TYPE_CMD = 1,
+ MLAN_BUF_TYPE_DATA,
+ MLAN_BUF_TYPE_EVENT,
+ MLAN_BUF_TYPE_RAW_DATA,
+#ifdef SDIO
+ MLAN_BUF_TYPE_SPA_DATA,
+#endif
+} mlan_buf_type;
+
+#ifdef USB
+/** mlan_usb_ep */
+typedef enum _mlan_usb_ep {
+ MLAN_USB_EP_CTRL = 0,
+ MLAN_USB_EP_CMD_EVENT = 1,
+ MLAN_USB_EP_DATA = 2,
+ MLAN_USB_EP_DATA_CH2 = 3,
+ MLAN_USB_EP_CMD_EVENT_IF2 = 4,
+ MLAN_USB_EP_DATA_IF2 = 5,
+ MLAN_USB_EP_DATA_CH2_IF2 = 6,
+} mlan_usb_ep;
+
+/** Timeout in milliseconds for usb_bulk_msg function */
+#define MLAN_USB_BULK_MSG_TIMEOUT 100
+#endif /* USB */
+
+/** MLAN BSS type */
+typedef enum _mlan_bss_type {
+ MLAN_BSS_TYPE_STA = 0,
+ MLAN_BSS_TYPE_UAP = 1,
+#ifdef WIFI_DIRECT_SUPPORT
+ MLAN_BSS_TYPE_WIFIDIRECT = 2,
+#endif
+ MLAN_BSS_TYPE_ANY = 0xff,
+} mlan_bss_type;
+
+/** MLAN BSS role */
+typedef enum _mlan_bss_role {
+ MLAN_BSS_ROLE_STA = 0,
+ MLAN_BSS_ROLE_UAP = 1,
+ MLAN_BSS_ROLE_ANY = 0xff,
+} mlan_bss_role;
+
+/** BSS role mask */
+#define BSS_ROLE_MASK (MBIT(0) | MBIT(1))
+
+/** Get BSS role */
+#define GET_BSS_ROLE(priv) ((priv)->bss_role & BSS_ROLE_MASK)
+
+/** mlan_data_frame_type */
+typedef enum _mlan_data_frame_type {
+ MLAN_DATA_FRAME_TYPE_ETH_II = 0,
+ MLAN_DATA_FRAME_TYPE_802_11,
+} mlan_data_frame_type;
+
+/** mlan_event_id */
+typedef enum _mlan_event_id {
+ /* Event generated by firmware (MSB=0) */
+ MLAN_EVENT_ID_FW_UNKNOWN = 0x00000001,
+ MLAN_EVENT_ID_FW_ADHOC_LINK_SENSED = 0x00000002,
+ MLAN_EVENT_ID_FW_ADHOC_LINK_LOST = 0x00000003,
+ MLAN_EVENT_ID_FW_DISCONNECTED = 0x00000004,
+ MLAN_EVENT_ID_FW_MIC_ERR_UNI = 0x00000005,
+ MLAN_EVENT_ID_FW_MIC_ERR_MUL = 0x00000006,
+ MLAN_EVENT_ID_FW_BCN_RSSI_LOW = 0x00000007,
+ MLAN_EVENT_ID_FW_BCN_RSSI_HIGH = 0x00000008,
+ MLAN_EVENT_ID_FW_BCN_SNR_LOW = 0x00000009,
+ MLAN_EVENT_ID_FW_BCN_SNR_HIGH = 0x0000000A,
+ MLAN_EVENT_ID_FW_MAX_FAIL = 0x0000000B,
+ MLAN_EVENT_ID_FW_DATA_RSSI_LOW = 0x0000000C,
+ MLAN_EVENT_ID_FW_DATA_RSSI_HIGH = 0x0000000D,
+ MLAN_EVENT_ID_FW_DATA_SNR_LOW = 0x0000000E,
+ MLAN_EVENT_ID_FW_DATA_SNR_HIGH = 0x0000000F,
+ MLAN_EVENT_ID_FW_LINK_QUALITY = 0x00000010,
+ MLAN_EVENT_ID_FW_PORT_RELEASE = 0x00000011,
+ MLAN_EVENT_ID_FW_PRE_BCN_LOST = 0x00000012,
+ MLAN_EVENT_ID_FW_DEBUG_INFO = 0x00000013,
+ MLAN_EVENT_ID_FW_WMM_CONFIG_CHANGE = 0x0000001A,
+ MLAN_EVENT_ID_FW_HS_WAKEUP = 0x0000001B,
+ MLAN_EVENT_ID_FW_BG_SCAN = 0x0000001D,
+ MLAN_EVENT_ID_FW_BG_SCAN_STOPPED = 0x0000001E,
+ MLAN_EVENT_ID_FW_WEP_ICV_ERR = 0x00000020,
+ MLAN_EVENT_ID_FW_STOP_TX = 0x00000021,
+ MLAN_EVENT_ID_FW_START_TX = 0x00000022,
+ MLAN_EVENT_ID_FW_CHANNEL_SWITCH_ANN = 0x00000023,
+ MLAN_EVENT_ID_FW_RADAR_DETECTED = 0x00000024,
+ MLAN_EVENT_ID_FW_CHANNEL_REPORT_RDY = 0x00000025,
+ MLAN_EVENT_ID_FW_BW_CHANGED = 0x00000026,
+ MLAN_EVENT_ID_FW_REMAIN_ON_CHAN_EXPIRED = 0x0000002B,
+
+#ifdef UAP_SUPPORT
+ MLAN_EVENT_ID_UAP_FW_BSS_START = 0x0000002C,
+ MLAN_EVENT_ID_UAP_FW_BSS_ACTIVE = 0x0000002D,
+ MLAN_EVENT_ID_UAP_FW_BSS_IDLE = 0x0000002E,
+ MLAN_EVENT_ID_UAP_FW_MIC_COUNTERMEASURES = 0x0000002F,
+ MLAN_EVENT_ID_UAP_FW_STA_CONNECT = 0x00000030,
+ MLAN_EVENT_ID_UAP_FW_STA_DISCONNECT = 0x00000031,
+#endif
+
+ MLAN_EVENT_ID_FW_DUMP_INFO = 0x00000033,
+
+ MLAN_EVENT_ID_FW_TX_STATUS = 0x00000034,
+ MLAN_EVENT_ID_FW_CHAN_SWITCH_COMPLETE = 0x00000036,
+#if defined(PCIE)
+ MLAN_EVENT_ID_SSU_DUMP_FILE = 0x00000039,
+#endif /* SSU_SUPPORT */
+ /* Event generated by MLAN driver (MSB=1) */
+ MLAN_EVENT_ID_DRV_CONNECTED = 0x80000001,
+ MLAN_EVENT_ID_DRV_DEFER_HANDLING = 0x80000002,
+ MLAN_EVENT_ID_DRV_HS_ACTIVATED = 0x80000003,
+ MLAN_EVENT_ID_DRV_HS_DEACTIVATED = 0x80000004,
+ MLAN_EVENT_ID_DRV_MGMT_FRAME = 0x80000005,
+ MLAN_EVENT_ID_DRV_OBSS_SCAN_PARAM = 0x80000006,
+ MLAN_EVENT_ID_DRV_PASSTHRU = 0x80000007,
+ MLAN_EVENT_ID_DRV_SCAN_REPORT = 0x80000009,
+ MLAN_EVENT_ID_DRV_MEAS_REPORT = 0x8000000A,
+ MLAN_EVENT_ID_DRV_ASSOC_FAILURE_REPORT = 0x8000000B,
+ MLAN_EVENT_ID_DRV_REPORT_STRING = 0x8000000F,
+ MLAN_EVENT_ID_DRV_DBG_DUMP = 0x80000012,
+ MLAN_EVENT_ID_DRV_BGSCAN_RESULT = 0x80000013,
+ MLAN_EVENT_ID_DRV_FLUSH_RX_WORK = 0x80000015,
+ MLAN_EVENT_ID_DRV_DEFER_RX_WORK = 0x80000016,
+ MLAN_EVENT_ID_DRV_FT_RESPONSE = 0x80000018,
+ MLAN_EVENT_ID_DRV_FLUSH_MAIN_WORK = 0x80000019,
+#ifdef UAP_SUPPORT
+ MLAN_EVENT_ID_DRV_UAP_CHAN_INFO = 0x80000020,
+#endif
+ MLAN_EVENT_ID_DRV_ASSOC_FAILURE_LOGGER = 0x80000026,
+ MLAN_EVENT_ID_DRV_ASSOC_SUCC_LOGGER = 0x80000027,
+ MLAN_EVENT_ID_DRV_DISCONNECT_LOGGER = 0x80000028,
+ MLAN_EVENT_ID_DRV_WIFI_STATUS = 0x80000029,
+ MLAN_EVENT_ID_STORE_HOST_CMD_RESP = 0x80000030,
+} mlan_event_id;
+
+/** Data Structures */
+/** mlan_image data structure */
+typedef struct _mlan_fw_image {
+ /** Firmware image buffer pointer */
+ t_u8 *pfw_buf;
+ /** Firmware image length */
+ t_u32 fw_len;
+ /** Firmware reload flag */
+ t_u8 fw_reload;
+} mlan_fw_image, *pmlan_fw_image;
+
+/** MrvlIEtypesHeader_t */
+typedef MLAN_PACK_START struct _MrvlIEtypesHeader {
+ /** Header type */
+ t_u16 type;
+ /** Header length */
+ t_u16 len;
+} MLAN_PACK_END MrvlIEtypesHeader_t;
+
+/** MrvlExtIEtypesHeader_t */
+typedef MLAN_PACK_START struct _MrvlExtIEtypesHeader {
+ /** Header type */
+ t_u16 type;
+ /** Header length */
+ t_u16 len;
+ /** ext id */
+ t_u8 ext_id;
+} MLAN_PACK_END MrvlExtIEtypesHeader_t;
+
+/** MrvlIEtypes_Data_t */
+typedef MLAN_PACK_START struct _MrvlExtIEtypes_Data_t {
+ /** Header */
+ MrvlExtIEtypesHeader_t header;
+ /** Data */
+ t_u8 data[];
+} MLAN_PACK_END MrvlExtIEtypes_Data_t;
+
+/** MrvlIEtypes_Data_t */
+typedef MLAN_PACK_START struct _MrvlIEtypes_Data_t {
+ /** Header */
+ MrvlIEtypesHeader_t header;
+ /** Data */
+ t_u8 data[];
+} MLAN_PACK_END MrvlIEtypes_Data_t;
+
+#define OID_TYPE_CAL 0x2
+#define OID_TYPE_DPD 0xa
+#define UNKNOW_DPD_LENGTH 0xffffffff
+
+/** Custom data structure */
+typedef struct _mlan_init_param {
+ /** DPD data buffer pointer */
+ t_u8 *pdpd_data_buf;
+ /** DPD data length */
+ t_u32 dpd_data_len;
+ /** region txpowerlimit cfg data buffer pointer */
+ t_u8 *ptxpwr_data_buf;
+ /** region txpowerlimit cfg data length */
+ t_u32 txpwr_data_len;
+ /** Cal data buffer pointer */
+ t_u8 *pcal_data_buf;
+ /** Cal data length */
+ t_u32 cal_data_len;
+ /** Other custom data */
+} mlan_init_param, *pmlan_init_param;
+
+/** channel type */
+enum mlan_channel_type {
+ CHAN_NO_HT,
+ CHAN_HT20,
+ CHAN_HT40MINUS,
+ CHAN_HT40PLUS,
+ CHAN_VHT80
+};
+
+/** channel band */
+enum { BAND_2GHZ = 0,
+ BAND_5GHZ = 1,
+ BAND_4GHZ = 2,
+};
+
+/** channel offset */
+enum { SEC_CHAN_NONE = 0,
+ SEC_CHAN_ABOVE = 1,
+ SEC_CHAN_5MHZ = 2,
+ SEC_CHAN_BELOW = 3 };
+
+/** channel bandwidth */
+enum { CHAN_BW_20MHZ = 0,
+ CHAN_BW_10MHZ,
+ CHAN_BW_40MHZ,
+ CHAN_BW_80MHZ,
+};
+
+/** scan mode */
+enum { SCAN_MODE_MANUAL = 0,
+ SCAN_MODE_ACS,
+ SCAN_MODE_USER,
+};
+
+/** max cac time 10 minutes */
+#define MAX_CAC_DWELL_TIME 600000
+/** default cac time 60 seconds */
+#define DEF_CAC_DWELL_TIME 60000
+/** start freq for 5G */
+#define START_FREQ_11A_BAND 5000
+/** DFS state */
+typedef enum _dfs_state_t {
+ /** Channel can be used, CAC (Channel Availability Check) must be done
+ before using it */
+ DFS_USABLE = 0,
+ /** Channel is not available, radar was detected */
+ DFS_UNAVAILABLE = 1,
+ /** Channel is Available, CAC is done and is free of radar */
+ DFS_AVAILABLE = 2,
+} dfs_state_t;
+
+typedef enum _dfs_w53_cfg_t {
+ /** DFS W53 Default Fw Value */
+ DFS_W53_DEFAULT_FW = 0,
+ /** DFS W53 New W53 Rules/Standard */
+ DFS_W53_NEW = 1,
+ /** DFS W53 Old W53 Rules/Standard */
+ DFS_W53_OLD = 2
+} dfs_w53_cfg_t;
+
+/** Band_Config_t */
+typedef MLAN_PACK_START struct _Band_Config_t {
+#ifdef BIG_ENDIAN_SUPPORT
+ /** Channel Selection Mode - (00)=manual, (01)=ACS, (02)=user*/
+ t_u8 scanMode : 2;
+ /** Secondary Channel Offset - (00)=None, (01)=Above, (11)=Below */
+ t_u8 chan2Offset : 2;
+ /** Channel Width - (00)=20MHz, (10)=40MHz, (11)=80MHz */
+ t_u8 chanWidth : 2;
+ /** Band Info - (00)=2.4GHz, (01)=5GHz */
+ t_u8 chanBand : 2;
+#else
+ /** Band Info - (00)=2.4GHz, (01)=5GHz */
+ t_u8 chanBand : 2;
+ /** Channel Width - (00)=20MHz, (10)=40MHz, (11)=80MHz */
+ t_u8 chanWidth : 2;
+ /** Secondary Channel Offset - (00)=None, (01)=Above, (11)=Below */
+ t_u8 chan2Offset : 2;
+ /** Channel Selection Mode - (00)=manual, (01)=ACS, (02)=Adoption mode*/
+ t_u8 scanMode : 2;
+#endif
+} MLAN_PACK_END Band_Config_t;
+
+/** channel_band_t */
+typedef MLAN_PACK_START struct _chan_band_info {
+ /** Band Configuration */
+ Band_Config_t bandcfg;
+ /** channel */
+ t_u8 channel;
+ /** 11n flag */
+ t_u8 is_11n_enabled;
+ /** center channel */
+ t_u8 center_chan;
+ /** dfs channel flag */
+ t_u8 is_dfs_chan;
+} MLAN_PACK_END chan_band_info, *pchan_band_info;
+
+/** Channel usability flags */
+#define NXP_CHANNEL_NO_OFDM MBIT(9)
+#define NXP_CHANNEL_NO_CCK MBIT(8)
+#define NXP_CHANNEL_DISABLED MBIT(7)
+/* BIT 5/6 resevered for FW */
+#define NXP_CHANNEL_NOHT160 MBIT(4)
+#define NXP_CHANNEL_NOHT80 MBIT(3)
+#define NXP_CHANNEL_NOHT40 MBIT(2)
+#define NXP_CHANNEL_DFS MBIT(1)
+#define NXP_CHANNEL_PASSIVE MBIT(0)
+
+/** CFP dynamic (non-const) elements */
+typedef struct _cfp_dyn_t {
+ /** extra flags to specify channel usability
+ * bit 9 : if set, channel is non-OFDM
+ * bit 8 : if set, channel is non-CCK
+ * bit 7 : if set, channel is disabled
+ * bit 5/6 resevered for FW
+ * bit 4 : if set, 160MHz on channel is disabled
+ * bit 3 : if set, 80MHz on channel is disabled
+ * bit 2 : if set, 40MHz on channel is disabled
+ * bit 1 : if set, channel is DFS channel
+ * bit 0 : if set, channel is passive
+ */
+ t_u16 flags;
+ /** TRUE: Channel is blacklisted (do not use) */
+ t_bool blacklist;
+} cfp_dyn_t;
+
+/** Chan-Freq-TxPower mapping table*/
+typedef struct _chan_freq_power_t {
+ /** Channel Number */
+ t_u16 channel;
+ /** Frequency of this Channel */
+ t_u32 freq;
+ /** Max allowed Tx power level */
+ t_u16 max_tx_power;
+ /** TRUE:radar detect required for BAND A or passive scan for BAND B/G;
+ * FALSE:radar detect not required for BAND A or active scan for BAND
+ * B/G*/
+ t_bool passive_scan_or_radar_detect;
+ /** Elements associated to cfp that change at run-time */
+ cfp_dyn_t dynamic;
+} chan_freq_power_t;
+
+/** mlan_event data structure */
+typedef struct _mlan_event {
+ /** BSS index number for multiple BSS support */
+ t_u32 bss_index;
+ /** Event ID */
+ mlan_event_id event_id;
+ /** Event length */
+ t_u32 event_len;
+ /** Event buffer */
+ t_u8 event_buf[];
+} mlan_event, *pmlan_event;
+
+/** mlan_cmdresp_event data structure */
+typedef struct _mlan_cmdresp_event {
+ /** BSS index number for multiple BSS support */
+ t_u32 bss_index;
+ /** Event ID */
+ mlan_event_id event_id;
+ /** Event length */
+ t_u32 event_len;
+ /** resp buffer pointer */
+ t_u8 *resp;
+} mlan_cmdresp_event, *pmlan_cmdresp_event;
+
+/** csi event data structure */
+
+/** mlan_ioctl_req data structure */
+typedef struct _mlan_ioctl_req {
+ /** Pointer to previous mlan_ioctl_req */
+ struct _mlan_ioctl_req *pprev;
+ /** Pointer to next mlan_ioctl_req */
+ struct _mlan_ioctl_req *pnext;
+ /** Status code from firmware/driver */
+ t_u32 status_code;
+ /** BSS index number for multiple BSS support */
+ t_u32 bss_index;
+ /** Request id */
+ t_u32 req_id;
+ /** Action: set or get */
+ t_u32 action;
+ /** Pointer to buffer */
+ t_u8 *pbuf;
+ /** Length of buffer */
+ t_u32 buf_len;
+ /** Length of the data read/written in buffer */
+ t_u32 data_read_written;
+ /** Length of buffer needed */
+ t_u32 buf_len_needed;
+ /** Reserved for MOAL module */
+ t_ptr reserved_1;
+} mlan_ioctl_req, *pmlan_ioctl_req;
+
+/** txpower structure */
+typedef MLAN_PACK_START struct {
+#ifdef BIG_ENDIAN_SUPPORT
+ /** Host tx power ctrl:
+ 0x0: use fw setting for TX power
+ 0x1: value specified in bit[6] and bit[5:0] are valid */
+ t_u8 hostctl : 1;
+ /** Sign of the power specified in bit[5:0] */
+ t_u8 sign : 1;
+ /** Power to be used for transmission(in dBm) */
+ t_u8 abs_val : 6;
+#else
+ /** Power to be used for transmission(in dBm) */
+ t_u8 abs_val : 6;
+ /** Sign of the power specified in bit[5:0] */
+ t_u8 sign : 1;
+ /** Host tx power ctrl:
+ 0x0: use fw setting for TX power
+ 0x1: value specified in bit[6] and bit[5:0] are valid */
+ t_u8 hostctl : 1;
+#endif
+} MLAN_PACK_END tx_power_t;
+/* pkt_txctrl */
+typedef MLAN_PACK_START struct _pkt_txctrl {
+ /**Data rate in unit of 0.5Mbps */
+ t_u16 data_rate;
+ /*Channel number to transmit the frame */
+ t_u8 channel;
+ /** Bandwidth to transmit the frame*/
+ t_u8 bw;
+ /** Power to be used for transmission*/
+ union {
+ tx_power_t tp;
+ t_u8 val;
+ } tx_power;
+ /** Retry time of tx transmission*/
+ t_u8 retry_limit;
+} MLAN_PACK_END pkt_txctrl, *ppkt_txctrl;
+
+/** pkt_rxinfo */
+typedef MLAN_PACK_START struct _pkt_rxinfo {
+ /** Data rate of received paccket*/
+ t_u16 data_rate;
+ /** Channel on which packet was received*/
+ t_u8 channel;
+ /** Rx antenna*/
+ t_u8 antenna;
+ /** Rx Rssi*/
+ t_u8 rssi;
+} MLAN_PACK_END pkt_rxinfo, *ppkt_rxinfo;
+
+/** mlan_buffer data structure */
+typedef struct _mlan_buffer {
+ /** Pointer to previous mlan_buffer */
+ struct _mlan_buffer *pprev;
+ /** Pointer to next mlan_buffer */
+ struct _mlan_buffer *pnext;
+ /** Status code from firmware/driver */
+ t_u32 status_code;
+ /** Flags for this buffer */
+ t_u32 flags;
+ /** BSS index number for multiple BSS support */
+ t_u32 bss_index;
+ /** Buffer descriptor, e.g. skb in Linux */
+ t_void *pdesc;
+ /** Pointer to buffer */
+ t_u8 *pbuf;
+#ifdef PCIE
+ /** Physical address of the pbuf pointer */
+ t_u64 buf_pa;
+ t_u32 total_pcie_buf_len;
+#endif
+ /** Offset to data */
+ t_u32 data_offset;
+ /** Data length */
+ t_u32 data_len;
+ /** Buffer type: data, cmd, event etc. */
+ mlan_buf_type buf_type;
+
+ /** Fields below are valid for data packet only */
+ /** QoS priority */
+ t_u32 priority;
+ /** Time stamp when packet is received (seconds) */
+ t_u32 in_ts_sec;
+ /** Time stamp when packet is received (micro seconds) */
+ t_u32 in_ts_usec;
+ /** Time stamp when packet is processed (seconds) */
+ t_u32 out_ts_sec;
+ /** Time stamp when packet is processed (micro seconds) */
+ t_u32 out_ts_usec;
+ /** tx_seq_num */
+ t_u32 tx_seq_num;
+
+ /** Fields below are valid for MLAN module only */
+ /** Pointer to parent mlan_buffer */
+ struct _mlan_buffer *pparent;
+ /** Use count for this buffer */
+ t_u32 use_count;
+ union {
+ pkt_txctrl tx_info;
+ pkt_rxinfo rx_info;
+ } u;
+} mlan_buffer, *pmlan_buffer, **ppmlan_buffer;
+
+/** mlan_fw_info data structure */
+typedef struct _mlan_hw_info {
+ t_u32 fw_cap;
+} mlan_hw_info, *pmlan_hw_info;
+
+/** mlan_bss_attr data structure */
+typedef struct _mlan_bss_attr {
+ /** BSS type */
+ t_u32 bss_type;
+ /** Data frame type: Ethernet II, 802.11, etc. */
+ t_u32 frame_type;
+ /** The BSS is active (non-0) or not (0). */
+ t_u32 active;
+ /** BSS Priority */
+ t_u32 bss_priority;
+ /** BSS number */
+ t_u32 bss_num;
+ /** The BSS is virtual */
+ t_u32 bss_virtual;
+} mlan_bss_attr, *pmlan_bss_attr;
+
+/** bss tbl data structure */
+typedef struct _mlan_bss_tbl {
+ /** BSS Attributes */
+ mlan_bss_attr bss_attr[MLAN_MAX_BSS_NUM];
+} mlan_bss_tbl, *pmlan_bss_tbl;
+
+#ifdef PRAGMA_PACK
+#pragma pack(push, 1)
+#endif
+
+/** Type enumeration for the command result */
+typedef MLAN_PACK_START enum _mlan_cmd_result_e {
+ MLAN_CMD_RESULT_SUCCESS = 0,
+ MLAN_CMD_RESULT_FAILURE = 1,
+ MLAN_CMD_RESULT_TIMEOUT = 2,
+ MLAN_CMD_RESULT_INVALID_DATA = 3
+} MLAN_PACK_END mlan_cmd_result_e;
+
+/** Type enumeration of WMM AC_QUEUES */
+typedef MLAN_PACK_START enum _mlan_wmm_ac_e {
+ WMM_AC_BK,
+ WMM_AC_BE,
+ WMM_AC_VI,
+ WMM_AC_VO
+} MLAN_PACK_END mlan_wmm_ac_e;
+
+/** Type enumeration for the action field in the Queue Config command */
+typedef MLAN_PACK_START enum _mlan_wmm_queue_config_action_e {
+ MLAN_WMM_QUEUE_CONFIG_ACTION_GET = 0,
+ MLAN_WMM_QUEUE_CONFIG_ACTION_SET = 1,
+ MLAN_WMM_QUEUE_CONFIG_ACTION_DEFAULT = 2,
+ MLAN_WMM_QUEUE_CONFIG_ACTION_MAX
+} MLAN_PACK_END mlan_wmm_queue_config_action_e;
+
+/** Type enumeration for the action field in the queue stats command */
+typedef MLAN_PACK_START enum _mlan_wmm_queue_stats_action_e {
+ MLAN_WMM_STATS_ACTION_START = 0,
+ MLAN_WMM_STATS_ACTION_STOP = 1,
+ MLAN_WMM_STATS_ACTION_GET_CLR = 2,
+ MLAN_WMM_STATS_ACTION_SET_CFG = 3, /* Not currently used */
+ MLAN_WMM_STATS_ACTION_GET_CFG = 4, /* Not currently used */
+ MLAN_WMM_STATS_ACTION_MAX
+} MLAN_PACK_END mlan_wmm_queue_stats_action_e;
+
+/**
+ * @brief IOCTL structure for a Traffic stream status.
+ *
+ */
+typedef MLAN_PACK_START struct {
+ /** TSID: Range: 0->7 */
+ t_u8 tid;
+ /** TSID specified is valid */
+ t_u8 valid;
+ /** AC TSID is active on */
+ t_u8 access_category;
+ /** UP specified for the TSID */
+ t_u8 user_priority;
+ /** Power save mode for TSID: 0 (legacy), 1 (UAPSD) */
+ t_u8 psb;
+ /** Upstream(0), Downlink(1), Bidirectional(3) */
+ t_u8 flow_dir;
+ /** Medium time granted for the TSID */
+ t_u16 medium_time;
+} MLAN_PACK_END wlan_ioctl_wmm_ts_status_t,
+ /** Type definition of mlan_ds_wmm_ts_status for
+ MLAN_OID_WMM_CFG_TS_STATUS */
+ mlan_ds_wmm_ts_status, *pmlan_ds_wmm_ts_status;
+
+/** Max Ie length */
+#define MAX_IE_SIZE 256
+
+/** custom IE */
+typedef MLAN_PACK_START struct _custom_ie {
+ /** IE Index */
+ t_u16 ie_index;
+ /** Mgmt Subtype Mask */
+ t_u16 mgmt_subtype_mask;
+ /** IE Length */
+ t_u16 ie_length;
+ /** IE buffer */
+ t_u8 ie_buffer[MAX_IE_SIZE];
+} MLAN_PACK_END custom_ie;
+
+/** Max IE index to FW */
+#define MAX_MGMT_IE_INDEX_TO_FW 4
+/** Max IE index per BSS */
+#define MAX_MGMT_IE_INDEX 26
+
+/** custom IE info */
+typedef MLAN_PACK_START struct _custom_ie_info {
+ /** size of buffer */
+ t_u16 buf_size;
+ /** no of buffers of buf_size */
+ t_u16 buf_count;
+} MLAN_PACK_END custom_ie_info;
+
+/** TLV buffer : Max Mgmt IE */
+typedef MLAN_PACK_START struct _tlvbuf_max_mgmt_ie {
+ /** Type */
+ t_u16 type;
+ /** Length */
+ t_u16 len;
+ /** No of tuples */
+ t_u16 count;
+ /** custom IE info tuples */
+ custom_ie_info info[MAX_MGMT_IE_INDEX];
+} MLAN_PACK_END tlvbuf_max_mgmt_ie;
+
+/** TLV buffer : custom IE */
+typedef MLAN_PACK_START struct _tlvbuf_custom_ie {
+ /** Type */
+ t_u16 type;
+ /** Length */
+ t_u16 len;
+ /** IE data */
+ custom_ie ie_data_list[MAX_MGMT_IE_INDEX_TO_FW];
+ /** Max mgmt IE TLV */
+ tlvbuf_max_mgmt_ie max_mgmt_ie;
+} MLAN_PACK_END mlan_ds_misc_custom_ie;
+
+/** channel width */
+typedef enum wifi_channel_width {
+ WIFI_CHAN_WIDTH_20 = 0,
+ WIFI_CHAN_WIDTH_40 = 1,
+ WIFI_CHAN_WIDTH_80 = 2,
+ WIFI_CHAN_WIDTH_160 = 3,
+ WIFI_CHAN_WIDTH_80P80 = 4,
+ WIFI_CHAN_WIDTH_5 = 5,
+ WIFI_CHAN_WIDTH_10 = 6,
+ WIFI_CHAN_WIDTH_INVALID = -1
+} wifi_channel_width_t;
+
+/** channel information */
+typedef struct {
+ /** channel width (20, 40, 80, 80+80, 160) */
+ wifi_channel_width_t width;
+ /** primary 20 MHz channel */
+ int center_freq;
+ /** center frequency (MHz) first segment */
+ int center_freq0;
+ /** center frequency (MHz) second segment */
+ int center_freq1;
+} wifi_channel_info;
+
+/** wifi rate */
+typedef struct {
+ /** 0: OFDM, 1:CCK, 2:HT 3:VHT 4..7 reserved */
+ t_u32 preamble : 3;
+ /** 0:1x1, 1:2x2, 3:3x3, 4:4x4 */
+ t_u32 nss : 2;
+ /** 0:20MHz, 1:40Mhz, 2:80Mhz, 3:160Mhz */
+ t_u32 bw : 3;
+ /** OFDM/CCK rate code would be as per ieee std in the units of 0.5mbps
+ */
+ /** HT/VHT it would be mcs index */
+ t_u32 rateMcsIdx : 8;
+ /** reserved */
+ t_u32 reserved : 16;
+ /** units of 100 Kbps */
+ t_u32 bitrate;
+} wifi_rate;
+
+/** wifi Preamble type */
+typedef enum {
+ WIFI_PREAMBLE_LEGACY = 0x1,
+ WIFI_PREAMBLE_HT = 0x2,
+ WIFI_PREAMBLE_VHT = 0x4
+} wifi_preamble;
+
+/** timeval */
+typedef struct {
+ /** Time (seconds) */
+ t_u32 time_sec;
+ /** Time (micro seconds) */
+ t_u32 time_usec;
+} wifi_timeval;
+
+#define MAX_NUM_RATE 32
+#define MAX_RADIO 2
+#define MAX_NUM_CHAN 1
+#define VHT_NUM_SUPPORT_MCS 10
+#define MCS_NUM_SUPP 16
+
+#define BUF_MAXLEN 4096
+/** connection state */
+typedef enum {
+ MLAN_DISCONNECTED = 0,
+ MLAN_AUTHENTICATING = 1,
+ MLAN_ASSOCIATING = 2,
+ MLAN_ASSOCIATED = 3,
+ /** if done by firmware/driver */
+ MLAN_EAPOL_STARTED = 4,
+ /** if done by firmware/driver */
+ MLAN_EAPOL_COMPLETED = 5,
+} mlan_connection_state;
+/** roam state */
+typedef enum {
+ MLAN_ROAMING_IDLE = 0,
+ MLAN_ROAMING_ACTIVE = 1,
+} mlan_roam_state;
+/** interface mode */
+typedef enum {
+ MLAN_INTERFACE_STA = 0,
+ MLAN_INTERFACE_SOFTAP = 1,
+ MLAN_INTERFACE_IBSS = 2,
+ MLAN_INTERFACE_P2P_CLIENT = 3,
+ MLAN_INTERFACE_P2P_GO = 4,
+ MLAN_INTERFACE_NAN = 5,
+ MLAN_INTERFACE_MESH = 6,
+} mlan_interface_mode;
+
+/** set for QOS association */
+#define MLAN_CAPABILITY_QOS 0x00000001
+/** set for protected association (802.11 beacon frame control protected bit
+ * set) */
+#define MLAN_CAPABILITY_PROTECTED 0x00000002
+/** set if 802.11 Extended Capabilities element interworking bit is set */
+#define MLAN_CAPABILITY_INTERWORKING 0x00000004
+/** set for HS20 association */
+#define MLAN_CAPABILITY_HS20 0x00000008
+/** set is 802.11 Extended Capabilities element UTF-8 SSID bit is set */
+#define MLAN_CAPABILITY_SSID_UTF8 0x00000010
+/** set is 802.11 Country Element is present */
+#define MLAN_CAPABILITY_COUNTRY 0x00000020
+
+/** link layer status */
+typedef struct {
+ /** interface mode */
+ mlan_interface_mode mode;
+ /** interface mac address (self) */
+ t_u8 mac_addr[6];
+ /** connection state (valid for STA, CLI only) */
+ mlan_connection_state state;
+ /** roaming state */
+ mlan_roam_state roaming;
+ /** WIFI_CAPABILITY_XXX (self) */
+ t_u32 capabilities;
+ /** null terminated SSID */
+ t_u8 ssid[33];
+ /** bssid */
+ t_u8 bssid[6];
+ /** country string advertised by AP */
+ t_u8 ap_country_str[3];
+ /** country string for this association */
+ t_u8 country_str[3];
+} mlan_interface_link_layer_info, *mlan_interface_handle;
+
+/** channel statistics */
+typedef struct {
+ /** channel */
+ wifi_channel_info channel;
+ /** msecs the radio is awake (32 bits number accruing over time) */
+ t_u32 on_time;
+ /** msecs the CCA register is busy (32 bits number accruing over time)
+ */
+ t_u32 cca_busy_time;
+} wifi_channel_stat;
+
+#define timeval_to_msec(timeval) \
+ (t_u64)((t_u64)(timeval.time_sec) * 1000 + \
+ (t_u64)(timeval.time_usec) / 1000)
+#define timeval_to_usec(timeval) \
+ (t_u64)((t_u64)(timeval.time_sec) * 1000 * 1000 + \
+ (t_u64)(timeval.time_usec))
+#define is_zero_timeval(timeval) \
+ ((timeval.time_sec == 0) && (timeval.time_usec == 0))
+
+/** radio statistics */
+typedef struct {
+ /** wifi radio (if multiple radio supported) */
+ int radio;
+ /** msecs the radio is awake (32 bits number accruing over time) */
+ t_u32 on_time;
+ /** msecs the radio is transmitting (32 bits number accruing over time)
+ */
+ t_u32 tx_time;
+ /** TBD: num_tx_levels: number of radio transmit power levels */
+ t_u32 reserved0;
+ /** TBD: tx_time_per_levels: pointer to an array of radio transmit per
+ * power levels in msecs accured over time */
+ /* t_u32 *reserved1;*/
+ /** msecs the radio is in active receive (32 bits number accruing over
+ * time) */
+ t_u32 rx_time;
+ /** msecs the radio is awake due to all scan (32 bits number accruing
+ * over time) */
+ t_u32 on_time_scan;
+ /** msecs the radio is awake due to NAN (32 bits number accruing over
+ * time) */
+ t_u32 on_time_nbd;
+ /** msecs the radio is awake due to G?scan (32 bits number accruing over
+ * time) */
+ t_u32 on_time_gscan;
+ /** msecs the radio is awake due to roam?scan (32 bits number accruing
+ * over time) */
+ t_u32 on_time_roam_scan;
+ /** msecs the radio is awake due to PNO scan (32 bits number accruing
+ * over time) */
+ t_u32 on_time_pno_scan;
+ /** msecs the radio is awake due to HS2.0 scans and GAS exchange (32
+ * bits number accruing over time) */
+ t_u32 on_time_hs20;
+ /** number of channels */
+ t_u32 num_channels;
+ /** channel statistics */
+ wifi_channel_stat channels[MAX_NUM_CHAN];
+} wifi_radio_stat;
+
+/** per rate statistics */
+typedef struct {
+ /** rate information */
+ wifi_rate rate;
+ /** number of successfully transmitted data pkts (ACK rcvd) */
+ t_u32 tx_mpdu;
+ /** number of received data pkts */
+ t_u32 rx_mpdu;
+ /** number of data packet losses (no ACK) */
+ t_u32 mpdu_lost;
+ /** total number of data pkt retries */
+ t_u32 retries;
+ /** number of short data pkt retries */
+ t_u32 retries_short;
+ /** number of long data pkt retries */
+ t_u32 retries_long;
+} wifi_rate_stat;
+
+/** wifi peer type */
+typedef enum {
+ WIFI_PEER_STA,
+ WIFI_PEER_AP,
+ WIFI_PEER_P2P_GO,
+ WIFI_PEER_P2P_CLIENT,
+ WIFI_PEER_NAN,
+ WIFI_PEER_TDLS,
+ WIFI_PEER_INVALID,
+} wifi_peer_type;
+
+/** per peer statistics */
+typedef struct {
+ /** peer type (AP, TDLS, GO etc.) */
+ wifi_peer_type type;
+ /** mac address */
+ t_u8 peer_mac_address[6];
+ /** peer WIFI_CAPABILITY_XXX */
+ t_u32 capabilities;
+ /** number of rates */
+ t_u32 num_rate;
+ /** per rate statistics, number of entries = num_rate */
+ wifi_rate_stat rate_stats[];
+} wifi_peer_info;
+
+/** per access category statistics */
+typedef struct {
+ /** access category (VI, VO, BE, BK) */
+ mlan_wmm_ac_e ac;
+ /** number of successfully transmitted unicast data pkts (ACK rcvd) */
+ t_u32 tx_mpdu;
+ /** number of received unicast mpdus */
+ t_u32 rx_mpdu;
+ /** number of succesfully transmitted multicast data packets */
+ /** STA case: implies ACK received from AP for the unicast packet in
+ * which mcast pkt was sent */
+ t_u32 tx_mcast;
+ /** number of received multicast data packets */
+ t_u32 rx_mcast;
+ /** number of received unicast a-mpdus */
+ t_u32 rx_ampdu;
+ /** number of transmitted unicast a-mpdus */
+ t_u32 tx_ampdu;
+ /** number of data pkt losses (no ACK) */
+ t_u32 mpdu_lost;
+ /** total number of data pkt retries */
+ t_u32 retries;
+ /** number of short data pkt retries */
+ t_u32 retries_short;
+ /** number of long data pkt retries */
+ t_u32 retries_long;
+ /** data pkt min contention time (usecs) */
+ t_u32 contention_time_min;
+ /** data pkt max contention time (usecs) */
+ t_u32 contention_time_max;
+ /** data pkt avg contention time (usecs) */
+ t_u32 contention_time_avg;
+ /** num of data pkts used for contention statistics */
+ t_u32 contention_num_samples;
+} wifi_wmm_ac_stat;
+
+/** interface statistics */
+typedef struct {
+ /** wifi interface */
+ /* wifi_interface_handle iface;*/
+ /** current state of the interface */
+ mlan_interface_link_layer_info info;
+ /** access point beacon received count from connected AP */
+ t_u32 beacon_rx;
+ /** Average beacon offset encountered (beacon_TSF - TBTT)
+ * the average_tsf_offset field is used so as to calculate the
+ * typical beacon contention time on the channel as well may be
+ * used to debug beacon synchronization and related power consumption
+ * issue
+ */
+ t_u64 average_tsf_offset;
+ /** indicate that this AP typically leaks packets beyond the driver
+ * guard time */
+ t_u32 leaky_ap_detected;
+ /** average number of frame leaked by AP after frame with PM bit set was
+ * ACK'ed by AP */
+ t_u32 leaky_ap_avg_num_frames_leaked;
+ /** Guard time currently in force (when implementing IEEE power
+ * management based on frame control PM bit), How long driver waits
+ * before shutting down the radio and after receiving an ACK for a data
+ * frame with PM bit set)
+ */
+ t_u32 leaky_ap_guard_time;
+ /** access point mgmt frames received count from connected AP (including
+ * Beacon) */
+ t_u32 mgmt_rx;
+ /** action frames received count */
+ t_u32 mgmt_action_rx;
+ /** action frames transmit count */
+ t_u32 mgmt_action_tx;
+ /** access Point Beacon and Management frames RSSI (averaged) */
+ t_s32 rssi_mgmt;
+ /** access Point Data Frames RSSI (averaged) from connected AP */
+ t_s32 rssi_data;
+ /** access Point ACK RSSI (averaged) from connected AP */
+ t_s32 rssi_ack;
+ /** per ac data packet statistics */
+ wifi_wmm_ac_stat ac[MAX_AC_QUEUES];
+ /** number of peers */
+ t_u32 num_peers;
+ /** per peer statistics */
+ wifi_peer_info peer_info[];
+} wifi_iface_stat;
+
+/** link layer stat configuration params */
+typedef struct {
+ /** threshold to classify the pkts as short or long */
+ t_u32 mpdu_size_threshold;
+ /** wifi statistics bitmap */
+ t_u32 aggressive_statistics_gathering;
+} wifi_link_layer_params;
+
+/** wifi statistics bitmap */
+#define WIFI_STATS_RADIO 0x00000001 /** all radio statistics */
+#define WIFI_STATS_RADIO_CCA \
+ 0x00000002 /** cca_busy_time (within radio statistics) */
+#define WIFI_STATS_RADIO_CHANNELS \
+ 0x00000004 /** all channel statistics (within radio statistics) */
+#define WIFI_STATS_RADIO_SCAN \
+ 0x00000008 /** all scan statistics (within radio statistics) */
+#define WIFI_STATS_IFACE 0x00000010 /** all interface statistics */
+#define WIFI_STATS_IFACE_TXRATE \
+ 0x00000020 /** all tx rate statistics (within interface statistics) */
+#define WIFI_STATS_IFACE_AC \
+ 0x00000040 /** all ac statistics (within interface statistics) */
+#define WIFI_STATS_IFACE_CONTENTION \
+ 0x00000080 /** all contention (min, max, avg) statistics (within ac \
+ statisctics) */
+
+/** station stats */
+typedef struct _sta_stats {
+ t_u64 last_rx_in_msec;
+} sta_stats;
+
+#ifdef PRAGMA_PACK
+#pragma pack(pop)
+#endif
+
+/** mlan_callbacks data structure */
+typedef struct _mlan_callbacks {
+ /** moal_get_fw_data */
+ mlan_status (*moal_get_fw_data)(t_void *pmoal_handle, t_u32 offset,
+ t_u32 len, t_u8 *pbuf);
+ mlan_status (*moal_get_vdll_data)(t_void *pmoal_handle, t_u32 len,
+ t_u8 *pbuf);
+ /** moal_get_hw_spec_complete */
+ mlan_status (*moal_get_hw_spec_complete)(t_void *pmoal_handle,
+ mlan_status status,
+ pmlan_hw_info phw,
+ pmlan_bss_tbl ptbl);
+ /** moal_init_fw_complete */
+ mlan_status (*moal_init_fw_complete)(t_void *pmoal_handle,
+ mlan_status status);
+ /** moal_shutdown_fw_complete */
+ mlan_status (*moal_shutdown_fw_complete)(t_void *pmoal_handle,
+ mlan_status status);
+ /** moal_send_packet_complete */
+ mlan_status (*moal_send_packet_complete)(t_void *pmoal_handle,
+ pmlan_buffer pmbuf,
+ mlan_status status);
+ /** moal_recv_complete */
+ mlan_status (*moal_recv_complete)(t_void *pmoal_handle,
+ pmlan_buffer pmbuf, t_u32 port,
+ mlan_status status);
+ /** moal_recv_packet */
+ mlan_status (*moal_recv_packet)(t_void *pmoal_handle,
+ pmlan_buffer pmbuf);
+ /** moal_recv_event */
+ mlan_status (*moal_recv_event)(t_void *pmoal_handle,
+ pmlan_event pmevent);
+ /** moal_ioctl_complete */
+ mlan_status (*moal_ioctl_complete)(t_void *pmoal_handle,
+ pmlan_ioctl_req pioctl_req,
+ mlan_status status);
+
+ /** moal_alloc_mlan_buffer */
+ mlan_status (*moal_alloc_mlan_buffer)(t_void *pmoal_handle, t_u32 size,
+ ppmlan_buffer pmbuf);
+ /** moal_free_mlan_buffer */
+ mlan_status (*moal_free_mlan_buffer)(t_void *pmoal_handle,
+ pmlan_buffer pmbuf);
+
+#ifdef USB
+ /** moal_write_data_async */
+ mlan_status (*moal_write_data_async)(t_void *pmoal_handle,
+ pmlan_buffer pmbuf, t_u32 port);
+#endif /* USB */
+#if defined(SDIO) || defined(PCIE)
+ /** moal_write_reg */
+ mlan_status (*moal_write_reg)(t_void *pmoal_handle, t_u32 reg,
+ t_u32 data);
+ /** moal_read_reg */
+ mlan_status (*moal_read_reg)(t_void *pmoal_handle, t_u32 reg,
+ t_u32 *data);
+#endif /* SDIO || PCIE */
+ /** moal_write_data_sync */
+ mlan_status (*moal_write_data_sync)(t_void *pmoal_handle,
+ pmlan_buffer pmbuf, t_u32 port,
+ t_u32 timeout);
+ /** moal_read_data_sync */
+ mlan_status (*moal_read_data_sync)(t_void *pmoal_handle,
+ pmlan_buffer pmbuf, t_u32 port,
+ t_u32 timeout);
+ /** moal_malloc */
+ mlan_status (*moal_malloc)(t_void *pmoal_handle, t_u32 size, t_u32 flag,
+ t_u8 **ppbuf);
+ /** moal_mfree */
+ mlan_status (*moal_mfree)(t_void *pmoal_handle, t_u8 *pbuf);
+ /** moal_vmalloc */
+ mlan_status (*moal_vmalloc)(t_void *pmoal_handle, t_u32 size,
+ t_u8 **ppbuf);
+ /** moal_vfree */
+ mlan_status (*moal_vfree)(t_void *pmoal_handle, t_u8 *pbuf);
+#ifdef PCIE
+ /** moal_malloc_consistent */
+ mlan_status (*moal_malloc_consistent)(t_void *pmoal_handle, t_u32 size,
+ t_u8 **ppbuf, t_u64 *pbuf_pa);
+ /** moal_mfree_consistent */
+ mlan_status (*moal_mfree_consistent)(t_void *pmoal_handle, t_u32 size,
+ t_u8 *pbuf, t_u64 buf_pa);
+ /** moal_map_memory */
+ mlan_status (*moal_map_memory)(t_void *pmoal_handle, t_u8 *pbuf,
+ t_u64 *pbuf_pa, t_u32 size, t_u32 flag);
+ /** moal_unmap_memory */
+ mlan_status (*moal_unmap_memory)(t_void *pmoal_handle, t_u8 *pbuf,
+ t_u64 buf_pa, t_u32 size, t_u32 flag);
+#endif /* PCIE */
+ /** moal_memset */
+ t_void *(*moal_memset)(t_void *pmoal_handle, t_void *pmem, t_u8 byte,
+ t_u32 num);
+ /** moal_memcpy */
+ t_void *(*moal_memcpy)(t_void *pmoal_handle, t_void *pdest,
+ const t_void *psrc, t_u32 num);
+ /** moal_memcpy_ext */
+ t_void *(*moal_memcpy_ext)(t_void *pmoal_handle, t_void *pdest,
+ const t_void *psrc, t_u32 num,
+ t_u32 dest_size);
+ /** moal_memmove */
+ t_void *(*moal_memmove)(t_void *pmoal_handle, t_void *pdest,
+ const t_void *psrc, t_u32 num);
+ /** moal_memcmp */
+ t_s32 (*moal_memcmp)(t_void *pmoal_handle, const t_void *pmem1,
+ const t_void *pmem2, t_u32 num);
+ /** moal_udelay */
+ t_void (*moal_udelay)(t_void *pmoal_handle, t_u32 udelay);
+ /** moal_usleep_range */
+ t_void (*moal_usleep_range)(t_void *pmoal_handle, t_u32 min_delay,
+ t_u32 max_delay);
+ /** moal_get_boot_ktime */
+ mlan_status (*moal_get_boot_ktime)(t_void *pmoal_handle, t_u64 *pnsec);
+ /** moal_get_system_time */
+ mlan_status (*moal_get_system_time)(t_void *pmoal_handle, t_u32 *psec,
+ t_u32 *pusec);
+ /** moal_init_timer*/
+ mlan_status (*moal_init_timer)(t_void *pmoal_handle, t_void **pptimer,
+ IN t_void (*callback)(t_void *pcontext),
+ t_void *pcontext);
+ /** moal_free_timer */
+ mlan_status (*moal_free_timer)(t_void *pmoal_handle, t_void *ptimer);
+ /** moal_start_timer*/
+ mlan_status (*moal_start_timer)(t_void *pmoal_handle, t_void *ptimer,
+ t_u8 periodic, t_u32 msec);
+ /** moal_stop_timer*/
+ mlan_status (*moal_stop_timer)(t_void *pmoal_handle, t_void *ptimer);
+ /** moal_init_lock */
+ mlan_status (*moal_init_lock)(t_void *pmoal_handle, t_void **pplock);
+ /** moal_free_lock */
+ mlan_status (*moal_free_lock)(t_void *pmoal_handle, t_void *plock);
+ /** moal_spin_lock */
+ mlan_status (*moal_spin_lock)(t_void *pmoal_handle, t_void *plock);
+ /** moal_spin_unlock */
+ mlan_status (*moal_spin_unlock)(t_void *pmoal_handle, t_void *plock);
+ /** moal_print */
+ t_void (*moal_print)(t_void *pmoal_handle, t_u32 level, char *pformat,
+ IN...);
+ /** moal_print_netintf */
+ t_void (*moal_print_netintf)(t_void *pmoal_handle, t_u32 bss_index,
+ t_u32 level);
+ /** moal_assert */
+ t_void (*moal_assert)(t_void *pmoal_handle, t_u32 cond);
+
+ /** moal_hist_data_add */
+ t_void (*moal_hist_data_add)(t_void *pmoal_handle, t_u32 bss_index,
+ t_u16 rx_rate, t_s8 snr, t_s8 nflr,
+ t_u8 antenna);
+#if defined(DRV_EMBEDDED_AUTHENTICATOR) || defined(DRV_EMBEDDED_SUPPLICANT)
+ mlan_status (*moal_wait_hostcmd_complete)(t_void *pmoal_handle,
+ t_u32 bss_index);
+ mlan_status (*moal_notify_hostcmd_complete)(t_void *pmoal_handle,
+ t_u32 bss_index);
+#endif
+ void (*moal_tp_accounting)(t_void *pmoal_handle, t_void *buf,
+ t_u32 drop_point);
+ void (*moal_tp_accounting_rx_param)(t_void *pmoal_handle,
+ unsigned int type,
+ unsigned int rsvd1);
+
+} mlan_callbacks, *pmlan_callbacks;
+
+/** Parameter unchanged, use MLAN default setting */
+#define ROBUSTCOEX_GPIO_UNCHANGED 0
+/** Parameter enabled, override MLAN default setting */
+#define ROBUSTCOEX_GPIO_CFG 1
+
+#if defined(SDIO)
+/** Interrupt Mode SDIO */
+#define INT_MODE_SDIO 0
+/** Interrupt Mode GPIO */
+#define INT_MODE_GPIO 1
+/** New mode: GPIO-1 as a duplicated signal of interrupt as appear of SDIO_DAT1
+ */
+#define GPIO_INT_NEW_MODE 255
+#endif
+
+/** Parameter unchanged, use MLAN default setting */
+#define MLAN_INIT_PARA_UNCHANGED 0
+/** Parameter enabled, override MLAN default setting */
+#define MLAN_INIT_PARA_ENABLED 1
+/** Parameter disabled, override MLAN default setting */
+#define MLAN_INIT_PARA_DISABLED 2
+
+/** Control bit for stream 2X2 */
+#define FEATURE_CTRL_STREAM_2X2 MBIT(0)
+/** Control bit for DFS support */
+#define FEATURE_CTRL_DFS_SUPPORT MBIT(1)
+#ifdef USB
+/** Control bit for winner check & not wait for FW ready event */
+#define FEATURE_CTRL_USB_NEW_INIT MBIT(2)
+#endif
+/** Default feature control */
+#define FEATURE_CTRL_DEFAULT 0xffffffff
+/** Check if stream 2X2 enabled */
+#define IS_STREAM_2X2(x) ((x)&FEATURE_CTRL_STREAM_2X2)
+/** Check if DFS support enabled */
+#define IS_DFS_SUPPORT(x) ((x)&FEATURE_CTRL_DFS_SUPPORT)
+#ifdef USB
+/** Check if winner check & not wait for FW ready event */
+#define IS_USB_NEW_INIT(x) ((x)&FEATURE_CTRL_USB_NEW_INIT)
+#endif
+
+/*
+#define DRV_MODE_NAN MBIT(4)
+#define DRV_MODE_11P MBIT(5)
+#define DRV_MODE_MAC80211 MBIT(6)
+#define DRV_MODE_DFS MBIT(7)*/
+#define DRV_MODE_MASK (MBIT(4) | MBIT(5) | MBIT(6) | MBIT(7))
+
+/** mlan_device data structure */
+typedef struct _mlan_device {
+ /** MOAL Handle */
+ t_void *pmoal_handle;
+ /** BSS Attributes */
+ mlan_bss_attr bss_attr[MLAN_MAX_BSS_NUM];
+ /** Callbacks */
+ mlan_callbacks callbacks;
+#ifdef MFG_CMD_SUPPORT
+ /** MFG mode */
+ t_u32 mfg_mode;
+#endif
+#if defined(SDIO)
+ /** SDIO interrupt mode (0: INT_MODE_SDIO, 1: INT_MODE_GPIO) */
+ t_u32 int_mode;
+ /** GPIO interrupt pin number */
+ t_u32 gpio_pin;
+#endif
+#ifdef DEBUG_LEVEL1
+ /** Driver debug bit masks */
+ t_u32 drvdbg;
+#endif
+ /** allocate fixed buffer size for scan beacon buffer*/
+ t_u32 fixed_beacon_buffer;
+ /** SDIO MPA Tx */
+ t_u32 mpa_tx_cfg;
+ /** SDIO MPA Rx */
+ t_u32 mpa_rx_cfg;
+#ifdef SDIO
+ /** SDIO Single port rx aggr */
+ t_u8 sdio_rx_aggr_enable;
+ /* see blk_queue_max_segment_size */
+ t_u32 max_seg_size;
+ /* see blk_queue_max_segments */
+ t_u16 max_segs;
+#endif
+ /** Auto deep sleep */
+ t_u32 auto_ds;
+ /** IEEE PS mode */
+ t_u32 ps_mode;
+ /** Max Tx buffer size */
+ t_u32 max_tx_buf;
+#if defined(STA_SUPPORT)
+ /** 802.11d configuration */
+ t_u32 cfg_11d;
+#endif
+ /** Feature control bitmask */
+ t_u32 feature_control;
+ /** enable/disable rx work */
+ t_u8 rx_work;
+ /** dev cap mask */
+ t_u32 dev_cap_mask;
+ /** oob independent reset */
+ t_u32 indrstcfg;
+ /** dtim interval */
+ t_u16 multi_dtim;
+ /** IEEE ps inactivity timeout value */
+ t_u16 inact_tmo;
+ /** card type */
+ t_u16 card_type;
+ /** card rev */
+ t_u8 card_rev;
+ /** Host sleep wakeup interval */
+ t_u32 hs_wake_interval;
+ /** GPIO to indicate wakeup source */
+ t_u8 indication_gpio;
+ /** Dynamic MIMO-SISO switch for hscfg*/
+ t_u8 hs_mimo_switch;
+#ifdef USB
+ /** Tx CMD endpoint address */
+ t_u8 tx_cmd_ep;
+ /** Rx CMD/EVT endpoint address */
+ t_u8 rx_cmd_ep;
+
+ /** Rx data endpoint address */
+ t_u8 rx_data_ep;
+ /** Tx data endpoint address */
+ t_u8 tx_data_ep;
+#endif
+ /** fw region */
+ t_bool fw_region;
+ /** passive to active scan */
+ t_u8 passive_to_active_scan;
+ /** uap max supported station per chip */
+ t_u8 uap_max_sta;
+ /** drv mode */
+ t_u32 drv_mode;
+ /** dfs w53 cfg */
+ t_u8 dfs53cfg;
+} mlan_device, *pmlan_device;
+
+/** MLAN API function prototype */
+#define MLAN_API
+
+/** Registration */
+MLAN_API mlan_status mlan_register(pmlan_device pmdevice,
+ t_void **ppmlan_adapter);
+
+/** Un-registration */
+MLAN_API mlan_status mlan_unregister(t_void *pmlan_adapter);
+
+/** Firmware Downloading */
+MLAN_API mlan_status mlan_dnld_fw(t_void *pmlan_adapter, pmlan_fw_image pmfw);
+
+/** Custom data pass API */
+MLAN_API mlan_status mlan_set_init_param(t_void *pmlan_adapter,
+ pmlan_init_param pparam);
+
+/** Firmware Initialization */
+MLAN_API mlan_status mlan_init_fw(t_void *pmlan_adapter);
+
+/** Firmware Shutdown */
+MLAN_API mlan_status mlan_shutdown_fw(t_void *pmlan_adapter);
+
+/** Main Process */
+MLAN_API mlan_status mlan_main_process(t_void *pmlan_adapter);
+
+/** Rx process */
+mlan_status mlan_rx_process(t_void *pmlan_adapter, t_u8 *rx_pkts);
+
+/** Packet Transmission */
+MLAN_API mlan_status mlan_send_packet(t_void *pmlan_adapter,
+ pmlan_buffer pmbuf);
+
+#ifdef USB
+/** mlan_write_data_async_complete */
+MLAN_API mlan_status mlan_write_data_async_complete(t_void *pmlan_adapter,
+ pmlan_buffer pmbuf,
+ t_u32 port,
+ mlan_status status);
+
+/** Packet Reception */
+MLAN_API mlan_status mlan_recv(t_void *pmlan_adapter, pmlan_buffer pmbuf,
+ t_u32 port);
+#endif /* USB */
+
+/** Packet Reception complete callback */
+MLAN_API mlan_status mlan_recv_packet_complete(t_void *pmlan_adapter,
+ pmlan_buffer pmbuf,
+ mlan_status status);
+
+#if defined(SDIO) || defined(PCIE)
+/** interrupt handler */
+MLAN_API mlan_status mlan_interrupt(t_u16 msg_id, t_void *pmlan_adapter);
+
+#if defined(SYSKT)
+/** GPIO IRQ callback function */
+MLAN_API t_void mlan_hs_callback(t_void *pctx);
+#endif /* SYSKT_MULTI || SYSKT */
+#endif /* SDIO || PCIE */
+
+MLAN_API t_void mlan_pm_wakeup_card(t_void *pmlan_adapter, t_u8 keep_wakeup);
+
+MLAN_API t_u8 mlan_is_main_process_running(t_void *adapter);
+#ifdef PCIE
+MLAN_API t_void mlan_set_int_mode(t_void *adapter, t_u32 int_mode,
+ t_u8 func_num);
+#endif
+/** mlan ioctl */
+MLAN_API mlan_status mlan_ioctl(t_void *pmlan_adapter,
+ pmlan_ioctl_req pioctl_req);
+/** mlan select wmm queue */
+MLAN_API t_u8 mlan_select_wmm_queue(t_void *pmlan_adapter, t_u8 bss_num,
+ t_u8 tid);
+
+#endif /* !_MLAN_DECL_H_ */
diff --git a/drivers/net/wireless/nxp/mxm_wifiex/wlan_src/mlan/mlan_fw.h b/drivers/net/wireless/nxp/mxm_wifiex/wlan_src/mlan/mlan_fw.h
new file mode 100644
index 000000000000..2011e2459f07
--- /dev/null
+++ b/drivers/net/wireless/nxp/mxm_wifiex/wlan_src/mlan/mlan_fw.h
@@ -0,0 +1,7410 @@
+/** @file mlan_fw.h
+ *
+ * @brief This file contains firmware specific defines.
+ * structures and declares global function prototypes used
+ * in MLAN module.
+ *
+ *
+ * Copyright 2014-2020 NXP
+ *
+ * This software file (the File) is distributed by NXP
+ * under the terms of the GNU General Public License Version 2, June 1991
+ * (the License). You may use, redistribute and/or modify the 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.
+ *
+ */
+
+/******************************************************
+Change log:
+ 10/27/2008: initial version
+******************************************************/
+
+#ifndef _MLAN_FW_H_
+#define _MLAN_FW_H_
+
+/** Interface header length */
+#ifdef USB
+#define USB_INTF_HEADER_LEN 0
+#endif /* USB */
+#ifdef SDIO
+#define SDIO_INTF_HEADER_LEN 4
+#endif /* SDIO */
+#ifdef PCIE
+#define PCIE_INTF_HEADER_LEN 4
+#endif /* PCIE */
+
+#ifdef PRAGMA_PACK
+#pragma pack(push, 1)
+#endif
+
+#define WPA_GCMP_KEY_LEN 32
+
+#define WPA_CCMP_256_KEY_LEN 32
+
+/** Ethernet header */
+typedef MLAN_PACK_START struct {
+ /** Ethernet header destination address */
+ t_u8 dest_addr[MLAN_MAC_ADDR_LENGTH];
+ /** Ethernet header source address */
+ t_u8 src_addr[MLAN_MAC_ADDR_LENGTH];
+ /** Ethernet header length */
+ t_u16 h803_len;
+
+} MLAN_PACK_END Eth803Hdr_t;
+
+/** RFC 1042 header */
+typedef MLAN_PACK_START struct {
+ /** LLC DSAP */
+ t_u8 llc_dsap;
+ /** LLC SSAP */
+ t_u8 llc_ssap;
+ /** LLC CTRL */
+ t_u8 llc_ctrl;
+ /** SNAP OUI */
+ t_u8 snap_oui[3];
+ /** SNAP type */
+ t_u16 snap_type;
+
+} MLAN_PACK_END Rfc1042Hdr_t;
+
+/** Rx packet header */
+typedef MLAN_PACK_START struct {
+ /** Etherner header */
+ Eth803Hdr_t eth803_hdr;
+ /** RFC 1042 header */
+ Rfc1042Hdr_t rfc1042_hdr;
+
+} MLAN_PACK_END RxPacketHdr_t;
+
+/** Rates supported in band B */
+#define B_SUPPORTED_RATES 5
+/** Rates supported in band G */
+#define G_SUPPORTED_RATES 9
+/** Rates supported in band BG */
+#define BG_SUPPORTED_RATES 13
+
+/** Setup the number of rates passed in the driver/firmware API */
+#define A_SUPPORTED_RATES 9
+
+/** CapInfo Short Slot Time Disabled */
+/* #define SHORT_SLOT_TIME_DISABLED(CapInfo)
+ * ((IEEEtypes_CapInfo_t)(CapInfo).short_slot_time = 0) */
+#define SHORT_SLOT_TIME_DISABLED(CapInfo) (CapInfo &= ~MBIT(10))
+/** CapInfo Short Slot Time Enabled */
+#define SHORT_SLOT_TIME_ENABLED(CapInfo) (CapInfo |= MBIT(10))
+/** CapInfo Spectrum Mgmt Disabled */
+#define SPECTRUM_MGMT_DISABLED(CapInfo) (CapInfo &= ~MBIT(8))
+/** CapInfo Spectrum Mgmt Enabled */
+#define SPECTRUM_MGMT_ENABLED(CapInfo) (CapInfo |= MBIT(8))
+/** CapInfo Radio Measurement Disabled */
+#define RADIO_MEASUREMENT_DISABLED(CapInfo) (CapInfo &= ~MBIT(12))
+/** CapInfo Radio Measurement Enabled */
+#define RADIO_MEASUREMENT_ENABLED(CapInfo) (CapInfo |= MBIT(12))
+
+/** Setup the number of rates passed in the driver/firmware API */
+#define HOSTCMD_SUPPORTED_RATES 14
+
+/** Rates supported in band N */
+#define N_SUPPORTED_RATES 3
+#ifdef STA_SUPPORT
+/** All bands (B, G, N, AAC, GAC) */
+#define ALL_802_11_BANDS \
+ (BAND_A | BAND_B | BAND_G | BAND_GN | BAND_AAC | BAND_GAC)
+#else
+/** All bands (B, G, A) */
+#define ALL_802_11_BANDS (BAND_B | BAND_G | BAND_A)
+#endif /* STA_SUPPORT */
+
+#ifdef STA_SUPPORT
+/** Firmware multiple bands support */
+#define FW_MULTI_BANDS_SUPPORT \
+ (MBIT(8) | MBIT(9) | MBIT(10) | MBIT(11) | MBIT(12) | MBIT(13))
+#else
+/** Firmware multiple bands support */
+#define FW_MULTI_BANDS_SUPPORT (MBIT(8) | MBIT(9) | MBIT(10))
+#endif /* STA_SUPPORT */
+/** Check if multiple bands support is enabled in firmware */
+#define IS_SUPPORT_MULTI_BANDS(_adapter) \
+ (_adapter->fw_cap_info & FW_MULTI_BANDS_SUPPORT)
+/** Get default bands of the firmware */
+/* need to shift bit 12 and bit 13 in fw_cap_info from the firmware
+ * to bit 13 and 14 for 11ac so that bit 11 is for GN, bit 12 for AN,
+ * bit 13 for GAC, and bit 14 for AAC, in order to be compatible with
+ * the band capability defined in the driver after right shift of 8 bits */
+#define GET_FW_DEFAULT_BANDS(_adapter) \
+ (((((_adapter->fw_cap_info & 0x3000) << 1) | \
+ (_adapter->fw_cap_info & ~0xF000)) >> \
+ 8) & \
+ ALL_802_11_BANDS)
+
+extern t_u8 SupportedRates_B[B_SUPPORTED_RATES];
+extern t_u8 SupportedRates_G[G_SUPPORTED_RATES];
+extern t_u8 SupportedRates_BG[BG_SUPPORTED_RATES];
+extern t_u8 SupportedRates_A[A_SUPPORTED_RATES];
+extern t_u8 SupportedRates_N[N_SUPPORTED_RATES];
+extern t_u8 AdhocRates_G[G_SUPPORTED_RATES];
+extern t_u8 AdhocRates_B[B_SUPPORTED_RATES];
+extern t_u8 AdhocRates_BG[BG_SUPPORTED_RATES];
+extern t_u8 AdhocRates_A[A_SUPPORTED_RATES];
+
+/** Default auto deep sleep mode */
+#define DEFAULT_AUTO_DS_MODE MTRUE
+/** Default power save mode */
+#define DEFAULT_PS_MODE Wlan802_11PowerModePSP
+
+/** WEP Key index mask */
+#define HostCmd_WEP_KEY_INDEX_MASK 0x3fff
+/** Length of WEP 40 bit key */
+#define WEP_40_BIT_LEN 5
+/** Length of WEP 104 bit key */
+#define WEP_104_BIT_LEN 13
+
+/** Key information enabled */
+#define KEY_INFO_ENABLED 0x01
+/** KEY_TYPE_ID */
+typedef enum _KEY_TYPE_ID {
+ /** Key type : WEP */
+ KEY_TYPE_ID_WEP = 0,
+ /** Key type : TKIP */
+ KEY_TYPE_ID_TKIP = 1,
+ /** Key type : AES */
+ KEY_TYPE_ID_AES = 2,
+ KEY_TYPE_ID_WAPI = 3,
+ KEY_TYPE_ID_AES_CMAC = 4,
+ /** Key type : GCMP */
+ KEY_TYPE_ID_GCMP = 5,
+ /** Key type : GCMP_256 */
+ KEY_TYPE_ID_GCMP_256 = 6,
+ /** Key type : CCMP_256 */
+ KEY_TYPE_ID_CCMP_256 = 7,
+} KEY_TYPE_ID;
+
+/** Key Info flag for multicast key */
+#define KEY_INFO_MCAST_KEY 0x01
+/** Key Info flag for unicast key */
+#define KEY_INFO_UCAST_KEY 0x02
+
+/** KEY_INFO_WEP*/
+typedef enum _KEY_INFO_WEP {
+ KEY_INFO_WEP_MCAST = 0x01,
+ KEY_INFO_WEP_UNICAST = 0x02,
+ KEY_INFO_WEP_ENABLED = 0x04
+} KEY_INFO_WEP;
+
+/** KEY_INFO_TKIP */
+typedef enum _KEY_INFO_TKIP {
+ KEY_INFO_TKIP_MCAST = 0x01,
+ KEY_INFO_TKIP_UNICAST = 0x02,
+ KEY_INFO_TKIP_ENABLED = 0x04
+} KEY_INFO_TKIP;
+
+/** KEY_INFO_AES*/
+typedef enum _KEY_INFO_AES {
+ KEY_INFO_AES_MCAST = 0x01,
+ KEY_INFO_AES_UNICAST = 0x02,
+ KEY_INFO_AES_ENABLED = 0x04,
+ KEY_INFO_AES_MCAST_IGTK = 0x400,
+} KEY_INFO_AES;
+
+/** WPA AES key length */
+#define WPA_AES_KEY_LEN 16
+/** WPA TKIP key length */
+#define WPA_TKIP_KEY_LEN 32
+/** WPA AES IGTK key length */
+#define CMAC_AES_KEY_LEN 16
+/** IGTK key length */
+#define WPA_IGTK_KEY_LEN 16
+
+/** WAPI key length */
+#define WAPI_KEY_LEN 50
+/** KEY_INFO_WAPI*/
+typedef enum _KEY_INFO_WAPI {
+ KEY_INFO_WAPI_MCAST = 0x01,
+ KEY_INFO_WAPI_UNICAST = 0x02,
+ KEY_INFO_WAPI_ENABLED = 0x04
+} KEY_INFO_WAPI;
+
+/** Maximum ethernet frame length sans FCS */
+#define MV_ETH_FRAME_LEN 1514
+
+#if defined(SDIO) || defined(PCIE)
+/** Length of SNAP header */
+#define MRVDRV_SNAP_HEADER_LEN 8
+
+/** The number of times to try when polling for status bits */
+#define MAX_POLL_TRIES 100
+
+/** The number of times to try when waiting for downloaded firmware to
+ become active when multiple interface is present */
+#define MAX_MULTI_INTERFACE_POLL_TRIES 150
+/** The number of times to try when waiting for downloaded firmware to
+ become active. (polling the scratch register). */
+#define MAX_FIRMWARE_POLL_TRIES 100
+
+/** FW fill in rx_len with extra 204 bytes */
+#define EXTRA_LEN 256
+
+/** Buffer size for ethernet Tx packets */
+#define MRVDRV_ETH_TX_PACKET_BUFFER_SIZE \
+ (MV_ETH_FRAME_LEN + sizeof(TxPD) + EXTRA_LEN)
+
+/** Buffer size for ethernet Rx packets */
+#define MRVDRV_ETH_RX_PACKET_BUFFER_SIZE \
+ (MV_ETH_FRAME_LEN + sizeof(RxPD) + MRVDRV_SNAP_HEADER_LEN + EXTRA_LEN)
+#endif /* SDIO || PCIE */
+
+#ifdef SDIO
+/* Macros in interface module */
+/** Firmware ready */
+#define SDIO_FIRMWARE_READY 0xfedc
+#endif /* SDIO */
+
+#ifdef PCIE
+/* Macros in interface module */
+/** Firmware ready */
+#define PCIE_FIRMWARE_READY 0xfedcba00
+#endif
+
+/** Enumeration definition*/
+/** WLAN_802_11_PRIVACY_FILTER */
+typedef enum _WLAN_802_11_PRIVACY_FILTER {
+ Wlan802_11PrivFilterAcceptAll,
+ Wlan802_11PrivFilter8021xWEP
+} WLAN_802_11_PRIVACY_FILTER;
+
+/** WLAN_802_11_WEP_STATUS */
+typedef enum _WLAN_802_11_WEP_STATUS {
+ Wlan802_11WEPEnabled,
+ Wlan802_11WEPDisabled,
+ Wlan802_11WEPKeyAbsent,
+ Wlan802_11WEPNotSupported
+} WLAN_802_11_WEP_STATUS;
+
+/** SNR calculation */
+#define CAL_SNR(RSSI, NF) ((t_s16)((t_s16)(RSSI) - (t_s16)(NF)))
+
+/** 2K buf size */
+#define MLAN_TX_DATA_BUF_SIZE_2K 2048
+
+/** Terminating TLV Type */
+#define MRVL_TERMINATE_TLV_ID 0xffff
+
+/** TLV type : SSID */
+#define TLV_TYPE_SSID 0x0000
+/** TLV type : Rates */
+#define TLV_TYPE_RATES 0x0001
+/** TLV type : PHY FH */
+#define TLV_TYPE_PHY_FH 0x0002
+/** TLV type : PHY DS */
+#define TLV_TYPE_PHY_DS 0x0003
+/** TLV type : CF */
+#define TLV_TYPE_CF 0x0004
+/** TLV type : IBSS */
+#define TLV_TYPE_IBSS 0x0006
+
+/** TLV type : Domain */
+#define TLV_TYPE_DOMAIN 0x0007
+
+/** TLV type : Power constraint */
+#define TLV_TYPE_POWER_CONSTRAINT 0x0020
+
+/** TLV type : Power capability */
+#define TLV_TYPE_POWER_CAPABILITY 0x0021
+
+#define TLV_TYPE_HT_CAPABILITY 0x002d
+
+#define TLV_TYPE_EXTENSION_ID 0x00ff
+
+/**TLV type : Host MLME Flag*/
+#define TLV_TYPE_HOST_MLME (PROPRIETARY_TLV_BASE_ID + 307)
+
+/** TLV type : Vendor Specific IE */
+#define TLV_TYPE_VENDOR_SPECIFIC_IE 0x00dd
+
+/** TLV type : Key material */
+#define TLV_TYPE_KEY_MATERIAL (PROPRIETARY_TLV_BASE_ID + 0x00) /* 0x0100 */
+/** TLV type : Channel list */
+#define TLV_TYPE_CHANLIST (PROPRIETARY_TLV_BASE_ID + 0x01) /* 0x0101 */
+/** TLV type : Number of probes */
+#define TLV_TYPE_NUMPROBES (PROPRIETARY_TLV_BASE_ID + 0x02) /* 0x0102 */
+/** TLV type : Beacon RSSI low */
+#define TLV_TYPE_RSSI_LOW (PROPRIETARY_TLV_BASE_ID + 0x04) /* 0x0104 */
+/** TLV type : Beacon SNR low */
+#define TLV_TYPE_SNR_LOW (PROPRIETARY_TLV_BASE_ID + 0x05) /* 0x0105 */
+/** TLV type : Fail count */
+#define TLV_TYPE_FAILCOUNT (PROPRIETARY_TLV_BASE_ID + 0x06) /* 0x0106 */
+/** TLV type : BCN miss */
+#define TLV_TYPE_BCNMISS (PROPRIETARY_TLV_BASE_ID + 0x07) /* 0x0107 */
+/** TLV type : LED behavior */
+#define TLV_TYPE_LEDBEHAVIOR (PROPRIETARY_TLV_BASE_ID + 0x09) /* 0x0109 */
+/** TLV type : Passthrough */
+#define TLV_TYPE_PASSTHROUGH (PROPRIETARY_TLV_BASE_ID + 0x0a) /* 0x010a */
+/** TLV type : Power TBL 2.4 Ghz */
+#define TLV_TYPE_POWER_TBL_2_4GHZ \
+ (PROPRIETARY_TLV_BASE_ID + 0x0c) /* 0x010c \
+ */
+/** TLV type : Power TBL 5 GHz */
+#define TLV_TYPE_POWER_TBL_5GHZ (PROPRIETARY_TLV_BASE_ID + 0x0d) /* 0x010d */
+/** TLV type : WMM queue status */
+#define TLV_TYPE_WMMQSTATUS (PROPRIETARY_TLV_BASE_ID + 0x10) /* 0x0110 */
+/** TLV type : Wildcard SSID */
+#define TLV_TYPE_WILDCARDSSID (PROPRIETARY_TLV_BASE_ID + 0x12) /* 0x0112 */
+/** TLV type : TSF timestamp */
+#define TLV_TYPE_TSFTIMESTAMP (PROPRIETARY_TLV_BASE_ID + 0x13) /* 0x0113 */
+/** TLV type : Beacon RSSI high */
+#define TLV_TYPE_RSSI_HIGH (PROPRIETARY_TLV_BASE_ID + 0x16) /* 0x0116 */
+/** TLV type : Beacon SNR high */
+#define TLV_TYPE_SNR_HIGH (PROPRIETARY_TLV_BASE_ID + 0x17) /* 0x0117 */
+/** TLV type : Start BG scan later */
+#define TLV_TYPE_STARTBGSCANLATER \
+ (PROPRIETARY_TLV_BASE_ID + 0x1e) /* 0x011e \
+ */
+/** TLV type: BG scan repeat count */
+#define TLV_TYPE_REPEAT_COUNT (PROPRIETARY_TLV_BASE_ID + 0xb0) /* 0x01b0 */
+/** TLV type : Authentication type */
+#define TLV_TYPE_AUTH_TYPE (PROPRIETARY_TLV_BASE_ID + 0x1f) /* 0x011f */
+/** TLV type : BSSID */
+#define TLV_TYPE_BSSID (PROPRIETARY_TLV_BASE_ID + 0x23) /* 0x0123 */
+
+/** TLV type : Link Quality */
+#define TLV_TYPE_LINK_QUALITY (PROPRIETARY_TLV_BASE_ID + 0x24) /* 0x0124 */
+
+/** TLV type : Data RSSI low */
+#define TLV_TYPE_RSSI_LOW_DATA (PROPRIETARY_TLV_BASE_ID + 0x26) /* 0x0126 */
+/** TLV type : Data SNR low */
+#define TLV_TYPE_SNR_LOW_DATA (PROPRIETARY_TLV_BASE_ID + 0x27) /* 0x0127 */
+/** TLV type : Data RSSI high */
+#define TLV_TYPE_RSSI_HIGH_DATA (PROPRIETARY_TLV_BASE_ID + 0x28) /* 0x0128 */
+/** TLV type : Data SNR high */
+#define TLV_TYPE_SNR_HIGH_DATA (PROPRIETARY_TLV_BASE_ID + 0x29) /* 0x0129 */
+
+/** TLV type : Channel band list */
+#define TLV_TYPE_CHANNELBANDLIST (PROPRIETARY_TLV_BASE_ID + 0x2a) /* 0x012a */
+
+/** TLV type : Security Cfg */
+#define TLV_TYPE_SECURITY_CFG (PROPRIETARY_TLV_BASE_ID + 0x3a) /* 0x013a */
+
+/** TLV type : Passphrase */
+#define TLV_TYPE_PASSPHRASE (PROPRIETARY_TLV_BASE_ID + 0x3c) /* 0x013c */
+/** TLV type : SAE Password */
+#define TLV_TYPE_SAE_PASSWORD (PROPRIETARY_TLV_BASE_ID + 0x141) /* 0x0241 */
+/** TLV type : Encryption Protocol TLV */
+#define TLV_TYPE_ENCRYPTION_PROTO \
+ (PROPRIETARY_TLV_BASE_ID + 0x40) /* 0x0140 \
+ */
+/** TLV type : Cipher TLV */
+#define TLV_TYPE_CIPHER (PROPRIETARY_TLV_BASE_ID + 0x42) /* 0x0142 */
+/** TLV type : PMK */
+#define TLV_TYPE_PMK (PROPRIETARY_TLV_BASE_ID + 0x44) /* 0x0144 */
+
+/** TLV type : BCN miss */
+#define TLV_TYPE_PRE_BCNMISS (PROPRIETARY_TLV_BASE_ID + 0x49) /* 0x0149 */
+
+/** TLV type: WAPI IE */
+#define TLV_TYPE_WAPI_IE (PROPRIETARY_TLV_BASE_ID + 0x5e) /* 0x015e */
+
+/** TLV type: MGMT IE */
+#define TLV_TYPE_MGMT_IE (PROPRIETARY_TLV_BASE_ID + 0x69) /* 0x0169 */
+/** TLV type: MAX_MGMT_IE */
+#define TLV_TYPE_MAX_MGMT_IE (PROPRIETARY_TLV_BASE_ID + 0xaa) /* 0x01aa */
+
+/** TLV type: key param v2 */
+#define TLV_TYPE_KEY_PARAM_V2 (PROPRIETARY_TLV_BASE_ID + 0x9C) /* 0x019C */
+
+/** TLV type: ps params in hs */
+#define TLV_TYPE_PS_PARAMS_IN_HS (PROPRIETARY_TLV_BASE_ID + 0xB5) /* 0x01b5 */
+/** TLV type: hs wake hold off */
+#define TLV_TYPE_HS_WAKE_HOLDOFF (PROPRIETARY_TLV_BASE_ID + 0xB6) /* 0x01b6 */
+/** TLV type: wake up source */
+#define TLV_TYPE_HS_WAKEUP_SOURCE_GPIO \
+ (PROPRIETARY_TLV_BASE_ID + 0x105) /* 0x0205 */
+/** TLV type: management filter */
+#define TLV_TYPE_MGMT_FRAME_WAKEUP \
+ (PROPRIETARY_TLV_BASE_ID + 0x116) /* 0x0216 */
+/** TLV type: extend wakeup source */
+#define TLV_TYPE_WAKEUP_EXTEND (PROPRIETARY_TLV_BASE_ID + 0x118) /* 0x0218 */
+/** TLV type: HS antenna mode */
+#define TLV_TYPE_HS_ANTMODE (PROPRIETARY_TLV_BASE_ID + 0x119) /* 0x0219 */
+
+/** TLV type: robustcoex mode */
+#define TLV_TYPE_ROBUSTCOEX (PROPRIETARY_TLV_BASE_ID + 0x11B) /* 0x021B */
+
+#define TLV_TYPE_DMCS_STATUS (PROPRIETARY_TLV_BASE_ID + 0x13A) /* 0x023A */
+
+/** TLV type : HT Capabilities */
+#define TLV_TYPE_HT_CAP (PROPRIETARY_TLV_BASE_ID + 0x4a) /* 0x014a */
+/** TLV type : HT Information */
+#define TLV_TYPE_HT_INFO (PROPRIETARY_TLV_BASE_ID + 0x4b) /* 0x014b */
+/** TLV type : Secondary Channel Offset */
+#define TLV_SECONDARY_CHANNEL_OFFSET \
+ (PROPRIETARY_TLV_BASE_ID + 0x4c) /* 0x014c */
+/** TLV type : 20/40 BSS Coexistence */
+#define TLV_TYPE_2040BSS_COEXISTENCE \
+ (PROPRIETARY_TLV_BASE_ID + 0x4d) /* 0x014d */
+/** TLV type : Overlapping BSS Scan Parameters */
+#define TLV_TYPE_OVERLAP_BSS_SCAN_PARAM \
+ (PROPRIETARY_TLV_BASE_ID + 0x4e) /* 0x014e */
+/** TLV type : Extended capabilities */
+#define TLV_TYPE_EXTCAP (PROPRIETARY_TLV_BASE_ID + 0x4f) /* 0x014f */
+/** TLV type : Set of MCS values that STA desires to use within the BSS */
+#define TLV_TYPE_HT_OPERATIONAL_MCS_SET \
+ (PROPRIETARY_TLV_BASE_ID + 0x50) /* 0x0150 */
+/** TLV ID : Management Frame */
+#define TLV_TYPE_MGMT_FRAME (PROPRIETARY_TLV_BASE_ID + 0x68) /* 0x0168 */
+/** TLV type : RXBA_SYNC */
+#define TLV_TYPE_RXBA_SYNC (PROPRIETARY_TLV_BASE_ID + 0x99) /* 0x0199 */
+
+#ifdef WIFI_DIRECT_SUPPORT
+/** TLV type : AP PSK */
+#define TLV_TYPE_UAP_PSK (PROPRIETARY_TLV_BASE_ID + 0xa8) /* 0x01a8 */
+/** TLV type : p2p NOA */
+#define TLV_TYPE_WIFI_DIRECT_NOA (PROPRIETARY_TLV_BASE_ID + 0x83)
+/** TLV type : p2p opp ps */
+#define TLV_TYPE_WIFI_DIRECT_OPP_PS (PROPRIETARY_TLV_BASE_ID + 0x84)
+#endif /* WIFI_DIRECT_SUPPORT */
+
+/** TLV : 20/40 coex config */
+#define TLV_TYPE_2040_BSS_COEX_CONTROL \
+ (PROPRIETARY_TLV_BASE_ID + 0x98) /* 0x0198 */
+
+/** TLV type : aggr win size */
+#define TLV_BTCOEX_WL_AGGR_WINSIZE (PROPRIETARY_TLV_BASE_ID + 0xca)
+/** TLV type : scan time */
+#define TLV_BTCOEX_WL_SCANTIME (PROPRIETARY_TLV_BASE_ID + 0Xcb)
+/** TLV type : Ewpa_eapol_pkt */
+#define TLV_TYPE_EAPOL_PKT (PROPRIETARY_TLV_BASE_ID + 0xcf)
+
+#define TLV_TYPE_COALESCE_RULE (PROPRIETARY_TLV_BASE_ID + 0x9a)
+
+/** TLV type : EES Configuration */
+#define TLV_TYPE_EES_CFG (PROPRIETARY_TLV_BASE_ID + 0xda)
+/** TLV type : EES Network Configuration */
+#define TLV_TYPE_EES_NET_CFG (PROPRIETARY_TLV_BASE_ID + 0xdb)
+
+#define TLV_TYPE_LL_STAT_IFACE (PROPRIETARY_TLV_BASE_ID + 300)
+#define TLV_TYPE_LL_STAT_RADIO (PROPRIETARY_TLV_BASE_ID + 301)
+
+/** TLV type: fw cap info */
+#define TLV_TYPE_FW_CAP_INFO (PROPRIETARY_TLV_BASE_ID + 318)
+
+/** ADDBA TID mask */
+#define ADDBA_TID_MASK (MBIT(2) | MBIT(3) | MBIT(4) | MBIT(5))
+/** DELBA TID mask */
+#define DELBA_TID_MASK (MBIT(12) | MBIT(13) | MBIT(14) | MBIT(15))
+/** ADDBA Starting Sequence Number Mask */
+#define SSN_MASK 0xfff0
+
+/** Block Ack result status */
+/** Block Ack Result : Success */
+#define BA_RESULT_SUCCESS 0x0
+/** Block Ack Result : Execution failure */
+#define BA_RESULT_FAILURE 0x1
+/** Block Ack Result : Timeout */
+#define BA_RESULT_TIMEOUT 0x2
+/** Block Ack Result : Data invalid */
+#define BA_RESULT_DATA_INVALID 0x3
+
+/** Get the baStatus (NOT_SETUP, COMPLETE, IN_PROGRESS)
+ * in Tx BA stream table */
+#define IS_BASTREAM_SETUP(ptr) (ptr->ba_status)
+
+/** An AMPDU/AMSDU could be disallowed for certain TID. 0xff means
+ * no aggregation is enabled for the assigned TID */
+#define BA_STREAM_NOT_ALLOWED 0xff
+
+#ifdef STA_SUPPORT
+#endif
+
+/** Test if 11n is enabled by checking the HTCap IE */
+#define IS_11N_ENABLED(priv) \
+ ((priv->config_bands & BAND_GN || priv->config_bands & BAND_AN) && \
+ priv->curr_bss_params.bss_descriptor.pht_cap && \
+ !priv->curr_bss_params.bss_descriptor.disable_11n)
+/** Find out if we are the initiator or not */
+#define INITIATOR_BIT(DelBAParamSet) \
+ (((DelBAParamSet)&MBIT(DELBA_INITIATOR_POS)) >> DELBA_INITIATOR_POS)
+
+/** 4K buf size */
+#define MLAN_TX_DATA_BUF_SIZE_4K 4096
+/** 8K buf size */
+#define MLAN_TX_DATA_BUF_SIZE_8K 8192
+/** 12K buf size */
+#define MLAN_TX_DATA_BUF_SIZE_12K 12288
+/** Max Rx AMPDU Size */
+#define MAX_RX_AMPDU_SIZE_64K 0x03
+/** Non green field station */
+#define NON_GREENFIELD_STAS 0x04
+
+/** Greenfield support */
+#define HWSPEC_GREENFIELD_SUPP MBIT(29)
+/** RX STBC support */
+#define HWSPEC_RXSTBC_SUPP MBIT(26)
+/** ShortGI @ 40Mhz support */
+#define HWSPEC_SHORTGI40_SUPP MBIT(24)
+/** ShortGI @ 20Mhz support */
+#define HWSPEC_SHORTGI20_SUPP MBIT(23)
+/** RX LDPC support */
+#define HWSPEC_LDPC_SUPP MBIT(22)
+/** Channel width 40Mhz support */
+#define HWSPEC_CHANBW40_SUPP MBIT(17)
+/** 40Mhz intolarent enable */
+#define CAPINFO_40MHZ_INTOLARENT MBIT(8)
+
+/** Default 11n capability mask for 2.4GHz */
+#define DEFAULT_11N_CAP_MASK_BG \
+ (HWSPEC_SHORTGI20_SUPP | HWSPEC_RXSTBC_SUPP | HWSPEC_LDPC_SUPP)
+/** Default 11n capability mask for 5GHz */
+#define DEFAULT_11N_CAP_MASK_A \
+ (HWSPEC_CHANBW40_SUPP | HWSPEC_SHORTGI20_SUPP | \
+ HWSPEC_SHORTGI40_SUPP | HWSPEC_RXSTBC_SUPP | HWSPEC_LDPC_SUPP)
+
+/** Default 11n TX BF capability 2X2 chip **/
+#define DEFAULT_11N_TX_BF_CAP_2X2 0x19E74618
+/** Default 11n TX BF capability 1X1 chip **/
+#define DEFAULT_11N_TX_BF_CAP_1X1 0x19E74608
+
+/** Bits to ignore in hw_dev_cap as these bits are set in get_hw_spec */
+#define IGN_HW_DEV_CAP (CAPINFO_40MHZ_INTOLARENT)
+
+/** HW_SPEC FwCapInfo */
+#define ISSUPP_11NENABLED(FwCapInfo) (FwCapInfo & MBIT(11))
+
+/** HW_SPEC Dot11nDevCap : MAX AMSDU supported */
+#define ISSUPP_MAXAMSDU(Dot11nDevCap) (Dot11nDevCap & MBIT(31))
+/** HW_SPEC Dot11nDevCap : Beamforming support */
+#define ISSUPP_BEAMFORMING(Dot11nDevCap) (Dot11nDevCap & MBIT(30))
+/** HW_SPEC Dot11nDevCap : Green field support */
+#define ISSUPP_GREENFIELD(Dot11nDevCap) (Dot11nDevCap & MBIT(29))
+/** HW_SPEC Dot11nDevCap : AMPDU support */
+#define ISSUPP_AMPDU(Dot11nDevCap) (Dot11nDevCap & MBIT(28))
+/** HW_SPEC Dot11nDevCap : MIMO PS support */
+#define ISSUPP_MIMOPS(Dot11nDevCap) (Dot11nDevCap & MBIT(27))
+/** HW_SPEC Dot11nDevCap : Rx STBC support */
+#define ISSUPP_RXSTBC(Dot11nDevCap) (Dot11nDevCap & MBIT(26))
+/** HW_SPEC Dot11nDevCap : Tx STBC support */
+#define ISSUPP_TXSTBC(Dot11nDevCap) (Dot11nDevCap & MBIT(25))
+/** HW_SPEC Dot11nDevCap : Short GI @ 40Mhz support */
+#define ISSUPP_SHORTGI40(Dot11nDevCap) (Dot11nDevCap & MBIT(24))
+/** HW_SPEC Dot11nDevCap : Reset Short GI @ 40Mhz support */
+#define RESETSUPP_SHORTGI40(Dot11nDevCap) (Dot11nDevCap &= ~MBIT(24))
+/** HW_SPEC Dot11nDevCap : Short GI @ 20Mhz support */
+#define ISSUPP_SHORTGI20(Dot11nDevCap) (Dot11nDevCap & MBIT(23))
+/** HW_SPEC Dot11nDevCap : Rx LDPC support */
+#define ISSUPP_RXLDPC(Dot11nDevCap) (Dot11nDevCap & MBIT(22))
+/** HW_SPEC Dot11nDevCap : Number of TX BA streams supported */
+#define ISSUPP_GETTXBASTREAM(Dot11nDevCap) ((Dot11nDevCap >> 18) & 0xF)
+/** HW_SPEC Dot11nDevCap : Channel BW support @ 40Mhz support */
+#define ISSUPP_CHANWIDTH40(Dot11nDevCap) (Dot11nDevCap & MBIT(17))
+/** HW_SPEC Dot11nDevCap : Channel BW support @ 20Mhz support */
+#define ISSUPP_CHANWIDTH20(Dot11nDevCap) (Dot11nDevCap & MBIT(16))
+/** HW_SPEC Dot11nDevCap : Channel BW support @ 10Mhz support */
+#define ISSUPP_CHANWIDTH10(Dot11nDevCap) (Dot11nDevCap & MBIT(15))
+/** Dot11nUsrCap : 40Mhz intolarance enabled */
+#define ISENABLED_40MHZ_INTOLARENT(Dot11nDevCap) (Dot11nDevCap & MBIT(8))
+/** Dot11nUsrCap : Reset 40Mhz intolarance enabled */
+#define RESET_40MHZ_INTOLARENT(Dot11nDevCap) (Dot11nDevCap &= ~MBIT(8))
+/** HW_SPEC Dot11nDevCap : Rx AntennaD support */
+#define ISSUPP_RXANTENNAD(Dot11nDevCap) (Dot11nDevCap & MBIT(7))
+/** HW_SPEC Dot11nDevCap : Rx AntennaC support */
+#define ISSUPP_RXANTENNAC(Dot11nDevCap) (Dot11nDevCap & MBIT(6))
+/** HW_SPEC Dot11nDevCap : Rx AntennaB support */
+#define ISSUPP_RXANTENNAB(Dot11nDevCap) (Dot11nDevCap & MBIT(5))
+/** HW_SPEC Dot11nDevCap : Rx AntennaA support */
+#define ISSUPP_RXANTENNAA(Dot11nDevCap) (Dot11nDevCap & MBIT(4))
+/** HW_SPEC Dot11nDevCap : Tx AntennaD support */
+#define ISSUPP_TXANTENNAD(Dot11nDevCap) (Dot11nDevCap & MBIT(3))
+/** HW_SPEC Dot11nDevCap : Tx AntennaC support */
+#define ISSUPP_TXANTENNAC(Dot11nDevCap) (Dot11nDevCap & MBIT(2))
+/** HW_SPEC Dot11nDevCap : Tx AntennaB support */
+#define ISSUPP_TXANTENNAB(Dot11nDevCap) (Dot11nDevCap & MBIT(1))
+/** HW_SPEC Dot11nDevCap : Tx AntennaA support */
+#define ISSUPP_TXANTENNAA(Dot11nDevCap) (Dot11nDevCap & MBIT(0))
+
+/** HW_SPEC Dot11nDevCap : Set support of channel bw @ 40Mhz */
+#define SETSUPP_CHANWIDTH40(Dot11nDevCap) (Dot11nDevCap |= MBIT(17))
+/** HW_SPEC Dot11nDevCap : Reset support of channel bw @ 40Mhz */
+#define RESETSUPP_CHANWIDTH40(Dot11nDevCap) (Dot11nDevCap &= ~MBIT(17))
+
+/** DevMCSSupported : Tx MCS supported */
+#define GET_TXMCSSUPP(DevMCSSupported) (DevMCSSupported >> 4)
+/** DevMCSSupported : Rx MCS supported */
+#define GET_RXMCSSUPP(DevMCSSupported) (DevMCSSupported & 0x0f)
+
+/** GET HTCapInfo : Supported Channel BW */
+#define GETHT_SUPPCHANWIDTH(HTCapInfo) (HTCapInfo & MBIT(1))
+/** GET HTCapInfo : Support for Greenfield */
+#define GETHT_GREENFIELD(HTCapInfo) (HTCapInfo & MBIT(4))
+/** GET HTCapInfo : Support for Short GI @ 20Mhz */
+#define GETHT_SHORTGI20(HTCapInfo) (HTCapInfo & MBIT(5))
+/** GET HTCapInfo : Support for Short GI @ 40Mhz */
+#define GETHT_SHORTGI40(HTCapInfo) (HTCapInfo & MBIT(6))
+/** GET HTCapInfo : Support for Tx STBC */
+#define GETHT_TXSTBC(HTCapInfo) (HTCapInfo & MBIT(7))
+
+/** GET HTCapInfo : Support for Rx STBC */
+#define GETHT_RXSTBC(HTCapInfo) ((HTCapInfo >> 8) & 0x03)
+/** GET HTCapInfo : Support for Delayed ACK */
+#define GETHT_DELAYEDBACK(HTCapInfo) (HTCapInfo & MBIT(10))
+/** GET HTCapInfo : Support for Max AMSDU */
+#define GETHT_MAXAMSDU(HTCapInfo) (HTCapInfo & MBIT(11))
+
+/** GET HTCapInfo : Support 40Mhz Intolarence */
+#define GETHT_40MHZ_INTOLARANT(HTCapInfo) (HTCapInfo & MBIT(14))
+
+/** SET HTCapInfo : Set support for LDPC coding capability */
+#define SETHT_LDPCCODINGCAP(HTCapInfo) (HTCapInfo |= MBIT(0))
+/** SET HTCapInfo : Set support for Channel BW */
+#define SETHT_SUPPCHANWIDTH(HTCapInfo) (HTCapInfo |= MBIT(1))
+/** SET HTCapInfo : Set support for Greenfield */
+#define SETHT_GREENFIELD(HTCapInfo) (HTCapInfo |= MBIT(4))
+/** SET HTCapInfo : Set support for Short GI @ 20Mhz */
+#define SETHT_SHORTGI20(HTCapInfo) (HTCapInfo |= MBIT(5))
+/** SET HTCapInfo : Set support for Short GI @ 40Mhz */
+#define SETHT_SHORTGI40(HTCapInfo) (HTCapInfo |= MBIT(6))
+/** SET HTCapInfo : Set support for Tx STBC */
+#define SETHT_TXSTBC(HTCapInfo) (HTCapInfo |= MBIT(7))
+/** SET HTCapInfo : Set support for Rx STBC */
+#define SETHT_RXSTBC(HTCapInfo, value) (HTCapInfo |= (value << 8))
+/** SET HTCapInfo : Set support for delayed block ack */
+#define SETHT_DELAYEDBACK(HTCapInfo) (HTCapInfo |= MBIT(10))
+/** SET HTCapInfo : Set support for Max size AMSDU */
+#define SETHT_MAXAMSDU(HTCapInfo) (HTCapInfo |= MBIT(11))
+/** SET HTCapInfo : Set support for DSSS/CCK Rates @ 40Mhz */
+#define SETHT_DSSSCCK40(HTCapInfo) (HTCapInfo |= MBIT(12))
+/** SET HTCapInfo : Enable 40Mhz Intolarence */
+#define SETHT_40MHZ_INTOLARANT(HTCapInfo) (HTCapInfo |= MBIT(14))
+/** SET HTCapInfo : Disable Static SM power save */
+#define SETHT_STATIC_SMPS(HTCapInfo) ((HTCapInfo) |= (MBIT(2) | MBIT(3)))
+
+/** RESET HTCapInfo : Set support for LDPC coding capability */
+#define RESETHT_LDPCCODINGCAP(HTCapInfo) (HTCapInfo &= ~MBIT(0))
+/** RESET HTCapInfo : Set support for Channel BW */
+#define RESETHT_SUPPCHANWIDTH(HTCapInfo) (HTCapInfo &= ~MBIT(1))
+/** RESET HTCapInfo : Set support for Greenfield */
+#define RESETHT_GREENFIELD(HTCapInfo) (HTCapInfo &= ~MBIT(4))
+/** RESET HTCapInfo : Set support for Short GI @ 20Mhz */
+#define RESETHT_SHORTGI20(HTCapInfo) (HTCapInfo &= ~MBIT(5))
+/** RESET HTCapInfo : Set support for Short GI @ 40Mhz */
+#define RESETHT_SHORTGI40(HTCapInfo) (HTCapInfo &= ~MBIT(6))
+/** RESET HTCapInfo : Set support for Tx STBC */
+#define RESETHT_TXSTBC(HTCapInfo) (HTCapInfo &= ~MBIT(7))
+/** RESET HTCapInfo : Set support for Rx STBC */
+#define RESETHT_RXSTBC(HTCapInfo) (HTCapInfo &= ~(0x03 << 8))
+/** RESET HTCapInfo : Set support for delayed block ack */
+#define RESETHT_DELAYEDBACK(HTCapInfo) (HTCapInfo &= ~MBIT(10))
+/** RESET HTCapInfo : Set support for Max size AMSDU */
+#define RESETHT_MAXAMSDU(HTCapInfo) (HTCapInfo &= ~MBIT(11))
+/** RESET HTCapInfo : Disable 40Mhz Intolarence */
+#define RESETHT_40MHZ_INTOLARANT(HTCapInfo) (HTCapInfo &= ~MBIT(14))
+/** RESET HTCapInfo: Enable SM power save */
+#define RESETHT_SM_POWERSAVE(HTCapInfo) ((HTCapInfo) &= ~(MBIT(2) | MBIT(3)))
+/** RESET HTExtCap : Clear RD Responder bit */
+#define RESETHT_EXTCAP_RDG(HTExtCap) (HTExtCap &= ~MBIT(11))
+/** SET MCS32 */
+#define SETHT_MCS32(x) (x[4] |= 1)
+/** Set mcs set defined bit */
+#define SETHT_MCS_SET_DEFINED(x) (x[12] |= 1)
+/** Set the highest Rx data rate */
+#define SETHT_RX_HIGHEST_DT_SUPP(x, y) ((*(t_u16 *)(x + 10)) = y)
+/** AMPDU factor size */
+#define AMPDU_FACTOR_64K 0x03
+/** Set AMPDU size in A-MPDU paramter field */
+#define SETAMPDU_SIZE(x, y) \
+ do { \
+ x = x & ~0x03; \
+ x |= y & 0x03; \
+ } while (0) /** Set AMPDU spacing in A-MPDU paramter field */
+#define SETAMPDU_SPACING(x, y) \
+ do { \
+ x = x & ~0x1c; \
+ x |= (y & 0x07) << 2; \
+ } while (0)
+
+/** RadioType : Support for Band A */
+#define ISSUPP_BANDA(FwCapInfo) (FwCapInfo & MBIT(10))
+/** RadioType : Support for 40Mhz channel BW */
+#define ISALLOWED_CHANWIDTH40(Field2) (Field2 & MBIT(2))
+/** RadioType : Set support 40Mhz channel */
+#define SET_CHANWIDTH40(Field2) (Field2 |= MBIT(2))
+/** RadioType : Reset support 40Mhz channel */
+#define RESET_CHANWIDTH40(Field2) (Field2 &= ~(MBIT(0) | MBIT(1) | MBIT(2)))
+/** RadioType : Get secondary channel */
+#define GET_SECONDARYCHAN(Field2) (Field2 & (MBIT(0) | MBIT(1)))
+
+/** ExtCap : Support for FILS */
+#define ISSUPP_EXTCAP_FILS(ext_cap) (ext_cap.FILS)
+/** ExtCap : Set support FILS */
+#define SET_EXTCAP_FILS(ext_cap) (ext_cap.FILS = 1)
+/** ExtCap : Reset support FILS */
+#define RESET_EXTCAP_FILS(ext_cap) (ext_cap.FILS = 0)
+
+/** ExtCap : Support for TDLS */
+#define ISSUPP_EXTCAP_TDLS(ext_cap) (ext_cap.TDLSSupport)
+/** ExtCap : Set support TDLS */
+#define SET_EXTCAP_TDLS(ext_cap) (ext_cap.TDLSSupport = 1)
+/** ExtCap : Reset support TDLS */
+#define RESET_EXTCAP_TDLS(ext_cap) (ext_cap.TDLSSupport = 0)
+/** ExtCap : Support for TDLS UAPSD */
+#define ISSUPP_EXTCAP_TDLS_UAPSD(ext_cap) (ext_cap.TDLSPeerUAPSDSupport)
+/** ExtCap : Set support TDLS UAPSD */
+#define SET_EXTCAP_TDLS_UAPSD(ext_cap) (ext_cap.TDLSPeerUAPSDSupport = 1)
+/** ExtCap : Reset support TDLS UAPSD */
+#define RESET_EXTCAP_TDLS_UAPSD(ext_cap) (ext_cap.TDLSPeerUAPSDSupport = 0)
+/** ExtCap : Support for TDLS CHANNEL SWITCH */
+#define ISSUPP_EXTCAP_TDLS_CHAN_SWITCH(ext_cap) (ext_cap.TDLSChannelSwitching)
+/** ExtCap : Set support TDLS CHANNEL SWITCH */
+#define SET_EXTCAP_TDLS_CHAN_SWITCH(ext_cap) (ext_cap.TDLSChannelSwitching = 1)
+/** ExtCap : Reset support TDLS CHANNEL SWITCH */
+#define RESET_EXTCAP_TDLS_CHAN_SWITCH(ext_cap) \
+ (ext_cap.TDLSChannelSwitching = 0)
+/** ExtCap : Set support Multi BSSID */
+#define SET_EXTCAP_MULTI_BSSID(ext_cap) (ext_cap.MultipleBSSID = 1)
+/** ExtCap : Support for Interworking */
+#define ISSUPP_EXTCAP_INTERWORKING(ext_cap) (ext_cap.Interworking)
+/** ExtCap : Set support Interworking */
+#define SET_EXTCAP_INTERWORKING(ext_cap) (ext_cap.Interworking = 1)
+/** ExtCap : Reset support Interworking */
+#define RESET_EXTCAP_INTERWORKING(ext_cap) (ext_cap.Interworking = 0)
+/** ExtCap : Support for Operation Mode Notification */
+#define ISSUPP_EXTCAP_OPERMODENTF(ext_cap) (ext_cap.OperModeNtf)
+/** ExtCap : Set support Operation Mode Notification */
+#define SET_EXTCAP_OPERMODENTF(ext_cap) (ext_cap.OperModeNtf = 1)
+/** ExtCap : Reset support Operation Mode Notification */
+#define RESET_EXTCAP_OPERMODENTF(ext_cap) (ext_cap.OperModeNtf = 0)
+/** ExtCap : Support for QosMap */
+#define ISSUPP_EXTCAP_QOS_MAP(ext_cap) (ext_cap.Qos_Map)
+/** ExtCap : Set Support QosMap */
+#define SET_EXTCAP_QOS_MAP(ext_cap) (ext_cap.Qos_Map = 1)
+/** ExtCap : Reset support QosMap */
+#define RESET_EXTCAP_QOS_MAP(ext_cap) (ext_cap.Qos_Map = 0)
+/** ExtCap : Support for BSS_Transition */
+#define ISSUPP_EXTCAP_BSS_TRANSITION(ext_cap) (ext_cap.BSS_Transition)
+/** ExtCap : Set Support BSS_Transition */
+#define SET_EXTCAP_BSS_TRANSITION(ext_cap) (ext_cap.BSS_Transition = 1)
+/** ExtCap : Reset support BSS_Transition */
+#define RESET_EXTCAP_BSS_TRANSITION(ext_cap) (ext_cap.BSS_Transition = 0)
+
+/** ExtCap : Support for TDLS wider bandwidth */
+#define ISSUPP_EXTCAP_TDLS_WIDER_BANDWIDTH(ext_cap) (ext_cap.TDLSWildBandwidth)
+/** ExtCap : Set support TDLS wider bandwidth */
+#define SET_EXTCAP_TDLS_WIDER_BANDWIDTH(ext_cap) (ext_cap.TDLSWildBandwidth = 1)
+/** ExtCap : Reset support TDLS wider bandwidth */
+#define RESET_EXTCAP_TDLS_WIDER_BANDWIDTH(ext_cap) \
+ (ext_cap.TDLSWildBandwidth = 0)
+
+/** ExtCap : Support for extend channel switch */
+#define ISSUPP_EXTCAP_EXT_CHANNEL_SWITCH(ext_cap) (ext_cap.ExtChanSwitching)
+/** ExtCap : Set support Ext Channel Switch */
+#define SET_EXTCAP_EXT_CHANNEL_SWITCH(ext_cap) (ext_cap.ExtChanSwitching = 1)
+/** ExtCap: Set Timing Measurement */
+#define SET_EXTCAP_EXT_TIMING_MEASUREMENT(ext_cap) \
+ (ext_cap.TimingMeasurement = 1)
+/** ExtCap : Reset support Ext Channel Switch */
+#define RESET_EXTCAP_EXT_CHANNEL_SWITCH(ext_cap) (ext_cap.ExtChanSwitching = 0)
+
+/** ExtCap : Support for TWT RESP */
+#define ISSUPP_EXTCAP_EXT_TWT_RESP(ext_cap) (ext_cap.TWTResp)
+/** ExtCap : Set support Ext TWT_REQ */
+#define SET_EXTCAP_TWT_REQ(ext_cap) (ext_cap.TWTReq = 1)
+/** ExtCap : ReSet support Ext TWT REQ */
+#define RESET_EXTCAP_TWT_REQ(ext_cap) (ext_cap.TWTReq = 0)
+
+/** LLC/SNAP header len */
+#define LLC_SNAP_LEN 8
+
+/** bandwidth following HTCAP */
+#define BW_FOLLOW_HTCAP 0
+/** bandwidth following VHTCAP */
+#define BW_FOLLOW_VHTCAP 1
+
+/** HW_SPEC FwCapInfo */
+#define HWSPEC_11ACSGI80_SUPP MBIT(5)
+#define HWSPEC_11ACRXSTBC_SUPP MBIT(8)
+
+#define ISSUPP_11ACENABLED(FwCapInfo) (FwCapInfo & (MBIT(12) | MBIT(13)))
+
+#define ISSUPP_11AC2GENABLED(FwCapInfo) (FwCapInfo & MBIT(12))
+#define ISSUPP_11AC5GENABLED(FwCapInfo) (FwCapInfo & MBIT(13))
+
+/** HW_SPEC Dot11acDevCap : HTC-VHT supported */
+#define ISSUPP_11ACVHTHTCVHT(Dot11acDevCap) (Dot11acDevCap & MBIT(22))
+/** HW_SPEC Dot11acDevCap : VHT TXOP PS support */
+#define ISSUPP_11ACVHTTXOPPS(Dot11acDevCap) (Dot11acDevCap & MBIT(21))
+/** HW_SPEC Dot11acDevCap : MU RX beamformee support */
+#define ISSUPP_11ACMURXBEAMFORMEE(Dot11acDevCap) (Dot11acDevCap & MBIT(20))
+/** HW_SPEC Dot11acDevCap : MU TX beamformee support */
+#define ISSUPP_11ACMUTXBEAMFORMEE(Dot11acDevCap) (Dot11acDevCap & MBIT(19))
+/** HW_SPEC Dot11acDevCap : SU Beamformee support */
+#define ISSUPP_11ACSUBEAMFORMEE(Dot11acDevCap) (Dot11acDevCap & MBIT(12))
+/** HW_SPEC Dot11acDevCap : SU Beamformer support */
+#define ISSUPP_11ACSUBEAMFORMER(Dot11acDevCap) (Dot11acDevCap & MBIT(11))
+/** HW_SPEC Dot11acDevCap : Rx STBC support */
+#define ISSUPP_11ACRXSTBC(Dot11acDevCap) (Dot11acDevCap & MBIT(8))
+/** HW_SPEC Dot11acDevCap : Tx STBC support */
+#define ISSUPP_11ACTXSTBC(Dot11acDevCap) (Dot11acDevCap & MBIT(7))
+/** HW_SPEC Dot11acDevCap : Short GI support for 160MHz BW */
+#define ISSUPP_11ACSGI160(Dot11acDevCap) (Dot11acDevCap & MBIT(6))
+/** HW_SPEC Dot11acDevCap : Short GI support for 80MHz BW */
+#define ISSUPP_11ACSGI80(Dot11acDevCap) (Dot11acDevCap & MBIT(5))
+/** HW_SPEC Dot11acDevCap : LDPC coding support */
+#define ISSUPP_11ACLDPC(Dot11acDevCap) (Dot11acDevCap & MBIT(4))
+/** HW_SPEC Dot11acDevCap : Channel BW 20/40/80/160/80+80 MHz support */
+#define ISSUPP_11ACBW8080(Dot11acDevCap) (Dot11acDevCap & MBIT(3))
+/** HW_SPEC Dot11acDevCap : Channel BW 20/40/80/160 MHz support */
+#define ISSUPP_11ACBW160(Dot11acDevCap) (Dot11acDevCap & MBIT(2))
+
+/** Set VHT Cap Info: Max MPDU length */
+#define SET_VHTCAP_MAXMPDULEN(VHTCapInfo, value) (VHTCapInfo |= (value & 0x03))
+/** SET VHT CapInfo: Supported Channel Width SET (2 bits)*/
+#define SET_VHTCAP_CHWDSET(VHTCapInfo, value) \
+ (VHTCapInfo |= ((value & 0x3) << 2))
+/** SET VHT CapInfo: Rx STBC (3 bits) */
+#define SET_VHTCAP_RXSTBC(VHTCapInfo, value) \
+ (VHTCapInfo |= ((value & 0x7) << 8))
+/** SET VHT CapInfo: Commpressed Steering Num of BFer Ant Supported (3 bits) */
+#define SET_VHTCAP_SNBFERANT(VHTCapInfo, value) \
+ (VHTCapInfo |= ((value & 0x7) << 13))
+/** SET VHT CapInfo: Num of Sounding Dimensions (3 bits) */
+#define SET_VHTCAP_NUMSNDDM(VHTCapInfo, value) \
+ (VHTCapInfo |= ((value & 0x7) << 16))
+/** SET VHT CapInfo: Max AMPDU Length Exponent (3 bits) */
+#define SET_VHTCAP_MAXAMPDULENEXP(VHTCapInfo, value) \
+ (VHTCapInfo |= ((value & 0x7) << 23))
+/** SET VHT CapInfo: VHT Link Adaptation Capable (2 bits) */
+#define SET_VHTCAP_LINKADPCAP(VHTCapInfo, value) \
+ (VHTCapInfo |= ((value & 0x3) << 26))
+
+/** HW_SPEC Dot11acDevCap : ReSet VHT Link Adapation Capable */
+#define RESET_11ACVHTLINKCAPA(Dot11acDevCap, value) (Dot11acDevCap &= ~(0x03))
+/** HW_SPEC Dot11acDevCap : ReSet Maximum AMPDU Length Exponent */
+#define RESET_11ACAMPDULENEXP(Dot11acDevCap, value) (Dot11acDevCap &= ~(0x07))
+/** HW_SPEC Dot11acDevCap : ReSet support of HTC-VHT */
+#define RESET_11ACVHTHTCVHT(Dot11acDevCap) (Dot11acDevCap &= ~MBIT(22))
+/** HW_SPEC Dot11acDevCap : ReSet support of VHT TXOP PS */
+#define RESET_11ACVHTTXOPPS(Dot11acDevCap) (Dot11acDevCap &= ~MBIT(21))
+/** HW_SPEC Dot11acDevCap : ReSet support of MU RX beamformee */
+#define RESET_11ACMURXBEAMFORMEE(Dot11acDevCap) (Dot11acDevCap &= ~MBIT(20))
+/** HW_SPEC Dot11acDevCap : ReSet support of MU TX beamformee */
+#define RESET_11ACMUTXBEAMFORMEE(Dot11acDevCap) (Dot11acDevCap &= ~MBIT(19))
+/** HW_SPEC Dot11acDevCap : ReSet Number of Sounding Dimensions */
+#define RESET_11ACSOUNDINGNUM(Dot11acDevCap) (Dot11acDevCap &= ~((0x07) << 16))
+/** HW_SPEC Dot11acDevCap : ReSet Compressed Steering Number
+ * of Beamformer Antenna */
+#define RESET_11ACBFANTNUM(Dot11acDevCap) (Dot11acDevCap &= ~((0x07) << 13))
+/** HW_SPEC Dot11acDevCap : ReSet support of SU Beamformee */
+#define RESET_11ACSUBEAMFORMEE(Dot11acDevCap) (Dot11acDevCap &= ~MBIT(12))
+/** HW_SPEC Dot11acDevCap : ReSet support of SU Beamformer */
+#define RESET_11ACSUBEAMFORMER(Dot11acDevCap) (Dot11acDevCap &= ~MBIT(11))
+/** HW_SPEC Dot11acDevCap : ReSet support of Rx STBC */
+#define RESET_11ACRXSTBC(Dot11acDevCap) (Dot11acDevCap &= ~((0x07) << 8))
+/** HW_SPEC Dot11acDevCap : ReSet support of Tx STBC */
+#define RESET_11ACTXSTBC(Dot11acDevCap) (Dot11acDevCap &= ~MBIT(7))
+/** HW_SPEC Dot11acDevCap : ReSet support of Short GI support for 160MHz BW */
+#define RESET_11ACSGI160(Dot11acDevCap) (Dot11acDevCap &= ~MBIT(6))
+/** HW_SPEC Dot11acDevCap : ReSet support of Short GI support for 80MHz BW */
+#define RESET_11ACSGI80(Dot11acDevCap) (Dot11acDevCap &= ~MBIT(5))
+/** HW_SPEC Dot11acDevCap : ReSet support of LDPC coding */
+#define RESET_11ACLDPC(Dot11acDevCap) (Dot11acDevCap &= ~MBIT(4))
+/** HW_SPEC Dot11acDevCap : ReSet support of
+ * Channel BW 20/40/80/160/80+80 MHz */
+#define RESET_11ACBW8080(Dot11acDevCap) (Dot11acDevCap &= ~MBIT(3))
+/** HW_SPEC Dot11acDevCap : ReSet support of
+ * Channel BW 20/40/80/160 MHz */
+#define RESET_11ACBW160(Dot11acDevCap) (Dot11acDevCap &= ~MBIT(2))
+/** HW_SPEC Dot11acDevCap : ReSet Max MPDU length */
+#define RESET_11ACMAXMPDULEN(Dot11acDevCap) (Dot11acDevCap &= ~(0x03))
+
+/** Default 11ac capability mask for 2.4GHz */
+#define DEFAULT_11AC_CAP_MASK_BG \
+ (HWSPEC_11ACSGI80_SUPP | HWSPEC_11ACRXSTBC_SUPP)
+/** Default 11ac capability mask for 5GHz */
+#define DEFAULT_11AC_CAP_MASK_A (HWSPEC_11ACSGI80_SUPP | HWSPEC_11ACRXSTBC_SUPP)
+/** GET VHT CapInfo : MAX MPDU Length */
+#define GET_VHTCAP_MAXMPDULEN(VHTCapInfo) (VHTCapInfo & 0x3)
+/** GET VHT CapInfo: Supported Channel Width SET (2 bits)*/
+#define GET_VHTCAP_CHWDSET(VHTCapInfo) ((VHTCapInfo >> 2) & 0x3)
+/** GET VHT CapInfo: Rx STBC (3 bits) */
+#define GET_VHTCAP_RXSTBC(VHTCapInfo) ((VHTCapInfo >> 8) & 0x7)
+/** GET VHT CapInfo: Compressed Steering Num of BFer Ant Supported (3 bits) */
+#define GET_VHTCAP_SNBFERANT(VHTCapInfo) ((VHTCapInfo >> 13) & 0x7)
+/** GET VHT CapInfo: Num of Sounding Dimensions (3 bits) */
+#define GET_VHTCAP_NUMSNDDM(VHTCapInfo) ((VHTCapInfo >> 16) & 0x7)
+/** GET VHT CapInfo: Max AMPDU Length Exponent (3 bits) */
+#define GET_VHTCAP_MAXAMPDULENEXP(VHTCapInfo) ((VHTCapInfo >> 23) & 0x7)
+/** GET VHT CapInfo: VHT Link Adaptation Capable (2 bits) */
+#define GET_VHTCAP_LINKADPCAP(VHTCapInfo) ((VHTCapInfo >> 26) & 0x3)
+/**SET OPERATING MODE:Channel Width:80M*/
+#define SET_OPER_MODE_80M(oper_mode) \
+ (oper_mode = (oper_mode & ~MBIT(0)) | MBIT(1))
+/**SET OPERATING MODE:Channel Width:40M*/
+#define SET_OPER_MODE_40M(oper_mode) \
+ (oper_mode = (oper_mode & ~MBIT(1)) | MBIT(0))
+/**SET OPERATING MODE:Channel Width:20M*/
+#define SET_OPER_MODE_20M(oper_mode) (oper_mode &= ~(0x03))
+#define IS_OPER_MODE_20M(oper_mode) (((oper_mode) & (MBIT(0) | MBIT(1))) == 0)
+/**SET OPERATING MODE:Rx NSS:2*/
+#define SET_OPER_MODE_2NSS(oper_mode) \
+ (oper_mode = (oper_mode & ~(MBIT(5) | MBIT(6))) | MBIT(4))
+/**SET OPERATING MODE:Rx NSS:1*/
+#define SET_OPER_MODE_1NSS(oper_mode) \
+ (oper_mode &= ~(MBIT(4) | MBIT(5) | MBIT(6)))
+
+#define GET_VHTMCS(MCSMapSet) (MCSMapSet & 0xFFFF)
+#define GET_VHTNSSMCS(MCSMapSet, nss) ((MCSMapSet >> (2 * (nss - 1))) & 0x3)
+#define RET_VHTNSSMCS(MCSMapSet, nss) ((MCSMapSet >> (2 * (nss - 1))) & 0x3)
+#define SET_VHTNSSMCS(MCSMapSet, nss, value) \
+ (MCSMapSet |= (value & 0x3) << (2 * (nss - 1)))
+
+/** DevMCSSupported : Tx MCS supported */
+#define GET_DEVTXMCSMAP(DevMCSMap) (DevMCSMap >> 16)
+#define GET_DEVNSSTXMCS(DevMCSMap, nss) \
+ ((DevMCSMap >> (2 * (nss - 1) + 16)) & 0x3)
+#define SET_DEVNSSTXMCS(DevMCSMap, nss, value) \
+ (DevMCSMap |= (value & 0x3) << (2 * (nss - 1) + 16))
+#define RESET_DEVTXMCSMAP(DevMCSMap) (DevMCSMap &= 0xFFFF)
+/** DevMCSSupported : Rx MCS supported */
+#define GET_DEVRXMCSMAP(DevMCSMap) (DevMCSMap & 0xFFFF)
+#define GET_DEVNSSRXMCS(DevMCSMap, nss) ((DevMCSMap >> (2 * (nss - 1))) & 0x3)
+#define SET_DEVNSSRXMCS(DevMCSMap, nss, value) \
+ (DevMCSMap |= (value & 0x3) << (2 * (nss - 1)))
+#define RESET_DEVRXMCSMAP(DevMCSMap) (DevMCSMap &= 0xFFFF0000)
+
+/** TLV type : Rate scope */
+#define TLV_TYPE_RATE_DROP_PATTERN \
+ (PROPRIETARY_TLV_BASE_ID + 0x51) /* 0x0151 \
+ */
+/** TLV type : Rate drop pattern */
+#define TLV_TYPE_RATE_DROP_CONTROL \
+ (PROPRIETARY_TLV_BASE_ID + 0x52) /* 0x0152 \
+ */
+/** TLV type : Rate scope */
+#define TLV_TYPE_RATE_SCOPE (PROPRIETARY_TLV_BASE_ID + 0x53) /* 0x0153 */
+
+/** TLV type : Power group */
+#define TLV_TYPE_POWER_GROUP (PROPRIETARY_TLV_BASE_ID + 0x54) /* 0x0154 */
+
+/** Modulation class for DSSS Rates */
+#define MOD_CLASS_HR_DSSS 0x03
+/** Modulation class for OFDM Rates */
+#define MOD_CLASS_OFDM 0x07
+/** Modulation class for HT Rates */
+#define MOD_CLASS_HT 0x08
+/** Modulation class for VHT Rates */
+#define MOD_CLASS_VHT 0x09
+/** HT bandwidth 20 MHz */
+#define HT_BW_20 0
+/** HT bandwidth 40 MHz */
+#define HT_BW_40 1
+/** HT bandwidth 80 MHz */
+#define HT_BW_80 2
+
+/** TLV type : TX RATE CFG, rename from TLV_TYPE_GI_LTF_SIZE to include CMD and
+ * HE ER SU settings to this tlv */
+#define TLV_TYPE_TX_RATE_CFG (PROPRIETARY_TLV_BASE_ID + 319) /* 0x023f */
+
+/** TLV type : Scan Response */
+#define TLV_TYPE_BSS_SCAN_RSP (PROPRIETARY_TLV_BASE_ID + 0x56) /* 0x0156 */
+/** TLV type : Scan Response Stats */
+#define TLV_TYPE_BSS_SCAN_INFO (PROPRIETARY_TLV_BASE_ID + 0x57) /* 0x0157 */
+
+/** TLV type : 11h Basic Rpt */
+#define TLV_TYPE_CHANRPT_11H_BASIC \
+ (PROPRIETARY_TLV_BASE_ID + 0x5b) /* 0x015b \
+ */
+
+/** TLV type : DFS W53 Configuration */
+#define TLV_TYPE_DFS_W53_CFG (PROPRIETARY_TLV_BASE_ID + 0x145) // + 325
+#ifdef OPCHAN
+/** TLV type : OpChannel control */
+#define TLV_TYPE_OPCHAN_CONTROL_DESC \
+ (PROPRIETARY_TLV_BASE_ID + 0x79) /* 0x0179 */
+/** TLV type : OpChannel channel group control */
+#define TLV_TYPE_OPCHAN_CHANGRP_CTRL \
+ (PROPRIETARY_TLV_BASE_ID + 0x7a) /* 0x017a */
+#endif
+
+/** TLV type : Action frame */
+#define TLV_TYPE_IEEE_ACTION_FRAME \
+ (PROPRIETARY_TLV_BASE_ID + 0x8c) /* 0x018c \
+ */
+
+/** TLV type : SCAN channel gap */
+#define TLV_TYPE_SCAN_CHANNEL_GAP \
+ (PROPRIETARY_TLV_BASE_ID + 0xc5) /* 0x01c5 \
+ */
+/** TLV type : Channel statistics */
+#define TLV_TYPE_CHANNEL_STATS (PROPRIETARY_TLV_BASE_ID + 0xc6) /* 0x01c6 */
+/** TLV type : BSS_MODE */
+#define TLV_TYPE_BSS_MODE (PROPRIETARY_TLV_BASE_ID + 0xce) /* 0x01ce */
+
+/** Firmware Host Command ID Constants */
+/** Host Command ID : Get hardware specifications */
+#define HostCmd_CMD_GET_HW_SPEC 0x0003
+/** Host Command ID : 802.11 scan */
+#define HostCmd_CMD_802_11_SCAN 0x0006
+/** Host Command ID : 802.11 get log */
+#define HostCmd_CMD_802_11_GET_LOG 0x000b
+
+/** Host Command id: GET_TX_RX_PKT_STATS */
+#define HOST_CMD_TX_RX_PKT_STATS 0x008d
+
+/** Host Command ID : 802.11 get/set link layer statistic */
+#define HostCmd_CMD_802_11_LINK_STATS 0x0256
+
+/** Host Command ID : MAC multicast address */
+#define HostCmd_CMD_MAC_MULTICAST_ADR 0x0010
+/** Host Command ID : 802.11 EEPROM access */
+#define HostCmd_CMD_802_11_EEPROM_ACCESS 0x0059
+/** Host Command ID : 802.11 associate */
+#define HostCmd_CMD_802_11_ASSOCIATE 0x0012
+
+/** Host Command ID : 802.11 SNMP MIB */
+#define HostCmd_CMD_802_11_SNMP_MIB 0x0016
+/** Host Command ID : MAC register access */
+#define HostCmd_CMD_MAC_REG_ACCESS 0x0019
+/** Host Command ID : BBP register access */
+#define HostCmd_CMD_BBP_REG_ACCESS 0x001a
+/** Host Command ID : RF register access */
+#define HostCmd_CMD_RF_REG_ACCESS 0x001b
+
+/** Host Command ID : 802.11 radio control */
+#define HostCmd_CMD_802_11_RADIO_CONTROL 0x001c
+/** Host Command ID : 802.11 RF channel */
+#define HostCmd_CMD_802_11_RF_CHANNEL 0x001d
+/** Host Command ID : 802.11 RF Tx power */
+#define HostCmd_CMD_802_11_RF_TX_POWER 0x001e
+
+/** Host Command ID : 802.11 RF antenna */
+#define HostCmd_CMD_802_11_RF_ANTENNA 0x0020
+
+/** Host Command ID : 802.11 deauthenticate */
+#define HostCmd_CMD_802_11_DEAUTHENTICATE 0x0024
+/** Host Command ID: 802.11 disassoicate */
+#define HostCmd_CMD_802_11_DISASSOCIATE 0x0026
+/** Host Command ID : MAC control */
+#define HostCmd_CMD_MAC_CONTROL 0x0028
+/** Host Command ID : 802.11 Ad-Hoc start */
+#define HostCmd_CMD_802_11_AD_HOC_START 0x002b
+/** Host Command ID : 802.11 Ad-Hoc join */
+#define HostCmd_CMD_802_11_AD_HOC_JOIN 0x002c
+
+/** Host Command ID: CW Mode */
+#define HostCmd_CMD_CW_MODE_CTRL 0x0239
+/** Host Command ID : 802.11 key material */
+#define HostCmd_CMD_802_11_KEY_MATERIAL 0x005e
+
+/** Host Command ID : 802.11 Ad-Hoc stop */
+#define HostCmd_CMD_802_11_AD_HOC_STOP 0x0040
+
+/** Host Command ID : 802.22 MAC address */
+#define HostCmd_CMD_802_11_MAC_ADDRESS 0x004D
+
+/** Host Command ID : WMM Traffic Stream Status */
+#define HostCmd_CMD_WMM_TS_STATUS 0x005d
+
+/** Host Command ID : 802.11 D domain information */
+#define HostCmd_CMD_802_11D_DOMAIN_INFO 0x005b
+
+/*This command gets/sets the Transmit Rate-based Power Control (TRPC) channel
+ * configuration.*/
+#define HostCmd_CHANNEL_TRPC_CONFIG 0x00fb
+
+/** Host Command ID : 802.11 TPC information */
+#define HostCmd_CMD_802_11_TPC_INFO 0x005f
+/** Host Command ID : 802.11 TPC adapt req */
+#define HostCmd_CMD_802_11_TPC_ADAPT_REQ 0x0060
+/** Host Command ID : 802.11 channel SW ann */
+#define HostCmd_CMD_802_11_CHAN_SW_ANN 0x0061
+
+/** Host Command ID : Measurement request */
+#define HostCmd_CMD_MEASUREMENT_REQUEST 0x0062
+/** Host Command ID : Measurement report */
+#define HostCmd_CMD_MEASUREMENT_REPORT 0x0063
+
+/** Host Command ID : 802.11 sleep parameters */
+#define HostCmd_CMD_802_11_SLEEP_PARAMS 0x0066
+
+/** Host Command ID : 802.11 ps inactivity timeout */
+#define HostCmd_CMD_802_11_PS_INACTIVITY_TIMEOUT 0x0067
+
+/** Host Command ID : 802.11 sleep period */
+#define HostCmd_CMD_802_11_SLEEP_PERIOD 0x0068
+
+/** Host Command ID: 802.11 BG scan config */
+#define HostCmd_CMD_802_11_BG_SCAN_CONFIG 0x006b
+/** Host Command ID : 802.11 BG scan query */
+#define HostCmd_CMD_802_11_BG_SCAN_QUERY 0x006c
+
+/** Host Command ID : WMM ADDTS req */
+#define HostCmd_CMD_WMM_ADDTS_REQ 0x006E
+/** Host Command ID : WMM DELTS req */
+#define HostCmd_CMD_WMM_DELTS_REQ 0x006F
+/** Host Command ID : WMM queue configuration */
+#define HostCmd_CMD_WMM_QUEUE_CONFIG 0x0070
+/** Host Command ID : 802.11 get status */
+#define HostCmd_CMD_WMM_GET_STATUS 0x0071
+
+/** Host Command ID : 802.11 subscribe event */
+#define HostCmd_CMD_802_11_SUBSCRIBE_EVENT 0x0075
+
+/** Host Command ID : 802.11 Tx rate query */
+#define HostCmd_CMD_802_11_TX_RATE_QUERY 0x007f
+/** Host Command ID :Get timestamp value */
+#define HostCmd_CMD_GET_TSF 0x0080
+
+/** Host Command ID : WMM queue stats */
+#define HostCmd_CMD_WMM_QUEUE_STATS 0x0081
+
+/** Host Command ID : KEEP ALIVE command */
+#define HostCmd_CMD_AUTO_TX 0x0082
+
+/** Host Command ID : 802.11 IBSS coalescing status */
+#define HostCmd_CMD_802_11_IBSS_COALESCING_STATUS 0x0083
+
+/** Host Command ID : Memory access */
+#define HostCmd_CMD_MEM_ACCESS 0x0086
+
+#if defined(SDIO)
+/** Host Command ID : SDIO GPIO interrupt configuration */
+#define HostCmd_CMD_SDIO_GPIO_INT_CONFIG 0x0088
+#endif
+
+/** Host Command ID : Mfg command */
+#define HostCmd_CMD_MFG_COMMAND 0x0089
+/** Host Command ID : Inactivity timeout ext */
+#define HostCmd_CMD_INACTIVITY_TIMEOUT_EXT 0x008a
+
+/** Host Command ID : DBGS configuration */
+#define HostCmd_CMD_DBGS_CFG 0x008b
+/** Host Command ID : Get memory */
+#define HostCmd_CMD_GET_MEM 0x008c
+
+/** Host Command ID : Cal data dnld */
+#define HostCmd_CMD_CFG_DATA 0x008f
+
+/** Host Command ID : SDIO pull control */
+#define HostCmd_CMD_SDIO_PULL_CTRL 0x0093
+
+/** Host Command ID : ECL system clock configuration */
+#define HostCmd_CMD_ECL_SYSTEM_CLOCK_CONFIG 0x0094
+
+/** Host Command ID : Extended version */
+#define HostCmd_CMD_VERSION_EXT 0x0097
+
+/** Host Command ID : MEF configuration */
+#define HostCmd_CMD_MEF_CFG 0x009a
+/** Host Command ID : 802.11 RSSI INFO*/
+#define HostCmd_CMD_RSSI_INFO 0x00a4
+/** Host Command ID : Function initialization */
+#define HostCmd_CMD_FUNC_INIT 0x00a9
+/** Host Command ID : Function shutdown */
+#define HostCmd_CMD_FUNC_SHUTDOWN 0x00aa
+
+/** Host Command ID : Robustcoex */
+#define HostCmd_CMD_802_11_ROBUSTCOEX 0x00e0
+
+/** Host Command ID :EAPOL PKT */
+#define HostCmd_CMD_802_11_EAPOL_PKT 0x012e
+
+/** Host Command ID :MIMO SWITCH **/
+#define HostCmd_CMD_802_11_MIMO_SWITCH 0x0235
+
+/** Host Command ID : 802.11 RSSI INFO EXT*/
+#define HostCmd_CMD_RSSI_INFO_EXT 0x0237
+
+#ifdef RX_PACKET_COALESCE
+/** TLV ID for RX pkt coalesce config */
+#define TLV_TYPE_RX_PKT_COAL_CONFIG (PROPRIETARY_TLV_BASE_ID + 0xC9)
+#endif
+
+/** Host Command ID : Channel report request */
+#define HostCmd_CMD_CHAN_REPORT_REQUEST 0x00dd
+
+/** Host Command ID: SUPPLICANT_PMK */
+#define HostCmd_CMD_SUPPLICANT_PMK 0x00c4
+/** Host Command ID: SUPPLICANT_PROFILE */
+#define HostCmd_CMD_SUPPLICANT_PROFILE 0x00c5
+
+/** Host Command ID : Add Block Ack Request */
+#define HostCmd_CMD_11N_ADDBA_REQ 0x00ce
+/** Host Command ID : Delete a Block Ack Request */
+#define HostCmd_CMD_11N_CFG 0x00cd
+/** Host Command ID : Add Block Ack Response */
+#define HostCmd_CMD_11N_ADDBA_RSP 0x00cf
+/** Host Command ID : Delete a Block Ack Request */
+#define HostCmd_CMD_11N_DELBA 0x00d0
+/** Host Command ID: Configure Tx Buf size */
+#define HostCmd_CMD_RECONFIGURE_TX_BUFF 0x00d9
+/** Host Command ID: AMSDU Aggr Ctrl */
+#define HostCmd_CMD_AMSDU_AGGR_CTRL 0x00df
+/** Host Command ID: 11AC config */
+#define HostCmd_CMD_11AC_CFG 0x0112
+/** Host Command ID: Configure TX Beamforming capability */
+#define HostCmd_CMD_TX_BF_CFG 0x0104
+
+/** Host Command ID : 802.11 TX power configuration */
+#define HostCmd_CMD_TXPWR_CFG 0x00d1
+
+/** Host Command ID : Soft Reset */
+#define HostCmd_CMD_SOFT_RESET 0x00d5
+
+/** Host Command ID : 802.11 b/g/n rate configration */
+#define HostCmd_CMD_TX_RATE_CFG 0x00d6
+
+/** Host Command ID : Enhanced PS mode */
+#define HostCmd_CMD_802_11_PS_MODE_ENH 0x00e4
+
+/** Host command action : Host sleep configuration */
+#define HostCmd_CMD_802_11_HS_CFG_ENH 0x00e5
+
+/** Host Command ID : CAU register access */
+#define HostCmd_CMD_CAU_REG_ACCESS 0x00ed
+
+/** Host Command ID : mgmt IE list */
+#define HostCmd_CMD_MGMT_IE_LIST 0x00f2
+
+#define HostCmd_CMD_802_11_BAND_STEERING 0x026f
+
+#ifdef SDIO
+/** Host Command ID : SDIO single port RX aggr */
+#define HostCmd_CMD_SDIO_SP_RX_AGGR_CFG 0x0223
+
+/** fw_cap_info bit16 for sdio sp rx aggr flag*/
+#define SDIO_SP_RX_AGGR_ENABLE MBIT(16)
+
+#endif
+
+/* fw_cap_info bit18 for ecsa support*/
+#define FW_CAPINFO_ECSA MBIT(18)
+
+/* fw_cap_info bit20 for get log*/
+#define FW_CAPINFO_GET_LOG MBIT(20)
+
+/** fw_cap_info bit22 for embedded supplicant support*/
+#define FW_CAPINFO_SUPPLICANT_SUPPORT MBIT(21)
+
+/** fw_cap_info bit23 for embedded authenticator support*/
+#define FW_CAPINFO_AUTH_SUPPORT MBIT(22)
+
+/** fw_cap_info bit25 for adhoc support*/
+#define FW_CAPINFO_ADHOC_SUPPORT MBIT(25)
+/** Check if adhoc is supported by firmware */
+#define IS_FW_SUPPORT_ADHOC(_adapter) \
+ (_adapter->fw_cap_info & FW_CAPINFO_ADHOC_SUPPORT)
+
+/** Check if supplicant is supported by firmware */
+#define IS_FW_SUPPORT_SUPPLICANT(_adapter) \
+ (_adapter->fw_cap_info & FW_CAPINFO_SUPPLICANT_SUPPORT)
+
+/** Check if authenticator is supported by firmware */
+#define IS_FW_SUPPORT_AUTHENTICATOR(_adapter) \
+ (_adapter->fw_cap_info & FW_CAPINFO_AUTH_SUPPORT)
+
+/** Ext fw cap info bit0 only 1x1 5G is available */
+#define FW_CAPINFO_EXT_5G_1X1_ONLY MBIT(0)
+/** Ext fw cap info bit1 1x1 5G is not available */
+#define FW_CAPINFO_EXT_NO_5G_1X1 MBIT(1)
+/** Ext fw cap info bit 2 only 1x1 2G is available */
+#define FW_CAPINFO_EXT_2G_1X1_ONLY MBIT(2)
+/**Ext fw cap info bit3 1x1 2G is not available */
+#define FW_CAPINFO_EXT_NO_2G_1X1 MBIT(3)
+/** Ext fw cap info bit4 1x1 + 1x1 5G mode is unavailable */
+#define FW_CAPINFO_EXT_NO_5G_1X1_PLUS_1X1 MBIT(4)
+/** Ext fw cap info bit5 80 + 80 MHz capability disabled */
+#define FW_CAPINFO_EXT_NO_80MHz_PLUS_80MHz MBIT(5)
+/** Ext fw cap info bit6 1024 QAM is disabled */
+#define FW_CAPINFO_EXT_NO_1024_QAM MBIT(6)
+/** FW cap info bit 7 11AX */
+#define FW_CAPINFO_EXT_802_11AX MBIT(7)
+/** FW cap info bit 8: 80MHZ disabled */
+#define FW_CAPINFO_EXT_NO_80MHZ MBIT(8)
+
+/** Check if 5G 1x1 only is supported by firmware */
+#define IS_FW_SUPPORT_5G_1X1_ONLY(_adapter) \
+ (_adapter->fw_cap_ext & FW_CAPINFO_EXT_5G_1X1_ONLY)
+/** Check if 5G 1x1 is unavailable in firmware */
+#define IS_FW_SUPPORT_NO_5G_1X1(_adapter) \
+ (_adapter->fw_cap_ext & FW_CAPINFO_EXT_NO_5G_1X1)
+/** Check if 2G 1x1 only is supported by firmware */
+#define IS_FW_SUPPORT_2G_1X1_ONLY(_adapter) \
+ (_adapter->fw_cap_ext & FW_CAPINFO_EXT_2G_1X1_ONLY)
+/** Check if 2G 1x1 is unavailable in firmware */
+#define IS_FW_SUPPORT_NO_2G_1X1(_adapter) \
+ (_adapter->fw_cap_ext & FW_CAPINFO_EXT_NO_2G_1X1)
+/** Check if 5G 1x1 + 1x1 mode is disabled in firmware */
+#define IS_FW_SUPPORT_NO_5G_1X1_PLUS_1X1(_adapter) \
+ (_adapter->fw_cap_ext & FW_CAPINFO_EXT_NO_5G_1X1_PLUS_1X1)
+/** Check if 80 + 80MHz is disabled in firmware */
+#define IS_FW_SUPPORT_NO_80MHz_PLUS_80MHz(_adapter) \
+ (_adapter->fw_cap_ext & FW_CAPINFO_EXT_NO_80MHz_PLUS_80MHz)
+/** Check if 1024 QAM disabled in firmware */
+#define IS_FW_SUPPORT_NO_1024_QAM(_adapter) \
+ (_adapter->fw_cap_ext & FW_CAPINFO_EXT_NO_1024_QAM)
+/** Check if 80MHZ disabled in firmware */
+#define IS_FW_SUPPORT_NO_80MHZ(_adapter) \
+ (_adapter->fw_cap_ext & FW_CAPINFO_EXT_NO_80MHZ)
+
+/** FW cap info TLV */
+typedef MLAN_PACK_START struct _MrvlIEtypes_fw_cap_info_t {
+ /** Header type */
+ t_u16 type;
+ /** Header length */
+ t_u16 len;
+ /** Fw cap info bitmap */
+ t_u32 fw_cap_info;
+ /** Extended fw cap info bitmap */
+ t_u32 fw_cap_ext;
+} MLAN_PACK_END MrvlIEtypes_fw_cap_info_t, *pMrvlIEtypes_fw_cap_info_t;
+
+/** Check if 11AX is supported by firmware */
+#define IS_FW_SUPPORT_11AX(_adapter) \
+ (_adapter->fw_cap_ext & FW_CAPINFO_EXT_802_11AX)
+
+typedef MLAN_PACK_START struct _MrvlIEtypes_Extension_t {
+ /** Header type */
+ t_u16 type;
+ /** Header length */
+ t_u16 len;
+ /** Element id extension */
+ t_u8 ext_id;
+ /** payload */
+ t_u8 data[];
+} MLAN_PACK_END MrvlIEtypes_Extension_t, *pMrvlIEtypes_Extension_t;
+
+/* HE MAC Capabilities Information field BIT 1 for TWT Req */
+#define HE_MAC_CAP_TWT_REQ_SUPPORT MBIT(1)
+/* HE MAC Capabilities Information field BIT 2 for TWT Resp*/
+#define HE_MAC_CAP_TWT_RESP_SUPPORT MBIT(2)
+typedef MLAN_PACK_START struct _MrvlIEtypes_He_cap_t {
+ /** Header type */
+ t_u16 type;
+ /** Header length */
+ t_u16 len;
+ /** Element id extension */
+ t_u8 ext_id;
+ /** he mac capability info */
+ t_u8 he_mac_cap[6];
+ /** he phy capability info */
+ t_u8 he_phy_cap[11];
+ /** he txrx mcs support , size would be 4 or 8 or 12 */
+ t_u8 he_txrx_mcs_support[4];
+ /** 160Mhz tx rx mcs support*/
+ t_u8 he160_txrx_mcs_support[4];
+ /** 80+80 Mhz tx rx mcs suport */
+ t_u8 he8080_txrx_mcs_support[4];
+ /** PPE Thresholds (optional) */
+ t_u8 val[20];
+} MLAN_PACK_END MrvlIEtypes_He_cap_t, *pMrvlIEtypes_he_cap_t;
+
+#ifdef RX_PACKET_COALESCE
+/** Host Command ID : Rx packet coalescing configuration */
+#define HostCmd_CMD_RX_PKT_COALESCE_CFG 0x012c
+#endif
+
+/** Host Command ID : Extended scan support */
+#define HostCmd_CMD_802_11_SCAN_EXT 0x0107
+
+/** Host Command ID : Forward mgmt frame */
+#define HostCmd_CMD_RX_MGMT_IND 0x010c
+
+#ifdef PCIE
+/** Host Command ID: Host buffer description */
+#define HostCmd_CMD_PCIE_HOST_BUF_DETAILS 0x00fa
+#endif
+
+/** Host Command ID : Set BSS_MODE */
+#define HostCmd_CMD_SET_BSS_MODE 0x00f7
+
+#ifdef UAP_SUPPORT
+/** Host Command id: SYS_INFO */
+#define HOST_CMD_APCMD_SYS_INFO 0x00ae
+/** Host Command id: sys_reset */
+#define HOST_CMD_APCMD_SYS_RESET 0x00af
+/** Host Command id: SYS_CONFIGURE */
+#define HOST_CMD_APCMD_SYS_CONFIGURE 0x00b0
+/** Host Command id: BSS_START */
+#define HOST_CMD_APCMD_BSS_START 0x00b1
+/** Host Command id: BSS_STOP */
+#define HOST_CMD_APCMD_BSS_STOP 0x00b2
+/** Host Command id: sta_list */
+#define HOST_CMD_APCMD_STA_LIST 0x00b3
+/** Host Command id: STA_DEAUTH */
+#define HOST_CMD_APCMD_STA_DEAUTH 0x00b5
+
+/** Host Command id: REPORT_MIC */
+#define HOST_CMD_APCMD_REPORT_MIC 0x00ee
+/** Host Command id: UAP_OPER_CTRL */
+#define HOST_CMD_APCMD_OPER_CTRL 0x0233
+#endif /* UAP_SUPPORT */
+
+/** Host Command id: PMIC CONFIGURE*/
+#define HOST_CMD_PMIC_CONFIGURE 0x23E
+
+/** Host Command ID: Tx data pause */
+#define HostCmd_CMD_CFG_TX_DATA_PAUSE 0x0103
+
+#ifdef WIFI_DIRECT_SUPPORT
+/** Host Command ID: P2P PARAMS CONFIG */
+#define HOST_CMD_P2P_PARAMS_CONFIG 0x00ea
+/** Host Command ID: WIFI_DIRECT_MODE_CONFIG */
+#define HOST_CMD_WIFI_DIRECT_MODE_CONFIG 0x00eb
+#endif
+
+/** Host Command ID: Remain On Channel */
+#define HostCmd_CMD_802_11_REMAIN_ON_CHANNEL 0x010d
+
+#define HostCmd_CMD_COALESCE_CFG 0x010a
+
+/** Host Command ID: GTK REKEY OFFLOAD CFG */
+#define HostCmd_CMD_GTK_REKEY_OFFLOAD_CFG 0x010f
+
+/** Host Command ID : OTP user data */
+#define HostCmd_CMD_OTP_READ_USER_DATA 0x0114
+
+/** Host Command ID: HS wakeup reason */
+#define HostCmd_CMD_HS_WAKEUP_REASON 0x0116
+
+/** Host Command ID: reject addba request */
+#define HostCmd_CMD_REJECT_ADDBA_REQ 0x0119
+
+#define HostCmd_CMD_FW_DUMP_EVENT 0x0125
+
+#define HostCMD_CONFIG_LOW_POWER_MODE 0x0128
+
+/** Host Command ID : Target device access */
+#define HostCmd_CMD_TARGET_ACCESS 0x012a
+
+/** Host Command ID: BCA device access */
+#define HostCmd_CMD_BCA_REG_ACCESS 0x0272
+
+/** Host Command ID: DFS repeater mode */
+#define HostCmd_DFS_REPEATER_MODE 0x012b
+
+/** Host Command ID: ACS scan */
+#define HostCMD_APCMD_ACS_SCAN 0x0224
+
+/** Host Command ID: Get sensor temp*/
+#define HostCmd_DS_GET_SENSOR_TEMP 0x0227
+
+/** Host Command ID : Configure ADHOC_OVER_IP parameters */
+#define HostCmd_CMD_WMM_PARAM_CONFIG 0x023a
+
+#ifdef STA_SUPPORT
+/** Host Command ID : set/get sta configure */
+#define HostCmd_CMD_STA_CONFIGURE 0x023f
+#endif
+
+/** Host Command ID : GPIO independent reset configure */
+#define HostCmd_CMD_INDEPENDENT_RESET_CFG 0x0243
+
+#if defined(PCIE9098) || defined(SD9098) || defined(USB9098) || \
+ defined(PCIE9097) || defined(USB9097) || defined(SD9097)
+/* TLV type: reg type */
+#define TLV_TYPE_REG_ACCESS_CTRL (PROPRIETARY_TLV_BASE_ID + 0x13C) /* 0x023c*/
+/** MrvlIEtypes_Reg_type_t*/
+typedef MLAN_PACK_START struct _MrvlIEtypes_Reg_type_t {
+ /** Header */
+ MrvlIEtypesHeader_t header;
+ /** type: 0x81/0x82/0x83 */
+ t_u8 type;
+} MLAN_PACK_END MrvlIEtypes_Reg_type_t;
+
+#endif
+#define HostCmd_CMD_CHAN_REGION_CFG 0x0242
+/* mod_grp */
+typedef enum _mod_grp {
+ MOD_CCK, // 0
+ MOD_OFDM_PSK, // 1
+ MOD_OFDM_QAM16, // 2
+ MOD_OFDM_QAM64, // 3
+ MOD_HT_20_PSK, // 4
+ MOD_HT_20_QAM16, // 5
+ MOD_HT_20_QAM64, // 6
+ MOD_HT_40_PSK, // 7
+ MOD_HT_40_QAM16, // 8
+ MOD_HT_40_QAM64, // 9
+#ifdef STREAM_2x2
+ MOD_HT2_20_PSK, // 10
+ MOD_HT2_20_QAM16, // 11
+ MOD_HT2_20_QAM64, // 12
+ MOD_HT2_40_PSK, // 13
+ MOD_HT2_40_QAM16, // 14
+ MOD_HT2_40_QAM64, // 15
+#endif
+
+ MOD_VHT_20_QAM256, // 16
+ MOD_VHT_40_QAM256, // 17
+ MOD_VHT_80_PSK, // 18
+ MOD_VHT_80_QAM16, // 19
+ MOD_VHT_80_QAM64, // 20
+ MOD_VHT_80_QAM256, // 21
+#ifdef STREAM_2x2
+ MOD_VHT2_20_QAM256, // 22
+ MOD_VHT2_40_QAM256, // 23
+ MOD_VHT2_80_PSK, // 24
+ MOD_VHT2_80_QAM16, // 25
+ MOD_VHT2_80_QAM64, // 26
+ MOD_VHT2_80_QAM256, // 27
+#endif
+} mod_grp;
+
+typedef MLAN_PACK_START struct _power_table_attr {
+ t_u8 rows_2g;
+ t_u8 cols_2g;
+ t_u8 rows_5g;
+ t_u8 cols_5g;
+} MLAN_PACK_END power_table_attr_t;
+
+#define FW_CFP_TABLE_MAX_ROWS_BG 14
+#define FW_CFP_TABLE_MAX_COLS_BG 17
+
+#define FW_CFP_TABLE_MAX_ROWS_A 39
+#define FW_CFP_TABLE_MAX_COLS_A 29
+
+#define HostCmd_CMD_DYN_BW 0x0252
+
+#define HostCmd_CMD_BOOT_SLEEP 0x0258
+
+#define HostCmd_CMD_RX_ABORT_CFG 0x0261
+#define HostCmd_CMD_RX_ABORT_CFG_EXT 0x0262
+#define HostCmd_CMD_TX_AMPDU_PROT_MODE 0x0263
+#define HostCmd_CMD_RATE_ADAPT_CFG 0x0264
+#define HostCmd_CMD_CCK_DESENSE_CFG 0x0265
+
+#define HostCmd_CMD_VDLL 0x0240
+#if defined(PCIE)
+#define HostCmd_CMD_SSU 0x0259
+#endif
+
+#define HostCmd_CMD_DMCS_CONFIG 0x0260
+
+/** Host Command ID: 11AX config */
+#define HostCmd_CMD_11AX_CFG 0x0266
+/** Host Command ID: 11AX command */
+#define HostCmd_CMD_11AX_CMD 0x026d
+/** Host Command ID: Range ext command */
+#define HostCmd_CMD_RANGE_EXT 0x0274
+/** Host Command ID: TWT cfg command */
+#define HostCmd_CMD_TWT_CFG 0x0270
+
+#define HostCmd_CMD_LOW_POWER_MODE_CFG 0x026e
+#define HostCmd_CMD_UAP_BEACON_STUCK_CFG 0x0271
+#define HostCmd_CMD_ARB_CONFIG 0x0273
+#define HostCmd_CMD_DOT11MC_UNASSOC_FTM_CFG 0x0275
+
+/** Enhanced PS modes */
+typedef enum _ENH_PS_MODES {
+ GET_PS = 0,
+ SLEEP_CONFIRM = 5,
+ DIS_AUTO_PS = 0xfe,
+ EN_AUTO_PS = 0xff,
+} ENH_PS_MODES;
+
+/** Command RET code, MSB is set to 1 */
+#define HostCmd_RET_BIT 0x8000
+
+/** General purpose action : Get */
+#define HostCmd_ACT_GEN_GET 0x0000
+/** General purpose action : Set */
+#define HostCmd_ACT_GEN_SET 0x0001
+/** General purpose action : Set Default */
+#define HostCmd_ACT_GEN_SET_DEFAULT 0x0002
+/** General purpose action : Get_Current */
+#define HostCmd_ACT_GEN_GET_CURRENT 0x0003
+/** General purpose action : Remove */
+#define HostCmd_ACT_GEN_REMOVE 0x0004
+/** General purpose action : Reset */
+#define HostCmd_ACT_GEN_RESET 0x0005
+
+/** Host command action : Set Rx */
+#define HostCmd_ACT_SET_RX 0x0001
+/** Host command action : Set Tx */
+#define HostCmd_ACT_SET_TX 0x0002
+/** Host command action : Set both Rx and Tx */
+#define HostCmd_ACT_SET_BOTH 0x0003
+/** Host command action : Get Rx */
+#define HostCmd_ACT_GET_RX 0x0004
+/** Host command action : Get Tx */
+#define HostCmd_ACT_GET_TX 0x0008
+/** Host command action : Get both Rx and Tx */
+#define HostCmd_ACT_GET_BOTH 0x000c
+
+/** General Result Code*/
+/** General result code OK */
+#define HostCmd_RESULT_OK 0x0000
+/** Genenral error */
+#define HostCmd_RESULT_ERROR 0x0001
+/** Command is not valid */
+#define HostCmd_RESULT_NOT_SUPPORT 0x0002
+/** Command is pending */
+#define HostCmd_RESULT_PENDING 0x0003
+/** System is busy (command ignored) */
+#define HostCmd_RESULT_BUSY 0x0004
+/** Data buffer is not big enough */
+#define HostCmd_RESULT_PARTIAL_DATA 0x0005
+
+/* Define action or option for HostCmd_CMD_MAC_CONTROL */
+/** MAC action : Rx on */
+#define HostCmd_ACT_MAC_RX_ON 0x0001
+/** MAC action : Tx on */
+#define HostCmd_ACT_MAC_TX_ON 0x0002
+/** MAC action : WEP enable */
+#define HostCmd_ACT_MAC_WEP_ENABLE 0x0008
+/** MAC action : EthernetII enable */
+#define HostCmd_ACT_MAC_ETHERNETII_ENABLE 0x0010
+/** MAC action : Promiscous mode enable */
+#define HostCmd_ACT_MAC_PROMISCUOUS_ENABLE 0x0080
+/** MAC action : All multicast enable */
+#define HostCmd_ACT_MAC_ALL_MULTICAST_ENABLE 0x0100
+/** MAC action : RTS/CTS enable */
+#define HostCmd_ACT_MAC_RTS_CTS_ENABLE 0x0200
+/** MAC action : Strict protection enable */
+#define HostCmd_ACT_MAC_STRICT_PROTECTION_ENABLE 0x0400
+/** MAC action : Force 11n protection disable */
+#define HostCmd_ACT_MAC_FORCE_11N_PROTECTION_OFF 0x0800
+/** MAC action : Ad-Hoc G protection on */
+#define HostCmd_ACT_MAC_ADHOC_G_PROTECTION_ON 0x2000
+/** MAC action : Static-Dynamic BW enable */
+#define HostCmd_ACT_MAC_STATIC_DYNAMIC_BW_ENABLE MBIT(16)
+/** MAC action : Dynamic BW */
+#define HostCmd_ACT_MAC_DYNAMIC_BW MBIT(17)
+
+/* Define action or option for HostCmd_CMD_802_11_SCAN */
+/** Scan type : BSS */
+#define HostCmd_BSS_MODE_BSS 0x0001
+/** Scan type : IBSS */
+#define HostCmd_BSS_MODE_IBSS 0x0002
+/** Scan type : Any */
+#define HostCmd_BSS_MODE_ANY 0x0003
+
+/** Define bitmap conditions for HOST_SLEEP_CFG : GPIO FF */
+#define HOST_SLEEP_CFG_GPIO_FF 0xff
+/** Define bitmap conditions for HOST_SLEEP_CFG : GAP FF */
+#define HOST_SLEEP_CFG_GAP_FF 0xff
+
+/** Buffer Constants */
+/** Number of command buffers */
+#define MRVDRV_NUM_OF_CMD_BUFFER 40
+/** Maximum number of BSS Descriptors */
+#define MRVDRV_MAX_BSSID_LIST 200
+
+/** Host command flag in command */
+#define CMD_F_HOSTCMD (1 << 0)
+/** command cancel flag in command */
+#define CMD_F_CANCELED (1 << 1)
+/** scan command flag */
+#define CMD_F_SCAN (1 << 2)
+
+/** Host Command ID bit mask (bit 11:0) */
+#define HostCmd_CMD_ID_MASK 0x0fff
+
+/** Host Command Sequence number mask (bit 7:0) */
+#define HostCmd_SEQ_NUM_MASK 0x00ff
+
+/** Host Command BSS number mask (bit 11:8) */
+#define HostCmd_BSS_NUM_MASK 0x0f00
+
+/** Host Command BSS type mask (bit 15:12) */
+#define HostCmd_BSS_TYPE_MASK 0xf000
+
+/** Set BSS information to Host Command */
+#define HostCmd_SET_SEQ_NO_BSS_INFO(seq, num, type) \
+ ((((seq)&0x00ff) | (((num)&0x000f) << 8)) | (((type)&0x000f) << 12))
+
+/** Get Sequence Number from Host Command (bit 7:0) */
+#define HostCmd_GET_SEQ_NO(seq) ((seq)&HostCmd_SEQ_NUM_MASK)
+
+/** Get BSS number from Host Command (bit 11:8) */
+#define HostCmd_GET_BSS_NO(seq) (((seq)&HostCmd_BSS_NUM_MASK) >> 8)
+
+/** Get BSS type from Host Command (bit 15:12) */
+#define HostCmd_GET_BSS_TYPE(seq) (((seq)&HostCmd_BSS_TYPE_MASK) >> 12)
+
+/** Card Event definition : Dummy host wakeup signal */
+#define EVENT_DUMMY_HOST_WAKEUP_SIGNAL 0x00000001
+/** Card Event definition : Link lost */
+#define EVENT_LINK_LOST 0x00000003
+/** Card Event definition : Link sensed */
+#define EVENT_LINK_SENSED 0x00000004
+/** Card Event definition : MIB changed */
+#define EVENT_MIB_CHANGED 0x00000006
+/** Card Event definition : Init done */
+#define EVENT_INIT_DONE 0x00000007
+/** Card Event definition : Deauthenticated */
+#define EVENT_DEAUTHENTICATED 0x00000008
+/** Card Event definition : Disassociated */
+#define EVENT_DISASSOCIATED 0x00000009
+/** Card Event definition : Power save awake */
+#define EVENT_PS_AWAKE 0x0000000a
+/** Card Event definition : Power save sleep */
+#define EVENT_PS_SLEEP 0x0000000b
+/** Card Event definition : MIC error multicast */
+#define EVENT_MIC_ERR_MULTICAST 0x0000000d
+/** Card Event definition : MIC error unicast */
+#define EVENT_MIC_ERR_UNICAST 0x0000000e
+
+/** Card Event definition : Ad-Hoc BCN lost */
+#define EVENT_ADHOC_BCN_LOST 0x00000011
+
+/** Card Event definition : Stop Tx */
+#define EVENT_STOP_TX 0x00000013
+/** Card Event definition : Start Tx */
+#define EVENT_START_TX 0x00000014
+/** Card Event definition : Channel switch */
+#define EVENT_CHANNEL_SWITCH 0x00000015
+
+/** Card Event definition : MEAS report ready */
+#define EVENT_MEAS_REPORT_RDY 0x00000016
+
+/** Card Event definition : WMM status change */
+#define EVENT_WMM_STATUS_CHANGE 0x00000017
+
+/** Card Event definition : BG scan report */
+#define EVENT_BG_SCAN_REPORT 0x00000018
+/** Card Event definition : BG scan stopped */
+#define EVENT_BG_SCAN_STOPPED 0x00000065
+
+/** Card Event definition : Beacon RSSI low */
+#define EVENT_RSSI_LOW 0x00000019
+/** Card Event definition : Beacon SNR low */
+#define EVENT_SNR_LOW 0x0000001a
+/** Card Event definition : Maximum fail */
+#define EVENT_MAX_FAIL 0x0000001b
+/** Card Event definition : Beacon RSSI high */
+#define EVENT_RSSI_HIGH 0x0000001c
+/** Card Event definition : Beacon SNR high */
+#define EVENT_SNR_HIGH 0x0000001d
+
+/** Card Event definition : IBSS coalsced */
+#define EVENT_IBSS_COALESCED 0x0000001e
+
+/** Event definition : IBSS station connected */
+#define EVENT_IBSS_STATION_CONNECT 0x00000020
+/** Event definition : IBSS station dis-connected */
+#define EVENT_IBSS_STATION_DISCONNECT 0x00000021
+
+/** Card Event definition : Data RSSI low */
+#define EVENT_DATA_RSSI_LOW 0x00000024
+/** Card Event definition : Data SNR low */
+#define EVENT_DATA_SNR_LOW 0x00000025
+/** Card Event definition : Data RSSI high */
+#define EVENT_DATA_RSSI_HIGH 0x00000026
+/** Card Event definition : Data SNR high */
+#define EVENT_DATA_SNR_HIGH 0x00000027
+
+/** Card Event definition : Link Quality */
+#define EVENT_LINK_QUALITY 0x00000028
+
+/** Card Event definition : Port release event */
+#define EVENT_PORT_RELEASE 0x0000002b
+
+/** Card Event definition : Pre-Beacon Lost */
+#define EVENT_PRE_BEACON_LOST 0x00000031
+
+#define EVENT_WATCHDOG_TMOUT 0x00000032
+
+/** Card Event definition : Add BA event */
+#define EVENT_ADDBA 0x00000033
+/** Card Event definition : Del BA event */
+#define EVENT_DELBA 0x00000034
+/** Card Event definition: BA stream timeout*/
+#define EVENT_BA_STREAM_TIMEOUT 0x00000037
+
+/** Card Event definition : AMSDU aggr control */
+#define EVENT_AMSDU_AGGR_CTRL 0x00000042
+
+/** Card Event definition: WEP ICV error */
+#define EVENT_WEP_ICV_ERR 0x00000046
+
+/** Card Event definition : Host sleep enable */
+#define EVENT_HS_ACT_REQ 0x00000047
+
+/** Card Event definition : BW changed */
+#define EVENT_BW_CHANGE 0x00000048
+
+#ifdef WIFI_DIRECT_SUPPORT
+/** WIFIDIRECT generic event */
+#define EVENT_WIFIDIRECT_GENERIC_EVENT 0x00000049
+/** WIFIDIRECT service discovery event */
+#define EVENT_WIFIDIRECT_SERVICE_DISCOVERY 0x0000004a
+#endif
+/** Remain on Channel expired event */
+#define EVENT_REMAIN_ON_CHANNEL_EXPIRED 0x0000005f
+
+#define EVENT_MEF_HOST_WAKEUP 0x0000004f
+
+/** Card Event definition: Channel switch pending announcment */
+#define EVENT_CHANNEL_SWITCH_ANN 0x00000050
+
+/** Event definition: Radar Detected by card */
+#define EVENT_RADAR_DETECTED 0x00000053
+
+/** Event definition: Radar Detected by card */
+#define EVENT_CHANNEL_REPORT_RDY 0x00000054
+
+/** Event definition: Scan results through event */
+#define EVENT_EXT_SCAN_REPORT 0x00000058
+/** Enhance ext scan done event */
+#define EVENT_EXT_SCAN_STATUS_REPORT 0x0000007f
+
+/** Event definition : FW debug information */
+#define EVENT_FW_DEBUG_INFO 0x00000063
+
+/** Event definition: RXBA_SYNC */
+#define EVENT_RXBA_SYNC 0x00000059
+
+#ifdef UAP_SUPPORT
+/** Event ID: STA deauth */
+#define EVENT_MICRO_AP_STA_DEAUTH 0x0000002c
+/** Event ID: STA assoicated */
+#define EVENT_MICRO_AP_STA_ASSOC 0x0000002d
+/** Event ID: BSS started */
+#define EVENT_MICRO_AP_BSS_START 0x0000002e
+/** Event ID: BSS idle event */
+#define EVENT_MICRO_AP_BSS_IDLE 0x00000043
+/** Event ID: BSS active event */
+#define EVENT_MICRO_AP_BSS_ACTIVE 0x00000044
+
+/** Event ID: MIC countermeasures event */
+#define EVENT_MICRO_AP_MIC_COUNTERMEASURES 0x0000004c
+#endif /* UAP_SUPPORT */
+
+/** Event ID: TX data pause event */
+#define EVENT_TX_DATA_PAUSE 0x00000055
+
+/** Event ID: SAD Report */
+#define EVENT_SAD_REPORT 0x00000066
+
+/** Event ID: Tx status */
+#define EVENT_TX_STATUS_REPORT 0x00000074
+
+#define EVENT_BT_COEX_WLAN_PARA_CHANGE 0x00000076
+
+#if defined(PCIE)
+#define EVENT_SSU_DUMP_DMA 0x0000008C
+#endif
+
+#define EVENT_VDLL_IND 0x00000081
+#define EVENT_EXCEED_MAX_P2P_CONN 0x00000089
+
+#define EVENT_FW_HANG_REPORT 0x0000008F
+
+#define EVENT_FW_DUMP_INFO 0x00000073
+/** Event ID mask */
+#define EVENT_ID_MASK 0xffff
+
+/** BSS number mask */
+#define BSS_NUM_MASK 0xf
+
+/** Get BSS number from event cause (bit 23:16) */
+#define EVENT_GET_BSS_NUM(event_cause) (((event_cause) >> 16) & BSS_NUM_MASK)
+
+/** Get BSS type from event cause (bit 31:24) */
+#define EVENT_GET_BSS_TYPE(event_cause) (((event_cause) >> 24) & 0x00ff)
+
+/** Event_WEP_ICV_ERR structure */
+typedef MLAN_PACK_START struct _Event_WEP_ICV_ERR {
+ /** Reason code */
+ t_u16 reason_code;
+ /** Source MAC address */
+ t_u8 src_mac_addr[MLAN_MAC_ADDR_LENGTH];
+ /** WEP decryption used key */
+ t_u8 wep_key_index;
+ /** WEP key length */
+ t_u8 wep_key_length;
+ /** WEP key */
+ t_u8 key[MAX_WEP_KEY_SIZE];
+} MLAN_PACK_END Event_WEP_ICV_ERR;
+
+/** WLAN_802_11_FIXED_IEs */
+typedef MLAN_PACK_START struct _WLAN_802_11_FIXED_IEs {
+ /** Timestamp */
+ t_u8 time_stamp[8];
+ /** Beacon interval */
+ t_u16 beacon_interval;
+ /** Capabilities*/
+ t_u16 capabilities;
+} MLAN_PACK_END WLAN_802_11_FIXED_IEs;
+
+/** WLAN_802_11_VARIABLE_IEs */
+typedef MLAN_PACK_START struct _WLAN_802_11_VARIABLE_IEs {
+ /** Element ID */
+ t_u8 element_id;
+ /** Length */
+ t_u8 length;
+ /** IE data */
+ t_u8 data[1];
+} MLAN_PACK_END WLAN_802_11_VARIABLE_IEs;
+
+/** TLV related data structures*/
+#if defined(STA_SUPPORT)
+/** Pairwise Cipher Suite length */
+#define PAIRWISE_CIPHER_SUITE_LEN 4
+/** AKM Suite length */
+#define AKM_SUITE_LEN 4
+/** MFPC bit in RSN capability */
+#define MFPC_BIT 7
+/** MFPR bit in RSN capability */
+#define MFPR_BIT 6
+#endif
+/** Bit mask for TxPD status field for null packet */
+#define MRVDRV_TxPD_POWER_MGMT_NULL_PACKET 0x01
+/** Bit mask for TxPD status field for last packet */
+#define MRVDRV_TxPD_POWER_MGMT_LAST_PACKET 0x08
+
+/** Bit mask for TxPD flags field for Tx status report */
+#define MRVDRV_TxPD_FLAGS_TX_PACKET_STATUS MBIT(5)
+
+/** Packet type: 802.11 */
+#define PKT_TYPE_802DOT11 0x05
+#define PKT_TYPE_MGMT_FRAME 0xE5
+/** Packet type: AMSDU */
+#define PKT_TYPE_AMSDU 0xE6
+/** Packet type: BAR */
+#define PKT_TYPE_BAR 0xE7
+
+/** Packet type: debugging */
+#define PKT_TYPE_DEBUG 0xEF
+
+/** channel number at bit 5-13 */
+#define RXPD_CHAN_MASK 0x3FE0
+/** Rate control mask 15-23 */
+#define TXPD_RATE_MASK 0xff8000
+/** enable bw ctrl in TxPD */
+#define TXPD_BW_ENABLE MBIT(20)
+/** enable tx power ctrl in TxPD */
+#define TXPD_TXPW_ENABLE MBIT(7)
+/** sign of power */
+#define TXPD_TXPW_NEGATIVE MBIT(6)
+/** Enable Rate ctrl in TxPD */
+#define TXPD_TXRATE_ENABLE MBIT(15)
+/** enable retry limit in TxPD */
+#define TXPD_RETRY_ENABLE MBIT(12)
+
+/** TxPD descriptor */
+typedef MLAN_PACK_START struct _TxPD {
+ /** BSS type */
+ t_u8 bss_type;
+ /** BSS number */
+ t_u8 bss_num;
+ /** Tx packet length */
+ t_u16 tx_pkt_length;
+ /** Tx packet offset */
+ t_u16 tx_pkt_offset;
+ /** Tx packet type */
+ t_u16 tx_pkt_type;
+ /** Tx Control */
+ t_u32 tx_control;
+ /** Pkt Priority */
+ t_u8 priority;
+ /** Transmit Pkt Flags*/
+ t_u8 flags;
+ /** Amount of time the packet has been queued
+ * in the driver (units = 2ms)*/
+ t_u8 pkt_delay_2ms;
+ /** reserved */
+ t_u8 reserved;
+ /** Tx Control */
+ t_u32 tx_control_1;
+} MLAN_PACK_END TxPD, *PTxPD;
+
+/** RxPD Descriptor */
+typedef MLAN_PACK_START struct _RxPD {
+ /** BSS type */
+ t_u8 bss_type;
+ /** BSS number */
+ t_u8 bss_num;
+ /** Rx Packet Length */
+ t_u16 rx_pkt_length;
+ /** Rx Pkt offset */
+ t_u16 rx_pkt_offset;
+ /** Rx packet type */
+ t_u16 rx_pkt_type;
+ /** Sequence number */
+ t_u16 seq_num;
+ /** Packet Priority */
+ t_u8 priority;
+ /** Rx Packet Rate */
+ t_u8 rx_rate;
+ /** SNR */
+ t_s8 snr;
+ /** Noise Floor */
+ t_s8 nf;
+ /** [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] [Bit4,
+ * Bit7] AX Guard interval, 00, 01, 10 */
+ t_u8 rate_info;
+ /** Reserved */
+ t_u8 reserved[3];
+ /** TDLS flags, bit 0: 0=InfraLink, 1=DirectLink */
+ t_u8 flags;
+ /**For SD8887 antenna info: 0 = 2.4G antenna a; 1 = 2.4G antenna b; 3 =
+ * 5G antenna; 0xff = invalid value */
+ t_u8 antenna;
+ /* [31:0] ToA of the rx packet, [63:32] ToD of the ack for the rx packet
+ * Both ToA and ToD are in nanoseconds */
+ t_u64 toa_tod_tstamps;
+ /** rx info */
+ t_u32 rx_info;
+} MLAN_PACK_END RxPD, *PRxPD;
+
+/** IEEEtypes_FrameCtl_t*/
+#ifdef BIG_ENDIAN_SUPPORT
+typedef MLAN_PACK_START struct _IEEEtypes_FrameCtl_t {
+ /** Order */
+ t_u8 order : 1;
+ /** Wep */
+ t_u8 wep : 1;
+ /** More Data */
+ t_u8 more_data : 1;
+ /** Power Mgmt */
+ t_u8 pwr_mgmt : 1;
+ /** Retry */
+ t_u8 retry : 1;
+ /** More Frag */
+ t_u8 more_frag : 1;
+ /** From DS */
+ t_u8 from_ds : 1;
+ /** To DS */
+ t_u8 to_ds : 1;
+ /** Sub Type */
+ t_u8 sub_type : 4;
+ /** Type */
+ t_u8 type : 2;
+ /** Protocol Version */
+ t_u8 protocol_version : 2;
+} MLAN_PACK_END IEEEtypes_FrameCtl_t;
+#else
+typedef MLAN_PACK_START struct _IEEEtypes_FrameCtl_t {
+ /** Protocol Version */
+ t_u8 protocol_version : 2;
+ /** Type */
+ t_u8 type : 2;
+ /** Sub Type */
+ t_u8 sub_type : 4;
+ /** To DS */
+ t_u8 to_ds : 1;
+ /** From DS */
+ t_u8 from_ds : 1;
+ /** More Frag */
+ t_u8 more_frag : 1;
+ /** Retry */
+ t_u8 retry : 1;
+ /** Power Mgmt */
+ t_u8 pwr_mgmt : 1;
+ /** More Data */
+ t_u8 more_data : 1;
+ /** Wep */
+ t_u8 wep : 1;
+ /** Order */
+ t_u8 order : 1;
+} MLAN_PACK_END IEEEtypes_FrameCtl_t;
+#endif
+
+/** MrvlIETypes_MgmtFrameSet_t */
+typedef MLAN_PACK_START struct _MrvlIETypes_MgmtFrameSet_t {
+ /** Type */
+ t_u16 type;
+ /** Length */
+ t_u16 len;
+ /** Frame Control */
+ IEEEtypes_FrameCtl_t frame_control;
+ /* t_u8 frame_contents[]; */
+} MLAN_PACK_END MrvlIETypes_MgmtFrameSet_t;
+
+/** Beacon */
+typedef MLAN_PACK_START struct _IEEEtypes_Beacon_t {
+ /** time stamp */
+ t_u8 time_stamp[8];
+ /** beacon interval */
+ t_u16 beacon_interval;
+ /** cap info */
+ t_u16 cap_info;
+} MLAN_PACK_END IEEEtypes_Beacon_t;
+
+/** Fixed size of station association event */
+#define ASSOC_EVENT_FIX_SIZE 12
+
+/** MrvlIEtypes_channel_band_t */
+typedef MLAN_PACK_START struct _MrvlIEtypes_channel_band_t {
+ /** Header */
+ MrvlIEtypesHeader_t header;
+ /** Band Configuration */
+ Band_Config_t bandcfg;
+ /** channel */
+ t_u8 channel;
+} MLAN_PACK_END MrvlIEtypes_channel_band_t;
+
+#ifdef UAP_SUPPORT
+/** IEEEtypes_AssocRqst_t */
+typedef MLAN_PACK_START struct _IEEEtypes_AssocRqst_t {
+ /** Capability Info */
+ t_u16 cap_info;
+ /** Listen Interval */
+ t_u16 listen_interval;
+ /* t_u8 ie_buffer[]; */
+} MLAN_PACK_END IEEEtypes_AssocRqst_t;
+
+/** IEEEtypes_ReAssocRqst_t */
+typedef MLAN_PACK_START struct _IEEEtypes_ReAssocRqst_t {
+ /** Capability Info */
+ t_u16 cap_info;
+ /** Listen Interval */
+ t_u16 listen_interval;
+ /** Current AP Address */
+ t_u8 current_ap_addr[MLAN_MAC_ADDR_LENGTH];
+ /* t_u8 ie_buffer[]; */
+} MLAN_PACK_END IEEEtypes_ReAssocRqst_t;
+#endif /* UAP_SUPPORT */
+
+/** wlan_802_11_header */
+typedef MLAN_PACK_START struct _wlan_802_11_header {
+ /** Frame Control */
+ t_u16 frm_ctl;
+ /** Duration ID */
+ t_u16 duration_id;
+ /** Address1 */
+ mlan_802_11_mac_addr addr1;
+ /** Address2 */
+ mlan_802_11_mac_addr addr2;
+ /** Address3 */
+ mlan_802_11_mac_addr addr3;
+ /** Sequence Control */
+ t_u16 seq_ctl;
+ /** Address4 */
+ mlan_802_11_mac_addr addr4;
+} MLAN_PACK_END wlan_802_11_header;
+
+/** wlan_802_11_header packet from FW with length */
+typedef MLAN_PACK_START struct _wlan_mgmt_pkt {
+ /** Packet Length */
+ t_u16 frm_len;
+ /** wlan_802_11_header */
+ wlan_802_11_header wlan_header;
+} MLAN_PACK_END wlan_mgmt_pkt;
+
+#ifdef STA_SUPPORT
+/** (Beaconsize(256)-5(IEId,len,contrystr(3))/3(FirstChan,NoOfChan,MaxPwr) */
+#define MAX_NO_OF_CHAN 40
+
+/** Channel-power table entries */
+typedef MLAN_PACK_START struct _chan_power_11d {
+ /** 11D channel */
+ t_u8 chan;
+ /** Band for channel */
+ t_u8 band;
+ /** 11D channel power */
+ t_u8 pwr;
+ /** AP seen on channel */
+ t_u8 ap_seen;
+} MLAN_PACK_END chan_power_11d_t;
+
+/** Region channel info */
+typedef MLAN_PACK_START struct _parsed_region_chan_11d {
+ /** 11D channel power per channel */
+ chan_power_11d_t chan_pwr[MAX_NO_OF_CHAN];
+ /** 11D number of channels */
+ t_u8 no_of_chan;
+} MLAN_PACK_END parsed_region_chan_11d_t;
+#endif /* STA_SUPPORT */
+
+/** ChanScanMode_t */
+typedef MLAN_PACK_START struct _ChanScanMode_t {
+#ifdef BIG_ENDIAN_SUPPORT
+ /** Reserved */
+ t_u8 reserved_7 : 1;
+ /** First passive scan then active scan */
+ t_u8 passive_to_active_scan : 1;
+ /** First channel in scan */
+ t_u8 first_chan : 1;
+ /** Enable hidden ssid report */
+ t_u8 hidden_ssid_report : 1;
+ /** Enable probe response timeout */
+ t_u8 rsp_timeout_en : 1;
+ /** Multidomain scan mode */
+ t_u8 multidomain_scan : 1;
+ /** Disble channel filtering flag */
+ t_u8 disable_chan_filt : 1;
+ /** Channel scan mode passive flag */
+ t_u8 passive_scan : 1;
+#else
+ /** Channel scan mode passive flag */
+ t_u8 passive_scan : 1;
+ /** Disble channel filtering flag */
+ t_u8 disable_chan_filt : 1;
+ /** Multidomain scan mode */
+ t_u8 multidomain_scan : 1;
+ /** Enable probe response timeout */
+ t_u8 rsp_timeout_en : 1;
+ /** Enable hidden ssid report */
+ t_u8 hidden_ssid_report : 1;
+ /** First channel in scan */
+ t_u8 first_chan : 1;
+ /** First passive scan then active scan */
+ t_u8 passive_to_active_scan : 1;
+ /** Reserved */
+ t_u8 reserved_7 : 1;
+#endif
+} MLAN_PACK_END ChanScanMode_t;
+
+/** ChanScanParamSet_t */
+typedef MLAN_PACK_START struct _ChanScanParamSet_t {
+ /** Channel scan parameter : band config */
+ Band_Config_t bandcfg;
+ /** Channel scan parameter : Channel number */
+ t_u8 chan_number;
+ /** Channel scan parameter : Channel scan mode */
+ ChanScanMode_t chan_scan_mode;
+ /** Channel scan parameter : Minimum scan time */
+ t_u16 min_scan_time;
+ /** Channel scan parameter : Maximum scan time */
+ t_u16 max_scan_time;
+} MLAN_PACK_END ChanScanParamSet_t;
+
+/** MrvlIEtypes_ChanListParamSet_t */
+typedef MLAN_PACK_START struct _MrvlIEtypes_ChanListParamSet_t {
+ /** Header */
+ MrvlIEtypesHeader_t header;
+ /** Channel scan parameters */
+ ChanScanParamSet_t chan_scan_param[1];
+} MLAN_PACK_END MrvlIEtypes_ChanListParamSet_t;
+
+/** MrvlIEtypes_EESParamSet_t */
+typedef MLAN_PACK_START struct _MrvlIEtypes_EESParamSet_t {
+ /** Header */
+ MrvlIEtypesHeader_t header;
+ /** EES scan mode */
+ t_u16 ees_mode;
+ /** EES report condition */
+ t_u16 report_cond;
+ /** EES High Period scan interval */
+ t_u16 high_period;
+ /** EES High Period scan count */
+ t_u16 high_period_count;
+ /** EES Medium Period scan interval */
+ t_u16 mid_period;
+ /** EES Medium Period scan count */
+ t_u16 mid_period_count;
+ /** EES Low Period scan interval */
+ t_u16 low_period;
+ /** EES Low Period scan count */
+ t_u16 low_period_count;
+} MLAN_PACK_END MrvlIEtypes_EESParamSet_t;
+
+/** MrvlIEtype_EESNetworkCfg_t */
+typedef MLAN_PACK_START struct _MrvlIEtype_EESNetworkCfg_t {
+ /** Header */
+ MrvlIEtypesHeader_t header;
+ /** Number of networks in the list */
+ t_u8 network_count;
+ /** Maximum number of connection */
+ t_u8 max_conn_count;
+ /** Black List Exp */
+ t_u8 black_list_exp;
+} MLAN_PACK_END MrvlIEtype_EESNetworkCfg_t;
+
+/** ChanBandParamSet_t */
+typedef struct _ChanBandParamSet_t {
+ /** Channel scan parameter : band config */
+ Band_Config_t bandcfg;
+ /** Channel number */
+ t_u8 chan_number;
+} ChanBandParamSet_t;
+
+/** MrvlIEtypes_ChanBandListParamSet_t */
+typedef MLAN_PACK_START struct _MrvlIEtypes_ChanBandListParamSet_t {
+ /** Header */
+ MrvlIEtypesHeader_t header;
+ /** Channel Band parameters */
+ ChanBandParamSet_t chan_band_param[1];
+} MLAN_PACK_END MrvlIEtypes_ChanBandListParamSet_t;
+
+/** MrvlIEtypes_RatesParamSet_t */
+typedef MLAN_PACK_START struct _MrvlIEtypes_RatesParamSet_t {
+ /** Header */
+ MrvlIEtypesHeader_t header;
+ /** Rates */
+ t_u8 rates[1];
+} MLAN_PACK_END MrvlIEtypes_RatesParamSet_t;
+
+/** _MrvlIEtypes_Bssid_List_t */
+typedef MLAN_PACK_START struct _MrvlIEtypes_Bssid_List_t {
+ /** Header */
+ MrvlIEtypesHeader_t header;
+ /** BSSID */
+ t_u8 bssid[MLAN_MAC_ADDR_LENGTH];
+} MLAN_PACK_END MrvlIEtypes_Bssid_List_t;
+
+/** MrvlIEtypes_SsIdParamSet_t */
+typedef MLAN_PACK_START struct _MrvlIEtypes_SsIdParamSet_t {
+ /** Header */
+ MrvlIEtypesHeader_t header;
+ /** SSID */
+ t_u8 ssid[1];
+} MLAN_PACK_END MrvlIEtypes_SsIdParamSet_t;
+
+/**MrvlIEtypes_AssocType_t */
+typedef MLAN_PACK_START struct _MrvlIEtypes_HostMlme_t {
+ /** Header */
+ MrvlIEtypesHeader_t header;
+ /** Authentication type */
+ t_u8 host_mlme;
+} MLAN_PACK_END MrvlIEtypes_HostMlme_t;
+
+/** MrvlIEtypes_NumProbes_t */
+typedef MLAN_PACK_START struct _MrvlIEtypes_NumProbes_t {
+ /** Header */
+ MrvlIEtypesHeader_t header;
+ /** Number of probes */
+ t_u16 num_probes;
+} MLAN_PACK_END MrvlIEtypes_NumProbes_t;
+
+/** MrvlIEtypes_WildCardSsIdParamSet_t */
+typedef MLAN_PACK_START struct _MrvlIEtypes_WildCardSsIdParamSet_t {
+ /** Header */
+ MrvlIEtypesHeader_t header;
+ /** Maximum SSID length */
+ t_u8 max_ssid_length;
+ /** SSID */
+ t_u8 ssid[1];
+} MLAN_PACK_END MrvlIEtypes_WildCardSsIdParamSet_t;
+
+/**TSF data size */
+#define TSF_DATA_SIZE 8
+/** Table of TSF values returned in the scan result */
+typedef MLAN_PACK_START struct _MrvlIEtypes_TsfTimestamp_t {
+ /** Header */
+ MrvlIEtypesHeader_t header;
+ /** the length of each TSF data is 8 bytes, could be multiple TSF here
+ */
+ t_u8 tsf_data[1];
+} MLAN_PACK_END MrvlIEtypes_TsfTimestamp_t;
+
+/** CfParamSet_t */
+typedef MLAN_PACK_START struct _CfParamSet_t {
+ /** CF parameter : Count */
+ t_u8 cfp_cnt;
+ /** CF parameter : Period */
+ t_u8 cfp_period;
+ /** CF parameter : Duration */
+ t_u16 cfp_max_duration;
+ /** CF parameter : Duration remaining */
+ t_u16 cfp_duration_remaining;
+} MLAN_PACK_END CfParamSet_t;
+
+/** IbssParamSet_t */
+typedef MLAN_PACK_START struct _IbssParamSet_t {
+ /** ATIM window value */
+ t_u16 atim_window;
+} MLAN_PACK_END IbssParamSet_t;
+
+/** MrvlIEtypes_SsParamSet_t */
+typedef MLAN_PACK_START struct _MrvlIEtypes_SsParamSet_t {
+ /** Header */
+ MrvlIEtypesHeader_t header;
+ /** CF/IBSS parameters sets */
+ union {
+ /** CF parameter set */
+ CfParamSet_t cf_param_set[1];
+ /** IBSS parameter set */
+ IbssParamSet_t ibss_param_set[1];
+ } cf_ibss;
+} MLAN_PACK_END MrvlIEtypes_SsParamSet_t;
+
+/** FhParamSet_t */
+typedef MLAN_PACK_START struct _FhParamSet_t {
+ /** FH parameter : Dwell time */
+ t_u16 dwell_time;
+ /** FH parameter : Hop set */
+ t_u8 hop_set;
+ /** FH parameter : Hop pattern */
+ t_u8 hop_pattern;
+ /** FH parameter : Hop index */
+ t_u8 hop_index;
+} MLAN_PACK_END FhParamSet_t;
+
+/** DsParamSet_t */
+typedef MLAN_PACK_START struct _DsParamSet_t {
+ /** Current channel number */
+ t_u8 current_chan;
+} MLAN_PACK_END DsParamSet_t;
+
+/** MrvlIEtypes_PhyParamSet_t */
+typedef MLAN_PACK_START struct _MrvlIEtypes_PhyParamSet_t {
+ /** Header */
+ MrvlIEtypesHeader_t header;
+ /** FH/DS parameters */
+ union {
+ /** FH parameter set */
+ FhParamSet_t fh_param_set[1];
+ /** DS parameter set */
+ DsParamSet_t ds_param_set[1];
+ } fh_ds;
+} MLAN_PACK_END MrvlIEtypes_PhyParamSet_t;
+
+/* Auth type to be used in the Authentication portion of an Assoc seq */
+/** MrvlIEtypes_AuthType_t */
+typedef MLAN_PACK_START struct _MrvlIEtypes_AuthType_t {
+ /** Header */
+ MrvlIEtypesHeader_t header;
+ /** Authentication type */
+ t_u16 auth_type;
+} MLAN_PACK_END MrvlIEtypes_AuthType_t;
+
+/** MrvlIEtypes_ScanChanGap_t */
+typedef MLAN_PACK_START struct _MrvlIEtypes_ScanChanGap_t {
+ /** Header */
+ MrvlIEtypesHeader_t header;
+ /** Time gap in units to TUs to be used between
+ * two consecutive channels scan */
+ t_u16 gap;
+} MLAN_PACK_END MrvlIEtypes_ScanChanGap_t;
+
+/** channel statictics */
+typedef MLAN_PACK_START struct _chan_statistics_t {
+ /** channle number */
+ t_u8 chan_num;
+ /** band info */
+ Band_Config_t bandcfg;
+ /** flags */
+ t_u8 flags;
+ /** noise */
+ t_s8 noise;
+ /** total network */
+ t_u16 total_networks;
+ /** scan duration */
+ t_u16 cca_scan_duration;
+ /** busy duration */
+ t_u16 cca_busy_duration;
+} MLAN_PACK_END chan_statistics_t;
+
+/** channel statictics tlv */
+typedef MLAN_PACK_START struct _MrvlIEtypes_ChannelStats_t {
+ /** Header */
+ MrvlIEtypesHeader_t header;
+ /** channel statictics */
+ chan_statistics_t chanStat[];
+} MLAN_PACK_END MrvlIEtypes_ChannelStats_t;
+
+/** MrvlIETypes_ActionFrame_t */
+typedef MLAN_PACK_START struct {
+ MrvlIEtypesHeader_t header; /**< Header */
+
+ t_u8 srcAddr[MLAN_MAC_ADDR_LENGTH];
+ t_u8 dstAddr[MLAN_MAC_ADDR_LENGTH];
+
+ IEEEtypes_ActionFrame_t actionFrame;
+
+} MLAN_PACK_END MrvlIETypes_ActionFrame_t;
+
+/** MrvlIEtypes_RxBaSync_t */
+typedef MLAN_PACK_START struct _MrvlIEtypes_RxBaSync_t {
+ /** Header */
+ MrvlIEtypesHeader_t header;
+ /** mac address */
+ t_u8 mac[MLAN_MAC_ADDR_LENGTH];
+ /** tid */
+ t_u8 tid;
+ /** reserved field */
+ t_u8 reserved;
+ /** start seq num */
+ t_u16 seq_num;
+ /** bitmap len */
+ t_u16 bitmap_len;
+ /** bitmap */
+ t_u8 bitmap[1];
+} MLAN_PACK_END MrvlIEtypes_RxBaSync_t;
+
+/** MrvlIEtypes_RsnParamSet_t */
+typedef MLAN_PACK_START struct _MrvlIEtypes_RsnParamSet_t {
+ /** Header */
+ MrvlIEtypesHeader_t header;
+ /** RSN IE */
+ t_u8 rsn_ie[];
+} MLAN_PACK_END MrvlIEtypes_RsnParamSet_t;
+
+/** MrvlIEtypes_SecurityCfg_t */
+typedef MLAN_PACK_START struct _MrvlIEtypes_SecurityCfg_t {
+ /** Header */
+ MrvlIEtypesHeader_t header;
+ /** enable 11w */
+ t_u8 use_mfp;
+} MLAN_PACK_END MrvlIEtypes_SecurityCfg_t;
+
+/** Host Command ID : _HostCmd_DS_BEACON_STUCK_CFG */
+typedef MLAN_PACK_START struct _HostCmd_DS_BEACON_STUCK_CFG {
+ /** ACT_GET/ACT_SET */
+ t_u8 action;
+ /** No of beacon interval after which firmware will check if beacon Tx
+ * is going fine */
+ t_u8 beacon_stuck_detect_count;
+ /** Upon performing MAC reset, no of beacon interval after which
+ * firmware will check if recovery was successful */
+ t_u8 recovery_confirm_count;
+} MLAN_PACK_END HostCmd_DS_BEACON_STUCK_CFG;
+
+/** Key Info flag for multicast key */
+#define KEY_INFO_MCAST_KEY 0x01
+/** Key Info flag for unicast key */
+#define KEY_INFO_UCAST_KEY 0x02
+/** Key Info flag for enable key */
+#define KEY_INFO_ENABLE_KEY 0x04
+/** Key Info flag for default key */
+#define KEY_INFO_DEFAULT_KEY 0x08
+/** Key Info flag for TX key */
+#define KEY_INFO_TX_KEY 0x10
+/** Key Info flag for RX key */
+#define KEY_INFO_RX_KEY 0x20
+#define KEY_INFO_CMAC_AES_KEY 0x400
+/** PN size for WPA/WPA2 */
+#define WPA_PN_SIZE 8
+/** PN size for PMF IGTK */
+#define IGTK_PN_SIZE 8
+/** WAPI KEY size */
+#define WAPI_KEY_SIZE 32
+/** key params fix size */
+#define KEY_PARAMS_FIXED_LEN 10
+/** key index mask */
+#define KEY_INDEX_MASK 0xf
+
+/** wep_param */
+typedef MLAN_PACK_START struct _wep_param_t {
+ /** key_len */
+ t_u16 key_len;
+ /** wep key */
+ t_u8 key[MAX_WEP_KEY_SIZE];
+} MLAN_PACK_END wep_param_t;
+
+/** tkip_param */
+typedef MLAN_PACK_START struct _tkip_param {
+ /** Rx packet num */
+ t_u8 pn[WPA_PN_SIZE];
+ /** key_len */
+ t_u16 key_len;
+ /** tkip key */
+ t_u8 key[WPA_TKIP_KEY_LEN];
+} MLAN_PACK_END tkip_param;
+
+/** aes_param */
+typedef MLAN_PACK_START struct _aes_param {
+ /** Rx packet num */
+ t_u8 pn[WPA_PN_SIZE];
+ /** key_len */
+ t_u16 key_len;
+ /** aes key */
+ t_u8 key[WPA_AES_KEY_LEN];
+} MLAN_PACK_END aes_param;
+
+/** wapi_param */
+typedef MLAN_PACK_START struct _wapi_param {
+ /** Rx packet num */
+ t_u8 pn[PN_SIZE];
+ /** key_len */
+ t_u16 key_len;
+ /** wapi key */
+ t_u8 key[WAPI_KEY_SIZE];
+} MLAN_PACK_END wapi_param;
+
+/** cmac_aes_param */
+typedef MLAN_PACK_START struct _cmac_aes_param {
+ /** IGTK pn */
+ t_u8 ipn[IGTK_PN_SIZE];
+ /** key_len */
+ t_u16 key_len;
+ /** aes key */
+ t_u8 key[CMAC_AES_KEY_LEN];
+} MLAN_PACK_END cmac_aes_param;
+
+/** gmac_param */
+typedef MLAN_PACK_START struct _gcmp_param {
+ /** GCMP pn */
+ t_u8 pn[WPA_PN_SIZE];
+ /** key_len */
+ t_u16 key_len;
+ /** aes key */
+ t_u8 key[WPA_GCMP_KEY_LEN];
+} MLAN_PACK_END gcmp_param;
+
+/** ccmp256_param */
+typedef MLAN_PACK_START struct _ccmp256_param {
+ /** CCMP pn */
+ t_u8 pn[WPA_PN_SIZE];
+ /** key_len */
+ t_u16 key_len;
+ /** ccmp256 key */
+ t_u8 key[WPA_CCMP_256_KEY_LEN];
+} MLAN_PACK_END ccmp_256_param;
+
+/** MrvlIEtype_KeyParamSet_t */
+typedef MLAN_PACK_START struct _MrvlIEtype_KeyParamSetV2_t {
+ /** Type ID */
+ t_u16 type;
+ /** Length of Payload */
+ t_u16 length;
+ /** mac address */
+ t_u8 mac_addr[MLAN_MAC_ADDR_LENGTH];
+ /** key index */
+ t_u8 key_idx;
+ /** Type of Key: WEP=0, TKIP=1, AES=2, WAPI=3 AES_CMAC=4 */
+ t_u8 key_type;
+ /** Key Control Info specific to a key_type_id */
+ t_u16 key_info;
+ union {
+ /** wep key param */
+ wep_param_t wep;
+ /** tkip key param */
+ tkip_param tkip;
+ /** aes key param */
+ aes_param aes;
+ /** wapi key param */
+ wapi_param wapi;
+ /** IGTK key param */
+ cmac_aes_param cmac_aes;
+ /** gcmp key param */
+ gcmp_param gcmp;
+ /** ccmp 256 key parameters */
+ ccmp_256_param ccmp256;
+ } key_params;
+} MLAN_PACK_END MrvlIEtype_KeyParamSetV2_t;
+
+/** HostCmd_DS_802_11_KEY_MATERIAL */
+typedef MLAN_PACK_START struct _HostCmd_DS_802_11_KEY_MATERIAL {
+ /** Action */
+ t_u16 action;
+ /** Key parameter set */
+ MrvlIEtype_KeyParamSetV2_t key_param_set;
+} MLAN_PACK_END HostCmd_DS_802_11_KEY_MATERIAL;
+
+/** HostCmd_DS_GTK_REKEY_PARAMS */
+typedef MLAN_PACK_START struct _HostCmd_DS_GTK_REKEY_PARAMS {
+ /** Action */
+ t_u16 action;
+ /** Key confirmation key */
+ t_u8 kck[MLAN_KCK_LEN];
+ /** Key encryption key */
+ t_u8 kek[MLAN_KEK_LEN];
+ /** Replay counter low 32 bit */
+ t_u32 replay_ctr_low;
+ /** Replay counter high 32 bit */
+ t_u32 replay_ctr_high;
+} MLAN_PACK_END HostCmd_DS_GTK_REKEY_PARAMS;
+
+/** Data structure of WMM QoS information */
+typedef MLAN_PACK_START struct _WmmQosInfo_t {
+#ifdef BIG_ENDIAN_SUPPORT
+ /** QoS UAPSD */
+ t_u8 qos_uapsd : 1;
+ /** Reserved */
+ t_u8 reserved : 3;
+ /** Parameter set count */
+ t_u8 para_set_count : 4;
+#else
+ /** Parameter set count */
+ t_u8 para_set_count : 4;
+ /** Reserved */
+ t_u8 reserved : 3;
+ /** QoS UAPSD */
+ t_u8 qos_uapsd : 1;
+#endif /* BIG_ENDIAN_SUPPORT */
+} MLAN_PACK_END WmmQosInfo_t, *pWmmQosInfo_t;
+
+/** Data structure of WMM ECW */
+typedef MLAN_PACK_START struct _WmmEcw_t {
+#ifdef BIG_ENDIAN_SUPPORT
+ /** Maximum Ecw */
+ t_u8 ecw_max : 4;
+ /** Minimum Ecw */
+ t_u8 ecw_min : 4;
+#else
+ /** Minimum Ecw */
+ t_u8 ecw_min : 4;
+ /** Maximum Ecw */
+ t_u8 ecw_max : 4;
+#endif /* BIG_ENDIAN_SUPPORT */
+} MLAN_PACK_END WmmEcw_t, *pWmmEcw_t;
+
+/** Data structure of WMM Aci/Aifsn */
+typedef MLAN_PACK_START struct _WmmAciAifsn_t {
+#ifdef BIG_ENDIAN_SUPPORT
+ /** Reserved */
+ t_u8 reserved : 1;
+ /** Aci */
+ t_u8 aci : 2;
+ /** Acm */
+ t_u8 acm : 1;
+ /** Aifsn */
+ t_u8 aifsn : 4;
+#else
+ /** Aifsn */
+ t_u8 aifsn : 4;
+ /** Acm */
+ t_u8 acm : 1;
+ /** Aci */
+ t_u8 aci : 2;
+ /** Reserved */
+ t_u8 reserved : 1;
+#endif /* BIG_ENDIAN_SUPPORT */
+} MLAN_PACK_END WmmAciAifsn_t, *pWmmAciAifsn_t;
+
+/** Data structure of WMM AC parameters */
+typedef MLAN_PACK_START struct _WmmAcParameters_t {
+ WmmAciAifsn_t aci_aifsn; /**< AciAifSn */
+ WmmEcw_t ecw; /**< Ecw */
+ t_u16 tx_op_limit; /**< Tx op limit */
+} MLAN_PACK_END WmmAcParameters_t, *pWmmAcParameters_t;
+
+/** Data structure of WMM parameter */
+typedef MLAN_PACK_START struct _WmmParameter_t {
+ /** OuiType: 00:50:f2:02 */
+ t_u8 ouitype[4];
+ /** Oui subtype: 01 */
+ t_u8 ouisubtype;
+ /** version: 01 */
+ t_u8 version;
+ /** QoS information */
+ t_u8 qos_info;
+ /** Reserved */
+ t_u8 reserved;
+ /** AC Parameters Record WMM_AC_BE, WMM_AC_BK, WMM_AC_VI, WMM_AC_VO */
+ WmmAcParameters_t ac_params[MAX_AC_QUEUES];
+} MLAN_PACK_END WmmParameter_t, *pWmmParameter_t;
+
+/** Data structure of Host command WMM_PARAM_CFG */
+typedef MLAN_PACK_START struct _HostCmd_DS_WMM_PARAM_CONFIG {
+ /** action */
+ t_u16 action;
+ /** AC Parameters Record WMM_AC_BE, WMM_AC_BK, WMM_AC_VI, WMM_AC_VO */
+ WmmAcParameters_t ac_params[MAX_AC_QUEUES];
+} MLAN_PACK_END HostCmd_DS_WMM_PARAM_CONFIG;
+
+/* Definition of firmware host command */
+/** HostCmd_DS_GEN */
+typedef MLAN_PACK_START struct _HostCmd_DS_GEN {
+ /** Command */
+ t_u16 command;
+ /** Size */
+ t_u16 size;
+ /** Sequence number */
+ t_u16 seq_num;
+ /** Result */
+ t_u16 result;
+} MLAN_PACK_END HostCmd_DS_GEN
+
+ ;
+
+/** Size of HostCmd_DS_GEN */
+#define S_DS_GEN sizeof(HostCmd_DS_GEN)
+
+/** mod_group_setting */
+typedef MLAN_PACK_START struct _mod_group_setting {
+ /** modulation group */
+ t_u8 mod_group;
+ /** power */
+ t_u8 power;
+} MLAN_PACK_END mod_group_setting;
+
+/** MrvlIETypes_ChanTRPCConfig_t */
+typedef MLAN_PACK_START struct _MrvlIETypes_ChanTRPCConfig_t {
+ /** Header */
+ MrvlIEtypesHeader_t header;
+ /** start freq */
+ t_u16 start_freq;
+ /* channel width */
+ t_u8 width;
+ /** channel number */
+ t_u8 chan_num;
+ /** mode groups */
+ mod_group_setting mod_group[];
+} MLAN_PACK_END MrvlIETypes_ChanTRPCConfig_t;
+
+/* HostCmd_DS_CHANNEL_TRPC_CONFIG */
+typedef MLAN_PACK_START struct _HostCmd_DS_CHANNEL_TRPC_CONFIG {
+ /** action */
+ t_u16 action;
+ /** 0/1/2/3 */
+ t_u16 sub_band;
+ /** chan TRPC config */
+ MrvlIETypes_ChanTRPCConfig_t tlv[];
+} MLAN_PACK_END HostCmd_DS_CHANNEL_TRPC_CONFIG;
+
+typedef MLAN_PACK_START struct _HostCmd_DS_MEF_CFG {
+ /** Criteria */
+ t_u32 criteria;
+ /** Number of entries */
+ t_u16 nentries;
+} MLAN_PACK_END HostCmd_DS_MEF_CFG;
+
+#define MAX_NUM_STACK_BYTES 100
+/** mef stack struct*/
+typedef MLAN_PACK_START struct _mef_stack {
+ /** length of byte*/
+ t_u16 sp;
+ /** data of filter items*/
+ t_u8 byte[MAX_NUM_STACK_BYTES];
+} MLAN_PACK_END mef_stack;
+
+/** mef entry struct */
+typedef MLAN_PACK_START struct _mef_entry_header {
+ /**mode:1->hostsleep;2->non hostsleep mode*/
+ t_u8 mode;
+ /**action=0->discard and not wake host
+ * action=1->discard and wake host
+ * action=3->allow and wake host*/
+ t_u8 action;
+} MLAN_PACK_END mef_entry_header;
+
+/** mef op struct is to help to generate mef data*/
+typedef MLAN_PACK_START struct _mef_op {
+ /** operand_type*/
+ t_u8 operand_type;
+ /** reserved*/
+ t_u8 rsvd[3];
+ /** data */
+ t_u8 val[MAX_NUM_BYTE_SEQ + 1];
+} MLAN_PACK_END mef_op;
+
+/* HostCmd_DS_802_11_SLEEP_PERIOD */
+typedef MLAN_PACK_START struct _HostCmd_DS_802_11_SLEEP_PERIOD {
+ /** ACT_GET/ACT_SET */
+ t_u16 action;
+
+ /** Sleep Period in msec */
+ t_u16 sleep_pd;
+} MLAN_PACK_END HostCmd_DS_802_11_SLEEP_PERIOD;
+
+/* HostCmd_DS_802_11_SLEEP_PARAMS */
+typedef MLAN_PACK_START struct _HostCmd_DS_802_11_SLEEP_PARAMS {
+ /** ACT_GET/ACT_SET */
+ t_u16 action;
+ /** Sleep clock error in ppm */
+ t_u16 error;
+ /** Wakeup offset in usec */
+ t_u16 offset;
+ /** Clock stabilization time in usec */
+ t_u16 stable_time;
+ /** Control periodic calibration */
+ t_u8 cal_control;
+ /** Control the use of external sleep clock */
+ t_u8 external_sleep_clk;
+ /** Reserved field, should be set to zero */
+ t_u16 reserved;
+} MLAN_PACK_END HostCmd_DS_802_11_SLEEP_PARAMS;
+
+/** Sleep response control */
+typedef enum _sleep_resp_ctrl {
+ RESP_NOT_NEEDED = 0,
+ RESP_NEEDED,
+} sleep_resp_ctrl;
+
+/** Structure definition for the new ieee power save parameters*/
+typedef MLAN_PACK_START struct __ps_param {
+ /** Null packet interval */
+ t_u16 null_pkt_interval;
+ /** Num dtims */
+ t_u16 multiple_dtims;
+ /** becaon miss interval */
+ t_u16 bcn_miss_timeout;
+ /** local listen interval */
+ t_u16 local_listen_interval;
+ /** Adhoc awake period */
+ t_u16 adhoc_wake_period;
+ /** mode - (0x01 - firmware to automatically choose PS_POLL or NULL
+ * mode, 0x02 - PS_POLL, 0x03 - NULL mode )
+ */
+ t_u16 mode;
+ /** Delay to PS in milliseconds */
+ t_u16 delay_to_ps;
+} MLAN_PACK_END ps_param;
+
+/** Structure definition for the new auto deep sleep command */
+typedef MLAN_PACK_START struct __auto_ds_param {
+ /** Deep sleep inactivity timeout */
+ t_u16 deep_sleep_timeout;
+} MLAN_PACK_END auto_ds_param;
+
+/** Structure definition for sleep confirmation in the new ps command */
+typedef MLAN_PACK_START struct __sleep_confirm_param {
+ /** response control 0x00 - response not needed, 0x01 - response needed
+ */
+ t_u16 resp_ctrl;
+} MLAN_PACK_END sleep_confirm_param;
+
+/** bitmap for get auto deepsleep */
+#define BITMAP_AUTO_DS 0x01
+/** bitmap for sta power save */
+#define BITMAP_STA_PS 0x10
+/** bitmap for beacon timeout */
+#define BITMAP_BCN_TMO 0x20
+/** bitmap for uap inactivity based PS */
+#define BITMAP_UAP_INACT_PS 0x100
+/** bitmap for uap DTIM PS */
+#define BITMAP_UAP_DTIM_PS 0x200
+/** Structure definition for the new ieee power save parameters*/
+typedef MLAN_PACK_START struct _auto_ps_param {
+ /** bitmap for enable power save mode */
+ t_u16 ps_bitmap;
+ /* auto deep sleep parameter,
+ * sta power save parameter
+ * uap inactivity parameter
+ * uap DTIM parameter */
+} MLAN_PACK_END auto_ps_param;
+
+/** fix size for auto ps */
+#define AUTO_PS_FIX_SIZE 4
+
+/** TLV type : auto ds param */
+#define TLV_TYPE_AUTO_DS_PARAM (PROPRIETARY_TLV_BASE_ID + 0x71) /* 0x0171 */
+/** TLV type : ps param */
+#define TLV_TYPE_PS_PARAM (PROPRIETARY_TLV_BASE_ID + 0x72) /* 0x0172 */
+/** TLV type : beacon timeout */
+#define TLV_TYPE_BCN_TIMEOUT (PROPRIETARY_TLV_BASE_ID + 0x11F) /* 0x011F */
+
+/** MrvlIEtypes_auto_ds_param_t */
+typedef MLAN_PACK_START struct _MrvlIEtypes_auto_ds_param_t {
+ /** Header */
+ MrvlIEtypesHeader_t header;
+ /** auto ds param */
+ auto_ds_param param;
+} MLAN_PACK_END MrvlIEtypes_auto_ds_param_t;
+
+/** MrvlIEtypes_ps_param_t */
+typedef MLAN_PACK_START struct _MrvlIEtypes_ps_param_t {
+ /** Header */
+ MrvlIEtypesHeader_t header;
+ /** ps param */
+ ps_param param;
+} MLAN_PACK_END MrvlIEtypes_ps_param_t;
+
+/** MrvlIEtypes_bcn_timeout_t */
+typedef MLAN_PACK_START struct _MrvlIEtypes_bcn_timeout_t {
+ /** Header */
+ MrvlIEtypesHeader_t header;
+ /** Beacon miss timeout period window */
+ t_u16 bcn_miss_tmo_window;
+ /** Beacon miss timeout period */
+ t_u16 bcn_miss_tmo_period;
+ /** Beacon reacquire timeout period window */
+ t_u16 bcn_rq_tmo_window;
+ /** Beacon reacquire timeout period */
+ t_u16 bcn_rq_tmo_period;
+} MLAN_PACK_END MrvlIEtypes_bcn_timeout_t;
+
+/** Structure definition for low power mode cfg command */
+typedef MLAN_PACK_START struct _HostCmd_DS_LOW_POWER_MODE_CFG {
+ /** Action */
+ t_u16 action;
+ /** Low power mode */
+ t_u16 lpm;
+} MLAN_PACK_END HostCmd_DS_LOW_POWER_MODE_CFG;
+
+/** Structure definition for new power save command */
+typedef MLAN_PACK_START struct _HostCmd_DS_PS_MODE_ENH {
+ /** Action */
+ t_u16 action;
+ /** Data speciifc to action */
+ /* For IEEE power save data will be as
+ * UINT16 mode (0x01 - firmware to automatically choose PS_POLL or NULL
+ * mode, 0x02 - PS_POLL, 0x03 - NULL mode ) UINT16 NullpacketInterval
+ * UINT16 NumDtims
+ * UINT16 BeaconMissInterval
+ * UINT16 locallisteninterval
+ * UINT16 adhocawakeperiod */
+
+ /* For auto deep sleep */
+ /* UINT16 Deep sleep inactivity timeout*/
+
+ /* For PS sleep confirm
+ * UINT16 responeCtrl - 0x00 - reponse from fw not needed, 0x01 -
+ * response from fw is needed */
+
+ union {
+ /** PS param definition */
+ ps_param opt_ps;
+ /** Auto ds param definition */
+ auto_ds_param auto_ds;
+ /** Sleep comfirm param definition */
+ sleep_confirm_param sleep_cfm;
+ /** bitmap for get PS info and Disable PS mode */
+ t_u16 ps_bitmap;
+ /** auto ps param */
+ auto_ps_param auto_ps;
+ } params;
+} MLAN_PACK_END HostCmd_DS_802_11_PS_MODE_ENH;
+
+/** FW VERSION tlv */
+#define TLV_TYPE_FW_VER_INFO (PROPRIETARY_TLV_BASE_ID + 0xC7) /* 0x1C7 */
+
+/** MrvlIEtypes_fw_ver_info_t */
+typedef MLAN_PACK_START struct _MrvlIEtypes_fw_ver_info_t {
+ /** Header */
+ MrvlIEtypesHeader_t header;
+ /** API id */
+ t_u16 api_id;
+ /** major version */
+ t_u8 major_ver;
+ /** minor version */
+ t_u8 minor_ver;
+} MLAN_PACK_END MrvlIEtypes_fw_ver_info_t;
+
+/** API ID */
+enum API_VER_ID {
+ KEY_API_VER_ID = 1,
+ FW_API_VER_ID = 2,
+ UAP_FW_API_VER_ID = 3,
+ CHANRPT_API_VER_ID = 4,
+};
+
+/** FW AP V15 */
+#define HOST_API_VERSION_V15 15
+/** FW minor version 1 */
+#define FW_MINOR_VERSION_1 1
+
+/** UAP FW version 2 */
+#define UAP_FW_VERSION_2 0x2
+
+/** HostCMD_DS_APCMD_ACS_SCAN */
+typedef MLAN_PACK_START struct _HostCMD_DS_APCMD_ACS_SCAN {
+ /** band */
+ Band_Config_t bandcfg;
+ /** channel */
+ t_u8 chan;
+} MLAN_PACK_END HostCMD_DS_APCMD_ACS_SCAN;
+
+/** HostCmd_DS_GET_HW_SPEC */
+typedef MLAN_PACK_START struct _HostCmd_DS_GET_HW_SPEC {
+ /** HW Interface version number */
+ t_u16 hw_if_version;
+ /** HW version number */
+ t_u16 version;
+ /** Reserved field */
+ t_u16 reserved;
+ /** Max no of Multicast address */
+ t_u16 num_of_mcast_adr;
+ /** MAC address */
+ t_u8 permanent_addr[MLAN_MAC_ADDR_LENGTH];
+ /** Region Code */
+ t_u16 region_code;
+ /** Number of antenna used */
+ t_u16 number_of_antenna;
+ /** FW release number, example 0x1234=1.2.3.4 */
+ t_u32 fw_release_number;
+ /** Reserved field */
+ t_u32 reserved_1;
+ /** Reserved field */
+ t_u32 reserved_2;
+ /** Reserved field */
+ t_u32 reserved_3;
+ /** FW/HW Capability */
+ t_u32 fw_cap_info;
+ /** 802.11n Device Capabilities */
+ t_u32 dot_11n_dev_cap;
+ /** MIMO abstraction of MCSs supported by device */
+ t_u8 dev_mcs_support;
+ /** Valid end port at init */
+ t_u16 mp_end_port;
+ /** mgmt IE buffer count */
+ t_u16 mgmt_buf_count;
+ /** Reserved */
+ t_u32 reserved_8;
+ /** Reserved */
+ t_u32 reserved_9;
+ /** 802.11ac Device Capabilities */
+ t_u32 Dot11acDevCap;
+ /** MCSs supported by 802.11ac device */
+ t_u32 Dot11acMcsSupport;
+} MLAN_PACK_END HostCmd_DS_GET_HW_SPEC;
+
+#ifdef SDIO
+/* HostCmd_DS_SDIO_SP_RX_AGGR_CFG */
+typedef MLAN_PACK_START struct _HostCmd_DS_SDIO_SP_RX_AGGR_CFG {
+ t_u8 action;
+ t_u8 enable;
+ t_u16 sdio_block_size;
+} MLAN_PACK_END HostCmd_DS_SDIO_SP_RX_AGGR_CFG;
+#endif
+
+/** HostCmd_DS_802_11_CFG_DATA */
+typedef MLAN_PACK_START struct _HostCmd_DS_802_11_CFG_DATA {
+ /** Action */
+ t_u16 action;
+ /** Type */
+ t_u16 type;
+ /** Data length */
+ t_u16 data_len;
+ /** Data */
+} MLAN_PACK_END HostCmd_DS_802_11_CFG_DATA;
+
+/** HostCmd_DS_CMD_802_11_RSSI_INFO_EXT */
+typedef MLAN_PACK_START struct _HostCmd_DS_802_11_RSSI_INFO_EXT {
+ /** Action */
+ t_u16 action;
+ /** Parameter used for exponential averaging for Data */
+ t_u16 ndata;
+ /** Parameter used for exponential averaging for Beacon */
+ t_u16 nbcn;
+ /** Last RSSI beacon TSF(only for Get action) */
+ t_u64 tsfbcn;
+ /** TLV info**/
+ t_u8 *tlv_buf[];
+} MLAN_PACK_END HostCmd_DS_802_11_RSSI_INFO_EXT;
+
+/** TLV rssi info */
+#define TLV_TYPE_RSSI_INFO (PROPRIETARY_TLV_BASE_ID + 0xe5) /* 0x01E5 */
+
+/** MrvlIEtypes_eapol_pkt_t */
+typedef MLAN_PACK_START struct _MrvlIEtypes_RSSI_EXT_t {
+ /** Header */
+ MrvlIEtypesHeader_t header;
+ /** Path ID
+ [Bit1:Bit0] = [0:1]: path A
+ [Bit1:Bit0] = [1:0]: path B
+ [Bit1:Bit0] = [1:1]: combined signal of path A and path B
+ [Bit7:Bit2] : Reserved
+ **/
+ t_u16 path_id;
+ /** Last Data RSSI in dBm */
+ t_s16 data_rssi_last;
+ /** Last Data NF in dBm */
+ t_s16 data_nf_last;
+ /** AVG DATA RSSI in dBm */
+ t_s16 data_rssi_avg;
+ /** AVG DATA NF in dBm */
+ t_s16 data_nf_avg;
+ /** Last BEACON RSSI in dBm */
+ t_s16 bcn_rssi_last;
+ /** Last BEACON NF in dBm */
+ t_s16 bcn_nf_last;
+ /** AVG BEACON RSSI in dBm */
+ t_s16 bcn_rssi_avg;
+ /** AVG BEACON NF in dBm */
+ t_s16 bcn_nf_avg;
+} MLAN_PACK_END MrvlIEtypes_RSSI_EXT_t;
+
+/** HostCmd_DS_CMD_802_11_RSSI_INFO */
+typedef MLAN_PACK_START struct _HostCmd_DS_802_11_RSSI_INFO {
+ /** Action */
+ t_u16 action;
+ /** Parameter used for exponential averaging for Data */
+ t_u16 ndata;
+ /** Parameter used for exponential averaging for Beacon */
+ t_u16 nbcn;
+ /** Reserved field 0 */
+ t_u16 reserved[9];
+ /** Reserved field 1 */
+ t_u64 reserved_1;
+} MLAN_PACK_END HostCmd_DS_802_11_RSSI_INFO;
+
+/** HostCmd_DS_802_11_RSSI_INFO_RSP */
+typedef MLAN_PACK_START struct _HostCmd_DS_802_11_RSSI_INFO_RSP {
+ /** Action */
+ t_u16 action;
+ /** Parameter used for exponential averaging for Data */
+ t_u16 ndata;
+ /** Parameter used for exponential averaging for beacon */
+ t_u16 nbcn;
+ /** Last Data RSSI in dBm */
+ t_s16 data_rssi_last;
+ /** Last Data NF in dBm */
+ t_s16 data_nf_last;
+ /** AVG DATA RSSI in dBm */
+ t_s16 data_rssi_avg;
+ /** AVG DATA NF in dBm */
+ t_s16 data_nf_avg;
+ /** Last BEACON RSSI in dBm */
+ t_s16 bcn_rssi_last;
+ /** Last BEACON NF in dBm */
+ t_s16 bcn_nf_last;
+ /** AVG BEACON RSSI in dBm */
+ t_s16 bcn_rssi_avg;
+ /** AVG BEACON NF in dBm */
+ t_s16 bcn_nf_avg;
+ /** Last RSSI Beacon TSF */
+ t_u64 tsf_bcn;
+} MLAN_PACK_END HostCmd_DS_802_11_RSSI_INFO_RSP;
+
+/** HostCmd_DS_802_11_MAC_ADDRESS */
+typedef MLAN_PACK_START struct _HostCmd_DS_802_11_MAC_ADDRESS {
+ /** Action */
+ t_u16 action;
+ /** MAC address */
+ t_u8 mac_addr[MLAN_MAC_ADDR_LENGTH];
+} MLAN_PACK_END HostCmd_DS_802_11_MAC_ADDRESS;
+
+/** HostCmd_DS_MAC_CONTROL */
+typedef MLAN_PACK_START struct _HostCmd_DS_MAC_CONTROL {
+ /** Action */
+ t_u32 action;
+} MLAN_PACK_END HostCmd_DS_MAC_CONTROL;
+
+/** HostCmd_DS_CMD_TX_DATA_PAUSE */
+typedef MLAN_PACK_START struct _HostCmd_DS_CMD_TX_DATA_PAUSE {
+ /** Action */
+ t_u16 action;
+ /** Enable/disable Tx data pause */
+ t_u8 enable_tx_pause;
+ /** Max number of TX buffers allowed for all PS clients*/
+ t_u8 pause_tx_count;
+} MLAN_PACK_END HostCmd_DS_CMD_TX_DATA_PAUSE;
+
+/** TLV type : TX pause TLV */
+#define TLV_TYPE_TX_PAUSE (PROPRIETARY_TLV_BASE_ID + 0x94) /* 0x0194 */
+/** MrvlIEtypes_SsIdParamSet_t */
+typedef MLAN_PACK_START struct _MrvlIEtypes_tx_pause_t {
+ /** Header */
+ MrvlIEtypesHeader_t header;
+ /** peer mac address */
+ t_u8 peermac[MLAN_MAC_ADDR_LENGTH];
+ /** Tx pause state, 1--pause, 0--free flowing */
+ t_u8 tx_pause;
+ /** total packets queued for the client */
+ t_u8 pkt_cnt;
+} MLAN_PACK_END MrvlIEtypes_tx_pause_t;
+
+/** HostCmd_CMD_MAC_MULTICAST_ADR */
+typedef MLAN_PACK_START struct _HostCmd_DS_MAC_MULTICAST_ADR {
+ /** Action */
+ t_u16 action;
+ /** Number of addresses */
+ t_u16 num_of_adrs;
+ /** List of MAC */
+ t_u8 mac_list[MLAN_MAC_ADDR_LENGTH * MLAN_MAX_MULTICAST_LIST_SIZE];
+} MLAN_PACK_END HostCmd_DS_MAC_MULTICAST_ADR;
+
+/** HostCmd_CMD_802_11_DEAUTHENTICATE */
+typedef MLAN_PACK_START struct _HostCmd_DS_802_11_DEAUTHENTICATE {
+ /** MAC address */
+ t_u8 mac_addr[MLAN_MAC_ADDR_LENGTH];
+ /** Deauthentication resaon code */
+ t_u16 reason_code;
+} MLAN_PACK_END HostCmd_DS_802_11_DEAUTHENTICATE;
+
+/** HostCmd_DS_802_11_ASSOCIATE */
+typedef MLAN_PACK_START struct _HostCmd_DS_802_11_ASSOCIATE {
+ /** Peer STA address */
+ t_u8 peer_sta_addr[MLAN_MAC_ADDR_LENGTH];
+ /** Capability information */
+ IEEEtypes_CapInfo_t cap_info;
+ /** Listen interval */
+ t_u16 listen_interval;
+ /** Beacon period */
+ t_u16 beacon_period;
+ /** DTIM period */
+ t_u8 dtim_period;
+
+ /**
+ * MrvlIEtypes_SsIdParamSet_t SsIdParamSet;
+ * MrvlIEtypes_PhyParamSet_t PhyParamSet;
+ * MrvlIEtypes_SsParamSet_t SsParamSet;
+ * MrvlIEtypes_RatesParamSet_t RatesParamSet;
+ */
+} MLAN_PACK_END HostCmd_DS_802_11_ASSOCIATE;
+
+/** HostCmd_CMD_802_11_ASSOCIATE response */
+typedef MLAN_PACK_START struct _HostCmd_DS_802_11_ASSOCIATE_RSP {
+ /** Association response structure */
+ IEEEtypes_AssocRsp_t assoc_rsp;
+} MLAN_PACK_END HostCmd_DS_802_11_ASSOCIATE_RSP;
+
+/** HostCmd_DS_802_11_AD_HOC_START*/
+typedef MLAN_PACK_START struct _HostCmd_DS_802_11_AD_HOC_START {
+ /** AdHoc SSID */
+ t_u8 ssid[MLAN_MAX_SSID_LENGTH];
+ /** BSS mode */
+ t_u8 bss_mode;
+ /** Beacon period */
+ t_u16 beacon_period;
+ /** DTIM period */
+ t_u8 dtim_period;
+ /** SS parameter set */
+ IEEEtypes_SsParamSet_t ss_param_set;
+ /** PHY parameter set */
+ IEEEtypes_PhyParamSet_t phy_param_set;
+ /** Reserved field */
+ t_u16 reserved1;
+ /** Capability information */
+ IEEEtypes_CapInfo_t cap;
+ /** Supported data rates */
+ t_u8 DataRate[HOSTCMD_SUPPORTED_RATES];
+} MLAN_PACK_END HostCmd_DS_802_11_AD_HOC_START;
+
+/** HostCmd_CMD_802_11_AD_HOC_START response */
+typedef MLAN_PACK_START struct _HostCmd_DS_802_11_AD_HOC_START_RESULT {
+ /** Padding */
+ t_u8 pad[3];
+ /** AdHoc BSSID */
+ t_u8 bssid[MLAN_MAC_ADDR_LENGTH];
+ /** Padding to sync with FW structure*/
+ t_u8 pad2[2];
+ /** Result */
+ t_u8 result;
+} MLAN_PACK_END HostCmd_DS_802_11_AD_HOC_START_RESULT;
+
+/** HostCmd_CMD_802_11_AD_HOC_START response */
+typedef MLAN_PACK_START struct _HostCmd_DS_802_11_AD_HOC_JOIN_RESULT {
+ /** Result */
+ t_u8 result;
+} MLAN_PACK_END HostCmd_DS_802_11_AD_HOC_JOIN_RESULT;
+
+/** AdHoc_BssDesc_t */
+typedef MLAN_PACK_START struct _AdHoc_BssDesc_t {
+ /** BSSID */
+ t_u8 bssid[MLAN_MAC_ADDR_LENGTH];
+ /** SSID */
+ t_u8 ssid[MLAN_MAX_SSID_LENGTH];
+ /** BSS mode */
+ t_u8 bss_mode;
+ /** Beacon period */
+ t_u16 beacon_period;
+ /** DTIM period */
+ t_u8 dtim_period;
+ /** Timestamp */
+ t_u8 time_stamp[8];
+ /** Local time */
+ t_u8 local_time[8];
+ /** PHY parameter set */
+ IEEEtypes_PhyParamSet_t phy_param_set;
+ /** SS parameter set */
+ IEEEtypes_SsParamSet_t ss_param_set;
+ /** Capability information */
+ IEEEtypes_CapInfo_t cap;
+ /** Supported data rates */
+ t_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
+ */
+} MLAN_PACK_END AdHoc_BssDesc_t;
+
+/** HostCmd_DS_802_11_AD_HOC_JOIN */
+typedef MLAN_PACK_START struct _HostCmd_DS_802_11_AD_HOC_JOIN {
+ /** AdHoc BSS descriptor */
+ AdHoc_BssDesc_t bss_descriptor;
+ /** Reserved field */
+ t_u16 reserved1;
+ /** Reserved field */
+ t_u16 reserved2;
+} MLAN_PACK_END HostCmd_DS_802_11_AD_HOC_JOIN;
+
+#if defined(SDIO)
+/** Interrupt Raising Edge */
+#define INT_RASING_EDGE 0
+/** Interrupt Falling Edge */
+#define INT_FALLING_EDGE 1
+
+/** Delay 1 usec */
+#define DELAY_1_US 1
+
+typedef MLAN_PACK_START struct _HostCmd_DS_SDIO_GPIO_INT_CONFIG {
+ /** Action */
+ t_u16 action;
+ /** GPIO interrupt pin */
+ t_u16 gpio_pin;
+ /** GPIO interrupt edge, 1: failing edge; 0: raising edge */
+ t_u16 gpio_int_edge;
+ /** GPIO interrupt pulse widthin usec units */
+ t_u16 gpio_pulse_width;
+} MLAN_PACK_END HostCmd_DS_SDIO_GPIO_INT_CONFIG;
+#endif /* GPIO_SDIO_INT_CTRL */
+
+typedef MLAN_PACK_START struct _HostCmd_DS_SDIO_PULL_CTRL {
+ /** Action */
+ t_u16 action;
+ /** The delay of pulling up in us */
+ t_u16 pull_up;
+ /** The delay of pulling down in us */
+ t_u16 pull_down;
+} MLAN_PACK_END HostCmd_DS_SDIO_PULL_CTRL;
+
+/** HostCmd_DS_802_11_GET_LOG */
+typedef MLAN_PACK_START struct _HostCmd_DS_802_11_GET_LOG {
+ /** Number of multicast transmitted frames */
+ t_u32 mcast_tx_frame;
+ /** Number of failures */
+ t_u32 failed;
+ /** Number of retries */
+ t_u32 retry;
+ /** Number of multiretries */
+ t_u32 multiretry;
+ /** Number of duplicate frames */
+ t_u32 frame_dup;
+ /** Number of RTS success */
+ t_u32 rts_success;
+ /** Number of RTS failure */
+ t_u32 rts_failure;
+ /** Number of acknowledgement failure */
+ t_u32 ack_failure;
+ /** Number of fragmented packets received */
+ t_u32 rx_frag;
+ /** Number of multicast frames received */
+ t_u32 mcast_rx_frame;
+ /** FCS error */
+ t_u32 fcs_error;
+ /** Number of transmitted frames */
+ t_u32 tx_frame;
+ /** Reserved field */
+ t_u32 reserved;
+ /** Number of WEP icv error for each key */
+ t_u32 wep_icv_err_cnt[4];
+ /** Beacon received count */
+ t_u32 bcn_rcv_cnt;
+ /** Beacon missed count */
+ t_u32 bcn_miss_cnt;
+ /** Tx frag count */
+ t_u32 tx_frag_cnt;
+ /** Qos Tx frag count */
+ t_u32 qos_tx_frag_cnt[8];
+ /** Qos failed count */
+ t_u32 qos_failed_cnt[8];
+ /** Qos retry count */
+ t_u32 qos_retry_cnt[8];
+ /** Qos multi retry count */
+ t_u32 qos_multi_retry_cnt[8];
+ /** Qos frame dup count */
+ t_u32 qos_frm_dup_cnt[8];
+ /** Qos rts success count */
+ t_u32 qos_rts_suc_cnt[8];
+ /** Qos rts failure count */
+ t_u32 qos_rts_failure_cnt[8];
+ /** Qos ack failure count */
+ t_u32 qos_ack_failure_cnt[8];
+ /** Qos Rx frag count */
+ t_u32 qos_rx_frag_cnt[8];
+ /** Qos Tx frame count */
+ t_u32 qos_tx_frm_cnt[8];
+ /** Qos discarded frame count */
+ t_u32 qos_discarded_frm_cnt[8];
+ /** Qos mpdus Rx count */
+ t_u32 qos_mpdus_rx_cnt[8];
+ /** Qos retry rx count */
+ t_u32 qos_retries_rx_cnt[8];
+ /** CMAC ICV errors count */
+ t_u32 cmacicv_errors;
+ /** CMAC replays count */
+ t_u32 cmac_replays;
+ /** mgmt CCMP replays count */
+ t_u32 mgmt_ccmp_replays;
+ /** TKIP ICV errors count */
+ t_u32 tkipicv_errors;
+ /** TKIP replays count */
+ t_u32 tkip_replays;
+ /** CCMP decrypt errors count */
+ t_u32 ccmp_decrypt_errors;
+ /** CCMP replays count */
+ t_u32 ccmp_replays;
+ /** Tx amsdu count */
+ t_u32 tx_amsdu_cnt;
+ /** failed amsdu count */
+ t_u32 failed_amsdu_cnt;
+ /** retry amsdu count */
+ t_u32 retry_amsdu_cnt;
+ /** multi-retry amsdu count */
+ t_u32 multi_retry_amsdu_cnt;
+ /** Tx octets in amsdu count */
+ t_u64 tx_octets_in_amsdu_cnt;
+ /** amsdu ack failure count */
+ t_u32 amsdu_ack_failure_cnt;
+ /** Rx amsdu count */
+ t_u32 rx_amsdu_cnt;
+ /** Rx octets in amsdu count */
+ t_u64 rx_octets_in_amsdu_cnt;
+ /** Tx ampdu count */
+ t_u32 tx_ampdu_cnt;
+ /** tx mpdus in ampdu count */
+ t_u32 tx_mpdus_in_ampdu_cnt;
+ /** tx octets in ampdu count */
+ t_u64 tx_octets_in_ampdu_cnt;
+ /** ampdu Rx count */
+ t_u32 ampdu_rx_cnt;
+ /** mpdu in Rx ampdu count */
+ t_u32 mpdu_in_rx_ampdu_cnt;
+ /** Rx octets ampdu count */
+ t_u64 rx_octets_in_ampdu_cnt;
+ /** ampdu delimiter CRC error count */
+ t_u32 ampdu_delimiter_crc_error_cnt;
+ /** Rx Stuck Related Info*/
+ /** Rx Stuck Issue count */
+ t_u32 rx_stuck_issue_cnt[2];
+ /** Rx Stuck Recovery count */
+ t_u32 rx_stuck_recovery_cnt;
+ /** Rx Stuck TSF */
+ t_u64 rx_stuck_tsf[2];
+ /** Tx Watchdog Recovery Related Info */
+ /** Tx Watchdog Recovery count */
+ t_u32 tx_watchdog_recovery_cnt;
+ /** Tx Watchdog TSF */
+ t_u64 tx_watchdog_tsf[2];
+ /** Channel Switch Related Info */
+ /** Channel Switch Announcement Sent */
+ t_u32 channel_switch_ann_sent;
+ /** Channel Switch State */
+ t_u32 channel_switch_state;
+ /** Register Class */
+ t_u32 reg_class;
+ /** Channel Number */
+ t_u32 channel_number;
+ /** Channel Switch Mode */
+ t_u32 channel_switch_mode;
+} MLAN_PACK_END HostCmd_DS_802_11_GET_LOG;
+
+/* maln wifi rate */
+typedef MLAN_PACK_START struct _mlan_wifi_rate {
+ /** 0: OFDM, 1:CCK, 2:HT 3:VHT 4..7 reserved */
+ t_u8 preamble;
+ /** 0:1x1, 1:2x2, 3:3x3, 4:4x4 */
+ t_u8 nss;
+ /** 0:20MHz, 1:40Mhz, 2:80Mhz, 3:160Mhz */
+ t_u8 bw;
+ /** OFDM/CCK rate code would be as per ieee std in the units of 0.5mbps
+ */
+ /** HT/VHT it would be mcs index */
+ t_u8 rateMcsIdx;
+ /** units of 100 Kbps */
+ t_u32 bitrate;
+} MLAN_PACK_START mlan_wifi_rate;
+
+/** channel information */
+typedef MLAN_PACK_START struct {
+ /** channel width (20, 40, 80, 80+80, 160) */
+ t_u32 width;
+ /** primary 20 MHz channel */
+ t_u32 center_freq;
+ /** center frequency (MHz) first segment */
+ t_u32 center_freq0;
+ /** center frequency (MHz) second segment */
+ t_u32 center_freq1;
+} MLAN_PACK_END mlan_wifi_channel_info;
+
+/** channel statistics */
+typedef MLAN_PACK_START struct {
+ /** channel */
+ mlan_wifi_channel_info channel;
+ /** msecs the radio is awake (32 bits number accruing over time) */
+ t_u32 on_time;
+ /** msecs the CCA register is busy (32 bits number accruing over time)
+ */
+ t_u32 cca_busy_time;
+} MLAN_PACK_END mlan_wifi_channel_stat;
+
+/** radio statistics */
+typedef MLAN_PACK_START struct {
+ /** supported wifi in case of multi radio */
+ t_u32 radio;
+ /** msecs the radio is awake */
+ t_u32 on_time;
+ /** msecs the radio is transmitting */
+ t_u32 tx_time;
+ /** TBD: num_tx_levels: number of radio transmit power levels */
+ t_u32 reserved0;
+ /** TBD: tx_time_per_levels: pointer to an array of radio transmit per
+ * power levels in msecs accured over time */
+ t_u32 reserved1;
+ /** msecs the radio is in active receive */
+ t_u32 rx_time;
+ /** msecs the radio is awake due to all scan */
+ t_u32 on_time_scan;
+ /** msecs the radio is awake due to NAN */
+ t_u32 on_time_nbd;
+ /** msecs the radio is awake due to G?scan */
+ t_u32 on_time_gscan;
+ /** msecs the radio is awake due to roam?scan */
+ t_u32 on_time_roam_scan;
+ /** msecs the radio is awake due to PNO scan */
+ t_u32 on_time_pno_scan;
+ /** msecs the radio is awake due to HS2.0 scans and GAS exchange */
+ t_u32 on_time_hs20;
+ /** number of channels */
+ t_u32 num_channels;
+ /** channel statistics */
+ mlan_wifi_channel_stat channels[MAX_NUM_CHAN]; // support only 1
+ // channel, so keep it.
+} MLAN_PACK_END mlan_wifi_radio_stat;
+
+/** per rate statistics */
+typedef MLAN_PACK_START struct {
+ /** rate information */
+ mlan_wifi_rate rate;
+ /** number of successfully transmitted data pkts (ACK rcvd) */
+ t_u32 tx_mpdu;
+ /** number of received data pkts */
+ t_u32 rx_mpdu;
+ /** number of data packet losses (no ACK) */
+ t_u32 mpdu_lost;
+ /** total number of data pkt retries */
+ t_u32 retries;
+ /** number of short data pkt retries */
+ t_u32 retries_short;
+ /** number of long data pkt retries */
+ t_u32 retries_long;
+} MLAN_PACK_END mlan_wifi_rate_stat;
+
+/** per peer statistics */
+typedef MLAN_PACK_START struct {
+ /** peer type (AP, TDLS, GO etc.) */
+ t_u8 type;
+ /** mac address */
+ t_u8 peer_mac_address[6];
+ /** peer WIFI_CAPABILITY_XXX */
+ t_u32 capabilities;
+ /** number of rates */
+ t_u32 num_rate;
+ /** per rate statistics, number of entries = num_rate */
+ mlan_wifi_rate_stat rate_stats[];
+} MLAN_PACK_END mlan_wifi_peer_info;
+
+/* per access category statistics */
+typedef MLAN_PACK_START struct {
+ /** access category (VI, VO, BE, BK) */
+ t_u32 ac;
+ /** number of successfully transmitted unicast data pkts (ACK rcvd) */
+ t_u32 tx_mpdu;
+ /** number of received unicast mpdus */
+ t_u32 rx_mpdu;
+ /** number of succesfully transmitted multicast data packets */
+ /** STA case: implies ACK received from AP for the unicast packet in
+ * which mcast pkt was sent */
+ t_u32 tx_mcast;
+ /** number of received multicast data packets */
+ t_u32 rx_mcast;
+ /** number of received unicast a-mpdus */
+ t_u32 rx_ampdu;
+ /** number of transmitted unicast a-mpdus */
+ t_u32 tx_ampdu;
+ /** number of data pkt losses (no ACK) */
+ t_u32 mpdu_lost;
+ /** total number of data pkt retries */
+ t_u32 retries;
+ /** number of short data pkt retries */
+ t_u32 retries_short;
+ /** number of long data pkt retries */
+ t_u32 retries_long;
+ /** data pkt min contention time (usecs) */
+ t_u32 contention_time_min;
+ /** data pkt max contention time (usecs) */
+ t_u32 contention_time_max;
+ /** data pkt avg contention time (usecs) */
+ t_u32 contention_time_avg;
+ /** num of data pkts used for contention statistics */
+ t_u32 contention_num_samples;
+} MLAN_PACK_END mlan_wifi_wmm_ac_stat;
+
+/** interface statistics */
+typedef MLAN_PACK_START struct {
+ /** access point beacon received count from connected AP */
+ t_u32 beacon_rx;
+ /** Average beacon offset encountered (beacon_TSF - TBTT)
+ * the average_tsf_offset field is used so as to calculate the
+ * typical beacon contention time on the channel as well may be
+ * used to debug beacon synchronization and related power consumption
+ * issue
+ */
+ t_u64 average_tsf_offset;
+ /** indicate that this AP typically leaks packets beyond the driver
+ * guard time */
+ t_u32 leaky_ap_detected;
+ /** average number of frame leaked by AP after frame with PM bit set was
+ * ACK'ed by AP */
+ t_u32 leaky_ap_avg_num_frames_leaked;
+ /** Guard time currently in force (when implementing IEEE power
+ * management based on frame control PM bit), How long driver waits
+ * before shutting down the radio and after receiving an ACK for a data
+ * frame with PM bit set)
+ */
+ t_u32 leaky_ap_guard_time;
+ /** access point mgmt frames received count from connected AP (including
+ * Beacon) */
+ t_u32 mgmt_rx;
+ /** action frames received count */
+ t_u32 mgmt_action_rx;
+ /** action frames transmit count */
+ t_u32 mgmt_action_tx;
+ /** access Point Beacon and Management frames RSSI (averaged) */
+ t_u32 rssi_mgmt;
+ /** access Point Data Frames RSSI (averaged) from connected AP */
+ t_u32 rssi_data;
+ /** access Point ACK RSSI (averaged) from connected AP */
+ t_u32 rssi_ack;
+ /** per ac data packet statistics */
+ mlan_wifi_wmm_ac_stat ac[MAX_AC_QUEUES];
+ /** number of peers */
+ t_u32 num_peers;
+ /** per peer statistics */
+ mlan_wifi_peer_info peer_info[];
+} MLAN_PACK_END mlan_wifi_iface_stat;
+
+/** MrvlIETypes_llStatIface_t */
+typedef MLAN_PACK_START struct _MrvlIETypes_llStatIface_t {
+ /** Type */
+ t_u16 type;
+ /** Length */
+ t_u16 len;
+ /** Frame Control */
+ mlan_wifi_iface_stat ifaceStat;
+ /* t_u8 frame_contents[]; */
+} MLAN_PACK_END MrvlIETypes_llStatIface_t;
+
+/** MrvlIETypes_llStatRadio_t */
+typedef MLAN_PACK_START struct _MrvlIETypes_llStatRadio_t {
+ /** Type */
+ t_u16 type;
+ /** Length */
+ t_u16 len;
+ /** Frame Control */
+ mlan_wifi_radio_stat radioStat[MAX_RADIO];
+ /* t_u8 frame_contents[]; */
+} MLAN_PACK_END MrvlIETypes_llStatRadio_t;
+
+#define TYPE_IFACE_STAT MBIT(0)
+#define TYPE_RADIO_STAT MBIT(1)
+#define TYPE_PEER_INFO MBIT(2)
+/** HostCmd_DS_802_11_LINK_STATISTIC */
+typedef MLAN_PACK_START struct _HostCmd_DS_802_11_LINK_STATISTIC {
+ /** Action : HostCmd_ACT_GEN_GET/SET/REMOVE */
+ t_u16 action;
+ /** statistic which would be get in action HostCmd_ACT_GEN_GET :
+ * TYPE_IFACE_STAT/RADIO_STAT/PEER_INFO */
+ t_u16 stat_type;
+ /* threshold to classify the pkts as short or long, packet size <
+ * mpdu_size_threshold => short */
+ t_u32 mpdu_size_threshold;
+ /* set for field debug mode. Driver should collect all statistics
+ * regardless of performance impact. */
+ t_u32 aggressive_statistics_gathering;
+ /** Value */
+ t_u8 value[];
+} MLAN_PACK_END HostCmd_DS_802_11_LINK_STATISTIC;
+
+/**_HostCmd_TX_RATE_QUERY */
+typedef MLAN_PACK_START struct _HostCmd_TX_RATE_QUERY {
+ /** Tx rate */
+ t_u8 tx_rate;
+ /** Tx Rate Info:
+ * [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
+ * [Bit4,Bit7] AX Guard Interval: 00, 01, 02 */
+ t_u8 tx_rate_info;
+ /**
+ * BIT0: DCM
+ * BIT3-BIT1: tone mode
+ ** 000: 26 tone
+ ** 001: 52 tone
+ ** 010: 106 tone
+ ** 011: 242 tone
+ ** 100: 484 tone
+ ** 101: 996 tone
+ * BIT7-BIT4: resvd
+ **/
+ t_u8 ext_tx_rate_info;
+} MLAN_PACK_END HostCmd_TX_RATE_QUERY;
+
+typedef MLAN_PACK_START struct _hs_config_param {
+ /** bit0=1: broadcast data
+ * bit1=1: unicast data
+ * bit2=1: mac events
+ * bit3=1: multicast data
+ */
+ t_u32 conditions;
+ /** GPIO pin or 0xff for interface */
+ t_u8 gpio;
+ /** gap in milliseconds or or 0xff for special setting when
+ * GPIO is used to wakeup host
+ */
+ t_u8 gap;
+} MLAN_PACK_END hs_config_param;
+
+/** HS Action 0x0001 - Configure enhanced host sleep mode,
+ * 0x0002 - Activate enhanced host sleep mode
+ */
+typedef enum _Host_Sleep_Action {
+ HS_CONFIGURE = 0x0001,
+ HS_ACTIVATE = 0x0002,
+} Host_Sleep_Action;
+
+/** Structure definition for activating enhanced hs */
+typedef MLAN_PACK_START struct __hs_activate_param {
+ /** response control 0x00 - response not needed, 0x01 - response needed
+ */
+ t_u16 resp_ctrl;
+} MLAN_PACK_END hs_activate_param;
+
+/** HostCmd_DS_802_11_HS_CFG_ENH */
+typedef MLAN_PACK_START struct _HostCmd_DS_802_11_HS_CFG_ENH {
+ /** Action 0x0001 - Configure enhanced host sleep mode,
+ * 0x0002 - Activate enhanced host sleep mode
+ */
+ t_u16 action;
+
+ union {
+ /** Configure enhanced hs */
+ hs_config_param hs_config;
+ /** Activate enhanced hs */
+ hs_activate_param hs_activate;
+ } params;
+} MLAN_PACK_END HostCmd_DS_802_11_HS_CFG_ENH;
+
+/** HostCmd_CMD_802_11_ROBUSTCOEX */
+typedef MLAN_PACK_START struct _HostCmd_DS_802_11_ROBUSTCOEX {
+ /** Action */
+ t_u16 action;
+ /** RSVD */
+ t_u16 rsvd;
+ t_u8 tlv_buf[];
+} MLAN_PACK_END HostCmd_DS_802_11_ROBUSTCOEX;
+
+/** HostCmd_CMD_DMCS_CFG */
+typedef MLAN_PACK_START struct _HostCmd_DS_DMCS_CFG {
+ /** Action */
+ t_u16 action;
+ /** SubCmd of DMCS */
+ t_u16 subcmd;
+ t_u8 tlv_buf[];
+} MLAN_PACK_END HostCmd_DS_DMCS_CFG;
+
+#if defined(PCIE)
+/** HostCmd_CMD_SSU */
+typedef MLAN_PACK_START struct _HostCmd_DS_SSU_CFG {
+ /** Action */
+ t_u16 action;
+ /** # of FFT sample to skip */
+ t_u32 nskip;
+ /** # of FFT sample selected to dump */
+ t_u32 nsel;
+ /** Down sample ADC input for buffering */
+ t_u32 adcdownsample;
+ /** Mask Out ADC Data From Spectral Packet */
+ t_u32 mask_adc_pkt;
+ /** Enable 16-Bit FFT Output Data Precision in Spectral Packet */
+ t_u32 out_16bits;
+ /** Enable power spectrum in dB for spectral packet */
+ t_u32 spec_pwr_enable;
+ /** Enable Spectral Packet Rate Reduction in dB output format */
+ t_u32 rate_deduction;
+ /** # of Spectral packets over which spectral data to be averaged */
+ t_u32 n_pkt_avg;
+ /** ret: Calculated fft length in dw */
+ t_u32 fft_len;
+ /** ret: Calculated adc length in dw */
+ t_u32 adc_len;
+ /** ret: Calculated record length in dw */
+ t_u32 rec_len;
+ /** Mapped address of DMA buffer */
+ t_u32 buffer_base_addr[2];
+ /** Total size of allocated buffer for SSU DMA */
+ t_u32 buffer_pool_size;
+ /** ret: Calculated buffer numbers */
+ t_u32 number_of_buffers;
+ /** ret: Calculated buffer size in byte for each descriptor */
+ t_u32 buffer_size;
+} MLAN_PACK_END HostCmd_DS_SSU_CFG;
+#endif
+
+/** SNMP_MIB_INDEX */
+typedef enum _SNMP_MIB_INDEX {
+ OpRateSet_i = 1,
+ DtimPeriod_i = 3,
+ RtsThresh_i = 5,
+ ShortRetryLim_i = 6,
+ LongRetryLim_i = 7,
+ FragThresh_i = 8,
+ Dot11D_i = 9,
+ Dot11H_i = 10,
+ WwsMode_i = 17,
+ Thermal_i = 34,
+ NullPktPeriod_i = 37,
+ SignalextEnable_i = 41,
+ ECSAEnable_i = 42,
+ StopDeauth_i = 44,
+} SNMP_MIB_INDEX;
+
+/** max SNMP buf size */
+#define MAX_SNMP_BUF_SIZE 128
+
+#ifdef UAP_SUPPORT
+/** HostCmd_CMD_802_11_SNMP_MIB */
+typedef MLAN_PACK_START struct _HostCmd_DS_UAP_802_11_SNMP_MIB {
+ /** SNMP query type */
+ t_u16 query_type;
+ /** snmp oid buf */
+ t_u8 snmp_data[];
+} MLAN_PACK_END HostCmd_DS_UAP_802_11_SNMP_MIB;
+#endif
+
+/** HostCmd_CMD_802_11_SNMP_MIB */
+typedef MLAN_PACK_START struct _HostCmd_DS_802_11_SNMP_MIB {
+ /** SNMP query type */
+ t_u16 query_type;
+ /** SNMP object ID */
+ t_u16 oid;
+ /** SNMP buffer size */
+ t_u16 buf_size;
+ /** Value */
+ t_u8 value[1];
+} MLAN_PACK_END HostCmd_DS_802_11_SNMP_MIB;
+
+/** Radio on */
+#define RADIO_ON 0x01
+/** Radio off */
+#define RADIO_OFF 0x00
+
+/** HostCmd_CMD_802_11_RADIO_CONTROL */
+typedef MLAN_PACK_START struct _HostCmd_DS_802_11_RADIO_CONTROL {
+ /** Action */
+ t_u16 action;
+ /** Control */
+ t_u16 control;
+} MLAN_PACK_END HostCmd_DS_802_11_RADIO_CONTROL;
+
+/** MrvlRateScope_t */
+typedef MLAN_PACK_START struct _MrvlRateScope_t {
+ /** Header Type */
+ t_u16 type;
+ /** Header Length */
+ t_u16 length;
+ /** Bitmap of HR/DSSS rates */
+ t_u16 hr_dsss_rate_bitmap;
+ /** Bitmap of OFDM rates */
+ t_u16 ofdm_rate_bitmap;
+ /** Bitmap of HT-MCSs allowed for initial rate */
+ t_u16 ht_mcs_rate_bitmap[8];
+ t_u16 vht_mcs_rate_bitmap[8];
+ t_u16 he_mcs_rate_bitmap[8];
+} MLAN_PACK_END MrvlRateScope_t;
+
+/** MrvlRateDropPattern_t */
+typedef MLAN_PACK_START struct _MrvlRateDropPattern_t {
+ /** Header Type */
+ t_u16 type;
+ /** Header Length */
+ t_u16 length;
+ /** Rate Drop Mode */
+ t_u32 rate_drop_mode;
+ /* MrvlRateDropControl_t RateDropControl[]; */
+} MLAN_PACK_END MrvlRateDropPattern_t;
+
+typedef MLAN_PACK_START struct _MrvlIETypes_rate_setting_t {
+ /** Header */
+ MrvlIEtypesHeader_t header;
+ /** Rate Setting */
+ t_u16 rate_setting;
+} MLAN_PACK_END MrvlIETypes_rate_setting_t;
+
+/** HostCmd_DS_TX_RATE_CFG */
+typedef MLAN_PACK_START struct _HostCmd_DS_TX_RATE_CFG {
+ /** Action */
+ t_u16 action;
+ t_u16 reserved_1;
+ /* MrvlRateScope_t RateScope;
+ * MrvlRateDropPattern_t RateDrop; */
+ t_u8 tlv_buf[];
+} MLAN_PACK_END HostCmd_DS_TX_RATE_CFG;
+
+/** Power_Group_t */
+typedef MLAN_PACK_START struct _Power_Group_t {
+ /** Modulation Class */
+ t_u8 modulation_class;
+ /** MCS Code or Legacy RateID */
+ t_u8 first_rate_code;
+ /** MCS Code or Legacy RateID */
+ t_u8 last_rate_code;
+ /** Power Adjustment Step */
+ t_s8 power_step;
+ /** Minimal Tx Power Level [dBm] */
+ t_s8 power_min;
+ /** Maximal Tx Power Level [dBm] */
+ t_s8 power_max;
+ /** 0: HTBW20, 1: HTBW40 */
+ t_u8 ht_bandwidth;
+ /** Reserved */
+ t_u8 reserved;
+} MLAN_PACK_END Power_Group_t;
+
+/** MrvlTypes_Power_Group_t */
+typedef MLAN_PACK_START struct _MrvlTypes_Power_Group_t {
+ /** Header Type */
+ t_u16 type;
+ /** Header Length */
+ t_u16 length;
+ /* Power_Group_t PowerGroups */
+} MLAN_PACK_END MrvlTypes_Power_Group_t;
+
+/** HostCmd_CMD_TXPWR_CFG */
+typedef MLAN_PACK_START struct _HostCmd_DS_TXPWR_CFG {
+ /** Action */
+ t_u16 action;
+ /** Power group configuration index */
+ t_u16 cfg_index;
+ /** Power group configuration mode */
+ t_u32 mode;
+ /* MrvlTypes_Power_Group_t PowerGrpCfg[]*/
+ t_u8 tlv_buf[];
+} MLAN_PACK_END HostCmd_DS_TXPWR_CFG;
+
+/** HostCmd_CMD_802_11_RF_TX_POWER */
+typedef MLAN_PACK_START struct _HostCmd_DS_802_11_RF_TX_POWER {
+ /** Action */
+ t_u16 action;
+ /** Current power level */
+ t_s16 current_level;
+ /** Maximum power */
+ t_s8 max_power;
+ /** Minimum power */
+ t_s8 min_power;
+} MLAN_PACK_END HostCmd_DS_802_11_RF_TX_POWER;
+
+/** Connection type infra */
+#define CONNECTION_TYPE_INFRA 0
+/** Connection type adhoc */
+#define CONNECTION_TYPE_ADHOC 1
+#ifdef WIFI_DIRECT_SUPPORT
+/** BSS Mode: WIFIDIRECT Client */
+#define BSS_MODE_WIFIDIRECT_CLIENT 0
+/** BSS Mode: WIFIDIRECT GO */
+#define BSS_MODE_WIFIDIRECT_GO 2
+#endif
+/** HostCmd_DS_SET_BSS_MODE */
+typedef MLAN_PACK_START struct _HostCmd_DS_SET_BSS_MODE {
+ /** connection type */
+ t_u8 con_type;
+} MLAN_PACK_END HostCmd_DS_SET_BSS_MODE;
+
+/** HT Capabilities element */
+typedef MLAN_PACK_START struct _MrvlIETypes_HTCap_t {
+ /** Header */
+ MrvlIEtypesHeader_t header;
+
+ /** HTCap struct */
+ HTCap_t ht_cap;
+} MLAN_PACK_END MrvlIETypes_HTCap_t;
+/** VHT Capabilities element */
+typedef MLAN_PACK_START struct _MrvlIETypes_VHTCap_t {
+ /** Header */
+ MrvlIEtypesHeader_t header;
+
+ /** VHTCap struct */
+ VHT_capa_t vht_cap;
+} MLAN_PACK_END MrvlIETypes_VHTCap_t;
+
+/** HostCmd_DS_REMAIN_ON_CHANNEL */
+typedef MLAN_PACK_START struct _HostCmd_DS_REMAIN_ON_CHANNEL {
+ /** Action 0-GET, 1-SET, 4 CLEAR*/
+ t_u16 action;
+ /** Not used set to zero */
+ t_u8 status;
+ /** Not used set to zero */
+ t_u8 reserved;
+ /** Band cfg */
+ Band_Config_t bandcfg;
+ /** channel */
+ t_u8 channel;
+ /** remain time: Unit ms*/
+ t_u32 remain_period;
+} MLAN_PACK_END HostCmd_DS_REMAIN_ON_CHANNEL;
+
+#ifdef WIFI_DIRECT_SUPPORT
+/** HostCmd_DS_WIFI_DIRECT_MODE */
+typedef MLAN_PACK_START struct _HostCmd_DS_WIFI_DIRECT_MODE {
+ /** Action 0-GET, 1-SET*/
+ t_u16 action;
+ /**0:disable 1:listen 2:GO 3:p2p client 4:find 5:stop find*/
+ t_u16 mode;
+} MLAN_PACK_END HostCmd_DS_WIFI_DIRECT_MODE;
+
+/** MrvlIEtypes_NoA_setting_t */
+typedef MLAN_PACK_START struct _MrvlIEtypes_NoA_setting_t {
+ /** Header */
+ MrvlIEtypesHeader_t header;
+ /** enable/disable */
+ t_u8 enable;
+ /** index */
+ t_u16 index;
+ /** NoA count */
+ t_u8 noa_count;
+ /** NoA duration */
+ t_u32 noa_duration;
+ /** NoA interval */
+ t_u32 noa_interval;
+} MLAN_PACK_END MrvlIEtypes_NoA_setting_t;
+
+/** MrvlIEtypes_NoA_setting_t */
+typedef MLAN_PACK_START struct _MrvlIEtypes_OPP_PS_setting_t {
+ /** Header */
+ MrvlIEtypesHeader_t header;
+ /** enable/disable && ct_window */
+ t_u8 enable;
+} MLAN_PACK_END MrvlIEtypes_OPP_PS_setting_t;
+
+/** HostCmd_DS_WIFI_DIRECT_PARAM_CONFIG */
+typedef MLAN_PACK_START struct _HostCmd_DS_WIFI_DIRECT_PARAM_CONFIG {
+ /** Action 0-GET, 1-SET */
+ t_u16 action;
+ /** MrvlIEtypes_NoA_setting_t
+ * MrvlIEtypes_OPP_PS_setting_t
+ */
+ t_u8 tlv_buf[];
+} MLAN_PACK_END HostCmd_DS_WIFI_DIRECT_PARAM_CONFIG;
+#endif
+
+MLAN_PACK_START struct coalesce_filt_field_param {
+ t_u8 operation;
+ t_u8 operand_len;
+ t_u16 offset;
+ t_u8 operand_byte_stream[4];
+} MLAN_PACK_END;
+
+MLAN_PACK_START struct coalesce_receive_filt_rule {
+ MrvlIEtypesHeader_t header;
+ t_u8 num_of_fields;
+ t_u8 pkt_type;
+ t_u16 max_coalescing_delay;
+ struct coalesce_filt_field_param params[];
+} MLAN_PACK_END;
+
+/** HostCmd_DS_COALESCE_CONFIG */
+typedef MLAN_PACK_START struct _HostCmd_DS_COALESCE_CONFIG {
+ /** Action 0-GET, 1-SET */
+ t_u16 action;
+ t_u16 num_of_rules;
+ struct coalesce_receive_filt_rule rule[];
+} MLAN_PACK_END HostCmd_DS_COALESCE_CONFIG;
+
+/** TLV type : FW support max connection TLV */
+#define TLV_TYPE_MAX_CONN (PROPRIETARY_TLV_BASE_ID + 0x117) /* 0x0217 */
+/** MrvlIEtypes_Max_Conn_t */
+typedef MLAN_PACK_START struct _MrvlIEtypes_Max_Conn_t {
+ /** Header */
+ MrvlIEtypesHeader_t header;
+ /** FW support max P2P connection */
+ t_u8 max_p2p_conn;
+ /** FW support max STA connection */
+ t_u8 max_sta_conn;
+} MLAN_PACK_END MrvlIEtypes_Max_Conn_t;
+
+/** exceed max p2p connection event */
+typedef MLAN_PACK_START struct _event_exceed_max_p2p_conn {
+ /** Event ID */
+ t_u16 event_id;
+ /** BSS index number for multiple BSS support */
+ t_u8 bss_index;
+ /** BSS type */
+ t_u8 bss_type;
+ /** When exceed max, the mac address who request p2p connect */
+ t_u8 peer_mac_addr[MLAN_MAC_ADDR_LENGTH];
+} MLAN_PACK_END event_exceed_max_p2p_conn;
+
+#ifdef STA_SUPPORT
+
+/**
+ * @brief Structure used internally in the wlan driver to configure a scan.
+ *
+ * Sent to the command process module to configure the firmware
+ * scan command prepared by wlan_cmd_802_11_scan.
+ *
+ * @sa wlan_scan_networks
+ *
+ */
+typedef MLAN_PACK_START struct _wlan_scan_cmd_config {
+ /**
+ * BSS Type to be sent in the firmware command
+ *
+ * Field can be used to restrict the types of networks returned in the
+ * scan. Valid settings are:
+ *
+ * - MLAN_SCAN_MODE_BSS (infrastructure)
+ * - MLAN_SCAN_MODE_IBSS (adhoc)
+ * - MLAN_SCAN_MODE_ANY (unrestricted, adhoc and infrastructure)
+ */
+ t_u8 bss_mode;
+
+ /**
+ * Specific BSSID used to filter scan results in the firmware
+ */
+ t_u8 specific_bssid[MLAN_MAC_ADDR_LENGTH];
+
+ /**
+ * Length of TLVs sent in command starting at tlvBuffer
+ */
+ t_u32 tlv_buf_len;
+
+ /**
+ * SSID TLV(s) and ChanList TLVs to be sent in the firmware command
+ *
+ * TLV_TYPE_CHANLIST, MrvlIEtypes_ChanListParamSet_t
+ * TLV_TYPE_SSID, MrvlIEtypes_SsIdParamSet_t
+ */
+ t_u8 tlv_buf[1]; /* SSID TLV(s) and ChanList TLVs are stored here */
+} MLAN_PACK_END wlan_scan_cmd_config;
+
+/**
+ * Sructure to retrieve the scan table
+ */
+typedef MLAN_PACK_START struct {
+ /**
+ * - Zero based scan entry to start retrieval in command request
+ * - Number of scans entries returned in command response
+ */
+ t_u32 scan_number;
+ /**
+ * Buffer marker for multiple wlan_ioctl_get_scan_table_entry
+ * structures. Each struct is padded to the nearest 32 bit boundary.
+ */
+ t_u8 scan_table_entry_buf[1];
+} MLAN_PACK_END wlan_get_scan_table_info;
+
+/** Generic structure defined for parsing WPA/RSN IEs for GTK/PTK OUIs */
+typedef MLAN_PACK_START struct {
+ /** Group key oui */
+ t_u8 GrpKeyOui[4];
+ /** Number of PTKs */
+ t_u8 PtkCnt[2];
+ /** Ptk body starts here */
+ t_u8 PtkBody[4];
+} MLAN_PACK_END IEBody;
+#endif /* STA_SUPPORT */
+
+/*
+ * This scan handle Country Information IE(802.11d compliant)
+ * Define data structure for HostCmd_CMD_802_11_SCAN
+ */
+/** HostCmd_DS_802_11_SCAN */
+typedef MLAN_PACK_START struct _HostCmd_DS_802_11_SCAN {
+ /** BSS mode */
+ t_u8 bss_mode;
+ /** BSSID */
+ t_u8 bssid[MLAN_MAC_ADDR_LENGTH];
+ /** TLV buffer */
+ t_u8 tlv_buffer[1];
+ /** MrvlIEtypes_SsIdParamSet_t SsIdParamSet;
+ * MrvlIEtypes_ChanListParamSet_t ChanListParamSet;
+ * MrvlIEtypes_RatesParamSet_t OpRateSet;
+ */
+} MLAN_PACK_END HostCmd_DS_802_11_SCAN;
+
+/** fw_cap_info bit to indicate enhance ext scan type */
+#define ENHANCE_EXT_SCAN_ENABLE MBIT(19)
+/** mlan_event_scan_result data structure */
+typedef MLAN_PACK_START struct _mlan_event_scan_result {
+ /** Event ID */
+ t_u16 event_id;
+ /** BSS index number for multiple BSS support */
+ t_u8 bss_index;
+ /** BSS type */
+ t_u8 bss_type;
+ /** More event available or not */
+ t_u8 more_event;
+ /** Reserved */
+ t_u8 reserved[3];
+ /** Size of the response buffer */
+ t_u16 buf_size;
+ /** Number of BSS in scan response */
+ t_u8 num_of_set;
+} MLAN_PACK_END mlan_event_scan_result, *pmlan_event_scan_result;
+
+/** ext scan status report event */
+typedef MLAN_PACK_START struct _mlan_event_scan_status {
+ /** Event ID */
+ t_u16 event_id;
+ /** BSS index number for multiple BSS support */
+ t_u8 bss_index;
+ /** BSS type */
+ t_u8 bss_type;
+ /** scan status */
+ t_u8 scan_status;
+ /** result */
+ t_u16 buf_len;
+ /** event buf */
+ t_u8 event_buf[];
+} MLAN_PACK_END mlan_event_scan_status, *pmlan_event_scan_status;
+
+/*
+ * This scan handle Country Information IE(802.11d compliant)
+ * Define data structure for HostCmd_CMD_802_11_SCAN_EXT
+ */
+/** HostCmd_DS_802_11_SCAN_EXT */
+typedef MLAN_PACK_START struct _HostCmd_DS_802_11_SCAN_EXT {
+ /** Scan type for ext scan
+ * 0: default type: cmd resp after ext scan report event
+ * 1: enhanced type: cmd resp before ext scan report event
+ * 2: scan cancelled: cancel scan during scan processing
+ */
+ t_u8 ext_scan_type;
+ /** Reserved */
+ t_u8 reserved[3];
+ /** TLV buffer */
+ t_u8 tlv_buffer[1];
+ /** MrvlIEtypes_Bssid_List_t BssIdList;
+ * MrvlIEtypes_SsIdParamSet_t SSIDParamSet;
+ * MrvlIEtypes_ChanListParamSet_t ChanListParamSet;
+ * MrvlIEtypes_RatesParamSet_t OpRateSet;
+ * MrvlIEtypes_NumProbes_t NumProbes;
+ * MrvlIEtypes_WildCardSsIdParamSet_t WildCardSSIDParamSet;
+ * MrvlIEtypes_BssMode_t BssMode;
+ */
+} MLAN_PACK_END HostCmd_DS_802_11_SCAN_EXT;
+
+/** MrvlIEtypes_BssMode */
+typedef MLAN_PACK_START struct _MrvlIEtypes_BssMode_t {
+ /** Header */
+ MrvlIEtypesHeader_t header;
+ /* INFRA/IBSS/AUTO */
+ t_u8 bss_mode;
+} MLAN_PACK_END MrvlIEtypes_BssMode_t;
+
+/** BSS scan Rsp */
+typedef MLAN_PACK_START struct _MrvlIEtypes_Bss_Scan_Rsp_t {
+ /** Header */
+ MrvlIEtypesHeader_t header;
+ /** BSSID of the BSS descriptor */
+ t_u8 bssid[MLAN_MAC_ADDR_LENGTH];
+ /** Beacon/Probe response buffer */
+ t_u8 frame_body[1];
+} MLAN_PACK_END MrvlIEtypes_Bss_Scan_Rsp_t;
+
+typedef MLAN_PACK_START struct _MrvlIEtypes_Bss_Scan_Info_t {
+ /** Header */
+ MrvlIEtypesHeader_t header;
+ /** RSSI for scan entry */
+ t_s16 rssi;
+ /** Channel ANPI */
+ t_s16 anpi;
+ /** Channel load (parts per 255) */
+ t_u8 cca_busy_fraction;
+ /** Band */
+ Band_Config_t bandcfg;
+ /** Channel */
+ t_u8 channel;
+ /** Reserved */
+ t_u8 reserved;
+ /** TSF data */
+ t_u64 tsf;
+} MLAN_PACK_END MrvlIEtypes_Bss_Scan_Info_t;
+
+/** HostCmd_DS_RX_MGMT_IND */
+typedef MLAN_PACK_START struct _HostCmd_DS_RX_MGMT_IND {
+ /** Action */
+ t_u16 action;
+ /** Mgmt frame subtype mask */
+ t_u32 mgmt_subtype_mask;
+} MLAN_PACK_END HostCmd_DS_RX_MGMT_IND;
+
+/** HostCmd_DS_802_11_SCAN_RSP */
+typedef MLAN_PACK_START struct _HostCmd_DS_802_11_SCAN_RSP {
+ /** Size of BSS descriptor */
+ t_u16 bss_descript_size;
+ /** Numner of sets */
+ t_u8 number_of_sets;
+ /** BSS descriptor and TLV buffer */
+ t_u8 bss_desc_and_tlv_buffer[1];
+} MLAN_PACK_END HostCmd_DS_802_11_SCAN_RSP;
+
+/** HostCmd_DS_802_11_BG_SCAN_CONFIG */
+typedef MLAN_PACK_START struct _HostCmd_DS_802_11_BG_SCAN_CONFIG {
+ /** action */
+ t_u16 action;
+ /** 0: disable, 1: enable */
+ t_u8 enable;
+ /** bss type */
+ t_u8 bss_type;
+ /** num of channel per scan */
+ t_u8 chan_per_scan;
+ /** reserved field */
+ t_u8 reserved;
+ /** reserved field */
+ t_u16 reserved1;
+ /** interval between consecutive scans */
+ t_u32 scan_interval;
+ /** reserved field */
+ t_u32 reserved2;
+ /** condition to trigger report to host */
+ t_u32 report_condition;
+ /** reserved field */
+ t_u16 reserved3;
+} MLAN_PACK_END HostCmd_DS_802_11_BG_SCAN_CONFIG;
+
+/** HostCmd_DS_802_11_BG_SCAN_QUERY */
+typedef MLAN_PACK_START struct _HostCmd_DS_802_11_BG_SCAN_QUERY {
+ /** Flush */
+ t_u8 flush;
+} MLAN_PACK_END HostCmd_DS_802_11_BG_SCAN_QUERY;
+
+/** HostCmd_DS_802_11_BG_SCAN_QUERY_RSP */
+typedef MLAN_PACK_START struct _HostCmd_DS_802_11_BG_SCAN_QUERY_RSP {
+ /** Report condition */
+ t_u32 report_condition;
+ /** Scan response */
+ HostCmd_DS_802_11_SCAN_RSP scan_resp;
+} MLAN_PACK_END HostCmd_DS_802_11_BG_SCAN_QUERY_RSP;
+
+/** MrvlIEtypes_StartLater_t */
+typedef MLAN_PACK_START struct _MrvlIEtypes_StartLater_t {
+ /** Header */
+ MrvlIEtypesHeader_t header;
+ /* 0 - BGScan start immediately, 1 - BGScan will start later after "Scan
+ * Interval" */
+ t_u16 value;
+} MLAN_PACK_END MrvlIEtypes_StartLater_t;
+
+/** MrvlIEtypes_RepeatCount_t */
+typedef MLAN_PACK_START struct _MrvlIEtypes_RepeatCount_t {
+ /** Header */
+ MrvlIEtypesHeader_t header;
+ /* Repeat count */
+ t_u16 repeat_count;
+} MLAN_PACK_END MrvlIEtypes_RepeatCount_t;
+
+/** MrvlIEtypes_DomainParamSet_t */
+typedef MLAN_PACK_START struct _MrvlIEtypes_DomainParamSet {
+ /** Header */
+ MrvlIEtypesHeader_t header;
+ /** Country code */
+ t_u8 country_code[COUNTRY_CODE_LEN];
+ /** Set of subbands */
+ IEEEtypes_SubbandSet_t sub_band[1];
+} MLAN_PACK_END MrvlIEtypes_DomainParamSet_t;
+
+/** HostCmd_DS_802_11D_DOMAIN_INFO */
+typedef MLAN_PACK_START struct _HostCmd_DS_802_11D_DOMAIN_INFO {
+ /** Action */
+ t_u16 action;
+ /** Domain parameter set */
+ MrvlIEtypes_DomainParamSet_t domain;
+} MLAN_PACK_END HostCmd_DS_802_11D_DOMAIN_INFO;
+
+/** HostCmd_DS_802_11D_DOMAIN_INFO_RSP */
+typedef MLAN_PACK_START struct _HostCmd_DS_802_11D_DOMAIN_INFO_RSP {
+ /** Action */
+ t_u16 action;
+ /** Domain parameter set */
+ MrvlIEtypes_DomainParamSet_t domain;
+} MLAN_PACK_END HostCmd_DS_802_11D_DOMAIN_INFO_RSP;
+
+/** HostCmd_DS_11N_ADDBA_REQ */
+typedef MLAN_PACK_START struct _HostCmd_DS_11N_ADDBA_REQ {
+ /** Result of the ADDBA Request Operation */
+ t_u8 add_req_result;
+ /** Peer MAC address */
+ t_u8 peer_mac_addr[MLAN_MAC_ADDR_LENGTH];
+ /** Dialog Token */
+ t_u8 dialog_token;
+ /** Block Ack Parameter Set */
+ t_u16 block_ack_param_set;
+ /** Block Act Timeout Value */
+ t_u16 block_ack_tmo;
+ /** Starting Sequence Number */
+ t_u16 ssn;
+} MLAN_PACK_END HostCmd_DS_11N_ADDBA_REQ;
+
+/** HostCmd_DS_11N_ADDBA_RSP */
+typedef MLAN_PACK_START struct _HostCmd_DS_11N_ADDBA_RSP {
+ /** Result of the ADDBA Response Operation */
+ t_u8 add_rsp_result;
+ /** Peer MAC address */
+ t_u8 peer_mac_addr[MLAN_MAC_ADDR_LENGTH];
+ /** Dialog Token */
+ t_u8 dialog_token;
+ /** Status Code */
+ t_u16 status_code;
+ /** Block Ack Parameter Set */
+ t_u16 block_ack_param_set;
+ /** Block Act Timeout Value */
+ t_u16 block_ack_tmo;
+ /** Starting Sequence Number */
+ t_u16 ssn;
+} MLAN_PACK_END HostCmd_DS_11N_ADDBA_RSP;
+
+/** HostCmd_DS_11N_DELBA */
+typedef MLAN_PACK_START struct _HostCmd_DS_11N_DELBA {
+ /** Result of the ADDBA Request Operation */
+ t_u8 del_result;
+ /** Peer MAC address */
+ t_u8 peer_mac_addr[MLAN_MAC_ADDR_LENGTH];
+ /** Delete Block Ack Parameter Set */
+ t_u16 del_ba_param_set;
+ /** Reason Code sent for DELBA */
+ t_u16 reason_code;
+ /** Reserved */
+ t_u8 reserved;
+} MLAN_PACK_END HostCmd_DS_11N_DELBA;
+
+/** HostCmd_DS_11N_BATIMEOUT */
+typedef MLAN_PACK_START struct _HostCmd_DS_11N_BATIMEOUT {
+ /** TID */
+ t_u8 tid;
+ /** Peer MAC address */
+ t_u8 peer_mac_addr[MLAN_MAC_ADDR_LENGTH];
+ /** Delete Block Ack Parameter Set */
+ t_u8 origninator;
+} MLAN_PACK_END HostCmd_DS_11N_BATIMEOUT;
+
+/** HostCmd_DS_11N_CFG */
+typedef MLAN_PACK_START struct _HostCmd_DS_11N_CFG {
+ /** Action */
+ t_u16 action;
+ /** HTTxCap */
+ t_u16 ht_tx_cap;
+ /** HTTxInfo */
+ t_u16 ht_tx_info;
+ /** Misc configuration */
+ t_u16 misc_config;
+} MLAN_PACK_END HostCmd_DS_11N_CFG;
+
+/** HostCmd_DS_11N_CFG */
+typedef MLAN_PACK_START struct _HostCmd_DS_REJECT_ADDBA_REQ {
+ /** Action */
+ t_u16 action;
+ /** Bit0 : host sleep activated
+ * Bit1 : auto reconnect enabled
+ * Others : reserved
+ */
+ t_u32 conditions;
+} MLAN_PACK_END HostCmd_DS_REJECT_ADDBA_REQ;
+
+/** HostCmd_DS_TXBUF_CFG*/
+typedef MLAN_PACK_START struct _HostCmd_DS_TXBUF_CFG {
+ /** Action */
+ t_u16 action;
+ /** Buffer Size */
+ t_u16 buff_size;
+ /** End Port_for Multiport */
+ t_u16 mp_end_port;
+ /** Reserved */
+ t_u16 reserved3;
+} MLAN_PACK_END HostCmd_DS_TXBUF_CFG;
+
+/** HostCmd_DS_AMSDU_AGGR_CTRL */
+typedef MLAN_PACK_START struct _HostCmd_DS_AMSDU_AGGR_CTRL {
+ /** Action */
+ t_u16 action;
+ /** Enable */
+ t_u16 enable;
+ /** Get the current Buffer Size valid */
+ t_u16 curr_buf_size;
+} MLAN_PACK_END HostCmd_DS_AMSDU_AGGR_CTRL;
+
+/** HostCmd_DS_11AC_CFG */
+typedef MLAN_PACK_START struct _HostCmd_DS_11AC_CFG {
+ /** Action */
+ t_u16 action;
+ /** BandConfig */
+ t_u8 band_config;
+ /** Misc Configuration */
+ t_u8 misc_config;
+ /** VHT Capability Info */
+ t_u32 vht_cap_info;
+ /** VHT Support MCS Set */
+ t_u8 vht_supp_mcs_set[VHT_MCS_SET_LEN];
+} MLAN_PACK_END HostCmd_DS_11AC_CFG;
+
+/** HostCmd_DS_11ACTXBUF_CFG*/
+typedef MLAN_PACK_START struct _HostCmd_DS_11ACTXBUF_CFG {
+ /** Action */
+ t_u16 action;
+ /** Buffer Size */
+ t_u16 buff_size;
+ /** End Port_for Multiport */
+ t_u16 mp_end_port;
+ /** Reserved */
+ t_u16 reserved3;
+} MLAN_PACK_END HostCmd_DS_11ACTXBUF_CFG;
+
+/** HostCmd_DS_11AX_CFG */
+typedef MLAN_PACK_START struct _HostCmd_DS_11AX_CFG {
+ /** Action */
+ t_u16 action;
+ /** BandConfig */
+ t_u8 band_config;
+ /** TLV for HE capability or HE operation */
+ t_u8 val[];
+} MLAN_PACK_END HostCmd_DS_11AX_CFG;
+
+/** HostCmd_DS_11AX_CMD_CFG */
+typedef MLAN_PACK_START struct _HostCmd_DS_11AX_CMD_CFG {
+ /** Action */
+ t_u16 action;
+ /** CMD_SUBID */
+ t_u16 sub_id;
+ /** TLV or value for cmd */
+ t_u8 val[];
+} MLAN_PACK_END HostCmd_DS_11AX_CMD_CFG;
+
+/** HostCmd_DS_RANGE_EXT */
+typedef MLAN_PACK_START struct _HostCmd_DS_RANGE_EXT {
+ /** Action */
+ t_u16 action;
+ /** Range ext mode */
+ t_u8 mode;
+} MLAN_PACK_END HostCmd_DS_RANGE_EXT;
+
+/** Type definition of hostcmd_twt_setup */
+typedef struct MLAN_PACK_START _hostcmd_twt_setup {
+ /** Implicit, 0: TWT session is explicit, 1: Session is implicit */
+ t_u8 implicit;
+ /** Announced, 0: Unannounced, 1: Announced TWT */
+ t_u8 announced;
+ /** Trigger Enabled, 0: Non-Trigger enabled, 1: Trigger enabled TWT */
+ t_u8 trigger_enabled;
+ /** TWT Information Disabled, 0: TWT info enabled, 1: TWT info disabled
+ */
+ t_u8 twt_info_disabled;
+ /** Negotiation Type, 0: Future Individual TWT SP start time, 1: Next
+ * Wake TBTT time */
+ t_u8 negotiation_type;
+ /** TWT Wakeup Duration, time after which the TWT requesting STA can
+ * transition to doze state */
+ t_u8 twt_wakeup_duration;
+ /** Flow Identifier. Range: [0-7]*/
+ t_u8 flow_identifier;
+ /** Hard Constraint, 0: FW can tweak the TWT setup parameters if it is
+ *rejected by AP.
+ ** 1: Firmware should not tweak any parameters. */
+ t_u8 hard_constraint;
+ /** TWT Exponent, Range: [0-63] */
+ t_u8 twt_exponent;
+ /** TWT Mantissa Range: [0-sizeof(UINT16)] */
+ t_u16 twt_mantissa;
+ /** TWT Request Type, 0: REQUEST_TWT, 1: SUGGEST_TWT*/
+ t_u8 twt_request;
+ /** TWT Setup State. Set to 0 by driver, filled by FW in response*/
+ t_u8 twt_setup_state;
+ /** Reserved, set to 0. */
+ t_u8 reserved[2];
+} MLAN_PACK_END hostcmd_twt_setup, *phostcmd_twt_setup;
+
+/** Type definition of hostcmd_twt_teardown */
+typedef struct MLAN_PACK_START _hostcmd_twt_teardown {
+ /** TWT Flow Identifier. Range: [0-7] */
+ t_u8 flow_identifier;
+ /** Negotiation Type. 0: Future Individual TWT SP start time, 1: Next
+ * Wake TBTT time */
+ t_u8 negotiation_type;
+ /** Tear down all TWT. 1: To teardown all TWT, 0 otherwise */
+ t_u8 teardown_all_twt;
+ /** TWT Teardown State. Set to 0 by driver, filled by FW in response */
+ t_u8 twt_teardown_state;
+ /** Reserved, set to 0. */
+ t_u8 reserved[3];
+} MLAN_PACK_END hostcmd_twt_teardown, *phostcmd_twt_teardown;
+
+/** HostCmd_DS_TWT_CFG */
+typedef MLAN_PACK_START struct _HostCmd_DS_TWT_CFG {
+ /** Action */
+ t_u16 action;
+ /** CMD_SUBID */
+ t_u16 sub_id;
+ /** TWT Setup/Teardown configuration parameters */
+ union {
+ /** TWT Setup config for Sub ID: MLAN_11AX_TWT_SETUP_SUBID */
+ hostcmd_twt_setup twt_setup;
+ /** TWT Teardown config for Sub ID: MLAN_11AX_TWT_TEARDOWN_SUBID
+ */
+ hostcmd_twt_teardown twt_teardown;
+ } param;
+} MLAN_PACK_END HostCmd_DS_TWT_CFG;
+
+/** HostCmd_DS_ECL_SYSTEM_CLOCK_CONFIG */
+typedef MLAN_PACK_START struct _HostCmd_DS_ECL_SYSTEM_CLOCK_CONFIG {
+ /** Action */
+ t_u16 action;
+ /** Current system clock */
+ t_u16 cur_sys_clk;
+ /** Clock type */
+ t_u16 sys_clk_type;
+ /** Length of clocks */
+ t_u16 sys_clk_len;
+ /** System clocks */
+ t_u16 sys_clk[16];
+} MLAN_PACK_END HostCmd_DS_ECL_SYSTEM_CLOCK_CONFIG;
+
+/** MrvlIEtypes_WmmParamSet_t */
+typedef MLAN_PACK_START struct _MrvlIEtypes_WmmParamSet_t {
+ /** Header */
+ MrvlIEtypesHeader_t header;
+ /** WMM IE */
+ t_u8 wmm_ie[1];
+} MLAN_PACK_END MrvlIEtypes_WmmParamSet_t;
+
+/** MrvlIEtypes_WmmQueueStatus_t */
+typedef MLAN_PACK_START struct {
+ /** Header */
+ MrvlIEtypesHeader_t header;
+ /** Queue index */
+ t_u8 queue_index;
+ /** Disabled flag */
+ t_u8 disabled;
+ /** Medium time allocation in 32us units*/
+ t_u16 medium_time;
+ /** Flow required flag */
+ t_u8 flow_required;
+ /** Flow created flag */
+ t_u8 flow_created;
+ /** Reserved */
+ t_u32 reserved;
+} MLAN_PACK_END MrvlIEtypes_WmmQueueStatus_t;
+
+/** Size of a TSPEC. Used to allocate necessary buffer space in commands */
+#define WMM_TSPEC_SIZE 63
+
+/** Extra IE bytes allocated in messages for appended IEs after a TSPEC */
+#define WMM_ADDTS_EXTRA_IE_BYTES 256
+
+/** Extra TLV bytes allocated in messages for configuring WMM Queues */
+#define WMM_QUEUE_CONFIG_EXTRA_TLV_BYTES 64
+
+/** Number of bins in the histogram for the HostCmd_DS_WMM_QUEUE_STATS */
+#define WMM_STATS_PKTS_HIST_BINS 7
+
+/**
+ * @brief Firmware command structure to retrieve the firmware WMM status.
+ *
+ * Used to retrieve the status of each WMM AC Queue in TLV
+ * format (MrvlIEtypes_WmmQueueStatus_t) as well as the current WMM
+ * parameter IE advertised by the AP.
+ *
+ * Used in response to a EVENT_WMM_STATUS_CHANGE event signaling
+ * a QOS change on one of the ACs or a change in the WMM Parameter in
+ * the Beacon.
+ *
+ * TLV based command, byte arrays used for max sizing purpose. There are no
+ * arguments sent in the command, the TLVs are returned by the firmware.
+ */
+typedef MLAN_PACK_START struct {
+ /** Queue status TLV */
+ t_u8 queue_status_tlv[sizeof(MrvlIEtypes_WmmQueueStatus_t) *
+ MAX_AC_QUEUES];
+ /** WMM parameter TLV */
+ t_u8 wmm_param_tlv[sizeof(IEEEtypes_WmmParameter_t) + 2];
+} MLAN_PACK_END HostCmd_DS_WMM_GET_STATUS;
+
+/**
+ * @brief Command structure for the HostCmd_CMD_WMM_ADDTS_REQ firmware command
+ */
+typedef MLAN_PACK_START struct {
+ mlan_cmd_result_e command_result; /**< Command result */
+ t_u32 timeout_ms; /**< Timeout value in milliseconds */
+ t_u8 dialog_token; /**< Dialog token */
+ t_u8 ieee_status_code; /**< IEEE status code */
+ t_u8 tspec_data[WMM_TSPEC_SIZE]; /**< TSPEC data */
+ t_u8 addts_extra_ie_buf[WMM_ADDTS_EXTRA_IE_BYTES]; /**< Extra IE buffer
+ */
+} MLAN_PACK_END HostCmd_DS_WMM_ADDTS_REQ;
+
+/**
+ * @brief Command structure for the HostCmd_CMD_WMM_DELTS_REQ firmware command
+ */
+typedef MLAN_PACK_START struct {
+ mlan_cmd_result_e command_result; /**< Command result */
+ t_u8 dialog_token; /**< Dialog token */
+ t_u8 ieee_reason_code; /**< IEEE reason code */
+ t_u8 tspec_data[WMM_TSPEC_SIZE]; /**< TSPEC data */
+} MLAN_PACK_END HostCmd_DS_WMM_DELTS_REQ;
+
+/**
+ * @brief Command structure for the HostCmd_CMD_WMM_QUEUE_CONFIG firmware cmd
+ *
+ * Set/Get/Default the Queue parameters for a specific AC in the firmware.
+ */
+typedef MLAN_PACK_START struct {
+ mlan_wmm_queue_config_action_e action; /**< Set, Get, or Default */
+ mlan_wmm_ac_e access_category; /**< WMM_AC_BK(0) to WMM_AC_VO(3) */
+ /** @brief MSDU lifetime expiry per 802.11e
+ *
+ * - Ignored if 0 on a set command
+ * - Set to the 802.11e specified 500 TUs when defaulted
+ */
+ t_u16 msdu_lifetime_expiry;
+ t_u8 tlv_buffer[WMM_QUEUE_CONFIG_EXTRA_TLV_BYTES]; /**< Not supported */
+} MLAN_PACK_END HostCmd_DS_WMM_QUEUE_CONFIG;
+
+/**
+ * @brief Command structure for the HostCmd_CMD_WMM_QUEUE_STATS firmware cmd
+ *
+ * Turn statistical collection on/off for a given AC or retrieve the
+ * accumulated stats for an AC and clear them in the firmware.
+ */
+typedef MLAN_PACK_START struct {
+ mlan_wmm_queue_stats_action_e action; /**< Start, Stop, or Get */
+#ifdef BIG_ENDIAN_SUPPORT
+ t_u8 select_bin : 7; /**< WMM_AC_BK(0) to WMM_AC_VO(3), or TID */
+ t_u8 select_is_userpri : 1; /**< Set if select_bin is UP, Clear for AC
+ */
+#else
+ t_u8 select_is_userpri : 1; /**< Set if select_bin is UP, Clear for AC
+ */
+ t_u8 select_bin : 7; /**< WMM_AC_BK(0) to WMM_AC_VO(3), or TID */
+#endif
+ t_u16 pkt_count; /**< Number of successful packets transmitted */
+ t_u16 pkt_loss; /**< Packets lost; not included in pktCount */
+ t_u32 avg_queue_delay; /**< Average Queue delay in microsec */
+ t_u32 avg_tx_delay; /**< Average Transmission delay in microsec */
+ t_u16 used_time; /**< Calc used time - units of 32 microsec */
+ t_u16 policed_time; /**< Calc policed time - units of 32 microsec */
+ /** @brief Queue Delay Histogram; number of packets per queue delay
+ * range
+ *
+ * [0] - 0ms <= delay < 5ms
+ * [1] - 5ms <= delay < 10ms
+ * [2] - 10ms <= delay < 20ms
+ * [3] - 20ms <= delay < 30ms
+ * [4] - 30ms <= delay < 40ms
+ * [5] - 40ms <= delay < 50ms
+ * [6] - 50ms <= delay < msduLifetime (TUs)
+ */
+ t_u16 delay_histogram[WMM_STATS_PKTS_HIST_BINS];
+ /** Reserved */
+ t_u16 reserved_1;
+} MLAN_PACK_END HostCmd_DS_WMM_QUEUE_STATS;
+
+/**
+ * @brief Command structure for the HostCmd_CMD_WMM_TS_STATUS firmware cmd
+ *
+ * Query the firmware to get the status of the WMM Traffic Streams
+ */
+typedef MLAN_PACK_START struct {
+ /** TSID: Range: 0->7 */
+ t_u8 tid;
+ /** TSID specified is valid */
+ t_u8 valid;
+ /** AC TSID is active on */
+ t_u8 access_category;
+ /** UP specified for the TSID */
+ t_u8 user_priority;
+ /** Power save mode for TSID: 0 (legacy), 1 (UAPSD) */
+ t_u8 psb;
+ /** Uplink(1), Downlink(2), Bidirectional(3) */
+ t_u8 flow_dir;
+ /** Medium time granted for the TSID */
+ t_u16 medium_time;
+} MLAN_PACK_END HostCmd_DS_WMM_TS_STATUS;
+
+/** Firmware status for a specific AC */
+typedef MLAN_PACK_START struct {
+ /** Disabled flag */
+ t_u8 disabled;
+ /** Flow required flag */
+ t_u8 flow_required;
+ /** Flow created flag */
+ t_u8 flow_created;
+} MLAN_PACK_END WmmAcStatus_t;
+
+/** Local Power Capability */
+typedef MLAN_PACK_START struct _MrvlIEtypes_PowerCapability_t {
+ /** Header */
+ MrvlIEtypesHeader_t header;
+ /** Minmum power */
+ t_s8 min_power;
+ /** Maximum power */
+ t_s8 max_power;
+} MLAN_PACK_END MrvlIEtypes_PowerCapability_t;
+
+/** HT Information element */
+typedef MLAN_PACK_START struct _MrvlIETypes_HTInfo_t {
+ /** Header */
+ MrvlIEtypesHeader_t header;
+
+ /** HTInfo struct */
+ HTInfo_t ht_info;
+} MLAN_PACK_END MrvlIETypes_HTInfo_t;
+
+/** 20/40 BSS Coexistence element */
+typedef MLAN_PACK_START struct _MrvlIETypes_2040BSSCo_t {
+ /** Header */
+ MrvlIEtypesHeader_t header;
+
+ /** BSSCo2040_t struct */
+ BSSCo2040_t bss_co_2040;
+} MLAN_PACK_END MrvlIETypes_2040BSSCo_t;
+
+/** Extended Capabilities element */
+typedef MLAN_PACK_START struct _MrvlIETypes_ExtCap_t {
+ /** Header */
+ MrvlIEtypesHeader_t header;
+
+ /** ExtCap_t struct */
+ ExtCap_t ext_cap;
+} MLAN_PACK_END MrvlIETypes_ExtCap_t;
+
+/** Supported operating classes element */
+typedef MLAN_PACK_START struct _MrvlIETypes_SuppOperClass_t {
+ /** Header */
+ MrvlIEtypesHeader_t header;
+ /** Current operationg class **/
+ t_u8 current_oper_class;
+ /** Operating class list */
+ t_u8 oper_class[1];
+} MLAN_PACK_END MrvlIETypes_SuppOperClass_t;
+
+/** Oper_class channel bandwidth element */
+typedef MLAN_PACK_START struct _MrvlIEtypes_chan_bw_oper_t {
+ /** Header */
+ MrvlIEtypesHeader_t header;
+ /** channel oper bandwidth*/
+ mlan_ds_bw_chan_oper ds_chan_bw_oper;
+} MLAN_PACK_END MrvlIEtypes_chan_bw_oper_t;
+
+/** Qos Info */
+typedef MLAN_PACK_START struct _MrvlIETypes_qosinfo_t {
+ /** Header */
+ MrvlIEtypesHeader_t header;
+ /** qos_info*/
+ t_u8 qos_info;
+} MLAN_PACK_END MrvlIETypes_qosinfo_t;
+
+/** Overlapping BSS Scan Parameters element */
+typedef MLAN_PACK_START struct _MrvlIETypes_OverlapBSSScanParam_t {
+ /** Header */
+ MrvlIEtypesHeader_t header;
+
+ /** OBSSScanParam_t struct */
+ OBSSScanParam_t obss_scan_param;
+} MLAN_PACK_END MrvlIETypes_OverlapBSSScanParam_t;
+
+/** Set of MCS values that STA desires to use within the BSS */
+typedef MLAN_PACK_START struct _MrvlIETypes_HTOperationalMCSSet_t {
+ /** Header */
+ MrvlIEtypesHeader_t header;
+
+ /** Bitmap indicating MCSs that STA desires to use within the BSS */
+ t_u8 ht_operational_mcs_bitmap[16];
+} MLAN_PACK_END MrvlIETypes_HTOperationalMCSSet_t;
+
+/** VHT Operations IE */
+typedef MLAN_PACK_START struct _MrvlIETypes_VHTOprat_t {
+ /** Header */
+ MrvlIEtypesHeader_t header;
+
+ t_u8 chan_width;
+ t_u8 chan_center_freq_1;
+ t_u8 chan_center_freq_2;
+ /** Basic MCS set map, each 2 bits stands for a Nss */
+ t_u16 basic_MCS_map;
+} MLAN_PACK_END MrvlIETypes_VHTOprat_t;
+
+/** VHT Transmit Power Envelope IE */
+typedef MLAN_PACK_START struct _MrvlIETypes_VHTtxpower_t {
+ /** Header */
+ MrvlIEtypesHeader_t header;
+
+ t_u8 max_tx_power;
+ t_u8 chan_center_freq;
+ t_u8 chan_width;
+} MLAN_PACK_END MrvlIETypes_VHTtxpower_t;
+
+/** Extended Power Constraint IE */
+typedef MLAN_PACK_START struct _MrvlIETypes_ExtPwerCons_t {
+ /** Header */
+ MrvlIEtypesHeader_t header;
+
+ /** channel width */
+ t_u8 chan_width;
+ /** local power constraint */
+ t_u8 local_power_cons;
+} MLAN_PACK_END MrvlIETypes_ExtPwerCons_t;
+
+/** Extended BSS Load IE */
+typedef MLAN_PACK_START struct _MrvlIETypes_ExtBSSload_t {
+ /** Header */
+ MrvlIEtypesHeader_t header;
+
+ t_u8 MU_MIMO_capa_count;
+ t_u8 stream_underutilization;
+ t_u8 VHT40_util;
+ t_u8 VHT80_util;
+ t_u8 VHT160_util;
+} MLAN_PACK_END MrvlIETypes_ExtBSSload_t;
+
+/** Quiet Channel IE */
+typedef MLAN_PACK_START struct _MrvlIETypes_QuietChan_t {
+ /** Header */
+ MrvlIEtypesHeader_t header;
+
+ t_u8 AP_quiet_mode;
+ t_u8 quiet_count;
+ t_u8 quiet_period;
+ t_u16 quiet_dur;
+ t_u16 quiet_offset;
+} MLAN_PACK_END MrvlIETypes_QuietChan_t;
+
+/** Wide Bandwidth Channel Switch IE */
+typedef MLAN_PACK_START struct _MrvlIETypes_BWSwitch_t {
+ /** Header */
+ MrvlIEtypesHeader_t header;
+
+ t_u8 new_chan_width;
+ t_u8 new_chan_center_freq_1;
+ t_u8 new_chan_center_freq_2;
+} MLAN_PACK_END MrvlIETypes_BWSwitch_t;
+
+/** AID IE */
+typedef MLAN_PACK_START struct _MrvlIETypes_AID_t {
+ /** Header */
+ MrvlIEtypesHeader_t header;
+
+ /** AID number */
+ t_u16 AID;
+} MLAN_PACK_END MrvlIETypes_AID_t;
+
+/** Operating Mode Notification IE */
+typedef MLAN_PACK_START struct _MrvlIETypes_OperModeNtf_t {
+ /** Header */
+ MrvlIEtypesHeader_t header;
+
+ /** operating mdoe */
+ t_u8 oper_mode;
+} MLAN_PACK_END MrvlIETypes_OperModeNtf_t;
+
+/** bf global args */
+typedef struct MLAN_PACK_START _bf_global_cfg_args {
+ /** Global enable/disable bf */
+ t_u8 bf_enbl;
+ /** Global enable/disable sounding */
+ t_u8 sounding_enbl;
+ /** FB Type */
+ t_u8 fb_type;
+ /** SNR Threshold */
+ t_u8 snr_threshold;
+ /** Sounding interval */
+ t_u16 sounding_interval;
+ /** BF mode */
+ t_u8 bf_mode;
+ /** Reserved */
+ t_u8 reserved;
+} MLAN_PACK_END bf_global_cfg_args;
+
+/** bf_trigger_sound_args_t */
+typedef MLAN_PACK_START struct _bf_trigger_sound_args_t {
+ /** Peer MAC address */
+ t_u8 peer_mac[MLAN_MAC_ADDR_LENGTH];
+ /** Status */
+ t_u8 status;
+} MLAN_PACK_END bf_trigger_sound_args_t;
+
+/** bf periodicity args */
+typedef MLAN_PACK_START struct _bf_periodicity_args {
+ /** Peer MAC address */
+ t_u8 peer_mac[MLAN_MAC_ADDR_LENGTH];
+ /** Current Tx BF Interval */
+ t_u16 interval;
+ /** Status */
+ t_u8 status;
+} MLAN_PACK_END bf_periodicity_args;
+
+/** bf peer configuration args */
+typedef struct MLAN_PACK_START _bf_peer_args {
+ /** Peer MAC address */
+ t_u8 peer_mac[MLAN_MAC_ADDR_LENGTH];
+ /** Reserved */
+ t_u16 reserved;
+ /** Enable/Disable Beamforming */
+ t_u8 bf_enbl;
+ /** Enable/Disable sounding */
+ t_u8 sounding_enbl;
+ /** FB Type */
+ t_u8 fb_type;
+} MLAN_PACK_END bf_peer_args;
+
+/** bf_snr_thr_t */
+typedef MLAN_PACK_START struct _bf_snr_thr_t {
+ /** Peer MAC address */
+ t_u8 peer_mac[MLAN_MAC_ADDR_LENGTH];
+ /** SNR */
+ t_u8 snr;
+} MLAN_PACK_END bf_snr_thr_t;
+
+/** HostCmd_DS_TX_BF_CFG */
+typedef MLAN_PACK_START struct _HostCmd_DS_TX_BF_CFG {
+ /* Beamforming action */
+ t_u16 bf_action;
+ /* action - SET/GET*/
+ t_u16 action;
+
+ MLAN_PACK_START union {
+ bf_global_cfg_args bf_global_cfg;
+ bf_trigger_sound_args_t bf_sound_args;
+ bf_periodicity_args bf_periodicity;
+ bf_peer_args tx_bf_peer;
+ bf_snr_thr_t bf_snr;
+ } MLAN_PACK_END body;
+} MLAN_PACK_END HostCmd_DS_TX_BF_CFG;
+
+#ifdef WIFI_DIRECT_SUPPORT
+/** MrvlIEtypes_psk_t */
+typedef MLAN_PACK_START struct _MrvlIEtypes_psk_t {
+ /** Header */
+ MrvlIEtypesHeader_t header;
+ /** PSK */
+ t_u8 psk[MLAN_MAX_KEY_LENGTH];
+} MLAN_PACK_END MrvlIEtypes_psk_t;
+#endif /* WIFI_DIRECT_SUPPORT */
+
+/** MrvlIEtypes_PMK_t */
+typedef MLAN_PACK_START struct _MrvlIEtypes_PMK_t {
+ /** Header */
+ MrvlIEtypesHeader_t header;
+ /** PMK */
+ t_u8 pmk[1];
+} MLAN_PACK_END MrvlIEtypes_PMK_t;
+
+/** MrvlIEtypes_Passphrase_t */
+typedef MLAN_PACK_START struct _MrvlIEtypes_Passphrase_t {
+ /** Header */
+ MrvlIEtypesHeader_t header;
+ /** Passphrase */
+ char passphrase[1];
+} MLAN_PACK_END MrvlIEtypes_Passphrase_t;
+
+/** MrvlIEtypes_SAE_Password_t */
+typedef MLAN_PACK_START struct _MrvlIEtypes_SAE_Password_t {
+ /** Header */
+ MrvlIEtypesHeader_t header;
+ /** SAE Password */
+ char sae_password[1];
+} MLAN_PACK_END MrvlIEtypes_SAE_Password_t;
+
+/* rsnMode -
+ * Bit 0 : No RSN
+ * Bit 1-2 : RFU
+ * Bit 3 : WPA
+ * Bit 4 : WPA-NONE
+ * Bit 5 : WPA2
+ * Bit 6 : AES CCKM
+ * Bit 7-15 : RFU
+ */
+/** MrvlIEtypes_EncrProto_t */
+typedef MLAN_PACK_START struct _MrvlIEtypes_EncrProto_t {
+ /** Header */
+ MrvlIEtypesHeader_t header;
+ /** EncrProto */
+ t_u16 rsn_mode;
+} MLAN_PACK_END MrvlIEtypes_EncrProto_t;
+
+/** MrvlIEtypes_Bssid_t */
+typedef MLAN_PACK_START struct _MrvlIEtypes_Bssid_t {
+ /** Header */
+ MrvlIEtypesHeader_t header;
+ /** Bssid */
+ t_u8 bssid[MLAN_MAC_ADDR_LENGTH];
+} MLAN_PACK_END MrvlIEtypes_Bssid_t;
+
+/*
+ * This struct will handle GET,SET,CLEAR function for embedded
+ * supplicant.
+ * Define data structure for HostCmd_CMD_802_11_SUPPLICANT_PMK
+ */
+/** HostCmd_DS_802_11_SUPPLICANT_PMK */
+typedef MLAN_PACK_START struct _HostCmd_DS_802_11_SUPPLICANT_PMK {
+ /** CMD Action GET/SET/CLEAR */
+ t_u16 action;
+ /** CacheResult initialized to 0 */
+ t_u16 cache_result;
+ /** TLV Buffer */
+ t_u8 tlv_buffer[1];
+ /** MrvlIEtypes_SsidParamSet_t SsidParamSet;
+ * MrvlIEtypes_PMK_t Pmk;
+ * MrvlIEtypes_Passphrase_t Passphrase;
+ * MrvlIEtypes_Bssid_t Bssid;
+ **/
+} MLAN_PACK_END HostCmd_DS_802_11_SUPPLICANT_PMK;
+
+/*
+ * This struct will GET the Supplicant supported bitmaps
+ * The GET_CURRENT action will get the network profile used
+ * for the current assocation.
+ * Define data structure for HostCmd_CMD_802_11_SUPPLICANT_PROFILE
+ */
+typedef MLAN_PACK_START struct _HostCmd_DS_802_11_SUPPLICANT_PROFILE {
+ /** GET/SET/GET_CURRENT */
+ t_u16 action;
+ /** Reserved */
+ t_u16 reserved;
+ /** TLVBuffer */
+ t_u8 tlv_buf[1];
+ /* MrvlIEtypes_EncrProto_t */
+} MLAN_PACK_END HostCmd_DS_802_11_SUPPLICANT_PROFILE;
+
+/* unicastCipher -
+ * Bit 0 : RFU
+ * Bit 1 : RFU
+ * Bit 2 : TKIP
+ * Bit 3 : AES CCKM
+ * Bit 2-7 : RFU
+ * multicastCipher -
+ * Bit 0 : WEP40
+ * Bit 1 : WEP104
+ * Bit 2 : TKIP
+ * Bit 3 : AES
+ * Bit 4-7 : Reserved for now
+ */
+/** MrvlIEtypes_Cipher_t */
+typedef MLAN_PACK_START struct _MrvlIEtypes_Cipher_t {
+ /** Header */
+ MrvlIEtypesHeader_t header;
+ /** PairCipher */
+ t_u8 pair_cipher;
+ /** GroupCipher */
+ t_u8 group_cipher;
+} MLAN_PACK_END MrvlIEtypes_Cipher_t;
+
+/** RFType */
+typedef MLAN_PACK_START struct _RFType_t {
+ /** band info */
+ Band_Config_t bandcfg;
+ /** reserved */
+ t_u8 reserved;
+} MLAN_PACK_END RFType_t;
+
+/** HostCmd_CMD_802_11_RF_CHANNEL */
+typedef MLAN_PACK_START struct _HostCmd_DS_802_11_RF_CHANNEL {
+ /** Action */
+ t_u16 action;
+ /** Current channel */
+ t_u16 current_channel;
+ /** RF type */
+ RFType_t rf_type;
+ /** Reserved field */
+ t_u16 reserved;
+#ifdef STA_SUPPORT
+ /** Reserved */
+ t_u8 reserved_1[32];
+#else /* STA_SUPPORT */
+ /** List of channels */
+ t_u8 channel_list[32];
+#endif /* !STA_SUPPORT */
+} MLAN_PACK_END HostCmd_DS_802_11_RF_CHANNEL;
+
+/** HostCmd_DS_VERSION_EXT */
+typedef MLAN_PACK_START struct _HostCmd_DS_VERSION_EXT {
+ /** Selected version string */
+ t_u8 version_str_sel;
+ /** Version string */
+ char version_str[128];
+} MLAN_PACK_END HostCmd_DS_VERSION_EXT;
+
+#define TLV_TYPE_CHAN_ATTR_CFG (PROPRIETARY_TLV_BASE_ID + 237)
+#define TLV_TYPE_REGION_INFO (PROPRIETARY_TLV_BASE_ID + 238)
+#define TLV_TYPE_POWER_TABLE (PROPRIETARY_TLV_BASE_ID + 262)
+#define TLV_TYPE_POWER_TABLE_ATTR (PROPRIETARY_TLV_BASE_ID + 317)
+/** HostCmd_DS_CHAN_REGION_CFG */
+typedef MLAN_PACK_START struct _HostCmd_DS_CHAN_REGION_CFG {
+ /** Action */
+ t_u16 action;
+} MLAN_PACK_END HostCmd_DS_CHAN_REGION_CFG;
+
+/** HostCmd_CMD_CW_MODE_CTRL */
+typedef MLAN_PACK_START struct _HostCmd_DS_CW_MODE_CTRL {
+ /** Action for CW Tone Control */
+ t_u16 action;
+ /** Mode of Operation 0: Disbale 1: Tx Continuous Packet 2: Tx
+ * Continuous Wave */
+ t_u8 mode;
+ /** channel */
+ t_u8 channel;
+ /** channel info*/
+ t_u8 chanInfo;
+ /** Tx Power level in dBm */
+ t_u16 txPower;
+ /** Packet Length */
+ t_u16 pktLength;
+ /** bit rate Info */
+ t_u32 rateInfo;
+} MLAN_PACK_END HostCmd_DS_CW_MODE_CTRL;
+
+/** HostCmd_CMD_802_11_RF_ANTENNA */
+typedef MLAN_PACK_START struct _HostCmd_DS_802_11_RF_ANTENNA {
+ /** Action for Tx antenna */
+ t_u16 action_tx;
+ /** Tx antenna mode Bit0:1, Bit1:2, Bit0-1:1+2, 0xffff: diversity */
+ t_u16 tx_antenna_mode;
+ /** Action for Rx antenna */
+ t_u16 action_rx;
+ /** Rx antenna mode Bit0:1, Bit1:2, Bit0-1:1+2, 0xffff: diversity */
+ t_u16 rx_antenna_mode;
+} MLAN_PACK_END HostCmd_DS_802_11_RF_ANTENNA;
+
+/** HostCmd_DS_802_11_IBSS_STATUS */
+typedef MLAN_PACK_START struct _HostCmd_DS_802_11_IBSS_STATUS {
+ /** Action */
+ t_u16 action;
+ /** Enable */
+ t_u16 enable;
+ /** BSSID */
+ t_u8 bssid[MLAN_MAC_ADDR_LENGTH];
+ /** Beacon interval */
+ t_u16 beacon_interval;
+ /** ATIM window interval */
+ t_u16 atim_window;
+ /** User G rate protection */
+ t_u16 use_g_rate_protect;
+} MLAN_PACK_END HostCmd_DS_802_11_IBSS_STATUS;
+
+/** HostCmd_DS_MGMT_IE_LIST_CFG */
+typedef MLAN_PACK_START struct _HostCmd_DS_MGMT_IE_LIST {
+ /** Action */
+ t_u16 action;
+ /** Get/Set mgmt IE */
+ mlan_ds_misc_custom_ie ds_mgmt_ie;
+} MLAN_PACK_END HostCmd_DS_MGMT_IE_LIST_CFG;
+
+/** HostCmd_CMD_MAC_REG_ACCESS */
+typedef MLAN_PACK_START struct _HostCmd_DS_MAC_REG_ACCESS {
+ /** Action */
+ t_u16 action;
+ /** MAC register offset */
+ t_u16 offset;
+ /** MAC register value */
+ t_u32 value;
+} MLAN_PACK_END HostCmd_DS_MAC_REG_ACCESS;
+
+/** HostCmd_CMD_BCA_REG_ACCESS */
+typedef MLAN_PACK_START struct _HostCmd_DS_BCA_REG_ACCESS {
+ /** Action */
+ t_u16 action;
+ /** BCA register offset */
+ t_u16 offset;
+ /** BCA register value */
+ t_u32 value;
+} MLAN_PACK_END HostCmd_DS_BCA_REG_ACCESS;
+
+/** HostCmd_CMD_BBP_REG_ACCESS */
+typedef MLAN_PACK_START struct _HostCmd_DS_BBP_REG_ACCESS {
+ /** Acion */
+ t_u16 action;
+ /** BBP register offset */
+ t_u16 offset;
+ /** BBP register value */
+ t_u8 value;
+ /** Reserved field */
+ t_u8 reserved[3];
+} MLAN_PACK_END HostCmd_DS_BBP_REG_ACCESS;
+
+/** HostCmd_CMD_RF_REG_ACCESS */
+typedef MLAN_PACK_START struct _HostCmd_DS_RF_REG_ACCESS {
+ /** Action */
+ t_u16 action;
+ /** RF register offset */
+ t_u16 offset;
+ /** RF register value */
+ t_u8 value;
+ /** Reserved field */
+ t_u8 reserved[3];
+} MLAN_PACK_END HostCmd_DS_RF_REG_ACCESS;
+
+/** HostCmd_DS_802_11_EEPROM_ACCESS */
+typedef MLAN_PACK_START struct _HostCmd_DS_802_11_EEPROM_ACCESS {
+ /** Action */
+ t_u16 action;
+
+ /** multiple 4 */
+ t_u16 offset;
+ /** Number of bytes */
+ t_u16 byte_count;
+ /** Value */
+ t_u8 value;
+} MLAN_PACK_END HostCmd_DS_802_11_EEPROM_ACCESS;
+
+/** HostCmd_DS_MEM_ACCESS */
+typedef MLAN_PACK_START struct _HostCmd_DS_MEM_ACCESS {
+ /** Action */
+ t_u16 action;
+ /** Reserved field */
+ t_u16 reserved;
+ /** Address */
+ t_u32 addr;
+ /** Value */
+ t_u32 value;
+} MLAN_PACK_END HostCmd_DS_MEM_ACCESS;
+
+/** HostCmd_DS_TARGET_ACCESS */
+typedef MLAN_PACK_START struct _HostCmd_DS_TARGET_ACCESS {
+ /** Action */
+ t_u16 action;
+ /** CSU Target Device. 1: CSU, 2: PSU */
+ t_u16 csu_target;
+ /** Target Device Address */
+ t_u16 address;
+ /** Data */
+ t_u8 data;
+} MLAN_PACK_END HostCmd_DS_TARGET_ACCESS;
+
+/** HostCmd_DS_SUBSCRIBE_EVENT */
+typedef MLAN_PACK_START struct _HostCmd_DS_SUBSCRIBE_EVENT {
+ /** Action */
+ t_u16 action;
+ /** Bitmap of subscribed events */
+ t_u16 event_bitmap;
+} MLAN_PACK_END HostCmd_DS_SUBSCRIBE_EVENT;
+
+/** HostCmd_DS_OTP_USER_DATA */
+typedef MLAN_PACK_START struct _HostCmd_DS_OTP_USER_DATA {
+ /** Action */
+ t_u16 action;
+ /** Reserved field */
+ t_u16 reserved;
+ /** User data length */
+ t_u16 user_data_length;
+ /** User data */
+ t_u8 user_data[1];
+} MLAN_PACK_END HostCmd_DS_OTP_USER_DATA;
+
+/** HostCmd_CMD_HS_WAKEUP_REASON */
+typedef MLAN_PACK_START struct _HostCmd_DS_HS_WAKEUP_REASON {
+ /** wakeupReason:
+ * 0: unknown
+ * 1: Broadcast data matched
+ * 2: Multicast data matched
+ * 3: Unicast data matched
+ * 4: Maskable event matched
+ * 5. Non-maskable event matched
+ * 6: Non-maskable condition matched (EAPoL rekey)
+ * 7: Magic pattern matched
+ * Others: reserved. (set to 0) */
+ t_u16 wakeup_reason;
+} MLAN_PACK_END HostCmd_DS_HS_WAKEUP_REASON;
+
+/** MrvlIEtypes_HsWakeHoldoff_t */
+typedef MLAN_PACK_START struct _MrvlIEtypes_HsWakeHoldoff_t {
+ /** Header */
+ MrvlIEtypesHeader_t header;
+ /** Minimum delay between HsActive and HostWake (in msec) */
+ t_u16 min_wake_holdoff;
+} MLAN_PACK_END MrvlIEtypes_HsWakeHoldoff_t;
+
+/** MrvlIEtypes_PsParamsInHs_t */
+typedef MLAN_PACK_START struct _MrvlIEtypes_PsParamsInHs_t {
+ /** Header */
+ MrvlIEtypesHeader_t header;
+ /** Host sleep wake interval(in msec) */
+ t_u32 hs_wake_interval;
+ /** Host sleep inactivity timeout (in msec) */
+ t_u32 hs_inactivity_timeout;
+} MLAN_PACK_END MrvlIEtypes_PsParamsInHs_t;
+
+/** MrvlIEtypes_WakeupSourceGPIO_t */
+typedef MLAN_PACK_START struct _MrvlIEtypes_WakeupSourceGPIO_t {
+ /** Header */
+ MrvlIEtypesHeader_t header;
+ /** GPIO for indication of wakeup source */
+ t_u8 ind_gpio;
+ /** Level on ind_gpio for normal wakeup source */
+ t_u8 level;
+} MLAN_PACK_END MrvlIEtypes_WakeupSourceGPIO_t;
+
+/** MrvlIEtypes_RobustcoexSourceGPIO_t */
+typedef MLAN_PACK_START struct _MrvlIEtypes_RobustcoexSourceGPIO_t {
+ /** Header */
+ MrvlIEtypesHeader_t header;
+ /** GPIO cfg for external bt request */
+ t_u8 enable;
+ /** GPIO number */
+ t_u8 gpio_num;
+ /** GPIO Polarity */
+ t_u8 gpio_polarity;
+} MLAN_PACK_END MrvlIEtypes_RobustcoexSourceGPIO_t;
+
+#define MAX_NUM_MAC 2
+
+typedef MLAN_PACK_START struct _dmcs_chan_status {
+ /** Channel number */
+ t_u8 channel;
+ /** Number of AP on this channel */
+ t_u8 ap_count;
+ /** Number of STA on this channel*/
+ t_u8 sta_count;
+} MLAN_PACK_END dmcs_chan_status;
+
+typedef MLAN_PACK_START struct _dmcs_status {
+ /** radio ID */
+ t_u8 radio_id;
+ /** Running mode
+ ** 0 - Idle
+ ** 1 - DBC
+ ** 2 - DRCS
+ */
+ t_u8 running_mode;
+ /** Channel status of this radio */
+ dmcs_chan_status chan_status[2];
+} MLAN_PACK_END dmcs_status;
+
+/** MrvlIEtypes_DmcsConfig_t */
+typedef MLAN_PACK_START struct _MrvlIEtypes_DmcsConfig_t {
+ /** Header */
+ MrvlIEtypesHeader_t header;
+ /** Mapping policy */
+ t_u8 mapping_policy;
+ /** Radio status of DMCS */
+ dmcs_status radio_status[MAX_NUM_MAC];
+} MLAN_PACK_END MrvlIEtypes_DmcsStatus_t;
+
+#define ANTMODE_FW_DECISION 0xff
+/** MrvlIEtypes_HS_Antmode_t */
+typedef MLAN_PACK_START struct _MrvlIEtypes_HS_Antmode_t {
+ /** Header */
+ MrvlIEtypesHeader_t header;
+ /** Tx Path antenna mode*/
+ t_u8 txpath_antmode;
+ /** Rx Path antenna mode */
+ t_u8 rxpath_antmode;
+} MLAN_PACK_END MrvlIEtypes_HS_Antmode_t;
+
+typedef MLAN_PACK_START struct _MrvlIEtypes_WakeupExtend_t {
+ /** Header */
+ MrvlIEtypesHeader_t header;
+ /** Events that will be forced ignore **/
+ t_u32 event_force_ignore;
+ /** Events that will use extend gap to inform host*/
+ t_u32 event_use_ext_gap;
+ /** Extend gap*/
+ t_u8 ext_gap;
+ /** GPIO wave level*/
+ t_u8 gpio_wave;
+} MLAN_PACK_END MrvlIEtypes_WakeupExtend_t;
+
+#define EVENT_MANAGEMENT_FRAME_WAKEUP 136
+typedef MLAN_PACK_START struct _mgmt_frame_filter {
+ /** action - bitmap
+ ** On matching rx'd pkt and filter during NON_HOSTSLEEP mode:
+ ** Action[1]=0 Discard
+ ** Action[1]=1 Allow
+ ** Note that default action on non-match is "Allow".
+ **
+ ** On matching rx'd pkt and filter during HOSTSLEEP mode:
+ ** Action[1:0]=00 Discard and Not Wake host
+ ** Action[1:0]=01 Discard and Wake host
+ ** Action[1:0]=10 Invalid
+ ** Note that default action on non-match is "Discard and Not Wake
+ *host".
+ **/
+ t_u8 action;
+ /** Frame type(p2p...)
+ ** type=0: invalid
+ ** type=1: p2p
+ ** type=0xff: management frames(assoc req/rsp, probe req/rsp,...)
+ ** type=others: reserved
+ **/
+ t_u8 type;
+ /** Frame mask according to each type
+ ** When type=1 for p2p, frame-mask have following define:
+ ** Bit Frame
+ ** 0 GO Negotiation Request
+ ** 1 GO Negotiation Response
+ ** 2 GO Negotiation Confirmation
+ ** 3 P2P Invitation Request
+ ** 4 P2P Invitation Response
+ ** 5 Device Discoverability Request
+ ** 6 Device Discoverability Response
+ ** 7 Provision Discovery Request
+ ** 8 Provision Discovery Response
+ ** 9 Notice of Absence
+ ** 10 P2P Presence Request
+ ** 11 P2P Presence Response
+ ** 12 GO Discoverability Request
+ ** 13-31 Reserved
+ **
+ ** When type=others, frame-mask is reserved.
+ **/
+ t_u32 frame_mask;
+} MLAN_PACK_END mgmt_frame_filter;
+
+#define MAX_MGMT_FRAME_FILTER 2
+/** MrvlIEtypes_MgmtFrameFilter_t */
+typedef MLAN_PACK_START struct _MrvlIEtypes_MgmtFrameFilter_t {
+ /** Header */
+ MrvlIEtypesHeader_t header;
+ /** management frame filters */
+ mgmt_frame_filter filter[MAX_MGMT_FRAME_FILTER];
+} MLAN_PACK_END MrvlIEtypes_MgmtFrameFilter_t;
+
+/** HostCmd_DS_INACTIVITY_TIMEOUT_EXT */
+typedef MLAN_PACK_START struct _HostCmd_DS_INACTIVITY_TIMEOUT_EXT {
+ /** ACT_GET/ACT_SET */
+ t_u16 action;
+ /** uS, 0 means 1000uS(1ms) */
+ t_u16 timeout_unit;
+ /** Inactivity timeout for unicast data */
+ t_u16 unicast_timeout;
+ /** Inactivity timeout for multicast data */
+ t_u16 mcast_timeout;
+ /** Timeout for additional RX traffic after Null PM1 packet exchange */
+ t_u16 ps_entry_timeout;
+ /** Reserved to further expansion */
+ t_u16 reserved;
+} MLAN_PACK_END HostCmd_DS_INACTIVITY_TIMEOUT_EXT;
+
+/** HostCmd_DS_INDEPENDENT_RESET_CFG */
+typedef MLAN_PACK_START struct _HostCmd_DS_INDEPENDENT_RESET_CFG {
+ /** ACT_GET/ACT_SET */
+ t_u16 action;
+ /** out band independent reset */
+ t_u8 ir_mode;
+ /** gpio pin */
+ t_u8 gpio_pin;
+} MLAN_PACK_END HostCmd_DS_INDEPENDENT_RESET_CFG;
+
+/** HostCmd_DS_802_11_PS_INACTIVITY_TIMEOUT */
+typedef MLAN_PACK_START struct _HostCmd_DS_802_11_PS_INACTIVITY_TIMEOUT {
+ /** ACT_GET/ACT_SET */
+ t_u16 action;
+ /** ps inactivity timeout value */
+ t_u16 inact_tmo;
+} MLAN_PACK_END HostCmd_DS_802_11_PS_INACTIVITY_TIMEOUT;
+
+/** TLV type : STA Mac address */
+#define TLV_TYPE_STA_MAC_ADDRESS (PROPRIETARY_TLV_BASE_ID + 0x20) /* 0x0120 */
+
+#define TLV_TYPE_RANDOM_MAC (PROPRIETARY_TLV_BASE_ID + 0xEC) /*0x01EC*/
+
+/** MrvlIEtypes_MacAddr_t */
+typedef MLAN_PACK_START struct _MrvlIEtypes_MacAddr_t {
+ /** Header */
+ MrvlIEtypesHeader_t header;
+ /** mac address */
+ t_u8 mac[MLAN_MAC_ADDR_LENGTH];
+} MLAN_PACK_END MrvlIEtypes_MacAddr_t;
+
+/** Assoc Request */
+#define SUBTYPE_ASSOC_REQUEST 0
+/** ReAssoc Request */
+#define SUBTYPE_REASSOC_REQUEST 2
+/** Probe Resp */
+#define SUBTYPE_PROBE_RESP 5
+/** Disassoc Request */
+#define SUBTYPE_DISASSOC 10
+/** Auth Request */
+#define SUBTYPE_AUTH 11
+/** Deauth Request */
+#define SUBTYPE_DEAUTH 12
+/** Action frame */
+#define SUBTYPE_ACTION 13
+/** beacon */
+#define SUBTYPE_BEACON 8
+
+#ifdef UAP_SUPPORT
+/** TLV type : AP Channel band Config */
+#define TLV_TYPE_UAP_CHAN_BAND_CONFIG \
+ (PROPRIETARY_TLV_BASE_ID + 0x2a) /* 0x012a */
+/** TLV type : AP Mac address */
+#define TLV_TYPE_UAP_MAC_ADDRESS (PROPRIETARY_TLV_BASE_ID + 0x2b) /* 0x012b */
+/** TLV type : AP Beacon period */
+#define TLV_TYPE_UAP_BEACON_PERIOD \
+ (PROPRIETARY_TLV_BASE_ID + 0x2c) /* 0x012c \
+ */
+/** TLV type : AP DTIM period */
+#define TLV_TYPE_UAP_DTIM_PERIOD (PROPRIETARY_TLV_BASE_ID + 0x2d) /* 0x012d */
+/** TLV type : AP Tx power */
+#define TLV_TYPE_UAP_TX_POWER (PROPRIETARY_TLV_BASE_ID + 0x2f) /* 0x012f */
+/** TLV type : AP SSID broadcast control */
+#define TLV_TYPE_UAP_BCAST_SSID_CTL \
+ (PROPRIETARY_TLV_BASE_ID + 0x30) /* 0x0130 */
+/** TLV type : AP Preamble control */
+#define TLV_TYPE_UAP_PREAMBLE_CTL \
+ (PROPRIETARY_TLV_BASE_ID + 0x31) /* 0x0131 \
+ */
+/** TLV type : AP Antenna control */
+#define TLV_TYPE_UAP_ANTENNA_CTL (PROPRIETARY_TLV_BASE_ID + 0x32) /* 0x0132 */
+/** TLV type : AP RTS threshold */
+#define TLV_TYPE_UAP_RTS_THRESHOLD \
+ (PROPRIETARY_TLV_BASE_ID + 0x33) /* 0x0133 \
+ */
+/** TLV type : AP Tx data rate */
+#define TLV_TYPE_UAP_TX_DATA_RATE \
+ (PROPRIETARY_TLV_BASE_ID + 0x35) /* 0x0135 \
+ */
+/** TLV type: AP Packet forwarding control */
+#define TLV_TYPE_UAP_PKT_FWD_CTL (PROPRIETARY_TLV_BASE_ID + 0x36) /* 0x0136 */
+/** TLV type: STA information */
+#define TLV_TYPE_UAP_STA_INFO (PROPRIETARY_TLV_BASE_ID + 0x37) /* 0x0137 */
+/** TLV type: AP STA MAC address filter */
+#define TLV_TYPE_UAP_STA_MAC_ADDR_FILTER \
+ (PROPRIETARY_TLV_BASE_ID + 0x38) /* 0x0138 */
+/** TLV type: AP STA ageout timer */
+#define TLV_TYPE_UAP_STA_AGEOUT_TIMER \
+ (PROPRIETARY_TLV_BASE_ID + 0x39) /* 0x0139 */
+/** TLV type: AP WEP keys */
+#define TLV_TYPE_UAP_WEP_KEY (PROPRIETARY_TLV_BASE_ID + 0x3b) /* 0x013b */
+/** TLV type: AP WPA passphrase */
+#define TLV_TYPE_UAP_WPA_PASSPHRASE \
+ (PROPRIETARY_TLV_BASE_ID + 0x3c) /* 0x013c */
+/** TLV type: AP protocol */
+#define TLV_TYPE_UAP_ENCRYPT_PROTOCOL \
+ (PROPRIETARY_TLV_BASE_ID + 0x40) /* 0x0140 */
+/** TLV type: AP AKMP */
+#define TLV_TYPE_UAP_AKMP (PROPRIETARY_TLV_BASE_ID + 0x41) /* 0x0141 */
+/** TLV type: AP Fragment threshold */
+#define TLV_TYPE_UAP_FRAG_THRESHOLD \
+ (PROPRIETARY_TLV_BASE_ID + 0x46) /* 0x0146 */
+/** TLV type: AP Group rekey timer */
+#define TLV_TYPE_UAP_GRP_REKEY_TIME \
+ (PROPRIETARY_TLV_BASE_ID + 0x47) /* 0x0147 */
+/**TLV type : AP Max Station number */
+#define TLV_TYPE_UAP_MAX_STA_CNT (PROPRIETARY_TLV_BASE_ID + 0x55) /* 0x0155 */
+/**TLV type : AP Max Station number per chip */
+#define TLV_TYPE_UAP_MAX_STA_CNT_PER_CHIP \
+ (PROPRIETARY_TLV_BASE_ID + 0x140) /* 0x0240 */
+/**TLV type : AP Retry limit */
+#define TLV_TYPE_UAP_RETRY_LIMIT (PROPRIETARY_TLV_BASE_ID + 0x5d) /* 0x015d */
+/** TLV type : AP MCBC data rate */
+#define TLV_TYPE_UAP_MCBC_DATA_RATE \
+ (PROPRIETARY_TLV_BASE_ID + 0x62) /* 0x0162 */
+/**TLV type: AP RSN replay protection */
+#define TLV_TYPE_UAP_RSN_REPLAY_PROTECT \
+ (PROPRIETARY_TLV_BASE_ID + 0x64) /* 0x0164 */
+/**TLV type: AP mgmt IE passthru mask */
+#define TLV_TYPE_UAP_MGMT_IE_PASSTHRU_MASK \
+ (PROPRIETARY_TLV_BASE_ID + 0x70) /* 0x0170 */
+
+/**TLV type: AP pairwise handshake timeout */
+#define TLV_TYPE_UAP_EAPOL_PWK_HSK_TIMEOUT \
+ (PROPRIETARY_TLV_BASE_ID + 0x75) /* 0x0175 */
+/**TLV type: AP pairwise handshake retries */
+#define TLV_TYPE_UAP_EAPOL_PWK_HSK_RETRIES \
+ (PROPRIETARY_TLV_BASE_ID + 0x76) /* 0x0176 */
+/**TLV type: AP groupwise handshake timeout */
+#define TLV_TYPE_UAP_EAPOL_GWK_HSK_TIMEOUT \
+ (PROPRIETARY_TLV_BASE_ID + 0x77) /* 0x0177 */
+/**TLV type: AP groupwise handshake retries */
+#define TLV_TYPE_UAP_EAPOL_GWK_HSK_RETRIES \
+ (PROPRIETARY_TLV_BASE_ID + 0x78) /* 0x0178 */
+/** TLV type: AP PS STA ageout timer */
+#define TLV_TYPE_UAP_PS_STA_AGEOUT_TIMER \
+ (PROPRIETARY_TLV_BASE_ID + 0x7b) /* 0x017b */
+/** TLV type : Pairwise Cipher */
+#define TLV_TYPE_PWK_CIPHER (PROPRIETARY_TLV_BASE_ID + 0x91) /* 0x0191 */
+/** TLV type : Group Cipher */
+#define TLV_TYPE_GWK_CIPHER (PROPRIETARY_TLV_BASE_ID + 0x92) /* 0x0192 */
+/** TLV type : BSS Status */
+#define TLV_TYPE_BSS_STATUS (PROPRIETARY_TLV_BASE_ID + 0x93) /* 0x0193 */
+/** TLV type : AP WMM params */
+#define TLV_TYPE_AP_WMM_PARAM (PROPRIETARY_TLV_BASE_ID + 0xd0) /* 0x01d0 */
+/** TLV type : AP Tx beacon rate */
+#define TLV_TYPE_UAP_TX_BEACON_RATE \
+ (PROPRIETARY_TLV_BASE_ID + 288) /* 0x0220 \
+ */
+
+/** MrvlIEtypes_beacon_period_t */
+typedef MLAN_PACK_START struct _MrvlIEtypes_beacon_period_t {
+ /** Header */
+ MrvlIEtypesHeader_t header;
+ /** beacon period */
+ t_u16 beacon_period;
+} MLAN_PACK_END MrvlIEtypes_beacon_period_t;
+
+/** MrvlIEtypes_dtim_period_t */
+typedef MLAN_PACK_START struct _MrvlIEtypes_dtim_period_t {
+ /** Header */
+ MrvlIEtypesHeader_t header;
+ /** DTIM period */
+ t_u8 dtim_period;
+} MLAN_PACK_END MrvlIEtypes_dtim_period_t;
+
+/** MrvlIEtypes_tx_rate_t */
+typedef MLAN_PACK_START struct _MrvlIEtypes_tx_rate_t {
+ /** Header */
+ MrvlIEtypesHeader_t header;
+ /** tx data rate */
+ t_u16 tx_data_rate;
+} MLAN_PACK_END MrvlIEtypes_tx_rate_t;
+
+/** MrvlIEtypes_mcbc_rate_t */
+typedef MLAN_PACK_START struct _MrvlIEtypes_mcbc_rate_t {
+ /** Header */
+ MrvlIEtypesHeader_t header;
+ /** mcbc data rate */
+ t_u16 mcbc_data_rate;
+} MLAN_PACK_END MrvlIEtypes_mcbc_rate_t;
+
+/** MrvlIEtypes_tx_power_t */
+typedef MLAN_PACK_START struct _MrvlIEtypes_tx_power_t {
+ /** Header */
+ MrvlIEtypesHeader_t header;
+ /** tx power */
+ t_u8 tx_power;
+} MLAN_PACK_END MrvlIEtypes_tx_power_t;
+
+/** MrvlIEtypes_bcast_ssid_t */
+typedef MLAN_PACK_START struct _MrvlIEtypes_bcast_ssid_t {
+ /** Header */
+ MrvlIEtypesHeader_t header;
+ /** bcast ssid control*/
+ t_u8 bcast_ssid_ctl;
+} MLAN_PACK_END MrvlIEtypes_bcast_ssid_t;
+
+/** MrvlIEtypes_antenna_mode_t */
+typedef MLAN_PACK_START struct _MrvlIEtypes_antenna_mode_t {
+ /** Header */
+ MrvlIEtypesHeader_t header;
+ /** which antenna */
+ t_u8 which_antenna;
+ /** antenna mode*/
+ t_u8 antenna_mode;
+} MLAN_PACK_END MrvlIEtypes_antenna_mode_t;
+
+/** MrvlIEtypes_pkt_forward_t */
+typedef MLAN_PACK_START struct _MrvlIEtypes_pkt_forward_t {
+ /** Header */
+ MrvlIEtypesHeader_t header;
+ /** pkt foward control */
+ t_u8 pkt_forward_ctl;
+} MLAN_PACK_END MrvlIEtypes_pkt_forward_t;
+
+/** MrvlIEtypes_max_sta_count_t */
+typedef MLAN_PACK_START struct _MrvlIEtypes_max_sta_count_t {
+ /** Header */
+ MrvlIEtypesHeader_t header;
+ /** max station count */
+ t_u16 max_sta_count;
+} MLAN_PACK_END MrvlIEtypes_max_sta_count_t;
+
+/** MrvlIEtypes_uap_max_sta_cnt */
+typedef MLAN_PACK_START struct _MrvlIEtypes_uap_max_sta_cnt_t {
+ /** Header */
+ MrvlIEtypesHeader_t header;
+ /** max station count */
+ t_u16 uap_max_sta;
+} MLAN_PACK_END MrvlIEtypes_uap_max_sta_cnt_t;
+
+/** MrvlIEtypes_sta_ageout_t */
+typedef MLAN_PACK_START struct _MrvlIEtypes_sta_ageout_t {
+ /** Header */
+ MrvlIEtypesHeader_t header;
+ /** station age out timer */
+ t_u32 sta_ageout_timer;
+} MLAN_PACK_END MrvlIEtypes_sta_ageout_t;
+
+/** MrvlIEtypes_rts_threshold_t */
+typedef MLAN_PACK_START struct _MrvlIEtypes_rts_threshold_t {
+ /** Header */
+ MrvlIEtypesHeader_t header;
+ /** rts threshold */
+ t_u16 rts_threshold;
+} MLAN_PACK_END MrvlIEtypes_rts_threshold_t;
+
+/** MrvlIEtypes_frag_threshold_t */
+typedef MLAN_PACK_START struct _MrvlIEtypes_frag_threshold_t {
+ /** Header */
+ MrvlIEtypesHeader_t header;
+ /** frag threshold */
+ t_u16 frag_threshold;
+} MLAN_PACK_END MrvlIEtypes_frag_threshold_t;
+
+/** MrvlIEtypes_retry_limit_t */
+typedef MLAN_PACK_START struct _MrvlIEtypes_retry_limit_t {
+ /** Header */
+ MrvlIEtypesHeader_t header;
+ /** retry limit */
+ t_u8 retry_limit;
+} MLAN_PACK_END MrvlIEtypes_retry_limit_t;
+
+/** MrvlIEtypes_eapol_pwk_hsk_timeout_t */
+typedef MLAN_PACK_START struct _MrvlIEtypes_eapol_pwk_hsk_timeout_t {
+ /** Header */
+ MrvlIEtypesHeader_t header;
+ /** pairwise update timeout in milliseconds */
+ t_u32 pairwise_update_timeout;
+} MLAN_PACK_END MrvlIEtypes_eapol_pwk_hsk_timeout_t;
+
+/** MrvlIEtypes_eapol_pwk_hsk_retries_t */
+typedef MLAN_PACK_START struct _MrvlIEtypes_eapol_pwk_hsk_retries_t {
+ /** Header */
+ MrvlIEtypesHeader_t header;
+ /** pairwise handshake retries */
+ t_u32 pwk_retries;
+} MLAN_PACK_END MrvlIEtypes_eapol_pwk_hsk_retries_t;
+
+/** MrvlIEtypes_eapol_gwk_hsk_timeout_t */
+typedef MLAN_PACK_START struct _MrvlIEtypes_eapol_gwk_hsk_timeout_t {
+ /** Header */
+ MrvlIEtypesHeader_t header;
+ /** groupwise update timeout in milliseconds */
+ t_u32 groupwise_update_timeout;
+} MLAN_PACK_END MrvlIEtypes_eapol_gwk_hsk_timeout_t;
+
+/** MrvlIEtypes_eapol_gwk_hsk_retries_t */
+typedef MLAN_PACK_START struct _MrvlIEtypes_eapol_gwk_hsk_retries_t {
+ /** Header */
+ MrvlIEtypesHeader_t header;
+ /** groupwise handshake retries */
+ t_u32 gwk_retries;
+} MLAN_PACK_END MrvlIEtypes_eapol_gwk_hsk_retries_t;
+
+/** MrvlIEtypes_mgmt_ie_passthru_t */
+typedef MLAN_PACK_START struct _MrvlIEtypes_mgmt_ie_passthru_t {
+ /** Header */
+ MrvlIEtypesHeader_t header;
+ /** mgmt IE mask value */
+ t_u32 mgmt_ie_mask;
+} MLAN_PACK_END MrvlIEtypes_mgmt_ie_passthru_t;
+
+/** MrvlIEtypes_mac_filter_t */
+typedef MLAN_PACK_START struct _MrvlIEtypes_mac_filter_t {
+ /** Header */
+ MrvlIEtypesHeader_t header;
+ /** Filter mode */
+ t_u8 filter_mode;
+ /** Number of STA MACs */
+ t_u8 count;
+ /** STA MAC addresses buffer */
+ t_u8 mac_address[1];
+} MLAN_PACK_END MrvlIEtypes_mac_filter_t;
+
+/** MrvlIEtypes_auth_type_t */
+typedef MLAN_PACK_START struct _MrvlIEtypes_auth_type_t {
+ /** Header */
+ MrvlIEtypesHeader_t header;
+ /** Authentication type */
+ t_u8 auth_type;
+} MLAN_PACK_END MrvlIEtypes_auth_type_t;
+
+/** MrvlIEtypes_encrypt_protocol_t */
+typedef MLAN_PACK_START struct _MrvlIEtypes_encrypt_protocol_t {
+ /** Header */
+ MrvlIEtypesHeader_t header;
+ /** encryption protocol */
+ t_u16 protocol;
+} MLAN_PACK_END MrvlIEtypes_encrypt_protocol_t;
+
+/** MrvlIEtypes_pwk_cipher_t */
+typedef MLAN_PACK_START struct _MrvlIEtypes_pwk_cipher_t {
+ /** Header */
+ MrvlIEtypesHeader_t header;
+ /** protocol */
+ t_u16 protocol;
+ /** pairwise cipher */
+ t_u8 pairwise_cipher;
+ /** reserved */
+ t_u8 reserved;
+} MLAN_PACK_END MrvlIEtypes_pwk_cipher_t;
+
+/** MrvlIEtypes_gwk_cipher_t */
+typedef MLAN_PACK_START struct _MrvlIEtypes_gwk_cipher_t {
+ /** Header */
+ MrvlIEtypesHeader_t header;
+ /** group cipher */
+ t_u8 group_cipher;
+ /** reserved */
+ t_u8 reserved;
+} MLAN_PACK_END MrvlIEtypes_gwk_cipher_t;
+
+/** MrvlIEtypes_akmp_t */
+typedef MLAN_PACK_START struct _MrvlIEtypes_akmp_t {
+ /** Header */
+ MrvlIEtypesHeader_t header;
+ /** key management */
+ t_u16 key_mgmt;
+ /** key management operation */
+ t_u16 key_mgmt_operation;
+} MLAN_PACK_END MrvlIEtypes_akmp_t;
+
+/** MrvlIEtypes_passphrase_t */
+typedef MLAN_PACK_START struct _MrvlIEtypes_passphrase_t {
+ /** Header */
+ MrvlIEtypesHeader_t header;
+ /** passphrase */
+ t_u8 passphrase[1];
+} MLAN_PACK_END MrvlIEtypes_passphrase_t;
+
+/** MrvlIEtypes_rsn_replay_prot_t */
+typedef MLAN_PACK_START struct _MrvlIEtypes_rsn_replay_prot_t {
+ /** Header */
+ MrvlIEtypesHeader_t header;
+ /** rsn replay proection */
+ t_u8 rsn_replay_prot;
+} MLAN_PACK_END MrvlIEtypes_rsn_replay_prot_t;
+
+/** MrvlIEtypes_group_rekey_time_t */
+typedef MLAN_PACK_START struct _MrvlIEtypes_group_rekey_time_t {
+ /** Header */
+ MrvlIEtypesHeader_t header;
+ /** group key rekey time */
+ t_u32 gk_rekey_time;
+} MLAN_PACK_END MrvlIEtypes_group_rekey_time_t;
+
+/** MrvlIEtypes_wep_key_t */
+typedef MLAN_PACK_START struct _MrvlIEtypes_wep_key_t {
+ /** Header */
+ MrvlIEtypesHeader_t header;
+ /** key index */
+ t_u8 key_index;
+ /** is default */
+ t_u8 is_default;
+ /** key data */
+ t_u8 key[1];
+} MLAN_PACK_END MrvlIEtypes_wep_key_t;
+
+/** MrvlIEtypes_bss_status_t */
+typedef MLAN_PACK_START struct _MrvlIEtypes_bss_status_t {
+ /** Header */
+ MrvlIEtypesHeader_t header;
+ /** BSS status, READ only */
+ t_u16 bss_status;
+} MLAN_PACK_END MrvlIEtypes_bss_status_t;
+
+/** MrvlIEtypes_preamble_t */
+typedef MLAN_PACK_START struct _MrvlIEtypes_preamble_t {
+ /** Header */
+ MrvlIEtypesHeader_t header;
+ /** preamble type, READ only */
+ t_u8 preamble_type;
+} MLAN_PACK_END MrvlIEtypes_preamble_t;
+
+/** MrvlIEtypes_wmm_parameter_t */
+typedef MLAN_PACK_START struct _MrvlIEtypes_wmm_parameter_t {
+ /** Header */
+ MrvlIEtypesHeader_t header;
+ /** WMM parameter */
+ WmmParameter_t wmm_para;
+} MLAN_PACK_END MrvlIEtypes_wmm_parameter_t;
+
+/** SNMP_MIB_UAP_INDEX */
+typedef enum _SNMP_MIB_UAP_INDEX {
+ tkip_mic_failures = 0x0b,
+ ccmp_decrypt_errors = 0x0c,
+ wep_undecryptable_count = 0x0d,
+ wep_icv_error_count = 0x0e,
+ decrypt_failure_count = 0xf,
+ dot11_failed_count = 0x12,
+ dot11_retry_count = 0x13,
+ dot11_multi_retry_count = 0x14,
+ dot11_frame_dup_count = 0x15,
+ dot11_rts_success_count = 0x16,
+ dot11_rts_failure_count = 0x17,
+ dot11_ack_failure_count = 0x18,
+ dot11_rx_fragment_count = 0x19,
+ dot11_mcast_rx_frame_count = 0x1a,
+ dot11_fcs_error_count = 0x1b,
+ dot11_tx_frame_count = 0x1c,
+ dot11_rsna_tkip_cm_invoked = 0x1d,
+ dot11_rsna_4way_hshk_failures = 0x1e,
+ dot11_mcast_tx_count = 0x1f,
+} SNMP_MIB_UAP_INDEX;
+
+/** MrvlIEtypes_snmp_oid_t */
+typedef MLAN_PACK_START struct _MrvlIEtypes_snmp_oid_t {
+ /** Header */
+ MrvlIEtypesHeader_t header;
+ /** data */
+ t_u32 data;
+} MLAN_PACK_END MrvlIEtypes_snmp_oid_t;
+
+/** HostCmd_SYS_CONFIG */
+typedef MLAN_PACK_START struct _HostCmd_DS_SYS_CONFIG {
+ /** CMD Action GET/SET*/
+ t_u16 action;
+ /** Tlv buffer */
+ t_u8 tlv_buffer[1];
+} MLAN_PACK_END HostCmd_DS_SYS_CONFIG;
+
+/** HostCmd_SYS_CONFIG */
+typedef MLAN_PACK_START struct _HostCmd_DS_SYS_INFO {
+ /** sys info */
+ t_u8 sys_info[64];
+} MLAN_PACK_END HostCmd_DS_SYS_INFO;
+
+/** HostCmd_DS_STA_DEAUTH */
+typedef MLAN_PACK_START struct _HostCmd_DS_STA_DEAUTH {
+ /** mac address */
+ t_u8 mac[MLAN_MAC_ADDR_LENGTH];
+ /** reason code */
+ t_u16 reason;
+} MLAN_PACK_END HostCmd_DS_STA_DEAUTH;
+
+/** HostCmd_DS_REPORT_MIC */
+typedef MLAN_PACK_START struct _HostCmd_DS_REPORT_MIC {
+ /** mac address */
+ t_u8 mac[MLAN_MAC_ADDR_LENGTH];
+} MLAN_PACK_END HostCmd_DS_REPORT_MIC;
+
+/** HostCmd_UAP_OPER_CTRL */
+typedef MLAN_PACK_START struct _HostCmd_DS_UAP_OPER_CTRL {
+ /** CMD Action GET/SET*/
+ t_u16 action;
+ /** control*/
+ t_u16 ctrl;
+ /**channel operation*/
+ t_u16 chan_opt;
+ /**channel band tlv*/
+ MrvlIEtypes_channel_band_t channel_band;
+} MLAN_PACK_END HostCmd_DS_UAP_OPER_CTRL;
+
+/** Host Command id: POWER_MGMT */
+#define HOST_CMD_POWER_MGMT_EXT 0x00ef
+/** TLV type: AP Sleep param */
+#define TLV_TYPE_AP_SLEEP_PARAM (PROPRIETARY_TLV_BASE_ID + 0x6a) /* 0x016a */
+/** TLV type: AP Inactivity Sleep param */
+#define TLV_TYPE_AP_INACT_SLEEP_PARAM \
+ (PROPRIETARY_TLV_BASE_ID + 0x6b) /* 0x016b */
+
+/** MrvlIEtypes_sleep_param_t */
+typedef MLAN_PACK_START struct _MrvlIEtypes_sleep_param_t {
+ /** Header */
+ MrvlIEtypesHeader_t header;
+ /** control bitmap */
+ t_u32 ctrl_bitmap;
+ /** min_sleep */
+ t_u32 min_sleep;
+ /** max_sleep */
+ t_u32 max_sleep;
+} MLAN_PACK_END MrvlIEtypes_sleep_param_t;
+
+/** MrvlIEtypes_inact_sleep_param_t */
+typedef MLAN_PACK_START struct _MrvlIEtypes_inact_sleep_param_t {
+ /** Header */
+ MrvlIEtypesHeader_t header;
+ /** inactivity timeout */
+ t_u32 inactivity_to;
+
+ /** min_awake */
+ t_u32 min_awake;
+ /** max_awake */
+ t_u32 max_awake;
+} MLAN_PACK_END MrvlIEtypes_inact_sleep_param_t;
+
+/** HostCmd_DS_POWER_MGMT */
+typedef MLAN_PACK_START struct _HostCmd_DS_POWER_MGMT_EXT {
+ /** CMD Action Get/Set*/
+ t_u16 action;
+ /** power mode */
+ t_u16 power_mode;
+} MLAN_PACK_END HostCmd_DS_POWER_MGMT_EXT;
+
+/** MrvlIEtypes_ps_sta_ageout_t */
+typedef MLAN_PACK_START struct _MrvlIEtypes_ps_sta_ageout_t {
+ /** Header */
+ MrvlIEtypesHeader_t header;
+ /** station age out timer */
+ t_u32 ps_sta_ageout_timer;
+} MLAN_PACK_END MrvlIEtypes_ps_sta_ageout_t;
+
+/** MrvlIEtypes_sta_info_t */
+typedef MLAN_PACK_START struct _MrvlIEtypes_sta_info_t {
+ /** Header */
+ MrvlIEtypesHeader_t header;
+ /** STA MAC address */
+ t_u8 mac_address[MLAN_MAC_ADDR_LENGTH];
+ /** Power Mgmt status */
+ t_u8 power_mgmt_status;
+ /** RSSI */
+ t_s8 rssi;
+ /** ie_buf */
+ t_u8 ie_buf[];
+} MLAN_PACK_END MrvlIEtypes_sta_info_t;
+
+/** HostCmd_DS_STA_LIST */
+typedef MLAN_PACK_START struct _HostCmd_DS_STA_LIST {
+ /** Number of STAs */
+ t_u16 sta_count;
+ /* MrvlIEtypes_sta_info_t sta_info[]; */
+ t_u8 tlv_buf[];
+} MLAN_PACK_END HostCmd_DS_STA_LIST;
+
+/** TLV ID : WAPI Information */
+#define TLV_TYPE_AP_WAPI_INFO (PROPRIETARY_TLV_BASE_ID + 0x67) /* 0x0167 */
+
+/** MrvlIEtypes_sta_info_t */
+typedef MLAN_PACK_START struct _MrvlIEtypes_wapi_info_t {
+ /** Header */
+ MrvlIEtypesHeader_t header;
+ /** Multicast PN */
+ t_u8 multicast_PN[16];
+} MLAN_PACK_END MrvlIEtypes_wapi_info_t;
+#endif /* UAP_SUPPORT */
+
+/** HostCmd_DS_TX_RX_HISTOGRAM */
+typedef MLAN_PACK_START struct _HostCmd_DS_TX_RX_HISTOGRAM {
+ /** Enable or disable */
+ t_u8 enable;
+ /** Choose to get TX, RX or both */
+ t_u16 action;
+} MLAN_PACK_END HostCmd_DS_TX_RX_HISTOGRAM;
+
+/** TLV buffer : 2040 coex config */
+typedef MLAN_PACK_START struct _MrvlIEtypes_2040_coex_enable_t {
+ /** Header */
+ MrvlIEtypesHeader_t header;
+ /** Enable */
+ t_u8 enable_2040coex;
+} MLAN_PACK_END MrvlIEtypes_2040_coex_enable_t;
+
+/**BT coexit scan time setting*/
+typedef MLAN_PACK_START struct _MrvlIEtypes_BtCoexScanTime_t {
+ /** Header */
+ MrvlIEtypesHeader_t header;
+ /**coex scan state 0: disable 1: enable*/
+ t_u8 coex_scan;
+ /**reserved*/
+ t_u8 reserved;
+ /**min scan time*/
+ t_u16 min_scan_time;
+ /**max scan time*/
+ t_u16 max_scan_time;
+} MLAN_PACK_END MrvlIEtypes_BtCoexScanTime_t;
+
+/**BT coexit aggr win size */
+typedef MLAN_PACK_START struct _MrvlIETypes_BtCoexAggrWinSize_t {
+ /** Header */
+ MrvlIEtypesHeader_t header;
+ /**winsize 0: restore default winsize, 1: use below winsize */
+ t_u8 coex_win_size;
+ /**tx win size*/
+ t_u8 tx_win_size;
+ /**rx win size*/
+ t_u8 rx_win_size;
+ /**reserved*/
+ t_u8 reserved;
+} MLAN_PACK_END MrvlIETypes_BtCoexAggrWinSize_t;
+
+/** MrvlIEtypes_eapol_pkt_t */
+typedef MLAN_PACK_START struct _MrvlIEtypes_eapol_pkt_t {
+ /** Header */
+ MrvlIEtypesHeader_t header;
+ /** eapol pkt buf */
+ t_u8 pkt_buf[];
+} MLAN_PACK_END MrvlIEtypes_eapol_pkt_t;
+
+/** HostCmd_DS_EAPOL_PKT */
+typedef MLAN_PACK_START struct _HostCmd_DS_EAPOL_PKT {
+ /** Action */
+ t_u16 action;
+ /** TLV buffer */
+ MrvlIEtypes_eapol_pkt_t tlv_eapol;
+} MLAN_PACK_END HostCmd_DS_EAPOL_PKT;
+
+/** HostCmd_DS_OXYGEN_MIMO_SWITCH */
+typedef MLAN_PACK_START struct _HostCmd_DS_MIMO_SWITCH {
+ /** Tx path antanne mode */
+ t_u8 txpath_antmode;
+ /** Rx path antanne mode */
+ t_u8 rxpath_antmode;
+} MLAN_PACK_END HostCmd_DS_MIMO_SWITCH;
+
+#ifdef RX_PACKET_COALESCE
+typedef MLAN_PACK_START struct _HostCmd_DS_RX_PKT_COAL_CFG {
+ /** Action */
+ t_u16 action;
+ /** Packet threshold */
+ t_u32 packet_threshold;
+ /** Timeout */
+ t_u16 delay;
+} MLAN_PACK_END HostCmd_DS_RX_PKT_COAL_CFG;
+#endif
+
+/** HostCmd_DS_DYN_BW */
+typedef MLAN_PACK_START struct _HostCmd_DS_DYN_BW {
+ /** Action */
+ t_u16 action;
+ /** Dynamic bandwidth */
+ t_u16 dyn_bw;
+} MLAN_PACK_END HostCmd_DS_DYN_BW;
+
+/** Host Command ID : Packet aggregation CTRL */
+#define HostCmd_CMD_PACKET_AGGR_CTRL 0x0251
+
+/** HostCmd_DS_PACKET_AGGR_CTRL */
+typedef MLAN_PACK_START struct _HostCmd_DS_PACKET_AGGR_AGGR_CTRL {
+ /** ACT_GET/ACT_SET */
+ t_u16 action;
+ /** enable aggregation, BIT(0) TX, BIT(1)RX */
+ t_u16 aggr_enable;
+ /** Tx aggregation alignment */
+ t_u16 tx_aggr_max_size;
+ /** Tx aggregation max packet number */
+ t_u16 tx_aggr_max_num;
+ /** Tx aggregation alignment */
+ t_u16 tx_aggr_align;
+} MLAN_PACK_END HostCmd_DS_PACKET_AGGR_CTRL;
+
+#ifdef USB
+/** Host Command ID : Packet aggregation over host interface */
+#define HostCmd_CMD_PACKET_AGGR_OVER_HOST_INTERFACE 0x0117
+
+/** TLV ID : USB Aggregation parameters */
+#define MRVL_USB_AGGR_PARAM_TLV_ID \
+ (PROPRIETARY_TLV_BASE_ID + 0xB1) /* 0x1B1 \
+ */
+
+/** TLV size : USB Aggregation parameters, except header */
+#define MRVL_USB_AGGR_PARAM_TLV_LEN (14)
+
+/** VHT Operations IE */
+typedef MLAN_PACK_START struct _MrvlIETypes_USBAggrParam_t {
+ /** Header */
+ MrvlIEtypesHeader_t header;
+
+ /** Enable */
+ t_u16 enable;
+ /** Rx aggregation mode */
+ t_u16 rx_aggr_mode;
+ /** Rx aggregation alignment */
+ t_u16 rx_aggr_align;
+ /** Rx aggregation max packet/size */
+ t_u16 rx_aggr_max;
+ /** Rx aggrgation timeout, in microseconds */
+ t_u16 rx_aggr_tmo;
+ /** Tx aggregation mode */
+ t_u16 tx_aggr_mode;
+ /** Tx aggregation alignment */
+ t_u16 tx_aggr_align;
+} MLAN_PACK_END MrvlIETypes_USBAggrParam_t;
+
+/** HostCmd_DS_PACKET_AGGR_OVER_HOST_INTERFACE */
+typedef MLAN_PACK_START struct _HostCmd_DS_PACKET_AGGR_OVER_HOST_INTERFACE {
+ /** ACT_GET/ACT_SET */
+ t_u16 action;
+ /**
+ * Host interface aggregation control TLV(s) to be sent in the firmware
+ * command
+ *
+ * TLV_USB_AGGR_PARAM, MrvlIETypes_USBAggrParam_t
+ */
+ t_u8 tlv_buf[1];
+} MLAN_PACK_END HostCmd_DS_PACKET_AGGR_OVER_HOST_INTERFACE;
+#endif /* USB */
+
+/** HostCmd_CONFIG_LOW_PWR_MODE */
+typedef MLAN_PACK_START struct _HostCmd_CONFIG_LOW_PWR_MODE {
+ /** Enable LPM */
+ t_u8 enable;
+} MLAN_PACK_END HostCmd_CONFIG_LOW_PWR_MODE;
+
+/** HostCmd_CMD_GET_TSF */
+typedef MLAN_PACK_START struct _HostCmd_DS_TSF {
+ /** tsf value*/
+ t_u64 tsf;
+} MLAN_PACK_END HostCmd_DS_TSF;
+/* WLAN_GET_TSF*/
+
+typedef struct _HostCmd_DS_DFS_REPEATER_MODE {
+ /** Set or Get */
+ t_u16 action;
+ /** 1 on or 0 off */
+ t_u16 mode;
+} HostCmd_DS_DFS_REPEATER_MODE;
+
+/** HostCmd_DS_BOOT_SLEEP */
+typedef MLAN_PACK_START struct _HostCmd_DS_BOOT_SLEEP {
+ /** Set or Get */
+ t_u16 action;
+ /** 1 on or 0 off */
+ t_u16 enable;
+} MLAN_PACK_END HostCmd_DS_BOOT_SLEEP;
+
+/**
+ * @brief 802.11h Local Power Constraint NXP extended TLV
+ */
+typedef MLAN_PACK_START struct {
+ MrvlIEtypesHeader_t header; /**< NXP TLV header: ID/Len */
+ t_u8 chan; /**< Channel local constraint applies to */
+
+ /** Power constraint included in beacons
+ * and used by fw to offset 11d info
+ */
+ t_u8 constraint;
+
+} MLAN_PACK_END MrvlIEtypes_LocalPowerConstraint_t;
+
+/*
+ *
+ * Data structures for driver/firmware command processing
+ *
+ */
+
+/** TPC Info structure sent in CMD_802_11_TPC_INFO command to firmware */
+typedef MLAN_PACK_START struct {
+ /**< Local constraint */
+ MrvlIEtypes_LocalPowerConstraint_t local_constraint;
+ /**< Power Capability */
+ MrvlIEtypes_PowerCapability_t power_cap;
+
+} MLAN_PACK_END HostCmd_DS_802_11_TPC_INFO;
+
+/** TPC Request structure sent in CMD_802_11_TPC_ADAPT_REQ
+ * command to firmware
+ */
+typedef MLAN_PACK_START struct {
+ t_u8 dest_mac[MLAN_MAC_ADDR_LENGTH]; /**< Destination STA address */
+ t_u16 timeout; /**< Response timeout in ms */
+ t_u8 rate_index; /**< IEEE Rate index to send request */
+
+} MLAN_PACK_END HostCmd_TpcRequest;
+
+/** TPC Response structure received from the
+ * CMD_802_11_TPC_ADAPT_REQ command
+ */
+typedef MLAN_PACK_START struct {
+ t_u8 tpc_ret_code; /**< Firmware command result status code */
+ t_s8 tx_power; /**< Reported TX Power from the TPC Report element */
+ t_s8 link_margin; /**< Reported link margin from the TPC Report element
+ */
+ t_s8 rssi; /**< RSSI of the received TPC Report frame */
+
+} MLAN_PACK_END HostCmd_TpcResponse;
+
+/** CMD_802_11_TPC_ADAPT_REQ substruct.
+ * Union of the TPC request and response
+ */
+typedef MLAN_PACK_START union {
+ HostCmd_TpcRequest req; /**< Request struct sent to firmware */
+ HostCmd_TpcResponse resp; /**< Response struct received from firmware */
+
+} MLAN_PACK_END HostCmd_DS_802_11_TPC_ADAPT_REQ;
+
+/** CMD_802_11_CHAN_SW_ANN firmware command substructure */
+typedef MLAN_PACK_START struct {
+ t_u8 switch_mode; /**< Set to 1 for a quiet switch request, no STA tx */
+ t_u8 new_chan; /**< Requested new channel */
+ t_u8 switch_count; /**< Number of TBTTs until the switch is to occur */
+} MLAN_PACK_END HostCmd_DS_802_11_CHAN_SW_ANN;
+
+/**
+ * @brief Enumeration of measurement types, including max supported
+ * enum for 11h/11k
+ */
+typedef MLAN_PACK_START enum _MeasType_t {
+ WLAN_MEAS_BASIC = 0, /**< 11h: Basic */
+ WLAN_MEAS_NUM_TYPES, /**< Number of enumerated measurements */
+ WLAN_MEAS_11H_MAX_TYPE = WLAN_MEAS_BASIC, /**< Max 11h measurement */
+
+} MLAN_PACK_END MeasType_t;
+
+/**
+ * @brief Mode octet of the measurement request element (7.3.2.21)
+ */
+typedef MLAN_PACK_START struct {
+#ifdef BIG_ENDIAN_SUPPORT
+ /**< Reserved */
+ t_u8 rsvd5_7 : 3;
+ /**< 11k: duration spec. for meas. is mandatory */
+ t_u8 duration_mandatory : 1;
+ /**< 11h: en/disable report rcpt. of spec. type */
+ t_u8 report : 1;
+ /**< 11h: en/disable requests of specified type */
+ t_u8 request : 1;
+ /**< 11h: enable report/request bits */
+ t_u8 enable : 1;
+ /**< 11k: series or parallel with previous meas */
+ t_u8 parallel : 1;
+#else
+ /**< 11k: series or parallel with previous meas */
+ t_u8 parallel : 1;
+ /**< 11h: enable report/request bits */
+ t_u8 enable : 1;
+ /**< 11h: en/disable requests of specified type */
+ t_u8 request : 1;
+ /**< 11h: en/disable report rcpt. of spec. type */
+ t_u8 report : 1;
+ /**< 11k: duration spec. for meas. is mandatory */
+ t_u8 duration_mandatory : 1;
+ /**< Reserved */
+ t_u8 rsvd5_7 : 3;
+#endif /* BIG_ENDIAN_SUPPORT */
+
+} MLAN_PACK_END MeasReqMode_t;
+
+/**
+ * @brief Common measurement request structure (7.3.2.21.1 to 7.3.2.21.3)
+ */
+typedef MLAN_PACK_START struct {
+ t_u8 channel; /**< Channel to measure */
+ t_u64 start_time; /**< TSF Start time of measurement (0 for immediate)
+ */
+ t_u16 duration; /**< TU duration of the measurement */
+
+} MLAN_PACK_END MeasReqCommonFormat_t;
+
+/**
+ * @brief Basic measurement request structure (7.3.2.21.1)
+ */
+typedef MeasReqCommonFormat_t MeasReqBasic_t;
+
+/**
+ * @brief CCA measurement request structure (7.3.2.21.2)
+ */
+typedef MeasReqCommonFormat_t MeasReqCCA_t;
+
+/**
+ * @brief RPI measurement request structure (7.3.2.21.3)
+ */
+typedef MeasReqCommonFormat_t MeasReqRPI_t;
+
+/**
+ * @brief Union of the availble measurement request types. Passed in the
+ * driver/firmware interface.
+ */
+typedef union {
+ MeasReqBasic_t basic; /**< Basic measurement request */
+ MeasReqCCA_t cca; /**< CCA measurement request */
+ MeasReqRPI_t rpi; /**< RPI measurement request */
+
+} MeasRequest_t;
+
+/**
+ * @brief Mode octet of the measurement report element (7.3.2.22)
+ */
+typedef MLAN_PACK_START struct {
+#ifdef BIG_ENDIAN_SUPPORT
+ t_u8 rsvd3_7 : 5; /**< Reserved */
+ t_u8 refused : 1; /**< Measurement refused */
+ t_u8 incapable : 1; /**< Incapable of performing measurement */
+ t_u8 late : 1; /**< Start TSF time missed for measurement */
+#else
+ t_u8 late : 1; /**< Start TSF time missed for measurement */
+ t_u8 incapable : 1; /**< Incapable of performing measurement */
+ t_u8 refused : 1; /**< Measurement refused */
+ t_u8 rsvd3_7 : 5; /**< Reserved */
+#endif /* BIG_ENDIAN_SUPPORT */
+
+} MLAN_PACK_END MeasRptMode_t;
+
+/**
+ * @brief Basic measurement report (7.3.2.22.1)
+ */
+typedef MLAN_PACK_START struct {
+ t_u8 channel; /**< Channel to measured */
+ t_u64 start_time; /**< Start time (TSF) of measurement */
+ t_u16 duration; /**< Duration of measurement in TUs */
+ MeasRptBasicMap_t map; /**< Basic measurement report */
+
+} MLAN_PACK_END MeasRptBasic_t;
+
+/**
+ * @brief CCA measurement report (7.3.2.22.2)
+ */
+typedef MLAN_PACK_START struct {
+ t_u8 channel; /**< Channel to measured */
+ t_u64 start_time; /**< Start time (TSF) of measurement */
+ t_u16 duration; /**< Duration of measurement in TUs */
+ t_u8 busy_fraction; /**< Fractional duration CCA indicated chan busy */
+
+} MLAN_PACK_END MeasRptCCA_t;
+
+/**
+ * @brief RPI measurement report (7.3.2.22.3)
+ */
+typedef MLAN_PACK_START struct {
+ t_u8 channel; /**< Channel to measured */
+ t_u64 start_time; /**< Start time (TSF) of measurement */
+ t_u16 duration; /**< Duration of measurement in TUs */
+ t_u8 density[8]; /**< RPI Density histogram report */
+
+} MLAN_PACK_END MeasRptRPI_t;
+
+/**
+ * @brief Union of the availble measurement report types. Passed in the
+ * driver/firmware interface.
+ */
+typedef union {
+ MeasRptBasic_t basic; /**< Basic measurement report */
+ MeasRptCCA_t cca; /**< CCA measurement report */
+ MeasRptRPI_t rpi; /**< RPI measurement report */
+
+} MeasReport_t;
+
+/**
+ * @brief Structure passed to firmware to perform a measurement
+ */
+typedef MLAN_PACK_START struct {
+ t_u8 mac_addr[MLAN_MAC_ADDR_LENGTH]; /**< Reporting STA address */
+ t_u8 dialog_token; /**< Measurement dialog toke */
+ MeasReqMode_t req_mode; /**< Report mode */
+ MeasType_t meas_type; /**< Measurement type */
+ MeasRequest_t req; /**< Measurement request data */
+
+} MLAN_PACK_END HostCmd_DS_MEASUREMENT_REQUEST,
+ *pHostCmd_DS_MEASUREMENT_REQUEST;
+
+/**
+ * @brief Structure passed back from firmware with a measurement report,
+ * also can be to send a measurement report to another STA
+ */
+typedef MLAN_PACK_START struct {
+ t_u8 mac_addr[MLAN_MAC_ADDR_LENGTH]; /**< Reporting STA address */
+ t_u8 dialog_token; /**< Measurement dialog token */
+ MeasRptMode_t rpt_mode; /**< Report mode */
+ MeasType_t meas_type; /**< Measurement type */
+ MeasReport_t rpt; /**< Measurement report data */
+
+} MLAN_PACK_END HostCmd_DS_MEASUREMENT_REPORT, *pHostCmd_DS_MEASUREMENT_REPORT;
+
+typedef MLAN_PACK_START struct {
+ t_u16 startFreq;
+ Band_Config_t bandcfg;
+ t_u8 chanNum;
+
+} MLAN_PACK_END MrvlChannelDesc_t;
+
+#ifdef OPCHAN
+typedef MLAN_PACK_START struct {
+ MrvlIEtypesHeader_t header; /**< Header */
+
+ MrvlChannelDesc_t chanDesc;
+
+ t_u16 controlFlags;
+ t_u16 reserved;
+
+ t_u8 actPower;
+ t_u8 mdMinPower;
+ t_u8 mdMaxPower;
+ t_u8 mdPower;
+
+} MLAN_PACK_END MrvlIEtypes_ChanControlDesc_t;
+
+typedef MLAN_PACK_START struct {
+ MrvlIEtypesHeader_t header; /**< Header */
+
+ t_u16 chanGroupBitmap;
+ ChanScanMode_t scanMode;
+ t_u8 numChan;
+
+ MrvlChannelDesc_t chanDesc[50];
+
+} MLAN_PACK_END MrvlIEtypes_ChanGroupControl_t;
+
+typedef MLAN_PACK_START struct {
+ t_u16 action; /**< CMD Action Get/Set*/
+
+ t_u8 tlv_buffer[1];
+
+} MLAN_PACK_END HostCmd_DS_OPCHAN_CONFIG;
+
+typedef MLAN_PACK_START struct {
+ t_u16 action; /**< CMD Action Get/Set*/
+
+ t_u8 tlv_buffer[1];
+
+} MLAN_PACK_END HostCmd_DS_OPCHAN_CHANGROUP_CONFIG;
+
+#define HostCmd_CMD_OPCHAN_CONFIG 0x00f8
+#define HostCmd_CMD_OPCHAN_CHANGROUP_CONFIG 0x00f9
+#endif
+
+typedef MLAN_PACK_START struct {
+ MrvlIEtypesHeader_t Header; /**< Header */
+
+ MeasRptBasicMap_t map; /**< IEEE 802.11h basic meas report */
+} MLAN_PACK_END MrvlIEtypes_ChanRpt11hBasic_t;
+
+/* MrvlIEtypes_DfsW53Cfg_t*/
+typedef MLAN_PACK_START struct {
+ /* header */
+ MrvlIEtypesHeader_t Header;
+ /** df53cfg vlue*/
+ t_u8 dfs53cfg;
+} MLAN_PACK_END MrvlIEtypes_DfsW53Cfg_t;
+
+typedef MLAN_PACK_START struct {
+ MrvlChannelDesc_t chan_desc; /**< Channel band, number */
+ t_u32 millisec_dwell_time; /**< Channel dwell time in milliseconds */
+} MLAN_PACK_END HostCmd_DS_CHAN_RPT_REQ;
+
+typedef MLAN_PACK_START struct {
+ t_u32 cmd_result; /**< Rpt request command result (0 == SUCCESS) */
+ t_u64 start_tsf; /**< TSF Measurement started */
+ t_u32 duration; /**< Duration of measurement in microsecs */
+ t_u8 tlv_buffer[1]; /**< TLV Buffer */
+} MLAN_PACK_END HostCmd_DS_CHAN_RPT_RSP;
+
+/** statistics threshold */
+typedef MLAN_PACK_START struct {
+ /** Header */
+ MrvlIEtypesHeader_t header;
+ /** value */
+ t_u8 value;
+ /** reporting frequency */
+ t_u8 frequency;
+} MLAN_PACK_END MrvlIEtypes_BeaconHighRssiThreshold_t,
+ MrvlIEtypes_BeaconLowRssiThreshold_t,
+ MrvlIEtypes_BeaconHighSnrThreshold_t,
+ MrvlIEtypes_BeaconLowSnrThreshold_t, MrvlIEtypes_FailureCount_t,
+ MrvlIEtypes_DataLowRssiThreshold_t, MrvlIEtypes_DataHighRssiThreshold_t,
+ MrvlIEtypes_DataLowSnrThreshold_t, MrvlIEtypes_DataHighSnrThreshold_t,
+ MrvlIETypes_PreBeaconMissed_t, MrvlIEtypes_BeaconsMissed_t;
+
+/** statistics threshold for LinkQuality */
+typedef MLAN_PACK_START struct {
+ /** Header */
+ MrvlIEtypesHeader_t header;
+ /** Link SNR threshold (dB) */
+ t_u16 link_snr;
+ /** Link SNR frequency */
+ t_u16 link_snr_freq;
+ /* Second minimum rate value as per the rate table below */
+ t_u16 link_rate;
+ /* Second minimum rate frequency */
+ t_u16 link_rate_freq;
+ /* Tx latency value (us) */
+ t_u16 link_tx_latency;
+ /* Tx latency frequency */
+ t_u16 link_tx_lantency_freq;
+} MLAN_PACK_END MrvlIEtypes_LinkQualityThreshold_t;
+
+#ifdef PCIE
+/** PCIE dual descriptor for data/event */
+typedef MLAN_PACK_START struct _dual_desc_buf {
+ /** buf size */
+ t_u16 len;
+ /** buffer descriptor flags */
+ t_u16 flags;
+ /** pkt size */
+ t_u16 pkt_size;
+ /** reserved */
+ t_u16 reserved;
+ /** Physical address of the buffer */
+ t_u64 paddr;
+} MLAN_PACK_END adma_dual_desc_buf, *padma_dual_desc_buf;
+
+#if defined(PCIE8997) || defined(PCIE8897)
+/** PCIE ring buffer description for DATA */
+typedef MLAN_PACK_START struct _mlan_pcie_data_buf {
+ /** Buffer descriptor flags */
+ t_u16 flags;
+ /** Offset of fragment/pkt to start of ip header */
+ t_u16 offset;
+ /** Fragment length of the buffer */
+ t_u16 frag_len;
+ /** Length of the buffer */
+ t_u16 len;
+ /** Physical address of the buffer */
+ t_u64 paddr;
+ /** Reserved */
+ t_u32 reserved;
+} MLAN_PACK_END mlan_pcie_data_buf, *pmlan_pcie_data_buf;
+
+/** PCIE ring buffer description for EVENT */
+typedef MLAN_PACK_START struct _mlan_pcie_evt_buf {
+ /** Physical address of the buffer */
+ t_u64 paddr;
+ /** Length of the buffer */
+ t_u16 len;
+ /** Buffer descriptor flags */
+ t_u16 flags;
+} MLAN_PACK_END mlan_pcie_evt_buf, *pmlan_pcie_evt_buf;
+
+/** PCIE host buffer configuration */
+typedef MLAN_PACK_START struct _HostCmd_DS_PCIE_HOST_BUF_DETAILS {
+ /** TX buffer descriptor ring address */
+ t_u32 txbd_addr_lo;
+ t_u32 txbd_addr_hi;
+ /** TX buffer descriptor ring count */
+ t_u32 txbd_count;
+
+ /** RX buffer descriptor ring address */
+ t_u32 rxbd_addr_lo;
+ t_u32 rxbd_addr_hi;
+ /** RX buffer descriptor ring count */
+ t_u32 rxbd_count;
+
+ /** Event buffer descriptor ring address */
+ t_u32 evtbd_addr_lo;
+ t_u32 evtbd_addr_hi;
+ /** Event buffer descriptor ring count */
+ t_u32 evtbd_count;
+} HostCmd_DS_PCIE_HOST_BUF_DETAILS;
+#endif
+#endif
+
+typedef MLAN_PACK_START struct _HostCmd_DS_SENSOR_TEMP {
+ t_u32 temperature;
+} MLAN_PACK_END HostCmd_DS_SENSOR_TEMP;
+
+#ifdef STA_SUPPORT
+typedef MLAN_PACK_START struct _HostCmd_DS_STA_CONFIGURE {
+ /** Action Set or get */
+ t_u16 action;
+ /** Tlv buffer */
+ t_u8 tlv_buffer[];
+ /**MrvlIEtypes_channel_band_t band_channel; */
+} MLAN_PACK_END HostCmd_DS_STA_CONFIGURE;
+#endif
+
+/** HostCmd_DS_AUTO_TX structure */
+typedef MLAN_PACK_START struct _HostCmd_DS_AUTO_TX {
+ /** Action Set or get */
+ t_u16 action;
+ /** Tlv buffer */
+ t_u8 tlv_buffer[];
+} MLAN_PACK_END HostCmd_DS_AUTO_TX;
+
+#define OID_CLOUD_KEEP_ALIVE 0
+#define EVENT_CLOUD_KEEP_ALIVE_RETRY_FAIL 133
+/** TLV for cloud keep alive control info */
+#define TLV_TYPE_CLOUD_KEEP_ALIVE \
+ (PROPRIETARY_TLV_BASE_ID + 0x102) /* 0x0100 + 258 */
+typedef MLAN_PACK_START struct _MrvlIEtypes_Cloud_Keep_Alive_t {
+ /** Header */
+ MrvlIEtypesHeader_t header;
+ /** ID for cloud keep alive */
+ t_u8 keep_alive_id;
+ /** Enable/disable for this ID */
+ t_u8 enable;
+ /** TLV buffer */
+ t_u8 tlv[];
+} MLAN_PACK_END MrvlIEtypes_Cloud_Keep_Alive_t;
+
+/** TLV for cloud keep alive control info */
+#define TLV_TYPE_KEEP_ALIVE_CTRL \
+ (PROPRIETARY_TLV_BASE_ID + 0x103) /* 0x0100 + 259 */
+typedef MLAN_PACK_START struct _MrvlIEtypes_Keep_Alive_Ctrl_t {
+ /** Header */
+ MrvlIEtypesHeader_t header;
+ /** period to send keep alive packet */
+ t_u32 snd_interval;
+ /** period to send retry packet */
+ t_u16 retry_interval;
+ /** count to send retry packet */
+ t_u16 retry_count;
+} MLAN_PACK_END MrvlIEtypes_Keep_Alive_Ctrl_t;
+
+/** TLV for cloud keep alive packet */
+#define TLV_TYPE_KEEP_ALIVE_PKT \
+ (PROPRIETARY_TLV_BASE_ID + 0x104) /* 0x0100 + 260 */
+typedef MLAN_PACK_START struct _MrvlIEtypes_Keep_Alive_Pkt_t {
+ /** Header */
+ MrvlIEtypesHeader_t header;
+ /** Ethernet Header */
+ Eth803Hdr_t eth_header;
+ /** packet buffer*/
+ t_u8 ip_packet[];
+} MLAN_PACK_END MrvlIEtypes_Keep_Alive_Pkt_t;
+
+/** TLV to indicate firmware only keep probe response while scan */
+#define TLV_TYPE_ONLYPROBERESP (PROPRIETARY_TLV_BASE_ID + 0xE9) /* 0x01E9 */
+typedef MLAN_PACK_START struct _MrvlIEtypes_OnlyProberesp_t {
+ /** Header */
+ MrvlIEtypesHeader_t header;
+ /** only keep probe response */
+ t_u8 proberesp_only;
+} MLAN_PACK_END MrvlIEtypes_OnlyProberesp_t;
+
+#if defined(DRV_EMBEDDED_AUTHENTICATOR) || defined(DRV_EMBEDDED_SUPPLICANT)
+#define HostCmd_CMD_CRYPTO 0x025e
+
+#define HostCmd_CMD_CRYPTO_SUBCMD_PRF_HMAC_SHA1 (0x1)
+#define HostCmd_CMD_CRYPTO_SUBCMD_HMAC_SHA1 (0x2)
+#define HostCmd_CMD_CRYPTO_SUBCMD_HMAC_SHA256 (0x3)
+#define HostCmd_CMD_CRYPTO_SUBCMD_SHA256 (0x4)
+#define HostCmd_CMD_CRYPTO_SUBCMD_RIJNDAEL (0x5)
+#define HostCmd_CMD_CRYPTO_SUBCMD_RC4 (0x6)
+#define HostCmd_CMD_CRYPTO_SUBCMD_MD5 (0x7)
+#define HostCmd_CMD_CRYPTO_SUBCMD_MRVL_F (0x8)
+#define HostCmd_CMD_CRYPTO_SUBCMD_SHA256_KDF (0x9)
+
+#define TLV_TYPE_CRYPTO_KEY (PROPRIETARY_TLV_BASE_ID + 308)
+#define TLV_TYPE_CRYPTO_KEY_IV (PROPRIETARY_TLV_BASE_ID + 309)
+#define TLV_TYPE_CRYPTO_KEY_PREFIX (PROPRIETARY_TLV_BASE_ID + 310)
+#define TLV_TYPE_CRYPTO_KEY_DATA_BLK (PROPRIETARY_TLV_BASE_ID + 311)
+
+/** MrvlIEParamSet_t */
+typedef MLAN_PACK_START struct {
+ /** Type */
+ t_u16 Type;
+ /** Length */
+ t_u16 Length;
+} MLAN_PACK_END MrvlIEParamSet_t;
+
+/** HostCmd_DS_CRYPTO */
+typedef MLAN_PACK_START struct _HostCmd_DS_CRYPTO {
+ /** action */
+ t_u16 action;
+ /** subCmdCode */
+ t_u8 subCmdCode;
+ /** subCmd start */
+ t_u8 subCmd[];
+} MLAN_PACK_END HostCmd_DS_CRYPTO;
+
+/** subcmd_prf_hmac_sha1 used by prf_hmac_sha1, md5 and sha256_kdf */
+typedef MLAN_PACK_START struct _subcmd_prf_hmac_sha1 {
+ /** output_len */
+ t_u16 output_len;
+ /** tlv start */
+ t_u8 tlv[];
+} MLAN_PACK_END subcmd_prf_hmac_sha1_t, subcmd_md5_t, subcmd_sha256_kdf_t;
+
+/** subcmd_hmac_sha1 used by hmac_sha1, hmac_sha256, sha256 */
+typedef MLAN_PACK_START struct _subcmd_hmac_sha1 {
+ /** output_len */
+ t_u16 output_len;
+ /** number of data blocks */
+ t_u16 data_blks_nr;
+ /** tlv start */
+ t_u8 tlv[];
+} MLAN_PACK_END subcmd_hmac_sha1_t, subcmd_hmac_sha256_t, subcmd_sha256_t;
+
+/** subcmd_rijndael, used by rijndael */
+typedef MLAN_PACK_START struct _subcmd_rijndael {
+ /** output_len */
+ t_u16 output_len;
+ /** sub action code */
+ t_u8 sub_action_code;
+ /** tlv start */
+ t_u8 tlv[];
+} MLAN_PACK_END subcmd_rijndael_t;
+
+/** subcmd_rc4, used by rc4 */
+typedef MLAN_PACK_START struct _subcmd_rc4 {
+ /** output_len */
+ t_u16 output_len;
+ /** skip bytes */
+ t_u16 skip_bytes;
+ /** tlv start */
+ t_u8 tlv[];
+} MLAN_PACK_END subcmd_rc4_t;
+
+/** subcmd_mrvf_f, used by mrvl_f*/
+typedef MLAN_PACK_START struct _subcmd_mrvf_f {
+ /** output_len */
+ t_u16 output_len;
+ /** iterations */
+ t_u32 iterations;
+ /** count */
+ t_u32 count;
+ /** tlv start */
+ t_u8 tlv[];
+} MLAN_PACK_END subcmd_mrvl_f_t;
+
+#endif
+
+#ifdef UAP_SUPPORT
+/** action add station */
+#define HostCmd_ACT_ADD_STA 0x1
+/** remove station */
+#define HostCmd_ACT_REMOVE_STA 0x0
+/** HostCmd_DS_ADD_STATION */
+typedef MLAN_PACK_START struct _HostCmd_DS_ADD_STATION {
+ /** 1 -add, 0 --delete */
+ t_u16 action;
+ /** aid */
+ t_u16 aid;
+ /** peer_mac */
+ t_u8 peer_mac[MLAN_MAC_ADDR_LENGTH];
+ /** Listen Interval */
+ int listen_interval;
+ /** Capability Info */
+ t_u16 cap_info;
+ /** tlv start */
+ t_u8 tlv[];
+} MLAN_PACK_END HostCmd_DS_ADD_STATION;
+
+/** Host Command ID : Add New Station */
+#define HostCmd_CMD_ADD_NEW_STATION 0x025f
+/** TLV id: station flag */
+#define TLV_TYPE_UAP_STA_FLAGS (PROPRIETARY_TLV_BASE_ID + 313)
+/**MrvlIEtypes_Sta_Flag_t */
+typedef MLAN_PACK_START struct _MrvlIEtypes_StaFlag_t {
+ /** Header */
+ MrvlIEtypesHeader_t header;
+ /** station flag */
+ t_u32 sta_flags;
+} MLAN_PACK_END MrvlIEtypes_StaFlag_t;
+#endif
+
+/** Host Command ID : _HostCmd_DS_BAND_STEERING */
+typedef MLAN_PACK_START struct _HostCmd_DS_BAND_STEERING {
+ /** ACT_GET/ACT_SET */
+ t_u8 action;
+ /** State */
+ t_u8 state;
+ /** probe requests to be blocked on 2g */
+ t_u8 block_2g_prb_req;
+ /** limit the btm request sent to STA at <max_btm_req_allowed>*/
+ t_u8 max_btm_req_allowed;
+} MLAN_PACK_END HostCmd_DS_BAND_STEERING;
+
+/** HostCmd_CMD_RX_ABORT_CFG */
+typedef MLAN_PACK_START struct _HostCmd_DS_CMD_RX_ABORT_CFG {
+ /** Action */
+ t_u16 action;
+ /** Enable/disable rx abort on weak pkt rssi */
+ t_u8 enable;
+ /** rx weak rssi pkt threshold */
+ t_s8 rssi_threshold;
+} MLAN_PACK_END HostCmd_DS_CMD_RX_ABORT_CFG;
+/** HostCmd_CMD_RX_ABORT_CFG_EXT */
+typedef MLAN_PACK_START struct _HostCmd_DS_CMD_RX_ABORT_CFG_EXT {
+ /** Action */
+ t_u16 action;
+ /** Enable/disable dyn rx abort on weak pkt rssi */
+ t_u8 enable;
+ /** specify rssi margin */
+ t_s8 rssi_margin;
+ /** specify ceil rssi threshold */
+ t_s8 ceil_rssi_threshold;
+} MLAN_PACK_END HostCmd_DS_CMD_RX_ABORT_CFG_EXT;
+
+/** HostCmd_CMD_ARB_CONFIG */
+typedef MLAN_PACK_START struct _HostCmd_DS_CMD_ARB_CONFIG {
+ /** Action */
+ t_u16 action;
+ /** 0-4 */
+ t_u32 arb_mode;
+ /** 1: use FW enhancement, 0: use FW default */
+ t_u32 reserved;
+} MLAN_PACK_END HostCmd_DS_CMD_ARB_CONFIG;
+
+/** HostCmd_DS_CMD_TX_AMPDU_PROT_MODE */
+typedef MLAN_PACK_START struct _HostCmd_DS_CMD_TX_AMPDU_PROT_MODE {
+ /** Action */
+ t_u16 action;
+ /** Prot mode */
+ t_u16 mode;
+} MLAN_PACK_END HostCmd_DS_CMD_TX_AMPDU_PROT_MODE;
+
+/** HostCmd_DS_CMD_DOT11MC_UNASSOC_FTM_CFG */
+typedef MLAN_PACK_START struct _HostCmd_DS_CMD_DOT11MC_UNASSOC_FTM_CFG {
+ /** Action */
+ t_u16 action;
+ /** Cfg state */
+ t_u16 state;
+} MLAN_PACK_END HostCmd_DS_CMD_DOT11MC_UNASSOC_FTM_CFG;
+
+/** HostCmd_CMD_RATE_ADAPT_CFG */
+typedef MLAN_PACK_START struct _HostCmd_DS_CMD_RATE_ADAPT_CFG {
+ /** Action */
+ t_u16 action;
+ /** SR Rateadapt*/
+ t_u8 sr_rateadapt;
+ /** set low threshold */
+ t_u8 ra_low_thresh;
+ /** set high threshold */
+ t_u8 ra_high_thresh;
+ /** set interval */
+ t_u16 ra_interval;
+} MLAN_PACK_END HostCmd_DS_CMD_RATE_ADAPT_CFG;
+
+/** HostCmd_CMD_CCK_DESENSE_CFG */
+typedef MLAN_PACK_START struct _HostCmd_DS_CMD_CCK_DESENSE_CFG {
+ /** Action */
+ t_u16 action;
+ /** cck desense mode: 0:disable 1:normal 2:dynamic */
+ t_u16 mode;
+ /** specify rssi margin */
+ t_s8 margin;
+ /** specify ceil rssi threshold */
+ t_s8 ceil_thresh;
+ /** cck desense "on" interval count */
+ t_u8 num_on_intervals;
+ /** cck desense "off" interval count */
+ t_u8 num_off_intervals;
+} MLAN_PACK_END HostCmd_DS_CMD_CCK_DESENSE_CFG;
+
+/** HostCmd_DS_COMMAND */
+typedef struct MLAN_PACK_START _HostCmd_DS_COMMAND {
+ /** Command Header : Command */
+ t_u16 command;
+ /** Command Header : Size */
+ t_u16 size;
+ /** Command Header : Sequence number */
+ t_u16 seq_num;
+ /** Command Header : Result */
+ t_u16 result;
+ /** Command Body */
+ union {
+ /** Hardware specifications */
+ HostCmd_DS_GET_HW_SPEC hw_spec;
+#ifdef SDIO
+ HostCmd_DS_SDIO_SP_RX_AGGR_CFG sdio_rx_aggr;
+#endif
+ /** Cfg data */
+ HostCmd_DS_802_11_CFG_DATA cfg_data;
+ /** MAC control */
+ HostCmd_DS_MAC_CONTROL mac_ctrl;
+ /** MAC address */
+ HostCmd_DS_802_11_MAC_ADDRESS mac_addr;
+ /** MAC muticast address */
+ HostCmd_DS_MAC_MULTICAST_ADR mc_addr;
+ /** Get log */
+ HostCmd_DS_802_11_GET_LOG get_log;
+ /** Get link layer statistic */
+ HostCmd_DS_802_11_LINK_STATISTIC get_link_statistic;
+ /** RSSI information */
+ HostCmd_DS_802_11_RSSI_INFO_EXT rssi_info_ext;
+ /** RSSI information */
+ HostCmd_DS_802_11_RSSI_INFO rssi_info;
+ /** RSSI information response */
+ HostCmd_DS_802_11_RSSI_INFO_RSP rssi_info_rsp;
+ /** SNMP MIB */
+ HostCmd_DS_802_11_SNMP_MIB smib;
+#ifdef UAP_SUPPORT
+ /** UAP SNMP MIB */
+ HostCmd_DS_UAP_802_11_SNMP_MIB uap_smib;
+#endif
+ /** Radio control */
+ HostCmd_DS_802_11_RADIO_CONTROL radio;
+ /** RF channel */
+ HostCmd_DS_802_11_RF_CHANNEL rf_channel;
+ /** Tx rate query */
+ HostCmd_TX_RATE_QUERY tx_rate;
+ /** Tx rate configuration */
+ HostCmd_DS_TX_RATE_CFG tx_rate_cfg;
+ /** Tx power configuration */
+ HostCmd_DS_TXPWR_CFG txp_cfg;
+ /** RF Tx power configuration */
+ HostCmd_DS_802_11_RF_TX_POWER txp;
+
+ /** RF antenna */
+ HostCmd_DS_802_11_RF_ANTENNA antenna;
+
+ /** CW Mode: Tx CW Level control */
+ HostCmd_DS_CW_MODE_CTRL cwmode;
+ /** Enhanced power save command */
+ HostCmd_DS_802_11_PS_MODE_ENH psmode_enh;
+ HostCmd_DS_802_11_HS_CFG_ENH opt_hs_cfg;
+ /** Scan */
+ HostCmd_DS_802_11_SCAN scan;
+ /** Extended Scan */
+ HostCmd_DS_802_11_SCAN_EXT ext_scan;
+
+ /** Mgmt frame subtype mask */
+ HostCmd_DS_RX_MGMT_IND rx_mgmt_ind;
+ /** Scan response */
+ HostCmd_DS_802_11_SCAN_RSP scan_resp;
+
+ HostCmd_DS_802_11_BG_SCAN_CONFIG bg_scan_config;
+ HostCmd_DS_802_11_BG_SCAN_QUERY bg_scan_query;
+ HostCmd_DS_802_11_BG_SCAN_QUERY_RSP bg_scan_query_resp;
+ HostCmd_DS_SUBSCRIBE_EVENT subscribe_event;
+ HostCmd_DS_OTP_USER_DATA otp_user_data;
+ /** Associate */
+ HostCmd_DS_802_11_ASSOCIATE associate;
+
+ /** Associate response */
+ HostCmd_DS_802_11_ASSOCIATE_RSP associate_rsp;
+ /** Deauthenticate */
+ HostCmd_DS_802_11_DEAUTHENTICATE deauth;
+ /** Ad-Hoc start */
+ HostCmd_DS_802_11_AD_HOC_START adhoc_start;
+ /** Ad-Hoc start result */
+ HostCmd_DS_802_11_AD_HOC_START_RESULT adhoc_start_result;
+ /** Ad-Hoc join result */
+ HostCmd_DS_802_11_AD_HOC_JOIN_RESULT adhoc_join_result;
+ /** Ad-Hoc join */
+ HostCmd_DS_802_11_AD_HOC_JOIN adhoc_join;
+ /** Domain information */
+ HostCmd_DS_802_11D_DOMAIN_INFO domain_info;
+ /** Domain information response */
+ HostCmd_DS_802_11D_DOMAIN_INFO_RSP domain_info_resp;
+ HostCmd_DS_802_11_TPC_ADAPT_REQ tpc_req;
+ HostCmd_DS_802_11_TPC_INFO tpc_info;
+ HostCmd_DS_802_11_CHAN_SW_ANN chan_sw_ann;
+ HostCmd_DS_CHAN_RPT_REQ chan_rpt_req;
+ HostCmd_DS_MEASUREMENT_REQUEST meas_req;
+ HostCmd_DS_MEASUREMENT_REPORT meas_rpt;
+ /** Add BA request */
+ HostCmd_DS_11N_ADDBA_REQ add_ba_req;
+ /** Add BA response */
+ HostCmd_DS_11N_ADDBA_RSP add_ba_rsp;
+ /** Delete BA entry */
+ HostCmd_DS_11N_DELBA del_ba;
+ /** Tx buffer configuration */
+ HostCmd_DS_TXBUF_CFG tx_buf;
+ /** AMSDU Aggr Ctrl configuration */
+ HostCmd_DS_AMSDU_AGGR_CTRL amsdu_aggr_ctrl;
+ /** 11n configuration */
+ HostCmd_DS_11N_CFG htcfg;
+ /** reject addba req conditions configuration */
+ HostCmd_DS_REJECT_ADDBA_REQ rejectaddbareq;
+ /* RANDYTODO need add more */
+ /** HostCmd_DS_11AC_CFG */
+ HostCmd_DS_11AC_CFG vhtcfg;
+ /** HostCmd_DS_11ACTXBUF_CFG*/
+ HostCmd_DS_11ACTXBUF_CFG ac_tx_buf;
+ /** 11n configuration */
+ HostCmd_DS_TX_BF_CFG tx_bf_cfg;
+ /** WMM status get */
+ HostCmd_DS_WMM_GET_STATUS get_wmm_status;
+ /** WMM ADDTS */
+ HostCmd_DS_WMM_ADDTS_REQ add_ts;
+ /** WMM DELTS */
+ HostCmd_DS_WMM_DELTS_REQ del_ts;
+ /** WMM set/get queue config */
+ HostCmd_DS_WMM_QUEUE_CONFIG queue_config;
+ /** WMM param config*/
+ HostCmd_DS_WMM_PARAM_CONFIG param_config;
+ /** WMM on/of/get queue statistics */
+ HostCmd_DS_WMM_QUEUE_STATS queue_stats;
+ /** WMM get traffic stream status */
+ HostCmd_DS_WMM_TS_STATUS ts_status;
+ /** Key material */
+ HostCmd_DS_802_11_KEY_MATERIAL key_material;
+ /** GTK Rekey parameters */
+ HostCmd_DS_GTK_REKEY_PARAMS gtk_rekey;
+ /** E-Supplicant PSK */
+ HostCmd_DS_802_11_SUPPLICANT_PMK esupplicant_psk;
+ /** E-Supplicant profile */
+ HostCmd_DS_802_11_SUPPLICANT_PROFILE esupplicant_profile;
+ /** Extended version */
+ HostCmd_DS_VERSION_EXT verext;
+ /** Adhoc Coalescing */
+ HostCmd_DS_802_11_IBSS_STATUS ibss_coalescing;
+ /** Mgmt IE list configuration */
+ HostCmd_DS_MGMT_IE_LIST_CFG mgmt_ie_list;
+ /** System clock configuration */
+ HostCmd_DS_ECL_SYSTEM_CLOCK_CONFIG sys_clock_cfg;
+ /** MAC register access */
+ HostCmd_DS_MAC_REG_ACCESS mac_reg;
+ /** BBP register access */
+ HostCmd_DS_BBP_REG_ACCESS bbp_reg;
+ /** RF register access */
+ HostCmd_DS_RF_REG_ACCESS rf_reg;
+ /** EEPROM register access */
+ HostCmd_DS_802_11_EEPROM_ACCESS eeprom;
+ /** Memory access */
+ HostCmd_DS_MEM_ACCESS mem;
+ /** Target device access */
+ HostCmd_DS_TARGET_ACCESS target;
+ /** BCA register access */
+ HostCmd_DS_BCA_REG_ACCESS bca_reg;
+ /** Inactivity timeout extend */
+ HostCmd_DS_INACTIVITY_TIMEOUT_EXT inactivity_to;
+#ifdef UAP_SUPPORT
+ HostCmd_DS_SYS_CONFIG sys_config;
+ HostCmd_DS_SYS_INFO sys_info;
+ HostCmd_DS_STA_DEAUTH sta_deauth;
+ HostCmd_DS_STA_LIST sta_list;
+ HostCmd_DS_POWER_MGMT_EXT pm_cfg;
+ HostCmd_DS_REPORT_MIC report_mic;
+ HostCmd_DS_UAP_OPER_CTRL uap_oper_ctrl;
+#endif /* UAP_SUPPORT */
+ HostCmd_DS_TX_RX_HISTOGRAM tx_rx_histogram;
+
+ /** Sleep period command */
+ HostCmd_DS_802_11_SLEEP_PERIOD sleep_pd;
+ /** Sleep params command */
+ HostCmd_DS_802_11_SLEEP_PARAMS sleep_param;
+
+#ifdef SDIO
+ /** SDIO GPIO interrupt config command */
+ HostCmd_DS_SDIO_GPIO_INT_CONFIG sdio_gpio_int;
+ HostCmd_DS_SDIO_PULL_CTRL sdio_pull_ctl;
+#endif
+ HostCmd_DS_SET_BSS_MODE bss_mode;
+ HostCmd_DS_CMD_TX_DATA_PAUSE tx_data_pause;
+#if defined(PCIE)
+#if defined(PCIE8997) || defined(PCIE8897)
+ HostCmd_DS_PCIE_HOST_BUF_DETAILS pcie_host_spec;
+#endif
+#endif
+ HostCmd_DS_REMAIN_ON_CHANNEL remain_on_chan;
+#ifdef WIFI_DIRECT_SUPPORT
+ HostCmd_DS_WIFI_DIRECT_MODE wifi_direct_mode;
+ HostCmd_DS_WIFI_DIRECT_PARAM_CONFIG p2p_params_config;
+#endif
+ HostCmd_DS_COALESCE_CONFIG coalesce_config;
+ HostCmd_DS_HS_WAKEUP_REASON hs_wakeup_reason;
+ HostCmd_DS_PACKET_AGGR_CTRL aggr_ctrl;
+#ifdef USB
+ HostCmd_DS_PACKET_AGGR_OVER_HOST_INTERFACE packet_aggr;
+#endif
+ HostCmd_CONFIG_LOW_PWR_MODE low_pwr_mode_cfg;
+ HostCmd_DS_TSF tsf;
+ HostCmd_DS_DFS_REPEATER_MODE dfs_repeater;
+#ifdef RX_PACKET_COALESCE
+ HostCmd_DS_RX_PKT_COAL_CFG rx_pkt_coal_cfg;
+#endif
+ HostCmd_DS_EAPOL_PKT eapol_pkt;
+ HostCmd_DS_SENSOR_TEMP temp_sensor;
+ HostCMD_DS_APCMD_ACS_SCAN acs_scan;
+ HostCmd_DS_MIMO_SWITCH mimo_switch;
+#ifdef STA_SUPPORT
+ HostCmd_DS_STA_CONFIGURE sta_cfg;
+#endif
+ /** GPIO Independent reset configure */
+ HostCmd_DS_INDEPENDENT_RESET_CFG ind_rst_cfg;
+ HostCmd_DS_802_11_PS_INACTIVITY_TIMEOUT ps_inact_tmo;
+ HostCmd_DS_CHAN_REGION_CFG reg_cfg;
+ HostCmd_DS_AUTO_TX auto_tx;
+ HostCmd_DS_DYN_BW dyn_bw;
+ HostCmd_DS_802_11_ROBUSTCOEX robustcoexparams;
+ HostCmd_DS_DMCS_CFG dmcs;
+#if defined(PCIE)
+ HostCmd_DS_SSU_CFG ssu_params;
+#endif
+ /** boot sleep configure */
+ HostCmd_DS_BOOT_SLEEP boot_sleep;
+#if defined(DRV_EMBEDDED_AUTHENTICATOR) || defined(DRV_EMBEDDED_SUPPLICANT)
+ /** crypto cmd */
+ HostCmd_DS_CRYPTO crypto_cmd;
+#endif
+#ifdef UAP_SUPPORT
+ /** Add station cmd */
+ HostCmd_DS_ADD_STATION sta_info;
+#endif
+ /** HostCmd_DS_11AX_CFG */
+ HostCmd_DS_11AX_CFG axcfg;
+ /** HostCmd_DS_11AX_CMD_CFG */
+ HostCmd_DS_11AX_CMD_CFG axcmd;
+ HostCmd_DS_RANGE_EXT range_ext;
+ /** HostCmd_DS_TWT_CFG */
+ HostCmd_DS_TWT_CFG twtcfg;
+
+ HostCmd_DS_CMD_RX_ABORT_CFG rx_abort_cfg;
+ HostCmd_DS_CMD_RX_ABORT_CFG_EXT rx_abort_cfg_ext;
+ HostCmd_DS_CMD_TX_AMPDU_PROT_MODE tx_ampdu_prot_mode;
+ HostCmd_DS_CMD_RATE_ADAPT_CFG rate_adapt_cfg;
+ HostCmd_DS_CMD_CCK_DESENSE_CFG cck_desense_cfg;
+ /** trpc_config */
+ HostCmd_DS_CHANNEL_TRPC_CONFIG ch_trpc_config;
+ HostCmd_DS_LOW_POWER_MODE_CFG lpm_cfg;
+ HostCmd_DS_BAND_STEERING band_steer_info;
+ HostCmd_DS_BEACON_STUCK_CFG beacon_stuck_cfg;
+ struct mfg_cmd_generic_cfg mfg_generic_cfg;
+ struct mfg_cmd_tx_cont mfg_tx_cont;
+ struct mfg_cmd_tx_frame2 mfg_tx_frame2;
+ HostCmd_DS_CMD_ARB_CONFIG arb_cfg;
+ HostCmd_DS_CMD_DOT11MC_UNASSOC_FTM_CFG dot11mc_unassoc_ftm_cfg;
+ } params;
+} MLAN_PACK_END HostCmd_DS_COMMAND, *pHostCmd_DS_COMMAND;
+
+/** PS_CMD_ConfirmSleep */
+typedef MLAN_PACK_START struct _OPT_Confirm_Sleep {
+ /** Command */
+ t_u16 command;
+ /** Size */
+ t_u16 size;
+ /** Sequence number */
+ t_u16 seq_num;
+ /** Result */
+ t_u16 result;
+ /** Action */
+ t_u16 action;
+ /** Sleep comfirm param definition */
+ sleep_confirm_param sleep_cfm;
+} MLAN_PACK_END OPT_Confirm_Sleep;
+
+typedef struct MLAN_PACK_START _opt_sleep_confirm_buffer {
+ /** Header for interface */
+ t_u32 hdr;
+ /** New power save command used to send
+ * sleep confirmation to the firmware */
+ OPT_Confirm_Sleep ps_cfm_sleep;
+} MLAN_PACK_END opt_sleep_confirm_buffer;
+
+/** req host side download vdll block */
+#define VDLL_IND_TYPE_REQ 0
+/** notify vdll start offset in firmware image */
+#define VDLL_IND_TYPE_OFFSET 1
+
+/** vdll indicate event structure */
+typedef MLAN_PACK_START struct _vdll_ind {
+ /*VDLL ind type*/
+ t_u16 type;
+ /*reserved*/
+ t_u16 reserved;
+ /*indicate the offset downloaded so far*/
+ t_u32 offset;
+ /*VDLL block size*/
+ t_u16 block_len;
+} MLAN_PACK_END vdll_ind, *pvdll_ind;
+#ifdef PRAGMA_PACK
+#pragma pack(pop)
+#endif
+
+#endif /* !_MLAN_FW_H_ */
diff --git a/drivers/net/wireless/nxp/mxm_wifiex/wlan_src/mlan/mlan_ieee.h b/drivers/net/wireless/nxp/mxm_wifiex/wlan_src/mlan/mlan_ieee.h
new file mode 100644
index 000000000000..03b5fd4ffc92
--- /dev/null
+++ b/drivers/net/wireless/nxp/mxm_wifiex/wlan_src/mlan/mlan_ieee.h
@@ -0,0 +1,1888 @@
+/** @file mlan_ieee.h
+ *
+ * @brief This file contains IEEE information element related
+ * definitions used in MLAN and MOAL module.
+ *
+ *
+ * Copyright 2014-2020 NXP
+ *
+ * This software file (the File) is distributed by NXP
+ * under the terms of the GNU General Public License Version 2, June 1991
+ * (the License). You may use, redistribute and/or modify the 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.
+ *
+ */
+
+/******************************************************
+Change log:
+ 11/03/2008: initial version
+******************************************************/
+
+#ifndef _MLAN_IEEE_H_
+#define _MLAN_IEEE_H_
+
+/** FIX IES size in beacon buffer */
+#define WLAN_802_11_FIXED_IE_SIZE 12
+/** WLAN supported rates */
+#define WLAN_SUPPORTED_RATES 14
+
+/** WLAN supported rates extension */
+#define WLAN_SUPPORTED_RATES_EXT 60
+
+/** Enumeration definition*/
+/** WLAN_802_11_NETWORK_TYPE */
+typedef enum _WLAN_802_11_NETWORK_TYPE {
+ Wlan802_11FH,
+ Wlan802_11DS,
+ /* Defined as upper bound*/
+ Wlan802_11NetworkTypeMax
+} WLAN_802_11_NETWORK_TYPE;
+
+#ifdef BIG_ENDIAN_SUPPORT
+/** Frame control: Type Mgmt frame */
+#define IEEE80211_FC_MGMT_FRAME_TYPE_MASK 0x3000
+/** Frame control: SubType Mgmt frame */
+#define IEEE80211_GET_FC_MGMT_FRAME_SUBTYPE(fc) (((fc)&0xF000) >> 12)
+#else
+/** Frame control: Type Mgmt frame */
+#define IEEE80211_FC_MGMT_FRAME_TYPE_MASK 0x000C
+/** Frame control: SubType Mgmt frame */
+#define IEEE80211_GET_FC_MGMT_FRAME_SUBTYPE(fc) (((fc)&0x00F0) >> 4)
+#endif
+
+#ifdef PRAGMA_PACK
+#pragma pack(push, 1)
+#endif
+
+/* Reason codes */
+#define IEEE_80211_REASONCODE_UNSPECIFIED 1
+
+typedef enum _IEEEtypes_Ext_ElementId_e {
+ HE_CAPABILITY = 35,
+ HE_OPERATION = 36
+} IEEEtypes_Ext_ElementId_e;
+
+/** IEEE Type definitions */
+typedef MLAN_PACK_START enum _IEEEtypes_ElementId_e {
+ SSID = 0,
+ SUPPORTED_RATES = 1,
+
+ FH_PARAM_SET = 2,
+ DS_PARAM_SET = 3,
+ CF_PARAM_SET = 4,
+
+ IBSS_PARAM_SET = 6,
+ COUNTRY_INFO = 7,
+ POWER_CONSTRAINT = 32,
+ POWER_CAPABILITY = 33,
+ TPC_REQUEST = 34,
+ TPC_REPORT = 35,
+ CHANNEL_SWITCH_ANN = 37,
+ EXTEND_CHANNEL_SWITCH_ANN = 60,
+ QUIET = 40,
+ IBSS_DFS = 41,
+ SUPPORTED_CHANNELS = 36,
+ REGULATORY_CLASS = 59,
+ HT_CAPABILITY = 45,
+ QOS_INFO = 46,
+ HT_OPERATION = 61,
+ MULTI_BSSID = 71,
+ BSSCO_2040 = 72,
+ OVERLAPBSSSCANPARAM = 74,
+ NONTX_BSSID_CAP = 83,
+ MBSSID_INDEX = 85,
+ EXT_CAPABILITY = 127,
+ /*IEEE802.11r*/
+ MOBILITY_DOMAIN = 54,
+ FAST_BSS_TRANSITION = 55,
+ TIMEOUT_INTERVAL = 56,
+ RIC = 57,
+ QOS_MAPPING = 110,
+ VHT_CAPABILITY = 191,
+ VHT_OPERATION = 192,
+ EXT_BSS_LOAD = 193,
+ BW_CHANNEL_SWITCH = 194,
+ VHT_TX_POWER_ENV = 195,
+ EXT_POWER_CONSTR = 196,
+ AID_INFO = 197,
+ QUIET_CHAN = 198,
+ OPER_MODE_NTF = 199,
+
+ ERP_INFO = 42,
+
+ EXTENDED_SUPPORTED_RATES = 50,
+
+ VENDOR_SPECIFIC_221 = 221,
+ WMM_IE = VENDOR_SPECIFIC_221,
+
+ WPS_IE = VENDOR_SPECIFIC_221,
+ /* WPA */
+ WPA_IE = VENDOR_SPECIFIC_221,
+ /* WPA2 */
+ RSN_IE = 48,
+ VS_IE = VENDOR_SPECIFIC_221,
+ WAPI_IE = 68,
+ FRAGMENT = 242,
+ EXTENSION = 255
+} MLAN_PACK_END IEEEtypes_ElementId_e;
+
+/** IEEE IE header */
+typedef MLAN_PACK_START struct _IEEEtypes_Header_t {
+ /** Element ID */
+ t_u8 element_id;
+ /** Length */
+ t_u8 len;
+} MLAN_PACK_END IEEEtypes_Header_t, *pIEEEtypes_Header_t;
+
+/** Vendor specific IE header */
+typedef MLAN_PACK_START struct _IEEEtypes_VendorHeader_t {
+ /** Element ID */
+ t_u8 element_id;
+ /** Length */
+ t_u8 len;
+ /** OUI */
+ t_u8 oui[3];
+ /** OUI type */
+ t_u8 oui_type;
+ /** OUI subtype */
+ t_u8 oui_subtype;
+ /** Version */
+ t_u8 version;
+} MLAN_PACK_END IEEEtypes_VendorHeader_t, *pIEEEtypes_VendorHeader_t;
+
+/** Vendor specific IE */
+typedef MLAN_PACK_START struct _IEEEtypes_VendorSpecific_t {
+ /** Vendor specific IE header */
+ IEEEtypes_VendorHeader_t vend_hdr;
+ /** IE Max - size of previous fields */
+ t_u8 data[IEEE_MAX_IE_SIZE - sizeof(IEEEtypes_VendorHeader_t)];
+} MLAN_PACK_END IEEEtypes_VendorSpecific_t, *pIEEEtypes_VendorSpecific_t;
+
+/** IEEE IE */
+typedef MLAN_PACK_START struct _IEEEtypes_Generic_t {
+ /** Generic IE header */
+ IEEEtypes_Header_t ieee_hdr;
+ /** IE Max - size of previous fields */
+ t_u8 data[IEEE_MAX_IE_SIZE - sizeof(IEEEtypes_Header_t)];
+} MLAN_PACK_END IEEEtypes_Generic_t, *pIEEEtypes_Generic_t;
+
+/**ft capability policy*/
+typedef MLAN_PACK_START struct _IEEEtypes_FtCapPolicy_t {
+#ifdef BIG_ENDIAN_SUPPORT
+ /** Reserved */
+ t_u8 reserved : 6;
+ /** RIC support */
+ t_u8 ric : 1;
+ /** FT over the DS capable */
+ t_u8 ft_over_ds : 1;
+#else
+ /** FT over the DS capable */
+ t_u8 ft_over_ds : 1;
+ /** RIC support */
+ t_u8 ric : 1;
+ /** Reserved */
+ t_u8 reserved : 6;
+#endif
+} MLAN_PACK_END IEEEtypes_FtCapPolicy_t;
+
+/** Mobility domain IE */
+typedef MLAN_PACK_START struct _IEEEtypes_MobilityDomain_t {
+ /** Generic IE header */
+ IEEEtypes_Header_t ieee_hdr;
+ /** Mobility Domain ID */
+ t_u16 mdid;
+ /** FT Capability policy */
+ t_u8 ft_cap;
+} MLAN_PACK_END IEEEtypes_MobilityDomain_t;
+
+/**FT MIC Control*/
+typedef MLAN_PACK_START struct _IEEEtypes_FT_MICControl_t {
+ /** reserved */
+ t_u8 reserved;
+ /** element count */
+ t_u8 element_count;
+} MLAN_PACK_END IEEEtypes_FT_MICControl_t;
+
+/** FTIE MIC LEN */
+#define FTIE_MIC_LEN 16
+
+/**FT IE*/
+typedef MLAN_PACK_START struct _IEEEtypes_FastBssTransElement_t {
+ /** Generic IE header */
+ IEEEtypes_Header_t ieee_hdr;
+ /** mic control */
+ IEEEtypes_FT_MICControl_t mic_control;
+ /** mic */
+ t_u8 mic[FTIE_MIC_LEN];
+ /** ANonce */
+ t_u8 a_nonce[32];
+ /** SNonce */
+ t_u8 s_nonce[32];
+ /** sub element */
+ t_u8 sub_element[1];
+} MLAN_PACK_END IEEEtypes_FastBssTransElement_t;
+
+/*Category for FT*/
+#define FT_CATEGORY 6
+/** FT ACTION request */
+#define FT_ACTION_REQUEST 1
+/** FT ACTION response */
+#define FT_ACTION_RESPONSE 2
+
+/*FT response and FT ack*/
+typedef MLAN_PACK_START struct {
+ /** category */
+ t_u8 category;
+ /** action */
+ t_u8 action;
+ /** sta address */
+ t_u8 sta_addr[MLAN_MAC_ADDR_LENGTH];
+ /** target ap address */
+ t_u8 target_ap_addr[MLAN_MAC_ADDR_LENGTH];
+ /** status code */
+ t_u16 status_code;
+ /** varible */
+ t_u8 variable[];
+} MLAN_PACK_END IEEEtypes_Ft_action_response;
+
+/**FT request */
+typedef MLAN_PACK_START struct {
+ /** category */
+ t_u8 category;
+ /** action */
+ t_u8 action;
+ /** sta address */
+ t_u8 sta_addr[MLAN_MAC_ADDR_LENGTH];
+ /** target ap address */
+ t_u8 target_ap_addr[MLAN_MAC_ADDR_LENGTH];
+ /** varible */
+ t_u8 variable[];
+} MLAN_PACK_END IEEEtypes_Ft_action_request;
+
+/** auth frame body*/
+typedef MLAN_PACK_START struct {
+ /** auth alg */
+ t_u16 auth_alg;
+ /** auth transaction */
+ t_u16 auth_transaction;
+ /** status code */
+ t_u16 status_code;
+ /** variable */
+ t_u8 variable[];
+} MLAN_PACK_END IEEEtypes_Auth_framebody;
+
+/** associate request frame */
+typedef MLAN_PACK_START struct {
+ t_u16 capab_info;
+ t_u16 listen_interval;
+ /** followed by SSID and Supported rates */
+ t_u8 variablep[];
+} MLAN_PACK_END IEEEtypes_assoc_req;
+
+/*Mgmt frame*/
+typedef MLAN_PACK_START struct {
+ /** frame control */
+ t_u16 frame_control;
+ /** duration */
+ t_u16 duration;
+ /** dest address */
+ t_u8 da[MLAN_MAC_ADDR_LENGTH];
+ /** source address */
+ t_u8 sa[MLAN_MAC_ADDR_LENGTH];
+ /** bssid */
+ t_u8 bssid[MLAN_MAC_ADDR_LENGTH];
+ /** seq control */
+ t_u16 seq_ctrl;
+ /** address 4 */
+ t_u8 addr4[MLAN_MAC_ADDR_LENGTH];
+ union {
+ IEEEtypes_Auth_framebody auth;
+ IEEEtypes_assoc_req assoc_req;
+ IEEEtypes_Ft_action_response ft_resp;
+ IEEEtypes_Ft_action_request ft_req;
+ } u;
+} MLAN_PACK_END IEEE80211_MGMT;
+
+/** TLV header */
+typedef MLAN_PACK_START struct _TLV_Generic_t {
+ /** Type */
+ t_u16 type;
+ /** Length */
+ t_u16 len;
+} MLAN_PACK_END TLV_Generic_t, *pTLV_Generic_t;
+
+/** Capability information mask */
+#define CAPINFO_MASK (~(MBIT(15) | MBIT(14) | MBIT(11) | MBIT(9)))
+
+/** Capability Bit Map*/
+#ifdef BIG_ENDIAN_SUPPORT
+typedef MLAN_PACK_START struct _IEEEtypes_CapInfo_t {
+ t_u8 rsrvd1 : 2;
+ t_u8 dsss_ofdm : 1;
+ t_u8 radio_measurement : 1;
+ t_u8 rsvrd2 : 1;
+ t_u8 short_slot_time : 1;
+ t_u8 rsrvd3 : 1;
+ t_u8 spectrum_mgmt : 1;
+ t_u8 chan_agility : 1;
+ t_u8 pbcc : 1;
+ t_u8 short_preamble : 1;
+ t_u8 privacy : 1;
+ t_u8 cf_poll_rqst : 1;
+ t_u8 cf_pollable : 1;
+ t_u8 ibss : 1;
+ t_u8 ess : 1;
+} MLAN_PACK_END IEEEtypes_CapInfo_t, *pIEEEtypes_CapInfo_t;
+#else
+typedef MLAN_PACK_START struct _IEEEtypes_CapInfo_t {
+ /** Capability Bit Map : ESS */
+ t_u8 ess : 1;
+ /** Capability Bit Map : IBSS */
+ t_u8 ibss : 1;
+ /** Capability Bit Map : CF pollable */
+ t_u8 cf_pollable : 1;
+ /** Capability Bit Map : CF poll request */
+ t_u8 cf_poll_rqst : 1;
+ /** Capability Bit Map : privacy */
+ t_u8 privacy : 1;
+ /** Capability Bit Map : Short preamble */
+ t_u8 short_preamble : 1;
+ /** Capability Bit Map : PBCC */
+ t_u8 pbcc : 1;
+ /** Capability Bit Map : Channel agility */
+ t_u8 chan_agility : 1;
+ /** Capability Bit Map : Spectrum management */
+ t_u8 spectrum_mgmt : 1;
+ /** Capability Bit Map : Reserved */
+ t_u8 rsrvd3 : 1;
+ /** Capability Bit Map : Short slot time */
+ t_u8 short_slot_time : 1;
+ /** Capability Bit Map : APSD */
+ t_u8 Apsd : 1;
+ /** Capability Bit Map : Reserved */
+ t_u8 rsvrd2 : 1;
+ /** Capability Bit Map : DSS OFDM */
+ t_u8 dsss_ofdm : 1;
+ /** Capability Bit Map : Reserved */
+ t_u8 rsrvd1 : 2;
+} MLAN_PACK_END IEEEtypes_CapInfo_t, *pIEEEtypes_CapInfo_t;
+#endif /* BIG_ENDIAN_SUPPORT */
+
+/** IEEEtypes_Ssid_t */
+typedef MLAN_PACK_START struct _IEEEtypes_Ssid_t {
+ /** SSID: Element ID */
+ t_u8 element_id;
+ /** SSID : Length */
+ t_u8 len;
+ /** ssid */
+ t_u8 ssid[MLAN_MAX_SSID_LENGTH];
+} MLAN_PACK_END IEEEtypes_Ssid_t, *pIEEEtypes_Ssid_t;
+
+/** IEEEtypes_CfParamSet_t */
+typedef MLAN_PACK_START struct _IEEEtypes_CfParamSet_t {
+ /** CF peremeter : Element ID */
+ t_u8 element_id;
+ /** CF peremeter : Length */
+ t_u8 len;
+ /** CF peremeter : Count */
+ t_u8 cfp_cnt;
+ /** CF peremeter : Period */
+ t_u8 cfp_period;
+ /** CF peremeter : Maximum duration */
+ t_u16 cfp_max_duration;
+ /** CF peremeter : Remaining duration */
+ t_u16 cfp_duration_remaining;
+} MLAN_PACK_END IEEEtypes_CfParamSet_t, *pIEEEtypes_CfParamSet_t;
+
+/** IEEEtypes_IbssParamSet_t */
+typedef MLAN_PACK_START struct _IEEEtypes_IbssParamSet_t {
+ /** Element ID */
+ t_u8 element_id;
+ /** Length */
+ t_u8 len;
+ /** ATIM window value in milliseconds */
+ t_u16 atim_window;
+} MLAN_PACK_END IEEEtypes_IbssParamSet_t, *pIEEEtypes_IbssParamSet_t;
+
+/** IEEEtypes_SsParamSet_t */
+typedef MLAN_PACK_START union _IEEEtypes_SsParamSet_t {
+ /** SS parameter : CF parameter set */
+ IEEEtypes_CfParamSet_t cf_param_set;
+ /** SS parameter : IBSS parameter set */
+ IEEEtypes_IbssParamSet_t ibss_param_set;
+} MLAN_PACK_END IEEEtypes_SsParamSet_t, *pIEEEtypes_SsParamSet_t;
+
+/** IEEEtypes_FhParamSet_t */
+typedef MLAN_PACK_START struct _IEEEtypes_FhParamSet_t {
+ /** FH parameter : Element ID */
+ t_u8 element_id;
+ /** FH parameter : Length */
+ t_u8 len;
+ /** FH parameter : Dwell time in milliseconds */
+ t_u16 dwell_time;
+ /** FH parameter : Hop set */
+ t_u8 hop_set;
+ /** FH parameter : Hop pattern */
+ t_u8 hop_pattern;
+ /** FH parameter : Hop index */
+ t_u8 hop_index;
+} MLAN_PACK_END IEEEtypes_FhParamSet_t, *pIEEEtypes_FhParamSet_t;
+
+/** IEEEtypes_DsParamSet_t */
+typedef MLAN_PACK_START struct _IEEEtypes_DsParamSet_t {
+ /** DS parameter : Element ID */
+ t_u8 element_id;
+ /** DS parameter : Length */
+ t_u8 len;
+ /** DS parameter : Current channel */
+ t_u8 current_chan;
+} MLAN_PACK_END IEEEtypes_DsParamSet_t, *pIEEEtypes_DsParamSet_t;
+
+/** IEEEtypes_PhyParamSet_t */
+typedef MLAN_PACK_START union _IEEEtypes_PhyParamSet_t {
+ /** FH parameter set */
+ IEEEtypes_FhParamSet_t fh_param_set;
+ /** DS parameter set */
+ IEEEtypes_DsParamSet_t ds_param_set;
+} MLAN_PACK_END IEEEtypes_PhyParamSet_t, *pIEEEtypes_PhyParamSet_t;
+
+/** IEEEtypes_ERPInfo_t */
+typedef MLAN_PACK_START struct _IEEEtypes_ERPInfo_t {
+ /** Element ID */
+ t_u8 element_id;
+ /** Length */
+ t_u8 len;
+ /** ERP flags */
+ t_u8 erp_flags;
+} MLAN_PACK_END IEEEtypes_ERPInfo_t, *pIEEEtypes_ERPInfo_t;
+
+/** IEEEtypes_AId_t */
+typedef t_u16 IEEEtypes_AId_t;
+
+/** IEEEtypes_StatusCode_t */
+typedef t_u16 IEEEtypes_StatusCode_t;
+
+/** Fixed size in assoc_resp */
+#define ASSOC_RESP_FIXED_SIZE 6
+
+/** IEEEtypes_SeqCtl_t */
+typedef MLAN_PACK_START struct _IEEEtypes_SeqCtl_t {
+ /** Fragment Number */
+ t_u16 FragNum : 4;
+ /** Sequence Number */
+ t_u16 SeqNum : 12;
+} MLAN_PACK_END IEEEtypes_SeqCtl_t;
+
+/** IEEEtypes_MgmtHdr_t */
+typedef MLAN_PACK_START struct _IEEEtypes_MgmtHdr_t {
+ /** FrmCtl*/
+ t_u16 FrmCtl;
+ /** Duration*/
+ t_u16 Duration;
+ /** Destination Addr*/
+ t_u8 DestAddr[6];
+ /** Source Addr*/
+ t_u8 SrcAddr[6];
+ /** BSSID */
+ t_u8 BssId[6];
+ /** IEEEtypes_SeqCtl_t */
+ IEEEtypes_SeqCtl_t SeqCtl;
+} MLAN_PACK_END IEEEtypes_MgmtHdr_t;
+
+/** IEEEtypes_AssocRsp_t */
+typedef MLAN_PACK_START struct _IEEEtypes_AssocRsp_t {
+ /** Capability information */
+ IEEEtypes_CapInfo_t capability;
+ /** Association response status code */
+ IEEEtypes_StatusCode_t status_code;
+ /** Association ID */
+ IEEEtypes_AId_t a_id;
+ /** IE data buffer */
+ t_u8 ie_buffer[1];
+} MLAN_PACK_END IEEEtypes_AssocRsp_t, *pIEEEtypes_AssocRsp_t;
+
+/** 802.11 supported rates */
+typedef t_u8 WLAN_802_11_RATES[WLAN_SUPPORTED_RATES];
+
+/** cipher TKIP */
+#define WPA_CIPHER_TKIP 2
+/** cipher AES */
+#define WPA_CIPHER_AES_CCM 4
+/** AKM: 8021x */
+#define RSN_AKM_8021X 1
+/** AKM: PSK */
+#define RSN_AKM_PSK 2
+/** AKM: PSK SHA256 */
+#define RSN_AKM_PSK_SHA256 6
+
+/** AKM: PSK SHA256 */
+#define RSN_AKM_SAE 8
+/** AKM: PSK SHA256 */
+#define RSN_AKM_OWE 18
+
+#if defined(STA_SUPPORT)
+/** Pairwise Cipher Suite length */
+#define PAIRWISE_CIPHER_SUITE_LEN 4
+/** AKM Suite length */
+#define AKM_SUITE_LEN 4
+/** MFPC bit in RSN capability */
+#define MFPC_BIT 7
+/** MFPR bit in RSN capability */
+#define MFPR_BIT 6
+/** PMF ORing mask */
+#define PMF_MASK 0x00c0
+#endif
+
+/** wpa_suite_t */
+typedef MLAN_PACK_START struct _wpa_suite_t {
+ /** OUI */
+ t_u8 oui[3];
+ /** tyep */
+ t_u8 type;
+} MLAN_PACK_END wpa_suite, wpa_suite_mcast_t;
+
+/** wpa_suite_ucast_t */
+typedef MLAN_PACK_START struct {
+ /* count */
+ t_u16 count;
+ /** wpa_suite list */
+ wpa_suite list[1];
+} MLAN_PACK_END wpa_suite_ucast_t, wpa_suite_auth_key_mgmt_t;
+
+/** IEEEtypes_Rsn_t */
+typedef MLAN_PACK_START struct _IEEEtypes_Rsn_t {
+ /** Rsn : Element ID */
+ t_u8 element_id;
+ /** Rsn : Length */
+ t_u8 len;
+ /** Rsn : version */
+ t_u16 version;
+ /** Rsn : group cipher */
+ wpa_suite_mcast_t group_cipher;
+ /** Rsn : pairwise cipher */
+ wpa_suite_ucast_t pairwise_cipher;
+} MLAN_PACK_END IEEEtypes_Rsn_t, *pIEEEtypes_Rsn_t;
+
+/** IEEEtypes_Wpa_t */
+typedef MLAN_PACK_START struct _IEEEtypes_Wpa_t {
+ /** Wpa : Element ID */
+ t_u8 element_id;
+ /** Wpa : Length */
+ t_u8 len;
+ /** Wpa : oui */
+ t_u8 oui[4];
+ /** version */
+ t_u16 version;
+ /** Wpa : group cipher */
+ wpa_suite_mcast_t group_cipher;
+ /** Wpa : pairwise cipher */
+ wpa_suite_ucast_t pairwise_cipher;
+} MLAN_PACK_END IEEEtypes_Wpa_t, *pIEEEtypes_Wpa_t;
+
+/** Data structure of WMM QoS information */
+typedef MLAN_PACK_START struct _IEEEtypes_WmmQosInfo_t {
+#ifdef BIG_ENDIAN_SUPPORT
+ /** QoS UAPSD */
+ t_u8 qos_uapsd : 1;
+ /** Reserved */
+ t_u8 reserved : 3;
+ /** Parameter set count */
+ t_u8 para_set_count : 4;
+#else
+ /** Parameter set count */
+ t_u8 para_set_count : 4;
+ /** Reserved */
+ t_u8 reserved : 3;
+ /** QoS UAPSD */
+ t_u8 qos_uapsd : 1;
+#endif /* BIG_ENDIAN_SUPPORT */
+} MLAN_PACK_END IEEEtypes_WmmQosInfo_t, *pIEEEtypes_WmmQosInfo_t;
+
+/** Data structure of WMM Aci/Aifsn */
+typedef MLAN_PACK_START struct _IEEEtypes_WmmAciAifsn_t {
+#ifdef BIG_ENDIAN_SUPPORT
+ /** Reserved */
+ t_u8 reserved : 1;
+ /** Aci */
+ t_u8 aci : 2;
+ /** Acm */
+ t_u8 acm : 1;
+ /** Aifsn */
+ t_u8 aifsn : 4;
+#else
+ /** Aifsn */
+ t_u8 aifsn : 4;
+ /** Acm */
+ t_u8 acm : 1;
+ /** Aci */
+ t_u8 aci : 2;
+ /** Reserved */
+ t_u8 reserved : 1;
+#endif /* BIG_ENDIAN_SUPPORT */
+} MLAN_PACK_END IEEEtypes_WmmAciAifsn_t, *pIEEEtypes_WmmAciAifsn_t;
+
+/** Data structure of WMM ECW */
+typedef MLAN_PACK_START struct _IEEEtypes_WmmEcw_t {
+#ifdef BIG_ENDIAN_SUPPORT
+ /** Maximum Ecw */
+ t_u8 ecw_max : 4;
+ /** Minimum Ecw */
+ t_u8 ecw_min : 4;
+#else
+ /** Minimum Ecw */
+ t_u8 ecw_min : 4;
+ /** Maximum Ecw */
+ t_u8 ecw_max : 4;
+#endif /* BIG_ENDIAN_SUPPORT */
+} MLAN_PACK_END IEEEtypes_WmmEcw_t, *pIEEEtypes_WmmEcw_t;
+
+/** Data structure of WMM AC parameters */
+typedef MLAN_PACK_START struct _IEEEtypes_WmmAcParameters_t {
+ IEEEtypes_WmmAciAifsn_t aci_aifsn; /**< AciAifSn */
+ IEEEtypes_WmmEcw_t ecw; /**< Ecw */
+ t_u16 tx_op_limit; /**< Tx op limit */
+} MLAN_PACK_END IEEEtypes_WmmAcParameters_t, *pIEEEtypes_WmmAcParameters_t;
+
+/** Data structure of WMM Info IE */
+typedef MLAN_PACK_START struct _IEEEtypes_WmmInfo_t {
+ /**
+ * WMM Info IE - Vendor Specific Header:
+ * element_id [221/0xdd]
+ * Len [7]
+ * Oui [00:50:f2]
+ * OuiType [2]
+ * OuiSubType [0]
+ * Version [1]
+ */
+ IEEEtypes_VendorHeader_t vend_hdr;
+
+ /** QoS information */
+ IEEEtypes_WmmQosInfo_t qos_info;
+
+} MLAN_PACK_END IEEEtypes_WmmInfo_t, *pIEEEtypes_WmmInfo_t;
+
+/** Data structure of WMM parameter IE */
+typedef MLAN_PACK_START struct _IEEEtypes_WmmParameter_t {
+ /**
+ * WMM Parameter IE - Vendor Specific Header:
+ * element_id [221/0xdd]
+ * Len [24]
+ * Oui [00:50:f2]
+ * OuiType [2]
+ * OuiSubType [1]
+ * Version [1]
+ */
+ IEEEtypes_VendorHeader_t vend_hdr;
+
+ /** QoS information */
+ IEEEtypes_WmmQosInfo_t qos_info;
+ /** Reserved */
+ t_u8 reserved;
+
+ /** AC Parameters Record WMM_AC_BE, WMM_AC_BK, WMM_AC_VI, WMM_AC_VO */
+ IEEEtypes_WmmAcParameters_t ac_params[MAX_AC_QUEUES];
+} MLAN_PACK_END IEEEtypes_WmmParameter_t, *pIEEEtypes_WmmParameter_t;
+
+/** Enumerator for TSPEC direction */
+typedef MLAN_PACK_START enum _IEEEtypes_WMM_TSPEC_TS_Info_Direction_e {
+
+ TSPEC_DIR_UPLINK = 0,
+ TSPEC_DIR_DOWNLINK = 1,
+ /* 2 is a reserved value */
+ TSPEC_DIR_BIDIRECT = 3,
+
+} MLAN_PACK_END IEEEtypes_WMM_TSPEC_TS_Info_Direction_e;
+
+/** Enumerator for TSPEC PSB */
+typedef MLAN_PACK_START enum _IEEEtypes_WMM_TSPEC_TS_Info_PSB_e {
+
+ TSPEC_PSB_LEGACY = 0,
+ TSPEC_PSB_TRIG = 1,
+
+} MLAN_PACK_END IEEEtypes_WMM_TSPEC_TS_Info_PSB_e;
+
+/** Enumerator for TSPEC Ack Policy */
+typedef MLAN_PACK_START enum _IEEEtypes_WMM_TSPEC_TS_Info_AckPolicy_e {
+
+ TSPEC_ACKPOLICY_NORMAL = 0,
+ TSPEC_ACKPOLICY_NOACK = 1,
+ /* 2 is reserved */
+ TSPEC_ACKPOLICY_BLOCKACK = 3,
+
+} MLAN_PACK_END IEEEtypes_WMM_TSPEC_TS_Info_AckPolicy_e;
+
+/** Enumerator for TSPEC Trafffice type */
+typedef MLAN_PACK_START enum _IEEEtypes_WMM_TSPEC_TS_TRAFFIC_TYPE_e {
+
+ TSPEC_TRAFFIC_APERIODIC = 0,
+ TSPEC_TRAFFIC_PERIODIC = 1,
+
+} MLAN_PACK_END IEEEtypes_WMM_TSPEC_TS_TRAFFIC_TYPE_e;
+
+/** Data structure of WMM TSPEC information */
+typedef MLAN_PACK_START struct {
+#ifdef BIG_ENDIAN_SUPPORT
+ t_u8 Reserved17_23 : 7; /* ! Reserved */
+ t_u8 Schedule : 1;
+ IEEEtypes_WMM_TSPEC_TS_Info_AckPolicy_e AckPolicy : 2;
+ t_u8 UserPri : 3; /* ! 802.1d User Priority */
+ IEEEtypes_WMM_TSPEC_TS_Info_PSB_e PowerSaveBehavior : 1; /* !
+ Legacy/Trigg
+ */
+ t_u8 Aggregation : 1; /* ! Reserved */
+ t_u8 AccessPolicy2 : 1; /* ! */
+ t_u8 AccessPolicy1 : 1; /* ! */
+ IEEEtypes_WMM_TSPEC_TS_Info_Direction_e Direction : 2;
+ t_u8 TID : 4; /* ! Unique identifier */
+ IEEEtypes_WMM_TSPEC_TS_TRAFFIC_TYPE_e TrafficType : 1;
+#else
+ IEEEtypes_WMM_TSPEC_TS_TRAFFIC_TYPE_e TrafficType : 1;
+ t_u8 TID : 4; /* ! Unique identifier */
+ IEEEtypes_WMM_TSPEC_TS_Info_Direction_e Direction : 2;
+ t_u8 AccessPolicy1 : 1; /* ! */
+ t_u8 AccessPolicy2 : 1; /* ! */
+ t_u8 Aggregation : 1; /* ! Reserved */
+ IEEEtypes_WMM_TSPEC_TS_Info_PSB_e PowerSaveBehavior : 1; /* !
+ Legacy/Trigg
+ */
+ t_u8 UserPri : 3; /* ! 802.1d User Priority */
+ IEEEtypes_WMM_TSPEC_TS_Info_AckPolicy_e AckPolicy : 2;
+ t_u8 Schedule : 1;
+ t_u8 Reserved17_23 : 7; /* ! Reserved */
+#endif
+} MLAN_PACK_END IEEEtypes_WMM_TSPEC_TS_Info_t;
+
+/** Data structure of WMM TSPEC Nominal Size */
+typedef MLAN_PACK_START struct {
+#ifdef BIG_ENDIAN_SUPPORT
+ t_u16 Fixed : 1; /* ! 1: Fixed size given in Size, 0: Var, size is
+ nominal */
+ t_u16 Size : 15; /* ! Nominal size in octets */
+#else
+ t_u16 Size : 15; /* ! Nominal size in octets */
+ t_u16 Fixed : 1; /* ! 1: Fixed size given in Size, 0: Var, size is
+ nominal */
+#endif
+} MLAN_PACK_END IEEEtypes_WMM_TSPEC_NomMSDUSize_t;
+
+/** Data structure of WMM TSPEC SBWA */
+typedef MLAN_PACK_START struct {
+#ifdef BIG_ENDIAN_SUPPORT
+ t_u16 Whole : 3; /* ! Whole portion */
+ t_u16 Fractional : 13; /* ! Fractional portion */
+#else
+ t_u16 Fractional : 13; /* ! Fractional portion */
+ t_u16 Whole : 3; /* ! Whole portion */
+#endif
+} MLAN_PACK_END IEEEtypes_WMM_TSPEC_SBWA;
+
+/** Data structure of WMM TSPEC Body */
+typedef MLAN_PACK_START struct {
+ IEEEtypes_WMM_TSPEC_TS_Info_t TSInfo;
+ IEEEtypes_WMM_TSPEC_NomMSDUSize_t NomMSDUSize;
+ t_u16 MaximumMSDUSize;
+ t_u32 MinServiceInterval;
+ t_u32 MaxServiceInterval;
+ t_u32 InactivityInterval;
+ t_u32 SuspensionInterval;
+ t_u32 ServiceStartTime;
+ t_u32 MinimumDataRate;
+ t_u32 MeanDataRate;
+ t_u32 PeakDataRate;
+ t_u32 MaxBurstSize;
+ t_u32 DelayBound;
+ t_u32 MinPHYRate;
+ IEEEtypes_WMM_TSPEC_SBWA SurplusBWAllowance;
+ t_u16 MediumTime;
+} MLAN_PACK_END IEEEtypes_WMM_TSPEC_Body_t;
+
+/** Data structure of WMM TSPEC all elements */
+typedef MLAN_PACK_START struct {
+ t_u8 ElementId;
+ t_u8 Len;
+ t_u8 OuiType[4]; /* 00:50:f2:02 */
+ t_u8 OuiSubType; /* 01 */
+ t_u8 Version;
+
+ IEEEtypes_WMM_TSPEC_Body_t TspecBody;
+
+} MLAN_PACK_END IEEEtypes_WMM_TSPEC_t;
+
+/** WMM Action Category values */
+typedef MLAN_PACK_START enum _IEEEtypes_ActionCategory_e {
+
+ IEEE_MGMT_ACTION_CATEGORY_SPECTRUM_MGMT = 0,
+ IEEE_MGMT_ACTION_CATEGORY_QOS = 1,
+ IEEE_MGMT_ACTION_CATEGORY_DLS = 2,
+ IEEE_MGMT_ACTION_CATEGORY_BLOCK_ACK = 3,
+ IEEE_MGMT_ACTION_CATEGORY_PUBLIC = 4,
+ IEEE_MGMT_ACTION_CATEGORY_RADIO_RSRC = 5,
+ IEEE_MGMT_ACTION_CATEGORY_FAST_BSS_TRANS = 6,
+ IEEE_MGMT_ACTION_CATEGORY_HT = 7,
+
+ IEEE_MGMT_ACTION_CATEGORY_WNM = 10,
+ IEEE_MGMT_ACTION_CATEGORY_UNPROTECT_WNM = 11,
+
+ IEEE_MGMT_ACTION_CATEGORY_WMM_TSPEC = 17
+
+} MLAN_PACK_END IEEEtypes_ActionCategory_e;
+
+/** WMM TSPEC operations */
+typedef MLAN_PACK_START enum _IEEEtypes_WMM_Tspec_Action_e {
+
+ TSPEC_ACTION_CODE_ADDTS_REQ = 0,
+ TSPEC_ACTION_CODE_ADDTS_RSP = 1,
+ TSPEC_ACTION_CODE_DELTS = 2,
+
+} MLAN_PACK_END IEEEtypes_WMM_Tspec_Action_e;
+
+/** WMM TSPEC Category Action Base */
+typedef MLAN_PACK_START struct {
+ IEEEtypes_ActionCategory_e category;
+ IEEEtypes_WMM_Tspec_Action_e action;
+ t_u8 dialogToken;
+
+} MLAN_PACK_END IEEEtypes_WMM_Tspec_Action_Base_Tspec_t;
+
+/** WMM TSPEC AddTS request structure */
+typedef MLAN_PACK_START struct {
+ IEEEtypes_WMM_Tspec_Action_Base_Tspec_t tspecAct;
+ t_u8 statusCode;
+ IEEEtypes_WMM_TSPEC_t tspecIE;
+
+ /* Place holder for additional elements after the TSPEC */
+ t_u8 subElem[256];
+
+} MLAN_PACK_END IEEEtypes_Action_WMM_AddTsReq_t;
+
+/** WMM TSPEC AddTS response structure */
+typedef MLAN_PACK_START struct {
+ IEEEtypes_WMM_Tspec_Action_Base_Tspec_t tspecAct;
+ t_u8 statusCode;
+ IEEEtypes_WMM_TSPEC_t tspecIE;
+
+ /* Place holder for additional elements after the TSPEC */
+ t_u8 subElem[256];
+
+} MLAN_PACK_END IEEEtypes_Action_WMM_AddTsRsp_t;
+
+/** WMM TSPEC DelTS structure */
+typedef MLAN_PACK_START struct {
+ IEEEtypes_WMM_Tspec_Action_Base_Tspec_t tspecAct;
+ t_u8 reasonCode;
+ IEEEtypes_WMM_TSPEC_t tspecIE;
+
+} MLAN_PACK_END IEEEtypes_Action_WMM_DelTs_t;
+
+/** union of WMM TSPEC structures */
+typedef MLAN_PACK_START union {
+ IEEEtypes_WMM_Tspec_Action_Base_Tspec_t tspecAct;
+
+ IEEEtypes_Action_WMM_AddTsReq_t addTsReq;
+ IEEEtypes_Action_WMM_AddTsRsp_t addTsRsp;
+ IEEEtypes_Action_WMM_DelTs_t delTs;
+
+} MLAN_PACK_END IEEEtypes_Action_WMMAC_t;
+
+/** union of WMM TSPEC & Action category */
+typedef MLAN_PACK_START union {
+ IEEEtypes_ActionCategory_e category;
+
+ IEEEtypes_Action_WMMAC_t wmmAc;
+
+} MLAN_PACK_END IEEEtypes_ActionFrame_t;
+
+/** Data structure for subband set */
+typedef MLAN_PACK_START struct _IEEEtypes_SubbandSet_t {
+ /** First channel */
+ t_u8 first_chan;
+ /** Number of channels */
+ t_u8 no_of_chan;
+ /** Maximum Tx power in dBm */
+ t_u8 max_tx_pwr;
+} MLAN_PACK_END IEEEtypes_SubbandSet_t, *pIEEEtypes_SubbandSet_t;
+
+#ifdef STA_SUPPORT
+/** Data structure for Country IE */
+typedef MLAN_PACK_START struct _IEEEtypes_CountryInfoSet_t {
+ /** Element ID */
+ t_u8 element_id;
+ /** Length */
+ t_u8 len;
+ /** Country code */
+ t_u8 country_code[COUNTRY_CODE_LEN];
+ /** Set of subbands */
+ IEEEtypes_SubbandSet_t sub_band[1];
+} MLAN_PACK_END IEEEtypes_CountryInfoSet_t, *pIEEEtypes_CountryInfoSet_t;
+
+/** Data structure for Country IE full set */
+typedef MLAN_PACK_START struct _IEEEtypes_CountryInfoFullSet_t {
+ /** Element ID */
+ t_u8 element_id;
+ /** Length */
+ t_u8 len;
+ /** Country code */
+ t_u8 country_code[COUNTRY_CODE_LEN];
+ /** Set of subbands */
+ IEEEtypes_SubbandSet_t sub_band[MRVDRV_MAX_SUBBAND_802_11D];
+} MLAN_PACK_END IEEEtypes_CountryInfoFullSet_t,
+ *pIEEEtypes_CountryInfoFullSet_t;
+
+#endif /* STA_SUPPORT */
+
+/** HT Capabilities Data */
+typedef struct MLAN_PACK_START _HTCap_t {
+ /** HT Capabilities Info field */
+ t_u16 ht_cap_info;
+ /** A-MPDU Parameters field */
+ t_u8 ampdu_param;
+ /** Supported MCS Set field */
+ t_u8 supported_mcs_set[16];
+ /** HT Extended Capabilities field */
+ t_u16 ht_ext_cap;
+ /** Transmit Beamforming Capabilities field */
+ t_u32 tx_bf_cap;
+ /** Antenna Selection Capability field */
+ t_u8 asel;
+} MLAN_PACK_END HTCap_t, *pHTCap_t;
+
+/** HT Information Data */
+typedef struct MLAN_PACK_START _HTInfo_t {
+ /** Primary channel */
+ t_u8 pri_chan;
+ /** Field 2 */
+ t_u8 field2;
+ /** Field 3 */
+ t_u16 field3;
+ /** Field 4 */
+ t_u16 field4;
+ /** Bitmap indicating MCSs supported by all HT STAs in the BSS */
+ t_u8 basic_mcs_set[16];
+} MLAN_PACK_END HTInfo_t, *pHTInfo_t;
+
+/** 20/40 BSS Coexistence Data */
+typedef struct MLAN_PACK_START _BSSCo2040_t {
+ /** 20/40 BSS Coexistence value */
+ t_u8 bss_co_2040_value;
+} MLAN_PACK_END BSSCo2040_t, *pBSSCo2040_t;
+
+#define MAX_DSCP_EXCEPTION_NUM 21
+/** DSCP Range */
+typedef struct MLAN_PACK_START _DSCP_Exception_t {
+ /* DSCP value 0 to 63 or ff */
+ t_u8 dscp_value;
+ /* user priority 0-7*/
+ t_u8 user_priority;
+} MLAN_PACK_END DSCP_Exception_t, *pDSCP_Exception_t;
+
+/** DSCP Range */
+typedef struct MLAN_PACK_START _DSCP_Range_t {
+ /* DSCP low value */
+ t_u8 dscp_low_value;
+ /* DSCP high value */
+ t_u8 dscp_high_value;
+} MLAN_PACK_END DSCP_Range_t, *pDSCP_Range_t;
+
+/** Overlapping BSS Scan Parameters Data */
+typedef struct MLAN_PACK_START _OverlapBSSScanParam_t {
+ /** OBSS Scan Passive Dwell in milliseconds */
+ t_u16 obss_scan_passive_dwell;
+ /** OBSS Scan Active Dwell in milliseconds */
+ t_u16 obss_scan_active_dwell;
+ /** BSS Channel Width Trigger Scan Interval in seconds */
+ t_u16 bss_chan_width_trigger_scan_int;
+ /** OBSS Scan Passive Total Per Channel */
+ t_u16 obss_scan_passive_total;
+ /** OBSS Scan Active Total Per Channel */
+ t_u16 obss_scan_active_total;
+ /** BSS Width Channel Transition Delay Factor */
+ t_u16 bss_width_chan_trans_delay;
+ /** OBSS Scan Activity Threshold */
+ t_u16 obss_scan_active_threshold;
+} MLAN_PACK_END OBSSScanParam_t, *pOBSSScanParam_t;
+
+/** HT Capabilities IE */
+typedef MLAN_PACK_START struct _IEEEtypes_HTCap_t {
+ /** Generic IE header */
+ IEEEtypes_Header_t ieee_hdr;
+ /** HTCap struct */
+ HTCap_t ht_cap;
+} MLAN_PACK_END IEEEtypes_HTCap_t, *pIEEEtypes_HTCap_t;
+
+/** HT Information IE */
+typedef MLAN_PACK_START struct _IEEEtypes_HTInfo_t {
+ /** Generic IE header */
+ IEEEtypes_Header_t ieee_hdr;
+ /** HTInfo struct */
+ HTInfo_t ht_info;
+} MLAN_PACK_END IEEEtypes_HTInfo_t, *pIEEEtypes_HTInfo_t;
+
+/** 20/40 BSS Coexistence IE */
+typedef MLAN_PACK_START struct _IEEEtypes_2040BSSCo_t {
+ /** Generic IE header */
+ IEEEtypes_Header_t ieee_hdr;
+ /** BSSCo2040_t struct */
+ BSSCo2040_t bss_co_2040;
+} MLAN_PACK_END IEEEtypes_2040BSSCo_t, *pIEEEtypes_2040BSSCo_t;
+
+/** Extended Capabilities IE */
+typedef MLAN_PACK_START struct _IEEEtypes_ExtCap_t {
+ /** Generic IE header */
+ IEEEtypes_Header_t ieee_hdr;
+ /** ExtCap_t struct */
+ ExtCap_t ext_cap;
+} MLAN_PACK_END IEEEtypes_ExtCap_t, *pIEEEtypes_ExtCap_t;
+
+/** Overlapping BSS Scan Parameters IE */
+typedef MLAN_PACK_START struct _IEEEtypes_OverlapBSSScanParam_t {
+ /** Generic IE header */
+ IEEEtypes_Header_t ieee_hdr;
+ /** OBSSScanParam_t struct */
+ OBSSScanParam_t obss_scan_param;
+} MLAN_PACK_END IEEEtypes_OverlapBSSScanParam_t,
+ *pIEEEtypes_OverlapBSSScanParam_t;
+
+/** VHT MCS rate set field, refer to 802.11ac */
+typedef MLAN_PACK_START struct _VHT_MCS_set {
+ t_u16 rx_mcs_map;
+ t_u16 rx_max_rate; /* bit 29-31 reserved */
+ t_u16 tx_mcs_map;
+ t_u16 tx_max_rate; /* bit 61-63 reserved */
+} MLAN_PACK_END VHT_MCS_set_t, *pVHT_MCS_set_t;
+
+/** VHT Capabilities info field, reference 802.11ac D1.4 p89 */
+typedef MLAN_PACK_START struct _VHT_capa {
+#if 0
+#ifdef BIG_ENDIAN_SUPPORT
+ t_u8 mpdu_max_len:2;
+ t_u8 chan_width:2;
+ t_u8 rx_LDPC:1;
+ t_u8 sgi_80:1;
+ t_u8 sgi_160:1;
+ t_u8 tx_STBC:1;
+ t_u8 rx_STBC:3;
+ t_u8 SU_beamformer_capa:1;
+ t_u8 SU_beamformee_capa:1;
+ t_u8 beamformer_ante_num:3;
+ t_u8 sounding_dim_num:3;
+ t_u8 MU_beamformer_capa:1;
+ t_u8 MU_beamformee_capa:1;
+ t_u8 VHT_TXOP_ps:1;
+ t_u8 HTC_VHT_capa:1;
+ t_u8 max_ampdu_len:3;
+ t_u8 link_apapt_capa:2;
+ t_u8 reserved_1:4;
+#else
+ t_u8 reserved_1:4;
+ t_u8 link_apapt_capa:2;
+ t_u8 max_ampdu_len:3;
+ t_u8 HTC_VHT_capa:1;
+ t_u8 VHT_TXOP_ps:1;
+ t_u8 MU_beamformee_capa:1;
+ t_u8 MU_beamformer_capa:1;
+ t_u8 sounding_dim_num:3;
+ t_u8 beamformer_ante_num:3;
+ t_u8 SU_beamformee_capa:1;
+ t_u8 SU_beamformer_capa:1;
+ t_u8 rx_STBC:3;
+ t_u8 tx_STBC:1;
+ t_u8 sgi_160:1;
+ t_u8 sgi_80:1;
+ t_u8 rx_LDPC:1;
+ t_u8 chan_width:2;
+ t_u8 mpdu_max_len:2;
+#endif /* BIG_ENDIAN_SUPPORT */
+#endif
+ t_u32 vht_cap_info;
+ VHT_MCS_set_t mcs_sets;
+} MLAN_PACK_END VHT_capa_t, *pVHT_capa_t;
+
+/** VHT Capabilities IE */
+typedef MLAN_PACK_START struct _IEEEtypes_VHTCap_t {
+ /** Generic IE header */
+ IEEEtypes_Header_t ieee_hdr;
+ VHT_capa_t vht_cap;
+} MLAN_PACK_END IEEEtypes_VHTCap_t, *pIEEEtypes_VHTCap_t;
+
+#define VHT_CAP_CHWD_80MHZ 0
+#define VHT_CAP_CHWD_160MHZ 1
+#define VHT_CAP_CHWD_80_80MHZ 2
+
+/** VHT Operations IE */
+typedef MLAN_PACK_START struct _IEEEtypes_VHTOprat_t {
+ /** Generic IE header */
+ IEEEtypes_Header_t ieee_hdr;
+ t_u8 chan_width;
+ t_u8 chan_center_freq_1;
+ t_u8 chan_center_freq_2;
+ /** Basic MCS set map, each 2 bits stands for a Nss */
+ t_u16 basic_MCS_map;
+} MLAN_PACK_END IEEEtypes_VHTOprat_t, *pIEEEtypes_VHTOprat_t;
+
+#define VHT_OPER_CHWD_20_40MHZ 0
+#define VHT_OPER_CHWD_80MHZ 1
+#define VHT_OPER_CHWD_160MHZ 2
+#define VHT_OPER_CHWD_80_80MHZ 3
+
+/** VHT Transmit Power Envelope IE */
+typedef MLAN_PACK_START struct _IEEEtypes_VHTtxpower_t {
+ /** Generic IE header */
+ IEEEtypes_Header_t ieee_hdr;
+ t_u8 max_tx_power;
+ t_u8 chan_center_freq;
+ t_u8 chan_width;
+} MLAN_PACK_END IEEEtypes_VHTtxpower_t, *pIEEEtypes_VHTtxpower_t;
+
+/** Extended Power Constraint IE */
+typedef MLAN_PACK_START struct _IEEEtypes_ExtPwerCons_t {
+ /** Generic IE header */
+ IEEEtypes_Header_t ieee_hdr;
+ /** channel width */
+ t_u8 chan_width;
+ /** local power constraint */
+ t_u8 local_power_cons;
+} MLAN_PACK_END IEEEtypes_ExtPwerCons_t, *pIEEEtypes_ExtPwerCons_t;
+
+/** Extended BSS Load IE */
+typedef MLAN_PACK_START struct _IEEEtypes_ExtBSSload_t {
+ /** Generic IE header */
+ IEEEtypes_Header_t ieee_hdr;
+ t_u8 MU_MIMO_capa_count;
+ t_u8 stream_underutilization;
+ t_u8 VHT40_util;
+ t_u8 VHT80_util;
+ t_u8 VHT160_util;
+} MLAN_PACK_END IEEEtypes_ExtBSSload_t, *pIEEEtypes_ExtBSSload_t;
+
+/** Quiet Channel IE */
+typedef MLAN_PACK_START struct _IEEEtypes_QuietChan_t {
+ /** Generic IE header */
+ IEEEtypes_Header_t ieee_hdr;
+ t_u8 AP_quiet_mode;
+ t_u8 quiet_count;
+ t_u8 quiet_period;
+ t_u16 quiet_dur;
+ t_u16 quiet_offset;
+} MLAN_PACK_END IEEEtypes_QuietChan_t, *pIEEEtypes_QuietChan_t;
+
+/** Wide Bandwidth Channel Switch IE */
+typedef MLAN_PACK_START struct _IEEEtypes_BWSwitch_t {
+ /** Generic IE header */
+ IEEEtypes_Header_t ieee_hdr;
+ t_u8 new_chan_width;
+ t_u8 new_chan_center_freq_1;
+ t_u8 new_chan_center_freq_2;
+} MLAN_PACK_END IEEEtypes_BWSwitch_t, *pIEEEtypes_BWSwitch_t;
+
+/** AID IE */
+typedef MLAN_PACK_START struct _IEEEtypes_AID_t {
+ /** Generic IE header */
+ IEEEtypes_Header_t ieee_hdr;
+ /** AID number */
+ t_u16 AID;
+} MLAN_PACK_END IEEEtypes_AID_t, *pIEEEtypes_AID_t;
+
+/** Operating Mode Notificaton IE */
+typedef MLAN_PACK_START struct _IEEEtypes_OperModeNtf_t {
+ /** Generic IE header */
+ IEEEtypes_Header_t ieee_hdr;
+ /** Operating Mode */
+ t_u8 oper_mode;
+} MLAN_PACK_END IEEEtypes_OperModeNtf_t, *pIEEEtypes_OperModeNtf_t;
+
+typedef MLAN_PACK_START struct _IEEEtypes_Extension_t {
+ /** Generic IE header */
+ IEEEtypes_Header_t ieee_hdr;
+ /** Element id extension */
+ t_u8 ext_id;
+ /** payload */
+ t_u8 data[];
+} MLAN_PACK_END IEEEtypes_Extension_t, *pIEEEtypes_Extension_t;
+
+typedef MLAN_PACK_START struct _IEEEtypes_HECap_t {
+ /** Generic IE header */
+ IEEEtypes_Header_t ieee_hdr;
+ /** Element id extension */
+ t_u8 ext_id;
+ /** he mac capability info */
+ t_u8 he_mac_cap[6];
+ /** he phy capability info */
+ t_u8 he_phy_cap[11];
+ /** he txrx mcs support , size would be 4 or 8 or 12 */
+ t_u8 he_txrx_mcs_support[4];
+ /** PPE Thresholds (optional) */
+} MLAN_PACK_END IEEEtypes_HECap_t, *pIEEEtypes_HECap_t;
+
+/** Maximum number of subbands in the IEEEtypes_SupportedChannels_t structure */
+#define WLAN_11H_MAX_SUBBANDS 5
+
+/** Maximum number of DFS channels configured in IEEEtypes_IBSS_DFS_t */
+#define WLAN_11H_MAX_IBSS_DFS_CHANNELS 25
+
+/** IEEE Power Constraint element (7.3.2.15) */
+typedef MLAN_PACK_START struct {
+ t_u8 element_id; /**< IEEE Element ID = 32 */
+ t_u8 len; /**< Element length after id and len */
+ t_u8 local_constraint; /**< Local power constraint applied to 11d
+ chan info */
+} MLAN_PACK_END IEEEtypes_PowerConstraint_t;
+
+/** IEEE Power Capability element (7.3.2.16) */
+typedef MLAN_PACK_START struct {
+ t_u8 element_id; /**< IEEE Element ID = 33 */
+ t_u8 len; /**< Element length after id and len */
+ t_s8 min_tx_power_capability; /**< Minimum Transmit power (dBm) */
+ t_s8 max_tx_power_capability; /**< Maximum Transmit power (dBm) */
+} MLAN_PACK_END IEEEtypes_PowerCapability_t;
+
+/** IEEE TPC Report element (7.3.2.18) */
+typedef MLAN_PACK_START struct {
+ t_u8 element_id; /**< IEEE Element ID = 35 */
+ t_u8 len; /**< Element length after id and len */
+ t_s8 tx_power; /**< Max power used to transmit the TPC Report frame
+ (dBm) */
+ t_s8 link_margin; /**< Link margin when TPC Request received (dB) */
+} MLAN_PACK_END IEEEtypes_TPCReport_t;
+
+/* IEEE Supported Channel sub-band description (7.3.2.19) */
+/**
+ * Sub-band description used in the supported channels element.
+ */
+typedef MLAN_PACK_START struct {
+ t_u8 start_chan; /**< Starting channel in the subband */
+ t_u8 num_chans; /**< Number of channels in the subband */
+
+} MLAN_PACK_END IEEEtypes_SupportChan_Subband_t;
+
+/* IEEE Supported Channel element (7.3.2.19) */
+/**
+ * Sent in association requests. Details the sub-bands and number
+ * of channels supported in each subband
+ */
+typedef MLAN_PACK_START struct {
+ t_u8 element_id; /**< IEEE Element ID = 36 */
+ t_u8 len; /**< Element length after id and len */
+
+ /** Configured sub-bands information in the element */
+ IEEEtypes_SupportChan_Subband_t subband[WLAN_11H_MAX_SUBBANDS];
+
+} MLAN_PACK_END IEEEtypes_SupportedChannels_t;
+
+/** default channel switch count */
+#define DEF_CHAN_SWITCH_COUNT 5
+
+/* IEEE Channel Switch Announcement Element (7.3.2.20) */
+/**
+ * Provided in beacons and probe responses. Used to advertise when
+ * and to which channel it is changing to. Only starting STAs in
+ * an IBSS and APs are allowed to originate a chan switch element.
+ */
+typedef MLAN_PACK_START struct {
+ t_u8 element_id; /**< IEEE Element ID = 37 */
+ t_u8 len; /**< Element length after id and len */
+ t_u8 chan_switch_mode; /**< STA should not transmit any frames if 1 */
+ t_u8 new_channel_num; /**< Channel # that AP/IBSS is moving to */
+ t_u8 chan_switch_count; /**< # of TBTTs before channel switch */
+
+} MLAN_PACK_END IEEEtypes_ChanSwitchAnn_t;
+
+/** data structure for extended channel switch */
+typedef MLAN_PACK_START struct {
+ /** IEEE element ID = 60 */
+ t_u8 element_id;
+ /** Element length after id and len, set to 4 */
+ t_u8 len;
+ /** STA should not transmit any frames if 1 */
+ t_u8 chan_switch_mode;
+ /** Operate class # that AP/IBSS is moving to */
+ t_u8 new_oper_class;
+ /** Channel # that AP/IBSS is moving to */
+ t_u8 new_channel_num;
+ /** of TBTTs before channel switch */
+ t_u8 chan_switch_count;
+} MLAN_PACK_END IEEEtypes_ExtChanSwitchAnn_t;
+
+/* IEEE Wide Bandwidth Channel Switch Element */
+/**
+ * Provided in beacons and probe responses. Used to advertise when
+ * and to which channel it is changing to. Only starting STAs in
+ * an IBSS and APs are allowed to originate a wide bandwidth chan
+ * switch element.
+ */
+typedef MLAN_PACK_START struct {
+ /** Generic IE header IEEE Element ID = 194*/
+ IEEEtypes_Header_t ieee_hdr;
+ t_u8 new_channel_width;
+ t_u8 new_channel_center_freq0;
+ t_u8 new_channel_center_freq1;
+} MLAN_PACK_END IEEEtypes_WideBWChanSwitch_t;
+
+/* IEEE VHT Transmit Power Envelope Element */
+/**
+ * Provided in beacons and probe responses. Used to advertise the max
+ * TX power in sepeate bandwidth and as a sub element of Channel Switch
+ * Wrapper IE.
+ */
+typedef MLAN_PACK_START struct {
+ /** Generic IE header IEEE Element ID = 195*/
+ IEEEtypes_Header_t ieee_hdr;
+ t_u8 tpc_info; /**< Transmit Power Information>*/
+ t_u8 local_max_tp_20mhz; /**< Local Maximum Transmit Power for 20 MHZ>*/
+ t_u8 local_max_tp_40mhz; /**< Local Maximum Transmit Power for 40 MHZ>*/
+ t_u8 local_max_tp_80mhz; /**< Local Maximum Transmit Power for 80 MHZ>*/
+} MLAN_PACK_END IEEEtypes_VhtTpcEnvelope_t;
+
+/* IEEE Quiet Period Element (7.3.2.23) */
+/**
+ * Provided in beacons and probe responses. Indicates times during
+ * which the STA should not be transmitting data. Only starting STAs in
+ * an IBSS and APs are allowed to originate a quiet element.
+ */
+typedef MLAN_PACK_START struct {
+ t_u8 element_id; /**< IEEE Element ID = 40 */
+ t_u8 len; /**< Element length after id and len */
+ t_u8 quiet_count; /**< Number of TBTTs until beacon with the quiet
+ period */
+ t_u8 quiet_period; /**< Regular quiet period, # of TBTTS between periods
+ */
+ t_u16 quiet_duration; /**< Duration of the quiet period in TUs */
+ t_u16 quiet_offset; /**< Offset in TUs from the TBTT for the quiet
+ period */
+
+} MLAN_PACK_END IEEEtypes_Quiet_t;
+
+/**
+*** @brief Map octet of the basic measurement report (7.3.2.22.1)
+**/
+typedef MLAN_PACK_START struct {
+#ifdef BIG_ENDIAN_SUPPORT
+ /**< Reserved */
+ t_u8 rsvd5_7 : 3;
+ /**< Channel is unmeasured */
+ t_u8 unmeasured : 1;
+ /**< Radar detected on channel */
+ t_u8 radar : 1;
+ /**< Unidentified signal found on channel */
+ t_u8 unidentified_sig : 1;
+ /**< OFDM preamble detected on channel */
+ t_u8 ofdm_preamble : 1;
+ /**< At least one valid MPDU received on channel */
+ t_u8 bss : 1;
+#else
+ /**< At least one valid MPDU received on channel */
+ t_u8 bss : 1;
+ /**< OFDM preamble detected on channel */
+ t_u8 ofdm_preamble : 1;
+ /**< Unidentified signal found on channel */
+ t_u8 unidentified_sig : 1;
+ /**< Radar detected on channel */
+ t_u8 radar : 1;
+ /**< Channel is unmeasured */
+ t_u8 unmeasured : 1;
+ /**< Reserved */
+ t_u8 rsvd5_7 : 3;
+#endif /* BIG_ENDIAN_SUPPORT */
+
+} MLAN_PACK_END MeasRptBasicMap_t;
+
+/* IEEE DFS Channel Map field (7.3.2.24) */
+/**
+ * Used to list supported channels and provide a octet "map" field which
+ * contains a basic measurement report for that channel in the
+ * IEEEtypes_IBSS_DFS_t element
+ */
+typedef MLAN_PACK_START struct {
+ t_u8 channel_number; /**< Channel number */
+ MeasRptBasicMap_t rpt_map; /**< Basic measurement report for the channel
+ */
+
+} MLAN_PACK_END IEEEtypes_ChannelMap_t;
+
+/* IEEE IBSS DFS Element (7.3.2.24) */
+/**
+ * IBSS DFS element included in ad hoc beacons and probe responses.
+ * Provides information regarding the IBSS DFS Owner as well as the
+ * originating STAs supported channels and basic measurement results.
+ */
+typedef MLAN_PACK_START struct {
+ t_u8 element_id; /**< IEEE Element ID = 41 */
+ t_u8 len; /**< Element length after id and len */
+ t_u8 dfs_owner[MLAN_MAC_ADDR_LENGTH]; /**< DFS Owner STA Address */
+ t_u8 dfs_recovery_interval; /**< DFS Recovery time in TBTTs */
+
+ /** Variable length map field, one Map entry for each supported channel
+ */
+ IEEEtypes_ChannelMap_t channel_map[WLAN_11H_MAX_IBSS_DFS_CHANNELS];
+
+} MLAN_PACK_END IEEEtypes_IBSS_DFS_t;
+
+/* 802.11h BSS information kept for each BSSID received in scan results */
+/**
+ * IEEE BSS information needed from scan results for later processing in
+ * join commands
+ */
+typedef struct {
+ t_u8 sensed_11h; /**< Capability bit set or 11h IE found in this BSS */
+
+ IEEEtypes_PowerConstraint_t power_constraint; /**< Power Constraint IE
+ */
+ IEEEtypes_PowerCapability_t power_capability; /**< Power Capability IE
+ */
+ IEEEtypes_TPCReport_t tpc_report; /**< TPC Report IE */
+ IEEEtypes_ChanSwitchAnn_t chan_switch_ann; /**< Channel Switch
+ Announcement IE */
+ IEEEtypes_Quiet_t quiet; /**< Quiet IE */
+ IEEEtypes_IBSS_DFS_t ibss_dfs; /**< IBSS DFS Element IE */
+
+} wlan_11h_bss_info_t;
+
+/** action code for 20/40 BSS Coexsitence Management frame */
+#define BSS_20_40_COEX 0
+
+#ifdef STA_SUPPORT
+/** Macro for maximum size of scan response buffer */
+#define MAX_SCAN_RSP_BUF (16 * 1024)
+
+/** Maximum number of channels that can be sent in user scan config */
+#define WLAN_USER_SCAN_CHAN_MAX 50
+/** Maximum length of SSID list */
+#define MRVDRV_MAX_SSID_LIST_LENGTH 10
+
+/** Maximum length of BSSID list */
+#define MAX_BSSID_FILTER_LIST 5
+
+/** Scan all the channels in specified band */
+#define BAND_SPECIFIED 0x80
+
+/**
+ * IOCTL SSID List sub-structure sent in wlan_ioctl_user_scan_cfg
+ *
+ * Used to specify SSID specific filters as well as SSID pattern matching
+ * filters for scan result processing in firmware.
+ */
+typedef MLAN_PACK_START struct _wlan_user_scan_ssid {
+ /** SSID */
+ t_u8 ssid[MLAN_MAX_SSID_LENGTH + 1];
+ /** Maximum length of SSID */
+ t_u8 max_len;
+} MLAN_PACK_END wlan_user_scan_ssid;
+
+/**
+ * @brief IOCTL channel sub-structure sent in wlan_ioctl_user_scan_cfg
+ *
+ * Multiple instances of this structure are included in the IOCTL command
+ * to configure a instance of a scan on the specific channel.
+ */
+typedef MLAN_PACK_START struct _wlan_user_scan_chan {
+ /** Channel Number to scan */
+ t_u8 chan_number;
+ /** Radio type: 'B/G' Band = 0, 'A' Band = 1 */
+ t_u8 radio_type;
+ /** Scan type: Active = 1, Passive = 2 */
+ t_u8 scan_type;
+ /** Reserved */
+ t_u8 reserved;
+ /** Scan duration in milliseconds; if 0 default used */
+ t_u32 scan_time;
+} MLAN_PACK_END wlan_user_scan_chan;
+
+/** channel statictics */
+typedef MLAN_PACK_START struct _ChanStatistics_t {
+ /** channle number */
+ t_u8 chan_num;
+ /** band info */
+ Band_Config_t bandcfg;
+ /** flags */
+ t_u8 flags;
+ /** noise */
+ t_s8 noise;
+ /** total network */
+ t_u16 total_networks;
+ /** scan duration */
+ t_u16 cca_scan_duration;
+ /** busy duration */
+ t_u16 cca_busy_duration;
+ /** min rss */
+ t_u8 min_rss;
+ /** max rssi */
+ t_u8 max_rss;
+} MLAN_PACK_END ChanStatistics_t;
+
+/** Enhance ext scan type defination */
+typedef enum _MLAN_EXT_SCAN_TYPE {
+ EXT_SCAN_DEFAULT,
+ EXT_SCAN_ENHANCE,
+ EXT_SCAN_CANCEL,
+} MLAN_EXT_SCAN_TYPE;
+
+/**
+ * Input structure to configure an immediate scan cmd to firmware
+ *
+ * Specifies a number of parameters to be used in general for the scan
+ * as well as a channel list (wlan_user_scan_chan) for each scan period
+ * desired.
+ */
+typedef MLAN_PACK_START struct {
+ /**
+ * Flag set to keep the previous scan table intact
+ *
+ * If set, the scan results will accumulate, replacing any previous
+ * matched entries for a BSS with the new scan data
+ */
+ t_u8 keep_previous_scan;
+ /**
+ * BSS mode to be sent in the firmware command
+ *
+ * Field can be used to restrict the types of networks returned in the
+ * scan. Valid settings are:
+ *
+ * - MLAN_SCAN_MODE_BSS (infrastructure)
+ * - MLAN_SCAN_MODE_IBSS (adhoc)
+ * - MLAN_SCAN_MODE_ANY (unrestricted, adhoc and infrastructure)
+ */
+ t_u8 bss_mode;
+ /**
+ * Configure the number of probe requests for active chan scans
+ */
+ t_u8 num_probes;
+ /**
+ * @brief ssid filter flag
+ */
+ t_u8 ssid_filter;
+ /**
+ * @brief BSSID filter sent in the firmware command to limit the
+ * results
+ */
+ t_u8 specific_bssid[MLAN_MAC_ADDR_LENGTH];
+ /**
+ * SSID filter list used in the to limit the scan results
+ */
+ wlan_user_scan_ssid ssid_list[MRVDRV_MAX_SSID_LIST_LENGTH];
+ /**
+ * Variable number (fixed maximum) of channels to scan up
+ */
+ wlan_user_scan_chan chan_list[WLAN_USER_SCAN_CHAN_MAX];
+ /** scan channel gap */
+ t_u16 scan_chan_gap;
+ /** scan type: 0 legacy, 1: enhance scan*/
+ t_u8 ext_scan_type;
+ /** flag to filer only probe response */
+ t_u8 proberesp_only;
+ t_u8 random_mac[MLAN_MAC_ADDR_LENGTH];
+ /** Number of BSSIDs to be filtered */
+ t_u8 bssid_num;
+ /** BSSID filter list used in the to limit the scan results */
+ mlan_802_11_mac_addr bssid_list[MAX_BSSID_FILTER_LIST];
+} MLAN_PACK_END wlan_user_scan_cfg;
+
+/** Default scan interval in millisecond*/
+#define DEFAULT_BGSCAN_INTERVAL 30000
+
+/** action get all, except pps/uapsd config */
+#define BG_SCAN_ACT_GET 0x0000
+/** action set all, except pps/uapsd config */
+#define BG_SCAN_ACT_SET 0x0001
+/** action get pps/uapsd config */
+#define BG_SCAN_ACT_GET_PPS_UAPSD 0x0100
+/** action set pps/uapsd config */
+#define BG_SCAN_ACT_SET_PPS_UAPSD 0x0101
+/** action set all */
+#define BG_SCAN_ACT_SET_ALL 0xff01
+/** ssid match */
+#define BG_SCAN_SSID_MATCH 0x0001
+/** ssid match and RSSI exceeded */
+#define BG_SCAN_SSID_RSSI_MATCH 0x0004
+/**wait for all channel scan to complete to report scan result*/
+#define BG_SCAN_WAIT_ALL_CHAN_DONE 0x80000000
+/** Maximum number of channels that can be sent in bg scan config */
+#define WLAN_BG_SCAN_CHAN_MAX 38
+
+/** Enumeration definition */
+/** EES MODE */
+typedef enum {
+ /** EES MODE: LOW */
+ EES_MODE_LOW = 0,
+ /** EES MODE: MID */
+ EES_MODE_MID,
+ /** EES MODE: HIGH */
+ EES_MODE_HIGH,
+ /** EES MODE: OFF */
+ EES_MODE_OFF,
+ /** EES MODE: LOOP */
+ EES_MODE_LOOP = 15,
+} ees_modes;
+
+/** EES Maximum SSID */
+#define EES_MAX_SSIDS 2
+
+/** ees_ssid_config */
+typedef MLAN_PACK_START struct {
+ /** SSID */
+ t_u8 ssid[MLAN_MAX_SSID_LENGTH + 1];
+ /** Maximum length of SSID */
+ t_u8 max_len;
+ /** PairCipher */
+ t_u8 pair_cipher;
+ /** GroupCipher */
+ t_u8 group_cipher;
+} MLAN_PACK_END ees_ssid_config;
+
+/**
+ * Input structure to configure bs scan cmd to firmware
+ */
+typedef MLAN_PACK_START struct {
+ /** action */
+ t_u16 action;
+ /** enable/disable */
+ t_u8 enable;
+ /** BSS type:
+ * MLAN_SCAN_MODE_BSS (infrastructure)
+ * MLAN_SCAN_MODE_IBSS (adhoc)
+ * MLAN_SCAN_MODE_ANY (unrestricted, adhoc and infrastructure)
+ */
+ t_u8 bss_type;
+ /** number of channel scanned during each scan */
+ t_u8 chan_per_scan;
+ /** interval between consecutive scan */
+ t_u32 scan_interval;
+ /** bit 0: ssid match bit 1: ssid match and SNR exceeded
+ * bit 2: ssid match and RSSI exceeded
+ * bit 31: wait for all channel scan to complete to report scan result
+ */
+ t_u32 report_condition;
+ /* Configure the number of probe requests for active chan scans */
+ t_u8 num_probes;
+ /** RSSI threshold */
+ t_u8 rssi_threshold;
+ /** SNR threshold */
+ t_u8 snr_threshold;
+ /** repeat count */
+ t_u16 repeat_count;
+ /** start later flag */
+ t_u16 start_later;
+ /** SSID filter list used in the to limit the scan results */
+ wlan_user_scan_ssid ssid_list[MRVDRV_MAX_SSID_LIST_LENGTH];
+ /** Variable number (fixed maximum) of channels to scan up */
+ wlan_user_scan_chan chan_list[WLAN_BG_SCAN_CHAN_MAX];
+ /** scan channel gap */
+ t_u16 scan_chan_gap;
+ /** Enable EES configuration */
+ t_u8 config_ees;
+ /** EES scan mode */
+ t_u16 ees_mode;
+ /** EES report condition */
+ t_u16 report_cond;
+ /** EES High Period scan interval */
+ t_u16 high_period;
+ /** EES High Period scan count */
+ t_u16 high_period_count;
+ /** EES Medium Period scan interval */
+ t_u16 mid_period;
+ /** EES Medium Period scan count */
+ t_u16 mid_period_count;
+ /** EES Low Period scan interval */
+ t_u16 low_period;
+ /** EES Low Period scan count */
+ t_u16 low_period_count;
+ /** Number of networks in the list */
+ t_u8 network_count;
+ /** Maximum number of connection count */
+ t_u8 max_conn_count;
+ /** Black List Exp */
+ t_u8 black_list_exp;
+ /** Array of ees config struct */
+ ees_ssid_config ees_ssid_cfg[EES_MAX_SSIDS];
+ t_u8 random_mac[MLAN_MAC_ADDR_LENGTH];
+} MLAN_PACK_END wlan_bgscan_cfg;
+#endif /* STA_SUPPORT */
+
+#ifdef PRAGMA_PACK
+#pragma pack(pop)
+#endif
+
+/** BSSDescriptor_t
+ * Structure used to store information for beacon/probe response
+ */
+typedef struct _BSSDescriptor_t {
+ /** MAC address */
+ mlan_802_11_mac_addr mac_address;
+
+ /** SSID */
+ mlan_802_11_ssid ssid;
+
+ /** WEP encryption requirement */
+ t_u32 privacy;
+
+ /** Receive signal strength in dBm */
+ t_s32 rssi;
+ /** channel load */
+ t_u8 chan_load;
+ /** Channel */
+ t_u32 channel;
+
+ /** Freq */
+ t_u32 freq;
+
+ /** Beacon period */
+ t_u16 beacon_period;
+
+ /** ATIM window */
+ t_u32 atim_window;
+
+ /** ERP flags */
+ t_u8 erp_flags;
+
+ /** Type of network in use */
+ WLAN_802_11_NETWORK_TYPE network_type_use;
+
+ /** Network infrastructure mode */
+ t_u32 bss_mode;
+
+ /** Network supported rates */
+ WLAN_802_11_RATES supported_rates;
+
+ /** Supported data rates */
+ t_u8 data_rates[WLAN_SUPPORTED_RATES];
+
+ /** Current channel bandwidth
+ * 0 : 20MHZ
+ * 1 : 40MHZ
+ * 2 : 80MHZ
+ * 3 : 160MHZ
+ */
+ t_u8 curr_bandwidth;
+
+ /** Network band.
+ * BAND_B(0x01): 'b' band
+ * BAND_G(0x02): 'g' band
+ * BAND_A(0X04): 'a' band
+ */
+ t_u16 bss_band;
+
+ /** TSF timestamp from the current firmware TSF */
+ t_u64 network_tsf;
+
+ /** TSF value included in the beacon/probe response */
+ t_u8 time_stamp[8];
+
+ /** PHY parameter set */
+ IEEEtypes_PhyParamSet_t phy_param_set;
+
+ /** SS parameter set */
+ IEEEtypes_SsParamSet_t ss_param_set;
+
+ /** Capability information */
+ IEEEtypes_CapInfo_t cap_info;
+
+ /** WMM IE */
+ IEEEtypes_WmmParameter_t wmm_ie;
+
+ /** 802.11h BSS information */
+ wlan_11h_bss_info_t wlan_11h_bss_info;
+
+ /** Indicate disabling 11n when associate with AP */
+ t_u8 disable_11n;
+ /** 802.11n BSS information */
+ /** HT Capabilities IE */
+ IEEEtypes_HTCap_t *pht_cap;
+ /** HT Capabilities Offset */
+ t_u16 ht_cap_offset;
+ /** HT Information IE */
+ IEEEtypes_HTInfo_t *pht_info;
+ /** HT Information Offset */
+ t_u16 ht_info_offset;
+ /** 20/40 BSS Coexistence IE */
+ IEEEtypes_2040BSSCo_t *pbss_co_2040;
+ /** 20/40 BSS Coexistence Offset */
+ t_u16 bss_co_2040_offset;
+ /** Extended Capabilities IE */
+ IEEEtypes_ExtCap_t *pext_cap;
+ /** Extended Capabilities Offset */
+ t_u16 ext_cap_offset;
+ /** Overlapping BSS Scan Parameters IE */
+ IEEEtypes_OverlapBSSScanParam_t *poverlap_bss_scan_param;
+ /** Overlapping BSS Scan Parameters Offset */
+ t_u16 overlap_bss_offset;
+
+ /** VHT Capabilities IE */
+ IEEEtypes_VHTCap_t *pvht_cap;
+ /** VHT Capabilities IE offset */
+ t_u16 vht_cap_offset;
+ /** VHT Operations IE */
+ IEEEtypes_VHTOprat_t *pvht_oprat;
+ /** VHT Operations IE offset */
+ t_u16 vht_oprat_offset;
+ /** VHT Transmit Power Envelope IE */
+ IEEEtypes_VHTtxpower_t *pvht_txpower;
+ /** VHT Transmit Power Envelope IE offset */
+ t_u16 vht_txpower_offset;
+ /** Extended Power Constraint IE */
+ IEEEtypes_ExtPwerCons_t *pext_pwer;
+ /** Extended Power Constraint IE offset */
+ t_u16 ext_pwer_offset;
+ /** Extended BSS Load IE */
+ IEEEtypes_ExtBSSload_t *pext_bssload;
+ /** Extended BSS Load IE offset */
+ t_u16 ext_bssload_offset;
+ /** Quiet Channel IE */
+ IEEEtypes_QuietChan_t *pquiet_chan;
+ /** Quiet Channel IE offset */
+ t_u16 quiet_chan_offset;
+ /** Operating Mode Notification IE */
+ IEEEtypes_OperModeNtf_t *poper_mode;
+ /** Operating Mode Notification IE offset */
+ t_u16 oper_mode_offset;
+ /** HE Capability IE */
+ IEEEtypes_HECap_t *phe_cap;
+ /** HE Capability IE offset */
+ t_u16 he_cap_offset;
+ /** HE operation IE */
+ IEEEtypes_Extension_t *phe_oprat;
+ /** HE operation IE offset */
+ t_u16 he_oprat_offset;
+#ifdef STA_SUPPORT
+ /** Country information set */
+ IEEEtypes_CountryInfoFullSet_t country_info;
+#endif /* STA_SUPPORT */
+
+ /** WPA IE */
+ IEEEtypes_VendorSpecific_t *pwpa_ie;
+ /** WPA IE offset in the beacon buffer */
+ t_u16 wpa_offset;
+ /** RSN IE */
+ IEEEtypes_Generic_t *prsn_ie;
+ /** RSN IE offset in the beacon buffer */
+ t_u16 rsn_offset;
+#ifdef STA_SUPPORT
+ /** WAPI IE */
+ IEEEtypes_Generic_t *pwapi_ie;
+ /** WAPI IE offset in the beacon buffer */
+ t_u16 wapi_offset;
+#endif
+ /* Hotspot 2.0 OSEN AKM IE*/
+ IEEEtypes_Generic_t *posen_ie;
+ /** osen IE offset in the beacon buffer */
+ t_u16 osen_offset;
+ /* Mobility domain IE */
+ IEEEtypes_MobilityDomain_t *pmd_ie;
+ /** Mobility domain IE offset in the beacon buffer */
+ t_u16 md_offset;
+
+ /** Pointer to the returned scan response */
+ t_u8 *pbeacon_buf;
+ /** Length of the stored scan response */
+ t_u32 beacon_buf_size;
+ /** Max allocated size for updated scan response */
+ t_u32 beacon_buf_size_max;
+
+} BSSDescriptor_t, *pBSSDescriptor_t;
+
+#endif /* !_MLAN_IEEE_H_ */
diff --git a/drivers/net/wireless/nxp/mxm_wifiex/wlan_src/mlan/mlan_init.c b/drivers/net/wireless/nxp/mxm_wifiex/wlan_src/mlan/mlan_init.c
new file mode 100644
index 000000000000..e81299d690a4
--- /dev/null
+++ b/drivers/net/wireless/nxp/mxm_wifiex/wlan_src/mlan/mlan_init.c
@@ -0,0 +1,1959 @@
+/** @file mlan_init.c
+ *
+ * @brief This file contains the initialization for FW
+ * and HW.
+ *
+ *
+ * Copyright 2014-2020 NXP
+ *
+ * This software file (the File) is distributed by NXP
+ * under the terms of the GNU General Public License Version 2, June 1991
+ * (the License). You may use, redistribute and/or modify the 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.
+ *
+ */
+
+/********************************************************
+Change log:
+ 10/13/2008: initial version
+********************************************************/
+
+#include "mlan.h"
+#ifdef STA_SUPPORT
+#include "mlan_join.h"
+#endif
+#include "mlan_util.h"
+#include "mlan_fw.h"
+#include "mlan_main.h"
+#include "mlan_init.h"
+#include "mlan_wmm.h"
+#include "mlan_11n.h"
+#include "mlan_11ac.h"
+#include "mlan_11h.h"
+#include "mlan_meas.h"
+#ifdef SDIO
+#include "mlan_sdio.h"
+#endif
+#ifdef PCIE
+#include "mlan_pcie.h"
+#endif /* PCIE */
+#if defined(DRV_EMBEDDED_AUTHENTICATOR) || defined(DRV_EMBEDDED_SUPPLICANT)
+#include "hostsa_init.h"
+#endif
+#include "mlan_11ax.h"
+
+/********************************************************
+ Global Variables
+********************************************************/
+extern pmlan_operations mlan_ops[];
+/*******************************************************
+ Local Functions
+********************************************************/
+
+/**
+ * @brief This function adds a BSS priority table
+ *
+ * @param priv A pointer to mlan_private structure
+ *
+ * @return MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ */
+static mlan_status wlan_add_bsspriotbl(pmlan_private priv)
+{
+ pmlan_adapter pmadapter = priv->adapter;
+ mlan_bssprio_node *pbssprio = MNULL;
+ mlan_status status = MLAN_STATUS_SUCCESS;
+
+ ENTER();
+
+ status = pmadapter->callbacks.moal_malloc(pmadapter->pmoal_handle,
+ sizeof(mlan_bssprio_node),
+ MLAN_MEM_DEF,
+ (t_u8 **)&pbssprio);
+ if (status) {
+ PRINTM(MERROR, "Failed to allocate bsspriotbl\n");
+ LEAVE();
+ return status;
+ }
+
+ pbssprio->priv = priv;
+
+ util_init_list((pmlan_linked_list)pbssprio);
+
+ if (!pmadapter->bssprio_tbl[priv->bss_priority].bssprio_cur)
+ pmadapter->bssprio_tbl[priv->bss_priority].bssprio_cur =
+ pbssprio;
+
+ util_enqueue_list_tail(
+ pmadapter->pmoal_handle,
+ &pmadapter->bssprio_tbl[priv->bss_priority].bssprio_head,
+ (pmlan_linked_list)pbssprio,
+ pmadapter->callbacks.moal_spin_lock,
+ pmadapter->callbacks.moal_spin_unlock);
+
+ LEAVE();
+ return status;
+}
+
+/**
+ * @brief This function deletes the BSS priority table
+ *
+ * @param priv A pointer to mlan_private structure
+ *
+ * @return N/A
+ */
+static t_void wlan_delete_bsspriotbl(pmlan_private priv)
+{
+ int i;
+ pmlan_adapter pmadapter = priv->adapter;
+ mlan_bssprio_node *pbssprio_node = MNULL, *ptmp_node = MNULL,
+ **ppcur = MNULL;
+ pmlan_list_head phead;
+
+ ENTER();
+
+ for (i = 0; i < pmadapter->priv_num; ++i) {
+ phead = &pmadapter->bssprio_tbl[i].bssprio_head;
+ ppcur = &pmadapter->bssprio_tbl[i].bssprio_cur;
+ PRINTM(MINFO,
+ "Delete BSS priority table, index = %d, i = %d, phead = %p, pcur = %p\n",
+ priv->bss_index, i, phead, *ppcur);
+ if (*ppcur) {
+ pbssprio_node = (mlan_bssprio_node *)util_peek_list(
+ pmadapter->pmoal_handle, phead,
+ pmadapter->callbacks.moal_spin_lock,
+ pmadapter->callbacks.moal_spin_unlock);
+ while (pbssprio_node &&
+ ((pmlan_list_head)pbssprio_node != phead)) {
+ ptmp_node = pbssprio_node->pnext;
+ if (pbssprio_node->priv == priv) {
+ PRINTM(MINFO,
+ "Delete node, pnode = %p, pnext = %p\n",
+ pbssprio_node, ptmp_node);
+ util_unlink_list(
+ pmadapter->pmoal_handle, phead,
+ (pmlan_linked_list)pbssprio_node,
+ pmadapter->callbacks
+ .moal_spin_lock,
+ pmadapter->callbacks
+ .moal_spin_unlock);
+ pmadapter->callbacks.moal_mfree(
+ pmadapter->pmoal_handle,
+ (t_u8 *)pbssprio_node);
+ }
+ pbssprio_node = ptmp_node;
+ }
+ *ppcur = (mlan_bssprio_node *)phead;
+ }
+ }
+
+ LEAVE();
+}
+
+/**
+ * @brief The function handles VDLL init
+ *
+ * @param pmadapter A pointer to mlan_adapter structure
+ *
+ * @return MLAN_STATUS_SUCCESS
+ *
+ */
+static mlan_status vdll_init(pmlan_adapter pmadapter)
+{
+ mlan_status status = MLAN_STATUS_SUCCESS;
+ vdll_dnld_ctrl *ctrl = &pmadapter->vdll_ctrl;
+
+ ENTER();
+ memset(pmadapter, ctrl, 0, sizeof(vdll_dnld_ctrl));
+#if defined(SDIO) || defined(PCIE)
+ if (!IS_USB(pmadapter->card_type)) {
+ ctrl->cmd_buf =
+ wlan_alloc_mlan_buffer(pmadapter,
+ MRVDRV_SIZE_OF_CMD_BUFFER, 0,
+ MOAL_MALLOC_BUFFER);
+ if (!ctrl->cmd_buf) {
+ PRINTM(MERROR,
+ "vdll init: fail to alloc command buffer");
+ status = MLAN_STATUS_FAILURE;
+ }
+ }
+#endif
+ LEAVE();
+ return status;
+}
+/**
+ * @brief The function handles VDLL deinit
+ *
+ * @param pmadapter A pointer to mlan_adapter structure
+ *
+ * @return MLAN_STATUS_SUCCESS
+ *
+ */
+static t_void vdll_deinit(pmlan_adapter pmadapter)
+{
+ pmlan_callbacks pcb = &pmadapter->callbacks;
+ ENTER();
+ if (pmadapter->vdll_ctrl.vdll_mem != MNULL) {
+ if (pcb->moal_vmalloc && pcb->moal_vfree)
+ pcb->moal_vfree(pmadapter->pmoal_handle,
+ (t_u8 *)pmadapter->vdll_ctrl.vdll_mem);
+ else
+ pcb->moal_mfree(pmadapter->pmoal_handle,
+ (t_u8 *)pmadapter->vdll_ctrl.vdll_mem);
+ pmadapter->vdll_ctrl.vdll_mem = MNULL;
+ pmadapter->vdll_ctrl.vdll_len = 0;
+ }
+#if defined(SDIO) || defined(PCIE)
+ if (!IS_USB(pmadapter->card_type) &&
+ pmadapter->vdll_ctrl.cmd_buf != MNULL) {
+ wlan_free_mlan_buffer(pmadapter, pmadapter->vdll_ctrl.cmd_buf);
+ pmadapter->vdll_ctrl.cmd_buf = MNULL;
+ }
+#endif
+ LEAVE();
+}
+
+/********************************************************
+ Global Functions
+********************************************************/
+
+/**
+ * @brief This function allocates buffer for the members of adapter
+ * structure like command buffer and BSSID list.
+ *
+ * @param pmadapter A pointer to mlan_adapter structure
+ *
+ * @return MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ */
+mlan_status wlan_allocate_adapter(pmlan_adapter pmadapter)
+{
+ mlan_status ret = MLAN_STATUS_SUCCESS;
+#ifdef STA_SUPPORT
+ t_u32 beacon_buffer_size;
+ t_u32 buf_size;
+ BSSDescriptor_t *ptemp_scan_table = MNULL;
+ t_u8 chan_2g[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14};
+ t_u8 chan_5g[] = {12, 16, 34, 38, 42, 46, 36, 40, 44, 48, 52,
+ 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128,
+ 132, 136, 140, 144, 149, 153, 157, 161, 165};
+#endif
+#ifdef SDIO
+ t_u32 max_mp_regs = 0;
+ t_u32 mp_tx_aggr_buf_size = 0;
+ t_u32 mp_rx_aggr_buf_size = 0;
+#endif
+
+ ENTER();
+
+#ifdef SDIO
+ if (IS_SD(pmadapter->card_type)) {
+ max_mp_regs = pmadapter->pcard_sd->reg->max_mp_regs;
+ mp_tx_aggr_buf_size = SDIO_MP_AGGR_BUF_SIZE_MAX;
+ mp_rx_aggr_buf_size = SDIO_MP_AGGR_BUF_SIZE_MAX;
+ }
+#endif
+
+#ifdef STA_SUPPORT
+ /* Allocate buffer to store the BSSID list */
+ buf_size = sizeof(BSSDescriptor_t) * MRVDRV_MAX_BSSID_LIST;
+ if (pmadapter->callbacks.moal_vmalloc &&
+ pmadapter->callbacks.moal_vfree)
+ ret = pmadapter->callbacks.moal_vmalloc(
+ pmadapter->pmoal_handle, buf_size,
+ (t_u8 **)&ptemp_scan_table);
+ else
+ ret = pmadapter->callbacks.moal_malloc(
+ pmadapter->pmoal_handle, buf_size, MLAN_MEM_DEF,
+ (t_u8 **)&ptemp_scan_table);
+ if (ret != MLAN_STATUS_SUCCESS || !ptemp_scan_table) {
+ PRINTM(MERROR, "Failed to allocate scan table\n");
+ LEAVE();
+ return MLAN_STATUS_FAILURE;
+ }
+ pmadapter->pscan_table = ptemp_scan_table;
+
+ if (pmadapter->fixed_beacon_buffer)
+ beacon_buffer_size = MAX_SCAN_BEACON_BUFFER;
+ else
+ beacon_buffer_size = DEFAULT_SCAN_BEACON_BUFFER;
+ ret = pmadapter->callbacks.moal_malloc(pmadapter->pmoal_handle,
+ beacon_buffer_size, MLAN_MEM_DEF,
+ (t_u8 **)&pmadapter->bcn_buf);
+ if (ret != MLAN_STATUS_SUCCESS || !pmadapter->bcn_buf) {
+ PRINTM(MERROR, "Failed to allocate bcn buf\n");
+ LEAVE();
+ return MLAN_STATUS_FAILURE;
+ }
+ pmadapter->bcn_buf_size = beacon_buffer_size;
+
+ pmadapter->num_in_chan_stats = sizeof(chan_2g);
+ pmadapter->num_in_chan_stats += sizeof(chan_5g);
+ buf_size = sizeof(ChanStatistics_t) * pmadapter->num_in_chan_stats;
+ if (pmadapter->callbacks.moal_vmalloc &&
+ pmadapter->callbacks.moal_vfree)
+ ret = pmadapter->callbacks.moal_vmalloc(
+ pmadapter->pmoal_handle, buf_size,
+ (t_u8 **)&pmadapter->pchan_stats);
+ else
+ ret = pmadapter->callbacks.moal_malloc(
+ pmadapter->pmoal_handle, buf_size, MLAN_MEM_DEF,
+ (t_u8 **)&pmadapter->pchan_stats);
+ if (ret != MLAN_STATUS_SUCCESS || !pmadapter->pchan_stats) {
+ PRINTM(MERROR, "Failed to allocate channel statistics\n");
+ LEAVE();
+ return MLAN_STATUS_FAILURE;
+ }
+#endif
+
+ /* Allocate command buffer */
+ ret = wlan_alloc_cmd_buffer(pmadapter);
+ if (ret != MLAN_STATUS_SUCCESS) {
+ PRINTM(MERROR, "Failed to allocate command buffer\n");
+ LEAVE();
+ return MLAN_STATUS_FAILURE;
+ }
+
+#ifdef SDIO
+ if (IS_SD(pmadapter->card_type)) {
+ ret = pmadapter->callbacks.moal_malloc(
+ pmadapter->pmoal_handle, max_mp_regs + DMA_ALIGNMENT,
+ MLAN_MEM_DEF | MLAN_MEM_DMA,
+ (t_u8 **)&pmadapter->pcard_sd->mp_regs_buf);
+ if (ret != MLAN_STATUS_SUCCESS ||
+ !pmadapter->pcard_sd->mp_regs_buf) {
+ PRINTM(MERROR, "Failed to allocate mp_regs_buf\n");
+ LEAVE();
+ return MLAN_STATUS_FAILURE;
+ }
+ pmadapter->pcard_sd->mp_regs = (t_u8 *)ALIGN_ADDR(
+ pmadapter->pcard_sd->mp_regs_buf, DMA_ALIGNMENT);
+
+ ret = pmadapter->callbacks.moal_malloc(
+ pmadapter->pmoal_handle, MAX_SUPPORT_AMSDU_SIZE,
+ MLAN_MEM_DEF | MLAN_MEM_DMA,
+ (t_u8 **)&pmadapter->pcard_sd->rx_buffer);
+
+ if (ret != MLAN_STATUS_SUCCESS ||
+ !pmadapter->pcard_sd->rx_buffer) {
+ PRINTM(MERROR, "Failed to allocate receive buffer\n");
+ LEAVE();
+ return MLAN_STATUS_FAILURE;
+ }
+ pmadapter->pcard_sd->rx_buf = (t_u8 *)ALIGN_ADDR(
+ pmadapter->pcard_sd->rx_buffer, DMA_ALIGNMENT);
+
+ pmadapter->pcard_sd->max_sp_tx_size = MAX_SUPPORT_AMSDU_SIZE;
+ pmadapter->pcard_sd->max_sp_rx_size = MAX_SUPPORT_AMSDU_SIZE;
+ ret = wlan_alloc_sdio_mpa_buffers(
+ pmadapter, mp_tx_aggr_buf_size, mp_rx_aggr_buf_size);
+ if (ret != MLAN_STATUS_SUCCESS) {
+ PRINTM(MERROR,
+ "Failed to allocate sdio mp-a buffers\n");
+ LEAVE();
+ return MLAN_STATUS_FAILURE;
+ }
+#ifdef DEBUG_LEVEL1
+ if (mlan_drvdbg & MMPA_D) {
+ pmadapter->pcard_sd->mpa_buf_size =
+ SDIO_MP_DBG_NUM * SDIO_MP_AGGR_DEF_PKT_LIMIT *
+ MLAN_SDIO_BLOCK_SIZE;
+ if (pmadapter->callbacks.moal_vmalloc &&
+ pmadapter->callbacks.moal_vfree)
+ ret = pmadapter->callbacks.moal_vmalloc(
+ pmadapter->pmoal_handle,
+ pmadapter->pcard_sd->mpa_buf_size,
+ (t_u8 **)&pmadapter->pcard_sd->mpa_buf);
+ else
+ ret = pmadapter->callbacks.moal_malloc(
+ pmadapter->pmoal_handle,
+ pmadapter->pcard_sd->mpa_buf_size,
+ MLAN_MEM_DEF,
+ (t_u8 **)&pmadapter->pcard_sd->mpa_buf);
+ if (ret != MLAN_STATUS_SUCCESS ||
+ !pmadapter->pcard_sd->mpa_buf) {
+ PRINTM(MERROR, "Failed to allocate mpa buf\n");
+ LEAVE();
+ return MLAN_STATUS_FAILURE;
+ }
+ }
+#endif
+ }
+#endif
+
+ pmadapter->psleep_cfm =
+ wlan_alloc_mlan_buffer(pmadapter,
+ sizeof(opt_sleep_confirm_buffer), 0,
+ MOAL_MALLOC_BUFFER);
+
+#ifdef PCIE
+ /* Initialize PCIE ring buffer */
+ if (IS_PCIE(pmadapter->card_type)) {
+ ret = wlan_alloc_pcie_ring_buf(pmadapter);
+ if (MLAN_STATUS_SUCCESS != ret) {
+ PRINTM(MERROR,
+ "Failed to allocate PCIE host buffers\n");
+ LEAVE();
+ return MLAN_STATUS_FAILURE;
+ }
+ }
+#endif /* PCIE */
+
+ vdll_init(pmadapter);
+ LEAVE();
+ return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ * @brief This function initializes the private structure
+ * and sets default values to the members of mlan_private.
+ *
+ * @param priv A pointer to mlan_private structure
+ *
+ * @return MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ */
+mlan_status wlan_init_priv(pmlan_private priv)
+{
+ t_u32 i;
+ pmlan_adapter pmadapter = priv->adapter;
+ mlan_status ret = MLAN_STATUS_SUCCESS;
+#ifdef USB
+ pusb_tx_aggr_params pusb_tx_aggr = MNULL;
+#endif
+
+ ENTER();
+
+ priv->media_connected = MFALSE;
+ memset(pmadapter, priv->curr_addr, 0xff, MLAN_MAC_ADDR_LENGTH);
+
+#ifdef STA_SUPPORT
+ priv->pkt_tx_ctrl = 0;
+ priv->bss_mode = MLAN_BSS_MODE_INFRA;
+ priv->data_rate = 0; /* Initially indicate the rate as auto */
+ priv->is_data_rate_auto = MTRUE;
+ priv->bcn_avg_factor = DEFAULT_BCN_AVG_FACTOR;
+ priv->data_avg_factor = DEFAULT_DATA_AVG_FACTOR;
+
+ priv->sec_info.wep_status = Wlan802_11WEPDisabled;
+ priv->sec_info.authentication_mode = MLAN_AUTH_MODE_AUTO;
+ priv->sec_info.encryption_mode = MLAN_ENCRYPTION_MODE_NONE;
+ for (i = 0; i < MRVL_NUM_WEP_KEY; i++)
+ memset(pmadapter, &priv->wep_key[i], 0, sizeof(mrvl_wep_key_t));
+ priv->wep_key_curr_index = 0;
+ priv->ewpa_query = MFALSE;
+ priv->curr_pkt_filter = HostCmd_ACT_MAC_STATIC_DYNAMIC_BW_ENABLE |
+ HostCmd_ACT_MAC_RTS_CTS_ENABLE |
+ HostCmd_ACT_MAC_RX_ON | HostCmd_ACT_MAC_TX_ON |
+ HostCmd_ACT_MAC_ETHERNETII_ENABLE;
+
+ priv->beacon_period = MLAN_BEACON_INTERVAL;
+ priv->pattempted_bss_desc = MNULL;
+ memset(pmadapter, &priv->gtk_rekey, 0,
+ sizeof(mlan_ds_misc_gtk_rekey_data));
+ memset(pmadapter, &priv->curr_bss_params, 0,
+ sizeof(priv->curr_bss_params));
+ priv->listen_interval = MLAN_DEFAULT_LISTEN_INTERVAL;
+
+ memset(pmadapter, &priv->assoc_rsp_buf, 0, sizeof(priv->assoc_rsp_buf));
+ priv->assoc_rsp_size = 0;
+
+ wlan_11d_priv_init(priv);
+ wlan_11h_priv_init(priv);
+
+#ifdef UAP_SUPPORT
+ priv->uap_bss_started = MFALSE;
+ priv->uap_host_based = MFALSE;
+ memset(pmadapter, &priv->uap_state_chan_cb, 0,
+ sizeof(priv->uap_state_chan_cb));
+#endif
+#ifdef UAP_SUPPORT
+ priv->num_drop_pkts = 0;
+#endif
+#if defined(STA_SUPPORT)
+ priv->adhoc_state_prev = ADHOC_IDLE;
+ memset(pmadapter, &priv->adhoc_last_start_ssid, 0,
+ sizeof(priv->adhoc_last_start_ssid));
+#endif
+ 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_rate_info = 0;
+ priv->rx_pkt_info = MFALSE;
+ /* refer to V15 CMD_TX_RATE_QUERY */
+ priv->rxpd_vhtinfo = 0;
+ priv->rxpd_rate = 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;
+ priv->sec_info.ewpa_enabled = MFALSE;
+ priv->sec_info.wpa_enabled = MFALSE;
+ priv->sec_info.wpa2_enabled = MFALSE;
+ memset(pmadapter, &priv->wpa_ie, 0, sizeof(priv->wpa_ie));
+ memset(pmadapter, &priv->aes_key, 0, sizeof(priv->aes_key));
+ priv->wpa_ie_len = 0;
+ priv->wpa_is_gtk_set = MFALSE;
+#if defined(STA_SUPPORT)
+ priv->pmfcfg.mfpc = 0;
+ priv->pmfcfg.mfpr = 0;
+#endif
+ priv->sec_info.wapi_enabled = MFALSE;
+ priv->wapi_ie_len = 0;
+ priv->sec_info.wapi_key_on = MFALSE;
+
+ memset(pmadapter, &priv->wps, 0, sizeof(priv->wps));
+ memset(pmadapter, &priv->gen_ie_buf, 0, sizeof(priv->gen_ie_buf));
+ priv->gen_ie_buf_len = 0;
+#endif /* STA_SUPPORT */
+ priv->wmm_required = MTRUE;
+ priv->wmm_enabled = MFALSE;
+ priv->wmm_qosinfo = 0;
+#ifdef STA_SUPPORT
+ priv->pcurr_bcn_buf = MNULL;
+ priv->curr_bcn_size = 0;
+ memset(pmadapter, &priv->ext_cap, 0, sizeof(priv->ext_cap));
+
+ SET_EXTCAP_OPERMODENTF(priv->ext_cap);
+ SET_EXTCAP_QOS_MAP(priv->ext_cap);
+ /* Save default Extended Capability */
+ memcpy_ext(priv->adapter, &priv->def_ext_cap, &priv->ext_cap,
+ sizeof(priv->ext_cap), sizeof(priv->def_ext_cap));
+#endif /* STA_SUPPORT */
+
+ for (i = 0; i < MAX_NUM_TID; i++)
+ priv->addba_reject[i] = ADDBA_RSP_STATUS_ACCEPT;
+ priv->addba_reject[6] = ADDBA_RSP_STATUS_REJECT;
+ priv->addba_reject[7] = ADDBA_RSP_STATUS_REJECT;
+ memcpy_ext(priv->adapter, priv->ibss_addba_reject, priv->addba_reject,
+ sizeof(priv->addba_reject), sizeof(priv->ibss_addba_reject));
+ priv->max_amsdu = 0;
+#ifdef STA_SUPPORT
+ if (priv->bss_type == MLAN_BSS_TYPE_STA) {
+ priv->add_ba_param.tx_win_size = MLAN_STA_AMPDU_DEF_TXWINSIZE;
+ priv->add_ba_param.rx_win_size = MLAN_STA_AMPDU_DEF_RXWINSIZE;
+ }
+#endif
+#ifdef WIFI_DIRECT_SUPPORT
+ if (priv->bss_type == MLAN_BSS_TYPE_WIFIDIRECT) {
+ priv->add_ba_param.tx_win_size = MLAN_WFD_AMPDU_DEF_TXRXWINSIZE;
+ priv->add_ba_param.rx_win_size = MLAN_WFD_AMPDU_DEF_TXRXWINSIZE;
+ }
+#endif
+#ifdef UAP_SUPPORT
+ if (priv->bss_type == MLAN_BSS_TYPE_UAP) {
+ priv->add_ba_param.tx_win_size = MLAN_UAP_AMPDU_DEF_TXWINSIZE;
+ priv->add_ba_param.rx_win_size = MLAN_UAP_AMPDU_DEF_RXWINSIZE;
+ priv->aggr_prio_tbl[6].ampdu_user =
+ priv->aggr_prio_tbl[7].ampdu_user =
+ BA_STREAM_NOT_ALLOWED;
+ }
+#endif
+ priv->user_rxwinsize = priv->add_ba_param.rx_win_size;
+
+ priv->port_ctrl_mode = MTRUE;
+ priv->port_open = MFALSE;
+
+ priv->intf_hr_len = pmadapter->ops.intf_header_len;
+#ifdef USB
+ if (IS_USB(pmadapter->card_type)) {
+ pusb_tx_aggr =
+ wlan_get_usb_tx_aggr_params(pmadapter, priv->port);
+ if (pusb_tx_aggr && pusb_tx_aggr->aggr_ctrl.aggr_mode ==
+ MLAN_USB_AGGR_MODE_LEN_V2) {
+ priv->intf_hr_len = MLAN_USB_TX_AGGR_HEADER;
+ }
+ priv->port = pmadapter->tx_data_ep;
+ }
+#endif
+ ret = wlan_add_bsspriotbl(priv);
+#if defined(DRV_EMBEDDED_AUTHENTICATOR) || defined(DRV_EMBEDDED_SUPPLICANT)
+ hostsa_init(priv);
+#endif
+
+ LEAVE();
+ return ret;
+}
+
+/**
+ * @brief This function initializes the adapter structure
+ * and sets default values to the members of adapter.
+ *
+ * @param pmadapter A pointer to mlan_adapter structure
+ *
+ * @return N/A
+ */
+t_void wlan_init_adapter(pmlan_adapter pmadapter)
+{
+ opt_sleep_confirm_buffer *sleep_cfm_buf = MNULL;
+#ifdef USB
+ t_s32 i = 0;
+#endif
+ ENTER();
+
+ if (pmadapter->psleep_cfm) {
+ sleep_cfm_buf = (opt_sleep_confirm_buffer
+ *)(pmadapter->psleep_cfm->pbuf +
+ pmadapter->psleep_cfm->data_offset);
+ }
+#ifdef MFG_CMD_SUPPORT
+ if (pmadapter->init_para.mfg_mode == MLAN_INIT_PARA_DISABLED)
+ pmadapter->mfg_mode = MFALSE;
+ else
+ pmadapter->mfg_mode = pmadapter->init_para.mfg_mode;
+#endif
+
+#ifdef STA_SUPPORT
+ pmadapter->pwarm_reset_ioctl_req = MNULL;
+#endif
+ pmadapter->cmd_sent = MFALSE;
+#ifdef SDIO
+ if (IS_SD(pmadapter->card_type)) {
+ pmadapter->pcard_sd->int_mode = pmadapter->init_para.int_mode;
+ pmadapter->pcard_sd->gpio_pin = pmadapter->init_para.gpio_pin;
+ pmadapter->data_sent = MTRUE;
+ pmadapter->pcard_sd->mp_rd_bitmap = 0;
+ pmadapter->pcard_sd->mp_wr_bitmap = 0;
+ pmadapter->pcard_sd->curr_rd_port = 0;
+ pmadapter->pcard_sd->curr_wr_port = 0;
+ pmadapter->pcard_sd->mp_data_port_mask =
+ pmadapter->pcard_sd->reg->data_port_mask;
+ pmadapter->pcard_sd->mp_invalid_update = 0;
+ memset(pmadapter, pmadapter->pcard_sd->mp_update, 0,
+ sizeof(pmadapter->pcard_sd->mp_update));
+ pmadapter->pcard_sd->mpa_tx.buf_len = 0;
+ pmadapter->pcard_sd->mpa_tx.pkt_cnt = 0;
+ pmadapter->pcard_sd->mpa_tx.start_port = 0;
+
+ if (!pmadapter->init_para.mpa_tx_cfg)
+ pmadapter->pcard_sd->mpa_tx.enabled = MFALSE;
+ else if (pmadapter->init_para.mpa_tx_cfg ==
+ MLAN_INIT_PARA_DISABLED)
+ pmadapter->pcard_sd->mpa_tx.enabled = MFALSE;
+ else
+ pmadapter->pcard_sd->mpa_tx.enabled = MTRUE;
+ pmadapter->pcard_sd->mpa_tx.pkt_aggr_limit =
+ SDIO_MP_AGGR_DEF_PKT_LIMIT;
+
+ pmadapter->pcard_sd->mpa_rx.buf_len = 0;
+ pmadapter->pcard_sd->mpa_rx.pkt_cnt = 0;
+ pmadapter->pcard_sd->mpa_rx.start_port = 0;
+
+ if (!pmadapter->init_para.mpa_rx_cfg)
+ pmadapter->pcard_sd->mpa_rx.enabled = MFALSE;
+ else if (pmadapter->init_para.mpa_rx_cfg ==
+ MLAN_INIT_PARA_DISABLED)
+ pmadapter->pcard_sd->mpa_rx.enabled = MFALSE;
+ else
+ pmadapter->pcard_sd->mpa_rx.enabled = MTRUE;
+ pmadapter->pcard_sd->mpa_rx.pkt_aggr_limit =
+ SDIO_MP_AGGR_DEF_PKT_LIMIT;
+ }
+#endif
+
+ pmadapter->rx_pkts_queued = 0;
+ pmadapter->cmd_resp_received = MFALSE;
+ pmadapter->event_received = MFALSE;
+ pmadapter->data_received = MFALSE;
+
+ pmadapter->cmd_timer_is_set = MFALSE;
+
+ /* PnP and power profile */
+ pmadapter->surprise_removed = MFALSE;
+ /* FW hang report */
+ pmadapter->fw_hang_report = MFALSE;
+
+ if (!pmadapter->init_para.ps_mode) {
+ pmadapter->ps_mode = DEFAULT_PS_MODE;
+ } else if (pmadapter->init_para.ps_mode == MLAN_INIT_PARA_DISABLED)
+ pmadapter->ps_mode = Wlan802_11PowerModeCAM;
+ else
+ pmadapter->ps_mode = Wlan802_11PowerModePSP;
+ pmadapter->ps_state = PS_STATE_AWAKE;
+ pmadapter->need_to_wakeup = MFALSE;
+
+#ifdef STA_SUPPORT
+ pmadapter->scan_block = MFALSE;
+ /* Scan type */
+ pmadapter->scan_type = MLAN_SCAN_TYPE_ACTIVE;
+ /* Scan mode */
+ pmadapter->scan_mode = HostCmd_BSS_MODE_ANY;
+ /* Scan time */
+ pmadapter->specific_scan_time = MRVDRV_SPECIFIC_SCAN_CHAN_TIME;
+ pmadapter->active_scan_time = MRVDRV_ACTIVE_SCAN_CHAN_TIME;
+ pmadapter->passive_scan_time = MRVDRV_PASSIVE_SCAN_CHAN_TIME;
+ if (!pmadapter->init_para.passive_to_active_scan)
+ pmadapter->passive_to_active_scan = MLAN_PASS_TO_ACT_SCAN_EN;
+ else if (pmadapter->init_para.passive_to_active_scan ==
+ MLAN_INIT_PARA_DISABLED)
+ pmadapter->passive_to_active_scan = MLAN_PASS_TO_ACT_SCAN_DIS;
+ else
+ pmadapter->passive_to_active_scan = MLAN_PASS_TO_ACT_SCAN_EN;
+
+ pmadapter->scan_chan_gap = 0;
+ pmadapter->num_in_scan_table = 0;
+ memset(pmadapter, pmadapter->pscan_table, 0,
+ (sizeof(BSSDescriptor_t) * MRVDRV_MAX_BSSID_LIST));
+ pmadapter->active_scan_triggered = MFALSE;
+ pmadapter->ext_scan = MTRUE;
+ pmadapter->scan_probes = DEFAULT_PROBES;
+
+ memset(pmadapter, pmadapter->bcn_buf, 0, pmadapter->bcn_buf_size);
+ pmadapter->pbcn_buf_end = pmadapter->bcn_buf;
+
+ pmadapter->radio_on = RADIO_ON;
+ if (!pmadapter->multiple_dtim)
+ pmadapter->multiple_dtim = MRVDRV_DEFAULT_MULTIPLE_DTIM;
+
+ pmadapter->local_listen_interval = 0; /* default value in firmware will
+ be used */
+#endif /* STA_SUPPORT */
+
+ pmadapter->is_deep_sleep = MFALSE;
+ pmadapter->idle_time = DEEP_SLEEP_IDLE_TIME;
+ if (!pmadapter->init_para.auto_ds)
+ pmadapter->init_auto_ds = DEFAULT_AUTO_DS_MODE;
+ else if (pmadapter->init_para.auto_ds == MLAN_INIT_PARA_DISABLED)
+ pmadapter->init_auto_ds = MFALSE;
+ else
+ pmadapter->init_auto_ds = MTRUE;
+
+ pmadapter->delay_null_pkt = MFALSE;
+ pmadapter->delay_to_ps = DELAY_TO_PS_DEFAULT;
+ pmadapter->enhanced_ps_mode = PS_MODE_AUTO;
+
+ pmadapter->gen_null_pkt = MFALSE; /* Disable NULL Pkt generation-default
+ */
+ pmadapter->pps_uapsd_mode = MFALSE; /* Disable pps/uapsd mode -default
+ */
+
+ pmadapter->pm_wakeup_card_req = MFALSE;
+
+ pmadapter->pm_wakeup_fw_try = MFALSE;
+
+ if (!pmadapter->init_para.max_tx_buf)
+ pmadapter->max_tx_buf_size =
+ pmadapter->pcard_info->max_tx_buf_size;
+ else
+ pmadapter->max_tx_buf_size =
+ (t_u16)pmadapter->init_para.max_tx_buf;
+ pmadapter->tx_buf_size = MLAN_TX_DATA_BUF_SIZE_2K;
+ pmadapter->curr_tx_buf_size = MLAN_TX_DATA_BUF_SIZE_2K;
+
+#ifdef USB
+ if (IS_USB(pmadapter->card_type)) {
+ for (i = 0; i < MAX_USB_TX_PORT_NUM; i++) {
+ pmadapter->pcard_usb->usb_tx_aggr[i].aggr_ctrl.enable =
+ MFALSE;
+ pmadapter->pcard_usb->usb_tx_aggr[i]
+ .aggr_ctrl.aggr_mode =
+ MLAN_USB_AGGR_MODE_LEN_V2;
+ pmadapter->pcard_usb->usb_tx_aggr[i]
+ .aggr_ctrl.aggr_align =
+ MLAN_USB_TX_AGGR_V2_ALIGN;
+ pmadapter->pcard_usb->usb_tx_aggr[i].aggr_ctrl.aggr_max =
+ MLAN_USB_TX_AGGR_MAX_LEN;
+ pmadapter->pcard_usb->usb_tx_aggr[i].aggr_ctrl.aggr_tmo =
+ MLAN_USB_TX_AGGR_TIMEOUT_MSEC * 1000;
+
+ pmadapter->pcard_usb->usb_tx_aggr[i].pmbuf_aggr = MNULL;
+ pmadapter->pcard_usb->usb_tx_aggr[i].aggr_len = 0;
+ pmadapter->pcard_usb->usb_tx_aggr[i].hold_timeout_msec =
+ MLAN_USB_TX_AGGR_TIMEOUT_MSEC;
+ pmadapter->pcard_usb->usb_tx_aggr[i].port =
+ pmadapter->tx_data_ep;
+ pmadapter->pcard_usb->usb_tx_aggr[i].phandle =
+ (t_void *)pmadapter;
+ }
+
+ pmadapter->pcard_usb->usb_rx_deaggr.aggr_ctrl.enable = MFALSE;
+ pmadapter->pcard_usb->usb_rx_deaggr.aggr_ctrl.aggr_mode =
+ MLAN_USB_AGGR_MODE_NUM;
+ pmadapter->pcard_usb->usb_rx_deaggr.aggr_ctrl.aggr_align =
+ MLAN_USB_RX_ALIGN_SIZE;
+ pmadapter->pcard_usb->usb_rx_deaggr.aggr_ctrl.aggr_max =
+ MLAN_USB_RX_MAX_AGGR_NUM;
+ pmadapter->pcard_usb->usb_rx_deaggr.aggr_ctrl.aggr_tmo =
+ MLAN_USB_RX_DEAGGR_TIMEOUT_USEC;
+
+ pmadapter->pcard_usb->fw_usb_aggr = MTRUE;
+ }
+#endif
+
+ pmadapter->is_hs_configured = MFALSE;
+ pmadapter->hs_cfg.conditions = HOST_SLEEP_DEF_COND;
+ pmadapter->hs_cfg.gpio = HOST_SLEEP_DEF_GPIO;
+ pmadapter->hs_cfg.gap = HOST_SLEEP_DEF_GAP;
+ pmadapter->hs_activated = MFALSE;
+ pmadapter->min_wake_holdoff = HOST_SLEEP_DEF_WAKE_HOLDOFF;
+ pmadapter->hs_inactivity_timeout = HOST_SLEEP_DEF_INACTIVITY_TIMEOUT;
+
+ memset(pmadapter, pmadapter->event_body, 0,
+ sizeof(pmadapter->event_body));
+ pmadapter->hw_dot_11n_dev_cap = 0;
+ pmadapter->hw_dev_mcs_support = 0;
+ pmadapter->coex_rx_winsize = 1;
+#ifdef STA_SUPPORT
+ pmadapter->chan_bandwidth = 0;
+#endif /* STA_SUPPORT */
+
+ pmadapter->min_ba_threshold = MIN_BA_THRESHOLD;
+ pmadapter->hw_dot_11ac_dev_cap = 0;
+ pmadapter->hw_dot_11ac_mcs_support = 0;
+ pmadapter->max_sta_conn = 0;
+ /* Initialize 802.11d */
+ wlan_11d_init(pmadapter);
+
+ wlan_11h_init(pmadapter);
+
+ wlan_wmm_init(pmadapter);
+ wlan_init_wmm_param(pmadapter);
+ pmadapter->bypass_pkt_count = 0;
+ if (pmadapter->psleep_cfm) {
+ pmadapter->psleep_cfm->buf_type = MLAN_BUF_TYPE_CMD;
+ pmadapter->psleep_cfm->data_len = sizeof(OPT_Confirm_Sleep);
+ memset(pmadapter, &sleep_cfm_buf->ps_cfm_sleep, 0,
+ sizeof(OPT_Confirm_Sleep));
+ sleep_cfm_buf->ps_cfm_sleep.command =
+ wlan_cpu_to_le16(HostCmd_CMD_802_11_PS_MODE_ENH);
+ sleep_cfm_buf->ps_cfm_sleep.size =
+ wlan_cpu_to_le16(sizeof(OPT_Confirm_Sleep));
+ sleep_cfm_buf->ps_cfm_sleep.result = 0;
+ sleep_cfm_buf->ps_cfm_sleep.action =
+ wlan_cpu_to_le16(SLEEP_CONFIRM);
+ sleep_cfm_buf->ps_cfm_sleep.sleep_cfm.resp_ctrl =
+ wlan_cpu_to_le16(RESP_NEEDED);
+#ifdef USB
+ if (IS_USB(pmadapter->card_type)) {
+ sleep_cfm_buf->hdr =
+ wlan_cpu_to_le32(MLAN_USB_TYPE_CMD);
+ pmadapter->psleep_cfm->data_len += MLAN_TYPE_LEN;
+ }
+#endif
+ }
+ memset(pmadapter, &pmadapter->sleep_params, 0,
+ sizeof(pmadapter->sleep_params));
+ memset(pmadapter, &pmadapter->sleep_period, 0,
+ sizeof(pmadapter->sleep_period));
+ pmadapter->tx_lock_flag = MFALSE;
+ pmadapter->null_pkt_interval = 0;
+ pmadapter->fw_bands = 0;
+ pmadapter->config_bands = 0;
+ pmadapter->adhoc_start_band = 0;
+ pmadapter->pscan_channels = MNULL;
+ pmadapter->fw_release_number = 0;
+ pmadapter->fw_cap_info = 0;
+ memset(pmadapter, &pmadapter->upld_buf, 0, sizeof(pmadapter->upld_buf));
+ pmadapter->upld_len = 0;
+ pmadapter->event_cause = 0;
+ pmadapter->pmlan_buffer_event = MNULL;
+ memset(pmadapter, &pmadapter->region_channel, 0,
+ sizeof(pmadapter->region_channel));
+ pmadapter->region_code = 0;
+ memcpy_ext(pmadapter, pmadapter->country_code,
+ MRVDRV_DEFAULT_COUNTRY_CODE, COUNTRY_CODE_LEN,
+ COUNTRY_CODE_LEN);
+ pmadapter->bcn_miss_time_out = DEFAULT_BCN_MISS_TIMEOUT;
+
+#ifdef PCIE
+ if (IS_PCIE(pmadapter->card_type)) {
+ pmadapter->pcard_pcie->txbd_wrptr = 0;
+ pmadapter->pcard_pcie->txbd_rdptr = 0;
+ pmadapter->pcard_pcie->rxbd_rdptr = 0;
+ pmadapter->pcard_pcie->evtbd_rdptr = 0;
+#if defined(PCIE8997) || defined(PCIE8897)
+ if (!pmadapter->pcard_pcie->reg->use_adma) {
+ pmadapter->pcard_pcie->rxbd_wrptr =
+ pmadapter->pcard_pcie->reg
+ ->txrx_rw_ptr_rollover_ind;
+ pmadapter->pcard_pcie->evtbd_wrptr =
+ EVT_RW_PTR_ROLLOVER_IND;
+ }
+#endif
+#if defined(PCIE9098) || defined(PCIE9097)
+ if (pmadapter->pcard_pcie->reg->use_adma) {
+ pmadapter->pcard_pcie->rxbd_wrptr = MLAN_MAX_TXRX_BD;
+ pmadapter->pcard_pcie->evtbd_wrptr = MLAN_MAX_EVT_BD;
+ }
+#endif
+ }
+#endif
+ LEAVE();
+ return;
+}
+
+/**
+ * @brief This function intializes the lock variables and
+ * the list heads for interface
+ *
+ * @param pmadapter A pointer to a mlan_adapter structure
+ * @param start_index start index of mlan private
+ *
+ * @return MLAN_STATUS_SUCCESS -- on success,
+ * otherwise MLAN_STATUS_FAILURE
+ *
+ */
+mlan_status wlan_init_priv_lock_list(pmlan_adapter pmadapter, t_u8 start_index)
+{
+ mlan_status ret = MLAN_STATUS_SUCCESS;
+ pmlan_private priv = MNULL;
+ pmlan_callbacks pcb = &pmadapter->callbacks;
+ t_s32 i = 0;
+ t_u32 j = 0;
+ for (i = start_index; i < pmadapter->priv_num; i++) {
+ if (pmadapter->priv[i]) {
+ priv = pmadapter->priv[i];
+ if (pcb->moal_init_lock(pmadapter->pmoal_handle,
+ &priv->rx_pkt_lock) !=
+ MLAN_STATUS_SUCCESS) {
+ ret = MLAN_STATUS_FAILURE;
+ goto error;
+ }
+ if (pcb->moal_init_lock(pmadapter->pmoal_handle,
+ &priv->wmm.ra_list_spinlock) !=
+ MLAN_STATUS_SUCCESS) {
+ ret = MLAN_STATUS_FAILURE;
+ goto error;
+ }
+#ifdef STA_SUPPORT
+ if (pcb->moal_init_lock(pmadapter->pmoal_handle,
+ &priv->curr_bcn_buf_lock) !=
+ MLAN_STATUS_SUCCESS) {
+ ret = MLAN_STATUS_FAILURE;
+ goto error;
+ }
+#endif
+ }
+ }
+ for (i = start_index; i < pmadapter->priv_num; ++i) {
+ util_init_list_head((t_void *)pmadapter->pmoal_handle,
+ &pmadapter->bssprio_tbl[i].bssprio_head,
+ MTRUE, pmadapter->callbacks.moal_init_lock);
+ pmadapter->bssprio_tbl[i].bssprio_cur = MNULL;
+ }
+
+ for (i = start_index; i < pmadapter->priv_num; i++) {
+ if (pmadapter->priv[i]) {
+ priv = pmadapter->priv[i];
+ for (j = 0; j < MAX_NUM_TID; ++j) {
+ util_init_list_head(
+ (t_void *)pmadapter->pmoal_handle,
+ &priv->wmm.tid_tbl_ptr[j].ra_list,
+ MTRUE,
+ priv->adapter->callbacks.moal_init_lock);
+ }
+ util_init_list_head(
+ (t_void *)pmadapter->pmoal_handle,
+ &priv->tx_ba_stream_tbl_ptr, MTRUE,
+ pmadapter->callbacks.moal_init_lock);
+ util_init_list_head(
+ (t_void *)pmadapter->pmoal_handle,
+ &priv->rx_reorder_tbl_ptr, MTRUE,
+ pmadapter->callbacks.moal_init_lock);
+ util_scalar_init((t_void *)pmadapter->pmoal_handle,
+ &priv->wmm.tx_pkts_queued, 0,
+ priv->wmm.ra_list_spinlock,
+ pmadapter->callbacks.moal_init_lock);
+ util_scalar_init((t_void *)pmadapter->pmoal_handle,
+ &priv->wmm.highest_queued_prio,
+ HIGH_PRIO_TID,
+ priv->wmm.ra_list_spinlock,
+ pmadapter->callbacks.moal_init_lock);
+ util_init_list_head(
+ (t_void *)pmadapter->pmoal_handle,
+ &priv->sta_list, MTRUE,
+ pmadapter->callbacks.moal_init_lock);
+ /* Initialize bypass_txq */
+ util_init_list_head(
+ (t_void *)pmadapter->pmoal_handle,
+ &priv->bypass_txq, MTRUE,
+ pmadapter->callbacks.moal_init_lock);
+ }
+ }
+error:
+ LEAVE();
+ return ret;
+}
+
+/**
+ * @brief This function intializes the lock variables and
+ * the list heads.
+ *
+ * @param pmadapter A pointer to a mlan_adapter structure
+ *
+ * @return MLAN_STATUS_SUCCESS -- on success,
+ * otherwise MLAN_STATUS_FAILURE
+ *
+ */
+mlan_status wlan_init_lock_list(pmlan_adapter pmadapter)
+{
+ mlan_status ret = MLAN_STATUS_SUCCESS;
+ pmlan_callbacks pcb = &pmadapter->callbacks;
+#if defined(USB)
+ t_s32 i = 0;
+#endif
+ ENTER();
+
+ if (pcb->moal_init_lock(pmadapter->pmoal_handle,
+ &pmadapter->pmlan_lock) !=
+ MLAN_STATUS_SUCCESS) {
+ ret = MLAN_STATUS_FAILURE;
+ goto error;
+ }
+#if defined(SDIO) || defined(PCIE)
+ if (!IS_USB(pmadapter->card_type)) {
+ if (pcb->moal_init_lock(pmadapter->pmoal_handle,
+ &pmadapter->pint_lock) !=
+ MLAN_STATUS_SUCCESS) {
+ ret = MLAN_STATUS_FAILURE;
+ goto error;
+ }
+ }
+#endif
+ if (pcb->moal_init_lock(pmadapter->pmoal_handle,
+ &pmadapter->pmain_proc_lock) !=
+ MLAN_STATUS_SUCCESS) {
+ ret = MLAN_STATUS_FAILURE;
+ goto error;
+ }
+ if (pcb->moal_init_lock(pmadapter->pmoal_handle,
+ &pmadapter->prx_proc_lock) !=
+ MLAN_STATUS_SUCCESS) {
+ ret = MLAN_STATUS_FAILURE;
+ goto error;
+ }
+ if (pcb->moal_init_lock(pmadapter->pmoal_handle,
+ &pmadapter->pmlan_cmd_lock) !=
+ MLAN_STATUS_SUCCESS) {
+ ret = MLAN_STATUS_FAILURE;
+ goto error;
+ }
+#if defined(USB)
+ if (IS_USB(pmadapter->card_type)) {
+ for (i = 0; i < MAX_USB_TX_PORT_NUM; i++) {
+ if (pcb->moal_init_lock(pmadapter->pmoal_handle,
+ &pmadapter->pcard_usb
+ ->usb_tx_aggr[i]
+ .paggr_lock) !=
+ MLAN_STATUS_SUCCESS) {
+ ret = MLAN_STATUS_FAILURE;
+ goto error;
+ }
+ }
+ }
+#endif
+
+ util_init_list_head((t_void *)pmadapter->pmoal_handle,
+ &pmadapter->rx_data_queue, MTRUE,
+ pmadapter->callbacks.moal_init_lock);
+ util_scalar_init((t_void *)pmadapter->pmoal_handle,
+ &pmadapter->pending_bridge_pkts, 0, MNULL,
+ pmadapter->callbacks.moal_init_lock);
+ /* Initialize cmd_free_q */
+ util_init_list_head((t_void *)pmadapter->pmoal_handle,
+ &pmadapter->cmd_free_q, MTRUE,
+ pmadapter->callbacks.moal_init_lock);
+ /* Initialize cmd_pending_q */
+ util_init_list_head((t_void *)pmadapter->pmoal_handle,
+ &pmadapter->cmd_pending_q, MTRUE,
+ pmadapter->callbacks.moal_init_lock);
+ /* Initialize scan_pending_q */
+ util_init_list_head((t_void *)pmadapter->pmoal_handle,
+ &pmadapter->scan_pending_q, MTRUE,
+ pmadapter->callbacks.moal_init_lock);
+
+ /* Initialize ioctl_pending_q */
+ util_init_list_head((t_void *)pmadapter->pmoal_handle,
+ &pmadapter->ioctl_pending_q, MTRUE,
+ pmadapter->callbacks.moal_init_lock);
+
+error:
+ LEAVE();
+ return ret;
+}
+
+/**
+ * @brief This function releases the lock variables
+ *
+ * @param pmadapter A pointer to a mlan_adapter structure
+ *
+ * @return None
+ *
+ */
+t_void wlan_free_lock_list(pmlan_adapter pmadapter)
+{
+ pmlan_private priv = MNULL;
+ pmlan_callbacks pcb = &pmadapter->callbacks;
+ t_s32 i = 0;
+ t_s32 j = 0;
+
+ ENTER();
+
+ if (pmadapter->pmlan_lock)
+ pcb->moal_free_lock(pmadapter->pmoal_handle,
+ pmadapter->pmlan_lock);
+#if defined(SDIO) || defined(PCIE)
+ if (!IS_USB(pmadapter->card_type) && pmadapter->pint_lock)
+ pcb->moal_free_lock(pmadapter->pmoal_handle,
+ pmadapter->pint_lock);
+#endif
+ if (pmadapter->prx_proc_lock)
+ pcb->moal_free_lock(pmadapter->pmoal_handle,
+ pmadapter->prx_proc_lock);
+ if (pmadapter->pmain_proc_lock)
+ pcb->moal_free_lock(pmadapter->pmoal_handle,
+ pmadapter->pmain_proc_lock);
+ if (pmadapter->pmlan_cmd_lock)
+ pcb->moal_free_lock(pmadapter->pmoal_handle,
+ pmadapter->pmlan_cmd_lock);
+#if defined(USB)
+ if (IS_USB(pmadapter->card_type)) {
+ for (i = 0; i < MAX_USB_TX_PORT_NUM; i++) {
+ if (pmadapter->pcard_usb->usb_tx_aggr[i].paggr_lock)
+ pcb->moal_free_lock(pmadapter->pmoal_handle,
+ pmadapter->pcard_usb
+ ->usb_tx_aggr[i]
+ .paggr_lock);
+ }
+ }
+#endif
+
+ for (i = 0; i < pmadapter->priv_num; i++) {
+ if (pmadapter->priv[i]) {
+ priv = pmadapter->priv[i];
+ if (priv->rx_pkt_lock)
+ pcb->moal_free_lock(pmadapter->pmoal_handle,
+ priv->rx_pkt_lock);
+ if (priv->wmm.ra_list_spinlock)
+ pcb->moal_free_lock(pmadapter->pmoal_handle,
+ priv->wmm.ra_list_spinlock);
+#ifdef STA_SUPPORT
+ if (priv->curr_bcn_buf_lock)
+ pcb->moal_free_lock(pmadapter->pmoal_handle,
+ priv->curr_bcn_buf_lock);
+#endif
+ }
+ }
+
+ /* Free lists */
+ util_free_list_head((t_void *)pmadapter->pmoal_handle,
+ &pmadapter->rx_data_queue, pcb->moal_free_lock);
+
+ util_scalar_free((t_void *)pmadapter->pmoal_handle,
+ &pmadapter->pending_bridge_pkts, pcb->moal_free_lock);
+ util_free_list_head((t_void *)pmadapter->pmoal_handle,
+ &pmadapter->cmd_free_q,
+ pmadapter->callbacks.moal_free_lock);
+
+ util_free_list_head((t_void *)pmadapter->pmoal_handle,
+ &pmadapter->cmd_pending_q,
+ pmadapter->callbacks.moal_free_lock);
+
+ util_free_list_head((t_void *)pmadapter->pmoal_handle,
+ &pmadapter->scan_pending_q,
+ pmadapter->callbacks.moal_free_lock);
+
+ util_free_list_head((t_void *)pmadapter->pmoal_handle,
+ &pmadapter->ioctl_pending_q,
+ pmadapter->callbacks.moal_free_lock);
+
+ for (i = 0; i < pmadapter->priv_num; i++)
+ util_free_list_head((t_void *)pmadapter->pmoal_handle,
+ &pmadapter->bssprio_tbl[i].bssprio_head,
+ pcb->moal_free_lock);
+
+ for (i = 0; i < pmadapter->priv_num; i++) {
+ if (pmadapter->priv[i]) {
+ priv = pmadapter->priv[i];
+ util_free_list_head(
+ (t_void *)pmadapter->pmoal_handle,
+ &priv->sta_list,
+ priv->adapter->callbacks.moal_free_lock);
+ util_free_list_head(
+ (t_void *)pmadapter->pmoal_handle,
+ &priv->bypass_txq,
+ pmadapter->callbacks.moal_free_lock);
+ for (j = 0; j < MAX_NUM_TID; ++j)
+ util_free_list_head(
+ (t_void *)priv->adapter->pmoal_handle,
+ &priv->wmm.tid_tbl_ptr[j].ra_list,
+ priv->adapter->callbacks.moal_free_lock);
+ util_free_list_head(
+ (t_void *)priv->adapter->pmoal_handle,
+ &priv->tx_ba_stream_tbl_ptr,
+ priv->adapter->callbacks.moal_free_lock);
+ util_free_list_head(
+ (t_void *)priv->adapter->pmoal_handle,
+ &priv->rx_reorder_tbl_ptr,
+ priv->adapter->callbacks.moal_free_lock);
+ util_scalar_free(
+ (t_void *)priv->adapter->pmoal_handle,
+ &priv->wmm.tx_pkts_queued,
+ priv->adapter->callbacks.moal_free_lock);
+ util_scalar_free(
+ (t_void *)priv->adapter->pmoal_handle,
+ &priv->wmm.highest_queued_prio,
+ priv->adapter->callbacks.moal_free_lock);
+ }
+ }
+
+ LEAVE();
+ return;
+}
+
+/**
+ * @brief This function intializes the timers
+ *
+ * @param pmadapter A pointer to a mlan_adapter structure
+ *
+ * @return MLAN_STATUS_SUCCESS -- on success,
+ * otherwise MLAN_STATUS_FAILURE
+ *
+ */
+mlan_status wlan_init_timer(pmlan_adapter pmadapter)
+{
+ mlan_status ret = MLAN_STATUS_SUCCESS;
+ pmlan_callbacks pcb = &pmadapter->callbacks;
+#if defined(USB)
+ t_s32 i = 0;
+#endif
+ ENTER();
+
+ if (pcb->moal_init_timer(
+ pmadapter->pmoal_handle, &pmadapter->pmlan_cmd_timer,
+ wlan_cmd_timeout_func, pmadapter) != MLAN_STATUS_SUCCESS) {
+ ret = MLAN_STATUS_FAILURE;
+ goto error;
+ }
+#if defined(USB)
+ if (IS_USB(pmadapter->card_type)) {
+ for (i = 0; i < MAX_USB_TX_PORT_NUM; i++) {
+ if (pcb->moal_init_timer(
+ pmadapter->pmoal_handle,
+ &pmadapter->pcard_usb->usb_tx_aggr[i]
+ .paggr_hold_timer,
+ wlan_usb_tx_aggr_timeout_func,
+ &pmadapter->pcard_usb->usb_tx_aggr[i]) !=
+ MLAN_STATUS_SUCCESS) {
+ ret = MLAN_STATUS_FAILURE;
+ goto error;
+ }
+ }
+ }
+#endif
+ if (pcb->moal_init_timer(pmadapter->pmoal_handle,
+ &pmadapter->pwakeup_fw_timer,
+ wlan_wakeup_card_timeout_func,
+ pmadapter) != MLAN_STATUS_SUCCESS) {
+ ret = MLAN_STATUS_FAILURE;
+ goto error;
+ }
+ pmadapter->wakeup_fw_timer_is_set = MFALSE;
+error:
+ LEAVE();
+ return ret;
+}
+
+/**
+ * @brief This function releases the timers
+ *
+ * @param pmadapter A pointer to a mlan_adapter structure
+ *
+ * @return None
+ *
+ */
+t_void wlan_free_timer(pmlan_adapter pmadapter)
+{
+ pmlan_callbacks pcb = &pmadapter->callbacks;
+#if defined(USB)
+ t_s32 i = 0;
+#endif
+ ENTER();
+
+ if (pmadapter->pmlan_cmd_timer)
+ pcb->moal_free_timer(pmadapter->pmoal_handle,
+ pmadapter->pmlan_cmd_timer);
+#if defined(USB)
+ if (IS_USB(pmadapter->card_type)) {
+ for (i = 0; i < MAX_USB_TX_PORT_NUM; i++) {
+ if (pmadapter->pcard_usb->usb_tx_aggr[i]
+ .paggr_hold_timer)
+ pcb->moal_free_timer(pmadapter->pmoal_handle,
+ pmadapter->pcard_usb
+ ->usb_tx_aggr[i]
+ .paggr_hold_timer);
+ }
+ }
+#endif
+
+ if (pmadapter->pwakeup_fw_timer)
+ pcb->moal_free_timer(pmadapter->pmoal_handle,
+ pmadapter->pwakeup_fw_timer);
+
+ LEAVE();
+ return;
+}
+
+/**
+ * @brief This function initializes firmware
+ *
+ * @param pmadapter A pointer to mlan_adapter
+ *
+ * @return MLAN_STATUS_SUCCESS, MLAN_STATUS_PENDING or
+ * MLAN_STATUS_FAILURE
+ */
+mlan_status wlan_init_fw(pmlan_adapter pmadapter)
+{
+ mlan_status ret = MLAN_STATUS_SUCCESS;
+#ifdef PCIE
+ pmlan_private priv = pmadapter->priv[0];
+#endif
+ ENTER();
+ /* Initialize adapter structure */
+ wlan_init_adapter(pmadapter);
+#ifdef MFG_CMD_SUPPORT
+ if (pmadapter->mfg_mode != MTRUE) {
+#endif
+ wlan_adapter_get_hw_spec(pmadapter);
+#ifdef MFG_CMD_SUPPORT
+ }
+#ifdef PCIE
+ else if (IS_PCIE(pmadapter->card_type)) {
+ if (MLAN_STATUS_SUCCESS != wlan_set_pcie_buf_config(priv)) {
+ ret = MLAN_STATUS_FAILURE;
+ goto done;
+ }
+ }
+#endif /* PCIE */
+#endif /* MFG_CMD_SUPPORT */
+ if (wlan_is_cmd_pending(pmadapter)) {
+ /* Send the first command in queue and return */
+ if (mlan_main_process(pmadapter) == MLAN_STATUS_FAILURE)
+ ret = MLAN_STATUS_FAILURE;
+ else
+ ret = MLAN_STATUS_PENDING;
+#if defined(MFG_CMD_SUPPORT) && defined(PCIE)
+ if (IS_PCIE(pmadapter->card_type) && pmadapter->mfg_mode) {
+ ret = MLAN_STATUS_SUCCESS;
+ }
+#endif
+ }
+#ifdef PCIE
+done:
+#endif
+#ifdef MFG_CMD_SUPPORT
+ if (pmadapter->mfg_mode == MTRUE) {
+ pmadapter->hw_status = WlanHardwareStatusInitializing;
+ ret = wlan_get_hw_spec_complete(pmadapter);
+ }
+#endif
+ LEAVE();
+ return ret;
+}
+
+/**
+ * @brief This function udpate hw spec info to each interface
+ *
+ * @param pmadapter A pointer to mlan_adapter
+ *
+ * @return MLAN_STATUS_SUCCESS, MLAN_STATUS_PENDING or
+ * MLAN_STATUS_FAILURE
+ */
+void wlan_update_hw_spec(pmlan_adapter pmadapter)
+{
+ t_u32 i;
+
+ ENTER();
+
+#ifdef STA_SUPPORT
+ if (IS_SUPPORT_MULTI_BANDS(pmadapter))
+ pmadapter->fw_bands = (t_u8)GET_FW_DEFAULT_BANDS(pmadapter);
+ else
+ pmadapter->fw_bands = BAND_B;
+
+ if ((pmadapter->fw_bands & BAND_A) && (pmadapter->fw_bands & BAND_GN))
+ pmadapter->fw_bands |= BAND_AN;
+ if (!(pmadapter->fw_bands & BAND_G) && (pmadapter->fw_bands & BAND_GN))
+ pmadapter->fw_bands &= ~BAND_GN;
+
+ pmadapter->config_bands = pmadapter->fw_bands;
+ for (i = 0; i < pmadapter->priv_num; i++) {
+ if (pmadapter->priv[i]) {
+ pmadapter->priv[i]->config_bands = pmadapter->fw_bands;
+ }
+ }
+
+ if (pmadapter->fw_bands & BAND_A) {
+ if (pmadapter->fw_bands & BAND_AN) {
+ pmadapter->config_bands |= BAND_AN;
+ for (i = 0; i < pmadapter->priv_num; i++) {
+ if (pmadapter->priv[i])
+ pmadapter->priv[i]->config_bands |=
+ BAND_AN;
+ }
+ }
+ if (pmadapter->fw_bands & BAND_AAC) {
+ pmadapter->config_bands |= BAND_AAC;
+ for (i = 0; i < pmadapter->priv_num; i++) {
+ if (pmadapter->priv[i])
+ pmadapter->priv[i]->config_bands |=
+ BAND_AAC;
+ }
+ }
+ pmadapter->adhoc_start_band = BAND_A;
+ for (i = 0; i < pmadapter->priv_num; i++) {
+ if (pmadapter->priv[i])
+ pmadapter->priv[i]->adhoc_channel =
+ DEFAULT_AD_HOC_CHANNEL_A;
+ }
+ } else if (pmadapter->fw_bands & BAND_G) {
+ pmadapter->adhoc_start_band = BAND_G | BAND_B;
+ for (i = 0; i < pmadapter->priv_num; i++) {
+ if (pmadapter->priv[i])
+ pmadapter->priv[i]->adhoc_channel =
+ DEFAULT_AD_HOC_CHANNEL;
+ }
+ } else if (pmadapter->fw_bands & BAND_B) {
+ pmadapter->adhoc_start_band = BAND_B;
+ for (i = 0; i < pmadapter->priv_num; i++) {
+ if (pmadapter->priv[i])
+ pmadapter->priv[i]->adhoc_channel =
+ DEFAULT_AD_HOC_CHANNEL;
+ }
+ }
+#endif /* STA_SUPPORT */
+ for (i = 0; i < pmadapter->priv_num; i++) {
+ if (pmadapter->priv[i]->curr_addr[0] == 0xff)
+ memmove(pmadapter, pmadapter->priv[i]->curr_addr,
+ pmadapter->permanent_addr,
+ MLAN_MAC_ADDR_LENGTH);
+ }
+ for (i = 0; i < pmadapter->priv_num; i++) {
+ if (pmadapter->priv[i])
+ wlan_update_11n_cap(pmadapter->priv[i]);
+ }
+ if (ISSUPP_BEAMFORMING(pmadapter->hw_dot_11n_dev_cap)) {
+ PRINTM(MCMND, "Enable Beamforming\n");
+ for (i = 0; i < pmadapter->priv_num; i++) {
+ if (pmadapter->priv[i])
+ pmadapter->priv[i]->tx_bf_cap =
+ pmadapter->pcard_info
+ ->default_11n_tx_bf_cap;
+ }
+ }
+ for (i = 0; i < pmadapter->priv_num; i++) {
+ if (pmadapter->priv[i])
+ wlan_update_11ac_cap(pmadapter->priv[i]);
+ }
+ if (IS_FW_SUPPORT_11AX(pmadapter)) {
+ if (pmadapter->hw_2g_hecap_len) {
+ pmadapter->fw_bands |= BAND_GAX;
+ pmadapter->config_bands |= BAND_GAX;
+ }
+ if (pmadapter->hw_hecap_len) {
+ pmadapter->fw_bands |= BAND_AAX;
+ pmadapter->config_bands |= BAND_AAX;
+ }
+ for (i = 0; i < pmadapter->priv_num; i++) {
+ if (pmadapter->priv[i]) {
+ pmadapter->priv[i]->config_bands =
+ pmadapter->config_bands;
+ pmadapter->priv[i]->user_2g_hecap_len =
+ pmadapter->hw_2g_hecap_len;
+ memcpy_ext(pmadapter,
+ pmadapter->priv[i]->user_2g_he_cap,
+ pmadapter->hw_2g_he_cap,
+ pmadapter->hw_2g_hecap_len,
+ sizeof(pmadapter->priv[i]
+ ->user_2g_he_cap));
+ pmadapter->priv[i]->user_hecap_len =
+ pmadapter->hw_hecap_len;
+ memcpy_ext(
+ pmadapter,
+ pmadapter->priv[i]->user_he_cap,
+ pmadapter->hw_he_cap,
+ pmadapter->hw_hecap_len,
+ sizeof(pmadapter->priv[i]->user_he_cap));
+ }
+ }
+ }
+ LEAVE();
+ return;
+}
+
+/**
+ * @brief This function initializes firmware for interface
+ *
+ * @param pmadapter A pointer to mlan_adapter
+ *
+ * @return MLAN_STATUS_SUCCESS, MLAN_STATUS_PENDING or
+ * MLAN_STATUS_FAILURE
+ */
+mlan_status wlan_init_priv_fw(pmlan_adapter pmadapter)
+{
+ mlan_status ret = MLAN_STATUS_SUCCESS;
+ pmlan_private priv = MNULL;
+ t_u8 i = 0;
+
+ ENTER();
+
+ wlan_init_priv_lock_list(pmadapter, 1);
+ for (i = 0; i < pmadapter->priv_num; i++) {
+ if (pmadapter->priv[i]) {
+ priv = pmadapter->priv[i];
+
+ /* Initialize private structure */
+ ret = wlan_init_priv(priv);
+ if (ret) {
+ ret = MLAN_STATUS_FAILURE;
+ goto done;
+ }
+ }
+ }
+#ifdef MFG_CMD_SUPPORT
+ if (pmadapter->mfg_mode != MTRUE) {
+#endif
+ wlan_update_hw_spec(pmadapter);
+ /* Issue firmware initialize commands for first BSS,
+ * for other interfaces it will be called after getting
+ * the last init command response of previous interface
+ */
+ priv = wlan_get_priv(pmadapter, MLAN_BSS_ROLE_ANY);
+ if (!priv) {
+ ret = MLAN_STATUS_FAILURE;
+ goto done;
+ }
+
+ ret = priv->ops.init_cmd(priv, MTRUE);
+ if (ret == MLAN_STATUS_FAILURE)
+ goto done;
+#ifdef MFG_CMD_SUPPORT
+ }
+#endif /* MFG_CMD_SUPPORT */
+
+ if (wlan_is_cmd_pending(pmadapter)) {
+ /* Send the first command in queue and return */
+ if (mlan_main_process(pmadapter) == MLAN_STATUS_FAILURE)
+ ret = MLAN_STATUS_FAILURE;
+ else
+ ret = MLAN_STATUS_PENDING;
+#if defined(MFG_CMD_SUPPORT) && defined(PCIE)
+ if (IS_PCIE(pmadapter->card_type) && pmadapter->mfg_mode) {
+ ret = MLAN_STATUS_SUCCESS;
+ pmadapter->hw_status = WlanHardwareStatusReady;
+ }
+#endif
+ } else {
+ pmadapter->hw_status = WlanHardwareStatusReady;
+ }
+done:
+ LEAVE();
+ return ret;
+}
+
+/**
+ * @brief This function frees the structure of adapter
+ *
+ * @param pmadapter A pointer to mlan_adapter structure
+ *
+ * @return N/A
+ */
+t_void wlan_free_adapter(pmlan_adapter pmadapter)
+{
+ mlan_callbacks *pcb = (mlan_callbacks *)&pmadapter->callbacks;
+#if defined(USB)
+ t_s32 i = 0;
+#endif
+ ENTER();
+
+ if (!pmadapter) {
+ PRINTM(MERROR, "The adapter is NULL\n");
+ LEAVE();
+ return;
+ }
+
+ wlan_cancel_all_pending_cmd(pmadapter, MTRUE);
+ /* Free command buffer */
+ PRINTM(MINFO, "Free Command buffer\n");
+ wlan_free_cmd_buffer(pmadapter);
+
+ if (pmadapter->cmd_timer_is_set) {
+ /* Cancel command timeout timer */
+ pcb->moal_stop_timer(pmadapter->pmoal_handle,
+ pmadapter->pmlan_cmd_timer);
+ pmadapter->cmd_timer_is_set = MFALSE;
+ }
+#if defined(USB)
+ if (IS_USB(pmadapter->card_type)) {
+ for (i = 0; i < MAX_USB_TX_PORT_NUM; i++) {
+ if (pmadapter->pcard_usb->usb_tx_aggr[i]
+ .aggr_hold_timer_is_set) {
+ /* Cancel usb_tx_aggregation timeout timer */
+ pcb->moal_stop_timer(pmadapter->pmoal_handle,
+ pmadapter->pcard_usb
+ ->usb_tx_aggr[i]
+ .paggr_hold_timer);
+ pmadapter->pcard_usb->usb_tx_aggr[i]
+ .aggr_hold_timer_is_set = MFALSE;
+ }
+ }
+ }
+#endif
+ if (pmadapter->wakeup_fw_timer_is_set) {
+ /* Cancel wakeup card timer */
+ pcb->moal_stop_timer(pmadapter->pmoal_handle,
+ pmadapter->pwakeup_fw_timer);
+ pmadapter->wakeup_fw_timer_is_set = MFALSE;
+ }
+ wlan_free_fw_cfp_tables(pmadapter);
+#ifdef STA_SUPPORT
+ PRINTM(MINFO, "Free ScanTable\n");
+ if (pmadapter->pscan_table) {
+ if (pcb->moal_vmalloc && pcb->moal_vfree)
+ pcb->moal_vfree(pmadapter->pmoal_handle,
+ (t_u8 *)pmadapter->pscan_table);
+ else
+ pcb->moal_mfree(pmadapter->pmoal_handle,
+ (t_u8 *)pmadapter->pscan_table);
+ pmadapter->pscan_table = MNULL;
+ }
+ if (pmadapter->pchan_stats) {
+ if (pcb->moal_vmalloc && pcb->moal_vfree)
+ pcb->moal_vfree(pmadapter->pmoal_handle,
+ (t_u8 *)pmadapter->pchan_stats);
+ else
+ pcb->moal_mfree(pmadapter->pmoal_handle,
+ (t_u8 *)pmadapter->pchan_stats);
+ pmadapter->pchan_stats = MNULL;
+ }
+ if (pmadapter->bcn_buf) {
+ pcb->moal_mfree(pmadapter->pmoal_handle,
+ (t_u8 *)pmadapter->bcn_buf);
+ pmadapter->bcn_buf = MNULL;
+ }
+#endif
+
+ wlan_11h_cleanup(pmadapter);
+
+#ifdef SDIO
+ if (IS_SD(pmadapter->card_type)) {
+ if (pmadapter->pcard_sd->mp_regs_buf) {
+ pcb->moal_mfree(
+ pmadapter->pmoal_handle,
+ (t_u8 *)pmadapter->pcard_sd->mp_regs_buf);
+ pmadapter->pcard_sd->mp_regs_buf = MNULL;
+ pmadapter->pcard_sd->mp_regs = MNULL;
+ }
+ if (pmadapter->pcard_sd->rx_buffer) {
+ pcb->moal_mfree(pmadapter->pmoal_handle,
+ (t_u8 *)pmadapter->pcard_sd->rx_buffer);
+ pmadapter->pcard_sd->rx_buffer = MNULL;
+ pmadapter->pcard_sd->rx_buf = MNULL;
+ }
+ wlan_free_sdio_mpa_buffers(pmadapter);
+#ifdef DEBUG_LEVEL1
+ if (pmadapter->pcard_sd->mpa_buf) {
+ if (pcb->moal_vmalloc && pcb->moal_vfree)
+ pcb->moal_vfree(
+ pmadapter->pmoal_handle,
+ (t_u8 *)pmadapter->pcard_sd->mpa_buf);
+ else
+ pcb->moal_mfree(
+ pmadapter->pmoal_handle,
+ (t_u8 *)pmadapter->pcard_sd->mpa_buf);
+ pmadapter->pcard_sd->mpa_buf = MNULL;
+ pmadapter->pcard_sd->mpa_buf_size = 0;
+ }
+#endif
+ }
+#endif
+
+ wlan_free_mlan_buffer(pmadapter, pmadapter->psleep_cfm);
+ pmadapter->psleep_cfm = MNULL;
+
+#ifdef PCIE
+ if (IS_PCIE(pmadapter->card_type)) {
+ /* Free ssu dma buffer just in case */
+ wlan_free_ssu_pcie_buf(pmadapter);
+ /* Free PCIE ring buffers */
+ wlan_free_pcie_ring_buf(pmadapter);
+ }
+#endif
+
+ /* Free timers */
+ wlan_free_timer(pmadapter);
+
+ /* Free lock variables */
+ wlan_free_lock_list(pmadapter);
+
+#ifdef SDIO
+ if (pmadapter->pcard_sd) {
+ pcb->moal_mfree(pmadapter->pmoal_handle,
+ (t_u8 *)pmadapter->pcard_sd);
+ pmadapter->pcard_sd = MNULL;
+ }
+#endif
+#ifdef PCIE
+ if (pmadapter->pcard_pcie) {
+ pcb->moal_mfree(pmadapter->pmoal_handle,
+ (t_u8 *)pmadapter->pcard_pcie);
+ pmadapter->pcard_pcie = MNULL;
+ }
+#endif
+#ifdef USB
+ if (pmadapter->pcard_usb) {
+ pcb->moal_mfree(pmadapter->pmoal_handle,
+ (t_u8 *)pmadapter->pcard_usb);
+ pmadapter->pcard_usb = MNULL;
+ }
+#endif
+ vdll_deinit(pmadapter);
+
+ LEAVE();
+ return;
+}
+
+/**
+ * @brief This function frees the structure of priv
+ *
+ * @param pmpriv A pointer to mlan_private structure
+ *
+ * @return N/A
+ */
+t_void wlan_free_priv(mlan_private *pmpriv)
+{
+ ENTER();
+ wlan_clean_txrx(pmpriv);
+ wlan_delete_bsspriotbl(pmpriv);
+
+#ifdef STA_SUPPORT
+ wlan_free_curr_bcn(pmpriv);
+#endif /* STA_SUPPORT */
+
+#if defined(DRV_EMBEDDED_AUTHENTICATOR) || defined(DRV_EMBEDDED_SUPPLICANT)
+ hostsa_cleanup(pmpriv);
+#endif /*EMBEDDED AUTHENTICATOR*/
+
+ wlan_delete_station_list(pmpriv);
+ LEAVE();
+}
+
+/**
+ * @brief This function init interface based on pmadapter's bss_attr table
+ *
+ * @param pmadapter A pointer to mlan_adapter structure
+ *
+ * @return N/A
+ */
+mlan_status wlan_init_interface(pmlan_adapter pmadapter)
+{
+ mlan_status ret = MLAN_STATUS_SUCCESS;
+ pmlan_callbacks pcb = MNULL;
+ t_u8 i = 0;
+ t_u32 j = 0;
+
+ ENTER();
+
+ pcb = &pmadapter->callbacks;
+ for (i = 0; i < MLAN_MAX_BSS_NUM; i++) {
+ if (pmadapter->bss_attr[i].active == MTRUE) {
+ if (!pmadapter->priv[i]) {
+ /* For valid bss_attr, allocate memory for
+ * private structure */
+ if (pcb->moal_vmalloc && pcb->moal_vfree)
+ ret = pcb->moal_vmalloc(
+ pmadapter->pmoal_handle,
+ sizeof(mlan_private),
+ (t_u8 **)&pmadapter->priv[i]);
+ else
+ ret = pcb->moal_malloc(
+ pmadapter->pmoal_handle,
+ sizeof(mlan_private),
+ MLAN_MEM_DEF,
+ (t_u8 **)&pmadapter->priv[i]);
+ if (ret != MLAN_STATUS_SUCCESS ||
+ !pmadapter->priv[i]) {
+ ret = MLAN_STATUS_FAILURE;
+ goto error;
+ }
+
+ pmadapter->priv_num++;
+ memset(pmadapter, pmadapter->priv[i], 0,
+ sizeof(mlan_private));
+ }
+ pmadapter->priv[i]->adapter = pmadapter;
+
+ /* Save bss_type, frame_type & bss_priority */
+ pmadapter->priv[i]->bss_type =
+ (t_u8)pmadapter->bss_attr[i].bss_type;
+ pmadapter->priv[i]->frame_type =
+ (t_u8)pmadapter->bss_attr[i].frame_type;
+ pmadapter->priv[i]->bss_priority =
+ (t_u8)pmadapter->bss_attr[i].bss_priority;
+ if (pmadapter->bss_attr[i].bss_type ==
+ MLAN_BSS_TYPE_STA)
+ pmadapter->priv[i]->bss_role =
+ MLAN_BSS_ROLE_STA;
+ else if (pmadapter->bss_attr[i].bss_type ==
+ MLAN_BSS_TYPE_UAP)
+ pmadapter->priv[i]->bss_role =
+ MLAN_BSS_ROLE_UAP;
+#ifdef WIFI_DIRECT_SUPPORT
+ else if (pmadapter->bss_attr[i].bss_type ==
+ MLAN_BSS_TYPE_WIFIDIRECT) {
+ pmadapter->priv[i]->bss_role =
+ MLAN_BSS_ROLE_STA;
+ if (pmadapter->bss_attr[i].bss_virtual)
+ pmadapter->priv[i]->bss_virtual = MTRUE;
+ }
+#endif
+ /* Save bss_index and bss_num */
+ pmadapter->priv[i]->bss_index = i;
+ pmadapter->priv[i]->bss_num =
+ (t_u8)pmadapter->bss_attr[i].bss_num;
+
+ /* init function table */
+ for (j = 0; mlan_ops[j]; j++) {
+ if (mlan_ops[j]->bss_role ==
+ GET_BSS_ROLE(pmadapter->priv[i])) {
+ memcpy_ext(pmadapter,
+ &pmadapter->priv[i]->ops,
+ mlan_ops[j],
+ sizeof(mlan_operations),
+ sizeof(mlan_operations));
+ break;
+ }
+ }
+ }
+ }
+ /*wmm init*/
+ wlan_wmm_init(pmadapter);
+ /* Initialize firmware, may return PENDING */
+ ret = wlan_init_priv_fw(pmadapter);
+ PRINTM(MINFO, "wlan_init_priv_fw returned ret=0x%x\n", ret);
+error:
+ LEAVE();
+ return ret;
+}
+
+/**
+ * @brief The cmdresp handler calls this function for init_fw_complete callback
+ *
+ * @param pmadapter A pointer to mlan_adapter structure
+ *
+ * @return MLAN_STATUS_SUCCESS
+ * The firmware initialization callback succeeded.
+ */
+mlan_status wlan_get_hw_spec_complete(pmlan_adapter pmadapter)
+{
+ mlan_status status = MLAN_STATUS_SUCCESS;
+ mlan_status ret = MLAN_STATUS_SUCCESS;
+ pmlan_callbacks pcb = &pmadapter->callbacks;
+ mlan_hw_info info;
+ mlan_bss_tbl bss_tbl;
+
+ ENTER();
+#ifdef MFG_CMD_SUPPORT
+ if (pmadapter->mfg_mode != MTRUE) {
+#endif
+ /* Check if hardware is ready */
+ if (pmadapter->hw_status != WlanHardwareStatusInitializing)
+ status = MLAN_STATUS_FAILURE;
+ else {
+ memset(pmadapter, &info, 0, sizeof(info));
+ info.fw_cap = pmadapter->fw_cap_info;
+ memset(pmadapter, &bss_tbl, 0, sizeof(bss_tbl));
+ memcpy_ext(pmadapter, bss_tbl.bss_attr,
+ pmadapter->bss_attr, sizeof(mlan_bss_tbl),
+ sizeof(mlan_bss_tbl));
+ }
+ /* Invoke callback */
+ ret = pcb->moal_get_hw_spec_complete(pmadapter->pmoal_handle,
+ status, &info, &bss_tbl);
+ if (ret == MLAN_STATUS_SUCCESS && status == MLAN_STATUS_SUCCESS)
+ memcpy_ext(pmadapter, pmadapter->bss_attr,
+ bss_tbl.bss_attr, sizeof(mlan_bss_tbl),
+ sizeof(mlan_bss_tbl));
+ else {
+ pmadapter->hw_status = WlanHardwareStatusNotReady;
+ wlan_init_fw_complete(pmadapter);
+ }
+#ifdef MFG_CMD_SUPPORT
+ }
+#endif
+ if (pmadapter->hw_status == WlanHardwareStatusInitializing)
+ ret = wlan_init_interface(pmadapter);
+ LEAVE();
+ return ret;
+}
+
+/**
+ * @brief The cmdresp handler calls this function for init_fw_complete callback
+ *
+ * @param pmadapter A pointer to mlan_adapter structure
+ *
+ * @return MLAN_STATUS_SUCCESS
+ * The firmware initialization callback succeeded.
+ */
+mlan_status wlan_init_fw_complete(pmlan_adapter pmadapter)
+{
+ mlan_status status = MLAN_STATUS_SUCCESS;
+ mlan_status ret = MLAN_STATUS_SUCCESS;
+ pmlan_callbacks pcb = &pmadapter->callbacks;
+ mlan_private *pmpriv = MNULL;
+
+ ENTER();
+
+ /* Check if hardware is ready */
+ if (pmadapter->hw_status != WlanHardwareStatusReady)
+ status = MLAN_STATUS_FAILURE;
+
+ /* Reconfigure wmm parameter*/
+ if (status == MLAN_STATUS_SUCCESS) {
+ pmpriv = wlan_get_priv(pmadapter, MLAN_BSS_ROLE_STA);
+ if (pmpriv)
+ status = wlan_prepare_cmd(pmpriv,
+ HostCmd_CMD_WMM_PARAM_CONFIG,
+ HostCmd_ACT_GEN_SET, 0, MNULL,
+ &pmadapter->ac_params);
+ }
+ /* Invoke callback */
+ ret = pcb->moal_init_fw_complete(pmadapter->pmoal_handle, status);
+ LEAVE();
+ return ret;
+}
+
+/**
+ * @brief The cmdresp handler calls this function
+ * for shutdown_fw_complete callback
+ *
+ * @param pmadapter A pointer to mlan_adapter structure
+ *
+ * @return MLAN_STATUS_SUCCESS
+ * The firmware shutdown callback succeeded.
+ */
+mlan_status wlan_shutdown_fw_complete(pmlan_adapter pmadapter)
+{
+ pmlan_callbacks pcb = &pmadapter->callbacks;
+ mlan_status status = MLAN_STATUS_SUCCESS;
+ mlan_status ret = MLAN_STATUS_SUCCESS;
+
+ ENTER();
+ pmadapter->hw_status = WlanHardwareStatusNotReady;
+ /* Invoke callback */
+ ret = pcb->moal_shutdown_fw_complete(pmadapter->pmoal_handle, status);
+ LEAVE();
+ return ret;
+}
diff --git a/drivers/net/wireless/nxp/mxm_wifiex/wlan_src/mlan/mlan_init.h b/drivers/net/wireless/nxp/mxm_wifiex/wlan_src/mlan/mlan_init.h
new file mode 100644
index 000000000000..f32731b6c788
--- /dev/null
+++ b/drivers/net/wireless/nxp/mxm_wifiex/wlan_src/mlan/mlan_init.h
@@ -0,0 +1,125 @@
+/** @file mlan_init.h
+ *
+ * @brief This file defines the FW initialization data
+ * structures.
+ *
+ *
+ * Copyright 2014-2020 NXP
+ *
+ * This software file (the File) is distributed by NXP
+ * under the terms of the GNU General Public License Version 2, June 1991
+ * (the License). You may use, redistribute and/or modify the 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.
+ *
+ */
+
+/******************************************************
+Change log:
+ 10/13/2008: initial version
+******************************************************/
+
+#ifndef _MLAN_INIT_H_
+#define _MLAN_INIT_H_
+
+/** Tx buffer size for firmware download*/
+#define FW_DNLD_TX_BUF_SIZE 2312
+/** Rx buffer size for firmware download*/
+#define FW_DNLD_RX_BUF_SIZE 2048
+/** Max firmware retry */
+#define MAX_FW_RETRY 3
+
+/** Firmware has last block */
+#define FW_HAS_LAST_BLOCK 0x00000004
+/** CMD id for CMD4 */
+#define FW_CMD_4 0x00000004
+/** CMD id for CMD6 */
+#define FW_CMD_6 0x00000006
+/** CMD id for CMD7 */
+#define FW_CMD_7 0x00000007
+/** CMD id for CMD10 */
+#define FW_CMD_10 0x0000000a
+
+/** Firmware data transmit size */
+#define FW_DATA_XMIT_SIZE (sizeof(FWHeader) + DataLength + sizeof(t_u32))
+
+/** FWHeader */
+typedef MLAN_PACK_START struct _FWHeader {
+ /** FW download command */
+ t_u32 dnld_cmd;
+ /** FW base address */
+ t_u32 base_addr;
+ /** FW data length */
+ t_u32 data_length;
+ /** FW CRC */
+ t_u32 crc;
+} MLAN_PACK_END FWHeader;
+
+/** FWData */
+typedef MLAN_PACK_START struct _FWData {
+ /** FW data header */
+ FWHeader fw_header;
+ /** FW data sequence number */
+ t_u32 seq_num;
+ /** FW data buffer */
+ t_u8 data[1];
+} MLAN_PACK_END FWData;
+
+/** FWSyncHeader */
+typedef MLAN_PACK_START struct _FWSyncHeader {
+ /** FW sync header command */
+ t_u32 cmd;
+ /** FW sync header sequence number */
+ t_u32 seq_num;
+ /** Extended header */
+ t_u32 magic;
+ /** Chip rev */
+ t_u32 chip_rev;
+ /** Strap */
+ t_u32 strap;
+ /** Status */
+ t_u32 status;
+ /** Offset */
+ t_u32 offset;
+} MLAN_PACK_END FWSyncHeader;
+
+/** FW Sync pkt */
+typedef MLAN_PACK_START struct _FWSyncPkt {
+ /** pkt type */
+ t_u32 pkt_type;
+ /** FW sync header command */
+ t_u32 cmd;
+ /** FW sync header sequence number */
+ t_u32 seq_num;
+ /** chip rev */
+ t_u32 chip_rev;
+ /** fw status */
+ t_u32 fw_ready;
+} MLAN_PACK_END FWSyncPkt;
+
+#ifdef BIG_ENDIAN_SUPPORT
+/** Convert sequence number and command fields
+ * of fwheader to correct endian format
+ */
+#define endian_convert_syncfwheader(x) \
+ { \
+ (x)->cmd = wlan_le32_to_cpu((x)->cmd); \
+ (x)->seq_num = wlan_le32_to_cpu((x)->seq_num); \
+ (x)->status = wlan_le32_to_cpu((x)->status); \
+ (x)->offset = wlan_le32_to_cpu((x)->offset); \
+ }
+#else
+/** Convert sequence number and command fields
+ * of fwheader to correct endian format
+ */
+#define endian_convert_syncfwheader(x)
+#endif /* BIG_ENDIAN_SUPPORT */
+
+#endif /* _MLAN_INIT_H_ */
diff --git a/drivers/net/wireless/nxp/mxm_wifiex/wlan_src/mlan/mlan_ioctl.h b/drivers/net/wireless/nxp/mxm_wifiex/wlan_src/mlan/mlan_ioctl.h
new file mode 100644
index 000000000000..2315b2a2b79e
--- /dev/null
+++ b/drivers/net/wireless/nxp/mxm_wifiex/wlan_src/mlan/mlan_ioctl.h
@@ -0,0 +1,5159 @@
+/** @file mlan_ioctl.h
+ *
+ * @brief This file declares the IOCTL data structures and APIs.
+ *
+ *
+ * Copyright 2014-2020 NXP
+ *
+ * This software file (the File) is distributed by NXP
+ * under the terms of the GNU General Public License Version 2, June 1991
+ * (the License). You may use, redistribute and/or modify the 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.
+ *
+ */
+
+/******************************************************
+Change log:
+ 11/07/2008: initial version
+******************************************************/
+
+#ifndef _MLAN_IOCTL_H_
+#define _MLAN_IOCTL_H_
+
+/** Enumeration for IOCTL request ID */
+enum _mlan_ioctl_req_id {
+ /* Scan Group */
+ MLAN_IOCTL_SCAN = 0x00010000,
+ MLAN_OID_SCAN_NORMAL = 0x00010001,
+ MLAN_OID_SCAN_SPECIFIC_SSID = 0x00010002,
+ MLAN_OID_SCAN_USER_CONFIG = 0x00010003,
+ MLAN_OID_SCAN_CONFIG = 0x00010004,
+ MLAN_OID_SCAN_GET_CURRENT_BSS = 0x00010005,
+ MLAN_OID_SCAN_CANCEL = 0x00010006,
+ MLAN_OID_SCAN_TABLE_FLUSH = 0x0001000A,
+ MLAN_OID_SCAN_BGSCAN_CONFIG = 0x0001000B,
+ /* BSS Configuration Group */
+ MLAN_IOCTL_BSS = 0x00020000,
+ MLAN_OID_BSS_START = 0x00020001,
+ MLAN_OID_BSS_STOP = 0x00020002,
+ MLAN_OID_BSS_MODE = 0x00020003,
+ MLAN_OID_BSS_CHANNEL = 0x00020004,
+ MLAN_OID_BSS_CHANNEL_LIST = 0x00020005,
+ MLAN_OID_BSS_MAC_ADDR = 0x00020006,
+ MLAN_OID_BSS_MULTICAST_LIST = 0x00020007,
+ MLAN_OID_BSS_FIND_BSS = 0x00020008,
+ MLAN_OID_IBSS_BCN_INTERVAL = 0x00020009,
+ MLAN_OID_IBSS_ATIM_WINDOW = 0x0002000A,
+ MLAN_OID_IBSS_CHANNEL = 0x0002000B,
+#ifdef UAP_SUPPORT
+ MLAN_OID_UAP_BSS_CONFIG = 0x0002000C,
+ MLAN_OID_UAP_DEAUTH_STA = 0x0002000D,
+ MLAN_OID_UAP_BSS_RESET = 0x0002000E,
+#endif
+#if defined(STA_SUPPORT) && defined(UAP_SUPPORT)
+ MLAN_OID_BSS_ROLE = 0x0002000F,
+#endif
+#ifdef WIFI_DIRECT_SUPPORT
+ MLAN_OID_WIFI_DIRECT_MODE = 0x00020010,
+#endif
+#ifdef STA_SUPPORT
+ MLAN_OID_BSS_LISTEN_INTERVAL = 0x00020011,
+#endif
+ MLAN_OID_BSS_REMOVE = 0x00020014,
+#ifdef UAP_SUPPORT
+ MLAN_OID_UAP_CFG_WMM_PARAM = 0x00020015,
+#endif
+ MLAN_OID_BSS_11D_CHECK_CHANNEL = 0x00020016,
+#ifdef UAP_SUPPORT
+ MLAN_OID_UAP_ACS_SCAN = 0x00020017,
+ MLAN_OID_UAP_SCAN_CHANNELS = 0x00020018,
+ MLAN_OID_UAP_CHANNEL = 0x00020019,
+ MLAN_OID_UAP_OPER_CTRL = 0x0002001A,
+#endif
+#ifdef STA_SUPPORT
+ MLAN_OID_BSS_CHAN_INFO = 0x0002001B,
+#endif
+#ifdef UAP_SUPPORT
+ MLAN_OID_UAP_ADD_STATION = 0x0002001C,
+#endif
+
+ MLAN_OID_BSS_FIND_BSSID = 0x0002001D,
+
+ /* Radio Configuration Group */
+ MLAN_IOCTL_RADIO_CFG = 0x00030000,
+ MLAN_OID_RADIO_CTRL = 0x00030001,
+ MLAN_OID_BAND_CFG = 0x00030002,
+ MLAN_OID_ANT_CFG = 0x00030003,
+ MLAN_OID_REMAIN_CHAN_CFG = 0x00030004,
+ MLAN_OID_MIMO_SWITCH = 0x00030005,
+
+ /* SNMP MIB Group */
+ MLAN_IOCTL_SNMP_MIB = 0x00040000,
+ MLAN_OID_SNMP_MIB_RTS_THRESHOLD = 0x00040001,
+ MLAN_OID_SNMP_MIB_FRAG_THRESHOLD = 0x00040002,
+ MLAN_OID_SNMP_MIB_RETRY_COUNT = 0x00040003,
+ MLAN_OID_SNMP_MIB_DOT11D = 0x00040004,
+#if defined(UAP_SUPPORT)
+ MLAN_OID_SNMP_MIB_DOT11H = 0x00040005,
+#endif
+ MLAN_OID_SNMP_MIB_DTIM_PERIOD = 0x00040006,
+ MLAN_OID_SNMP_MIB_SIGNALEXT_ENABLE = 0x00040007,
+ MLAN_OID_SNMP_MIB_CTRL_DEAUTH = 0x00040008,
+
+ /* Status Information Group */
+ MLAN_IOCTL_GET_INFO = 0x00050000,
+ MLAN_OID_GET_STATS = 0x00050001,
+ MLAN_OID_GET_SIGNAL = 0x00050002,
+ MLAN_OID_GET_FW_INFO = 0x00050003,
+ MLAN_OID_GET_VER_EXT = 0x00050004,
+ MLAN_OID_GET_BSS_INFO = 0x00050005,
+ MLAN_OID_GET_DEBUG_INFO = 0x00050006,
+#ifdef UAP_SUPPORT
+ MLAN_OID_UAP_STA_LIST = 0x00050007,
+#endif
+ MLAN_OID_GET_SIGNAL_EXT = 0x00050008,
+ MLAN_OID_LINK_STATS = 0x00050009,
+ MLAN_OID_GET_UAP_STATS_LOG = 0x0005000A,
+ /* Security Configuration Group */
+ MLAN_IOCTL_SEC_CFG = 0x00060000,
+ MLAN_OID_SEC_CFG_AUTH_MODE = 0x00060001,
+ MLAN_OID_SEC_CFG_ENCRYPT_MODE = 0x00060002,
+ MLAN_OID_SEC_CFG_WPA_ENABLED = 0x00060003,
+ MLAN_OID_SEC_CFG_ENCRYPT_KEY = 0x00060004,
+ MLAN_OID_SEC_CFG_PASSPHRASE = 0x00060005,
+ MLAN_OID_SEC_CFG_EWPA_ENABLED = 0x00060006,
+ MLAN_OID_SEC_CFG_ESUPP_MODE = 0x00060007,
+ MLAN_OID_SEC_CFG_WAPI_ENABLED = 0x00060009,
+ MLAN_OID_SEC_CFG_PORT_CTRL_ENABLED = 0x0006000A,
+#ifdef UAP_SUPPORT
+ MLAN_OID_SEC_CFG_REPORT_MIC_ERR = 0x0006000B,
+#endif
+ MLAN_OID_SEC_QUERY_KEY = 0x0006000C,
+
+ /* Rate Group */
+ MLAN_IOCTL_RATE = 0x00070000,
+ MLAN_OID_RATE_CFG = 0x00070001,
+ MLAN_OID_GET_DATA_RATE = 0x00070002,
+ MLAN_OID_SUPPORTED_RATES = 0x00070003,
+
+ /* Power Configuration Group */
+ MLAN_IOCTL_POWER_CFG = 0x00080000,
+ MLAN_OID_POWER_CFG = 0x00080001,
+ MLAN_OID_POWER_CFG_EXT = 0x00080002,
+ MLAN_OID_POWER_LOW_POWER_MODE = 0x00080003,
+
+ /* Power Management Configuration Group */
+ MLAN_IOCTL_PM_CFG = 0x00090000,
+ MLAN_OID_PM_CFG_IEEE_PS = 0x00090001,
+ MLAN_OID_PM_CFG_HS_CFG = 0x00090002,
+ MLAN_OID_PM_CFG_INACTIVITY_TO = 0x00090003,
+ MLAN_OID_PM_CFG_DEEP_SLEEP = 0x00090004,
+ MLAN_OID_PM_CFG_SLEEP_PD = 0x00090005,
+ MLAN_OID_PM_CFG_PS_CFG = 0x00090006,
+ MLAN_OID_PM_CFG_SLEEP_PARAMS = 0x00090008,
+#ifdef UAP_SUPPORT
+ MLAN_OID_PM_CFG_PS_MODE = 0x00090009,
+#endif /* UAP_SUPPORT */
+ MLAN_OID_PM_INFO = 0x0009000A,
+ MLAN_OID_PM_HS_WAKEUP_REASON = 0x0009000B,
+ MLAN_OID_PM_MGMT_FILTER = 0x0009000C,
+ MLAN_OID_PM_CFG_BCN_TIMEOUT = 0x0009000D,
+
+ /* WMM Configuration Group */
+ MLAN_IOCTL_WMM_CFG = 0x000A0000,
+ MLAN_OID_WMM_CFG_ENABLE = 0x000A0001,
+ MLAN_OID_WMM_CFG_QOS = 0x000A0002,
+ MLAN_OID_WMM_CFG_ADDTS = 0x000A0003,
+ MLAN_OID_WMM_CFG_DELTS = 0x000A0004,
+ MLAN_OID_WMM_CFG_QUEUE_CONFIG = 0x000A0005,
+ MLAN_OID_WMM_CFG_QUEUE_STATS = 0x000A0006,
+ MLAN_OID_WMM_CFG_QUEUE_STATUS = 0x000A0007,
+ MLAN_OID_WMM_CFG_TS_STATUS = 0x000A0008,
+
+ /* WPS Configuration Group */
+ MLAN_IOCTL_WPS_CFG = 0x000B0000,
+ MLAN_OID_WPS_CFG_SESSION = 0x000B0001,
+
+ /* 802.11n Configuration Group */
+ MLAN_IOCTL_11N_CFG = 0x000C0000,
+ MLAN_OID_11N_CFG_TX = 0x000C0001,
+ MLAN_OID_11N_HTCAP_CFG = 0x000C0002,
+ MLAN_OID_11N_CFG_ADDBA_REJECT = 0x000C0003,
+ MLAN_OID_11N_CFG_AGGR_PRIO_TBL = 0x000C0004,
+ MLAN_OID_11N_CFG_ADDBA_PARAM = 0x000C0005,
+ MLAN_OID_11N_CFG_MAX_TX_BUF_SIZE = 0x000C0006,
+ MLAN_OID_11N_CFG_AMSDU_AGGR_CTRL = 0x000C0007,
+ MLAN_OID_11N_CFG_SUPPORTED_MCS_SET = 0x000C0008,
+ MLAN_OID_11N_CFG_TX_BF_CAP = 0x000C0009,
+ MLAN_OID_11N_CFG_TX_BF_CFG = 0x000C000A,
+ MLAN_OID_11N_CFG_STREAM_CFG = 0x000C000B,
+ MLAN_OID_11N_CFG_DELBA = 0x000C000C,
+ MLAN_OID_11N_CFG_REJECT_ADDBA_REQ = 0x000C000D,
+ MLAN_OID_11N_CFG_COEX_RX_WINSIZE = 0x000C000E,
+ MLAN_OID_11N_CFG_IBSS_AMPDU_PARAM = 0x000C0010,
+ MLAN_OID_11N_CFG_MIN_BA_THRESHOLD = 0x000C0011,
+
+ /* 802.11d Configuration Group */
+ MLAN_IOCTL_11D_CFG = 0x000D0000,
+#ifdef STA_SUPPORT
+ MLAN_OID_11D_CFG_ENABLE = 0x000D0001,
+ MLAN_OID_11D_CLR_CHAN_TABLE = 0x000D0002,
+#endif /* STA_SUPPORT */
+#ifdef UAP_SUPPORT
+ MLAN_OID_11D_DOMAIN_INFO = 0x000D0003,
+#endif
+ MLAN_OID_11D_DOMAIN_INFO_EXT = 0x000D0004,
+
+ /* Register Memory Access Group */
+ MLAN_IOCTL_REG_MEM = 0x000E0000,
+ MLAN_OID_REG_RW = 0x000E0001,
+ MLAN_OID_EEPROM_RD = 0x000E0002,
+ MLAN_OID_MEM_RW = 0x000E0003,
+
+ /* Multi-Radio Configuration Group */
+ MLAN_IOCTL_MFR_CFG = 0x00100000,
+ /* 802.11h Configuration Group */
+ MLAN_IOCTL_11H_CFG = 0x00110000,
+ MLAN_OID_11H_CHANNEL_CHECK = 0x00110001,
+ MLAN_OID_11H_LOCAL_POWER_CONSTRAINT = 0x00110002,
+ MLAN_OID_11H_DFS_TESTING = 0x00110003,
+ MLAN_OID_11H_CHAN_REPORT_REQUEST = 0x00110004,
+ MLAN_OID_11H_CHAN_SWITCH_COUNT = 0x00110005,
+ MLAN_OID_11H_CHAN_NOP_INFO = 0x00110006,
+ MLAN_OID_11H_DFS_W53_CFG = 0x00110008,
+
+ /* 802.11n Configuration Group RANDYTODO for value assign */
+ MLAN_IOCTL_11AC_CFG = 0x00120000,
+ MLAN_OID_11AC_VHT_CFG = 0x00120001,
+ MLAN_OID_11AC_CFG_SUPPORTED_MCS_SET = 0x00120002,
+ MLAN_OID_11AC_OPERMODE_CFG = 0x00120003,
+
+ /* 802.11ax Configuration Group */
+ MLAN_IOCTL_11AX_CFG = 0x00170000,
+ MLAN_OID_11AX_HE_CFG = 0x00170001,
+ MLAN_OID_11AX_CMD_CFG = 0x00170002,
+ MLAN_OID_11AX_TWT_CFG = 0x00170003,
+
+ /* Miscellaneous Configuration Group */
+ MLAN_IOCTL_MISC_CFG = 0x00200000,
+ MLAN_OID_MISC_GEN_IE = 0x00200001,
+ MLAN_OID_MISC_REGION = 0x00200002,
+ MLAN_OID_MISC_WARM_RESET = 0x00200003,
+#ifdef SDIO
+ MLAN_OID_MISC_SDIO_MPA_CTRL = 0x00200006,
+#endif
+ MLAN_OID_MISC_HOST_CMD = 0x00200007,
+ MLAN_OID_MISC_SYS_CLOCK = 0x00200009,
+ MLAN_OID_MISC_SOFT_RESET = 0x0020000A,
+ MLAN_OID_MISC_WWS = 0x0020000B,
+ MLAN_OID_MISC_ASSOC_RSP = 0x0020000C,
+ MLAN_OID_MISC_INIT_SHUTDOWN = 0x0020000D,
+ MLAN_OID_MISC_CUSTOM_IE = 0x0020000F,
+ MLAN_OID_MISC_TX_DATAPAUSE = 0x00200012,
+ MLAN_OID_MISC_IP_ADDR = 0x00200013,
+ MLAN_OID_MISC_MAC_CONTROL = 0x00200014,
+ MLAN_OID_MISC_MEF_CFG = 0x00200015,
+ MLAN_OID_MISC_CFP_CODE = 0x00200016,
+ MLAN_OID_MISC_COUNTRY_CODE = 0x00200017,
+ MLAN_OID_MISC_THERMAL = 0x00200018,
+ MLAN_OID_MISC_RX_MGMT_IND = 0x00200019,
+ MLAN_OID_MISC_SUBSCRIBE_EVENT = 0x0020001A,
+#ifdef DEBUG_LEVEL1
+ MLAN_OID_MISC_DRVDBG = 0x0020001B,
+#endif
+ MLAN_OID_MISC_HOTSPOT_CFG = 0x0020001C,
+ MLAN_OID_MISC_OTP_USER_DATA = 0x0020001D,
+#ifdef USB
+ MLAN_OID_MISC_USB_AGGR_CTRL = 0x0020001F,
+#endif
+ MLAN_OID_MISC_TXCONTROL = 0x00200020,
+#ifdef STA_SUPPORT
+ MLAN_OID_MISC_EXT_CAP_CFG = 0x00200021,
+#endif
+#if defined(STA_SUPPORT)
+ MLAN_OID_MISC_PMFCFG = 0x00200022,
+#endif
+#ifdef WIFI_DIRECT_SUPPORT
+ MLAN_OID_MISC_WIFI_DIRECT_CONFIG = 0x00200025,
+#endif
+ MLAN_OID_MISC_LOW_PWR_MODE = 0x00200029,
+ MLAN_OID_MISC_MEF_FLT_CFG = 0x0020002A,
+ MLAN_OID_MISC_DFS_REAPTER_MODE = 0x0020002B,
+#ifdef RX_PACKET_COALESCE
+ MLAN_OID_MISC_RX_PACKET_COALESCE = 0x0020002C,
+#endif
+ MLAN_OID_MISC_COALESCE_CFG = 0x0020002E,
+ MLAN_OID_MISC_GET_SENSOR_TEMP = 0x00200030,
+ MLAN_OID_MISC_GTK_REKEY_OFFLOAD = 0x00200037,
+ MLAN_OID_MISC_OPER_CLASS = 0x00200038,
+ MLAN_OID_MISC_PMIC_CFG = 0x00200039,
+ MLAN_OID_MISC_IND_RST_CFG = 0x00200040,
+ MLAN_OID_MISC_GET_TSF = 0x00200045,
+ MLAN_OID_MISC_GET_CHAN_REGION_CFG = 0x00200046,
+ MLAN_OID_MISC_CLOUD_KEEP_ALIVE = 0x00200048,
+ MLAN_OID_MISC_OPER_CLASS_CHECK = 0x00200049,
+
+ MLAN_OID_MISC_CWMODE_CTRL = 0x00200051,
+ MLAN_OID_MISC_AGGR_CTRL = 0x00200052,
+ MLAN_OID_MISC_DYN_BW = 0x00200053,
+ MLAN_OID_MISC_FW_DUMP_EVENT = 0x00200054,
+ MLAN_OID_MISC_PER_PKT_CFG = 0x00200055,
+
+ MLAN_OID_MISC_ROBUSTCOEX = 0x00200056,
+ MLAN_OID_MISC_GET_TX_RX_HISTOGRAM = 0x00200057,
+ MLAN_OID_MISC_CFP_INFO = 0x00200060,
+ MLAN_OID_MISC_BOOT_SLEEP = 0x00200061,
+#if defined(PCIE)
+ MLAN_OID_MISC_SSU = 0x00200062,
+#endif
+ MLAN_OID_MISC_DMCS_CONFIG = 0x00200065,
+ MLAN_OID_MISC_RX_ABORT_CFG = 0x00200066,
+ MLAN_OID_MISC_RX_ABORT_CFG_EXT = 0x00200067,
+ MLAN_OID_MISC_TX_AMPDU_PROT_MODE = 0x00200068,
+ MLAN_OID_MISC_RATE_ADAPT_CFG = 0x00200069,
+ MLAN_OID_MISC_CCK_DESENSE_CFG = 0x00200070,
+ MLAN_OID_MISC_GET_CHAN_TRPC_CFG = 0x00200072,
+ MLAN_OID_MISC_BAND_STEERING = 0x00200073,
+ MLAN_OID_MISC_GET_REGIONPWR_CFG = 0x00200074,
+ MLAN_OID_MISC_RF_TEST_GENERIC = 0x00200075,
+ MLAN_OID_MISC_RF_TEST_TX_CONT = 0x00200076,
+ MLAN_OID_MISC_RF_TEST_TX_FRAME = 0x00200077,
+ MLAN_OID_MISC_ARB_CONFIG = 0x00200078,
+ MLAN_OID_MISC_BEACON_STUCK = 0x00200079,
+ MLAN_OID_MISC_CFP_TABLE = 0x0020007A,
+ MLAN_OID_MISC_RANGE_EXT = 0x0020007B,
+ MLAN_OID_MISC_DOT11MC_UNASSOC_FTM_CFG = 0x0020007C,
+ MLAN_OID_MISC_TP_STATE = 0x0020007D,
+};
+
+/** Sub command size */
+#define MLAN_SUB_COMMAND_SIZE 4
+
+/** Enumeration for the action of IOCTL request */
+enum _mlan_act_ioctl {
+ MLAN_ACT_SET = 1,
+ MLAN_ACT_GET,
+ MLAN_ACT_CANCEL,
+ MLAN_ACT_CLEAR,
+ MLAN_ACT_RESET,
+ MLAN_ACT_DEFAULT
+};
+
+/** Enumeration for generic enable/disable */
+enum _mlan_act_generic { MLAN_ACT_DISABLE = 0, MLAN_ACT_ENABLE = 1 };
+
+/** Enumeration for scan mode */
+enum _mlan_scan_mode {
+ MLAN_SCAN_MODE_UNCHANGED = 0,
+ MLAN_SCAN_MODE_BSS,
+ MLAN_SCAN_MODE_IBSS,
+ MLAN_SCAN_MODE_ANY
+};
+
+/** Enumeration for scan type */
+enum _mlan_scan_type {
+ MLAN_SCAN_TYPE_UNCHANGED = 0,
+ MLAN_SCAN_TYPE_ACTIVE,
+ MLAN_SCAN_TYPE_PASSIVE,
+ MLAN_SCAN_TYPE_PASSIVE_TO_ACTIVE
+};
+
+/** Enumeration for passive to active scan */
+enum _mlan_pass_to_act_scan {
+ MLAN_PASS_TO_ACT_SCAN_UNCHANGED = 0,
+ MLAN_PASS_TO_ACT_SCAN_EN,
+ MLAN_PASS_TO_ACT_SCAN_DIS
+};
+
+/** Max number of supported rates */
+#define MLAN_SUPPORTED_RATES 32
+
+/** Mrvl Proprietary Tlv base */
+#define PROPRIETARY_TLV_BASE_ID 0x100
+
+/** RSSI scan */
+#define SCAN_RSSI(RSSI) (0x100 - ((t_u8)(RSSI)))
+
+/** Max passive scan time for each channel in milliseconds */
+#define MRVDRV_MAX_PASSIVE_SCAN_CHAN_TIME 2000
+
+/** Max active scan time for each channel in milliseconds */
+#define MRVDRV_MAX_ACTIVE_SCAN_CHAN_TIME 500
+/** Max gap time between 2 scan in milliseconds */
+#define MRVDRV_MAX_SCAN_CHAN_GAP_TIME 500
+
+/** Maximum number of probes to send on each channel */
+#define MAX_PROBES 5
+
+/** Default number of probes to send on each channel */
+#define DEFAULT_PROBES 4
+
+/**
+ * @brief Sub-structure passed in wlan_ioctl_get_scan_table_entry for each BSS
+ *
+ * Fixed field information returned for the scan response in the IOCTL
+ * response.
+ */
+typedef struct _wlan_get_scan_table_fixed {
+ /** BSSID of this network */
+ t_u8 bssid[MLAN_MAC_ADDR_LENGTH];
+ /** Channel this beacon/probe response was detected */
+ t_u8 channel;
+ /** RSSI for the received packet */
+ t_u8 rssi;
+ /** channel load */
+ t_u8 chan_load;
+ /** TSF value in microseconds from the firmware at packet reception */
+ t_u64 network_tsf;
+} wlan_get_scan_table_fixed;
+
+/** mlan_802_11_ssid data structure */
+typedef struct _mlan_802_11_ssid {
+ /** SSID Length */
+ t_u32 ssid_len;
+ /** SSID information field */
+ t_u8 ssid[MLAN_MAX_SSID_LENGTH];
+} mlan_802_11_ssid, *pmlan_802_11_ssid;
+
+typedef MLAN_PACK_START struct _tx_status_event {
+ /** packet type */
+ t_u8 packet_type;
+ /** tx_token_id */
+ t_u8 tx_token_id;
+ /** 0--success, 1--fail, 2--watchdogtimeout */
+ t_u8 status;
+} MLAN_PACK_END tx_status_event;
+
+/**
+ * Sructure to retrieve the scan table
+ */
+typedef struct {
+ /**
+ * - Zero based scan entry to start retrieval in command request
+ * - Number of scans entries returned in command response
+ */
+ t_u32 scan_number;
+ /**
+ * Buffer marker for multiple wlan_ioctl_get_scan_table_entry
+ * structures. Each struct is padded to the nearest 32 bit boundary.
+ */
+ t_u8 scan_table_entry_buf[1];
+} wlan_ioctl_get_scan_table_info;
+
+/**
+ * Structure passed in the wlan_ioctl_get_scan_table_info for each
+ * BSS returned in the WLAN_GET_SCAN_RESP IOCTL
+ */
+typedef struct _wlan_ioctl_get_scan_table_entry {
+ /**
+ * Fixed field length included in the response.
+ *
+ * Length value is included so future fixed fields can be added to the
+ * response without breaking backwards compatibility. Use the length
+ * to find the offset for the bssInfoLength field, not a sizeof()
+ * calc.
+ */
+ t_u32 fixed_field_length;
+
+ /**
+ * Length of the BSS Information (probe resp or beacon) that
+ * follows after the fixed_field_length
+ */
+ t_u32 bss_info_length;
+
+ /**
+ * Always present, fixed length data fields for the BSS
+ */
+ wlan_get_scan_table_fixed fixed_fields;
+
+ /*
+ * Probe response or beacon scanned for the BSS.
+ *
+ * Field layout:
+ * - TSF 8 octets
+ * - Beacon Interval 2 octets
+ * - Capability Info 2 octets
+ *
+ * - IEEE Infomation Elements; variable number & length per 802.11 spec
+ */
+ /* t_u8 bss_info_buffer[]; */
+} wlan_ioctl_get_scan_table_entry;
+
+/** Type definition of mlan_scan_time_params */
+typedef struct _mlan_scan_time_params {
+ /** Scan channel time for specific scan in milliseconds */
+ t_u32 specific_scan_time;
+ /** Scan channel time for active scan in milliseconds */
+ t_u32 active_scan_time;
+ /** Scan channel time for passive scan in milliseconds */
+ t_u32 passive_scan_time;
+} mlan_scan_time_params, *pmlan_scan_time_params;
+
+/** Type definition of mlan_user_scan */
+typedef struct _mlan_user_scan {
+ /** Length of scan_cfg_buf */
+ t_u32 scan_cfg_len;
+ /** Buffer of scan config */
+ t_u8 scan_cfg_buf[1];
+} mlan_user_scan, *pmlan_user_scan;
+
+/** Type definition of mlan_scan_req */
+typedef struct _mlan_scan_req {
+ /** BSS mode for scanning */
+ t_u32 scan_mode;
+ /** Scan type */
+ t_u32 scan_type;
+ /** SSID */
+ mlan_802_11_ssid scan_ssid;
+ /** Scan time parameters */
+ mlan_scan_time_params scan_time;
+ /** Scan config parameters in user scan */
+ mlan_user_scan user_scan;
+} mlan_scan_req, *pmlan_scan_req;
+
+/** Type defnition of mlan_scan_resp */
+typedef struct _mlan_scan_resp {
+ /** Number of scan result */
+ t_u32 num_in_scan_table;
+ /** Scan table */
+ t_u8 *pscan_table;
+ /* Age in seconds */
+ t_u32 age_in_secs;
+ /** channel statstics */
+ t_u8 *pchan_stats;
+ /** Number of records in the chan_stats */
+ t_u32 num_in_chan_stats;
+} mlan_scan_resp, *pmlan_scan_resp;
+
+#define EXT_SCAN_TYPE_ENH 2
+/** Type definition of mlan_scan_cfg */
+typedef struct _mlan_scan_cfg {
+ /** Scan type */
+ t_u32 scan_type;
+ /** BSS mode for scanning */
+ t_u32 scan_mode;
+ /** Scan probe */
+ t_u32 scan_probe;
+ /** Scan time parameters */
+ mlan_scan_time_params scan_time;
+ /** First passive scan then active scan */
+ t_u8 passive_to_active_scan;
+ /** Ext_scan: 0 disable, 1: enable, 2: enhance scan*/
+ t_u32 ext_scan;
+ /** scan channel gap */
+ t_u32 scan_chan_gap;
+} mlan_scan_cfg, *pmlan_scan_cfg;
+
+/** Type defnition of mlan_ds_scan for MLAN_IOCTL_SCAN */
+typedef struct _mlan_ds_scan {
+ /** Sub-command */
+ t_u32 sub_command;
+ /** Scan request/response */
+ union {
+ /** Scan request */
+ mlan_scan_req scan_req;
+ /** Scan response */
+ mlan_scan_resp scan_resp;
+ /** Scan config parameters in user scan */
+ mlan_user_scan user_scan;
+ /** Scan config parameters */
+ mlan_scan_cfg scan_cfg;
+ } param;
+} mlan_ds_scan, *pmlan_ds_scan;
+
+/*-----------------------------------------------------------------*/
+/** BSS Configuration Group */
+/*-----------------------------------------------------------------*/
+/** Enumeration for BSS mode */
+enum _mlan_bss_mode {
+ MLAN_BSS_MODE_INFRA = 1,
+ MLAN_BSS_MODE_IBSS,
+ MLAN_BSS_MODE_AUTO
+};
+
+/** Maximum key length */
+#define MLAN_MAX_KEY_LENGTH 32
+
+/** Maximum atim window in milliseconds */
+#define MLAN_MAX_ATIM_WINDOW 50
+
+/** Minimum beacon interval */
+#define MLAN_MIN_BEACON_INTERVAL 20
+/** Maximum beacon interval */
+#define MLAN_MAX_BEACON_INTERVAL 1000
+/** Default beacon interval */
+#define MLAN_BEACON_INTERVAL 100
+
+/** Receive all packets */
+#define MLAN_PROMISC_MODE 1
+/** Receive multicast packets in multicast list */
+#define MLAN_MULTICAST_MODE 2
+/** Receive all multicast packets */
+#define MLAN_ALL_MULTI_MODE 4
+
+/** Maximum size of multicast list */
+#define MLAN_MAX_MULTICAST_LIST_SIZE 32
+
+/** mlan_multicast_list data structure for MLAN_OID_BSS_MULTICAST_LIST */
+typedef struct _mlan_multicast_list {
+ /** Multicast mode */
+ t_u32 mode;
+ /** Number of multicast addresses in the list */
+ t_u32 num_multicast_addr;
+ /** Multicast address list */
+ mlan_802_11_mac_addr mac_list[MLAN_MAX_MULTICAST_LIST_SIZE];
+} mlan_multicast_list, *pmlan_multicast_list;
+
+/** Max channel */
+#define MLAN_MAX_CHANNEL 165
+/** Maximum number of channels in table */
+#define MLAN_MAX_CHANNEL_NUM 128
+
+/** Channel/frequence for MLAN_OID_BSS_CHANNEL */
+typedef struct _chan_freq {
+ /** Channel Number */
+ t_u32 channel;
+ /** Frequency of this Channel */
+ t_u32 freq;
+} chan_freq;
+
+/** mlan_chan_list data structure for MLAN_OID_BSS_CHANNEL_LIST */
+typedef struct _mlan_chan_list {
+ /** Number of channel */
+ t_u32 num_of_chan;
+ /** Channel-Frequency table */
+ chan_freq cf[MLAN_MAX_CHANNEL_NUM];
+} mlan_chan_list;
+
+/* This channel is disabled.*/
+#define CHAN_FLAGS_DISABLED MBIT(0)
+/* do not initiate radiation, this includes sending probe requests or beaconing
+ */
+#define CHAN_FLAGS_NO_IR MBIT(1)
+/* Radar detection is required on this channel */
+#define CHAN_FLAGS_RADAR MBIT(3)
+/* extension channel above this channel is not permitted */
+#define CHAN_FLAGS_NO_HT40PLUS MBIT(4)
+/* extension channel below this channel is not permitted */
+#define CHAN_FLAGS_NO_HT40MINUS MBIT(5)
+/* OFDM is not allowed on this channel */
+#define CHAN_FLAGS_NO_OFDM MBIT(6)
+/** 80Mhz can not used on this channel */
+#define CHAN_FLAGS_NO_80MHZ MBIT(7)
+/** 180Mhz can not used on this channel */
+#define CHAN_FLAGS_NO_160MHZ MBIT(8)
+/* Only indoor use is permitted on this channel */
+#define CHAN_FLAGS_INDOOR_ONLY MBIT(9)
+/* IR operation is allowed on this channel if it's
+ * connected concurrently to a BSS on the same channel on
+ * the 2 GHz band or to a channel in the same UNII band (on the 5 GHz
+ * band), and IEEE80211_CHAN_RADAR is not set */
+#define CHAN_FLAGS_IR_CONCURRENT MBIT(10)
+/* 20 MHz operation is not allowed on this channel */
+#define CHAN_FLAGS_20MHZ MBIT(11)
+/* 10 MHz operation is not allowed on this channel */
+#define CHAN_FLAGS_NO_10MHZ MBIT(12)
+/** This channel's flag is valid */
+#define CHAN_FLAGS_MAX MBIT(31)
+
+/** Maximum response buffer length */
+#define ASSOC_RSP_BUF_SIZE 500
+
+/** Type definition of mlan_ds_misc_assoc_rsp for MLAN_OID_MISC_ASSOC_RSP */
+typedef struct _mlan_ds_misc_assoc_rsp {
+ /** Associate response buffer */
+ t_u8 assoc_resp_buf[ASSOC_RSP_BUF_SIZE];
+ /** Response buffer length */
+ t_u32 assoc_resp_len;
+} mlan_ds_misc_assoc_rsp, *pmlan_ds_misc_assoc_rsp;
+
+/** mlan_ssid_bssid data structure for
+ * MLAN_OID_BSS_START and MLAN_OID_BSS_FIND_BSS
+ */
+typedef struct _mlan_ssid_bssid {
+ /** SSID */
+ mlan_802_11_ssid ssid;
+ /** BSSID */
+ mlan_802_11_mac_addr bssid;
+ /** index in BSSID list, start from 1 */
+ t_u32 idx;
+ /** Receive signal strength in dBm */
+ t_s32 rssi;
+ /**channel*/
+ t_u16 channel;
+ /**mobility domain value*/
+ t_u16 ft_md;
+ /**ft capability*/
+ t_u8 ft_cap;
+ /**band*/
+ t_u16 bss_band;
+ /** channel flag */
+ t_u32 channel_flags;
+ /** host mlme flag*/
+ t_u8 host_mlme;
+ /** assoicate resp frame/ie from firmware */
+ mlan_ds_misc_assoc_rsp assoc_rsp;
+} mlan_ssid_bssid, *pmlan_ssid_bssid;
+
+/** Data structure of WMM ECW */
+typedef struct _wmm_ecw_t {
+#ifdef BIG_ENDIAN_SUPPORT
+ /** Maximum Ecw */
+ t_u8 ecw_max : 4;
+ /** Minimum Ecw */
+ t_u8 ecw_min : 4;
+#else
+ /** Minimum Ecw */
+ t_u8 ecw_min : 4;
+ /** Maximum Ecw */
+ t_u8 ecw_max : 4;
+#endif /* BIG_ENDIAN_SUPPORT */
+} wmm_ecw_t, *pwmm_ecw_t;
+
+/** Data structure of WMM Aci/Aifsn */
+typedef struct _wmm_aci_aifsn_t {
+#ifdef BIG_ENDIAN_SUPPORT
+ /** Reserved */
+ t_u8 reserved : 1;
+ /** Aci */
+ t_u8 aci : 2;
+ /** Acm */
+ t_u8 acm : 1;
+ /** Aifsn */
+ t_u8 aifsn : 4;
+#else
+ /** Aifsn */
+ t_u8 aifsn : 4;
+ /** Acm */
+ t_u8 acm : 1;
+ /** Aci */
+ t_u8 aci : 2;
+ /** Reserved */
+ t_u8 reserved : 1;
+#endif /* BIG_ENDIAN_SUPPORT */
+} wmm_aci_aifsn_t, *pwmm_aci_aifsn_t;
+
+/** Data structure of WMM AC parameters */
+typedef struct _wmm_ac_parameters_t {
+ wmm_aci_aifsn_t aci_aifsn; /**< AciAifSn */
+ wmm_ecw_t ecw; /**< Ecw */
+ t_u16 tx_op_limit; /**< Tx op limit */
+} wmm_ac_parameters_t, *pwmm_ac_parameters_t;
+
+/** mlan_deauth_param */
+typedef struct _mlan_deauth_param {
+ /** STA mac addr */
+ t_u8 mac_addr[MLAN_MAC_ADDR_LENGTH];
+ /** deauth reason */
+ t_u16 reason_code;
+} mlan_deauth_param;
+
+#ifdef UAP_SUPPORT
+/** UAP FLAG: Host based */
+#define UAP_FLAG_HOST_BASED MBIT(0)
+/** UAP FLAG: Host mlme */
+#define UAP_FLAG_HOST_MLME MBIT(1)
+
+/** Maximum packet forward control value */
+#define MAX_PKT_FWD_CTRL 15
+/** Maximum BEACON period */
+#define MAX_BEACON_PERIOD 4000
+/** Minimum BEACON period */
+#define MIN_BEACON_PERIOD 50
+/** Maximum DTIM period */
+#define MAX_DTIM_PERIOD 100
+/** Minimum DTIM period */
+#define MIN_DTIM_PERIOD 1
+/** Maximum TX Power Limit */
+#define MAX_TX_POWER 20
+/** Minimum TX Power Limit */
+#define MIN_TX_POWER 0
+/** MAX station count */
+#define MAX_STA_COUNT 64
+/** Maximum RTS threshold */
+#define MAX_RTS_THRESHOLD 2347
+/** Maximum fragmentation threshold */
+#define MAX_FRAG_THRESHOLD 2346
+/** Minimum fragmentation threshold */
+#define MIN_FRAG_THRESHOLD 256
+/** data rate 54 M */
+#define DATA_RATE_54M 108
+/** Maximum value of bcast_ssid_ctl */
+#define MAX_BCAST_SSID_CTL 2
+/** antenna A */
+#define ANTENNA_MODE_A 0
+/** antenna B */
+#define ANTENNA_MODE_B 1
+/** transmit antenna */
+#define TX_ANTENNA 1
+/** receive antenna */
+#define RX_ANTENNA 0
+/** Maximum stage out time */
+#define MAX_STAGE_OUT_TIME 864000
+/** Minimum stage out time */
+#define MIN_STAGE_OUT_TIME 50
+/** Maximum Retry Limit */
+#define MAX_RETRY_LIMIT 14
+
+/** Maximum group key timer in seconds */
+#define MAX_GRP_TIMER 86400
+
+/** Maximum value of 4 byte configuration */
+#define MAX_VALID_DWORD 0x7FFFFFFF /* (1 << 31) - 1 */
+
+/** default UAP BAND 2.4G */
+#define DEFAULT_UAP_BAND 0
+/** default UAP channel 6 */
+#define DEFAULT_UAP_CHANNEL 6
+
+/** Maximum data rates */
+#define MAX_DATA_RATES 14
+
+/** auto data rate */
+#define DATA_RATE_AUTO 0
+
+/**filter mode: disable */
+#define MAC_FILTER_MODE_DISABLE 0
+/**filter mode: block mac address */
+#define MAC_FILTER_MODE_ALLOW_MAC 1
+/**filter mode: block mac address */
+#define MAC_FILTER_MODE_BLOCK_MAC 2
+/** Maximum mac filter num */
+#define MAX_MAC_FILTER_NUM 64
+
+/* Bitmap for protocol to use */
+/** No security */
+#define PROTOCOL_NO_SECURITY 0x01
+/** Static WEP */
+#define PROTOCOL_STATIC_WEP 0x02
+/** WPA */
+#define PROTOCOL_WPA 0x08
+/** WPA2 */
+#define PROTOCOL_WPA2 0x20
+/** WP2 Mixed */
+#define PROTOCOL_WPA2_MIXED 0x28
+/** EAP */
+#define PROTOCOL_EAP 0x40
+/** WAPI */
+#define PROTOCOL_WAPI 0x80
+/** WPA3 SAE */
+#define PROTOCOL_WPA3_SAE 0x100
+
+/** Key_mgmt_psk */
+#define KEY_MGMT_NONE 0x04
+/** Key_mgmt_none */
+#define KEY_MGMT_PSK 0x02
+/** Key_mgmt_eap */
+#define KEY_MGMT_EAP 0x01
+/** Key_mgmt_psk_sha256 */
+#define KEY_MGMT_PSK_SHA256 0x100
+/** Key_mgmt_sae */
+#define KEY_MGMT_SAE 0x400
+/** Key_mgmt_owe */
+#define KEY_MGMT_OWE 0x200
+
+/** TKIP */
+#define CIPHER_TKIP 0x04
+/** AES CCMP */
+#define CIPHER_AES_CCMP 0x08
+
+/** Valid cipher bitmap */
+#define VALID_CIPHER_BITMAP 0x0c
+
+/** Packet forwarding to be done by FW or host */
+#define PKT_FWD_FW_BIT 0x01
+/** Intra-BSS broadcast packet forwarding allow bit */
+#define PKT_FWD_INTRA_BCAST 0x02
+/** Intra-BSS unicast packet forwarding allow bit */
+#define PKT_FWD_INTRA_UCAST 0x04
+/** Inter-BSS unicast packet forwarding allow bit */
+#define PKT_FWD_INTER_UCAST 0x08
+/** Intra-BSS unicast packet */
+#define PKT_INTRA_UCAST 0x01
+/** Inter-BSS unicast packet */
+#define PKT_INTER_UCAST 0x02
+/** Enable Host PKT forwarding */
+#define PKT_FWD_ENABLE_BIT 0x01
+
+/** Channel List Entry */
+typedef struct _channel_list {
+ /** Channel Number */
+ t_u8 chan_number;
+ /** Band Config */
+ Band_Config_t bandcfg;
+} scan_chan_list;
+
+/** mac_filter data structure */
+typedef struct _mac_filter {
+ /** mac filter mode */
+ t_u16 filter_mode;
+ /** mac adress count */
+ t_u16 mac_count;
+ /** mac address list */
+ mlan_802_11_mac_addr mac_list[MAX_MAC_FILTER_NUM];
+} mac_filter;
+
+/** wpa parameter */
+typedef struct _wpa_param {
+ /** Pairwise cipher WPA */
+ t_u8 pairwise_cipher_wpa;
+ /** Pairwise cipher WPA2 */
+ t_u8 pairwise_cipher_wpa2;
+ /** group cipher */
+ t_u8 group_cipher;
+ /** RSN replay protection */
+ t_u8 rsn_protection;
+ /** passphrase length */
+ t_u32 length;
+ /** passphrase */
+ t_u8 passphrase[64];
+ /**group key rekey time in seconds */
+ t_u32 gk_rekey_time;
+} wpa_param;
+
+/** wep key */
+typedef struct _wep_key {
+ /** key index 0-3 */
+ t_u8 key_index;
+ /** is default */
+ t_u8 is_default;
+ /** length */
+ t_u16 length;
+ /** key data */
+ t_u8 key[26];
+} wep_key;
+
+/** wep param */
+typedef struct _wep_param {
+ /** key 0 */
+ wep_key key0;
+ /** key 1 */
+ wep_key key1;
+ /** key 2 */
+ wep_key key2;
+ /** key 3 */
+ wep_key key3;
+} wep_param;
+
+/** Data structure of WMM QoS information */
+typedef struct _wmm_qos_info_t {
+#ifdef BIG_ENDIAN_SUPPORT
+ /** QoS UAPSD */
+ t_u8 qos_uapsd : 1;
+ /** Reserved */
+ t_u8 reserved : 3;
+ /** Parameter set count */
+ t_u8 para_set_count : 4;
+#else
+ /** Parameter set count */
+ t_u8 para_set_count : 4;
+ /** Reserved */
+ t_u8 reserved : 3;
+ /** QoS UAPSD */
+ t_u8 qos_uapsd : 1;
+#endif /* BIG_ENDIAN_SUPPORT */
+} wmm_qos_info_t, *pwmm_qos_info_t;
+
+/** Data structure of WMM parameter IE */
+typedef struct _wmm_parameter_t {
+ /** OuiType: 00:50:f2:02 */
+ t_u8 ouitype[4];
+ /** Oui subtype: 01 */
+ t_u8 ouisubtype;
+ /** version: 01 */
+ t_u8 version;
+ /** QoS information */
+ t_u8 qos_info;
+ /** Reserved */
+ t_u8 reserved;
+ /** AC Parameters Record WMM_AC_BE, WMM_AC_BK, WMM_AC_VI, WMM_AC_VO */
+ wmm_ac_parameters_t ac_params[MAX_AC_QUEUES];
+} wmm_parameter_t, *pwmm_parameter_t;
+
+/** MAX BG channel */
+#define MAX_BG_CHANNEL 14
+/** mlan_bss_param
+ * Note: For each entry you must enter an invalid value
+ * in the MOAL function woal_set_sys_config_invalid_data().
+ * Otherwise for a valid data an unwanted TLV will be
+ * added to that command.
+ */
+typedef struct _mlan_uap_bss_param {
+ /** AP mac addr */
+ mlan_802_11_mac_addr mac_addr;
+ /** SSID */
+ mlan_802_11_ssid ssid;
+ /** Broadcast ssid control */
+ t_u8 bcast_ssid_ctl;
+ /** Radio control: on/off */
+ t_u8 radio_ctl;
+ /** dtim period */
+ t_u8 dtim_period;
+ /** beacon period */
+ t_u16 beacon_period;
+ /** rates */
+ t_u8 rates[MAX_DATA_RATES];
+ /** Tx data rate */
+ t_u16 tx_data_rate;
+ /** Tx beacon rate */
+ t_u16 tx_beacon_rate;
+ /** multicast/broadcast data rate */
+ t_u16 mcbc_data_rate;
+ /** Tx power level in dBm */
+ t_u8 tx_power_level;
+ /** Tx antenna */
+ t_u8 tx_antenna;
+ /** Rx antenna */
+ t_u8 rx_antenna;
+ /** packet forward control */
+ t_u8 pkt_forward_ctl;
+ /** max station count */
+ t_u16 max_sta_count;
+ /** mac filter */
+ mac_filter filter;
+ /** station ageout timer in unit of 100ms */
+ t_u32 sta_ageout_timer;
+ /** PS station ageout timer in unit of 100ms */
+ t_u32 ps_sta_ageout_timer;
+ /** RTS threshold */
+ t_u16 rts_threshold;
+ /** fragmentation threshold */
+ t_u16 frag_threshold;
+ /** retry_limit */
+ t_u16 retry_limit;
+ /** pairwise update timeout in milliseconds */
+ t_u32 pairwise_update_timeout;
+ /** pairwise handshake retries */
+ t_u32 pwk_retries;
+ /** groupwise update timeout in milliseconds */
+ t_u32 groupwise_update_timeout;
+ /** groupwise handshake retries */
+ t_u32 gwk_retries;
+ /** preamble type */
+ t_u8 preamble_type;
+ /** band cfg */
+ Band_Config_t bandcfg;
+ /** channel */
+ t_u8 channel;
+ /** auth mode */
+ t_u16 auth_mode;
+ /** encryption protocol */
+ t_u16 protocol;
+ /** key managment type */
+ t_u16 key_mgmt;
+ /** wep param */
+ wep_param wep_cfg;
+ /** wpa param */
+ wpa_param wpa_cfg;
+ /** Mgmt IE passthru mask */
+ t_u32 mgmt_ie_passthru_mask;
+ /*
+ * 11n HT Cap HTCap_t ht_cap
+ */
+ /** HT Capabilities Info field */
+ t_u16 ht_cap_info;
+ /** A-MPDU Parameters field */
+ t_u8 ampdu_param;
+ /** Supported MCS Set field */
+ t_u8 supported_mcs_set[16];
+ /** HT Extended Capabilities field */
+ t_u16 ht_ext_cap;
+ /** Transmit Beamforming Capabilities field */
+ t_u32 tx_bf_cap;
+ /** Antenna Selection Capability field */
+ t_u8 asel;
+ /** Enable 2040 Coex */
+ t_u8 enable_2040coex;
+ /** key management operation */
+ t_u16 key_mgmt_operation;
+ /** BSS status */
+ t_u16 bss_status;
+#ifdef WIFI_DIRECT_SUPPORT
+ /* pre shared key */
+ t_u8 psk[MLAN_MAX_KEY_LENGTH];
+#endif /* WIFI_DIRECT_SUPPORT */
+ /** Number of channels in scan_channel_list */
+ t_u32 num_of_chan;
+ /** scan channel list in ACS mode */
+ scan_chan_list chan_list[MLAN_MAX_CHANNEL];
+ /** Wmm parameters */
+ wmm_parameter_t wmm_para;
+
+ /** uap host based config */
+ t_u32 uap_host_based_config;
+} mlan_uap_bss_param, *pmlan_uap_bss_param;
+
+/** mlan_uap_scan_channels */
+typedef struct _mlan_uap_scan_channels {
+ /** flag for remove nop channel*/
+ t_u8 remove_nop_channel;
+ /** num of removed channel */
+ t_u8 num_remvoed_channel;
+ /** Number of channels in scan_channel_list */
+ t_u32 num_of_chan;
+ /** scan channel list in ACS mode */
+ scan_chan_list chan_list[MLAN_MAX_CHANNEL];
+} mlan_uap_scan_channels;
+
+/** mlan_uap_oper_ctrl */
+typedef struct _mlan_uap_oper_ctrl {
+ /** control value
+ * 0: do nothing,
+ * 2: uap stops and restarts automaticaly
+ */
+ t_u16 ctrl_value;
+ /** channel opt
+ * 1: uap restart on default 2.4G/channel 6
+ * 2: uap restart on the band/channel configured by driver previously
+ * 3: uap restart on the band/channel specified by band_cfg and channel
+ */
+ t_u16 chan_opt;
+ /** band cfg 0
+ * 0: 20Mhz 2: 40 Mhz 3: 80Mhz
+ */
+ t_u8 band_cfg;
+ /** channel */
+ t_u8 channel;
+} mlan_uap_oper_ctrl;
+
+/** mlan_uap_acs_scan */
+typedef struct _mlan_uap_acs_scan {
+ /** band */
+ Band_Config_t bandcfg;
+ /** channel */
+ t_u8 chan;
+} mlan_uap_acs_scan;
+
+/** station is authorized (802.1X) */
+#define STA_FLAG_AUTHORIZED MBIT(1)
+/** Station is capable of receiving frames with short barker preamble */
+#define STA_FLAG_SHORT_PREAMBLE MBIT(2)
+/** station is WME/QoS capable */
+#define STA_FLAG_WME MBIT(3)
+/** station uses management frame protection */
+#define STA_FLAG_MFP MBIT(4)
+/** station is authenticated */
+#define STA_FLAG_AUTHENTICATED MBIT(5)
+/** station is a TDLS peer */
+#define STA_FLAG_TDLS_PEER MBIT(6)
+/** station is associated */
+#define STA_FLAG_ASSOCIATED MBIT(7)
+/** mlan_ds_sta_info */
+typedef struct _mlan_ds_sta_info {
+ /** aid */
+ t_u16 aid;
+ /** peer_mac */
+ t_u8 peer_mac[MLAN_MAC_ADDR_LENGTH];
+ /** Listen Interval */
+ int listen_interval;
+ /** Capability Info */
+ t_u16 cap_info;
+ /** station flag */
+ t_u32 sta_flags;
+ /** tlv len */
+ t_u16 tlv_len;
+ /** tlv start */
+ t_u8 tlv[];
+} mlan_ds_sta_info;
+#endif
+
+#ifdef WIFI_DIRECT_SUPPORT
+/** mode: disable wifi direct */
+#define WIFI_DIRECT_MODE_DISABLE 0
+/** mode: listen */
+#define WIFI_DIRECT_MODE_LISTEN 1
+/** mode: GO */
+#define WIFI_DIRECT_MODE_GO 2
+/** mode: client */
+#define WIFI_DIRECT_MODE_CLIENT 3
+/** mode: find */
+#define WIFI_DIRECT_MODE_FIND 4
+/** mode: stop find */
+#define WIFI_DIRECT_MODE_STOP_FIND 5
+#endif
+
+/** Type definition of mlan_ds_bss for MLAN_IOCTL_BSS */
+typedef struct _mlan_ds_bss {
+ /** Sub-command */
+ t_u32 sub_command;
+ /** BSS parameter */
+ union {
+ /** SSID-BSSID for MLAN_OID_BSS_START */
+ mlan_ssid_bssid ssid_bssid;
+ /** BSSID for MLAN_OID_BSS_STOP */
+ mlan_802_11_mac_addr bssid;
+ /** BSS mode for MLAN_OID_BSS_MODE */
+ t_u32 bss_mode;
+ /** BSS channel/frequency for MLAN_OID_BSS_CHANNEL */
+ chan_freq bss_chan;
+ /** BSS channel list for MLAN_OID_BSS_CHANNEL_LIST */
+ mlan_chan_list chanlist;
+ /** MAC address for MLAN_OID_BSS_MAC_ADDR */
+ mlan_802_11_mac_addr mac_addr;
+ /** Multicast list for MLAN_OID_BSS_MULTICAST_LIST */
+ mlan_multicast_list multicast_list;
+ /** Beacon interval for MLAN_OID_IBSS_BCN_INTERVAL */
+ t_u32 bcn_interval;
+ /** ATIM window for MLAN_OID_IBSS_ATIM_WINDOW */
+ t_u32 atim_window;
+ /** deauth param for MLAN_OID_BSS_STOP & MLAN_OID_UAP_DEAUTH_STA
+ */
+ mlan_deauth_param deauth_param;
+#ifdef UAP_SUPPORT
+ /** host based flag for MLAN_OID_BSS_START */
+ t_u8 host_based;
+ /** BSS param for AP mode for MLAN_OID_UAP_BSS_CONFIG */
+ mlan_uap_bss_param bss_config;
+ /** AP Wmm parameters for MLAN_OID_UAP_CFG_WMM_PARAM */
+ wmm_parameter_t ap_wmm_para;
+ /** ap scan channels for MLAN_OID_UAP_SCAN_CHANNELS*/
+ mlan_uap_scan_channels ap_scan_channels;
+ /** ap channel for MLAN_OID_UAP_CHANNEL*/
+ chan_band_info ap_channel;
+ /** ap operation control for MLAN_OID_UAP_OPER_CTRL*/
+ mlan_uap_oper_ctrl ap_oper_ctrl;
+ /** AP acs scan MLAN_OID_UAP_ACS_SCAN */
+ mlan_uap_acs_scan ap_acs_scan;
+#endif
+#if defined(STA_SUPPORT) && defined(UAP_SUPPORT)
+ /** BSS role for MLAN_OID_BSS_ROLE */
+ t_u8 bss_role;
+#endif
+#ifdef WIFI_DIRECT_SUPPORT
+ /** wifi direct mode for MLAN_OID_WIFI_DIRECT_MODE */
+ t_u16 wfd_mode;
+#endif
+#ifdef STA_SUPPORT
+ /** Listen interval for MLAN_OID_BSS_LISTEN_INTERVAL */
+ t_u16 listen_interval;
+ /** STA channel info for MLAN_OID_BSS_CHAN_INFO */
+ chan_band_info sta_channel;
+#endif
+#ifdef UAP_SUPPORT
+ /** STA info for MLAN_OID_UAP_ADD_STATION */
+ mlan_ds_sta_info sta_info;
+#endif
+ } param;
+} mlan_ds_bss, *pmlan_ds_bss;
+
+/* OTP Region info */
+typedef MLAN_PACK_START struct _otp_region_info {
+ t_u8 country_code[2];
+ t_u8 region_code;
+ t_u8 environment;
+ t_u16 force_reg : 1;
+ t_u16 reserved : 15;
+} MLAN_PACK_END otp_region_info_t;
+
+/** Type definition of mlan_ds_custom_reg_domain */
+typedef struct _mlan_ds_custom_reg_domain {
+ otp_region_info_t region;
+ /** num of 2g channels in custom_reg_domain */
+ t_u8 num_bg_chan;
+ /** num of 5g channels in custom_reg_domain */
+ t_u8 num_a_chan;
+ /** cfp table */
+ chan_freq_power_t cfp_tbl[];
+} mlan_ds_custom_reg_domain;
+/*-----------------------------------------------------------------*/
+/** Radio Control Group */
+/*-----------------------------------------------------------------*/
+/** Enumeration for band */
+enum _mlan_band_def {
+ BAND_B = 1,
+ BAND_G = 2,
+ BAND_A = 4,
+ BAND_GN = 8,
+ BAND_AN = 16,
+ BAND_GAC = 32,
+ BAND_AAC = 64,
+ BAND_GAX = 256,
+ BAND_AAX = 512,
+
+};
+
+/** Channel bandwidth */
+#define CHANNEL_BW_20MHZ 0
+#define CHANNEL_BW_40MHZ_ABOVE 1
+#define CHANNEL_BW_40MHZ_BELOW 3
+/** secondary channel is 80Mhz bandwidth for 11ac */
+#define CHANNEL_BW_80MHZ 4
+#define CHANNEL_BW_160MHZ 5
+
+/** RF antenna selection */
+#define RF_ANTENNA_MASK(n) ((1 << (n)) - 1)
+/** RF antenna auto select */
+#define RF_ANTENNA_AUTO 0xFFFF
+
+/** Type definition of mlan_ds_band_cfg for MLAN_OID_BAND_CFG */
+typedef struct _mlan_ds_band_cfg {
+ /** Infra band */
+ t_u32 config_bands;
+ /** Ad-hoc start band */
+ t_u32 adhoc_start_band;
+ /** Ad-hoc start channel */
+ t_u32 adhoc_channel;
+ /** fw supported band */
+ t_u32 fw_bands;
+} mlan_ds_band_cfg;
+
+/** Type definition of mlan_ds_ant_cfg for MLAN_OID_ANT_CFG */
+typedef struct _mlan_ds_ant_cfg {
+ /** Tx antenna mode */
+ t_u32 tx_antenna;
+ /** Rx antenna mode */
+ t_u32 rx_antenna;
+} mlan_ds_ant_cfg, *pmlan_ds_ant_cfg;
+/** Type definition of mlan_ds_mimo_switch for MLAN_OID_MIMO_SWITCH */
+typedef struct _mlan_ds_mimo_switch {
+ /** Tx antenna mode */
+ t_u8 txpath_antmode;
+ /** Rx antenna mode */
+ t_u8 rxpath_antmode;
+} mlan_ds_mimo_switch, *pmlan_ds_mimo_switch;
+/** Type definition of mlan_ds_ant_cfg_1x1 for MLAN_OID_ANT_CFG */
+typedef struct _mlan_ds_ant_cfg_1x1 {
+ /** Antenna mode */
+ t_u32 antenna;
+ /** Evaluate time */
+ t_u16 evaluate_time;
+ /** Current antenna */
+ t_u16 current_antenna;
+} mlan_ds_ant_cfg_1x1, *pmlan_ds_ant_cfg_1x1;
+
+/** Type definition of mlan_ds_remain_chan for MLAN_OID_REMAIN_CHAN_CFG */
+typedef struct _mlan_ds_remain_chan {
+ /** remove flag */
+ t_u16 remove;
+ /** status */
+ t_u8 status;
+ /** Band cfg */
+ Band_Config_t bandcfg;
+ /** channel */
+ t_u8 channel;
+ /** remain time: Unit ms*/
+ t_u32 remain_period;
+} mlan_ds_remain_chan, *pmlan_ds_remain_chan;
+
+/** Type definition of mlan_ds_radio_cfg for MLAN_IOCTL_RADIO_CFG */
+typedef struct _mlan_ds_radio_cfg {
+ /** Sub-command */
+ t_u32 sub_command;
+ /** Radio control parameter */
+ union {
+ /** Radio on/off for MLAN_OID_RADIO_CTRL */
+ t_u32 radio_on_off;
+ /** Band info for MLAN_OID_BAND_CFG */
+ mlan_ds_band_cfg band_cfg;
+ /** Antenna info for MLAN_OID_ANT_CFG */
+ mlan_ds_ant_cfg ant_cfg;
+ /** Antenna mode for MLAN_OID_MIMO_SWITCH */
+ mlan_ds_mimo_switch mimo_switch_cfg;
+ /** Antenna info for MLAN_OID_ANT_CFG */
+ mlan_ds_ant_cfg_1x1 ant_cfg_1x1;
+ /** remain on channel for MLAN_OID_REMAIN_CHAN_CFG */
+ mlan_ds_remain_chan remain_chan;
+ } param;
+} mlan_ds_radio_cfg, *pmlan_ds_radio_cfg;
+
+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 COALESCE_MAX_RULES 8
+#define COALESCE_MAX_BYTESEQ 4 /* non-adjustable */
+#define COALESCE_MAX_FILTERS 4
+#define MAX_COALESCING_DELAY 100 /* in msecs */
+#define MAX_PATTERN_LEN 20
+#define MAX_OFFSET_LEN 100
+
+struct filt_field_param {
+ t_u8 operation;
+ t_u8 operand_len;
+ t_u16 offset;
+ t_u8 operand_byte_stream[COALESCE_MAX_BYTESEQ];
+};
+
+struct coalesce_rule {
+ t_u16 max_coalescing_delay;
+ t_u8 num_of_fields;
+ t_u8 pkt_type;
+ struct filt_field_param params[COALESCE_MAX_FILTERS];
+};
+
+typedef struct _mlan_ds_coalesce_cfg {
+ t_u16 num_of_rules;
+ struct coalesce_rule rule[COALESCE_MAX_RULES];
+} mlan_ds_coalesce_cfg;
+
+/*-----------------------------------------------------------------*/
+/** SNMP MIB Group */
+/*-----------------------------------------------------------------*/
+/** Type definition of mlan_ds_snmp_mib for MLAN_IOCTL_SNMP_MIB */
+typedef struct _mlan_ds_snmp_mib {
+ /** Sub-command */
+ t_u32 sub_command;
+ /** SNMP MIB parameter */
+ union {
+ /** RTS threshold for MLAN_OID_SNMP_MIB_RTS_THRESHOLD */
+ t_u32 rts_threshold;
+ /** Fragment threshold for MLAN_OID_SNMP_MIB_FRAG_THRESHOLD */
+ t_u32 frag_threshold;
+ /** Retry count for MLAN_OID_SNMP_MIB_RETRY_COUNT */
+ t_u32 retry_count;
+ /** OID value for MLAN_OID_SNMP_MIB_DOT11D/H */
+ t_u32 oid_value;
+ /** DTIM period for MLAN_OID_SNMP_MIB_DTIM_PERIOD */
+ t_u32 dtim_period;
+ /** Singal_ext Enable for MLAN_OID_SNMP_MIB_SIGNALEXT_ENABLE */
+ t_u8 signalext_enable;
+ /** Control deauth when uap switch channel */
+ t_u8 deauthctrl;
+ } param;
+} mlan_ds_snmp_mib, *pmlan_ds_snmp_mib;
+
+/*-----------------------------------------------------------------*/
+/** Status Information Group */
+/*-----------------------------------------------------------------*/
+/** Enumeration for ad-hoc status */
+enum _mlan_adhoc_status {
+ ADHOC_IDLE,
+ ADHOC_STARTED,
+ ADHOC_JOINED,
+ ADHOC_COALESCED,
+ ADHOC_STARTING
+};
+
+typedef struct _mlan_ds_get_stats_org {
+ /** Statistics counter */
+ /** Multicast transmitted frame count */
+ t_u32 mcast_tx_frame;
+ /** Failure count */
+ t_u32 failed;
+ /** Retry count */
+ t_u32 retry;
+ /** Multi entry count */
+ t_u32 multi_retry;
+ /** Duplicate frame count */
+ t_u32 frame_dup;
+ /** RTS success count */
+ t_u32 rts_success;
+ /** RTS failure count */
+ t_u32 rts_failure;
+ /** Ack failure count */
+ t_u32 ack_failure;
+ /** Rx fragmentation count */
+ t_u32 rx_frag;
+ /** Multicast Tx frame count */
+ t_u32 mcast_rx_frame;
+ /** FCS error count */
+ t_u32 fcs_error;
+ /** Tx frame count */
+ t_u32 tx_frame;
+ /** WEP ICV error count */
+ t_u32 wep_icv_error[4];
+ /** beacon recv count */
+ t_u32 bcn_rcv_cnt;
+ /** beacon miss count */
+ t_u32 bcn_miss_cnt;
+ /** received amsdu count*/
+ t_u32 amsdu_rx_cnt;
+ /** received msdu count in amsdu*/
+ t_u32 msdu_in_rx_amsdu_cnt;
+ /** tx amsdu count*/
+ t_u32 amsdu_tx_cnt;
+ /** tx msdu count in amsdu*/
+ t_u32 msdu_in_tx_amsdu_cnt;
+} mlan_ds_get_stats_org;
+
+/** Type definition of mlan_ds_get_stats for MLAN_OID_GET_STATS */
+typedef struct _mlan_ds_get_stats {
+ /** Statistics counter */
+ /** Multicast transmitted frame count */
+ t_u32 mcast_tx_frame;
+ /** Failure count */
+ t_u32 failed;
+ /** Retry count */
+ t_u32 retry;
+ /** Multi entry count */
+ t_u32 multi_retry;
+ /** Duplicate frame count */
+ t_u32 frame_dup;
+ /** RTS success count */
+ t_u32 rts_success;
+ /** RTS failure count */
+ t_u32 rts_failure;
+ /** Ack failure count */
+ t_u32 ack_failure;
+ /** Rx fragmentation count */
+ t_u32 rx_frag;
+ /** Multicast Tx frame count */
+ t_u32 mcast_rx_frame;
+ /** FCS error count */
+ t_u32 fcs_error;
+ /** Tx frame count */
+ t_u32 tx_frame;
+ /** WEP ICV error count */
+ t_u32 wep_icv_error[4];
+ /** beacon recv count */
+ t_u32 bcn_rcv_cnt;
+ /** beacon miss count */
+ t_u32 bcn_miss_cnt;
+ /** received amsdu count*/
+ t_u32 amsdu_rx_cnt;
+ /** received msdu count in amsdu*/
+ t_u32 msdu_in_rx_amsdu_cnt;
+ /** tx amsdu count*/
+ t_u32 amsdu_tx_cnt;
+ /** tx msdu count in amsdu*/
+ t_u32 msdu_in_tx_amsdu_cnt;
+
+ /** Tx frag count */
+ t_u32 tx_frag_cnt;
+ /** Qos Tx frag count */
+ t_u32 qos_tx_frag_cnt[8];
+ /** Qos failed count */
+ t_u32 qos_failed_cnt[8];
+ /** Qos retry count */
+ t_u32 qos_retry_cnt[8];
+ /** Qos multi retry count */
+ t_u32 qos_multi_retry_cnt[8];
+ /** Qos frame dup count */
+ t_u32 qos_frm_dup_cnt[8];
+ /** Qos rts success count */
+ t_u32 qos_rts_suc_cnt[8];
+ /** Qos rts failure count */
+ t_u32 qos_rts_failure_cnt[8];
+ /** Qos ack failure count */
+ t_u32 qos_ack_failure_cnt[8];
+ /** Qos Rx frag count */
+ t_u32 qos_rx_frag_cnt[8];
+ /** Qos Tx frame count */
+ t_u32 qos_tx_frm_cnt[8];
+ /** Qos discarded frame count */
+ t_u32 qos_discarded_frm_cnt[8];
+ /** Qos mpdus Rx count */
+ t_u32 qos_mpdus_rx_cnt[8];
+ /** Qos retry rx count */
+ t_u32 qos_retries_rx_cnt[8];
+ /** CMAC ICV errors count */
+ t_u32 cmacicv_errors;
+ /** CMAC replays count */
+ t_u32 cmac_replays;
+ /** mgmt CCMP replays count */
+ t_u32 mgmt_ccmp_replays;
+ /** TKIP ICV errors count */
+ t_u32 tkipicv_errors;
+ /** TKIP replays count */
+ t_u32 tkip_replays;
+ /** CCMP decrypt errors count */
+ t_u32 ccmp_decrypt_errors;
+ /** CCMP replays count */
+ t_u32 ccmp_replays;
+ /** Tx amsdu count */
+ t_u32 tx_amsdu_cnt;
+ /** failed amsdu count */
+ t_u32 failed_amsdu_cnt;
+ /** retry amsdu count */
+ t_u32 retry_amsdu_cnt;
+ /** multi-retry amsdu count */
+ t_u32 multi_retry_amsdu_cnt;
+ /** Tx octets in amsdu count */
+ t_u64 tx_octets_in_amsdu_cnt;
+ /** amsdu ack failure count */
+ t_u32 amsdu_ack_failure_cnt;
+ /** Rx amsdu count */
+ t_u32 rx_amsdu_cnt;
+ /** Rx octets in amsdu count */
+ t_u64 rx_octets_in_amsdu_cnt;
+ /** Tx ampdu count */
+ t_u32 tx_ampdu_cnt;
+ /** tx mpdus in ampdu count */
+ t_u32 tx_mpdus_in_ampdu_cnt;
+ /** tx octets in ampdu count */
+ t_u64 tx_octets_in_ampdu_cnt;
+ /** ampdu Rx count */
+ t_u32 ampdu_rx_cnt;
+ /** mpdu in Rx ampdu count */
+ t_u32 mpdu_in_rx_ampdu_cnt;
+ /** Rx octets ampdu count */
+ t_u64 rx_octets_in_ampdu_cnt;
+ /** ampdu delimiter CRC error count */
+ t_u32 ampdu_delimiter_crc_error_cnt;
+ /** Rx Stuck Related Info*/
+ /** Rx Stuck Issue count */
+ t_u32 rx_stuck_issue_cnt[2];
+ /** Rx Stuck Recovery count */
+ t_u32 rx_stuck_recovery_cnt;
+ /** Rx Stuck TSF */
+ t_u64 rx_stuck_tsf[2];
+ /** Tx Watchdog Recovery Related Info */
+ /** Tx Watchdog Recovery count */
+ t_u32 tx_watchdog_recovery_cnt;
+ /** Tx Watchdog TSF */
+ t_u64 tx_watchdog_tsf[2];
+ /** Channel Switch Related Info */
+ /** Channel Switch Announcement Sent */
+ t_u32 channel_switch_ann_sent;
+ /** Channel Switch State */
+ t_u32 channel_switch_state;
+ /** Register Class */
+ t_u32 reg_class;
+ /** Channel Number */
+ t_u32 channel_number;
+ /** Channel Switch Mode */
+ t_u32 channel_switch_mode;
+} mlan_ds_get_stats, *pmlan_ds_get_stats;
+
+/** Type definition of mlan_ds_uap_stats for MLAN_OID_GET_STATS */
+typedef struct _mlan_ds_uap_stats {
+ /** tkip mic failures */
+ t_u32 tkip_mic_failures;
+ /** ccmp decrypt errors */
+ t_u32 ccmp_decrypt_errors;
+ /** wep undecryptable count */
+ t_u32 wep_undecryptable_count;
+ /** wep icv error count */
+ t_u32 wep_icv_error_count;
+ /** decrypt failure count */
+ t_u32 decrypt_failure_count;
+ /** dot11 multicast tx count */
+ t_u32 mcast_tx_count;
+ /** dot11 failed count */
+ t_u32 failed_count;
+ /** dot11 retry count */
+ t_u32 retry_count;
+ /** dot11 multi retry count */
+ t_u32 multi_retry_count;
+ /** dot11 frame duplicate count */
+ t_u32 frame_dup_count;
+ /** dot11 rts success count */
+ t_u32 rts_success_count;
+ /** dot11 rts failure count */
+ t_u32 rts_failure_count;
+ /** dot11 ack failure count */
+ t_u32 ack_failure_count;
+ /** dot11 rx ragment count */
+ t_u32 rx_fragment_count;
+ /** dot11 mcast rx frame count */
+ t_u32 mcast_rx_frame_count;
+ /** dot11 fcs error count */
+ t_u32 fcs_error_count;
+ /** dot11 tx frame count */
+ t_u32 tx_frame_count;
+ /** dot11 rsna tkip cm invoked */
+ t_u32 rsna_tkip_cm_invoked;
+ /** dot11 rsna 4way handshake failures */
+ t_u32 rsna_4way_hshk_failures;
+} mlan_ds_uap_stats, *pmlan_ds_uap_stats;
+
+/** Mask of last beacon RSSI */
+#define BCN_RSSI_LAST_MASK 0x00000001
+/** Mask of average beacon RSSI */
+#define BCN_RSSI_AVG_MASK 0x00000002
+/** Mask of last data RSSI */
+#define DATA_RSSI_LAST_MASK 0x00000004
+/** Mask of average data RSSI */
+#define DATA_RSSI_AVG_MASK 0x00000008
+/** Mask of last beacon SNR */
+#define BCN_SNR_LAST_MASK 0x00000010
+/** Mask of average beacon SNR */
+#define BCN_SNR_AVG_MASK 0x00000020
+/** Mask of last data SNR */
+#define DATA_SNR_LAST_MASK 0x00000040
+/** Mask of average data SNR */
+#define DATA_SNR_AVG_MASK 0x00000080
+/** Mask of last beacon NF */
+#define BCN_NF_LAST_MASK 0x00000100
+/** Mask of average beacon NF */
+#define BCN_NF_AVG_MASK 0x00000200
+/** Mask of last data NF */
+#define DATA_NF_LAST_MASK 0x00000400
+/** Mask of average data NF */
+#define DATA_NF_AVG_MASK 0x00000800
+/** Mask of all RSSI_INFO */
+#define ALL_RSSI_INFO_MASK 0x00000fff
+#define MAX_PATH_NUM 3
+/** path A */
+#define PATH_A 0x01
+/** path B */
+#define PATH_B 0x02
+/** path AB */
+#define PATH_AB 0x03
+/** ALL the path */
+#define PATH_ALL 0
+/** Type definition of mlan_ds_get_signal for MLAN_OID_GET_SIGNAL */
+typedef struct _mlan_ds_get_signal {
+ /** Selector of get operation */
+ /*
+ * Bit0: Last Beacon RSSI, Bit1: Average Beacon RSSI,
+ * Bit2: Last Data RSSI, Bit3: Average Data RSSI,
+ * Bit4: Last Beacon SNR, Bit5: Average Beacon SNR,
+ * Bit6: Last Data SNR, Bit7: Average Data SNR,
+ * Bit8: Last Beacon NF, Bit9: Average Beacon NF,
+ * Bit10: Last Data NF, Bit11: Average Data NF
+ *
+ * Bit0: PATH A
+ * Bit1: PATH B
+ */
+ t_u16 selector;
+
+ /** RSSI */
+ /** RSSI of last beacon */
+ t_s16 bcn_rssi_last;
+ /** RSSI of beacon average */
+ t_s16 bcn_rssi_avg;
+ /** RSSI of last data packet */
+ t_s16 data_rssi_last;
+ /** RSSI of data packet average */
+ t_s16 data_rssi_avg;
+
+ /** SNR */
+ /** SNR of last beacon */
+ t_s16 bcn_snr_last;
+ /** SNR of beacon average */
+ t_s16 bcn_snr_avg;
+ /** SNR of last data packet */
+ t_s16 data_snr_last;
+ /** SNR of data packet average */
+ t_s16 data_snr_avg;
+
+ /** NF */
+ /** NF of last beacon */
+ t_s16 bcn_nf_last;
+ /** NF of beacon average */
+ t_s16 bcn_nf_avg;
+ /** NF of last data packet */
+ t_s16 data_nf_last;
+ /** NF of data packet average */
+ t_s16 data_nf_avg;
+} mlan_ds_get_signal, *pmlan_ds_get_signal;
+
+/** bit for 2.4 G antenna diversity */
+#define ANT_DIVERSITY_2G MBIT(3)
+/** bit for 5 G antenna diversity */
+#define ANT_DIVERSITY_5G MBIT(7)
+
+/** mlan_fw_info data structure for MLAN_OID_GET_FW_INFO */
+typedef struct _mlan_fw_info {
+ /** Firmware version */
+ t_u32 fw_ver;
+ /** MAC address */
+ mlan_802_11_mac_addr mac_addr;
+ /** 802.11n device capabilities */
+ t_u32 hw_dot_11n_dev_cap;
+ /** Device support for MIMO abstraction of MCSs */
+ t_u8 hw_dev_mcs_support;
+ /** user's MCS setting */
+ t_u8 usr_dev_mcs_support;
+ /** 802.11ac device capabilities */
+ t_u32 hw_dot_11ac_dev_cap;
+ /** 802.11ac device Capabilities for 2.4GHz */
+ t_u32 usr_dot_11ac_dev_cap_bg;
+ /** 802.11ac device Capabilities for 5GHz */
+ t_u32 usr_dot_11ac_dev_cap_a;
+ /** length of hw he capability */
+ t_u8 hw_hecap_len;
+ /** 802.11ax HE capability */
+ t_u8 hw_he_cap[54];
+ /** length of hw 2.4G he capability */
+ t_u8 hw_2g_hecap_len;
+ /** 802.11ax 2.4G HE capability */
+ t_u8 hw_2g_he_cap[54];
+ /** 802.11ac device support for MIMO abstraction of MCSs */
+ t_u32 hw_dot_11ac_mcs_support;
+ /** User conf 802.11ac device support for MIMO abstraction of MCSs */
+ t_u32 usr_dot_11ac_mcs_support;
+ /** fw supported band */
+ t_u16 fw_bands;
+ /** region code */
+ t_u16 region_code;
+ /** force_reg */
+ t_u8 force_reg;
+ /** ECSA support */
+ t_u8 ecsa_enable;
+ /** Get log support */
+ t_u8 getlog_enable;
+ /** FW support for embedded supplicant */
+ t_u8 fw_supplicant_support;
+ /** ant info */
+ t_u8 antinfo;
+ /** max AP associated sta count supported by fw */
+ t_u8 max_ap_assoc_sta;
+ /** Bandwidth not support 80Mhz */
+ t_u8 prohibit_80mhz;
+} mlan_fw_info, *pmlan_fw_info;
+
+/** Version string buffer length */
+#define MLAN_MAX_VER_STR_LEN 128
+
+/** mlan_ver_ext data structure for MLAN_OID_GET_VER_EXT */
+typedef struct _mlan_ver_ext {
+ /** Selected version string */
+ t_u32 version_str_sel;
+ /** Version string */
+ char version_str[MLAN_MAX_VER_STR_LEN];
+} mlan_ver_ext, *pmlan_ver_ext;
+
+#ifdef BIG_ENDIAN_SUPPORT
+/** Extended Capabilities Data */
+typedef struct MLAN_PACK_START _ExtCap_t {
+ /** Extended Capabilities value */
+ t_u8 rsvdBit79 : 1; /* bit 79 */
+ t_u8 TWTResp : 1; /* bit 78 */
+ t_u8 TWTReq : 1; /* bit 77 */
+ t_u8 rsvdBit76 : 1; /* bit 76 */
+ t_u8 rsvdBit75 : 1; /* bit 75 */
+ t_u8 rsvdBit74 : 1; /* bit 74 */
+ t_u8 rsvdBit73 : 1; /* bit 73 */
+ t_u8 FILS : 1; /* bit 72 */
+ t_u8 FTMI : 1; /* bit 71 */
+ t_u8 FTMR : 1; /* bit 70 */
+ t_u8 CAQ : 1; /* bit 69 */
+ t_u8 rsvdBit68 : 1; /* bit 68 */
+ t_u8 NCC : 1; /* bit 67 */
+ t_u8 rsvdBit66 : 1; /* bit 66 */
+ t_u8 chanSchedMgnt : 1; /* bit 65 */
+ t_u8 MaxAMSDU1 : 1; /* bit 64 */
+ t_u8 MaxAMSDU0 : 1; /* bit 63 */
+ t_u8 OperModeNtf : 1; /* bit 62 */
+ t_u8 TDLSWildBandwidth : 1; /* bit 61 */
+ t_u8 rsvdBit60 : 1; /* bit 60 */
+ t_u8 rsvdBit59 : 1; /* bit 59 */
+ t_u8 rsvdBit58 : 1; /* bit 58 */
+ t_u8 rsvdBit57 : 1; /* bit 57 */
+ t_u8 rsvdBit56 : 1; /* bit 56 */
+ t_u8 rsvdBit55 : 1; /* bit 55 */
+ t_u8 rsvdBit54 : 1; /* bit 54 */
+ t_u8 rsvdBit53 : 1; /* bit 53 */
+ t_u8 rsvdBit52 : 1; /* bit 52 */
+ t_u8 rsvdBit51 : 1; /* bit 51 */
+ t_u8 rsvdBit50 : 1; /* bit 50 */
+ t_u8 rsvdBit49 : 1; /* bit 49 */
+ t_u8 rsvdBit48 : 1; /* bit 48 */
+ t_u8 rsvdBit47 : 1; /* bit 47 */
+ t_u8 rsvdBit46 : 1; /* bit 46 */
+ t_u8 rsvdBit45 : 1; /* bit 45 */
+ t_u8 rsvdBit44 : 1; /* bit 44 */
+ t_u8 rsvdBit43 : 1; /* bit 43 */
+ t_u8 rsvdBit42 : 1; /* bit 42 */
+ t_u8 rsvdBit41 : 1; /* bit 41 */
+ t_u8 rsvdBit40 : 1; /* bit 40 */
+ t_u8 TDLSChlSwitchProhib : 1; /* bit 39 */
+ t_u8 TDLSProhibited : 1; /* bit 38 */
+ t_u8 TDLSSupport : 1; /* bit 37 */
+ t_u8 MSGCF_Capa : 1; /* bit 36 */
+ t_u8 Reserved35 : 1; /* bit 35 */
+ t_u8 SSPN_Interface : 1; /* bit 34 */
+ t_u8 EBR : 1; /* bit 33 */
+ t_u8 Qos_Map : 1; /* bit 32 */
+ t_u8 Interworking : 1; /* bit 31 */
+ t_u8 TDLSChannelSwitching : 1; /* bit 30 */
+ t_u8 TDLSPeerPSMSupport : 1; /* bit 29 */
+ t_u8 TDLSPeerUAPSDSupport : 1; /* bit 28 */
+ t_u8 UTC : 1; /* bit 27 */
+ t_u8 DMS : 1; /* bit 26 */
+ t_u8 SSID_List : 1; /* bit 25 */
+ t_u8 ChannelUsage : 1; /* bit 24 */
+ t_u8 TimingMeasurement : 1; /* bit 23 */
+ t_u8 MultipleBSSID : 1; /* bit 22 */
+ t_u8 AC_StationCount : 1; /* bit 21 */
+ t_u8 QoSTrafficCap : 1; /* bit 20 */
+ t_u8 BSS_Transition : 1; /* bit 19 */
+ t_u8 TIM_Broadcast : 1; /* bit 18 */
+ t_u8 WNM_Sleep : 1; /* bit 17 */
+ t_u8 TFS : 1; /* bit 16 */
+ t_u8 GeospatialLocation : 1; /* bit 15 */
+ t_u8 CivicLocation : 1; /* bit 14 */
+ t_u8 CollocatedIntf : 1; /* bit 13 */
+ t_u8 ProxyARPService : 1; /* bit 12 */
+ t_u8 FMS : 1; /* bit 11 */
+ t_u8 LocationTracking : 1; /* bit 10 */
+ t_u8 MulticastDiagnostics : 1; /* bit 9 */
+ t_u8 Diagnostics : 1; /* bit 8 */
+ t_u8 Event : 1; /* bit 7 */
+ t_u8 SPSMP_Support : 1; /* bit 6 */
+ t_u8 Reserved5 : 1; /* bit 5 */
+ t_u8 PSMP_Capable : 1; /* bit 4 */
+ t_u8 RejectUnadmFrame : 1; /* bit 3 */
+ t_u8 ExtChanSwitching : 1; /* bit 2 */
+ t_u8 Reserved1 : 1; /* bit 1 */
+ t_u8 BSS_CoexistSupport : 1; /* bit 0 */
+} MLAN_PACK_END ExtCap_t, *pExtCap_t;
+#else
+/** Extended Capabilities Data */
+typedef struct MLAN_PACK_START _ExtCap_t {
+ /** Extended Capabilities value */
+ t_u8 BSS_CoexistSupport : 1; /* bit 0 */
+ t_u8 Reserved1 : 1; /* bit 1 */
+ t_u8 ExtChanSwitching : 1; /* bit 2 */
+ t_u8 RejectUnadmFrame : 1; /* bit 3 */
+ t_u8 PSMP_Capable : 1; /* bit 4 */
+ t_u8 Reserved5 : 1; /* bit 5 */
+ t_u8 SPSMP_Support : 1; /* bit 6 */
+ t_u8 Event : 1; /* bit 7 */
+ t_u8 Diagnostics : 1; /* bit 8 */
+ t_u8 MulticastDiagnostics : 1; /* bit 9 */
+ t_u8 LocationTracking : 1; /* bit 10 */
+ t_u8 FMS : 1; /* bit 11 */
+ t_u8 ProxyARPService : 1; /* bit 12 */
+ t_u8 CollocatedIntf : 1; /* bit 13 */
+ t_u8 CivicLocation : 1; /* bit 14 */
+ t_u8 GeospatialLocation : 1; /* bit 15 */
+ t_u8 TFS : 1; /* bit 16 */
+ t_u8 WNM_Sleep : 1; /* bit 17 */
+ t_u8 TIM_Broadcast : 1; /* bit 18 */
+ t_u8 BSS_Transition : 1; /* bit 19 */
+ t_u8 QoSTrafficCap : 1; /* bit 20 */
+ t_u8 AC_StationCount : 1; /* bit 21 */
+ t_u8 MultipleBSSID : 1; /* bit 22 */
+ t_u8 TimingMeasurement : 1; /* bit 23 */
+ t_u8 ChannelUsage : 1; /* bit 24 */
+ t_u8 SSID_List : 1; /* bit 25 */
+ t_u8 DMS : 1; /* bit 26 */
+ t_u8 UTC : 1; /* bit 27 */
+ t_u8 TDLSPeerUAPSDSupport : 1; /* bit 28 */
+ t_u8 TDLSPeerPSMSupport : 1; /* bit 29 */
+ t_u8 TDLSChannelSwitching : 1; /* bit 30 */
+ t_u8 Interworking : 1; /* bit 31 */
+ t_u8 Qos_Map : 1; /* bit 32 */
+ t_u8 EBR : 1; /* bit 33 */
+ t_u8 SSPN_Interface : 1; /* bit 34 */
+ t_u8 Reserved35 : 1; /* bit 35 */
+ t_u8 MSGCF_Capa : 1; /* bit 36 */
+ t_u8 TDLSSupport : 1; /* bit 37 */
+ t_u8 TDLSProhibited : 1; /* bit 38 */
+ t_u8 TDLSChlSwitchProhib : 1; /* bit 39 */
+ t_u8 rsvdBit40 : 1; /* bit 40 */
+ t_u8 rsvdBit41 : 1; /* bit 41 */
+ t_u8 rsvdBit42 : 1; /* bit 42 */
+ t_u8 rsvdBit43 : 1; /* bit 43 */
+ t_u8 rsvdBit44 : 1; /* bit 44 */
+ t_u8 rsvdBit45 : 1; /* bit 45 */
+ t_u8 rsvdBit46 : 1; /* bit 46 */
+ t_u8 rsvdBit47 : 1; /* bit 47 */
+ t_u8 rsvdBit48 : 1; /* bit 48 */
+ t_u8 rsvdBit49 : 1; /* bit 49 */
+ t_u8 rsvdBit50 : 1; /* bit 50 */
+ t_u8 rsvdBit51 : 1; /* bit 51 */
+ t_u8 rsvdBit52 : 1; /* bit 52 */
+ t_u8 rsvdBit53 : 1; /* bit 53 */
+ t_u8 rsvdBit54 : 1; /* bit 54 */
+ t_u8 rsvdBit55 : 1; /* bit 55 */
+ t_u8 rsvdBit56 : 1; /* bit 56 */
+ t_u8 rsvdBit57 : 1; /* bit 57 */
+ t_u8 rsvdBit58 : 1; /* bit 58 */
+ t_u8 rsvdBit59 : 1; /* bit 59 */
+ t_u8 rsvdBit60 : 1; /* bit 60 */
+ t_u8 TDLSWildBandwidth : 1; /* bit 61 */
+ t_u8 OperModeNtf : 1; /* bit 62 */
+ t_u8 MaxAMSDU0 : 1; /* bit 63 */
+ t_u8 MaxAMSDU1 : 1; /* bit 64 */
+ t_u8 chanSchedMgnt : 1; /* bit 65 */
+ t_u8 rsvdBit66 : 1; /* bit 66 */
+ t_u8 NCC : 1; /* bit 67 */
+ t_u8 rsvdBit68 : 1; /* bit 68 */
+ t_u8 CAQ : 1; /* bit 69 */
+ t_u8 FTMR : 1; /* bit 70 */
+ t_u8 FTMI : 1; /* bit 71 */
+ t_u8 FILS : 1; /* bit 72 */
+ t_u8 rsvdBit73 : 1; /* bit 73 */
+ t_u8 rsvdBit74 : 1; /* bit 74 */
+ t_u8 rsvdBit75 : 1; /* bit 75 */
+ t_u8 rsvdBit76 : 1; /* bit 76 */
+ t_u8 TWTReq : 1; /* bit 77 */
+ t_u8 TWTResp : 1; /* bit 78 */
+ t_u8 rsvdBit79 : 1; /* bit 79 */
+} MLAN_PACK_END ExtCap_t, *pExtCap_t;
+#endif
+
+/** ExtCap : TDLS prohibited */
+#define IS_EXTCAP_TDLS_PROHIBITED(ext_cap) (ext_cap.TDLSProhibited)
+/** ExtCap : TDLS channel switch prohibited */
+#define IS_EXTCAP_TDLS_CHLSWITCHPROHIB(ext_cap) (ext_cap.TDLSChlSwitchProhib)
+
+/** mlan_bss_info data structure for MLAN_OID_GET_BSS_INFO */
+typedef struct _mlan_bss_info {
+ /** BSS mode */
+ t_u32 bss_mode;
+ /** SSID */
+ mlan_802_11_ssid ssid;
+ /** Table index */
+ t_u32 scan_table_idx;
+ /** Channel */
+ t_u32 bss_chan;
+ /** Band */
+ t_u8 bss_band;
+ /** Region code */
+ t_u32 region_code;
+ /** Connection status */
+ t_u32 media_connected;
+ /** Radio on */
+ t_u32 radio_on;
+ /** Max power level in dBm */
+ t_s32 max_power_level;
+ /** Min power level in dBm */
+ t_s32 min_power_level;
+ /** Adhoc state */
+ t_u32 adhoc_state;
+ /** NF of last beacon */
+ t_s32 bcn_nf_last;
+ /** wep status */
+ t_u32 wep_status;
+ /** scan block status */
+ t_u8 scan_block;
+ /** Host Sleep configured flag */
+ t_u32 is_hs_configured;
+ /** Deep Sleep flag */
+ t_u32 is_deep_sleep;
+ /** BSSID */
+ mlan_802_11_mac_addr bssid;
+#ifdef STA_SUPPORT
+ /** Capability Info */
+ t_u16 capability_info;
+ /** Beacon Interval */
+ t_u16 beacon_interval;
+ /** Listen Interval */
+ t_u16 listen_interval;
+ /** Association Id */
+ t_u16 assoc_id;
+ /** AP/Peer supported rates */
+ t_u8 peer_supp_rates[MLAN_SUPPORTED_RATES];
+ /** extend capability for AP */
+ ExtCap_t ext_cap;
+#endif /* STA_SUPPORT */
+ /** Mobility Domain ID */
+ t_u16 mdid;
+ /** FT Capability policy */
+ t_u8 ft_cap;
+ /** 11h active */
+ t_bool is_11h_active;
+ /** dfs check channel */
+ t_u8 dfs_check_channel;
+} mlan_bss_info, *pmlan_bss_info;
+
+/** MAXIMUM number of TID */
+#define MAX_NUM_TID 8
+
+/** Max RX Win size */
+#define MAX_RX_WINSIZE 64
+
+/** rx_reorder_tbl */
+typedef struct {
+ /** TID */
+ t_u16 tid;
+ /** TA */
+ t_u8 ta[MLAN_MAC_ADDR_LENGTH];
+ /** Start window */
+ t_u32 start_win;
+ /** Window size */
+ t_u32 win_size;
+ /** amsdu flag */
+ t_u8 amsdu;
+ /** buffer status */
+ t_u32 buffer[MAX_RX_WINSIZE];
+} rx_reorder_tbl;
+
+/** tx_ba_stream_tbl */
+typedef struct {
+ /** TID */
+ t_u16 tid;
+ /** RA */
+ t_u8 ra[MLAN_MAC_ADDR_LENGTH];
+ /** amsdu flag */
+ t_u8 amsdu;
+} tx_ba_stream_tbl;
+
+/** Debug command number */
+#define DBG_CMD_NUM 10
+
+#ifdef SDIO
+/** sdio mp debug number */
+#define SDIO_MP_DBG_NUM 10
+#endif
+
+#ifdef PCIE
+#define MLAN_MAX_TXRX_BD 0x20
+#endif
+
+/** Maximum size of IEEE Information Elements */
+#define IEEE_MAX_IE_SIZE 256
+
+/** max ralist num */
+#define MLAN_MAX_RALIST_NUM 8
+/** ralist info */
+typedef struct _ralist_info {
+ /** RA list buffer */
+ t_u8 ra[MLAN_MAC_ADDR_LENGTH];
+ /** total packets in RA list */
+ t_u16 total_pkts;
+ /** tid num */
+ t_u8 tid;
+ /** tx_pause flag */
+ t_u8 tx_pause;
+} ralist_info, *pralist_info;
+
+/** mlan_debug_info data structure for MLAN_OID_GET_DEBUG_INFO */
+typedef struct _mlan_debug_info {
+ /* WMM AC_BK count */
+ t_u32 wmm_ac_bk;
+ /* WMM AC_BE count */
+ t_u32 wmm_ac_be;
+ /* WMM AC_VI count */
+ t_u32 wmm_ac_vi;
+ /* WMM AC_VO count */
+ t_u32 wmm_ac_vo;
+ /** Corresponds to max_tx_buf_size member of mlan_adapter*/
+ t_u32 max_tx_buf_size;
+ /** Corresponds to tx_buf_size member of mlan_adapter*/
+ t_u32 tx_buf_size;
+ /** Corresponds to curr_tx_buf_size member of mlan_adapter*/
+ t_u32 curr_tx_buf_size;
+ /** Tx table num */
+ t_u32 tx_tbl_num;
+ /** Tx ba stream table */
+ tx_ba_stream_tbl tx_tbl[MLAN_MAX_TX_BASTREAM_SUPPORTED];
+ /** Rx table num */
+ t_u32 rx_tbl_num;
+ /** Rx reorder table*/
+ rx_reorder_tbl rx_tbl[MLAN_MAX_RX_BASTREAM_SUPPORTED];
+ /** ralist num */
+ t_u32 ralist_num;
+ /** ralist info */
+ ralist_info ralist[MLAN_MAX_RALIST_NUM];
+ /** Corresponds to ps_mode member of mlan_adapter */
+ t_u16 ps_mode;
+ /** Corresponds to ps_state member of mlan_adapter */
+ t_u32 ps_state;
+#ifdef STA_SUPPORT
+ /** Corresponds to is_deep_sleep member of mlan_adapter */
+ t_u8 is_deep_sleep;
+#endif /** STA_SUPPORT */
+ /** Corresponds to pm_wakeup_card_req member of mlan_adapter */
+ t_u8 pm_wakeup_card_req;
+ /** Corresponds to pm_wakeup_fw_try member of mlan_adapter */
+ t_u32 pm_wakeup_fw_try;
+ /** time stamp when host try to wake up firmware */
+ t_u32 pm_wakeup_in_secs;
+ /** wake up timeout happened */
+ t_u32 pm_wakeup_timeout;
+ /** Corresponds to is_hs_configured member of mlan_adapter */
+ t_u8 is_hs_configured;
+ /** Corresponds to hs_activated member of mlan_adapter */
+ t_u8 hs_activated;
+ /** Corresponds to pps_uapsd_mode member of mlan_adapter */
+ t_u16 pps_uapsd_mode;
+ /** Corresponds to sleep_period.period member of mlan_adapter */
+ t_u16 sleep_pd;
+ /** Corresponds to wmm_qosinfo member of mlan_private */
+ t_u8 qos_cfg;
+ /** Corresponds to tx_lock_flag member of mlan_adapter */
+ t_u8 tx_lock_flag;
+ /** Corresponds to port_open member of mlan_private */
+ t_u8 port_open;
+ /** bypass pkt count */
+ t_u16 bypass_pkt_count;
+ /** Corresponds to scan_processing member of mlan_adapter */
+ t_u32 scan_processing;
+ /** Corresponds to mlan_processing member of mlan_adapter */
+ t_u32 mlan_processing;
+ /** Corresponds to main_lock_flag member of mlan_adapter */
+ t_u32 main_lock_flag;
+ /** Corresponds to main_process_cnt member of mlan_adapter */
+ t_u32 main_process_cnt;
+ /** Corresponds to delay_task_flag member of mlan_adapter */
+ t_u32 delay_task_flag;
+ /** mlan_rx_processing */
+ t_u32 mlan_rx_processing;
+ /** rx pkts queued */
+ t_u32 rx_pkts_queued;
+ /** Number of host to card command failures */
+ t_u32 num_cmd_host_to_card_failure;
+ /** Number of host to card sleep confirm failures */
+ t_u32 num_cmd_sleep_cfm_host_to_card_failure;
+ /** Number of host to card Tx failures */
+ t_u32 num_tx_host_to_card_failure;
+ /** Number of allocate buffer failure */
+ t_u32 num_alloc_buffer_failure;
+ /** Number of pkt dropped */
+ t_u32 num_pkt_dropped;
+#ifdef SDIO
+ /** Number of card to host command/event failures */
+ t_u32 num_cmdevt_card_to_host_failure;
+ /** Number of card to host Rx failures */
+ t_u32 num_rx_card_to_host_failure;
+ /** Number of interrupt read failures */
+ t_u32 num_int_read_failure;
+ /** Last interrupt status */
+ t_u32 last_int_status;
+ /** number of interrupt receive */
+ t_u32 num_of_irq;
+ /** flag for sdio rx aggr */
+ t_u8 sdio_rx_aggr;
+ /** FW update port number */
+ t_u32 mp_update[SDIO_MP_AGGR_DEF_PKT_LIMIT_MAX * 2];
+ /** Invalid port update count */
+ t_u32 mp_invalid_update;
+ /** Number of packets tx aggr */
+ t_u32 mpa_tx_count[SDIO_MP_AGGR_DEF_PKT_LIMIT_MAX];
+ /** no more packets count*/
+ t_u32 mpa_sent_last_pkt;
+ /** no write_ports count */
+ t_u32 mpa_sent_no_ports;
+ /** last recv wr_bitmap */
+ t_u32 last_recv_wr_bitmap;
+ /** last mp_wr_bitmap */
+ t_u32 last_mp_wr_bitmap[SDIO_MP_DBG_NUM];
+ /** last ports for cmd53 write data */
+ t_u32 last_mp_wr_ports[SDIO_MP_DBG_NUM];
+ /** last len for cmd53 write data */
+ t_u32 last_mp_wr_len[SDIO_MP_DBG_NUM];
+ /** last curr_wr_port */
+ t_u8 last_curr_wr_port[SDIO_MP_DBG_NUM];
+ /** length info for cmd53 write data */
+ t_u16 last_mp_wr_info[SDIO_MP_DBG_NUM * SDIO_MP_AGGR_DEF_PKT_LIMIT_MAX];
+ /** last mp_index */
+ t_u8 last_mp_index;
+ /** buffer for mp debug */
+ t_u8 *mpa_buf;
+ /** length info for mp buf size */
+ t_u32 mpa_buf_size;
+ /** Number of packets rx aggr */
+ t_u32 mpa_rx_count[SDIO_MP_AGGR_DEF_PKT_LIMIT_MAX];
+ /** mp aggr_pkt limit */
+ t_u8 mp_aggr_pkt_limit;
+#endif
+ /** Number of deauthentication events */
+ t_u32 num_event_deauth;
+ /** Number of disassosiation events */
+ t_u32 num_event_disassoc;
+ /** Number of link lost events */
+ t_u32 num_event_link_lost;
+ /** Number of deauthentication commands */
+ t_u32 num_cmd_deauth;
+ /** Number of association comamnd successes */
+ t_u32 num_cmd_assoc_success;
+ /** Number of association command failures */
+ t_u32 num_cmd_assoc_failure;
+ /** Number of consecutive association failures */
+ t_u32 num_cons_assoc_failure;
+
+ /** Number of command timeouts */
+ t_u32 num_cmd_timeout;
+ /** Timeout command ID */
+ t_u16 timeout_cmd_id;
+ /** Timeout command action */
+ t_u16 timeout_cmd_act;
+ /** List of last command IDs */
+ t_u16 last_cmd_id[DBG_CMD_NUM];
+ /** List of last command actions */
+ t_u16 last_cmd_act[DBG_CMD_NUM];
+ /** Last command index */
+ t_u16 last_cmd_index;
+ /** List of last command response IDs */
+ t_u16 last_cmd_resp_id[DBG_CMD_NUM];
+ /** Last command response index */
+ t_u16 last_cmd_resp_index;
+ /** List of last events */
+ t_u16 last_event[DBG_CMD_NUM];
+ /** Last event index */
+ t_u16 last_event_index;
+ /** Number of no free command node */
+ t_u16 num_no_cmd_node;
+ /** pending command id */
+ t_u16 pending_cmd;
+ /** time stamp for dnld last cmd */
+ t_u32 dnld_cmd_in_secs;
+ /** Corresponds to data_sent member of mlan_adapter */
+ t_u8 data_sent;
+ /** Corresponds to cmd_sent member of mlan_adapter */
+ t_u8 cmd_sent;
+ /** SDIO multiple port read bitmap */
+ t_u32 mp_rd_bitmap;
+ /** SDIO multiple port write bitmap */
+ t_u32 mp_wr_bitmap;
+ /** Current available port for read */
+ t_u8 curr_rd_port;
+ /** Current available port for write */
+ t_u8 curr_wr_port;
+#ifdef PCIE
+ /** PCIE txbd read pointer */
+ t_u32 txbd_rdptr;
+ /** PCIE txbd write pointer */
+ t_u32 txbd_wrptr;
+ /** PCIE rxbd read pointer */
+ t_u32 rxbd_rdptr;
+ /** PCIE rxbd write pointer */
+ t_u32 rxbd_wrptr;
+ /** PCIE eventbd read pointer */
+ t_u32 eventbd_rdptr;
+ /** PCIE eventbd write pointer */
+ t_u32 eventbd_wrptr;
+ /** Last pkt size in transmit */
+ t_u32 last_tx_pkt_size[MLAN_MAX_TXRX_BD];
+ /** txbd ring vbase */
+ t_u8 *txbd_ring_vbase;
+ /** txbd ring size */
+ t_u32 txbd_ring_size;
+ /** rxbd ring vbase */
+ t_u8 *rxbd_ring_vbase;
+ /** rxbd ring size */
+ t_u32 rxbd_ring_size;
+ /** evtbd ring vbase */
+ t_u8 *evtbd_ring_vbase;
+ /** evtbd ring size */
+ t_u32 evtbd_ring_size;
+#endif
+ /** Corresponds to cmdresp_received member of mlan_adapter */
+ t_u8 cmd_resp_received;
+ /** Corresponds to event_received member of mlan_adapter */
+ t_u8 event_received;
+ /** pendig tx pkts */
+ t_u32 tx_pkts_queued;
+#ifdef UAP_SUPPORT
+ /** pending bridge pkts */
+ t_u16 num_bridge_pkts;
+ /** dropped pkts */
+ t_u32 num_drop_pkts;
+#endif
+ /** FW hang report */
+ t_u8 fw_hang_report;
+ /** mlan_adapter pointer */
+ t_void *mlan_adapter;
+ /** mlan_adapter_size */
+ t_u32 mlan_adapter_size;
+ /** mlan_priv vector */
+ t_void *mlan_priv[MLAN_MAX_BSS_NUM];
+ /** mlan_priv_size */
+ t_u32 mlan_priv_size[MLAN_MAX_BSS_NUM];
+ /** mlan_priv_num */
+ t_u8 mlan_priv_num;
+} mlan_debug_info, *pmlan_debug_info;
+
+#ifdef UAP_SUPPORT
+/** Maximum number of clients supported by AP */
+#define MAX_NUM_CLIENTS MAX_STA_COUNT
+
+/** station info */
+typedef struct _sta_info {
+ /** STA MAC address */
+ t_u8 mac_address[MLAN_MAC_ADDR_LENGTH];
+ /** Power mgmt status */
+ t_u8 power_mgmt_status;
+ /** RSSI */
+ t_s8 rssi;
+ /** station bandmode */
+ t_u16 bandmode;
+ /** station stats */
+ sta_stats stats;
+ /** ie length */
+ t_u16 ie_len;
+ /** ie buffer */
+ t_u8 ie_buf[];
+} sta_info;
+
+/** mlan_ds_sta_list structure for MLAN_OID_UAP_STA_LIST */
+typedef struct _mlan_ds_sta_list {
+ /** station count */
+ t_u16 sta_count;
+ /** station list */
+ sta_info info[MAX_NUM_CLIENTS];
+} mlan_ds_sta_list, *pmlan_ds_sta_list;
+#endif
+
+/** Type definition of mlan_ds_get_info for MLAN_IOCTL_GET_INFO */
+typedef struct _mlan_ds_get_info {
+ /** Sub-command */
+ t_u32 sub_command;
+
+ /** Status information parameter */
+ union {
+ /** Signal information for MLAN_OID_GET_SIGNAL */
+ mlan_ds_get_signal signal;
+ /** Signal path id for MLAN_OID_GET_SIGNAL_EXT */
+ t_u16 path_id;
+ /** Signal information for MLAN_OID_GET_SIGNAL_EXT */
+ mlan_ds_get_signal signal_ext[MAX_PATH_NUM];
+ /** Statistics information for MLAN_OID_GET_STATS */
+ mlan_ds_get_stats stats;
+ /** Statistics information for MLAN_OID_LINK_STATS*/
+ t_u8 link_statistic[1];
+ /** Firmware information for MLAN_OID_GET_FW_INFO */
+ mlan_fw_info fw_info;
+ /** Extended version information for MLAN_OID_GET_VER_EXT */
+ mlan_ver_ext ver_ext;
+ /** BSS information for MLAN_OID_GET_BSS_INFO */
+ mlan_bss_info bss_info;
+ /** Debug information for MLAN_OID_GET_DEBUG_INFO */
+ t_u8 debug_info[1];
+#ifdef UAP_SUPPORT
+ /** UAP Statistics information for MLAN_OID_GET_STATS */
+ mlan_ds_uap_stats ustats;
+ /** UAP station list for MLAN_OID_UAP_STA_LIST */
+ mlan_ds_sta_list sta_list;
+#endif
+ } param;
+} mlan_ds_get_info, *pmlan_ds_get_info;
+
+/*-----------------------------------------------------------------*/
+/** Security Configuration Group */
+/*-----------------------------------------------------------------*/
+/** Enumeration for authentication mode */
+enum _mlan_auth_mode {
+ MLAN_AUTH_MODE_OPEN = 0x00,
+ MLAN_AUTH_MODE_SHARED = 0x01,
+ MLAN_AUTH_MODE_FT = 0x02,
+ MLAN_AUTH_MODE_SAE = 0x03,
+ MLAN_AUTH_MODE_NETWORKEAP = 0x80,
+ MLAN_AUTH_MODE_AUTO = 0xFF,
+};
+
+/**Enumeration for AssocAgent authentication mode, sync from FW.*/
+typedef enum {
+ AssocAgentAuth_Open,
+ AssocAgentAuth_Shared,
+ AssocAgentAuth_FastBss,
+ AssocAgentAuth_FastBss_Skip,
+ AssocAgentAuth_Network_EAP,
+ AssocAgentAuth_Wpa3Sae,
+ AssocAgentAuth_Auto,
+} AssocAgentAuthType_e;
+
+/** Enumeration for encryption mode */
+enum _mlan_encryption_mode {
+ MLAN_ENCRYPTION_MODE_NONE = 0,
+ MLAN_ENCRYPTION_MODE_WEP40 = 1,
+ MLAN_ENCRYPTION_MODE_TKIP = 2,
+ MLAN_ENCRYPTION_MODE_CCMP = 3,
+ MLAN_ENCRYPTION_MODE_WEP104 = 4,
+ MLAN_ENCRYPTION_MODE_GCMP = 5,
+ MLAN_ENCRYPTION_MODE_GCMP_256 = 6,
+ MLAN_ENCRYPTION_MODE_CCMP_256 = 7,
+};
+
+/** Enumeration for PSK */
+enum _mlan_psk_type {
+ MLAN_PSK_PASSPHRASE = 1,
+ MLAN_PSK_PMK,
+ MLAN_PSK_CLEAR,
+ MLAN_PSK_QUERY,
+ MLAN_PSK_SAE_PASSWORD,
+};
+
+/** The bit to indicate the key is for unicast */
+#define MLAN_KEY_INDEX_UNICAST 0x40000000
+/** The key index to indicate default key */
+#define MLAN_KEY_INDEX_DEFAULT 0x000000ff
+/** Maximum key length */
+/* #define MLAN_MAX_KEY_LENGTH 32 */
+/** Minimum passphrase length */
+#define MLAN_MIN_PASSPHRASE_LENGTH 8
+/** Maximum passphrase length */
+#define MLAN_MAX_PASSPHRASE_LENGTH 63
+/** Minimum sae_password length */
+#define MLAN_MIN_SAE_PASSWORD_LENGTH 8
+/** Maximum sae_password length */
+#define MLAN_MAX_SAE_PASSWORD_LENGTH 255
+/** PMK length */
+#define MLAN_PMK_HEXSTR_LENGTH 64
+/* A few details needed for WEP (Wireless Equivalent Privacy) */
+/** 104 bits */
+#define MAX_WEP_KEY_SIZE 13
+/** 40 bits RC4 - WEP */
+#define MIN_WEP_KEY_SIZE 5
+/** packet number size */
+#define PN_SIZE 16
+/** max seq size of wpa/wpa2 key */
+#define SEQ_MAX_SIZE 8
+
+/** key flag for tx_seq */
+#define KEY_FLAG_TX_SEQ_VALID 0x00000001
+/** key flag for rx_seq */
+#define KEY_FLAG_RX_SEQ_VALID 0x00000002
+/** key flag for group key */
+#define KEY_FLAG_GROUP_KEY 0x00000004
+/** key flag for tx */
+#define KEY_FLAG_SET_TX_KEY 0x00000008
+/** key flag for mcast IGTK */
+#define KEY_FLAG_AES_MCAST_IGTK 0x00000010
+/** key flag for remove key */
+#define KEY_FLAG_REMOVE_KEY 0x80000000
+/** key flag for GCMP */
+#define KEY_FLAG_GCMP 0x00000020
+/** key flag for GCMP_256 */
+#define KEY_FLAG_GCMP_256 0x00000040
+/** key flag for ccmp 256 */
+#define KEY_FLAG_CCMP_256 0x00000080
+
+/** Type definition of mlan_ds_encrypt_key for MLAN_OID_SEC_CFG_ENCRYPT_KEY */
+typedef struct _mlan_ds_encrypt_key {
+ /** Key disabled, all other fields will be
+ * ignore when this flag set to MTRUE
+ */
+ t_u32 key_disable;
+ /** key removed flag, when this flag is set
+ * to MTRUE, only key_index will be check
+ */
+ t_u32 key_remove;
+ /** Key index, used as current tx key index
+ * when is_current_wep_key is set to MTRUE
+ */
+ t_u32 key_index;
+ /** Current Tx key flag */
+ t_u32 is_current_wep_key;
+ /** Key length */
+ t_u32 key_len;
+ /** Key */
+ t_u8 key_material[MLAN_MAX_KEY_LENGTH];
+ /** mac address */
+ t_u8 mac_addr[MLAN_MAC_ADDR_LENGTH];
+ /** wapi key flag */
+ t_u32 is_wapi_key;
+ /** Initial packet number */
+ t_u8 pn[PN_SIZE];
+ /** key flags */
+ t_u32 key_flags;
+} mlan_ds_encrypt_key, *pmlan_ds_encrypt_key;
+
+/** Type definition of mlan_passphrase_t */
+typedef struct _mlan_passphrase_t {
+ /** Length of passphrase */
+ t_u32 passphrase_len;
+ /** Passphrase */
+ t_u8 passphrase[MLAN_MAX_PASSPHRASE_LENGTH];
+} mlan_passphrase_t;
+
+/** Type definition of mlan_sae_password_t */
+typedef struct _mlan_sae_password_t {
+ /** Length of SAE Password */
+ t_u32 sae_password_len;
+ /** SAE Password */
+ t_u8 sae_password[MLAN_MAX_SAE_PASSWORD_LENGTH];
+} mlan_sae_password_t;
+
+/** Type defnition of mlan_pmk_t */
+typedef struct _mlan_pmk_t {
+ /** PMK */
+ t_u8 pmk[MLAN_MAX_KEY_LENGTH];
+} mlan_pmk_t;
+
+/** Embedded supplicant RSN type: No RSN */
+#define RSN_TYPE_NO_RSN MBIT(0)
+/** Embedded supplicant RSN type: WPA */
+#define RSN_TYPE_WPA MBIT(3)
+/** Embedded supplicant RSN type: WPA-NONE */
+#define RSN_TYPE_WPANONE MBIT(4)
+/** Embedded supplicant RSN type: WPA2 */
+#define RSN_TYPE_WPA2 MBIT(5)
+/** Embedded supplicant RSN type: RFU */
+#define RSN_TYPE_VALID_BITS \
+ (RSN_TYPE_NO_RSN | RSN_TYPE_WPA | RSN_TYPE_WPANONE | RSN_TYPE_WPA2)
+
+/** Embedded supplicant cipher type: TKIP */
+#define EMBED_CIPHER_TKIP MBIT(2)
+/** Embedded supplicant cipher type: AES */
+#define EMBED_CIPHER_AES MBIT(3)
+/** Embedded supplicant cipher type: RFU */
+#define EMBED_CIPHER_VALID_BITS (EMBED_CIPHER_TKIP | EMBED_CIPHER_AES)
+
+/** Type definition of mlan_ds_passphrase for MLAN_OID_SEC_CFG_PASSPHRASE */
+typedef struct _mlan_ds_passphrase {
+ /** SSID may be used */
+ mlan_802_11_ssid ssid;
+ /** BSSID may be used */
+ mlan_802_11_mac_addr bssid;
+ /** Flag for passphrase or pmk used */
+ t_u16 psk_type;
+ /** Passphrase or PMK */
+ union {
+ /** Passphrase */
+ mlan_passphrase_t passphrase;
+ /** SAE Password */
+ mlan_sae_password_t sae_password;
+ /** PMK */
+ mlan_pmk_t pmk;
+ } psk;
+} mlan_ds_passphrase, *pmlan_ds_passphrase;
+
+/** Type definition of mlan_ds_esupp_mode for MLAN_OID_SEC_CFG_ESUPP_MODE */
+typedef struct _mlan_ds_ewpa_mode {
+ /** RSN mode */
+ t_u32 rsn_mode;
+ /** Active pairwise cipher */
+ t_u32 act_paircipher;
+ /** Active pairwise cipher */
+ t_u32 act_groupcipher;
+} mlan_ds_esupp_mode, *pmlan_ds_esupp_mode;
+
+/** Type definition of mlan_ds_sec_cfg for MLAN_IOCTL_SEC_CFG */
+typedef struct _mlan_ds_sec_cfg {
+ /** Sub-command */
+ t_u32 sub_command;
+ /** Security configuration parameter */
+ union {
+ /** Authentication mode for MLAN_OID_SEC_CFG_AUTH_MODE */
+ t_u32 auth_mode;
+ /** Encryption mode for MLAN_OID_SEC_CFG_ENCRYPT_MODE */
+ t_u32 encrypt_mode;
+ /** WPA enabled flag for MLAN_OID_SEC_CFG_WPA_ENABLED */
+ t_u32 wpa_enabled;
+ /** WAPI enabled flag for MLAN_OID_SEC_CFG_WAPI_ENABLED */
+ t_u32 wapi_enabled;
+ /** Port Control enabled flag for MLAN_OID_SEC_CFG_PORT_CTRL */
+ t_u32 port_ctrl_enabled;
+ /** Encryption key for MLAN_OID_SEC_CFG_ENCRYPT_KEY */
+ mlan_ds_encrypt_key encrypt_key;
+ /** Passphrase for MLAN_OID_SEC_CFG_PASSPHRASE */
+ mlan_ds_passphrase passphrase;
+ /** Embedded supplicant WPA enabled flag for
+ * MLAN_OID_SEC_CFG_EWPA_ENABLED
+ */
+ t_u32 ewpa_enabled;
+ /** Embedded supplicant mode for MLAN_OID_SEC_CFG_ESUPP_MODE */
+ mlan_ds_esupp_mode esupp_mode;
+#ifdef UAP_SUPPORT
+ t_u8 sta_mac[MLAN_MAC_ADDR_LENGTH];
+#endif
+ } param;
+} mlan_ds_sec_cfg, *pmlan_ds_sec_cfg;
+
+#if defined(DRV_EMBEDDED_AUTHENTICATOR) || defined(DRV_EMBEDDED_SUPPLICANT)
+#define BIT_TLV_TYPE_CRYPTO_KEY (1 << 0)
+#define BIT_TLV_TYPE_CRYPTO_KEY_IV (1 << 1)
+#define BIT_TLV_TYPE_CRYPTO_KEY_PREFIX (1 << 2)
+#define BIT_TLV_TYPE_CRYPTO_KEY_DATA_BLK (1 << 3)
+
+/** Type definition of mlan_ds_sup_cfg */
+typedef struct _mlan_ds_sup_cfg {
+ /** Sub-command */
+ t_u8 sub_command;
+ /** output length */
+ t_u16 output_len;
+ /** number of data blks */
+ t_u16 data_blks_nr;
+ /** sub action code */
+ t_u8 sub_action_code;
+ /** skip bytes */
+ t_u16 skip_bytes;
+ /** iteration */
+ t_u32 iteration;
+ /** count */
+ t_u32 count;
+ /** pointer to output */
+ t_u8 *output;
+ /** key length */
+ t_u16 key_len;
+ /** pointer to key */
+ t_u8 *key;
+ /** key iv length */
+ t_u16 key_iv_len;
+ /** pointer to key iv */
+ t_u8 *key_iv;
+ /** key prefix length */
+ t_u16 key_prefix_len;
+ /** pointer to key prefix */
+ t_u8 *key_prefix;
+ /** pointer to data blk length array */
+ t_u32 *key_data_blk_len;
+ /** pointer to key data blk pointer array */
+ t_u8 **key_data_blk;
+ /** callback */
+ t_u8 call_back;
+} mlan_ds_sup_cfg, *pmlan_ds_sup_cfg;
+#endif
+
+/*-----------------------------------------------------------------*/
+/** Rate Configuration Group */
+/*-----------------------------------------------------------------*/
+/** Enumeration for rate type */
+enum _mlan_rate_type { MLAN_RATE_INDEX, MLAN_RATE_VALUE, MLAN_RATE_BITMAP };
+
+/** Enumeration for rate format */
+enum _mlan_rate_format {
+ MLAN_RATE_FORMAT_LG = 0,
+ MLAN_RATE_FORMAT_HT,
+ MLAN_RATE_FORMAT_VHT,
+ MLAN_RATE_FORMAT_HE,
+ MLAN_RATE_FORMAT_AUTO = 0xFF,
+};
+
+/** Max bitmap rates size */
+#define MAX_BITMAP_RATES_SIZE 26
+
+/** Type definition of mlan_rate_cfg_t for MLAN_OID_RATE_CFG */
+typedef struct _mlan_rate_cfg_t {
+ /** Fixed rate: 0, auto rate: 1 */
+ t_u32 is_rate_auto;
+ /** Rate type. 0: index; 1: value; 2: bitmap */
+ t_u32 rate_type;
+ /** Rate/MCS index or rate value if fixed rate */
+ t_u32 rate;
+ /** Rate Bitmap */
+ t_u16 bitmap_rates[MAX_BITMAP_RATES_SIZE];
+ /** NSS */
+ t_u32 nss;
+ /* LG rate: 0, HT rate: 1, VHT rate: 2 */
+ t_u32 rate_format;
+ /** Rate Setting */
+ t_u16 rate_setting;
+} mlan_rate_cfg_t;
+
+/** HT channel bandwidth */
+typedef enum _mlan_ht_bw {
+ MLAN_HT_BW20,
+ MLAN_HT_BW40,
+ /** VHT channel bandwidth */
+ MLAN_VHT_BW80,
+ MLAN_VHT_BW160,
+} mlan_ht_bw;
+
+/** HT guard interval */
+typedef enum _mlan_ht_gi {
+ MLAN_HT_LGI,
+ MLAN_HT_SGI,
+} mlan_ht_gi;
+
+typedef enum _mlan_vht_stbc {
+ MLAN_VHT_STBC,
+ MLAN_VHT_NO_STBC,
+} mlan_vht_stbc;
+
+typedef enum _mlan_vht_ldpc {
+ MLAN_VHT_LDPC,
+ MLAN_VHT_NO_LDPC,
+} mlan_vht_ldpc;
+
+/** Band and BSS mode */
+typedef struct _mlan_band_data_rate {
+ /** Band configuration */
+ t_u8 config_bands;
+ /** BSS mode (Infra or IBSS) */
+ t_u8 bss_mode;
+} mlan_band_data_rate;
+
+/** Type definition of mlan_data_rate for MLAN_OID_GET_DATA_RATE */
+typedef struct _mlan_data_rate {
+ /** Tx data rate */
+ t_u32 tx_data_rate;
+ /** Rx data rate */
+ t_u32 rx_data_rate;
+
+ /** Tx channel bandwidth */
+ t_u32 tx_ht_bw;
+ /** Tx guard interval */
+ t_u32 tx_ht_gi;
+ /** Rx channel bandwidth */
+ t_u32 rx_ht_bw;
+ /** Rx guard interval */
+ t_u32 rx_ht_gi;
+ /** MCS index */
+ t_u32 tx_mcs_index;
+ t_u32 rx_mcs_index;
+ /** NSS */
+ t_u32 tx_nss;
+ t_u32 rx_nss;
+ /* LG rate: 0, HT rate: 1, VHT rate: 2 */
+ t_u32 tx_rate_format;
+ t_u32 rx_rate_format;
+} mlan_data_rate;
+
+/** Type definition of mlan_ds_rate for MLAN_IOCTL_RATE */
+typedef struct _mlan_ds_rate {
+ /** Sub-command */
+ t_u32 sub_command;
+ /** Rate configuration parameter */
+ union {
+ /** Rate configuration for MLAN_OID_RATE_CFG */
+ mlan_rate_cfg_t rate_cfg;
+ /** Data rate for MLAN_OID_GET_DATA_RATE */
+ mlan_data_rate data_rate;
+ /** Supported rates for MLAN_OID_SUPPORTED_RATES */
+ t_u8 rates[MLAN_SUPPORTED_RATES];
+ /** Band/BSS mode for getting supported rates */
+ mlan_band_data_rate rate_band_cfg;
+ } param;
+} mlan_ds_rate, *pmlan_ds_rate;
+
+/*-----------------------------------------------------------------*/
+/** Power Configuration Group */
+/*-----------------------------------------------------------------*/
+
+/** Type definition of mlan_power_cfg_t for MLAN_OID_POWER_CFG */
+typedef struct _mlan_power_cfg_t {
+ /** Is power auto */
+ t_u32 is_power_auto;
+ /** Power level in dBm */
+ t_s32 power_level;
+} mlan_power_cfg_t;
+
+/** max power table size */
+#define MAX_POWER_TABLE_SIZE 128
+#define TX_PWR_CFG_AUTO_CTRL_OFF 0xFF
+#define MAX_POWER_GROUP 64
+/** Type definition of mlan_power group info */
+typedef struct mlan_power_group {
+ /** rate format (LG: 0, HT: 1, VHT: 2, no auto ctrl: 0xFF) */
+ t_u32 rate_format;
+ /** bandwidth (LG: 20 MHz, HT: 20/40 MHz, VHT: 80/160/80+80 MHz) */
+ t_u8 bandwidth;
+ /** NSS */
+ t_u32 nss;
+ /** LG: first rate index, HT/VHT: first MCS */
+ t_u8 first_rate_ind;
+ /** LG: last rate index, HT/VHT: last MCS */
+ t_u8 last_rate_ind;
+ /** minmum tx power (dBm) */
+ t_s8 power_min;
+ /** maximum tx power (dBm) */
+ t_s8 power_max;
+ /** tx power step (dB) */
+ t_s8 power_step;
+} mlan_power_group;
+
+/** Type definition of mlan_power_cfg_ext for MLAN_OID_POWER_CFG_EXT */
+typedef struct _mlan_power_cfg_ext {
+ /** number of power_groups */
+ t_u32 num_pwr_grp;
+ /** array of power groups */
+ mlan_power_group power_group[MAX_POWER_GROUP];
+} mlan_power_cfg_ext;
+
+/** Type definition of mlan_ds_power_cfg for MLAN_IOCTL_POWER_CFG */
+typedef struct _mlan_ds_power_cfg {
+ /** Sub-command */
+ t_u32 sub_command;
+ /** Power configuration parameter */
+ union {
+ /** Power configuration for MLAN_OID_POWER_CFG */
+ mlan_power_cfg_t power_cfg;
+ /** Extended power configuration for MLAN_OID_POWER_CFG_EXT */
+ mlan_power_cfg_ext power_ext;
+ /** Low power mode for MLAN_OID_POWER_LOW_POWER_MODE */
+ t_u16 lpm;
+ } param;
+} mlan_ds_power_cfg, *pmlan_ds_power_cfg;
+
+/** Type definition of mlan_ds_band_steer_cfg for MLAN_IOCTL_POWER_CFG */
+typedef struct _mlan_ds_band_steer_cfg {
+ /** Set/Get */
+ t_u8 action;
+ /** enable/disable band steering*/
+ t_u8 state;
+ /** Probe Response will be blocked to 2G channel for first
+ * block_2g_prb_req probe requests*/
+ t_u8 block_2g_prb_req;
+ /** When band steering is enabled, limit the btm request sent to STA at
+ * <max_btm_req_allowed>*/
+ t_u8 max_btm_req_allowed;
+} mlan_ds_band_steer_cfg, *pmlan_ds_band_steer_cfg;
+
+/** Type definition of mlan_ds_beacon_stuck_param_cfg for MLAN_IOCTL_POWER_CFG
+ */
+typedef struct _mlan_ds_beacon_stuck_param_cfg {
+ /** subcmd */
+ t_u32 subcmd;
+ /** Set/Get */
+ t_u8 action;
+ /** No of beacon interval after which firmware will check if beacon Tx
+ * is going fine */
+ t_u8 beacon_stuck_detect_count;
+ /** Upon performing MAC reset, no of beacon interval after which
+ * firmware will check if recovery was successful */
+ t_u8 recovery_confirm_count;
+} mlan_ds_beacon_stuck_param_cfg, *pmlan_ds_beacon_stuck_param_cfg;
+
+/*-----------------------------------------------------------------*/
+/** Power Management Configuration Group */
+/*-----------------------------------------------------------------*/
+/** Host sleep config conditions : Cancel */
+#define HOST_SLEEP_CFG_CANCEL 0xffffffff
+
+/** Host sleep config condition: broadcast data */
+#define HOST_SLEEP_COND_BROADCAST_DATA MBIT(0)
+/** Host sleep config condition: unicast data */
+#define HOST_SLEEP_COND_UNICAST_DATA MBIT(1)
+/** Host sleep config condition: mac event */
+#define HOST_SLEEP_COND_MAC_EVENT MBIT(2)
+/** Host sleep config condition: multicast data */
+#define HOST_SLEEP_COND_MULTICAST_DATA MBIT(3)
+/** Host sleep config condition: IPV6 packet */
+#define HOST_SLEEP_COND_IPV6_PACKET MBIT(31)
+
+/** Host sleep config conditions: Default */
+#define HOST_SLEEP_DEF_COND 0
+
+/** Host sleep config GPIO : Default */
+#define HOST_SLEEP_DEF_GPIO 0xff
+/** Host sleep config gap : Default */
+#define HOST_SLEEP_DEF_GAP 200
+/** Host sleep config min wake holdoff */
+#define HOST_SLEEP_DEF_WAKE_HOLDOFF 0;
+/** Host sleep config inactivity timeout */
+#define HOST_SLEEP_DEF_INACTIVITY_TIMEOUT 10;
+
+/** Type definition of mlan_ds_hs_cfg for MLAN_OID_PM_CFG_HS_CFG */
+typedef struct _mlan_ds_hs_cfg {
+ /** MTRUE to invoke the HostCmd, MFALSE otherwise */
+ t_u32 is_invoke_hostcmd;
+ /** Host sleep config condition */
+ /** Bit0: broadcast data
+ * Bit1: unicast data
+ * Bit2: mac event
+ * Bit3: multicast data
+ */
+ t_u32 conditions;
+ /** GPIO pin or 0xff for interface */
+ t_u32 gpio;
+ /** Gap in milliseconds or or 0xff for special
+ * setting when GPIO is used to wakeup host
+ */
+ t_u32 gap;
+ /** Host sleep wake interval */
+ t_u32 hs_wake_interval;
+ /** Parameter type for indication gpio*/
+ t_u8 param_type_ind;
+ /** GPIO pin for indication wakeup source */
+ t_u32 ind_gpio;
+ /** Level on ind_gpio pin for indication normal wakeup source */
+ t_u32 level;
+ /** Parameter type for extend hscfg*/
+ t_u8 param_type_ext;
+ /** Events that will be forced ignore*/
+ t_u32 event_force_ignore;
+ /** Events that will use extend gap to inform host*/
+ t_u32 event_use_ext_gap;
+ /** Ext gap*/
+ t_u8 ext_gap;
+ /** GPIO wave level for extend hscfg*/
+ t_u8 gpio_wave;
+} mlan_ds_hs_cfg, *pmlan_ds_hs_cfg;
+
+#define MAX_MGMT_FRAME_FILTER 2
+typedef struct _mlan_mgmt_frame_wakeup {
+ /** action - bitmap
+ ** On matching rx'd pkt and filter during NON_HOSTSLEEP mode:
+ ** Action[1]=0 Discard
+ ** Action[1]=1 Allow
+ ** Note that default action on non-match is "Allow".
+ **
+ ** On matching rx'd pkt and filter during HOSTSLEEP mode:
+ ** Action[1:0]=00 Discard and Not Wake host
+ ** Action[1:0]=01 Discard and Wake host
+ ** Action[1:0]=10 Invalid
+ ** Note that default action on non-match is "Discard and Not Wake
+ *host".
+ **/
+ t_u32 action;
+ /** Frame type(p2p, tdls...)
+ ** type=0: invalid
+ ** type=1: p2p
+ ** type=others: reserved
+ **/
+ t_u32 type;
+ /** Frame mask according to each type
+ ** When type=1 for p2p, frame-mask have following define:
+ ** Bit Frame
+ ** 0 GO Negotiation Request
+ ** 1 GO Negotiation Response
+ ** 2 GO Negotiation Confirmation
+ ** 3 P2P Invitation Request
+ ** 4 P2P Invitation Response
+ ** 5 Device Discoverability Request
+ ** 6 Device Discoverability Response
+ ** 7 Provision Discovery Request
+ ** 8 Provision Discovery Response
+ ** 9 Notice of Absence
+ ** 10 P2P Presence Request
+ ** 11 P2P Presence Response
+ ** 12 GO Discoverability Request
+ ** 13-31 Reserved
+ **
+ ** When type=others, frame-mask is reserved.
+ **/
+ t_u32 frame_mask;
+} mlan_mgmt_frame_wakeup, *pmlan_mgmt_frame_wakeup;
+
+/** Enable deep sleep mode */
+#define DEEP_SLEEP_ON 1
+/** Disable deep sleep mode */
+#define DEEP_SLEEP_OFF 0
+
+/** Default idle time in milliseconds for auto deep sleep */
+#define DEEP_SLEEP_IDLE_TIME 100
+
+typedef struct _mlan_ds_auto_ds {
+ /** auto ds mode, 0 - disable, 1 - enable */
+ t_u16 auto_ds;
+ /** auto ds idle time in milliseconds */
+ t_u16 idletime;
+} mlan_ds_auto_ds;
+
+/** Type definition of mlan_ds_inactivity_to
+ * for MLAN_OID_PM_CFG_INACTIVITY_TO
+ */
+typedef struct _mlan_ds_inactivity_to {
+ /** Timeout unit in microsecond, 0 means 1000us (1ms) */
+ t_u32 timeout_unit;
+ /** Inactivity timeout for unicast data */
+ t_u32 unicast_timeout;
+ /** Inactivity timeout for multicast data */
+ t_u32 mcast_timeout;
+ /** Timeout for additional Rx traffic after Null PM1 packet exchange */
+ t_u32 ps_entry_timeout;
+} mlan_ds_inactivity_to, *pmlan_ds_inactivity_to;
+
+/** Minimum sleep period in milliseconds */
+#define MIN_SLEEP_PERIOD 10
+/** Maximum sleep period in milliseconds */
+#define MAX_SLEEP_PERIOD 60
+/** Special setting for UPSD certification tests */
+#define SLEEP_PERIOD_RESERVED_FF 0xFF
+
+/** PS null interval disable */
+#define PS_NULL_DISABLE (-1)
+
+/** Local listen interval disable */
+#define MRVDRV_LISTEN_INTERVAL_DISABLE (-1)
+/** Minimum listen interval */
+#define MRVDRV_MIN_LISTEN_INTERVAL 0
+
+/** Minimum multiple DTIM */
+#define MRVDRV_MIN_MULTIPLE_DTIM 0
+/** Maximum multiple DTIM */
+#define MRVDRV_MAX_MULTIPLE_DTIM 5
+/** Ignore multiple DTIM */
+#define MRVDRV_IGNORE_MULTIPLE_DTIM 0xfffe
+/** Match listen interval to closest DTIM */
+#define MRVDRV_MATCH_CLOSEST_DTIM 0xfffd
+
+/** Minimum beacon miss timeout in milliseconds */
+#define MIN_BCN_MISS_TO 0
+/** Maximum beacon miss timeout in milliseconds */
+#define MAX_BCN_MISS_TO 50
+/** Disable beacon miss timeout */
+#define DISABLE_BCN_MISS_TO 65535
+
+/** Minimum delay to PS in milliseconds */
+#define MIN_DELAY_TO_PS 0
+/** Maximum delay to PS in milliseconds */
+#define MAX_DELAY_TO_PS 65535
+/** Delay to PS unchanged */
+#define DELAY_TO_PS_UNCHANGED (-1)
+/** Default delay to PS in milliseconds */
+#define DELAY_TO_PS_DEFAULT 1000
+
+/** PS mode: Unchanged */
+#define PS_MODE_UNCHANGED 0
+/** PS mode: Auto */
+#define PS_MODE_AUTO 1
+/** PS mode: Poll */
+#define PS_MODE_POLL 2
+/** PS mode: Null */
+#define PS_MODE_NULL 3
+
+/** Type definition of mlan_ds_ps_cfg for MLAN_OID_PM_CFG_PS_CFG */
+typedef struct _mlan_ds_ps_cfg {
+ /** PS null interval in seconds */
+ t_u32 ps_null_interval;
+ /** Multiple DTIM interval */
+ t_u32 multiple_dtim_interval;
+ /** Listen interval */
+ t_u32 listen_interval;
+ /** Beacon miss timeout in milliseconds */
+ t_u32 bcn_miss_timeout;
+ /** Delay to PS in milliseconds */
+ t_s32 delay_to_ps;
+ /** PS mode */
+ t_u32 ps_mode;
+} mlan_ds_ps_cfg, *pmlan_ds_ps_cfg;
+
+/** Type definition of mlan_ds_sleep_params for MLAN_OID_PM_CFG_SLEEP_PARAMS */
+typedef struct _mlan_ds_sleep_params {
+ /** Error */
+ t_u32 error;
+ /** Offset in microseconds */
+ t_u32 offset;
+ /** Stable time in microseconds */
+ t_u32 stable_time;
+ /** Calibration control */
+ t_u32 cal_control;
+ /** External sleep clock */
+ t_u32 ext_sleep_clk;
+ /** Reserved */
+ t_u32 reserved;
+} mlan_ds_sleep_params, *pmlan_ds_sleep_params;
+
+/** sleep_param */
+typedef struct _ps_sleep_param {
+ /** control bitmap */
+ t_u32 ctrl_bitmap;
+ /** minimum sleep period (micro second) */
+ t_u32 min_sleep;
+ /** maximum sleep period (micro second) */
+ t_u32 max_sleep;
+} ps_sleep_param;
+
+/** inactivity sleep_param */
+typedef struct _inact_sleep_param {
+ /** inactivity timeout (micro second) */
+ t_u32 inactivity_to;
+ /** miniumu awake period (micro second) */
+ t_u32 min_awake;
+ /** maximum awake period (micro second) */
+ t_u32 max_awake;
+} inact_sleep_param;
+
+/** flag for ps mode */
+#define PS_FLAG_PS_MODE 1
+/** flag for sleep param */
+#define PS_FLAG_SLEEP_PARAM 2
+/** flag for inactivity sleep param */
+#define PS_FLAG_INACT_SLEEP_PARAM 4
+
+/** Enable Robust Coex mode */
+#define ROBUSTCOEX_GPIOCFG_ENABLE 1
+/** Disable Robust Coex mode */
+#define ROBUSTCOEX_GPIOCFG_DISABLE 0
+
+/** Disable power mode */
+#define PS_MODE_DISABLE 0
+/** Enable periodic dtim ps */
+#define PS_MODE_PERIODIC_DTIM 1
+/** Enable inactivity ps */
+#define PS_MODE_INACTIVITY 2
+/** FW wake up method interface */
+#define FW_WAKEUP_METHOD_INTERFACE 1
+/** FW wake up method gpio */
+#define FW_WAKEUP_METHOD_GPIO 2
+/** mlan_ds_ps_mgmt */
+typedef struct _mlan_ds_ps_mgmt {
+ /** flags for valid field */
+ t_u16 flags;
+ /** power mode */
+ t_u16 ps_mode;
+ /** sleep param */
+ ps_sleep_param sleep_param;
+ /** inactivity sleep param */
+ inact_sleep_param inact_param;
+} mlan_ds_ps_mgmt;
+
+/** mlan_ds_ps_info */
+typedef struct _mlan_ds_ps_info {
+ /** suspend allowed flag */
+ t_u32 is_suspend_allowed;
+} mlan_ds_ps_info;
+
+/** Type definition of mlan_ds_wakeup_reason for MLAN_OID_PM_HS_WAKEUP_REASON */
+typedef struct _mlan_ds_hs_wakeup_reason {
+ t_u16 hs_wakeup_reason;
+} mlan_ds_hs_wakeup_reason;
+
+/** Type definition of mlan_ds_ps_cfg for MLAN_OID_PM_CFG_PS_CFG */
+typedef struct _mlan_ds_bcn_timeout {
+ /** Beacon miss timeout period window */
+ t_u16 bcn_miss_tmo_window;
+ /** Beacon miss timeout period */
+ t_u16 bcn_miss_tmo_period;
+ /** Beacon reacquire timeout period window */
+ t_u16 bcn_rq_tmo_window;
+ /** Beacon reacquire timeout period */
+ t_u16 bcn_rq_tmo_period;
+} mlan_ds_bcn_timeout, *pmlan_ds_bcn_timeout;
+
+/** Type definition of mlan_ds_pm_cfg for MLAN_IOCTL_PM_CFG */
+typedef struct _mlan_ds_pm_cfg {
+ /** Sub-command */
+ t_u32 sub_command;
+ /** Power management parameter */
+ union {
+ /** Power saving mode for MLAN_OID_PM_CFG_IEEE_PS */
+ t_u32 ps_mode;
+ /** Host Sleep configuration for MLAN_OID_PM_CFG_HS_CFG */
+ mlan_ds_hs_cfg hs_cfg;
+ /** Deep sleep mode for MLAN_OID_PM_CFG_DEEP_SLEEP */
+ mlan_ds_auto_ds auto_deep_sleep;
+ /** Inactivity timeout for MLAN_OID_PM_CFG_INACTIVITY_TO */
+ mlan_ds_inactivity_to inactivity_to;
+ /** Sleep period for MLAN_OID_PM_CFG_SLEEP_PD */
+ t_u32 sleep_period;
+ /** PS configuration parameters for MLAN_OID_PM_CFG_PS_CFG */
+ mlan_ds_ps_cfg ps_cfg;
+ /** PS configuration parameters for MLAN_OID_PM_CFG_SLEEP_PARAMS
+ */
+ mlan_ds_sleep_params sleep_params;
+ /** PS configuration parameters for MLAN_OID_PM_CFG_PS_MODE */
+ mlan_ds_ps_mgmt ps_mgmt;
+ /** power info for MLAN_OID_PM_INFO */
+ mlan_ds_ps_info ps_info;
+ /** hs wakeup reason for MLAN_OID_PM_HS_WAKEUP_REASON */
+ mlan_ds_hs_wakeup_reason wakeup_reason;
+ /** config manamgement frame for hs wakeup */
+ mlan_mgmt_frame_wakeup mgmt_filter[MAX_MGMT_FRAME_FILTER];
+ /** Beacon timout parameters for MLAN_OID_PM_CFG_BCN_TIMEOUT */
+ mlan_ds_bcn_timeout bcn_timeout;
+ } param;
+} mlan_ds_pm_cfg, *pmlan_ds_pm_cfg;
+
+#ifdef RX_PACKET_COALESCE
+typedef struct {
+ mlan_cmd_result_e cmd_result; /**< Firmware execution result */
+
+ t_u32 pkt_threshold; /** Packet threshold */
+ t_u16 delay; /** Timeout value in milliseconds */
+} wlan_ioctl_rx_pkt_coalesce_config_t;
+#endif
+
+/*-----------------------------------------------------------------*/
+/** WMM Configuration Group */
+/*-----------------------------------------------------------------*/
+
+/** WMM TSpec size */
+#define MLAN_WMM_TSPEC_SIZE 63
+/** WMM Add TS extra IE bytes */
+#define MLAN_WMM_ADDTS_EXTRA_IE_BYTES 256
+/** WMM statistics for packets hist bins */
+#define MLAN_WMM_STATS_PKTS_HIST_BINS 7
+/** Maximum number of AC QOS queues available */
+#define MLAN_WMM_MAX_AC_QUEUES 4
+
+/**
+ * @brief IOCTL structure to send an ADDTS request and retrieve the response.
+ *
+ * IOCTL structure from the application layer relayed to firmware to
+ * instigate an ADDTS management frame with an appropriate TSPEC IE as well
+ * as any additional IEs appended in the ADDTS Action frame.
+ *
+ * @sa woal_wmm_addts_req_ioctl
+ */
+typedef struct {
+ mlan_cmd_result_e cmd_result; /**< Firmware execution result */
+
+ t_u32 timeout_ms; /**< Timeout value in milliseconds */
+ t_u8 ieee_status_code; /**< IEEE status code */
+
+ t_u32 ie_data_len; /**< Length of ie block in ie_data */
+ t_u8 ie_data[MLAN_WMM_TSPEC_SIZE /**< TSPEC to send in the ADDTS */
+ + MLAN_WMM_ADDTS_EXTRA_IE_BYTES]; /**< Extra IE buf*/
+} wlan_ioctl_wmm_addts_req_t;
+
+/**
+ * @brief IOCTL structure to send a DELTS request.
+ *
+ * IOCTL structure from the application layer relayed to firmware to
+ * instigate an DELTS management frame with an appropriate TSPEC IE.
+ *
+ * @sa woal_wmm_delts_req_ioctl
+ */
+typedef struct {
+ mlan_cmd_result_e cmd_result; /**< Firmware execution result */
+ t_u8 ieee_reason_code; /**< IEEE reason code sent, unused for WMM */
+ t_u32 ie_data_len; /**< Length of ie block in ie_data */
+ t_u8 ie_data[MLAN_WMM_TSPEC_SIZE]; /**< TSPEC to send in the DELTS */
+} wlan_ioctl_wmm_delts_req_t;
+
+/**
+ * @brief IOCTL structure to configure a specific AC Queue's parameters
+ *
+ * IOCTL structure from the application layer relayed to firmware to
+ * get, set, or default the WMM AC queue parameters.
+ *
+ * - msdu_lifetime_expiry is ignored if set to 0 on a set command
+ *
+ * @sa woal_wmm_queue_config_ioctl
+ */
+typedef struct {
+ mlan_wmm_queue_config_action_e action; /**< Set, Get, or Default */
+ mlan_wmm_ac_e access_category; /**< WMM_AC_BK(0) to WMM_AC_VO(3) */
+ t_u16 msdu_lifetime_expiry; /**< lifetime expiry in TUs */
+ t_u8 supported_rates[10]; /**< Not supported yet */
+} wlan_ioctl_wmm_queue_config_t;
+
+/**
+ * @brief IOCTL structure to start, stop, and get statistics for a WMM AC
+ *
+ * IOCTL structure from the application layer relayed to firmware to
+ * start or stop statistical collection for a given AC. Also used to
+ * retrieve and clear the collected stats on a given AC.
+ *
+ * @sa woal_wmm_queue_stats_ioctl
+ */
+typedef struct {
+ /** Action of Queue Config : Start, Stop, or Get */
+ mlan_wmm_queue_stats_action_e action;
+ /** User Priority */
+ t_u8 user_priority;
+ /** Number of successful packets transmitted */
+ t_u16 pkt_count;
+ /** Packets lost; not included in pkt_count */
+ t_u16 pkt_loss;
+ /** Average Queue delay in microseconds */
+ t_u32 avg_queue_delay;
+ /** Average Transmission delay in microseconds */
+ t_u32 avg_tx_delay;
+ /** Calculated used time in units of 32 microseconds */
+ t_u16 used_time;
+ /** Calculated policed time in units of 32 microseconds */
+ t_u16 policed_time;
+ /** Queue Delay Histogram; number of packets per queue delay range
+ *
+ * [0] - 0ms <= delay < 5ms
+ * [1] - 5ms <= delay < 10ms
+ * [2] - 10ms <= delay < 20ms
+ * [3] - 20ms <= delay < 30ms
+ * [4] - 30ms <= delay < 40ms
+ * [5] - 40ms <= delay < 50ms
+ * [6] - 50ms <= delay < msduLifetime (TUs)
+ */
+ t_u16 delay_histogram[MLAN_WMM_STATS_PKTS_HIST_BINS];
+} wlan_ioctl_wmm_queue_stats_t,
+ /** Type definition of mlan_ds_wmm_queue_stats
+ * for MLAN_OID_WMM_CFG_QUEUE_STATS
+ */
+ mlan_ds_wmm_queue_stats, *pmlan_ds_wmm_queue_stats;
+
+/**
+ * @brief IOCTL sub structure for a specific WMM AC Status
+ */
+typedef struct {
+ /** WMM Acm */
+ t_u8 wmm_acm;
+ /** Flow required flag */
+ t_u8 flow_required;
+ /** Flow created flag */
+ t_u8 flow_created;
+ /** Disabled flag */
+ t_u8 disabled;
+} wlan_ioctl_wmm_queue_status_ac_t;
+
+/**
+ * @brief IOCTL structure to retrieve the WMM AC Queue status
+ *
+ * IOCTL structure from the application layer to retrieve:
+ * - ACM bit setting for the AC
+ * - Firmware status (flow required, flow created, flow disabled)
+ *
+ * @sa woal_wmm_queue_status_ioctl
+ */
+typedef struct {
+ /** WMM AC queue status */
+ wlan_ioctl_wmm_queue_status_ac_t ac_status[MLAN_WMM_MAX_AC_QUEUES];
+} wlan_ioctl_wmm_queue_status_t,
+ /** Type definition of mlan_ds_wmm_queue_status
+ * for MLAN_OID_WMM_CFG_QUEUE_STATUS
+ */
+ mlan_ds_wmm_queue_status, *pmlan_ds_wmm_queue_status;
+
+/** Type definition of mlan_ds_wmm_addts for MLAN_OID_WMM_CFG_ADDTS */
+typedef struct _mlan_ds_wmm_addts {
+ /** Result of ADDTS request */
+ mlan_cmd_result_e result;
+ /** Timeout value in milliseconds */
+ t_u32 timeout;
+ /** IEEE status code */
+ t_u32 status_code;
+ /** Dialog token */
+ t_u8 dialog_tok;
+ /** TSPEC data length */
+ t_u32 ie_data_len;
+ /** TSPEC to send in the ADDTS + buffering for any extra IEs */
+ t_u8 ie_data[MLAN_WMM_TSPEC_SIZE + MLAN_WMM_ADDTS_EXTRA_IE_BYTES];
+} mlan_ds_wmm_addts, *pmlan_ds_wmm_addts;
+
+/** Type definition of mlan_ds_wmm_delts for MLAN_OID_WMM_CFG_DELTS */
+typedef struct _mlan_ds_wmm_delts {
+ /** Result of DELTS request */
+ mlan_cmd_result_e result;
+ /** IEEE status code */
+ t_u32 status_code;
+ /** TSPEC data length */
+ t_u8 ie_data_len;
+ /** TSPEC to send in the DELTS */
+ t_u8 ie_data[MLAN_WMM_TSPEC_SIZE];
+} mlan_ds_wmm_delts, *pmlan_ds_wmm_delts;
+
+/** Type definition of mlan_ds_wmm_queue_config
+ * for MLAN_OID_WMM_CFG_QUEUE_CONFIG
+ */
+typedef struct _mlan_ds_wmm_queue_config {
+ /** Action of Queue Config : Set, Get, or Default */
+ mlan_wmm_queue_config_action_e action;
+ /** WMM Access Category: WMM_AC_BK(0) to WMM_AC_VO(3) */
+ mlan_wmm_ac_e access_category;
+ /** Lifetime expiry in TUs */
+ t_u16 msdu_lifetime_expiry;
+ /** Reserve for future use */
+ t_u8 reserved[10];
+} mlan_ds_wmm_queue_config, *pmlan_ds_wmm_queue_config;
+
+/** Type definition of mlan_ds_wmm_cfg for MLAN_IOCTL_WMM_CFG */
+typedef struct _mlan_ds_wmm_cfg {
+ /** Sub-command */
+ t_u32 sub_command;
+ /** WMM configuration parameter */
+ union {
+ /** WMM enable for MLAN_OID_WMM_CFG_ENABLE */
+ t_u32 wmm_enable;
+ /** QoS configuration for MLAN_OID_WMM_CFG_QOS */
+ t_u8 qos_cfg;
+ /** WMM add TS for MLAN_OID_WMM_CFG_ADDTS */
+ mlan_ds_wmm_addts addts;
+ /** WMM delete TS for MLAN_OID_WMM_CFG_DELTS */
+ mlan_ds_wmm_delts delts;
+ /** WMM queue configuration for MLAN_OID_WMM_CFG_QUEUE_CONFIG */
+ mlan_ds_wmm_queue_config q_cfg;
+ /** AC Parameters Record WMM_AC_BE, WMM_AC_BK, WMM_AC_VI,
+ * WMM_AC_VO */
+ wmm_ac_parameters_t ac_params[MAX_AC_QUEUES];
+ /** WMM queue status for MLAN_OID_WMM_CFG_QUEUE_STATS */
+ mlan_ds_wmm_queue_stats q_stats;
+ /** WMM queue status for MLAN_OID_WMM_CFG_QUEUE_STATUS */
+ mlan_ds_wmm_queue_status q_status;
+ /** WMM TS status for MLAN_OID_WMM_CFG_TS_STATUS */
+ mlan_ds_wmm_ts_status ts_status;
+ } param;
+} mlan_ds_wmm_cfg, *pmlan_ds_wmm_cfg;
+
+/*-----------------------------------------------------------------*/
+/** WPS Configuration Group */
+/*-----------------------------------------------------------------*/
+/** Enumeration for WPS session */
+enum _mlan_wps_status {
+ MLAN_WPS_CFG_SESSION_START = 1,
+ MLAN_WPS_CFG_SESSION_END = 0
+};
+
+/** Type definition of mlan_ds_wps_cfg for MLAN_IOCTL_WPS_CFG */
+typedef struct _mlan_ds_wps_cfg {
+ /** Sub-command */
+ t_u32 sub_command;
+ /** WPS configuration parameter */
+ union {
+ /** WPS session for MLAN_OID_WPS_CFG_SESSION */
+ t_u32 wps_session;
+ } param;
+} mlan_ds_wps_cfg, *pmlan_ds_wps_cfg;
+
+/*-----------------------------------------------------------------*/
+/** 802.11n Configuration Group */
+/*-----------------------------------------------------------------*/
+/** Maximum MCS */
+#define NUM_MCS_FIELD 16
+
+/** Supported stream modes */
+#define HT_STREAM_MODE_1X1 0x11
+#define HT_STREAM_MODE_2X2 0x22
+
+/* Both 2.4G and 5G band selected */
+#define BAND_SELECT_BOTH 0
+/* Band 2.4G selected */
+#define BAND_SELECT_BG 1
+/* Band 5G selected */
+#define BAND_SELECT_A 2
+
+/** Type definition of mlan_ds_11n_htcap_cfg for MLAN_OID_11N_HTCAP_CFG */
+typedef struct _mlan_ds_11n_htcap_cfg {
+ /** HT Capability information */
+ t_u32 htcap;
+ /** Band selection */
+ t_u32 misc_cfg;
+ /** Hardware HT cap information required */
+ t_u32 hw_cap_req;
+} mlan_ds_11n_htcap_cfg, *pmlan_ds_11n_htcap_cfg;
+
+/** Type definition of mlan_ds_11n_addba_param
+ * for MLAN_OID_11N_CFG_ADDBA_PARAM
+ */
+typedef struct _mlan_ds_11n_addba_param {
+ /** Timeout */
+ t_u32 timeout;
+ /** Buffer size for ADDBA request */
+ t_u32 txwinsize;
+ /** Buffer size for ADDBA response */
+ t_u32 rxwinsize;
+ /** amsdu for ADDBA request */
+ t_u8 txamsdu;
+ /** amsdu for ADDBA response */
+ t_u8 rxamsdu;
+} mlan_ds_11n_addba_param, *pmlan_ds_11n_addba_param;
+
+/** Type definition of mlan_ds_11n_tx_cfg for MLAN_OID_11N_CFG_TX */
+typedef struct _mlan_ds_11n_tx_cfg {
+ /** HTTxCap */
+ t_u16 httxcap;
+ /** HTTxInfo */
+ t_u16 httxinfo;
+ /** Band selection */
+ t_u32 misc_cfg;
+} mlan_ds_11n_tx_cfg, *pmlan_ds_11n_tx_cfg;
+
+/** BF Global Configuration */
+#define BF_GLOBAL_CONFIGURATION 0x00
+/** Performs NDP sounding for PEER specified */
+#define TRIGGER_SOUNDING_FOR_PEER 0x01
+/** TX BF interval for channel sounding */
+#define SET_GET_BF_PERIODICITY 0x02
+/** Tell FW not to perform any sounding for peer */
+#define TX_BF_FOR_PEER_ENBL 0x03
+/** TX BF SNR threshold for peer */
+#define SET_SNR_THR_PEER 0x04
+/** TX Sounding*/
+#define TX_SOUNDING_CFG 0x05
+
+/* Maximum number of peer MAC and status/SNR tuples */
+#define MAX_PEER_MAC_TUPLES 10
+
+/** Any new subcommand structure should be declare here */
+
+/** bf global cfg args */
+typedef struct _mlan_bf_global_cfg_args {
+ /** Global enable/disable bf */
+ t_u8 bf_enbl;
+ /** Global enable/disable sounding */
+ t_u8 sounding_enbl;
+ /** FB Type */
+ t_u8 fb_type;
+ /** SNR Threshold */
+ t_u8 snr_threshold;
+ /** Sounding interval in milliseconds */
+ t_u16 sounding_interval;
+ /** BF mode */
+ t_u8 bf_mode;
+ /** Reserved */
+ t_u8 reserved;
+} mlan_bf_global_cfg_args;
+
+/** trigger sounding args */
+typedef struct _mlan_trigger_sound_args {
+ /** Peer MAC address */
+ t_u8 peer_mac[MLAN_MAC_ADDR_LENGTH];
+ /** Status */
+ t_u8 status;
+} mlan_trigger_sound_args;
+
+/** bf periodicity args */
+typedef struct _mlan_bf_periodicity_args {
+ /** Peer MAC address */
+ t_u8 peer_mac[MLAN_MAC_ADDR_LENGTH];
+ /** Current Tx BF Interval in milliseconds */
+ t_u16 interval;
+ /** Status */
+ t_u8 status;
+} mlan_bf_periodicity_args;
+
+/** tx bf peer args */
+typedef struct _mlan_tx_bf_peer_args {
+ /** Peer MAC address */
+ t_u8 peer_mac[MLAN_MAC_ADDR_LENGTH];
+ /** Reserved */
+ t_u16 reserved;
+ /** Enable/Disable Beamforming */
+ t_u8 bf_enbl;
+ /** Enable/Disable sounding */
+ t_u8 sounding_enbl;
+ /** FB Type */
+ t_u8 fb_type;
+} mlan_tx_bf_peer_args;
+
+/** SNR threshold args */
+typedef struct _mlan_snr_thr_args {
+ /** Peer MAC address */
+ t_u8 peer_mac[MLAN_MAC_ADDR_LENGTH];
+ /** SNR for peer */
+ t_u8 snr;
+} mlan_snr_thr_args;
+
+/** Type definition of mlan_ds_11n_tx_bf_cfg for MLAN_OID_11N_CFG_TX_BF_CFG */
+typedef struct _mlan_ds_11n_tx_bf_cfg {
+ /** BF Action */
+ t_u16 bf_action;
+ /** Action */
+ t_u16 action;
+ /** Number of peers */
+ t_u32 no_of_peers;
+ union {
+ mlan_bf_global_cfg_args bf_global_cfg;
+ mlan_trigger_sound_args bf_sound[MAX_PEER_MAC_TUPLES];
+ mlan_bf_periodicity_args bf_periodicity[MAX_PEER_MAC_TUPLES];
+ mlan_tx_bf_peer_args tx_bf_peer[MAX_PEER_MAC_TUPLES];
+ mlan_snr_thr_args bf_snr[MAX_PEER_MAC_TUPLES];
+ } body;
+} mlan_ds_11n_tx_bf_cfg, *pmlan_ds_11n_tx_bf_cfg;
+
+/** Type definition of mlan_ds_11n_amsdu_aggr_ctrl for
+ * MLAN_OID_11N_AMSDU_AGGR_CTRL*/
+typedef struct _mlan_ds_11n_amsdu_aggr_ctrl {
+ /** Enable/Disable */
+ t_u16 enable;
+ /** Current AMSDU size valid */
+ t_u16 curr_buf_size;
+} mlan_ds_11n_amsdu_aggr_ctrl, *pmlan_ds_11n_amsdu_aggr_ctrl;
+
+/** Type definition of mlan_ds_11n_aggr_prio_tbl
+ * for MLAN_OID_11N_CFG_AGGR_PRIO_TBL
+ */
+typedef struct _mlan_ds_11n_aggr_prio_tbl {
+ /** ampdu priority table */
+ t_u8 ampdu[MAX_NUM_TID];
+ /** amsdu priority table */
+ t_u8 amsdu[MAX_NUM_TID];
+} mlan_ds_11n_aggr_prio_tbl, *pmlan_ds_11n_aggr_prio_tbl;
+
+/** DelBA All TIDs */
+#define DELBA_ALL_TIDS 0xff
+/** DelBA Tx */
+#define DELBA_TX MBIT(0)
+/** DelBA Rx */
+#define DELBA_RX MBIT(1)
+
+/** Type definition of mlan_ds_11n_delba for MLAN_OID_11N_CFG_DELBA */
+typedef struct _mlan_ds_11n_delba {
+ /** TID */
+ t_u8 tid;
+ /** Peer MAC address */
+ t_u8 peer_mac_addr[MLAN_MAC_ADDR_LENGTH];
+ /** Direction (Tx: bit 0, Rx: bit 1) */
+ t_u8 direction;
+} mlan_ds_11n_delba, *pmlan_ds_11n_delba;
+
+/** Type definition of mlan_ds_delba for MLAN_OID_11N_CFG_REJECT_ADDBA_REQ */
+typedef struct _mlan_ds_reject_addba_req {
+ /** Bit0 : host sleep activated
+ * Bit1 : auto reconnect enabled
+ * Others : reserved
+ */
+ t_u32 conditions;
+} mlan_ds_reject_addba_req, *pmlan_ds_reject_addba_req;
+
+/** Type definition of mlan_ds_ibss_ampdu_param */
+typedef struct _mlan_ds_ibss_ampdu_param {
+ /** ampdu priority table */
+ t_u8 ampdu[MAX_NUM_TID];
+ /** rx amdpdu setting */
+ t_u8 addba_reject[MAX_NUM_TID];
+} mlan_ds_ibss_ampdu_param, *pmlan_ds_ibss_ampdu_param;
+
+/** Type definition of mlan_ds_11n_cfg for MLAN_IOCTL_11N_CFG */
+typedef struct _mlan_ds_11n_cfg {
+ /** Sub-command */
+ t_u32 sub_command;
+ /** 802.11n configuration parameter */
+ union {
+ /** Tx param for 11n for MLAN_OID_11N_CFG_TX */
+ mlan_ds_11n_tx_cfg tx_cfg;
+ /** Aggr priority table for MLAN_OID_11N_CFG_AGGR_PRIO_TBL */
+ mlan_ds_11n_aggr_prio_tbl aggr_prio_tbl;
+ /** Add BA param for MLAN_OID_11N_CFG_ADDBA_PARAM */
+ mlan_ds_11n_addba_param addba_param;
+ /** Add BA Reject paramters for MLAN_OID_11N_CFG_ADDBA_REJECT */
+ t_u8 addba_reject[MAX_NUM_TID];
+ /** Tx buf size for MLAN_OID_11N_CFG_MAX_TX_BUF_SIZE */
+ t_u32 tx_buf_size;
+ /** HT cap info configuration for MLAN_OID_11N_HTCAP_CFG */
+ mlan_ds_11n_htcap_cfg htcap_cfg;
+ /** Tx param for 11n for MLAN_OID_11N_AMSDU_AGGR_CTRL */
+ mlan_ds_11n_amsdu_aggr_ctrl amsdu_aggr_ctrl;
+ /** Supported MCS Set field */
+ t_u8 supported_mcs_set[NUM_MCS_FIELD];
+ /** Transmit Beamforming Capabilities field */
+ t_u32 tx_bf_cap;
+ /** Transmit Beamforming configuration */
+ mlan_ds_11n_tx_bf_cfg tx_bf;
+ /** HT stream configuration */
+ t_u32 stream_cfg;
+ /** DelBA for MLAN_OID_11N_CFG_DELBA */
+ mlan_ds_11n_delba del_ba;
+ /** Reject Addba Req for MLAN_OID_11N_CFG_REJECT_ADDBA_REQ */
+ mlan_ds_reject_addba_req reject_addba_req;
+ /** Control coex RX window size configuration */
+ t_u32 coex_rx_winsize;
+ /** aggrprirotity table for MLAN_OID_11N_CFG_IBSS_AMPDU_PARAM */
+ mlan_ds_ibss_ampdu_param ibss_ampdu;
+ /** Minimum BA Threshold for MLAN_OID_11N_CFG_MIN_BA_THRESHOLD
+ */
+ t_u8 min_ba_threshold;
+ } param;
+} mlan_ds_11n_cfg, *pmlan_ds_11n_cfg;
+
+#define NUM_MCS_SUPP 20
+#define VHT_MCS_SET_LEN 8
+
+/** Type definition of mlan_ds_11ac_vhtcap_cfg for MLAN_OID_11AC_VHTCAP_CFG */
+typedef struct _mlan_ds_11ac_vhtcap_cfg {
+ /** HT Capability information */
+ t_u32 vhtcap;
+ /** Band selection */
+ t_u32 misc_cfg;
+ /** Hardware HT cap information required */
+ t_u32 hw_cap_req;
+} mlan_ds_11ac_vhtcap_cfg, *pmlan_ds_11ac_vhtcap_cfg;
+
+/** Type definition of mlan_ds_11ac_tx_cfg for MLAN_OID_11AC_CFG_TX */
+typedef struct _mlan_ds_11ac_tx_cfg {
+ /** Band selection */
+ t_u8 band_cfg;
+ /** misc configuration */
+ t_u8 misc_cfg;
+ /** HTTxCap */
+ t_u16 vhttxcap;
+ /** HTTxInfo */
+ t_u16 vhttxinfo;
+} mlan_ds_11ac_tx_cfg, *pmlan_ds_11ac_tx_cfg;
+
+/** Tx */
+#define MLAN_RADIO_TX MBIT(0)
+/** Rx */
+#define MLAN_RADIO_RX MBIT(1)
+/** Tx & Rx */
+#define MLAN_RADIO_TXRX (MLAN_RADIO_TX | MLAN_RADIO_RX)
+
+/** Type definition of mlan_ds_11ac_tx_cfg for MLAN_OID_11AC_CFG */
+typedef struct _mlan_ds_11ac_vht_cfg {
+ /** Band selection (1: 2.4G, 2: 5 G, 3: both 2.4G and 5G) */
+ t_u32 band;
+ /** TxRx (1: Tx, 2: Rx, 3: both Tx and Rx) */
+ t_u32 txrx;
+ /** BW CFG (0: 11N CFG, 1: vhtcap) */
+ t_u32 bwcfg;
+ /** VHT capabilities. */
+ t_u32 vht_cap_info;
+ /** VHT Tx mcs */
+ t_u32 vht_tx_mcs;
+ /** VHT Rx mcs */
+ t_u32 vht_rx_mcs;
+ /** VHT rx max rate */
+ t_u16 vht_rx_max_rate;
+ /** VHT max tx rate */
+ t_u16 vht_tx_max_rate;
+ /** Skip usr 11ac mcs cfg */
+ t_bool skip_usr_11ac_mcs_cfg;
+} mlan_ds_11ac_vht_cfg, *pmlan_ds_11ac_vht_cfg;
+
+/** Type definition of mlan_ds_11ac_tx_cfg for MLAN_OID_11AC_CFG */
+typedef struct _mlan_ds_11ac_opermode_cfg {
+ /** channel width: 1-20MHz, 2-40MHz, 3-80MHz, 4-160MHz or 80+80MHz */
+ t_u8 bw;
+ /** Rx NSS */
+ t_u8 nss;
+} mlan_ds_11ac_opermode_cfg, *pmlan_ds_11ac_opermode_cfg;
+
+/** Type definition of mlan_ds_11ac_cfg for MLAN_IOCTL_11AC_CFG */
+typedef struct _mlan_ds_11ac_cfg {
+ /** Sub-command */
+ t_u32 sub_command;
+ /** 802.11n configuration parameter */
+ union {
+ /** VHT configuration for MLAN_OID_11AC_VHT_CFG */
+ mlan_ds_11ac_vht_cfg vht_cfg;
+ /** Supported MCS Set field */
+ t_u8 supported_mcs_set[NUM_MCS_SUPP];
+ /** Oper mode configuration for MLAN_OID_11AC_OPERMODE_CFG */
+ mlan_ds_11ac_opermode_cfg opermode_cfg;
+ } param;
+} mlan_ds_11ac_cfg, *pmlan_ds_11ac_cfg;
+
+/** Type definition of mlan_ds_11ax_he_capa for MLAN_OID_11AX_HE_CFG */
+typedef MLAN_PACK_START struct _mlan_ds_11ax_he_capa {
+ /** tlv id of he capability */
+ t_u16 id;
+ /** length of the payload */
+ t_u16 len;
+ /** extension id */
+ t_u8 ext_id;
+ /** he mac capability info */
+ t_u8 he_mac_cap[6];
+ /** he phy capability info */
+ t_u8 he_phy_cap[11];
+ /** he txrx mcs support for 80MHz */
+ t_u8 he_txrx_mcs_support[4];
+ /** val for txrx mcs 160Mhz or 80+80, and PPE thresholds */
+ t_u8 val[28];
+} MLAN_PACK_END mlan_ds_11ax_he_capa, *pmlan_ds_11ax_he_capa;
+
+/** Type definition of mlan_ds_11ax_he_cfg for MLAN_OID_11AX_HE_CFG */
+typedef struct _mlan_ds_11ax_he_cfg {
+ /** band, BIT0:2.4G, BIT1:5G*/
+ t_u8 band;
+ /** mlan_ds_11ax_he_capa */
+ mlan_ds_11ax_he_capa he_cap;
+} mlan_ds_11ax_he_cfg, *pmlan_ds_11ax_he_cfg;
+/** Type definition of mlan_ds_11as_cfg for MLAN_IOCTL_11AX_CFG */
+typedef struct _mlan_ds_11ax_cfg {
+ /** Sub-command */
+ t_u32 sub_command;
+ /** 802.11n configuration parameter */
+ union {
+ /** HE configuration for MLAN_OID_11AX_HE_CFG */
+ mlan_ds_11ax_he_cfg he_cfg;
+ } param;
+} mlan_ds_11ax_cfg, *pmlan_ds_11ax_cfg;
+
+#define MLAN_11AXCMD_CFG_ID_SR_OBSS_PD_OFFSET 1
+#define MLAN_11AXCMD_CFG_ID_SR_ENABLE 2
+#define MLAN_11AXCMD_CFG_ID_BEAM_CHANGE 3
+#define MLAN_11AXCMD_CFG_ID_HTC_ENABLE 4
+#define MLAN_11AXCMD_CFG_ID_TXOP_RTS 5
+#define MLAN_11AXCMD_CFG_ID_TX_OMI 6
+#define MLAN_11AXCMD_CFG_ID_OBSSNBRU_TOLTIME 7
+
+#define MLAN_11AXCMD_SR_SUBID 0x102
+#define MLAN_11AXCMD_BEAM_SUBID 0x103
+#define MLAN_11AXCMD_HTC_SUBID 0x104
+#define MLAN_11AXCMD_TXOMI_SUBID 0x105
+#define MLAN_11AXCMD_OBSS_TOLTIME_SUBID 0x106
+#define MLAN_11AXCMD_TXOPRTS_SUBID 0x108
+
+#define MLAN_11AX_TWT_SETUP_SUBID 0x114
+#define MLAN_11AX_TWT_TEARDOWN_SUBID 0x115
+
+#define MRVL_DOT11AX_ENABLE_SR_TLV_ID (PROPRIETARY_TLV_BASE_ID + 322)
+#define MRVL_DOT11AX_OBSS_PD_OFFSET_TLV_ID (PROPRIETARY_TLV_BASE_ID + 323)
+
+/** Type definition of mlan_11axcmdcfg_obss_pd_offset for MLAN_OID_11AX_CMD_CFG
+ */
+typedef struct MLAN_PACK_START _mlan_11axcmdcfg_obss_pd_offset {
+ /** <NON_SRG_OffSET, SRG_OFFSET> */
+ t_u8 offset[2];
+} MLAN_PACK_END mlan_11axcmdcfg_obss_pd_offset;
+
+/** Type definition of mlan_11axcmdcfg_sr_control for MLAN_OID_11AX_CMD_CFG */
+typedef struct MLAN_PACK_START _mlan_11axcmdcfg_sr_control {
+ /** 1 enable, 0 disable */
+ t_u8 control;
+} MLAN_PACK_END mlan_11axcmdcfg_sr_control;
+
+/** Type definition of mlan_ds_11ax_sr_cmd for MLAN_OID_11AX_CMD_CFG */
+typedef struct MLAN_PACK_START _mlan_ds_11ax_sr_cmd {
+ /** type*/
+ t_u16 type;
+ /** length of TLV */
+ t_u16 len;
+ /** value */
+ union {
+ mlan_11axcmdcfg_obss_pd_offset obss_pd_offset;
+ mlan_11axcmdcfg_sr_control sr_control;
+ } param;
+} MLAN_PACK_END mlan_ds_11ax_sr_cmd, *pmlan_ds_11ax_sr_cmd;
+
+/** Type definition of mlan_ds_11ax_beam_cmd for MLAN_OID_11AX_CMD_CFG */
+typedef struct _mlan_ds_11ax_beam_cmd {
+ /** command value: 1 is disable, 0 is enable*/
+ t_u8 value;
+} mlan_ds_11ax_beam_cmd, *pmlan_ds_11ax_beam_cmd;
+
+/** Type definition of mlan_ds_11ax_htc_cmd for MLAN_OID_11AX_CMD_CFG */
+typedef struct _mlan_ds_11ax_htc_cmd {
+ /** command value: 1 is enable, 0 is disable*/
+ t_u8 value;
+} mlan_ds_11ax_htc_cmd, *pmlan_ds_11ax_htc_cmd;
+
+/** Type definition of mlan_ds_11ax_htc_cmd for MLAN_OID_11AX_CMD_CFG */
+typedef struct _mlan_ds_11ax_txop_cmd {
+ /** Two byte rts threshold value of which only 10 bits, bit 0 to bit 9
+ * are valid */
+ t_u16 rts_thres;
+} mlan_ds_11ax_txop_cmd, *pmlan_ds_11ax_txop_cmd;
+
+/** Type definition of mlan_ds_11ax_htc_cmd for MLAN_OID_11AX_CMD_CFG */
+typedef struct _mlan_ds_11ax_txomi_cmd {
+ /* 11ax spec 9.2.4.6a.2 OM Control 12 bits. Bit 0 to bit 11 */
+ t_u16 omi;
+} mlan_ds_11ax_txomi_cmd, *pmlan_ds_11ax_txomi_cmd;
+
+/** Type definition of mlan_ds_11ax_toltime_cmd for MLAN_OID_11AX_CMD_CFG */
+typedef struct _mlan_ds_11ax_toltime_cmd {
+ /* OBSS Narrow Bandwidth RU Tolerance Time */
+ t_u32 tol_time;
+} mlan_ds_11ax_toltime_cmd, *pmlan_ds_11ax_toltime_cmd;
+
+/** Type definition of mlan_ds_11ax_cmd_cfg for MLAN_OID_11AX_CMD_CFG */
+typedef struct _mlan_ds_11ax_cmd_cfg {
+ /** Sub-command */
+ t_u32 sub_command;
+ /** Sub-id */
+ t_u32 sub_id;
+ /** 802.11n configuration parameter */
+ union {
+ /** SR configuration for MLAN_11AXCMD_SR_SUBID */
+ mlan_ds_11ax_sr_cmd sr_cfg;
+ /** Beam configuration for MLAN_11AXCMD_BEAM_SUBID */
+ mlan_ds_11ax_beam_cmd beam_cfg;
+ /** HTC configuration for MLAN_11AXCMD_HTC_SUBID */
+ mlan_ds_11ax_htc_cmd htc_cfg;
+ /** txop RTS configuration for MLAN_11AXCMD_TXOPRTS_SUBID */
+ mlan_ds_11ax_txop_cmd txop_cfg;
+ /** tx omi configuration for MLAN_11AXCMD_TXOMI_SUBID */
+ mlan_ds_11ax_txomi_cmd txomi_cfg;
+ /** OBSS tolerance time configuration for
+ * MLAN_11AXCMD_TOLTIME_SUBID */
+ mlan_ds_11ax_toltime_cmd toltime_cfg;
+ } param;
+} mlan_ds_11ax_cmd_cfg, *pmlan_ds_11ax_cmd_cfg;
+
+/** Type definition of mlan_ds_twt_setup for MLAN_OID_11AX_TWT_CFG */
+typedef struct MLAN_PACK_START _mlan_ds_twt_setup {
+ /** Implicit, 0: TWT session is explicit, 1: Session is implicit */
+ t_u8 implicit;
+ /** Announced, 0: Unannounced, 1: Announced TWT */
+ t_u8 announced;
+ /** Trigger Enabled, 0: Non-Trigger enabled, 1: Trigger enabled TWT */
+ t_u8 trigger_enabled;
+ /** TWT Information Disabled, 0: TWT info enabled, 1: TWT info disabled
+ */
+ t_u8 twt_info_disabled;
+ /** Negotiation Type, 0: Future Individual TWT SP start time, 1: Next
+ * Wake TBTT time */
+ t_u8 negotiation_type;
+ /** TWT Wakeup Duration, time after which the TWT requesting STA can
+ * transition to doze state */
+ t_u8 twt_wakeup_duration;
+ /** Flow Identifier. Range: [0-7]*/
+ t_u8 flow_identifier;
+ /** Hard Constraint, 0: FW can tweak the TWT setup parameters if it is
+ *rejected by AP.
+ ** 1: Firmware should not tweak any parameters. */
+ t_u8 hard_constraint;
+ /** TWT Exponent, Range: [0-63] */
+ t_u8 twt_exponent;
+ /** TWT Mantissa Range: [0-sizeof(UINT16)] */
+ t_u16 twt_mantissa;
+ /** TWT Request Type, 0: REQUEST_TWT, 1: SUGGEST_TWT*/
+ t_u8 twt_request;
+} MLAN_PACK_END mlan_ds_twt_setup, *pmlan_ds_twt_setup;
+
+/** Type definition of mlan_ds_twt_teardown for MLAN_OID_11AX_TWT_CFG */
+typedef struct MLAN_PACK_START _mlan_ds_twt_teardown {
+ /** TWT Flow Identifier. Range: [0-7] */
+ t_u8 flow_identifier;
+ /** Negotiation Type. 0: Future Individual TWT SP start time, 1: Next
+ * Wake TBTT time */
+ t_u8 negotiation_type;
+ /** Tear down all TWT. 1: To teardown all TWT, 0 otherwise */
+ t_u8 teardown_all_twt;
+} MLAN_PACK_END mlan_ds_twt_teardown, *pmlan_ds_twt_teardown;
+
+/** Type definition of mlan_ds_twtcfg for MLAN_OID_11AX_TWT_CFG */
+typedef struct MLAN_PACK_START _mlan_ds_twtcfg {
+ /** Sub-command */
+ t_u32 sub_command;
+ /** Sub-id */
+ t_u32 sub_id;
+ /** TWT Setup/Teardown configuration parameter */
+ union {
+ /** TWT Setup config for Sub ID: MLAN_11AX_TWT_SETUP_SUBID */
+ mlan_ds_twt_setup twt_setup;
+ /** TWT Teardown config for Sub ID: MLAN_11AX_TWT_TEARDOWN_SUBID
+ */
+ mlan_ds_twt_teardown twt_teardown;
+ } param;
+} MLAN_PACK_END mlan_ds_twtcfg, *pmlan_ds_twtcfg;
+
+/** Country code length */
+#define COUNTRY_CODE_LEN 3
+
+/*-----------------------------------------------------------------*/
+/** 802.11d Configuration Group */
+/*-----------------------------------------------------------------*/
+/** Maximum subbands for 11d */
+#define MRVDRV_MAX_SUBBAND_802_11D 83
+
+/** Data structure for subband set */
+typedef struct _mlan_ds_subband_set_t {
+ /** First channel */
+ t_u8 first_chan;
+ /** Number of channels */
+ t_u8 no_of_chan;
+ /** Maximum Tx power in dBm */
+ t_u8 max_tx_pwr;
+} mlan_ds_subband_set_t;
+
+/** Domain regulatory information */
+typedef struct _mlan_ds_11d_domain_info {
+ /** Country Code */
+ t_u8 country_code[COUNTRY_CODE_LEN];
+ /** Band that channels in sub_band belong to */
+ t_u8 band;
+ /** No. of subband in below */
+ t_u8 no_of_sub_band;
+ /** Subband data to send/last sent */
+ mlan_ds_subband_set_t sub_band[MRVDRV_MAX_SUBBAND_802_11D];
+} mlan_ds_11d_domain_info;
+
+/** Type definition of mlan_ds_11d_cfg for MLAN_IOCTL_11D_CFG */
+typedef struct _mlan_ds_11d_cfg {
+ /** Sub-command */
+ t_u32 sub_command;
+ /** 802.11d configuration parameter */
+ union {
+#ifdef STA_SUPPORT
+ /** Enable for MLAN_OID_11D_CFG_ENABLE */
+ t_u32 enable_11d;
+#endif /* STA_SUPPORT */
+ /** Domain info for MLAN_OID_11D_DOMAIN_INFO_EXT */
+ mlan_ds_11d_domain_info domain_info;
+#ifdef UAP_SUPPORT
+ /** tlv data for MLAN_OID_11D_DOMAIN_INFO */
+ t_u8 domain_tlv[MAX_IE_SIZE];
+#endif /* UAP_SUPPORT */
+ } param;
+} mlan_ds_11d_cfg, *pmlan_ds_11d_cfg;
+
+/*-----------------------------------------------------------------*/
+/** Register Memory Access Group */
+/*-----------------------------------------------------------------*/
+/** Enumeration for CSU target device type */
+enum _mlan_csu_target_type {
+ MLAN_CSU_TARGET_CAU = 1,
+ MLAN_CSU_TARGET_PSU,
+};
+
+/** Enumeration for register type */
+enum _mlan_reg_type {
+ MLAN_REG_MAC = 1,
+ MLAN_REG_BBP,
+ MLAN_REG_RF,
+ MLAN_REG_CAU = 5,
+ MLAN_REG_PSU = 6,
+ MLAN_REG_BCA = 7,
+#if defined(PCIE9098) || defined(SD9098) || defined(USB9098) || \
+ defined(PCIE9097) || defined(USB9097) || defined(SD9097)
+ MLAN_REG_MAC2 = 0x81,
+ MLAN_REG_BBP2 = 0x82,
+ MLAN_REG_RF2 = 0x83,
+ MLAN_REG_BCA2 = 0x87
+#endif
+};
+
+/** Type definition of mlan_ds_reg_rw for MLAN_OID_REG_RW */
+typedef struct _mlan_ds_reg_rw {
+ /** Register type */
+ t_u32 type;
+ /** Offset */
+ t_u32 offset;
+ /** Value */
+ t_u32 value;
+} mlan_ds_reg_rw;
+
+/** Maximum EEPROM data */
+#define MAX_EEPROM_DATA 256
+
+/** Type definition of mlan_ds_read_eeprom for MLAN_OID_EEPROM_RD */
+typedef struct _mlan_ds_read_eeprom {
+ /** Multiples of 4 */
+ t_u16 offset;
+ /** Number of bytes */
+ t_u16 byte_count;
+ /** Value */
+ t_u8 value[MAX_EEPROM_DATA];
+} mlan_ds_read_eeprom;
+
+/** Type definition of mlan_ds_mem_rw for MLAN_OID_MEM_RW */
+typedef struct _mlan_ds_mem_rw {
+ /** Address */
+ t_u32 addr;
+ /** Value */
+ t_u32 value;
+} mlan_ds_mem_rw;
+
+/** Type definition of mlan_ds_reg_mem for MLAN_IOCTL_REG_MEM */
+typedef struct _mlan_ds_reg_mem {
+ /** Sub-command */
+ t_u32 sub_command;
+ /** Register memory access parameter */
+ union {
+ /** Register access for MLAN_OID_REG_RW */
+ mlan_ds_reg_rw reg_rw;
+ /** EEPROM access for MLAN_OID_EEPROM_RD */
+ mlan_ds_read_eeprom rd_eeprom;
+ /** Memory access for MLAN_OID_MEM_RW */
+ mlan_ds_mem_rw mem_rw;
+ } param;
+} mlan_ds_reg_mem, *pmlan_ds_reg_mem;
+
+/*-----------------------------------------------------------------*/
+/** Multi-Radio Configuration Group */
+/*-----------------------------------------------------------------*/
+/*-----------------------------------------------------------------*/
+/** 802.11h Configuration Group */
+/*-----------------------------------------------------------------*/
+/** Type definition of mlan_ds_11h_dfs_testing for MLAN_OID_11H_DFS_TESTING */
+typedef struct _mlan_ds_11h_dfs_testing {
+ /** User-configured CAC period in milliseconds, 0 to use default */
+ t_u32 usr_cac_period_msec;
+ /** User-configured NOP period in seconds, 0 to use default */
+ t_u16 usr_nop_period_sec;
+ /** User-configured skip channel change, 0 to disable */
+ t_u8 usr_no_chan_change;
+ /** User-configured fixed channel to change to, 0 to use random channel
+ */
+ t_u8 usr_fixed_new_chan;
+ /** User-configured cac restart */
+ t_u8 usr_cac_restart;
+} mlan_ds_11h_dfs_testing, *pmlan_ds_11h_dfs_testing;
+
+/** Type definition of mlan_ds_11h_dfs_testing for MLAN_OID_11H_CHAN_NOP_INFO */
+typedef struct _mlan_ds_11h_chan_nop_info {
+ /** current channel */
+ t_u8 curr_chan;
+ /** channel_width */
+ t_u8 chan_width;
+ /** flag for chan under nop */
+ t_bool chan_under_nop;
+ /** chan_ban_info for new channel */
+ chan_band_info new_chan;
+} mlan_ds_11h_chan_nop_info, *pmlan_ds_11h_chan_nop_info;
+
+typedef struct _mlan_ds_11h_chan_rep_req {
+ t_u16 startFreq;
+ Band_Config_t bandcfg;
+ t_u8 chanNum;
+ t_u32 millisec_dwell_time; /**< Channel dwell time in milliseconds */
+ t_u8 host_based;
+} mlan_ds_11h_chan_rep_req;
+
+typedef struct _mlan_ds_11h_dfs_w53_cfg {
+ /** dfs w53 cfg */
+ t_u8 dfs53cfg;
+} mlan_ds_11h_dfs_w53_cfg;
+
+/** Type definition of mlan_ds_11h_cfg for MLAN_IOCTL_11H_CFG */
+typedef struct _mlan_ds_11h_cfg {
+ /** Sub-command */
+ t_u32 sub_command;
+ union {
+ /** Local power constraint for
+ * MLAN_OID_11H_LOCAL_POWER_CONSTRAINT */
+ t_s8 usr_local_power_constraint;
+ /** User-configuation for MLAN_OID_11H_DFS_TESTING */
+ mlan_ds_11h_dfs_testing dfs_testing;
+ /** channel NOP information for MLAN_OID_11H_CHAN_NOP_INFO */
+ mlan_ds_11h_chan_nop_info ch_nop_info;
+ /** channel report req for MLAN_OID_11H_CHAN_REPORT_REQUEST */
+ mlan_ds_11h_chan_rep_req chan_rpt_req;
+ /** channel switch count for MLAN_OID_11H_CHAN_SWITCH_COUNT*/
+ t_s8 cs_count;
+ mlan_ds_11h_dfs_w53_cfg dfs_w53_cfg;
+ } param;
+} mlan_ds_11h_cfg, *pmlan_ds_11h_cfg;
+
+/*-----------------------------------------------------------------*/
+/** Miscellaneous Configuration Group */
+/*-----------------------------------------------------------------*/
+
+/** CMD buffer size */
+#define MLAN_SIZE_OF_CMD_BUFFER (3 * 1024)
+
+/** LDO Internal */
+#define LDO_INTERNAL 0
+/** LDO External */
+#define LDO_EXTERNAL 1
+
+/** Enumeration for IE type */
+enum _mlan_ie_type {
+ MLAN_IE_TYPE_GEN_IE = 0,
+};
+
+/** Type definition of mlan_ds_misc_gen_ie for MLAN_OID_MISC_GEN_IE */
+typedef struct _mlan_ds_misc_gen_ie {
+ /** IE type */
+ t_u32 type;
+ /** IE length */
+ t_u32 len;
+ /** IE buffer */
+ t_u8 ie_data[MAX_IE_SIZE];
+} mlan_ds_misc_gen_ie;
+
+#ifdef SDIO
+/** Type definition of mlan_ds_misc_sdio_mpa_ctrl
+ * for MLAN_OID_MISC_SDIO_MPA_CTRL
+ */
+typedef struct _mlan_ds_misc_sdio_mpa_ctrl {
+ /** SDIO MP-A TX enable/disable */
+ t_u16 tx_enable;
+ /** SDIO MP-A RX enable/disable */
+ t_u16 rx_enable;
+ /** SDIO MP-A TX buf size */
+ t_u16 tx_buf_size;
+ /** SDIO MP-A RX buf size */
+ t_u16 rx_buf_size;
+ /** SDIO MP-A TX Max Ports */
+ t_u16 tx_max_ports;
+ /** SDIO MP-A RX Max Ports */
+ t_u16 rx_max_ports;
+} mlan_ds_misc_sdio_mpa_ctrl;
+#endif
+
+/** Type definition of mlan_ds_misc_cmd for MLAN_OID_MISC_HOST_CMD */
+typedef struct _mlan_ds_misc_cmd {
+ /** Command length */
+ t_u32 len;
+ /** Command buffer */
+ t_u8 cmd[MRVDRV_SIZE_OF_CMD_BUFFER];
+} mlan_ds_misc_cmd;
+
+/** Maximum number of system clocks */
+#define MLAN_MAX_CLK_NUM 16
+
+/** Clock type : Configurable */
+#define MLAN_CLK_CONFIGURABLE 0
+/** Clock type : Supported */
+#define MLAN_CLK_SUPPORTED 1
+
+/** Type definition of mlan_ds_misc_sys_clock for MLAN_OID_MISC_SYS_CLOCK */
+typedef struct _mlan_ds_misc_sys_clock {
+ /** Current system clock */
+ t_u16 cur_sys_clk;
+ /** Clock type */
+ t_u16 sys_clk_type;
+ /** Number of clocks */
+ t_u16 sys_clk_num;
+ /** System clocks */
+ t_u16 sys_clk[MLAN_MAX_CLK_NUM];
+} mlan_ds_misc_sys_clock;
+
+/** Enumeration for function init/shutdown */
+enum _mlan_func_cmd {
+ MLAN_FUNC_INIT = 1,
+ MLAN_FUNC_SHUTDOWN,
+};
+
+/** Type definition of mlan_ds_misc_tx_datapause
+ * for MLAN_OID_MISC_TX_DATAPAUSE
+ */
+typedef struct _mlan_ds_misc_tx_datapause {
+ /** Tx data pause flag */
+ t_u16 tx_pause;
+ /** Max number of Tx buffers for all PS clients */
+ t_u16 tx_buf_cnt;
+} mlan_ds_misc_tx_datapause;
+
+/** Type definition of mlan_ds_misc_rx_abort_cfg
+ * for MLAN_OID_MISC_RX_ABORT_CFG
+ */
+typedef struct _mlan_ds_misc_rx_abort_cfg {
+ /** enable/disable rx abort */
+ t_u8 enable;
+ /** Rx weak RSSI pkt threshold */
+ t_s8 rssi_threshold;
+} mlan_ds_misc_rx_abort_cfg;
+
+/** Type definition of mlan_ds_misc_rx_abort_cfg_ext
+ * for MLAN_OID_MISC_RX_ABORT_CFG_EXT
+ */
+typedef struct _mlan_ds_misc_rx_abort_cfg_ext {
+ /** enable/disable dynamic rx abort */
+ t_u8 enable;
+ /** rssi margin */
+ t_s8 rssi_margin;
+ /** specify ceil rssi threshold */
+ t_s8 ceil_rssi_threshold;
+} mlan_ds_misc_rx_abort_cfg_ext;
+
+/** Type definition of mlan_ds_misc_rx_abort_cfg_ext
+ * for MLAN_OID_MISC_TX_AMDPU_PROT_MODE
+ */
+typedef struct _mlan_ds_misc_tx_ampdu_prot_mode {
+ /** set prot mode */
+ t_u16 mode;
+} mlan_ds_misc_tx_ampdu_prot_mode;
+
+/** Type definition of mlan_ds_misc_dot11mc_unassoc_ftm_cfg
+ * for MLAN_OID_MISC_DOT11MC_UNASSOC_FTM_CFG
+ */
+typedef struct _mlan_ds_misc_dot11mc_unassoc_ftm_cfg {
+ /** set the state */
+ t_u16 state;
+} mlan_ds_misc_dot11mc_unassoc_ftm_cfg;
+
+#define RATEADAPT_ALGO_LEGACY 0
+#define RATEADAPT_ALGO_SR 1
+
+/** Type definition of mlan_ds_misc_rate_adapt_cfg
+ * for MLAN_OID_MISC_RATE_ADAPT_CFG
+ */
+typedef struct _mlan_ds_misc_rate_adapt_cfg {
+ /** SR Rateadapt */
+ t_u8 sr_rateadapt;
+ /** set low threshold */
+ t_u8 ra_low_thresh;
+ /** set high threshold */
+ t_u8 ra_high_thresh;
+ /** set interval */
+ t_u16 ra_interval;
+} mlan_ds_misc_rate_adapt_cfg;
+
+/** Type definition of mlan_ds_misc_cck_desense_cfg
+ * for MLAN_OID_MISC_CCK_DESENSE_CFG
+ */
+typedef struct _mlan_ds_misc_cck_desense_cfg {
+ /** cck desense mode: 0:disable 1:normal 2:dynamic */
+ t_u16 mode;
+ /** specify rssi margin */
+ t_s8 margin;
+ /** specify ceil rssi threshold */
+ t_s8 ceil_thresh;
+ /** cck desense "on" interval count */
+ t_u8 num_on_intervals;
+ /** cck desense "off" interval count */
+ t_u8 num_off_intervals;
+} mlan_ds_misc_cck_desense_cfg;
+
+/** IP address length */
+#define IPADDR_LEN (16)
+/** Max number of ip */
+#define MAX_IPADDR (4)
+/** IP address type - NONE*/
+#define IPADDR_TYPE_NONE (0)
+/** IP address type - IPv4*/
+#define IPADDR_TYPE_IPV4 (1)
+/** IP operation remove */
+#define MLAN_IPADDR_OP_IP_REMOVE (0)
+/** IP operation ARP response */
+#define MLAN_IPADDR_OP_AUTO_ARP_RESP MBIT(1)
+
+/** Type definition of mlan_ds_misc_ipaddr_cfg for MLAN_OID_MISC_IP_ADDR */
+typedef struct _mlan_ds_misc_ipaddr_cfg {
+ /** Operation code */
+ t_u32 op_code;
+ /** IP address type */
+ t_u32 ip_addr_type;
+ /** Number of IP */
+ t_u32 ip_addr_num;
+ /** IP address */
+ t_u8 ip_addr[MAX_IPADDR][IPADDR_LEN];
+} mlan_ds_misc_ipaddr_cfg;
+
+/* MEF configuration disable */
+#define MEF_CFG_DISABLE 0
+/* MEF configuration Rx filter enable */
+#define MEF_CFG_RX_FILTER_ENABLE 1
+/* MEF configuration auto ARP response */
+#define MEF_CFG_AUTO_ARP_RESP 2
+/* MEF configuration host command */
+#define MEF_CFG_HOSTCMD 0xFFFF
+
+/** Type definition of mlan_ds_misc_mef_cfg for MLAN_OID_MISC_MEF_CFG */
+typedef struct _mlan_ds_misc_mef_cfg {
+ /** Sub-ID for operation */
+ t_u32 sub_id;
+ /** Parameter according to sub-ID */
+ union {
+ /** MEF command buffer for MEF_CFG_HOSTCMD */
+ mlan_ds_misc_cmd cmd_buf;
+ } param;
+} mlan_ds_misc_mef_cfg;
+
+/** Type definition of mlan_ds_misc_cfp_code for MLAN_OID_MISC_CFP_CODE */
+typedef struct _mlan_ds_misc_cfp_code {
+ /** CFP table code for 2.4GHz */
+ t_u32 cfp_code_bg;
+ /** CFP table code for 5GHz */
+ t_u32 cfp_code_a;
+} mlan_ds_misc_cfp_code;
+
+/** Type definition of mlan_ds_misc_arb_cfg
+ * for MLAN_OID_MISC_ARB_CFG
+ */
+typedef struct _mlan_ds_misc_arb_cfg {
+ /** arb mode 0-4 */
+ t_u32 arb_mode;
+} mlan_ds_misc_arb_cfg;
+
+/** Type definition of mlan_ds_misc_tp_state
+ * for MLAN_OID_MISC_TP_STATE
+ */
+typedef struct _mlan_ds_misc_tp_state {
+ /** TP account mode 0-disable 1-enable */
+ t_u32 on;
+ /** Packet drop point */
+ t_u32 drop_point;
+} mlan_ds_misc_tp_state;
+
+/** Type definition of mlan_ds_misc_country_code
+ * for MLAN_OID_MISC_COUNTRY_CODE
+ */
+typedef struct _mlan_ds_misc_country_code {
+ /** Country Code */
+ t_u8 country_code[COUNTRY_CODE_LEN];
+} mlan_ds_misc_country_code;
+
+/** action for set */
+#define SUBSCRIBE_EVT_ACT_BITWISE_SET 0x0002
+/** action for clear */
+#define SUBSCRIBE_EVT_ACT_BITWISE_CLR 0x0003
+/** BITMAP for subscribe event rssi low */
+#define SUBSCRIBE_EVT_RSSI_LOW MBIT(0)
+/** BITMAP for subscribe event snr low */
+#define SUBSCRIBE_EVT_SNR_LOW MBIT(1)
+/** BITMAP for subscribe event max fail */
+#define SUBSCRIBE_EVT_MAX_FAIL MBIT(2)
+/** BITMAP for subscribe event beacon missed */
+#define SUBSCRIBE_EVT_BEACON_MISSED MBIT(3)
+/** BITMAP for subscribe event rssi high */
+#define SUBSCRIBE_EVT_RSSI_HIGH MBIT(4)
+/** BITMAP for subscribe event snr high */
+#define SUBSCRIBE_EVT_SNR_HIGH MBIT(5)
+/** BITMAP for subscribe event data rssi low */
+#define SUBSCRIBE_EVT_DATA_RSSI_LOW MBIT(6)
+/** BITMAP for subscribe event data snr low */
+#define SUBSCRIBE_EVT_DATA_SNR_LOW MBIT(7)
+/** BITMAP for subscribe event data rssi high */
+#define SUBSCRIBE_EVT_DATA_RSSI_HIGH MBIT(8)
+/** BITMAP for subscribe event data snr high */
+#define SUBSCRIBE_EVT_DATA_SNR_HIGH MBIT(9)
+/** BITMAP for subscribe event link quality */
+#define SUBSCRIBE_EVT_LINK_QUALITY MBIT(10)
+/** BITMAP for subscribe event pre_beacon_lost */
+#define SUBSCRIBE_EVT_PRE_BEACON_LOST MBIT(11)
+/** default PRE_BEACON_MISS_COUNT */
+#define DEFAULT_PRE_BEACON_MISS 30
+
+/** Type definition of mlan_ds_subscribe_evt for MLAN_OID_MISC_CFP_CODE */
+typedef struct _mlan_ds_subscribe_evt {
+ /** evt action */
+ t_u16 evt_action;
+ /** bitmap for subscribe event */
+ t_u16 evt_bitmap;
+ /** Absolute value of RSSI threshold value (dBm) */
+ t_u8 low_rssi;
+ /** 0--report once, 1--report everytime happen,
+ * N -- report only happend > N consecutive times
+ */
+ t_u8 low_rssi_freq;
+ /** SNR threshold value (dB) */
+ t_u8 low_snr;
+ /** 0--report once, 1--report everytime happen,
+ * N -- report only happend > N consecutive times
+ */
+ t_u8 low_snr_freq;
+ /** Failure count threshold */
+ t_u8 failure_count;
+ /** 0--report once, 1--report everytime happen,
+ * N -- report only happend > N consecutive times
+ */
+ t_u8 failure_count_freq;
+ /** num of missed beacons */
+ t_u8 beacon_miss;
+ /** 0--report once, 1--report everytime happen,
+ * N -- report only happend > N consecutive times
+ */
+ t_u8 beacon_miss_freq;
+ /** Absolute value of RSSI threshold value (dBm) */
+ t_u8 high_rssi;
+ /** 0--report once, 1--report everytime happen,
+ * N -- report only happend > N consecutive times
+ */
+ t_u8 high_rssi_freq;
+ /** SNR threshold value (dB) */
+ t_u8 high_snr;
+ /** 0--report once, 1--report everytime happen,
+ * N -- report only happend > N consecutive times
+ */
+ t_u8 high_snr_freq;
+ /** Absolute value of data RSSI threshold value (dBm) */
+ t_u8 data_low_rssi;
+ /** 0--report once, 1--report everytime happen,
+ * N -- report only happend > N consecutive times
+ */
+ t_u8 data_low_rssi_freq;
+ /** Absolute value of data SNR threshold value (dBm) */
+ t_u8 data_low_snr;
+ /** 0--report once, 1--report everytime happen,
+ * N -- report only happend > N consecutive times
+ */
+ t_u8 data_low_snr_freq;
+ /** Absolute value of data RSSI threshold value (dBm) */
+ t_u8 data_high_rssi;
+ /** 0--report once, 1--report everytime happen,
+ * N -- report only happend > N consecutive times
+ */
+ t_u8 data_high_rssi_freq;
+ /** Absolute value of data SNR threshold value (dBm) */
+ t_u8 data_high_snr;
+ /** 0--report once, 1--report everytime happen,
+ * N -- report only happend > N consecutive times
+ */
+ t_u8 data_high_snr_freq;
+ /* Link SNR threshold (dB)*/
+ t_u16 link_snr;
+ /* Link SNR frequency */
+ t_u16 link_snr_freq;
+ /* Second minimum rate value as per the rate table below */
+ t_u16 link_rate;
+ /* Second minimum rate frequency */
+ t_u16 link_rate_freq;
+ /* Tx latency value (us) */
+ t_u16 link_tx_latency;
+ /* Tx latency frequency */
+ t_u16 link_tx_lantency_freq;
+ /* Number of pre missed beacons */
+ t_u8 pre_beacon_miss;
+} mlan_ds_subscribe_evt;
+
+/** Max OTP user data length */
+#define MAX_OTP_USER_DATA_LEN 252
+
+/** Type definition of mlan_ds_misc_otp_user_data
+ * for MLAN_OID_MISC_OTP_USER_DATA
+ */
+typedef struct _mlan_ds_misc_otp_user_data {
+ /** Reserved */
+ t_u16 reserved;
+ /** OTP user data length */
+ t_u16 user_data_length;
+ /** User data buffer */
+ t_u8 user_data[MAX_OTP_USER_DATA_LEN];
+} mlan_ds_misc_otp_user_data;
+
+typedef struct _aggr_ctrl {
+ /** Enable */
+ t_u16 enable;
+ /** Aggregation alignment */
+ t_u16 aggr_align;
+ /** Aggregation max size */
+ t_u16 aggr_max_size;
+ /** Aggregation max packet number */
+ t_u16 aggr_max_num;
+ /** Aggrgation timeout, in microseconds */
+ t_u16 aggr_tmo;
+} aggr_ctrl;
+
+/** Type definition of mlan_ds_misc_aggr_ctrl
+ * for MLAN_OID_MISC_AGGR_CTRL
+ */
+typedef struct _mlan_ds_misc_aggr_ctrl {
+ /** Tx aggregation control */
+ aggr_ctrl tx;
+} mlan_ds_misc_aggr_ctrl;
+
+#ifdef USB
+typedef struct _usb_aggr_ctrl {
+ /** Enable */
+ t_u16 enable;
+ /** Aggregation mode */
+ t_u16 aggr_mode;
+ /** Aggregation alignment */
+ t_u16 aggr_align;
+ /** Aggregation max packet/size */
+ t_u16 aggr_max;
+ /** Aggrgation timeout, in microseconds */
+ t_u16 aggr_tmo;
+} usb_aggr_ctrl;
+
+/** Type definition of mlan_ds_misc_usb_aggr_ctrl
+ * for MLAN_OID_MISC_USB_AGGR_CTRL
+ */
+typedef struct _mlan_ds_misc_usb_aggr_ctrl {
+ /** Tx aggregation control */
+ usb_aggr_ctrl tx_aggr_ctrl;
+ /** Rx deaggregation control */
+ usb_aggr_ctrl rx_deaggr_ctrl;
+} mlan_ds_misc_usb_aggr_ctrl;
+#endif
+
+#ifdef WIFI_DIRECT_SUPPORT
+/** flag for NOA */
+#define WIFI_DIRECT_NOA 1
+/** flag for OPP_PS */
+#define WIFI_DIRECT_OPP_PS 2
+/** Type definition of mlan_ds_wifi_direct_config
+ * for MLAN_OID_MISC_WIFI_DIRECT_CONFIG
+ */
+typedef struct _mlan_ds_wifi_direct_config {
+ /** flags for NOA/OPP_PS */
+ t_u8 flags;
+ /** NoA enable/disable */
+ t_u8 noa_enable;
+ /** index */
+ t_u16 index;
+ /** NoA count */
+ t_u8 noa_count;
+ /** NoA duration */
+ t_u32 noa_duration;
+ /** NoA interval */
+ t_u32 noa_interval;
+ /** opp ps enable/disable */
+ t_u8 opp_ps_enable;
+ /** CT window value */
+ t_u8 ct_window;
+} mlan_ds_wifi_direct_config;
+#endif
+
+#if defined(STA_SUPPORT)
+typedef struct _mlan_ds_misc_pmfcfg {
+ /** Management Frame Protection Capable */
+ t_u8 mfpc;
+ /** Management Frame Protection Required */
+ t_u8 mfpr;
+} mlan_ds_misc_pmfcfg;
+#endif
+
+#define MAX_SSID_NUM 16
+#define MAX_AP_LIST 8
+
+#ifdef RX_PACKET_COALESCE
+typedef struct _mlan_ds_misc_rx_packet_coalesce {
+ /** packet threshold */
+ t_u32 packet_threshold;
+ /** timeout value */
+ t_u16 delay;
+} mlan_ds_misc_rx_packet_coalesce;
+#endif
+
+typedef struct _mlan_ds_misc_dfs_repeater {
+ /** Set or Get */
+ t_u16 action;
+ /** 1 on or 0 off */
+ t_u16 mode;
+} mlan_ds_misc_dfs_repeater;
+
+#define WOWLAN_MAX_PATTERN_LEN 20
+#define WOWLAN_MAX_OFFSET_LEN 50
+#define MAX_NUM_FILTERS 10
+#define MEF_MODE_HOST_SLEEP (1 << 0)
+#define MEF_MODE_NON_HOST_SLEEP (1 << 1)
+#define MEF_ACTION_WAKE (1 << 0)
+#define MEF_ACTION_ALLOW (1 << 1)
+#define MEF_ACTION_ALLOW_AND_WAKEUP_HOST 3
+#define MEF_AUTO_ARP 0x10
+#define MEF_AUTO_PING 0x20
+#define MEF_NS_RESP 0x40
+#define MEF_MAGIC_PKT 0x80
+#define CRITERIA_BROADCAST BIT(0)
+#define CRITERIA_UNICAST BIT(1)
+#define CRITERIA_MULTICAST BIT(3)
+
+#define MAX_NUM_ENTRIES 8
+#define MAX_NUM_BYTE_SEQ 6
+#define MAX_NUM_MASK_SEQ 6
+
+#define OPERAND_DNUM 1
+#define OPERAND_BYTE_SEQ 2
+
+#define MAX_OPERAND 0x40
+#define TYPE_BYTE_EQ (MAX_OPERAND + 1)
+#define TYPE_DNUM_EQ (MAX_OPERAND + 2)
+#define TYPE_BIT_EQ (MAX_OPERAND + 3)
+
+#define RPN_TYPE_AND (MAX_OPERAND + 4)
+#define RPN_TYPE_OR (MAX_OPERAND + 5)
+
+#define ICMP_OF_IP_PROTOCOL 0x01
+#define TCP_OF_IP_PROTOCOL 0x06
+#define UDP_OF_IP_PROTOCOL 0x11
+
+#define IPV4_PKT_OFFSET 20
+#define IP_PROTOCOL_OFFSET 31
+#define PORT_PROTOCOL_OFFSET 44
+
+#define FILLING_TYPE MBIT(0)
+#define FILLING_PATTERN MBIT(1)
+#define FILLING_OFFSET MBIT(2)
+#define FILLING_NUM_BYTES MBIT(3)
+#define FILLING_REPEAT MBIT(4)
+#define FILLING_BYTE_SEQ MBIT(5)
+#define FILLING_MASK_SEQ MBIT(6)
+
+/** Type definition of filter_item
+ * Support three match methods:
+ * <1>Byte comparison type=0x41
+ * <2>Decimal comparison type=0x42
+ * <3>Bit comparison type=0x43
+ */
+typedef struct _mef_filter_t {
+ /** flag*/
+ t_u32 fill_flag;
+ /** BYTE 0X41; Decimal 0X42; Bit 0x43*/
+ t_u16 type;
+ /** value*/
+ t_u32 pattern;
+ /** offset*/
+ t_u16 offset;
+ /** number of bytes*/
+ t_u16 num_bytes;
+ /** repeat*/
+ t_u16 repeat;
+ /** byte number*/
+ t_u8 num_byte_seq;
+ /** array*/
+ t_u8 byte_seq[MAX_NUM_BYTE_SEQ];
+ /** mask numbers*/
+ t_u8 num_mask_seq;
+ /** array*/
+ t_u8 mask_seq[MAX_NUM_MASK_SEQ];
+} mef_filter_t;
+
+typedef struct _mef_entry_t {
+ /** mode: bit0--hostsleep mode; bit1--non hostsleep mode */
+ t_u8 mode;
+ /** action: 0--discard and not wake host;
+ 1--discard and wake host;
+ 3--allow and wake host;*/
+ t_u8 action;
+ /** filter number */
+ t_u8 filter_num;
+ /** filter array*/
+ mef_filter_t filter_item[MAX_NUM_FILTERS];
+ /** rpn array*/
+ t_u8 rpn[MAX_NUM_FILTERS];
+} mef_entry_t;
+
+/** Type definition of mlan_ds_nvflt_mef_entry
+ *for MLAN_OID_MISC_MEF_FLT_CFG
+ */
+typedef struct _mlan_ds_misc_mef_flt_cfg {
+ /** Type of action*/
+ int mef_act_type;
+ /** NV Filter Criteria*/
+ t_u32 criteria;
+ /** NV MEF entry*/
+ mef_entry_t mef_entry;
+} mlan_ds_misc_mef_flt_cfg;
+
+/** Enumeration for action type*/
+enum _mlan_act_mef_act_type {
+ MEF_ACT_ADD = 1,
+ MEF_ACT_ENABLE,
+ MEF_ACT_DISABLE,
+ MEF_ACT_CANCEL,
+ MEF_ACT_AUTOARP,
+ MEF_ACT_WOWLAN,
+ MEF_ACT_IPV6_NS,
+};
+
+typedef struct _mlan_ds_sensor_temp {
+ t_u32 temperature;
+} mlan_ds_sensor_temp;
+
+#define MLAN_KCK_LEN 16
+#define MLAN_KEK_LEN 16
+#define MLAN_REPLAY_CTR_LEN 8
+/** mlan_ds_misc_gtk_rekey_data */
+typedef struct _mlan_ds_misc_gtk_rekey_data {
+ /** key encryption key */
+ t_u8 kek[MLAN_KEK_LEN];
+ /** key confirmation key */
+ t_u8 kck[MLAN_KCK_LEN];
+ /** replay counter */
+ t_u8 replay_ctr[MLAN_REPLAY_CTR_LEN];
+} mlan_ds_misc_gtk_rekey_data;
+typedef struct _mlan_ds_bw_chan_oper {
+ /* bandwidth 20:20M 40:40M 80:80M*/
+ t_u8 bandwidth;
+ /* channel number */
+ t_u8 channel;
+ /* Non-global operating class */
+ t_u8 oper_class;
+} mlan_ds_bw_chan_oper;
+
+typedef struct _mlan_ds_ind_rst_cfg {
+ /** Set or Get */
+ t_u16 action;
+ /** oob mode enable/ disable */
+ t_u8 ir_mode;
+ /** gpio pin */
+ t_u8 gpio_pin;
+} mlan_ds_ind_rst_cfg;
+
+#define MKEEP_ALIVE_IP_PKT_MAX 256
+typedef struct _mlan_ds_misc_keep_alive {
+ t_u8 mkeep_alive_id;
+ t_u8 enable;
+ /** enable/disable tcp reset*/
+ t_u8 reset;
+ /**True means saved in driver, false means not saved or download*/
+ t_u8 cached;
+ t_u32 send_interval;
+ t_u16 retry_interval;
+ t_u16 retry_count;
+ t_u8 dst_mac[MLAN_MAC_ADDR_LENGTH];
+ t_u8 src_mac[MLAN_MAC_ADDR_LENGTH];
+ t_u16 pkt_len;
+ t_u8 packet[MKEEP_ALIVE_IP_PKT_MAX];
+ /** Ethernet type */
+ t_u16 ether_type;
+} mlan_ds_misc_keep_alive, *pmlan_ds_misc_keep_alive;
+
+/** TX and RX histogram statistic parameters*/
+typedef MLAN_PACK_START struct _mlan_ds_misc_tx_rx_histogram {
+ /** Enable or disable get tx/rx histogram statistic */
+ t_u8 enable;
+ /** Choose to get TX, RX or both histogram statistic */
+ t_u16 action;
+ /** Size of Tx/Rx info */
+ t_u16 size;
+ /** Store Tx/Rx info */
+ t_u8 value[1];
+} MLAN_PACK_END mlan_ds_misc_tx_rx_histogram;
+
+typedef MLAN_PACK_START struct _mlan_ds_cw_mode_ctrl {
+ /** Mode of Operation 0: Disable 1: Tx Continuous Packet 2: Tx
+ * Continuous Wave */
+ t_u8 mode;
+ /*channel*/
+ t_u8 channel;
+ /* channel info*/
+ t_u8 chanInfo;
+ /** Tx Power level in dBm */
+ t_u16 txPower;
+ /** Packet Length */
+ t_u16 pktLength;
+ /** bit rate Info */
+ t_u32 rateInfo;
+} MLAN_PACK_END mlan_ds_cw_mode_ctrl;
+
+#define RX_PKT_INFO MBIT(1)
+/** Struct for per-packet configuration */
+typedef struct _mlan_per_pkt_cfg {
+ /** Type ID*/
+ t_u16 type;
+ /** Length of payload*/
+ t_u16 len;
+ /** Tx/Rx per-packet control */
+ t_u8 tx_rx_control;
+ /** Number of ethernet types in ether_type array */
+ t_u8 proto_type_num;
+ /** Array of ether_type for per-packet control */
+ t_u16 ether_type[];
+} mlan_per_pkt_cfg;
+
+/** Type definition of mlan_ds_misc_robustcoex_params for MLAN_IOCTL_MISC_CFG */
+typedef struct _mlan_ds_misc_robustcoex_params {
+ t_u16 method;
+ /** enable/disable robustcoex gpio cfg */
+ t_u8 enable;
+ /** Number of GPIO */
+ t_u8 gpio_num;
+ /** Polarity of GPIO */
+ t_u8 gpio_polarity;
+} mlan_ds_misc_robustcoex_params;
+
+#if defined(PCIE)
+typedef struct _mlan_ds_ssu_params {
+ t_u32 nskip;
+ t_u32 nsel;
+ t_u32 adcdownsample;
+ t_u32 mask_adc_pkt;
+ t_u32 out_16bits;
+ t_u32 spec_pwr_enable;
+ t_u32 rate_deduction;
+ t_u32 n_pkt_avg;
+} mlan_ds_ssu_params;
+#endif
+
+#define MAX_NUM_MAC 2
+/** Type definition of mlan_ds_misc_mapping_policy */
+typedef struct _mlan_ds_misc_mapping_policy {
+ /** Enable/disable dynamic mapping */
+ t_u16 subcmd;
+ /** Mapping policy */
+ t_u8 mapping_policy;
+} mlan_ds_misc_mapping_policy, *pmlan_ds_misc_mapping_policy;
+
+typedef struct _dmcsChanStatus_t {
+ /** Channel number */
+ t_u8 channel;
+ /** Number of ap on this channel */
+ t_u8 ap_count;
+ /** Number of sta on this channel */
+ t_u8 sta_count;
+} dmcsChanStatus_t, *pdmcsChanStatus_t;
+
+typedef struct _dmcsStatus_t {
+ /** Radio ID */
+ t_u8 radio_id;
+ /** Running mode
+ ** 0 - Idle
+ ** 1 - DBC
+ ** 2 - DRCS
+ */
+ t_u8 running_mode;
+ /** Current channel status */
+ dmcsChanStatus_t chan_status[2];
+} dmcsStatus_t, *pdmcsStatus_t;
+
+/** Type definition of mlan_ds_misc_dmcs_status */
+typedef struct _mlan_ds_misc_dmcs_status {
+ t_u8 mapping_policy;
+ dmcsStatus_t radio_status[MAX_NUM_MAC];
+} mlan_ds_misc_dmcs_status, *pmlan_ds_misc_dmcs_status;
+
+/** Type definition of mlan_ds_misc_chan_trpc_cfg for
+ * MLAN_OID_MISC_GET_CHAN_TRPC_CFG */
+typedef struct _mlan_ds_misc_chan_trpc_cfg {
+ /** sub_band */
+ t_u16 sub_band;
+ /** length */
+ t_u16 length;
+ /** buf */
+ t_u8 trpc_buf[2048];
+} mlan_ds_misc_chan_trpc_cfg;
+
+#define MFG_CMD_SET_TEST_MODE 1
+#define MFG_CMD_UNSET_TEST_MODE 0
+#define MFG_CMD_TX_ANT 0x1004
+#define MFG_CMD_RX_ANT 0x1005
+#define MFG_CMD_TX_CONT 0x1009
+#define MFG_CMD_RF_CHAN 0x100A
+#define MFG_CMD_CLR_RX_ERR 0x1010
+#define MFG_CMD_TX_FRAME 0x1021
+#define MFG_CMD_RFPWR 0x1033
+#define MFG_CMD_RF_BAND_AG 0x1034
+#define MFG_CMD_RF_CHANNELBW 0x1044
+/** MFG CMD generic cfg */
+struct MLAN_PACK_START mfg_cmd_generic_cfg {
+ /** MFG command code */
+ t_u32 mfg_cmd;
+ /** Action */
+ t_u16 action;
+ /** Device ID */
+ t_u16 device_id;
+ /** MFG Error code */
+ t_u32 error;
+ /** value 1 */
+ t_u32 data1;
+ /** value 2 */
+ t_u32 data2;
+ /** value 3 */
+ t_u32 data3;
+} MLAN_PACK_END;
+
+/** MFG CMD Tx Frame 2 */
+struct MLAN_PACK_START mfg_cmd_tx_frame2 {
+ /** MFG command code */
+ t_u32 mfg_cmd;
+ /** Action */
+ t_u16 action;
+ /** Device ID */
+ t_u16 device_id;
+ /** MFG Error code */
+ t_u32 error;
+ /** enable */
+ t_u32 enable;
+ /** data_rate */
+ t_u32 data_rate;
+ /** frame pattern */
+ t_u32 frame_pattern;
+ /** frame length */
+ t_u32 frame_length;
+ /** BSSID */
+ t_u8 bssid[MLAN_MAC_ADDR_LENGTH];
+ /** Adjust burst sifs */
+ t_u16 adjust_burst_sifs;
+ /** Burst sifs in us*/
+ t_u32 burst_sifs_in_us;
+ /** short preamble */
+ t_u32 short_preamble;
+ /** active sub channel */
+ t_u32 act_sub_ch;
+ /** short GI */
+ t_u32 short_gi;
+ /** Adv coding */
+ t_u32 adv_coding;
+ /** Tx beamforming */
+ t_u32 tx_bf;
+ /** HT Greenfield Mode*/
+ t_u32 gf_mode;
+ /** STBC */
+ t_u32 stbc;
+ /** power id */
+ t_u32 rsvd[2];
+} MLAN_PACK_END;
+
+/* MFG CMD Tx Continuous */
+struct MLAN_PACK_START mfg_cmd_tx_cont {
+ /** MFG command code */
+ t_u32 mfg_cmd;
+ /** Action */
+ t_u16 action;
+ /** Device ID */
+ t_u16 device_id;
+ /** MFG Error code */
+ t_u32 error;
+ /** enable Tx*/
+ t_u32 enable_tx;
+ /** Continuous Wave mode */
+ t_u32 cw_mode;
+ /** payload pattern */
+ t_u32 payload_pattern;
+ /** CS Mode */
+ t_u32 cs_mode;
+ /** active sub channel */
+ t_u32 act_sub_ch;
+ /** Tx rate */
+ t_u32 tx_rate;
+ /** power id */
+ t_u32 rsvd;
+} MLAN_PACK_END;
+
+typedef struct _mlan_ds_misc_chnrgpwr_cfg {
+ /** length */
+ t_u16 length;
+ /** chnrgpwr buf */
+ t_u8 chnrgpwr_buf[2048];
+} mlan_ds_misc_chnrgpwr_cfg;
+
+/** dfs chan list for MLAN_OID_MISC_CFP_TABLE */
+typedef struct _mlan_ds_misc_cfp_tbl {
+ /** band */
+ t_u8 band;
+ /** num chan */
+ t_u8 num_chan;
+ /** cfp table */
+ chan_freq_power_t cfp_tbl[];
+} mlan_ds_misc_cfp_tbl;
+
+/** Type definition of mlan_ds_misc_cfg for MLAN_IOCTL_MISC_CFG */
+typedef struct _mlan_ds_misc_cfg {
+ /** Sub-command */
+ t_u32 sub_command;
+ /** Miscellaneous configuration parameter */
+ union {
+ /** Generic IE for MLAN_OID_MISC_GEN_IE */
+ mlan_ds_misc_gen_ie gen_ie;
+ /** Region code for MLAN_OID_MISC_REGION */
+ t_u32 region_code;
+#ifdef SDIO
+ /** SDIO MP-A Ctrl command for MLAN_OID_MISC_SDIO_MPA_CTRL */
+ mlan_ds_misc_sdio_mpa_ctrl mpa_ctrl;
+#endif
+ /** Hostcmd for MLAN_OID_MISC_HOST_CMD */
+ mlan_ds_misc_cmd hostcmd;
+ /** System clock for MLAN_OID_MISC_SYS_CLOCK */
+ mlan_ds_misc_sys_clock sys_clock;
+ /** WWS set/get for MLAN_OID_MISC_WWS */
+ t_u32 wws_cfg;
+ /** Get associate response for MLAN_OID_MISC_ASSOC_RSP */
+ mlan_ds_misc_assoc_rsp assoc_resp;
+ /** Function init/shutdown for MLAN_OID_MISC_INIT_SHUTDOWN */
+ t_u32 func_init_shutdown;
+ /** Custom IE for MLAN_OID_MISC_CUSTOM_IE */
+ mlan_ds_misc_custom_ie cust_ie;
+ /** Config dynamic bandwidth*/
+ t_u16 dyn_bw;
+ /** Tx data pause for MLAN_OID_MISC_TX_DATAPAUSE */
+ mlan_ds_misc_tx_datapause tx_datapause;
+ /** IP address configuration */
+ mlan_ds_misc_ipaddr_cfg ipaddr_cfg;
+ /** MAC control for MLAN_OID_MISC_MAC_CONTROL */
+ t_u32 mac_ctrl;
+ /** MEF configuration for MLAN_OID_MISC_MEF_CFG */
+ mlan_ds_misc_mef_cfg mef_cfg;
+ /** CFP code for MLAN_OID_MISC_CFP_CODE */
+ mlan_ds_misc_cfp_code cfp_code;
+ /** Country code for MLAN_OID_MISC_COUNTRY_CODE */
+ mlan_ds_misc_country_code country_code;
+ /** Thermal reading for MLAN_OID_MISC_THERMAL */
+ t_u32 thermal;
+ /** Mgmt subtype mask for MLAN_OID_MISC_RX_MGMT_IND */
+ t_u32 mgmt_subtype_mask;
+ /** subscribe event for MLAN_OID_MISC_SUBSCRIBE_EVENT */
+ mlan_ds_subscribe_evt subscribe_event;
+#ifdef DEBUG_LEVEL1
+ /** Driver debug bit masks */
+ t_u32 drvdbg;
+#endif
+ /** Hotspot config param set */
+ t_u32 hotspot_cfg;
+#ifdef STA_SUPPORT
+ ExtCap_t ext_cap;
+#endif
+ mlan_ds_misc_otp_user_data otp_user_data;
+#ifdef USB
+ /** USB aggregation parameters for MLAN_OID_MISC_USB_AGGR_CTRL
+ */
+ mlan_ds_misc_usb_aggr_ctrl usb_aggr_params;
+#endif
+ mlan_ds_misc_aggr_ctrl aggr_params;
+ /** Tx control */
+ t_u32 tx_control;
+#if defined(STA_SUPPORT)
+ mlan_ds_misc_pmfcfg pmfcfg;
+#endif
+#ifdef WIFI_DIRECT_SUPPORT
+ mlan_ds_wifi_direct_config p2p_config;
+#endif
+ mlan_ds_coalesce_cfg coalesce_cfg;
+ t_u8 low_pwr_mode;
+ /** MEF-FLT-CONFIG for MLAN_OID_MISC_NV_FLT_CFG */
+ mlan_ds_misc_mef_flt_cfg mef_flt_cfg;
+ mlan_ds_misc_dfs_repeater dfs_repeater;
+#ifdef RX_PACKET_COALESCE
+ mlan_ds_misc_rx_packet_coalesce rx_coalesce;
+#endif
+ /** FW reload flag */
+ t_u8 fw_reload;
+ mlan_ds_sensor_temp sensor_temp;
+ /** GTK rekey data */
+ mlan_ds_misc_gtk_rekey_data gtk_rekey;
+ mlan_ds_bw_chan_oper bw_chan_oper;
+ mlan_ds_ind_rst_cfg ind_rst_cfg;
+ t_u64 misc_tsf;
+ mlan_ds_custom_reg_domain custom_reg_domain;
+ mlan_ds_misc_keep_alive keep_alive;
+ mlan_ds_misc_tx_rx_histogram tx_rx_histogram;
+ mlan_ds_cw_mode_ctrl cwmode;
+ /** Tx/Rx per-packet control */
+ t_u8 txrx_pkt_ctrl;
+ mlan_ds_misc_robustcoex_params robustcoexparams;
+#if defined(PCIE)
+ mlan_ds_ssu_params ssu_params;
+#endif
+ /** boot sleep enable or disable */
+ t_u16 boot_sleep;
+ /** Mapping Policy */
+ mlan_ds_misc_mapping_policy dmcs_policy;
+ mlan_ds_misc_dmcs_status dmcs_status;
+ mlan_ds_misc_rx_abort_cfg rx_abort_cfg;
+ mlan_ds_misc_rx_abort_cfg_ext rx_abort_cfg_ext;
+ mlan_ds_misc_tx_ampdu_prot_mode tx_ampdu_prot_mode;
+ mlan_ds_misc_rate_adapt_cfg rate_adapt_cfg;
+ mlan_ds_misc_cck_desense_cfg cck_desense_cfg;
+ mlan_ds_misc_chan_trpc_cfg trpc_cfg;
+ mlan_ds_misc_chnrgpwr_cfg rgchnpwr_cfg;
+
+ mlan_ds_band_steer_cfg band_steer_cfg;
+ mlan_ds_beacon_stuck_param_cfg beacon_stuck_cfg;
+ struct mfg_cmd_generic_cfg mfg_generic_cfg;
+ struct mfg_cmd_tx_cont mfg_tx_cont;
+ struct mfg_cmd_tx_frame2 mfg_tx_frame2;
+ mlan_ds_misc_arb_cfg arb_cfg;
+ mlan_ds_misc_cfp_tbl cfp;
+ t_u8 range_ext_mode;
+ mlan_ds_misc_dot11mc_unassoc_ftm_cfg dot11mc_unassoc_ftm_cfg;
+ mlan_ds_misc_tp_state tp_state;
+ } param;
+} mlan_ds_misc_cfg, *pmlan_ds_misc_cfg;
+
+/** Hotspot status enable */
+#define HOTSPOT_ENABLED MBIT(0)
+/** Hotspot status disable */
+#define HOTSPOT_DISABLED MFALSE
+/** Keep Hotspot2.0 compatible in mwu and wpa_supplicant */
+#define HOTSPOT_BY_SUPPLICANT MBIT(1)
+
+/** Reason codes */
+#define MLAN_REASON_UNSPECIFIED 1
+#define MLAN_REASON_PREV_AUTH_NOT_VALID 2
+#define MLAN_REASON_DEAUTH_LEAVING 3
+#define MLAN_REASON_DISASSOC_DUE_TO_INACTIVITY 4
+#define MLAN_REASON_DISASSOC_AP_BUSY 5
+#define MLAN_REASON_CLASS2_FRAME_FROM_NOAUTH_STA 6
+#define MLAN_REASON_CLASS3_FRAME_FROM_NOASSOC_STA 7
+#define MLAN_REASON_DISASSOC_STA_HAS_LEFT 8
+#define MLAN_REASON_STA_REQ_ASSOC_WITHOUT_AUTH 9
+#endif /* !_MLAN_IOCTL_H_ */
diff --git a/drivers/net/wireless/nxp/mxm_wifiex/wlan_src/mlan/mlan_join.c b/drivers/net/wireless/nxp/mxm_wifiex/wlan_src/mlan/mlan_join.c
new file mode 100644
index 000000000000..359e0319a6f8
--- /dev/null
+++ b/drivers/net/wireless/nxp/mxm_wifiex/wlan_src/mlan/mlan_join.c
@@ -0,0 +1,2621 @@
+/** @file mlan_join.c
+ *
+ * @brief Functions implementing wlan infrastructure and adhoc join routines
+ *
+ * IOCTL handlers as well as command preparation and response routines
+ * for sending adhoc start, adhoc join, and association commands
+ * to the firmware.
+ *
+ *
+ * Copyright 2014-2020 NXP
+ *
+ * This software file (the File) is distributed by NXP
+ * under the terms of the GNU General Public License Version 2, June 1991
+ * (the License). You may use, redistribute and/or modify the 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.
+ *
+ */
+
+/******************************************************
+Change log:
+ 10/30/2008: initial version
+******************************************************/
+
+#include "mlan.h"
+#include "mlan_join.h"
+#include "mlan_util.h"
+#include "mlan_fw.h"
+#include "mlan_main.h"
+#include "mlan_wmm.h"
+#include "mlan_11n.h"
+#include "mlan_11ac.h"
+#include "mlan_11ax.h"
+#include "mlan_11h.h"
+#ifdef DRV_EMBEDDED_SUPPLICANT
+#include "authenticator_api.h"
+#endif
+/********************************************************
+ Local Constants
+********************************************************/
+
+/********************************************************
+ Local Variables
+********************************************************/
+
+/********************************************************
+ Global Variables
+********************************************************/
+
+/********************************************************
+ Local Functions
+********************************************************/
+/**
+ * @brief Append a generic IE as a pass through TLV to a TLV buffer.
+ *
+ * This function is called from the network join command prep. 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.
+ *
+ * @param priv A pointer to mlan_private structure
+ * @param ppbuffer pointer to command buffer pointer
+ *
+ * @return bytes added to the buffer
+ */
+static int wlan_cmd_append_generic_ie(mlan_private *priv, t_u8 **ppbuffer)
+{
+ int ret_len = 0;
+ MrvlIEtypesHeader_t ie_header;
+
+ ENTER();
+
+ /* Null Checks */
+ if (ppbuffer == MNULL) {
+ LEAVE();
+ return 0;
+ }
+ if (*ppbuffer == MNULL) {
+ LEAVE();
+ return 0;
+ }
+
+ /*
+ * If there is a generic ie buffer setup, append it to the return
+ * parameter buffer pointer.
+ */
+ if (priv->gen_ie_buf_len) {
+ PRINTM(MINFO, "append generic IE %d to %p\n",
+ priv->gen_ie_buf_len, *ppbuffer);
+
+ /* Wrap the generic IE buffer with a pass through TLV type */
+ ie_header.type = wlan_cpu_to_le16(TLV_TYPE_PASSTHROUGH);
+ ie_header.len = wlan_cpu_to_le16(priv->gen_ie_buf_len);
+ memcpy_ext(priv->adapter, *ppbuffer, &ie_header,
+ sizeof(ie_header), sizeof(ie_header));
+
+ /* Increment the return size and the return buffer pointer param
+ */
+ *ppbuffer += sizeof(ie_header);
+ ret_len += sizeof(ie_header);
+
+ /* Copy the generic IE buffer to the output buffer, advance
+ * pointer */
+ memcpy_ext(priv->adapter, *ppbuffer, priv->gen_ie_buf,
+ priv->gen_ie_buf_len, priv->gen_ie_buf_len);
+
+ /* Increment the return size and the return buffer pointer param
+ */
+ *ppbuffer += 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 */
+ LEAVE();
+ return ret_len;
+}
+
+/**
+ * @brief Append IE as a pass through TLV to a TLV buffer.
+ *
+ * This routine appends IE as a pass through TLV type to the request.
+ *
+ * @param priv A pointer to mlan_private structure
+ * @param ie A pointer to IE buffer
+ * @param ppbuffer pointer to command buffer pointer
+ *
+ * @return bytes added to the buffer
+ */
+static int wlan_cmd_append_pass_through_ie(mlan_private *priv,
+ IEEEtypes_Generic_t *ie,
+ t_u8 **ppbuffer)
+{
+ int ret_len = 0;
+ MrvlIEtypesHeader_t ie_header;
+
+ ENTER();
+
+ /* Null Checks */
+ if (ppbuffer == MNULL) {
+ LEAVE();
+ return 0;
+ }
+ if (*ppbuffer == MNULL) {
+ LEAVE();
+ return 0;
+ }
+ if (ie->ieee_hdr.len) {
+ PRINTM(MINFO, "append generic IE %d to %p\n", ie->ieee_hdr.len,
+ *ppbuffer);
+
+ /* Wrap the generic IE buffer with a pass through TLV type */
+ ie_header.type = wlan_cpu_to_le16(TLV_TYPE_PASSTHROUGH);
+ ie_header.len = wlan_cpu_to_le16(ie->ieee_hdr.len +
+ sizeof(IEEEtypes_Header_t));
+ memcpy_ext(priv->adapter, *ppbuffer, &ie_header,
+ sizeof(ie_header), sizeof(ie_header));
+
+ /* Increment the return size and the return buffer pointer param
+ */
+ *ppbuffer += sizeof(ie_header);
+ ret_len += sizeof(ie_header);
+
+ /* Copy the generic IE buffer to the output buffer, advance
+ * pointer */
+ memcpy_ext(priv->adapter, *ppbuffer, ie,
+ ie->ieee_hdr.len + sizeof(IEEEtypes_Header_t),
+ ie->ieee_hdr.len + sizeof(IEEEtypes_Header_t));
+
+ /* Increment the return size and the return buffer pointer param
+ */
+ *ppbuffer += ie->ieee_hdr.len + sizeof(IEEEtypes_Header_t);
+ ret_len += ie->ieee_hdr.len + sizeof(IEEEtypes_Header_t);
+ }
+ /* return the length appended to the buffer */
+ LEAVE();
+ return ret_len;
+}
+
+/**
+ * @brief Append TSF tracking info from the scan table for the target AP
+ *
+ * This function is called from the network join command prep. 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.
+ *
+ * @param pmpriv A pointer to mlan_private structure
+ * @param ppbuffer A pointer to command buffer pointer
+ * @param pbss_desc A pointer to the BSS Descriptor from the scan table of
+ * the AP we are trying to join
+ *
+ * @return bytes added to the buffer
+ */
+static int wlan_cmd_append_tsf_tlv(mlan_private *pmriv, t_u8 **ppbuffer,
+ BSSDescriptor_t *pbss_desc)
+{
+ MrvlIEtypes_TsfTimestamp_t tsf_tlv;
+ t_u64 tsf_val;
+
+ ENTER();
+
+ /* Null Checks */
+ if (ppbuffer == MNULL) {
+ LEAVE();
+ return 0;
+ }
+ if (*ppbuffer == MNULL) {
+ LEAVE();
+ return 0;
+ }
+
+ memset(pmriv->adapter, &tsf_tlv, 0x00,
+ sizeof(MrvlIEtypes_TsfTimestamp_t));
+
+ tsf_tlv.header.type = wlan_cpu_to_le16(TLV_TYPE_TSFTIMESTAMP);
+ tsf_tlv.header.len = wlan_cpu_to_le16(2 * sizeof(tsf_val));
+
+ memcpy_ext(pmriv->adapter, *ppbuffer, &tsf_tlv, sizeof(tsf_tlv.header),
+ sizeof(tsf_tlv.header));
+ *ppbuffer += sizeof(tsf_tlv.header);
+
+ /* TSF timestamp from the firmware TSF when the bcn/prb rsp was received
+ */
+ tsf_val = wlan_cpu_to_le64(pbss_desc->network_tsf);
+ memcpy_ext(pmriv->adapter, *ppbuffer, &tsf_val, sizeof(tsf_val),
+ sizeof(tsf_val));
+ *ppbuffer += sizeof(tsf_val);
+
+ memcpy_ext(pmriv->adapter, &tsf_val, pbss_desc->time_stamp,
+ sizeof(pbss_desc->time_stamp), sizeof(tsf_val));
+
+ PRINTM(MINFO, "ASSOC: TSF offset calc: %016llx - %016llx\n", tsf_val,
+ pbss_desc->network_tsf);
+
+ memcpy_ext(pmriv->adapter, *ppbuffer, &tsf_val, sizeof(tsf_val),
+ sizeof(tsf_val));
+ *ppbuffer += sizeof(tsf_val);
+
+ LEAVE();
+ return sizeof(tsf_tlv.header) + (2 * sizeof(tsf_val));
+}
+
+/**
+ * @brief 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
+ *
+ * @param pmpriv A pointer to mlan_private structure
+ * @param rate1 the buffer which keeps input and output
+ * @param rate1_size the size of rate1 buffer
+ * @param rate2 the buffer which keeps rate2
+ * @param rate2_size the size of rate2 buffer.
+ *
+ * @return MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ */
+static mlan_status wlan_get_common_rates(mlan_private *pmpriv, t_u8 *rate1,
+ t_u32 rate1_size, t_u8 *rate2,
+ t_u32 rate2_size)
+{
+ mlan_status ret = MLAN_STATUS_SUCCESS;
+ mlan_callbacks *pcb = (mlan_callbacks *)&pmpriv->adapter->callbacks;
+ t_u8 *ptr = rate1;
+ t_u8 *tmp = MNULL;
+ t_u32 i, j;
+
+ ENTER();
+
+ ret = pcb->moal_malloc(pmpriv->adapter->pmoal_handle, rate1_size,
+ MLAN_MEM_DEF, &tmp);
+ if (ret != MLAN_STATUS_SUCCESS || !tmp) {
+ PRINTM(MERROR, "Failed to allocate buffer\n");
+ ret = MLAN_STATUS_FAILURE;
+ goto done;
+ }
+
+ memcpy_ext(pmpriv->adapter, tmp, rate1, rate1_size, rate1_size);
+ memset(pmpriv->adapter, rate1, 0, rate1_size);
+
+ for (i = 0; rate2[i] && i < rate2_size; i++) {
+ for (j = 0; tmp[j] && j < rate1_size; j++) {
+ /* Check common rate, excluding the bit
+ * for basic rate */
+ if ((rate2[i] & 0x7F) == (tmp[j] & 0x7F)) {
+ *rate1++ = tmp[j];
+ break;
+ }
+ }
+ }
+
+ HEXDUMP("rate1 (AP) Rates", tmp, rate1_size);
+ HEXDUMP("rate2 (Card) Rates", rate2, rate2_size);
+ HEXDUMP("Common Rates", ptr, rate1 - ptr);
+ PRINTM(MINFO, "Tx DataRate is set to 0x%X\n", pmpriv->data_rate);
+
+ if (!pmpriv->is_data_rate_auto) {
+ while (*ptr) {
+ if ((*ptr & 0x7f) == pmpriv->data_rate) {
+ ret = MLAN_STATUS_SUCCESS;
+ goto done;
+ }
+ ptr++;
+ }
+ PRINTM(MMSG,
+ "Previously set fixed data rate %#x is not "
+ "compatible with the network\n",
+ pmpriv->data_rate);
+
+ ret = MLAN_STATUS_FAILURE;
+ goto done;
+ }
+
+ ret = MLAN_STATUS_SUCCESS;
+done:
+ if (tmp)
+ pcb->moal_mfree(pmpriv->adapter->pmoal_handle, tmp);
+
+ LEAVE();
+ return ret;
+}
+
+/**
+ * @brief Create the intersection of the rates supported by a target BSS and
+ * our pmadapter settings for use in an assoc/join command.
+ *
+ * @param pmpriv A pointer to mlan_private structure
+ * @param pbss_desc BSS Descriptor whose rates are used in the setup
+ * @param pout_rates Output: Octet array of rates common between the BSS
+ * and the pmadapter supported rates settings
+ * @param pout_rates_size Output: Number of rates/octets set in pout_rates
+ *
+ * @return MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ */
+static mlan_status wlan_setup_rates_from_bssdesc(mlan_private *pmpriv,
+ BSSDescriptor_t *pbss_desc,
+ t_u8 *pout_rates,
+ t_u32 *pout_rates_size)
+{
+ t_u8 card_rates[WLAN_SUPPORTED_RATES];
+ t_u32 card_rates_size = 0;
+ ENTER();
+ /* Copy AP supported rates */
+ memcpy_ext(pmpriv->adapter, pout_rates, pbss_desc->supported_rates,
+ WLAN_SUPPORTED_RATES, WLAN_SUPPORTED_RATES);
+
+ if ((pmpriv->adapter->region_code == COUNTRY_CODE_JP_40 ||
+ pmpriv->adapter->region_code == COUNTRY_CODE_JP_FF) &&
+ (pbss_desc->phy_param_set.ds_param_set.current_chan == 14)) {
+ /* Special Case: For Japan, 11G rates on CH14 are not allowed*/
+ card_rates_size = wlan_get_supported_rates(
+ pmpriv, pmpriv->bss_mode, BAND_B, card_rates);
+ } else {
+ /* Get the STA supported rates */
+ card_rates_size =
+ wlan_get_supported_rates(pmpriv, pmpriv->bss_mode,
+ pmpriv->config_bands,
+ card_rates);
+ }
+ /* Get the common rates between AP and STA supported rates */
+ if (wlan_get_common_rates(pmpriv, pout_rates, WLAN_SUPPORTED_RATES,
+ card_rates, card_rates_size)) {
+ *pout_rates_size = 0;
+ PRINTM(MERROR, "wlan_get_common_rates failed\n");
+ LEAVE();
+ return MLAN_STATUS_FAILURE;
+ }
+
+ *pout_rates_size =
+ MIN(wlan_strlen((char *)pout_rates), WLAN_SUPPORTED_RATES);
+
+ LEAVE();
+ return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ * @brief Update the scan entry TSF timestamps to reflect a new association
+ *
+ * @param pmpriv A pointer to mlan_private structure
+ * @param pnew_bss_desc A pointer to the newly associated AP's scan table entry
+ *
+ * @return N/A
+ */
+static t_void wlan_update_tsf_timestamps(mlan_private *pmpriv,
+ BSSDescriptor_t *pnew_bss_desc)
+{
+ mlan_adapter *pmadapter = pmpriv->adapter;
+ t_u32 table_idx;
+ t_u64 new_tsf_base;
+ t_s64 tsf_delta;
+
+ ENTER();
+
+ memcpy_ext(pmpriv->adapter, &new_tsf_base, pnew_bss_desc->time_stamp,
+ sizeof(pnew_bss_desc->time_stamp), sizeof(new_tsf_base));
+
+ tsf_delta = new_tsf_base - pnew_bss_desc->network_tsf;
+
+ PRINTM(MINFO, "TSF: Update TSF timestamps, 0x%016llx -> 0x%016llx\n",
+ pnew_bss_desc->network_tsf, new_tsf_base);
+
+ for (table_idx = 0; table_idx < pmadapter->num_in_scan_table;
+ table_idx++) {
+ pmadapter->pscan_table[table_idx].network_tsf += tsf_delta;
+ }
+
+ LEAVE();
+}
+
+/**
+ * @brief Append a wapi IE
+ *
+ * This function is called from the network join command prep. routine.
+ * If the IE buffer has been setup by the application, this routine appends
+ * the buffer as a wapi TLV type to the request.
+ *
+ * @param priv A pointer to mlan_private structure
+ * @param ppbuffer pointer to command buffer pointer
+ *
+ * @return bytes added to the buffer
+ */
+static int wlan_cmd_append_wapi_ie(mlan_private *priv, t_u8 **ppbuffer)
+{
+ int retlen = 0;
+ MrvlIEtypesHeader_t ie_header;
+
+ ENTER();
+
+ /* Null Checks */
+ if (ppbuffer == MNULL) {
+ LEAVE();
+ return 0;
+ }
+ if (*ppbuffer == MNULL) {
+ LEAVE();
+ return 0;
+ }
+
+ /*
+ * If there is a wapi ie buffer setup, append it to the return
+ * parameter buffer pointer.
+ */
+ if (priv->wapi_ie_len) {
+ PRINTM(MCMND, "append wapi ie %d to %p\n", priv->wapi_ie_len,
+ *ppbuffer);
+
+ /* Wrap the generic IE buffer with a pass through TLV type */
+ ie_header.type = wlan_cpu_to_le16(TLV_TYPE_WAPI_IE);
+ ie_header.len = wlan_cpu_to_le16(priv->wapi_ie_len);
+ memcpy_ext(priv->adapter, *ppbuffer, &ie_header,
+ sizeof(ie_header), sizeof(ie_header));
+
+ /* Increment the return size and the return buffer pointer param
+ */
+ *ppbuffer += sizeof(ie_header);
+ retlen += sizeof(ie_header);
+
+ /* Copy the wapi IE buffer to the output buffer, advance pointer
+ */
+ memcpy_ext(priv->adapter, *ppbuffer, priv->wapi_ie,
+ priv->wapi_ie_len, priv->wapi_ie_len);
+
+ /* Increment the return size and the return buffer pointer param
+ */
+ *ppbuffer += priv->wapi_ie_len;
+ retlen += priv->wapi_ie_len;
+ }
+ /* return the length appended to the buffer */
+ LEAVE();
+ return retlen;
+}
+
+/**
+ * @brief Append a osen IE
+ *
+ * This function is called from the network join command prep. routine.
+ * If the IE buffer has been setup by the application, this routine appends
+ * the buffer as a osen TLV type to the request.
+ *
+ * @param priv A pointer to mlan_private structure
+ * @param ppbuffer pointer to command buffer pointer
+ *
+ * @return bytes added to the buffer
+ */
+static int wlan_cmd_append_osen_ie(mlan_private *priv, t_u8 **ppbuffer)
+{
+ int retlen = 0;
+ MrvlIEtypesHeader_t ie_header;
+
+ ENTER();
+
+ /* Null Checks */
+ if (ppbuffer == MNULL) {
+ LEAVE();
+ return 0;
+ }
+ if (*ppbuffer == MNULL) {
+ LEAVE();
+ return 0;
+ }
+
+ /*
+ * If there is a osen ie buffer setup, append it to the return
+ * parameter buffer pointer.
+ */
+ if (priv->osen_ie_len) {
+ PRINTM(MCMND, "append osen ie %d to %p\n", priv->osen_ie_len,
+ *ppbuffer);
+
+ /* Wrap the generic IE buffer with a pass through TLV type */
+ ie_header.type = wlan_cpu_to_le16(TLV_TYPE_VENDOR_SPECIFIC_IE);
+ ie_header.len = wlan_cpu_to_le16(priv->osen_ie[1]);
+ memcpy_ext(priv->adapter, *ppbuffer, &ie_header,
+ sizeof(ie_header), sizeof(ie_header));
+
+ /* Increment the return size and the return buffer pointer param
+ */
+ *ppbuffer += sizeof(ie_header);
+ retlen += sizeof(ie_header);
+
+ /* Copy the osen IE buffer to the output buffer, advance pointer
+ */
+ memcpy_ext(priv->adapter, *ppbuffer, &priv->osen_ie[2],
+ priv->osen_ie[1], priv->osen_ie[1]);
+
+ /* Increment the return size and the return buffer pointer param
+ */
+ *ppbuffer += priv->osen_ie[1];
+ retlen += priv->osen_ie[1];
+ }
+ /* return the length appended to the buffer */
+ LEAVE();
+ return retlen;
+}
+
+/**
+ * @brief This function get the rsn_cap from RSN ie buffer.
+ *
+ * @param pmpriv A pointer to mlan_private structure
+ *
+ * @param data A pointer to rsn_ie data after IE header
+ * @param return rsn_cap
+ */
+t_u16 wlan_get_rsn_cap(t_u8 *data)
+{
+ t_u16 rsn_cap = 0;
+ t_u16 *ptr;
+ t_u16 pairwise_cipher_count = 0;
+ t_u16 akm_suite_count = 0;
+ /* rsn_cap = data + 2 bytes version + 4 bytes
+ * group_cipher_suite + 2 bytes pairwise_cipher_count +
+ * pairwise_cipher_count * PAIRWISE_CIPHER_SUITE_LEN + 2 bytes
+ * akm_suite_count + akm_suite_count * AKM_SUITE_LEN
+ */
+ ptr = (t_u16 *)(data + sizeof(t_u16) + 4 * sizeof(t_u8));
+ pairwise_cipher_count = wlan_le16_to_cpu(*ptr);
+ ptr = (t_u16 *)(data + sizeof(t_u16) + 4 * sizeof(t_u8) +
+ sizeof(t_u16) +
+ pairwise_cipher_count * PAIRWISE_CIPHER_SUITE_LEN);
+ akm_suite_count = wlan_le16_to_cpu(*ptr);
+ ptr = (t_u16 *)(data + sizeof(t_u16) + 4 * sizeof(t_u8) +
+ sizeof(t_u16) +
+ pairwise_cipher_count * PAIRWISE_CIPHER_SUITE_LEN +
+ sizeof(t_u16) + akm_suite_count * AKM_SUITE_LEN);
+ rsn_cap = wlan_le16_to_cpu(*ptr);
+ PRINTM(MCMND, "rsn_cap=0x%x\n", rsn_cap);
+ return rsn_cap;
+}
+
+/**
+ * @brief This function check if we should enable 11w
+ *
+ * @param pmpriv A pointer to mlan_private structure
+ *
+ * @param BSSDescriptor_t A pointer to BSSDescriptor_t data structure
+ * @param return MTRUE/MFALSE
+ */
+t_u8 wlan_use_mfp(mlan_private *pmpriv, BSSDescriptor_t *pbss_desc)
+{
+ t_u16 ap_rsn_cap = 0;
+ t_u16 sta_rsn_cap = 0;
+ t_u8 ap_mfpc, ap_mfpr;
+ t_u8 sta_mfpc, sta_mfpr;
+
+ if (pmpriv->wpa_ie[0] != RSN_IE)
+ return 0;
+ sta_rsn_cap = wlan_get_rsn_cap(pmpriv->wpa_ie + 2);
+ if (!pbss_desc->prsn_ie)
+ return 0;
+ ap_rsn_cap = wlan_get_rsn_cap(pbss_desc->prsn_ie->data);
+ ap_mfpc = ((ap_rsn_cap & (0x1 << MFPC_BIT)) == (0x1 << MFPC_BIT));
+ ap_mfpr = ((ap_rsn_cap & (0x1 << MFPR_BIT)) == (0x1 << MFPR_BIT));
+ sta_mfpc = ((sta_rsn_cap & (0x1 << MFPC_BIT)) == (0x1 << MFPC_BIT));
+ sta_mfpr = ((sta_rsn_cap & (0x1 << MFPR_BIT)) == (0x1 << MFPR_BIT));
+ if (!ap_mfpc && !ap_mfpr)
+ return MFALSE;
+ if (!sta_mfpc && !sta_mfpr)
+ return MFALSE;
+ return MTRUE;
+}
+
+/********************************************************
+ Global Functions
+********************************************************/
+
+/**
+ * @brief This function updates RSN IE in the association request.
+ *
+ * @param pmpriv A pointer to mlan_private structure
+ *
+ * @param ptlv_rsn_ie A pointer to rsn_ie TLV
+ */
+int wlan_update_rsn_ie(mlan_private *pmpriv,
+ MrvlIEtypes_RsnParamSet_t *ptlv_rsn_ie)
+{
+ t_u16 *prsn_cap;
+ t_u16 *ptr;
+ t_u16 *akm_suite_count_ptr;
+ t_u16 pmf_mask = 0x00;
+ t_u8 *temp;
+ t_u16 pairwise_cipher_count = 0;
+ t_u16 akm_suite_count = 0;
+ t_u16 temp_akm_suite_count = 0;
+ int found = 0;
+ t_u8 sha_256_oui[4] = {0x00, 0x0f, 0xac, 0x06};
+ t_u8 sae_oui[4] = {0x00, 0x0f, 0xac, 0x08};
+ mlan_adapter *pmadapter = pmpriv->adapter;
+
+ int ap_mfpc = 0, ap_mfpr = 0, ret = MLAN_STATUS_SUCCESS;
+
+ pmf_mask = (((pmpriv->pmfcfg.mfpc << MFPC_BIT) |
+ (pmpriv->pmfcfg.mfpr << MFPR_BIT)) |
+ (~PMF_MASK));
+ /* prsn_cap = prsn_ie->rsn_ie + 2 bytes version + 4 bytes
+ * group_cipher_suite + 2 bytes pairwise_cipher_count +
+ * pairwise_cipher_count * PAIRWISE_CIPHER_SUITE_LEN + 2 bytes
+ * akm_suite_count + akm_suite_count * AKM_SUITE_LEN
+ */
+ ptr = (t_u16 *)(ptlv_rsn_ie->rsn_ie + sizeof(t_u16) + 4 * sizeof(t_u8));
+ pairwise_cipher_count = wlan_le16_to_cpu(*ptr);
+ ptr = (t_u16 *)(ptlv_rsn_ie->rsn_ie + sizeof(t_u16) + 4 * sizeof(t_u8) +
+ sizeof(t_u16) +
+ pairwise_cipher_count * PAIRWISE_CIPHER_SUITE_LEN);
+ temp_akm_suite_count = wlan_le16_to_cpu(*ptr);
+ akm_suite_count = wlan_le16_to_cpu(*ptr);
+ /* Save pointer to akm_suite_count in RSN IE to update it later */
+ akm_suite_count_ptr = ptr;
+ temp = ptlv_rsn_ie->rsn_ie + sizeof(t_u16) + 4 * sizeof(t_u8) +
+ sizeof(t_u16) +
+ pairwise_cipher_count * PAIRWISE_CIPHER_SUITE_LEN +
+ sizeof(t_u16);
+ /* ptr now points to the 1st AKM suite */
+ if (temp_akm_suite_count > 1) {
+ while (temp_akm_suite_count) {
+ if (pmpriv->sec_info.authentication_mode ==
+ MLAN_AUTH_MODE_SAE) {
+ if (!memcmp(pmadapter, temp, sae_oui,
+ AKM_SUITE_LEN)) {
+ found = 1;
+ break;
+ }
+ } else if (!memcmp(pmadapter, temp, sha_256_oui,
+ AKM_SUITE_LEN)) {
+ found = 1;
+ break;
+ }
+ temp += AKM_SUITE_LEN;
+ temp_akm_suite_count--;
+ }
+ if (found) {
+ /* Copy SHA256 as AKM suite */
+ memcpy_ext(pmadapter,
+ ptlv_rsn_ie->rsn_ie +
+ (sizeof(t_u16) + 4 * sizeof(t_u8) +
+ sizeof(t_u16) +
+ pairwise_cipher_count *
+ PAIRWISE_CIPHER_SUITE_LEN +
+ sizeof(t_u16)),
+ temp, AKM_SUITE_LEN, AKM_SUITE_LEN);
+ /* Shift remaining bytes of RSN IE after this */
+ memmove(pmadapter,
+ ptlv_rsn_ie->rsn_ie +
+ (sizeof(t_u16) + 4 * sizeof(t_u8) +
+ sizeof(t_u16) +
+ pairwise_cipher_count *
+ PAIRWISE_CIPHER_SUITE_LEN +
+ sizeof(t_u16) + AKM_SUITE_LEN),
+ ptlv_rsn_ie->rsn_ie +
+ (sizeof(t_u16) + 4 * sizeof(t_u8) +
+ sizeof(t_u16) +
+ pairwise_cipher_count *
+ PAIRWISE_CIPHER_SUITE_LEN +
+ sizeof(t_u16) +
+ akm_suite_count * AKM_SUITE_LEN),
+ ptlv_rsn_ie->header.len -
+ (sizeof(t_u16) + 4 * sizeof(t_u8) +
+ sizeof(t_u16) +
+ pairwise_cipher_count *
+ PAIRWISE_CIPHER_SUITE_LEN +
+ sizeof(t_u16) +
+ akm_suite_count * AKM_SUITE_LEN));
+ ptlv_rsn_ie->header.len =
+ ptlv_rsn_ie->header.len -
+ (akm_suite_count - 1) * AKM_SUITE_LEN;
+ /* Update akm suite count */
+ akm_suite_count = 1;
+ *akm_suite_count_ptr = akm_suite_count;
+ }
+ }
+ ptr = (t_u16 *)(ptlv_rsn_ie->rsn_ie + sizeof(t_u16) + 4 * sizeof(t_u8) +
+ sizeof(t_u16) +
+ pairwise_cipher_count * PAIRWISE_CIPHER_SUITE_LEN +
+ sizeof(t_u16) + akm_suite_count * AKM_SUITE_LEN);
+ prsn_cap = ptr;
+
+ ap_mfpc = ((*prsn_cap & (0x1 << MFPC_BIT)) == (0x1 << MFPC_BIT));
+ ap_mfpr = ((*prsn_cap & (0x1 << MFPR_BIT)) == (0x1 << MFPR_BIT));
+
+ if ((!ap_mfpc && !ap_mfpr && pmpriv->pmfcfg.mfpr) ||
+ ((!ap_mfpc) && ap_mfpr) ||
+ (ap_mfpc && ap_mfpr && (!pmpriv->pmfcfg.mfpc))) {
+ PRINTM(MERROR,
+ "Mismatch in PMF config of STA and AP, can't associate to AP\n");
+ return MLAN_STATUS_FAILURE;
+ }
+ if ((pmpriv->pmfcfg.mfpr && pmpriv->pmfcfg.mfpc) ||
+ pmpriv->pmfcfg.mfpc) {
+ *prsn_cap |= PMF_MASK;
+ *prsn_cap &= pmf_mask;
+ }
+
+ return ret;
+}
+
+/**
+ * @brief This function is to find FT AKM in RSN.
+ *
+ * @param pmpriv A pointer to mlan_private structure
+ *
+ * @param rsn_ie A pointer to rsn_ie
+ *
+ */
+t_u8 wlan_ft_akm_is_used(mlan_private *pmpriv, t_u8 *rsn_ie)
+{
+ t_u8 *temp;
+ t_u16 count;
+ t_u16 pairwise_cipher_count = 0;
+ t_u16 akm_suite_count = 0;
+ t_u8 found = 0;
+ t_u8 rsn_ft_1x_oui[4] = {0x00, 0x0f, 0xac, 0x03};
+ t_u8 rsn_ft_psk_oui[4] = {0x00, 0x0f, 0xac, 0x04};
+ t_u8 rsn_ft_sae_oui[4] = {0x00, 0x0f, 0xac, 0x09};
+ mlan_adapter *pmadapter = pmpriv->adapter;
+
+ ENTER();
+
+ if (!rsn_ie)
+ goto done;
+
+ if (rsn_ie[0] != RSN_IE)
+ goto done;
+
+ /* 2 bytes header + 2 bytes version + 4 bytes group_cipher_suite +
+ * 2 bytes pairwise_cipher_count + pairwise_cipher_count *
+ * PAIRWISE_CIPHER_SUITE_LEN (4) + 2 bytes akm_suite_count +
+ * akm_suite_count * AKM_SUITE_LEN (4)
+ */
+ count = *(t_u16 *)(rsn_ie + 2 + 2 + 4 * sizeof(t_u8));
+ pairwise_cipher_count = wlan_le16_to_cpu(count);
+ count = *(t_u16 *)(rsn_ie + 2 + 2 + 4 * sizeof(t_u8) + sizeof(t_u16) +
+ pairwise_cipher_count * 4);
+ akm_suite_count = wlan_le16_to_cpu(count);
+ temp = (t_u8 *)(rsn_ie + 2 + sizeof(t_u16) + 4 * sizeof(t_u8) +
+ sizeof(t_u16) + pairwise_cipher_count * 4 +
+ sizeof(t_u16));
+
+ while (akm_suite_count) {
+ if (!memcmp(pmadapter, temp, rsn_ft_1x_oui,
+ sizeof(rsn_ft_1x_oui)) ||
+ !memcmp(pmadapter, temp, rsn_ft_psk_oui,
+ sizeof(rsn_ft_psk_oui)) ||
+ !memcmp(pmadapter, temp, rsn_ft_sae_oui,
+ sizeof(rsn_ft_sae_oui))) {
+ found = 1;
+ break;
+ }
+ temp += 4;
+ akm_suite_count--;
+ }
+
+done:
+ LEAVE();
+ return found;
+}
+
+/**
+ * @brief This function is to find specific IE.
+ *
+ * @param ie A pointer to ie buffer
+ * @param ie_len Length of ie buffer
+ * @param ie_type Type of ie that wants to be found in ie buffer
+ *
+ * @return MFALSE if not found; MTURE if found
+ */
+t_u8 wlan_find_ie(t_u8 *ie, t_u8 ie_len, t_u8 ie_type)
+{
+ IEEEtypes_Header_t *pheader = MNULL;
+ t_u8 *pos = MNULL;
+ t_s8 ret_len;
+ t_u8 ret = MFALSE;
+
+ ENTER();
+
+ pos = (t_u8 *)ie;
+ ret_len = ie_len;
+ while (ret_len >= 2) {
+ pheader = (IEEEtypes_Header_t *)pos;
+ if (pheader->len + sizeof(IEEEtypes_Header_t) > ret_len) {
+ PRINTM(MMSG, "invalid IE length = %d left len %d\n",
+ pheader->len, ret_len);
+ break;
+ }
+ if (pheader->element_id == ie_type) {
+ ret = MTRUE;
+ break;
+ }
+ ret_len -= pheader->len + sizeof(IEEEtypes_Header_t);
+ pos += pheader->len + sizeof(IEEEtypes_Header_t);
+ }
+
+ LEAVE();
+ return ret;
+}
+
+/**
+ * @brief This function prepares command of association.
+ *
+ * @param pmpriv A pointer to mlan_private structure
+ * @param cmd A pointer to HostCmd_DS_COMMAND structure
+ * @param pdata_buf A pointer cast of BSSDescriptor_t from the
+ * scan table to assoc
+ *
+ * @return MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ */
+mlan_status wlan_cmd_802_11_associate(mlan_private *pmpriv,
+ HostCmd_DS_COMMAND *cmd,
+ t_void *pdata_buf)
+{
+ mlan_status ret = MLAN_STATUS_SUCCESS;
+ mlan_adapter *pmadapter = pmpriv->adapter;
+ HostCmd_DS_802_11_ASSOCIATE *passo = &cmd->params.associate;
+ BSSDescriptor_t *pbss_desc;
+ MrvlIEtypes_SsIdParamSet_t *pssid_tlv;
+ MrvlIEtypes_PhyParamSet_t *pphy_tlv;
+ MrvlIEtypes_SsParamSet_t *pss_tlv;
+ MrvlIEtypes_RatesParamSet_t *prates_tlv;
+ MrvlIEtypes_AuthType_t *pauth_tlv;
+ MrvlIEtypes_RsnParamSet_t *prsn_ie_tlv = MNULL;
+ MrvlIEtypes_SecurityCfg_t *psecurity_cfg_ie = MNULL;
+ MrvlIEtypes_ChanListParamSet_t *pchan_tlv;
+ WLAN_802_11_RATES rates;
+ t_u32 rates_size;
+ t_u16 tmp_cap;
+ t_u8 *pos;
+#ifdef DRV_EMBEDDED_SUPPLICANT
+ void *rsn_wpa_ie_tmp = MNULL;
+#endif
+ t_u8 ft_akm = 0;
+ t_u8 oper_class;
+ t_u8 oper_class_flag = MFALSE;
+ MrvlIEtypes_HostMlme_t *host_mlme_tlv = MNULL;
+
+ ENTER();
+
+ pbss_desc = (BSSDescriptor_t *)pdata_buf;
+ pos = (t_u8 *)passo;
+
+ cmd->command = wlan_cpu_to_le16(HostCmd_CMD_802_11_ASSOCIATE);
+
+ /* Save so we know which BSS Desc to use in the response handler */
+ pmpriv->pattempted_bss_desc = pbss_desc;
+ /* clear assoc_rsp_size */
+ pmpriv->assoc_rsp_size = 0;
+
+ memcpy_ext(pmadapter, passo->peer_sta_addr, pbss_desc->mac_address,
+ sizeof(pbss_desc->mac_address),
+ sizeof(passo->peer_sta_addr));
+ pos += sizeof(passo->peer_sta_addr);
+
+ /* Set the listen interval */
+ passo->listen_interval = wlan_cpu_to_le16(pmpriv->listen_interval);
+ /* Set the beacon period */
+ passo->beacon_period = wlan_cpu_to_le16(pbss_desc->beacon_period);
+
+ pos += sizeof(passo->cap_info);
+ pos += sizeof(passo->listen_interval);
+ pos += sizeof(passo->beacon_period);
+ pos += sizeof(passo->dtim_period);
+
+ pssid_tlv = (MrvlIEtypes_SsIdParamSet_t *)pos;
+ pssid_tlv->header.type = wlan_cpu_to_le16(TLV_TYPE_SSID);
+ pssid_tlv->header.len = (t_u16)pbss_desc->ssid.ssid_len;
+ memcpy_ext(pmadapter, pssid_tlv->ssid, pbss_desc->ssid.ssid,
+ pssid_tlv->header.len, pssid_tlv->header.len);
+ pos += sizeof(pssid_tlv->header) + pssid_tlv->header.len;
+ pssid_tlv->header.len = wlan_cpu_to_le16(pssid_tlv->header.len);
+
+ pphy_tlv = (MrvlIEtypes_PhyParamSet_t *)pos;
+ pphy_tlv->header.type = wlan_cpu_to_le16(TLV_TYPE_PHY_DS);
+ pphy_tlv->header.len = sizeof(pphy_tlv->fh_ds.ds_param_set);
+ memcpy_ext(pmadapter, &pphy_tlv->fh_ds.ds_param_set,
+ &pbss_desc->phy_param_set.ds_param_set.current_chan,
+ sizeof(pphy_tlv->fh_ds.ds_param_set),
+ sizeof(pphy_tlv->fh_ds.ds_param_set));
+ pos += sizeof(pphy_tlv->header) + pphy_tlv->header.len;
+ pphy_tlv->header.len = wlan_cpu_to_le16(pphy_tlv->header.len);
+
+ pss_tlv = (MrvlIEtypes_SsParamSet_t *)pos;
+ pss_tlv->header.type = wlan_cpu_to_le16(TLV_TYPE_CF);
+ pss_tlv->header.len = sizeof(pss_tlv->cf_ibss.cf_param_set);
+ pos += sizeof(pss_tlv->header) + pss_tlv->header.len;
+ pss_tlv->header.len = wlan_cpu_to_le16(pss_tlv->header.len);
+
+ /* Get the common rates supported between the driver and the BSS Desc */
+ if (wlan_setup_rates_from_bssdesc(pmpriv, pbss_desc, rates,
+ &rates_size)) {
+ ret = MLAN_STATUS_FAILURE;
+ goto done;
+ }
+
+ /* Save the data rates into Current BSS state structure */
+ pmpriv->curr_bss_params.num_of_rates = rates_size;
+ memcpy_ext(pmadapter, &pmpriv->curr_bss_params.data_rates, rates,
+ rates_size, WLAN_SUPPORTED_RATES);
+
+ /* Setup the Rates TLV in the association command */
+ prates_tlv = (MrvlIEtypes_RatesParamSet_t *)pos;
+ prates_tlv->header.type = wlan_cpu_to_le16(TLV_TYPE_RATES);
+ prates_tlv->header.len = wlan_cpu_to_le16((t_u16)rates_size);
+ memcpy_ext(pmadapter, prates_tlv->rates, rates, rates_size, rates_size);
+ pos += sizeof(prates_tlv->header) + rates_size;
+ PRINTM(MINFO, "ASSOC_CMD: Rates size = %d\n", rates_size);
+
+ /* Add the Authentication type to be used for Auth frames if needed */
+ if ((pmpriv->sec_info.authentication_mode != MLAN_AUTH_MODE_AUTO)) {
+ pauth_tlv = (MrvlIEtypes_AuthType_t *)pos;
+ pauth_tlv->header.type = wlan_cpu_to_le16(TLV_TYPE_AUTH_TYPE);
+ pauth_tlv->header.len = sizeof(pauth_tlv->auth_type);
+ if ((pmpriv->sec_info.wep_status == Wlan802_11WEPEnabled) ||
+ (pmpriv->sec_info.authentication_mode ==
+ MLAN_AUTH_MODE_NETWORKEAP))
+ pauth_tlv->auth_type = wlan_cpu_to_le16(
+ (t_u16)pmpriv->sec_info.authentication_mode);
+ else if (pmpriv->sec_info.authentication_mode ==
+ MLAN_AUTH_MODE_FT)
+ pauth_tlv->auth_type =
+ wlan_cpu_to_le16(AssocAgentAuth_FastBss_Skip);
+ else if (pmpriv->sec_info.authentication_mode ==
+ MLAN_AUTH_MODE_SAE)
+ pauth_tlv->auth_type =
+ wlan_cpu_to_le16(AssocAgentAuth_Wpa3Sae);
+ else
+ pauth_tlv->auth_type =
+ wlan_cpu_to_le16(MLAN_AUTH_MODE_OPEN);
+ pos += sizeof(pauth_tlv->header) + pauth_tlv->header.len;
+ pauth_tlv->header.len = wlan_cpu_to_le16(pauth_tlv->header.len);
+ }
+
+ if (IS_SUPPORT_MULTI_BANDS(pmadapter) &&
+ (pbss_desc->bss_band & pmpriv->config_bands) &&
+ !(ISSUPP_11NENABLED(pmadapter->fw_cap_info) &&
+ (!pbss_desc->disable_11n) &&
+ (pmpriv->config_bands & BAND_GN ||
+ pmpriv->config_bands & BAND_AN) &&
+ (pbss_desc->pht_cap))) {
+ /* Append a channel TLV for the channel the attempted AP was
+ * found on */
+ pchan_tlv = (MrvlIEtypes_ChanListParamSet_t *)pos;
+ pchan_tlv->header.type = wlan_cpu_to_le16(TLV_TYPE_CHANLIST);
+ pchan_tlv->header.len =
+ wlan_cpu_to_le16(sizeof(ChanScanParamSet_t));
+
+ memset(pmadapter, pchan_tlv->chan_scan_param, 0x00,
+ sizeof(ChanScanParamSet_t));
+ pchan_tlv->chan_scan_param[0].chan_number =
+ (pbss_desc->phy_param_set.ds_param_set.current_chan);
+ PRINTM(MINFO, "Assoc: TLV Chan = %d\n",
+ pchan_tlv->chan_scan_param[0].chan_number);
+
+ pchan_tlv->chan_scan_param[0].bandcfg.chanBand =
+ wlan_band_to_radio_type((t_u8)pbss_desc->bss_band);
+
+ PRINTM(MINFO, "Assoc: TLV Bandcfg = %x\n",
+ pchan_tlv->chan_scan_param[0].bandcfg);
+ pos += sizeof(pchan_tlv->header) + sizeof(ChanScanParamSet_t);
+ }
+ if (!pmpriv->wps.session_enable) {
+ if ((pmpriv->sec_info.wpa_enabled ||
+ pmpriv->sec_info.wpa2_enabled)) {
+ prsn_ie_tlv = (MrvlIEtypes_RsnParamSet_t *)pos;
+ /* WPA_IE or RSN_IE */
+ prsn_ie_tlv->header.type = (t_u16)pmpriv->wpa_ie[0];
+ prsn_ie_tlv->header.type =
+ prsn_ie_tlv->header.type & 0x00FF;
+ prsn_ie_tlv->header.type =
+ wlan_cpu_to_le16(prsn_ie_tlv->header.type);
+ prsn_ie_tlv->header.len = (t_u16)pmpriv->wpa_ie[1];
+ prsn_ie_tlv->header.len =
+ prsn_ie_tlv->header.len & 0x00FF;
+ if (prsn_ie_tlv->header.len <=
+ (sizeof(pmpriv->wpa_ie) - 2))
+ memcpy_ext(pmadapter, prsn_ie_tlv->rsn_ie,
+ &pmpriv->wpa_ie[2],
+ prsn_ie_tlv->header.len,
+ prsn_ie_tlv->header.len);
+ else {
+ ret = MLAN_STATUS_FAILURE;
+ goto done;
+ }
+ HEXDUMP("ASSOC_CMD: RSN IE", (t_u8 *)prsn_ie_tlv,
+ sizeof(prsn_ie_tlv->header) +
+ prsn_ie_tlv->header.len);
+ pos += sizeof(prsn_ie_tlv->header) +
+ prsn_ie_tlv->header.len;
+ prsn_ie_tlv->header.len =
+ wlan_cpu_to_le16(prsn_ie_tlv->header.len);
+ /** parse rsn ie to find whether ft akm is used*/
+ ft_akm = wlan_ft_akm_is_used(pmpriv, pmpriv->wpa_ie);
+ /* Append PMF Configuration coming from cfg80211 layer
+ */
+ psecurity_cfg_ie = (MrvlIEtypes_SecurityCfg_t *)pos;
+ psecurity_cfg_ie->header.type =
+ wlan_cpu_to_le16(TLV_TYPE_SECURITY_CFG);
+
+ pmpriv->curr_bss_params.use_mfp =
+ wlan_use_mfp(pmpriv, pbss_desc);
+ PRINTM(MCMND, "use_mfp=%d\n",
+ pmpriv->curr_bss_params.use_mfp);
+
+ if (!pmpriv->curr_bss_params.use_mfp)
+ psecurity_cfg_ie->use_mfp = MFALSE;
+ else
+ psecurity_cfg_ie->use_mfp = MTRUE;
+ psecurity_cfg_ie->header.len = sizeof(t_u8);
+ pos += sizeof(psecurity_cfg_ie->header) +
+ psecurity_cfg_ie->header.len;
+ }
+#ifdef DRV_EMBEDDED_SUPPLICANT
+ else if (supplicantIsEnabled(pmpriv->psapriv)) {
+ supplicantClrEncryptKey(pmpriv->psapriv);
+
+ if (pbss_desc->prsn_ie)
+ rsn_wpa_ie_tmp = pbss_desc->prsn_ie;
+ else if (pbss_desc->pwpa_ie)
+ rsn_wpa_ie_tmp = pbss_desc->pwpa_ie;
+ prsn_ie_tlv = (MrvlIEtypes_RsnParamSet_t *)pos;
+ pos += supplicantFormatRsnWpaTlv(
+ pmpriv->psapriv, rsn_wpa_ie_tmp, prsn_ie_tlv);
+ }
+#endif
+ else if (pmpriv->sec_info.ewpa_enabled) {
+ prsn_ie_tlv = (MrvlIEtypes_RsnParamSet_t *)pos;
+ if (pbss_desc->pwpa_ie) {
+ prsn_ie_tlv->header.type =
+ (t_u16)(*(pbss_desc->pwpa_ie))
+ .vend_hdr.element_id;
+ prsn_ie_tlv->header.type =
+ prsn_ie_tlv->header.type & 0x00FF;
+ prsn_ie_tlv->header.type = wlan_cpu_to_le16(
+ prsn_ie_tlv->header.type);
+ prsn_ie_tlv->header.len =
+ (t_u16)(*(pbss_desc->pwpa_ie))
+ .vend_hdr.len;
+ prsn_ie_tlv->header.len =
+ prsn_ie_tlv->header.len & 0x00FF;
+ if (prsn_ie_tlv->header.len <=
+ (sizeof(pmpriv->wpa_ie))) {
+ memcpy_ext(pmadapter,
+ prsn_ie_tlv->rsn_ie,
+ &((*(pbss_desc->pwpa_ie))
+ .vend_hdr.oui[0]),
+ prsn_ie_tlv->header.len,
+ prsn_ie_tlv->header.len);
+ } else {
+ ret = MLAN_STATUS_FAILURE;
+ goto done;
+ }
+
+ HEXDUMP("ASSOC_CMD: RSN IE",
+ (t_u8 *)prsn_ie_tlv,
+ sizeof(prsn_ie_tlv->header) +
+ prsn_ie_tlv->header.len);
+ pos += sizeof(prsn_ie_tlv->header) +
+ prsn_ie_tlv->header.len;
+ prsn_ie_tlv->header.len = wlan_cpu_to_le16(
+ prsn_ie_tlv->header.len);
+ }
+ if (pbss_desc->prsn_ie) {
+ prsn_ie_tlv = (MrvlIEtypes_RsnParamSet_t *)pos;
+ prsn_ie_tlv->header.type =
+ (t_u16)(*(pbss_desc->prsn_ie))
+ .ieee_hdr.element_id;
+ prsn_ie_tlv->header.type =
+ prsn_ie_tlv->header.type & 0x00FF;
+ prsn_ie_tlv->header.type = wlan_cpu_to_le16(
+ prsn_ie_tlv->header.type);
+ prsn_ie_tlv->header.len =
+ (t_u16)(*(pbss_desc->prsn_ie))
+ .ieee_hdr.len;
+ prsn_ie_tlv->header.len =
+ prsn_ie_tlv->header.len & 0x00FF;
+ if (prsn_ie_tlv->header.len <=
+ (sizeof(pmpriv->wpa_ie))) {
+ memcpy_ext(pmadapter,
+ prsn_ie_tlv->rsn_ie,
+ &((*(pbss_desc->prsn_ie))
+ .data[0]),
+ prsn_ie_tlv->header.len,
+ prsn_ie_tlv->header.len);
+ ret = wlan_update_rsn_ie(pmpriv,
+ prsn_ie_tlv);
+ if (ret != MLAN_STATUS_SUCCESS) {
+ goto done;
+ }
+ } else {
+ ret = MLAN_STATUS_FAILURE;
+ goto done;
+ }
+
+ HEXDUMP("ASSOC_CMD: RSN IE",
+ (t_u8 *)prsn_ie_tlv,
+ sizeof(prsn_ie_tlv->header) +
+ prsn_ie_tlv->header.len);
+ pos += sizeof(prsn_ie_tlv->header) +
+ prsn_ie_tlv->header.len;
+ prsn_ie_tlv->header.len = wlan_cpu_to_le16(
+ prsn_ie_tlv->header.len);
+ }
+ }
+ }
+
+ if (ISSUPP_11NENABLED(pmadapter->fw_cap_info) &&
+ (!pbss_desc->disable_11n) &&
+ wlan_11n_bandconfig_allowed(pmpriv, pbss_desc->bss_band))
+ wlan_cmd_append_11n_tlv(pmpriv, pbss_desc, &pos);
+ else if ((pmpriv->hotspot_cfg & HOTSPOT_ENABLED) &&
+ !(pmpriv->hotspot_cfg & HOTSPOT_BY_SUPPLICANT))
+ wlan_add_ext_capa_info_ie(pmpriv, pbss_desc, &pos);
+ if (pmpriv->adapter->ecsa_enable) {
+ oper_class_flag =
+ wlan_find_ie(pmpriv->gen_ie_buf, pmpriv->gen_ie_buf_len,
+ REGULATORY_CLASS);
+ if (!oper_class_flag) {
+ if (MLAN_STATUS_SUCCESS ==
+ wlan_get_curr_oper_class(
+ pmpriv,
+ pbss_desc->phy_param_set.ds_param_set
+ .current_chan,
+ pbss_desc->curr_bandwidth, &oper_class))
+ wlan_add_supported_oper_class_ie(pmpriv, &pos,
+ oper_class);
+ }
+ }
+ if (ISSUPP_11ACENABLED(pmadapter->fw_cap_info) &&
+ (!pbss_desc->disable_11n) &&
+ wlan_11ac_bandconfig_allowed(pmpriv, pbss_desc->bss_band))
+ wlan_cmd_append_11ac_tlv(pmpriv, pbss_desc, &pos);
+
+ if ((IS_FW_SUPPORT_11AX(pmadapter)) && (!pbss_desc->disable_11n) &&
+ wlan_11ax_bandconfig_allowed(pmpriv, pbss_desc->bss_band))
+ wlan_cmd_append_11ax_tlv(pmpriv, pbss_desc, &pos);
+
+ wlan_wmm_process_association_req(pmpriv, &pos, &pbss_desc->wmm_ie,
+ pbss_desc->pht_cap);
+ if (pmpriv->sec_info.wapi_enabled && pmpriv->wapi_ie_len)
+ wlan_cmd_append_wapi_ie(pmpriv, &pos);
+
+ if (pmpriv->sec_info.osen_enabled && pmpriv->osen_ie_len)
+ wlan_cmd_append_osen_ie(pmpriv, &pos);
+
+ wlan_cmd_append_generic_ie(pmpriv, &pos);
+
+ if (pbss_desc->pmd_ie)
+ wlan_cmd_append_pass_through_ie(
+ pmpriv, (IEEEtypes_Generic_t *)pbss_desc->pmd_ie, &pos);
+ wlan_cmd_append_tsf_tlv(pmpriv, &pos, pbss_desc);
+
+ if (pmpriv->curr_bss_params.host_mlme) {
+ host_mlme_tlv = (MrvlIEtypes_HostMlme_t *)pos;
+ host_mlme_tlv->header.type =
+ wlan_cpu_to_le16(TLV_TYPE_HOST_MLME);
+ host_mlme_tlv->header.len =
+ wlan_cpu_to_le16(sizeof(host_mlme_tlv->host_mlme));
+ host_mlme_tlv->host_mlme = MTRUE;
+ pos += sizeof(host_mlme_tlv->header) +
+ host_mlme_tlv->header.len;
+ }
+
+ if (wlan_11d_create_dnld_countryinfo(pmpriv,
+ (t_u8)pbss_desc->bss_band)) {
+ PRINTM(MERROR, "Dnld_countryinfo_11d failed\n");
+ ret = MLAN_STATUS_FAILURE;
+ goto done;
+ }
+ if (wlan_11d_parse_dnld_countryinfo(pmpriv,
+ pmpriv->pattempted_bss_desc)) {
+ ret = MLAN_STATUS_FAILURE;
+ goto done;
+ }
+
+ /*
+ * Call 11h join API after capability bits are set so adhoc/infra 11h
+ * behavior can be properly triggered. pos modified if data is appended
+ */
+ wlan_11h_process_join(
+ pmpriv, &pos, &passo->cap_info, (t_u8)pbss_desc->bss_band,
+ pbss_desc->phy_param_set.ds_param_set.current_chan,
+ &pbss_desc->wlan_11h_bss_info);
+
+ cmd->size = wlan_cpu_to_le16((t_u16)(pos - (t_u8 *)passo) + S_DS_GEN);
+
+ /* Set the Capability info at last */
+ memcpy_ext(pmadapter, &tmp_cap, &pbss_desc->cap_info,
+ sizeof(passo->cap_info), sizeof(tmp_cap));
+
+ if (pmpriv->config_bands == BAND_B)
+ SHORT_SLOT_TIME_DISABLED(tmp_cap);
+
+ tmp_cap &= CAPINFO_MASK;
+ PRINTM(MINFO, "ASSOC_CMD: tmp_cap=%4X CAPINFO_MASK=%4lX\n", tmp_cap,
+ CAPINFO_MASK);
+ tmp_cap = wlan_cpu_to_le16(tmp_cap);
+ memcpy_ext(pmadapter, &passo->cap_info, &tmp_cap, sizeof(tmp_cap),
+ sizeof(passo->cap_info));
+
+done:
+ LEAVE();
+ return ret;
+}
+
+/**
+ * @brief 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 for association |
+ * | 0xFFFE(-2): Authentication unhandled message |
+ * | 0xFFFD(-3): Authentication refused |
+ * | 0xFFFC(-4): Timeout waiting for AP response |
+ * | 0xFFFB(-5): Internal error for authentication |
+ * .------------------------------------------------------------.
+ * | status_code(t_u16): |
+ * | If cap_info is -1: |
+ * | An internal firmware failure prevented the |
+ * | command from being processed. The status code |
+ * | is 6 if associate response parameter invlaid, |
+ * | 1 otherwise. |
+ * | |
+ * | 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 |
+ * | |
+ * | If cap_info is -5: |
+ * | An internal firmware failure prevented the |
+ * | command from being processed. The status code |
+ * | is 6 if authentication parameter invlaid, |
+ * | 1 otherwise. |
+ * .------------------------------------------------------------.
+ * | 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).
+ *
+ * @param pmpriv A pointer to mlan_private structure
+ * @param resp A pointer to HostCmd_DS_COMMAND
+ * @param pioctl_buf A pointer to mlan_ioctl_req structure
+ *
+ * @return MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ */
+mlan_status wlan_ret_802_11_associate(mlan_private *pmpriv,
+ HostCmd_DS_COMMAND *resp,
+ t_void *pioctl_buf)
+{
+ mlan_status ret = MLAN_STATUS_SUCCESS;
+ mlan_ioctl_req *pioctl_req = (mlan_ioctl_req *)pioctl_buf;
+ IEEEtypes_AssocRsp_t *passoc_rsp;
+ BSSDescriptor_t *pbss_desc;
+ t_u8 enable_data = MTRUE;
+ t_u8 event_buf[100];
+ mlan_event *pevent = (mlan_event *)event_buf;
+ t_u8 cur_mac[MLAN_MAC_ADDR_LENGTH];
+ t_u8 media_connected = pmpriv->media_connected;
+ mlan_adapter *pmadapter = pmpriv->adapter;
+ assoc_logger_data *assoc_succ;
+ mlan_ds_bss *bss;
+
+ ENTER();
+
+ if (pmpriv->curr_bss_params.host_mlme)
+ passoc_rsp =
+ (IEEEtypes_AssocRsp_t *)((t_u8 *)(&resp->params) +
+ sizeof(IEEEtypes_MgmtHdr_t));
+ else
+
+ passoc_rsp = (IEEEtypes_AssocRsp_t *)&resp->params;
+ passoc_rsp->status_code = wlan_le16_to_cpu(passoc_rsp->status_code);
+ if (pmpriv->media_connected == MTRUE)
+ memcpy_ext(pmpriv->adapter, cur_mac,
+ pmpriv->curr_bss_params.bss_descriptor.mac_address,
+ MLAN_MAC_ADDR_LENGTH, MLAN_MAC_ADDR_LENGTH);
+
+ HEXDUMP("ASSOC_RESP:", (t_u8 *)&resp->params, (resp->size - S_DS_GEN));
+
+ pmpriv->assoc_rsp_size =
+ MIN(resp->size - S_DS_GEN, sizeof(pmpriv->assoc_rsp_buf));
+
+ memcpy_ext(pmpriv->adapter, pmpriv->assoc_rsp_buf, &resp->params,
+ pmpriv->assoc_rsp_size, pmpriv->assoc_rsp_size);
+
+ if (pioctl_req != MNULL) {
+ bss = (mlan_ds_bss *)pioctl_req->pbuf;
+ bss->param.ssid_bssid.assoc_rsp.assoc_resp_len =
+ pmpriv->assoc_rsp_size;
+ memcpy_ext(pmpriv->adapter,
+ bss->param.ssid_bssid.assoc_rsp.assoc_resp_buf,
+ pmpriv->assoc_rsp_buf, pmpriv->assoc_rsp_size,
+ ASSOC_RSP_BUF_SIZE);
+ }
+ if (passoc_rsp->status_code) {
+ if (pmpriv->media_connected == MTRUE) {
+ if (pmpriv->port_ctrl_mode == MTRUE)
+ pmpriv->port_open = pmpriv->prior_port_status;
+ if (!memcmp(pmpriv->adapter, cur_mac,
+ pmpriv->pattempted_bss_desc->mac_address,
+ MLAN_MAC_ADDR_LENGTH))
+ wlan_reset_connect_state(pmpriv, MTRUE);
+ else
+ wlan_recv_event(
+ pmpriv,
+ MLAN_EVENT_ID_DRV_ASSOC_FAILURE_REPORT,
+ MNULL);
+ } else
+ wlan_reset_connect_state(pmpriv, MTRUE);
+ pmpriv->adapter->dbg.num_cmd_assoc_failure++;
+ pmpriv->adapter->dbg.num_cons_assoc_failure++;
+ PRINTM(MERROR,
+ "ASSOC_RESP: Association Failed, "
+ "status code = %d, error = 0x%x, a_id = 0x%x\n",
+ passoc_rsp->status_code,
+ wlan_le16_to_cpu(*(t_u16 *)&passoc_rsp->capability),
+ wlan_le16_to_cpu(passoc_rsp->a_id));
+ memset(pmadapter, event_buf, 0, sizeof(event_buf));
+ pevent->bss_index = pmpriv->bss_index;
+ pevent->event_id = MLAN_EVENT_ID_DRV_ASSOC_FAILURE_LOGGER;
+ pevent->event_len = sizeof(passoc_rsp->status_code);
+ memcpy_ext(pmpriv->adapter, (t_u8 *)pevent->event_buf,
+ &passoc_rsp->status_code, pevent->event_len,
+ pevent->event_len);
+ wlan_recv_event(pmpriv, MLAN_EVENT_ID_DRV_ASSOC_FAILURE_LOGGER,
+ pevent);
+
+ ret = MLAN_STATUS_FAILURE;
+ goto done;
+ }
+
+ /* Send a Media Connected event, according to the Spec */
+ pmpriv->media_connected = MTRUE;
+
+ pmpriv->adapter->pps_uapsd_mode = MFALSE;
+ pmpriv->adapter->tx_lock_flag = MFALSE;
+ pmpriv->adapter->delay_null_pkt = MFALSE;
+
+ /* Set the attempted BSSID Index to current */
+ pbss_desc = pmpriv->pattempted_bss_desc;
+
+ PRINTM(MCMND, "ASSOC_RESP: %-32s (a_id = 0x%x)\n", pbss_desc->ssid.ssid,
+ wlan_le16_to_cpu(passoc_rsp->a_id));
+ /* Restore default extended capabilities */
+ memcpy_ext(pmpriv->adapter, &pmpriv->ext_cap, &pmpriv->def_ext_cap,
+ sizeof(pmpriv->ext_cap), sizeof(pmpriv->ext_cap));
+ /* Make a copy of current BSSID descriptor */
+ memcpy_ext(pmpriv->adapter, &pmpriv->curr_bss_params.bss_descriptor,
+ pbss_desc, sizeof(BSSDescriptor_t), sizeof(BSSDescriptor_t));
+
+ /* Update curr_bss_params */
+ pmpriv->curr_bss_params.bss_descriptor.channel =
+ pbss_desc->phy_param_set.ds_param_set.current_chan;
+
+ pmpriv->curr_bss_params.band = (t_u8)pbss_desc->bss_band;
+
+ /* Store current channel for further reference.
+ * This would save one extra call to get current
+ * channel when disconnect/bw_ch event is raised.
+ */
+ pmpriv->adapter->dfsr_channel =
+ pmpriv->curr_bss_params.bss_descriptor.channel;
+
+ /*
+ * Adjust the timestamps in the scan table to be relative to the newly
+ * associated AP's TSF
+ */
+ wlan_update_tsf_timestamps(pmpriv, pbss_desc);
+
+ if (pbss_desc->wmm_ie.vend_hdr.element_id == WMM_IE)
+ pmpriv->curr_bss_params.wmm_enabled = MTRUE;
+ else
+ pmpriv->curr_bss_params.wmm_enabled = MFALSE;
+
+ if ((pmpriv->wmm_required ||
+ (pbss_desc->pht_cap &&
+ (pbss_desc->pht_cap->ieee_hdr.element_id == HT_CAPABILITY))) &&
+ pmpriv->curr_bss_params.wmm_enabled)
+ pmpriv->wmm_enabled = MTRUE;
+ else
+ pmpriv->wmm_enabled = MFALSE;
+
+ pmpriv->curr_bss_params.wmm_uapsd_enabled = MFALSE;
+
+ if (pmpriv->wmm_enabled == MTRUE)
+ pmpriv->curr_bss_params.wmm_uapsd_enabled =
+ pbss_desc->wmm_ie.qos_info.qos_uapsd;
+
+ PRINTM(MINFO, "ASSOC_RESP: curr_pkt_filter is 0x%x\n",
+ pmpriv->curr_pkt_filter);
+ if (pmpriv->sec_info.wpa_enabled || pmpriv->sec_info.wpa2_enabled)
+ pmpriv->wpa_is_gtk_set = MFALSE;
+ if (pmpriv->wmm_enabled)
+ /* Don't re-enable carrier until we get the WMM_GET_STATUS event
+ */
+ enable_data = MFALSE;
+ else
+ /* Since WMM is not enabled, setup the queues with the defaults
+ */
+ wlan_wmm_setup_queues(pmpriv);
+
+ if (enable_data)
+ PRINTM(MINFO, "Post association, re-enabling data flow\n");
+
+ /* Reset SNR/NF/RSSI values */
+ pmpriv->data_rssi_last = 0;
+ pmpriv->data_nf_last = 0;
+ pmpriv->data_rssi_avg = 0;
+ pmpriv->data_nf_avg = 0;
+ pmpriv->bcn_rssi_last = 0;
+ pmpriv->bcn_nf_last = 0;
+ pmpriv->bcn_rssi_avg = 0;
+ pmpriv->bcn_nf_avg = 0;
+ pmpriv->rxpd_rate = 0;
+ pmpriv->rxpd_rate_info = 0;
+ /* Reset mib statistics*/
+ pmpriv->amsdu_rx_cnt = 0;
+ pmpriv->amsdu_tx_cnt = 0;
+ pmpriv->msdu_in_rx_amsdu_cnt = 0;
+ pmpriv->msdu_in_tx_amsdu_cnt = 0;
+ if (pbss_desc->pvht_cap && pbss_desc->pht_cap) {
+ if (GET_VHTCAP_MAXMPDULEN(
+ pbss_desc->pvht_cap->vht_cap.vht_cap_info) == 2)
+ pmpriv->max_amsdu = MLAN_TX_DATA_BUF_SIZE_12K;
+ else if (GET_VHTCAP_MAXMPDULEN(
+ pbss_desc->pvht_cap->vht_cap.vht_cap_info) ==
+ 1)
+ pmpriv->max_amsdu = MLAN_TX_DATA_BUF_SIZE_8K;
+ else
+ pmpriv->max_amsdu = MLAN_TX_DATA_BUF_SIZE_4K;
+ } else if (pbss_desc->pht_cap) {
+ if (GETHT_MAXAMSDU(pbss_desc->pht_cap->ht_cap.ht_cap_info))
+ pmpriv->max_amsdu = MLAN_TX_DATA_BUF_SIZE_8K;
+ else
+ pmpriv->max_amsdu = MLAN_TX_DATA_BUF_SIZE_4K;
+ }
+
+ wlan_save_curr_bcn(pmpriv);
+
+ pmpriv->adapter->dbg.num_cmd_assoc_success++;
+ pmpriv->adapter->dbg.num_cons_assoc_failure = 0;
+ PRINTM(MINFO, "ASSOC_RESP: Associated\n");
+ pevent->bss_index = pmpriv->bss_index;
+ pevent->event_id = MLAN_EVENT_ID_DRV_CONNECTED;
+ pevent->event_len = MLAN_MAC_ADDR_LENGTH;
+ memcpy_ext(pmpriv->adapter, (t_u8 *)pevent->event_buf,
+ (t_u8 *)pmpriv->curr_bss_params.bss_descriptor.mac_address,
+ MLAN_MAC_ADDR_LENGTH, pevent->event_len);
+
+ /* Add the ra_list here for infra mode as there will be only 1 ra always
+ */
+ if (media_connected) {
+ /** replace ralist's mac address with new mac address */
+ if (0 ==
+ wlan_ralist_update(
+ pmpriv, cur_mac,
+ pmpriv->curr_bss_params.bss_descriptor.mac_address))
+ wlan_ralist_add(pmpriv,
+ pmpriv->curr_bss_params.bss_descriptor
+ .mac_address);
+ wlan_11n_cleanup_reorder_tbl(pmpriv);
+ wlan_11n_deleteall_txbastream_tbl(pmpriv);
+
+ } else
+ wlan_ralist_add(
+ pmpriv,
+ pmpriv->curr_bss_params.bss_descriptor.mac_address);
+
+ wlan_recv_event(pmpriv, MLAN_EVENT_ID_DRV_CONNECTED, pevent);
+
+ /* Send OBSS scan param to the application if available */
+ wlan_2040_coex_event(pmpriv);
+ wlan_coex_ampdu_rxwinsize(pmpriv->adapter);
+
+ if (!pmpriv->sec_info.wpa_enabled && !pmpriv->sec_info.wpa2_enabled &&
+ !pmpriv->sec_info.ewpa_enabled && !pmpriv->sec_info.wapi_enabled &&
+ !pmpriv->wps.session_enable && !pmpriv->sec_info.osen_enabled
+#ifdef DRV_EMBEDDED_SUPPLICANT
+ && !supplicantIsEnabled(pmpriv->psapriv)
+#endif
+ ) {
+ /* We are in Open/WEP mode, open port immediately */
+ if (pmpriv->port_ctrl_mode == MTRUE) {
+ pmpriv->port_open = MTRUE;
+ PRINTM(MINFO, "ASSOC_RESP: port_status = OPEN\n");
+ }
+ }
+ if (pmpriv->sec_info.wpa_enabled || pmpriv->sec_info.wpa2_enabled ||
+ pmpriv->sec_info.ewpa_enabled || pmpriv->sec_info.wapi_enabled ||
+ pmpriv->wps.session_enable || pmpriv->sec_info.osen_enabled
+#ifdef DRV_EMBEDDED_SUPPLICANT
+ || (supplicantIsEnabled(pmpriv->psapriv))
+#endif
+ )
+ pmpriv->adapter->scan_block = MTRUE;
+
+#ifdef DRV_EMBEDDED_SUPPLICANT
+ supplicantInitSession(
+ pmpriv->psapriv,
+ (t_u8 *)&pmpriv->curr_bss_params.bss_descriptor.ssid.ssid,
+ pmpriv->curr_bss_params.bss_descriptor.ssid.ssid_len,
+ (t_u8 *)&pmpriv->curr_bss_params.bss_descriptor.mac_address,
+ (t_u8 *)&pmpriv->curr_addr);
+#endif
+
+ pevent = (mlan_event *)event_buf;
+ memset(pmadapter, event_buf, 0, sizeof(event_buf));
+ pevent->bss_index = pmpriv->bss_index;
+ pevent->event_id = MLAN_EVENT_ID_DRV_ASSOC_SUCC_LOGGER;
+ pevent->event_len = sizeof(assoc_logger_data);
+ assoc_succ = (assoc_logger_data *)pevent->event_buf;
+ memcpy_ext(pmpriv->adapter, (t_u8 *)assoc_succ->bssid,
+ pbss_desc->mac_address, MLAN_MAC_ADDR_LENGTH,
+ MLAN_MAC_ADDR_LENGTH);
+ memcpy_ext(pmpriv->adapter, (t_u8 *)assoc_succ->oui,
+ pbss_desc->mac_address, MLAN_MAC_ADDR_LENGTH / 2,
+ MLAN_MAC_ADDR_LENGTH / 2);
+ memcpy_ext(pmpriv->adapter, (t_u8 *)assoc_succ->ssid,
+ pbss_desc->ssid.ssid, pbss_desc->ssid.ssid_len,
+ MLAN_MAX_SSID_LENGTH);
+ assoc_succ->rssi = pbss_desc->rssi;
+ assoc_succ->channel = pbss_desc->channel;
+ wlan_recv_event(pmpriv, MLAN_EVENT_ID_DRV_ASSOC_SUCC_LOGGER, pevent);
+
+done:
+ /* Need to indicate IOCTL complete */
+ if (pioctl_req != MNULL) {
+ if (ret != MLAN_STATUS_SUCCESS) {
+ if (passoc_rsp->status_code)
+ pioctl_req->status_code =
+ (wlan_le16_to_cpu(*(t_u16 *)&passoc_rsp
+ ->capability)
+ << 16) +
+ passoc_rsp->status_code;
+ else
+ pioctl_req->status_code =
+ MLAN_ERROR_CMD_ASSOC_FAIL;
+ } else {
+ pioctl_req->status_code = MLAN_ERROR_NO_ERROR;
+ }
+ }
+
+ LEAVE();
+ return ret;
+}
+
+/**
+ * @brief This function prepares command of ad_hoc_start.
+ *
+ * @param pmpriv A pointer to mlan_private structure
+ * @param cmd A pointer to HostCmd_DS_COMMAND structure
+ * @param pdata_buf A pointer cast of mlan_802_11_ssid structure
+ *
+ * @return MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ */
+mlan_status wlan_cmd_802_11_ad_hoc_start(mlan_private *pmpriv,
+ HostCmd_DS_COMMAND *cmd,
+ t_void *pdata_buf)
+{
+ mlan_status ret = MLAN_STATUS_SUCCESS;
+ mlan_adapter *pmadapter = pmpriv->adapter;
+ HostCmd_DS_802_11_AD_HOC_START *padhoc_start = &cmd->params.adhoc_start;
+ BSSDescriptor_t *pbss_desc;
+ t_u32 cmd_append_size = 0;
+ t_u32 i;
+ t_u16 tmp_cap;
+ MrvlIEtypes_ChanListParamSet_t *pchan_tlv;
+
+ MrvlIEtypes_RsnParamSet_t *prsn_ie_tlv;
+ /* wpa ie for WPA_NONE AES */
+ const t_u8 wpa_ie[24] = {0xdd, 0x16, 0x00, 0x50, 0xf2, 0x01,
+ 0x01, 0x00, 0x00, 0x50, 0xf2, 0x04,
+ 0x01, 0x00, 0x00, 0x50, 0xf2, 0x00,
+ 0x01, 0x00, 0x00, 0x50, 0xf2, 0x00};
+ t_s32 append_size_11h = 0;
+ t_u8 *pos =
+ (t_u8 *)padhoc_start + sizeof(HostCmd_DS_802_11_AD_HOC_START);
+
+ ENTER();
+
+ if (!pmadapter) {
+ ret = MLAN_STATUS_FAILURE;
+ goto done;
+ }
+
+ cmd->command = wlan_cpu_to_le16(HostCmd_CMD_802_11_AD_HOC_START);
+
+ pbss_desc = &pmpriv->curr_bss_params.bss_descriptor;
+ pmpriv->pattempted_bss_desc = pbss_desc;
+
+ /*
+ * Fill in the parameters for 2 data structures:
+ * 1. HostCmd_DS_802_11_AD_HOC_START command
+ * 2. pbss_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(pmadapter, padhoc_start->ssid, 0, MLAN_MAX_SSID_LENGTH);
+
+ memcpy_ext(pmadapter, padhoc_start->ssid,
+ ((mlan_802_11_ssid *)pdata_buf)->ssid,
+ ((mlan_802_11_ssid *)pdata_buf)->ssid_len,
+ MLAN_MAX_SSID_LENGTH);
+
+ PRINTM(MINFO, "ADHOC_S_CMD: SSID = %s\n", padhoc_start->ssid);
+
+ memset(pmadapter, pbss_desc->ssid.ssid, 0, MLAN_MAX_SSID_LENGTH);
+ memcpy_ext(pmadapter, pbss_desc->ssid.ssid,
+ ((mlan_802_11_ssid *)pdata_buf)->ssid,
+ ((mlan_802_11_ssid *)pdata_buf)->ssid_len,
+ MLAN_MAX_SSID_LENGTH);
+
+ pbss_desc->ssid.ssid_len =
+ MIN(MLAN_MAX_SSID_LENGTH,
+ ((mlan_802_11_ssid *)pdata_buf)->ssid_len);
+
+ /* Set the BSS mode */
+ padhoc_start->bss_mode = HostCmd_BSS_MODE_IBSS;
+ pbss_desc->bss_mode = MLAN_BSS_MODE_IBSS;
+ padhoc_start->beacon_period = wlan_cpu_to_le16(pmpriv->beacon_period);
+ pbss_desc->beacon_period = pmpriv->beacon_period;
+
+ /* Set Physical param set */
+/** Parameter IE Id */
+#define DS_PARA_IE_ID 3
+/** Parameter IE length */
+#define DS_PARA_IE_LEN 1
+
+ padhoc_start->phy_param_set.ds_param_set.element_id = DS_PARA_IE_ID;
+ padhoc_start->phy_param_set.ds_param_set.len = DS_PARA_IE_LEN;
+
+ if (!wlan_get_cfp_by_band_and_channel(
+ pmadapter, pmadapter->adhoc_start_band,
+ (t_u16)pmpriv->adhoc_channel, pmadapter->region_channel)) {
+ chan_freq_power_t *cfp;
+ cfp = wlan_get_cfp_by_band_and_channel(
+ pmadapter, pmadapter->adhoc_start_band,
+ FIRST_VALID_CHANNEL, pmadapter->region_channel);
+ if (cfp)
+ pmpriv->adhoc_channel = (t_u8)cfp->channel;
+ }
+
+ MASSERT(pmpriv->adhoc_channel);
+
+ PRINTM(MINFO, "ADHOC_S_CMD: Creating ADHOC on Channel %d\n",
+ pmpriv->adhoc_channel);
+
+ pmpriv->curr_bss_params.bss_descriptor.channel = pmpriv->adhoc_channel;
+ pmpriv->curr_bss_params.band = pmadapter->adhoc_start_band;
+
+ pbss_desc->channel = pmpriv->adhoc_channel;
+ padhoc_start->phy_param_set.ds_param_set.current_chan =
+ pmpriv->adhoc_channel;
+
+ memcpy_ext(pmadapter, &pbss_desc->phy_param_set,
+ &padhoc_start->phy_param_set,
+ sizeof(IEEEtypes_PhyParamSet_t),
+ sizeof(IEEEtypes_PhyParamSet_t));
+
+ pbss_desc->network_type_use = Wlan802_11DS;
+
+ /* Set IBSS param set */
+/** IBSS parameter IE Id */
+#define IBSS_PARA_IE_ID 6
+/** IBSS parameter IE length */
+#define IBSS_PARA_IE_LEN 2
+
+ padhoc_start->ss_param_set.ibss_param_set.element_id = IBSS_PARA_IE_ID;
+ padhoc_start->ss_param_set.ibss_param_set.len = IBSS_PARA_IE_LEN;
+ padhoc_start->ss_param_set.ibss_param_set.atim_window =
+ wlan_cpu_to_le16(pmpriv->atim_window);
+ pbss_desc->atim_window = pmpriv->atim_window;
+ memcpy_ext(pmadapter, &pbss_desc->ss_param_set,
+ &padhoc_start->ss_param_set, sizeof(IEEEtypes_SsParamSet_t),
+ sizeof(IEEEtypes_SsParamSet_t));
+
+ /* Set Capability info */
+ padhoc_start->cap.ess = 0;
+ padhoc_start->cap.ibss = 1;
+ pbss_desc->cap_info.ibss = 1;
+
+ /* Set up privacy in pbss_desc */
+ if (pmpriv->sec_info.wep_status == Wlan802_11WEPEnabled ||
+ pmpriv->sec_info.wpa_enabled || pmpriv->sec_info.ewpa_enabled) {
+/** Ad-Hoc capability privacy on */
+#define AD_HOC_CAP_PRIVACY_ON 1
+ PRINTM(MINFO, "ADHOC_S_CMD: wep_status set, Privacy to WEP\n");
+ pbss_desc->privacy = Wlan802_11PrivFilter8021xWEP;
+ padhoc_start->cap.privacy = AD_HOC_CAP_PRIVACY_ON;
+ } else {
+ PRINTM(MWARN, "ADHOC_S_CMD: wep_status NOT set, Setting "
+ "Privacy to ACCEPT ALL\n");
+ pbss_desc->privacy = Wlan802_11PrivFilterAcceptAll;
+ }
+
+ memset(pmadapter, padhoc_start->DataRate, 0,
+ sizeof(padhoc_start->DataRate));
+
+ if ((pmpriv->adapter->region_code == COUNTRY_CODE_JP_40 ||
+ pmpriv->adapter->region_code == COUNTRY_CODE_JP_FF) &&
+ (pbss_desc->phy_param_set.ds_param_set.current_chan == 14)) {
+ wlan_get_active_data_rates(pmpriv, pmpriv->bss_mode, BAND_B,
+ padhoc_start->DataRate);
+ } else {
+ wlan_get_active_data_rates(pmpriv, pmpriv->bss_mode,
+ pmadapter->adhoc_start_band,
+ padhoc_start->DataRate);
+ }
+
+ if ((pmadapter->adhoc_start_band & BAND_G) &&
+ (pmpriv->curr_pkt_filter & HostCmd_ACT_MAC_ADHOC_G_PROTECTION_ON)) {
+ ret = wlan_prepare_cmd(pmpriv, HostCmd_CMD_MAC_CONTROL,
+ HostCmd_ACT_GEN_SET, 0, MNULL,
+ &pmpriv->curr_pkt_filter);
+
+ if (ret) {
+ PRINTM(MERROR,
+ "ADHOC_S_CMD: G Protection config failed\n");
+ ret = MLAN_STATUS_FAILURE;
+ goto done;
+ }
+ }
+ /* Find the last non zero */
+ for (i = 0;
+ i < sizeof(padhoc_start->DataRate) && padhoc_start->DataRate[i];
+ i++)
+ /* XXX Do not delete no-operation line */
+ ;
+
+ pmpriv->curr_bss_params.num_of_rates = i;
+
+ /* Copy the ad-hoc creating rates into Current BSS rate structure */
+ memcpy_ext(pmadapter, &pmpriv->curr_bss_params.data_rates,
+ &padhoc_start->DataRate,
+ pmpriv->curr_bss_params.num_of_rates, WLAN_SUPPORTED_RATES);
+
+ PRINTM(MINFO, "ADHOC_S_CMD: Rates=%02x %02x %02x %02x\n",
+ padhoc_start->DataRate[0], padhoc_start->DataRate[1],
+ padhoc_start->DataRate[2], padhoc_start->DataRate[3]);
+
+ PRINTM(MINFO, "ADHOC_S_CMD: AD HOC Start command is ready\n");
+
+ if (IS_SUPPORT_MULTI_BANDS(pmadapter)) {
+ /* Append a channel TLV */
+ pchan_tlv = (MrvlIEtypes_ChanListParamSet_t *)pos;
+ pchan_tlv->header.type = wlan_cpu_to_le16(TLV_TYPE_CHANLIST);
+ pchan_tlv->header.len =
+ wlan_cpu_to_le16(sizeof(ChanScanParamSet_t));
+
+ memset(pmadapter, pchan_tlv->chan_scan_param, 0x00,
+ sizeof(ChanScanParamSet_t));
+ pchan_tlv->chan_scan_param[0].chan_number =
+ (t_u8)pmpriv->curr_bss_params.bss_descriptor.channel;
+
+ PRINTM(MINFO, "ADHOC_S_CMD: TLV Chan = %d\n",
+ pchan_tlv->chan_scan_param[0].chan_number);
+
+ pchan_tlv->chan_scan_param[0].bandcfg.chanBand =
+ wlan_band_to_radio_type(pmpriv->curr_bss_params.band);
+ PRINTM(MINFO, "ADHOC_S_CMD: TLV Bandcfg = %x\n",
+ pchan_tlv->chan_scan_param[0].bandcfg);
+ pos += sizeof(pchan_tlv->header) + sizeof(ChanScanParamSet_t);
+ cmd_append_size +=
+ sizeof(pchan_tlv->header) + sizeof(ChanScanParamSet_t);
+ }
+
+ if (wlan_11d_create_dnld_countryinfo(pmpriv,
+ pmpriv->curr_bss_params.band)) {
+ PRINTM(MERROR, "ADHOC_S_CMD: dnld_countryinfo_11d failed\n");
+ ret = MLAN_STATUS_FAILURE;
+ goto done;
+ }
+
+ /*
+ * Call 11h start API to add any 11h flags/elements as TLV parameters
+ */
+ append_size_11h =
+ wlan_11h_process_start(pmpriv, &pos, &padhoc_start->cap,
+ pmpriv->adhoc_channel,
+ &pbss_desc->wlan_11h_bss_info);
+ if (append_size_11h >= 0)
+ cmd_append_size += append_size_11h;
+ else {
+ ret = MLAN_STATUS_FAILURE;
+ goto done;
+ }
+
+ if (pmpriv->sec_info.ewpa_enabled) {
+ memcpy_ext(pmadapter, pmpriv->wpa_ie, wpa_ie, sizeof(wpa_ie),
+ sizeof(pmpriv->wpa_ie));
+ pmpriv->wpa_ie_len = sizeof(wpa_ie);
+ }
+
+ if (pmpriv->sec_info.wpa_enabled || pmpriv->sec_info.ewpa_enabled) {
+ prsn_ie_tlv = (MrvlIEtypes_RsnParamSet_t *)pos;
+ prsn_ie_tlv->header.type = (t_u16)pmpriv->wpa_ie[0];
+ /* WPA_IE or RSN_IE */
+ prsn_ie_tlv->header.type = prsn_ie_tlv->header.type & 0x00FF;
+ prsn_ie_tlv->header.type =
+ wlan_cpu_to_le16(prsn_ie_tlv->header.type);
+ prsn_ie_tlv->header.len = (t_u16)pmpriv->wpa_ie[1];
+ prsn_ie_tlv->header.len = prsn_ie_tlv->header.len & 0x00FF;
+ if (prsn_ie_tlv->header.len <= (sizeof(pmpriv->wpa_ie) - 2))
+ memcpy_ext(pmadapter, prsn_ie_tlv->rsn_ie,
+ &pmpriv->wpa_ie[2], prsn_ie_tlv->header.len,
+ prsn_ie_tlv->header.len);
+ else {
+ ret = MLAN_STATUS_FAILURE;
+ goto done;
+ }
+
+ DBG_HEXDUMP(MCMD_D, "ADHOC_S_CMD: RSN IE", (t_u8 *)prsn_ie_tlv,
+ sizeof(prsn_ie_tlv->header) +
+ prsn_ie_tlv->header.len);
+ pos += sizeof(prsn_ie_tlv->header) + prsn_ie_tlv->header.len;
+ cmd_append_size +=
+ sizeof(prsn_ie_tlv->header) + prsn_ie_tlv->header.len;
+ prsn_ie_tlv->header.len =
+ wlan_cpu_to_le16(prsn_ie_tlv->header.len);
+ }
+
+ cmd->size = (t_u16)wlan_cpu_to_le16(
+ (t_u16)(sizeof(HostCmd_DS_802_11_AD_HOC_START) + S_DS_GEN +
+ cmd_append_size));
+
+ memcpy_ext(pmadapter, &tmp_cap, &padhoc_start->cap, sizeof(t_u16),
+ sizeof(tmp_cap));
+
+ if (pmadapter->adhoc_start_band == BAND_B)
+ SHORT_SLOT_TIME_DISABLED(tmp_cap);
+ else
+ SHORT_SLOT_TIME_ENABLED(tmp_cap);
+
+ tmp_cap = wlan_cpu_to_le16(tmp_cap);
+ memcpy_ext(pmadapter, &padhoc_start->cap, &tmp_cap, sizeof(t_u16),
+ sizeof(padhoc_start->cap));
+
+ ret = MLAN_STATUS_SUCCESS;
+done:
+ LEAVE();
+ return ret;
+}
+
+/**
+ * @brief This function prepares command of ad_hoc_join.
+ *
+ * @param pmpriv A pointer to mlan_private structure
+ * @param cmd A pointer to HostCmd_DS_COMMAND structure
+ * @param pdata_buf Void cast of BSSDescriptor_t from the
+ * scan table to join
+ *
+ * @return MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ */
+mlan_status wlan_cmd_802_11_ad_hoc_join(mlan_private *pmpriv,
+ HostCmd_DS_COMMAND *cmd,
+ t_void *pdata_buf)
+{
+ mlan_status ret = MLAN_STATUS_SUCCESS;
+ mlan_adapter *pmadapter = pmpriv->adapter;
+ HostCmd_DS_802_11_AD_HOC_JOIN *padhoc_join = &cmd->params.adhoc_join;
+ BSSDescriptor_t *pbss_desc = (BSSDescriptor_t *)pdata_buf;
+ MrvlIEtypes_ChanListParamSet_t *pchan_tlv;
+ MrvlIEtypes_RsnParamSet_t *prsn_ie_tlv;
+ t_u32 cmd_append_size = 0;
+ t_u16 tmp_cap;
+ t_u32 i, rates_size = 0;
+ t_u32 curr_pkt_filter;
+ t_u8 *pos = (t_u8 *)padhoc_join + sizeof(HostCmd_DS_802_11_AD_HOC_JOIN);
+
+ ENTER();
+
+/** Use G protection */
+#define USE_G_PROTECTION 0x02
+ if (pbss_desc->erp_flags & USE_G_PROTECTION) {
+ curr_pkt_filter = pmpriv->curr_pkt_filter |
+ HostCmd_ACT_MAC_ADHOC_G_PROTECTION_ON;
+
+ ret = wlan_prepare_cmd(pmpriv, HostCmd_CMD_MAC_CONTROL,
+ HostCmd_ACT_GEN_SET, 0, MNULL,
+ &curr_pkt_filter);
+ if (ret) {
+ PRINTM(MERROR,
+ "ADHOC_J_CMD: G Protection config failed\n");
+ ret = MLAN_STATUS_FAILURE;
+ goto done;
+ }
+ }
+
+ pmpriv->pattempted_bss_desc = pbss_desc;
+
+ cmd->command = wlan_cpu_to_le16(HostCmd_CMD_802_11_AD_HOC_JOIN);
+
+ padhoc_join->bss_descriptor.bss_mode = HostCmd_BSS_MODE_IBSS;
+
+ padhoc_join->bss_descriptor.beacon_period =
+ wlan_cpu_to_le16(pbss_desc->beacon_period);
+
+ memcpy_ext(pmadapter, &padhoc_join->bss_descriptor.bssid,
+ &pbss_desc->mac_address, MLAN_MAC_ADDR_LENGTH,
+ MLAN_MAC_ADDR_LENGTH);
+
+ memcpy_ext(pmadapter, &padhoc_join->bss_descriptor.ssid,
+ &pbss_desc->ssid.ssid, pbss_desc->ssid.ssid_len,
+ MLAN_MAX_SSID_LENGTH);
+
+ memcpy_ext(pmadapter, &padhoc_join->bss_descriptor.phy_param_set,
+ &pbss_desc->phy_param_set, sizeof(IEEEtypes_PhyParamSet_t),
+ sizeof(IEEEtypes_PhyParamSet_t));
+
+ padhoc_join->bss_descriptor.phy_param_set.fh_param_set.dwell_time =
+ wlan_cpu_to_le16(padhoc_join->bss_descriptor.phy_param_set
+ .fh_param_set.dwell_time);
+
+ memcpy_ext(pmadapter, &padhoc_join->bss_descriptor.ss_param_set,
+ &pbss_desc->ss_param_set, sizeof(IEEEtypes_SsParamSet_t),
+ sizeof(IEEEtypes_SsParamSet_t));
+ padhoc_join->bss_descriptor.ss_param_set.ibss_param_set.atim_window = 0;
+ padhoc_join->bss_descriptor.ss_param_set.ibss_param_set.atim_window =
+ wlan_cpu_to_le16(padhoc_join->bss_descriptor.ss_param_set
+ .ibss_param_set.atim_window);
+
+ memcpy_ext(pmadapter, &tmp_cap, &pbss_desc->cap_info,
+ sizeof(IEEEtypes_CapInfo_t), sizeof(IEEEtypes_CapInfo_t));
+
+ tmp_cap &= CAPINFO_MASK;
+
+ PRINTM(MINFO, "ADHOC_J_CMD: tmp_cap=%4X CAPINFO_MASK=%4lX\n", tmp_cap,
+ CAPINFO_MASK);
+ memcpy_ext(pmadapter, &padhoc_join->bss_descriptor.cap, &tmp_cap,
+ sizeof(IEEEtypes_CapInfo_t), sizeof(IEEEtypes_CapInfo_t));
+
+ /* Information on BSSID descriptor passed to FW */
+ PRINTM(MINFO, "ADHOC_J_CMD: BSSID = " MACSTR ", SSID = %s\n",
+ MAC2STR(padhoc_join->bss_descriptor.bssid),
+ padhoc_join->bss_descriptor.ssid);
+
+ for (i = 0; i < WLAN_SUPPORTED_RATES && pbss_desc->supported_rates[i];
+ i++)
+ /* XXX Do not delete no-operation line */
+ ;
+ rates_size = i;
+
+ /* Copy Data Rates from the Rates recorded in scan response */
+ memset(pmadapter, padhoc_join->bss_descriptor.data_rates, 0,
+ sizeof(padhoc_join->bss_descriptor.data_rates));
+ memcpy_ext(pmadapter, padhoc_join->bss_descriptor.data_rates,
+ pbss_desc->supported_rates, rates_size,
+ WLAN_SUPPORTED_RATES);
+
+ HEXDUMP("Adapted Rates:", padhoc_join->bss_descriptor.data_rates,
+ rates_size);
+
+ /* Copy the adhoc join rates into Current BSS state structure */
+ pmpriv->curr_bss_params.num_of_rates = rates_size;
+ memcpy_ext(pmadapter, &pmpriv->curr_bss_params.data_rates,
+ pbss_desc->supported_rates, rates_size,
+ WLAN_SUPPORTED_RATES);
+
+ /* Copy the channel information */
+ pmpriv->curr_bss_params.bss_descriptor.channel = pbss_desc->channel;
+ pmpriv->curr_bss_params.band = (t_u8)pbss_desc->bss_band;
+
+ if (pmpriv->sec_info.wep_status == Wlan802_11WEPEnabled ||
+ pmpriv->sec_info.wpa_enabled || pmpriv->sec_info.ewpa_enabled)
+ padhoc_join->bss_descriptor.cap.privacy = AD_HOC_CAP_PRIVACY_ON;
+
+ if (IS_SUPPORT_MULTI_BANDS(pmadapter)) {
+ /* Append a channel TLV */
+ pchan_tlv = (MrvlIEtypes_ChanListParamSet_t *)pos;
+ pchan_tlv->header.type = wlan_cpu_to_le16(TLV_TYPE_CHANLIST);
+ pchan_tlv->header.len =
+ wlan_cpu_to_le16(sizeof(ChanScanParamSet_t));
+
+ memset(pmadapter, pchan_tlv->chan_scan_param, 0x00,
+ sizeof(ChanScanParamSet_t));
+ pchan_tlv->chan_scan_param[0].chan_number =
+ (pbss_desc->phy_param_set.ds_param_set.current_chan);
+ PRINTM(MINFO, "ADHOC_J_CMD: TLV Chan = %d\n",
+ pchan_tlv->chan_scan_param[0].chan_number);
+
+ pchan_tlv->chan_scan_param[0].bandcfg.chanBand =
+ wlan_band_to_radio_type((t_u8)pbss_desc->bss_band);
+
+ PRINTM(MINFO, "ADHOC_J_CMD: TLV Bandcfg = %x\n",
+ pchan_tlv->chan_scan_param[0].bandcfg);
+ pos += sizeof(pchan_tlv->header) + sizeof(ChanScanParamSet_t);
+ cmd_append_size +=
+ sizeof(pchan_tlv->header) + sizeof(ChanScanParamSet_t);
+ }
+
+ if (wlan_11d_create_dnld_countryinfo(pmpriv,
+ (t_u8)pbss_desc->bss_band)) {
+ PRINTM(MERROR, "Dnld_countryinfo_11d failed\n");
+ ret = MLAN_STATUS_FAILURE;
+ goto done;
+ }
+ if (wlan_11d_parse_dnld_countryinfo(pmpriv,
+ pmpriv->pattempted_bss_desc)) {
+ ret = MLAN_STATUS_FAILURE;
+ goto done;
+ }
+
+ /*
+ * Call 11h join API after capability bits are set so
+ * adhoc/infra 11h behavior can be properly triggered.
+ * pos modified if data is appended
+ */
+ cmd_append_size += wlan_11h_process_join(
+ pmpriv, &pos, &padhoc_join->bss_descriptor.cap,
+ (t_u8)pbss_desc->bss_band, pbss_desc->channel,
+ &pbss_desc->wlan_11h_bss_info);
+
+ if (pmpriv->sec_info.wpa_enabled) {
+ prsn_ie_tlv = (MrvlIEtypes_RsnParamSet_t *)pos;
+ /* WPA_IE or RSN_IE */
+ prsn_ie_tlv->header.type = (t_u16)pmpriv->wpa_ie[0];
+ prsn_ie_tlv->header.type = prsn_ie_tlv->header.type & 0x00FF;
+ prsn_ie_tlv->header.type =
+ wlan_cpu_to_le16(prsn_ie_tlv->header.type);
+ prsn_ie_tlv->header.len = (t_u16)pmpriv->wpa_ie[1];
+ prsn_ie_tlv->header.len = prsn_ie_tlv->header.len & 0x00FF;
+ if (prsn_ie_tlv->header.len <= (sizeof(pmpriv->wpa_ie) - 2))
+ memcpy_ext(pmadapter, prsn_ie_tlv->rsn_ie,
+ &pmpriv->wpa_ie[2], prsn_ie_tlv->header.len,
+ prsn_ie_tlv->header.len);
+ else {
+ ret = MLAN_STATUS_FAILURE;
+ goto done;
+ }
+
+ HEXDUMP("ADHOC_JOIN: RSN IE", (t_u8 *)prsn_ie_tlv,
+ sizeof(prsn_ie_tlv->header) + prsn_ie_tlv->header.len);
+ pos += sizeof(prsn_ie_tlv->header) + prsn_ie_tlv->header.len;
+ cmd_append_size +=
+ sizeof(prsn_ie_tlv->header) + prsn_ie_tlv->header.len;
+ prsn_ie_tlv->header.len =
+ wlan_cpu_to_le16(prsn_ie_tlv->header.len);
+ } else if (pmpriv->sec_info.ewpa_enabled) {
+ prsn_ie_tlv = (MrvlIEtypes_RsnParamSet_t *)pos;
+ if (pbss_desc->pwpa_ie) {
+ prsn_ie_tlv->header.type =
+ (t_u16)(*(pbss_desc->pwpa_ie))
+ .vend_hdr.element_id;
+ prsn_ie_tlv->header.type =
+ prsn_ie_tlv->header.type & 0x00FF;
+ prsn_ie_tlv->header.type =
+ wlan_cpu_to_le16(prsn_ie_tlv->header.type);
+ prsn_ie_tlv->header.len =
+ (t_u16)(*(pbss_desc->pwpa_ie)).vend_hdr.len;
+ prsn_ie_tlv->header.len =
+ prsn_ie_tlv->header.len & 0x00FF;
+ if (prsn_ie_tlv->header.len <=
+ (sizeof(pmpriv->wpa_ie))) {
+ memcpy_ext(pmadapter, prsn_ie_tlv->rsn_ie,
+ &((*(pbss_desc->pwpa_ie))
+ .vend_hdr.oui[0]),
+ prsn_ie_tlv->header.len,
+ prsn_ie_tlv->header.len);
+ } else {
+ ret = MLAN_STATUS_FAILURE;
+ goto done;
+ }
+
+ HEXDUMP("ADHOC_JOIN: RSN IE", (t_u8 *)prsn_ie_tlv,
+ sizeof(prsn_ie_tlv->header) +
+ prsn_ie_tlv->header.len);
+ pos += sizeof(prsn_ie_tlv->header) +
+ prsn_ie_tlv->header.len;
+ cmd_append_size += sizeof(prsn_ie_tlv->header) +
+ prsn_ie_tlv->header.len;
+ prsn_ie_tlv->header.len =
+ wlan_cpu_to_le16(prsn_ie_tlv->header.len);
+ }
+ if (pbss_desc->prsn_ie) {
+ prsn_ie_tlv = (MrvlIEtypes_RsnParamSet_t *)pos;
+ prsn_ie_tlv->header.type =
+ (t_u16)(*(pbss_desc->prsn_ie))
+ .ieee_hdr.element_id;
+ prsn_ie_tlv->header.type =
+ prsn_ie_tlv->header.type & 0x00FF;
+ prsn_ie_tlv->header.type =
+ wlan_cpu_to_le16(prsn_ie_tlv->header.type);
+ prsn_ie_tlv->header.len =
+ (t_u16)(*(pbss_desc->prsn_ie)).ieee_hdr.len;
+ prsn_ie_tlv->header.len =
+ prsn_ie_tlv->header.len & 0x00FF;
+ if (prsn_ie_tlv->header.len <=
+ (sizeof(pmpriv->wpa_ie))) {
+ memcpy_ext(pmadapter, prsn_ie_tlv->rsn_ie,
+ &((*(pbss_desc->prsn_ie)).data[0]),
+ prsn_ie_tlv->header.len,
+ prsn_ie_tlv->header.len);
+ } else {
+ ret = MLAN_STATUS_FAILURE;
+ goto done;
+ }
+
+ HEXDUMP("ADHOC_JOIN: RSN IE", (t_u8 *)prsn_ie_tlv,
+ sizeof(prsn_ie_tlv->header) +
+ prsn_ie_tlv->header.len);
+ pos += sizeof(prsn_ie_tlv->header) +
+ prsn_ie_tlv->header.len;
+ cmd_append_size += sizeof(prsn_ie_tlv->header) +
+ prsn_ie_tlv->header.len;
+ prsn_ie_tlv->header.len =
+ wlan_cpu_to_le16(prsn_ie_tlv->header.len);
+ }
+ }
+
+ cmd->size = (t_u16)wlan_cpu_to_le16(
+ (t_u16)(sizeof(HostCmd_DS_802_11_AD_HOC_JOIN) + S_DS_GEN +
+ cmd_append_size));
+
+ memcpy_ext(pmadapter, &tmp_cap, &padhoc_join->bss_descriptor.cap,
+ sizeof(IEEEtypes_CapInfo_t), sizeof(IEEEtypes_CapInfo_t));
+ tmp_cap = wlan_cpu_to_le16(tmp_cap);
+
+ memcpy_ext(pmadapter, &padhoc_join->bss_descriptor.cap, &tmp_cap,
+ sizeof(IEEEtypes_CapInfo_t), sizeof(IEEEtypes_CapInfo_t));
+
+done:
+ LEAVE();
+ return ret;
+}
+
+/**
+ * @brief This function handles the command response of ad_hoc_start and
+ * ad_hoc_join
+ *
+ * @param pmpriv A pointer to mlan_private structure
+ * @param resp A pointer to HostCmd_DS_COMMAND
+ * @param pioctl_buf A pointer to mlan_ioctl_req structure
+ *
+ * @return MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ */
+mlan_status wlan_ret_802_11_ad_hoc(mlan_private *pmpriv,
+ HostCmd_DS_COMMAND *resp, t_void *pioctl_buf)
+{
+ mlan_status ret = MLAN_STATUS_SUCCESS;
+ mlan_ioctl_req *pioctl_req = (mlan_ioctl_req *)pioctl_buf;
+ HostCmd_DS_802_11_AD_HOC_START_RESULT *padhoc_start_result =
+ &resp->params.adhoc_start_result;
+ HostCmd_DS_802_11_AD_HOC_JOIN_RESULT *padhoc_join_result =
+ &resp->params.adhoc_join_result;
+ BSSDescriptor_t *pbss_desc;
+ t_u16 command = resp->command;
+ t_u8 result = 0;
+ t_u8 event_buf[100];
+ mlan_event *pevent = (mlan_event *)event_buf;
+ int ie_len = 0;
+ IEEEtypes_WmmParameter_t *pwmm_param_ie = MNULL;
+ mlan_adapter *pmadapter = pmpriv->adapter;
+ const t_u8 wmm_oui[4] = {0x00, 0x50, 0xf2, 0x02};
+
+ ENTER();
+
+ pmpriv->wmm_enabled = MFALSE;
+ if (command == HostCmd_CMD_802_11_AD_HOC_START) {
+ result = padhoc_start_result->result;
+ ie_len = resp->size -
+ (sizeof(HostCmd_DS_802_11_AD_HOC_START_RESULT) +
+ S_DS_GEN);
+ pwmm_param_ie =
+ (IEEEtypes_WmmParameter_t
+ *)((t_u8 *)resp +
+ (sizeof(HostCmd_DS_802_11_AD_HOC_START_RESULT) +
+ S_DS_GEN));
+ } else {
+ result = padhoc_join_result->result;
+ ie_len = resp->size -
+ (sizeof(HostCmd_DS_802_11_AD_HOC_JOIN_RESULT) +
+ S_DS_GEN);
+ pwmm_param_ie =
+ (IEEEtypes_WmmParameter_t
+ *)((t_u8 *)resp +
+ (sizeof(HostCmd_DS_802_11_AD_HOC_JOIN_RESULT) +
+ S_DS_GEN));
+ }
+
+ pbss_desc = pmpriv->pattempted_bss_desc;
+
+ /*
+ * Join result code 0 --> SUCCESS
+ */
+ if (result) {
+ PRINTM(MERROR, "ADHOC_RESP Failed 0x%x\n", result);
+ if (pmpriv->media_connected == MTRUE)
+ wlan_reset_connect_state(pmpriv, MTRUE);
+ if (pmpriv->adhoc_state == ADHOC_STARTING)
+ pmpriv->adhoc_state = ADHOC_IDLE;
+
+ memset(pmpriv->adapter, &pmpriv->curr_bss_params.bss_descriptor,
+ 0x00, sizeof(BSSDescriptor_t));
+
+ ret = MLAN_STATUS_FAILURE;
+ goto done;
+ }
+
+ /* Send a Media Connected event, according to the Spec */
+ pmpriv->media_connected = MTRUE;
+
+ if (command == HostCmd_CMD_802_11_AD_HOC_START) {
+ PRINTM(MINFO, "ADHOC_S_RESP %s\n", pbss_desc->ssid.ssid);
+
+ /* Update the created network descriptor with the new BSSID */
+ memcpy_ext(pmpriv->adapter, pbss_desc->mac_address,
+ padhoc_start_result->bssid, MLAN_MAC_ADDR_LENGTH,
+ MLAN_MAC_ADDR_LENGTH);
+
+ pmpriv->adhoc_state = ADHOC_STARTED;
+ if (pmpriv->adapter->state_rdh.stage == RDH_RESTART_INTFS)
+ wlan_11h_radar_detected_callback((t_void *)pmpriv);
+ } else {
+ /*
+ * Now the join cmd should be successful.
+ * If BSSID has changed use SSID to compare instead of BSSID
+ */
+ PRINTM(MINFO, "ADHOC_J_RESP %s\n", pbss_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_ext(pmpriv->adapter,
+ &pmpriv->curr_bss_params.bss_descriptor, pbss_desc,
+ sizeof(BSSDescriptor_t), sizeof(BSSDescriptor_t));
+
+ pmpriv->adhoc_state = ADHOC_JOINED;
+ }
+
+ /** process wmm ie */
+ if (ie_len >= sizeof(IEEEtypes_VendorHeader_t)) {
+ if ((pwmm_param_ie->vend_hdr.element_id ==
+ VENDOR_SPECIFIC_221) &&
+ !memcmp(pmadapter, pwmm_param_ie->vend_hdr.oui, wmm_oui,
+ sizeof(wmm_oui)) &&
+ (pwmm_param_ie->vend_hdr.len + 2 == ie_len)) {
+ DBG_HEXDUMP(MCMD_D, "WMM Param", (t_u8 *)pwmm_param_ie,
+ ie_len);
+ memcpy_ext(pmpriv->adapter,
+ (t_u8 *)&pmpriv->curr_bss_params
+ .bss_descriptor.wmm_ie,
+ pwmm_param_ie,
+ (pwmm_param_ie->vend_hdr.len + 2),
+ sizeof(IEEEtypes_WmmParameter_t));
+ pmpriv->wmm_enabled = MTRUE;
+ wlan_wmm_setup_queue_priorities(pmpriv, pwmm_param_ie);
+ wlan_wmm_setup_ac_downgrade(pmpriv);
+ }
+ }
+ /* Since WMM is not enabled, setup the queues with the defaults */
+ if (!pmpriv->wmm_enabled)
+ wlan_wmm_setup_queues(pmpriv);
+
+ PRINTM(MINFO, "ADHOC_RESP: Channel = %d\n", pmpriv->adhoc_channel);
+ PRINTM(MINFO, "ADHOC_RESP: BSSID = " MACSTR "\n",
+ MAC2STR(pmpriv->curr_bss_params.bss_descriptor.mac_address));
+
+ pevent->bss_index = pmpriv->bss_index;
+ pevent->event_id = MLAN_EVENT_ID_DRV_CONNECTED;
+ pevent->event_len = MLAN_MAC_ADDR_LENGTH;
+ memcpy_ext(pmpriv->adapter, (t_u8 *)pevent->event_buf,
+ (t_u8 *)pmpriv->curr_bss_params.bss_descriptor.mac_address,
+ MLAN_MAC_ADDR_LENGTH, MLAN_MAC_ADDR_LENGTH);
+ wlan_recv_event(pmpriv, MLAN_EVENT_ID_DRV_CONNECTED, pevent);
+ wlan_save_curr_bcn(pmpriv);
+
+done:
+ /* Need to indicate IOCTL complete */
+ if (pioctl_req != MNULL) {
+ if (ret != MLAN_STATUS_SUCCESS)
+ pioctl_req->status_code = MLAN_ERROR_CMD_ASSOC_FAIL;
+ else
+ pioctl_req->status_code = MLAN_ERROR_NO_ERROR;
+ }
+
+ LEAVE();
+ return ret;
+}
+
+/**
+ * @brief Associated to a specific BSS discovered in a scan
+ *
+ * @param pmpriv A pointer to mlan_private structure
+ * @param pioctl_buf A pointer to MLAN IOCTL Request buffer
+ * @param pbss_desc A pointer to the BSS descriptor to associate with.
+ *
+ * @return MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ */
+mlan_status wlan_associate(mlan_private *pmpriv, t_void *pioctl_buf,
+ BSSDescriptor_t *pbss_desc)
+{
+ mlan_status ret = MLAN_STATUS_SUCCESS;
+ t_u8 current_bssid[MLAN_MAC_ADDR_LENGTH];
+ pmlan_ioctl_req pioctl_req = (mlan_ioctl_req *)pioctl_buf;
+
+ ENTER();
+
+ /* Return error if the pmadapter or table entry
+ * is not marked as infra */
+ if ((pmpriv->bss_mode != MLAN_BSS_MODE_INFRA) ||
+ (pbss_desc->bss_mode != MLAN_BSS_MODE_INFRA)) {
+ if (pioctl_req)
+ pioctl_req->status_code = MLAN_ERROR_IOCTL_INVALID;
+ LEAVE();
+ return MLAN_STATUS_FAILURE;
+ }
+
+ memcpy_ext(pmpriv->adapter, &current_bssid,
+ &pmpriv->curr_bss_params.bss_descriptor.mac_address,
+ sizeof(current_bssid), sizeof(current_bssid));
+
+ /* Clear any past association response stored for application retrieval
+ */
+ pmpriv->assoc_rsp_size = 0;
+
+ ret = wlan_prepare_cmd(pmpriv, HostCmd_CMD_802_11_ASSOCIATE,
+ HostCmd_ACT_GEN_SET, 0, pioctl_buf, pbss_desc);
+
+ LEAVE();
+ return ret;
+}
+
+/**
+ * @brief Start an Adhoc Network
+ *
+ * @param pmpriv A pointer to mlan_private structure
+ * @param pioctl_buf A pointer to MLAN IOCTL Request buffer
+ * @param padhoc_ssid The ssid of the Adhoc Network
+ *
+ * @return MLAN_STATUS_SUCCESS--success, MLAN_STATUS_FAILURE--fail
+ */
+mlan_status wlan_adhoc_start(mlan_private *pmpriv, t_void *pioctl_buf,
+ mlan_802_11_ssid *padhoc_ssid)
+{
+ mlan_status ret = MLAN_STATUS_SUCCESS;
+ wlan_meas_state_t *pmeas_state = &pmpriv->adapter->state_meas;
+ t_u8 radar = MFALSE;
+ pmlan_ioctl_req pioctl_req = (mlan_ioctl_req *)pioctl_buf;
+
+ ENTER();
+
+ /*
+ * If the report indicates no measurement was done, leave the default
+ * return value alone.
+ */
+ if (!pmeas_state->meas_rpt_returned.rpt.basic.map.unmeasured) {
+ radar = pmeas_state->meas_rpt_returned.rpt.basic.map.radar ?
+ MTRUE :
+ MFALSE;
+ }
+
+ if (radar) {
+ if (pioctl_req)
+ pioctl_req->status_code = MLAN_ERROR_IOCTL_INVALID;
+ ret = MLAN_STATUS_FAILURE;
+ LEAVE();
+ return ret;
+ }
+
+ PRINTM(MINFO, "Adhoc Channel = %d\n", pmpriv->adhoc_channel);
+ PRINTM(MINFO, "curr_bss_params.channel = %d\n",
+ pmpriv->curr_bss_params.bss_descriptor.channel);
+ PRINTM(MINFO, "curr_bss_params.band = %d\n",
+ pmpriv->curr_bss_params.band);
+
+ ret = wlan_prepare_cmd(pmpriv, HostCmd_CMD_802_11_AD_HOC_START,
+ HostCmd_ACT_GEN_SET, 0, pioctl_buf, padhoc_ssid);
+#if defined(STA_SUPPORT)
+ if (ret == MLAN_STATUS_SUCCESS)
+ memcpy_ext(pmpriv->adapter, &pmpriv->adhoc_last_start_ssid,
+ padhoc_ssid, sizeof(mlan_802_11_ssid),
+ sizeof(mlan_802_11_ssid));
+#endif
+
+ LEAVE();
+ return ret;
+}
+
+/**
+ * @brief Join an adhoc network found in a previous scan
+ *
+ * @param pmpriv A pointer to mlan_private structure
+ * @param pioctl_buf A pointer to MLAN IOCTL Request buffer
+ * @param pbss_desc A pointer to the BSS descriptor found in a previous
+ * scan to attempt to join
+ *
+ * @return MLAN_STATUS_SUCCESS--success, MLAN_STATUS_FAILURE--fail
+ */
+mlan_status wlan_adhoc_join(mlan_private *pmpriv, t_void *pioctl_buf,
+ BSSDescriptor_t *pbss_desc)
+{
+ pmlan_adapter pmadapter = pmpriv->adapter;
+ mlan_status ret = MLAN_STATUS_SUCCESS;
+ pmlan_ioctl_req pioctl_req = (mlan_ioctl_req *)pioctl_buf;
+
+ ENTER();
+
+ PRINTM(MINFO, "wlan_adhoc_join: CurBss.ssid =%s\n",
+ pmpriv->curr_bss_params.bss_descriptor.ssid.ssid);
+ PRINTM(MINFO, "wlan_adhoc_join: CurBss.ssid_len =%u\n",
+ pmpriv->curr_bss_params.bss_descriptor.ssid.ssid_len);
+ PRINTM(MINFO, "wlan_adhoc_join: ssid =%s\n", pbss_desc->ssid.ssid);
+ PRINTM(MINFO, "wlan_adhoc_join: ssid len =%u\n",
+ pbss_desc->ssid.ssid_len);
+
+ /* Check if the requested SSID is already joined */
+ if (pmpriv->curr_bss_params.bss_descriptor.ssid.ssid_len &&
+ !wlan_ssid_cmp(pmadapter, &pbss_desc->ssid,
+ &pmpriv->curr_bss_params.bss_descriptor.ssid) &&
+ (pmpriv->curr_bss_params.bss_descriptor.bss_mode ==
+ MLAN_BSS_MODE_IBSS)) {
+ PRINTM(MINFO,
+ "ADHOC_J_CMD: New ad-hoc SSID is the same as current, "
+ "not attempting to re-join\n");
+
+ if (pioctl_req)
+ pioctl_req->status_code = MLAN_ERROR_IOCTL_INVALID;
+ LEAVE();
+ return MLAN_STATUS_FAILURE;
+ }
+
+ PRINTM(MINFO, "curr_bss_params.channel = %d\n",
+ pmpriv->curr_bss_params.bss_descriptor.channel);
+ PRINTM(MINFO, "curr_bss_params.band = %d\n",
+ pmpriv->curr_bss_params.band);
+
+ ret = wlan_prepare_cmd(pmpriv, HostCmd_CMD_802_11_AD_HOC_JOIN,
+ HostCmd_ACT_GEN_SET, 0, pioctl_buf, pbss_desc);
+
+ LEAVE();
+ return ret;
+}
+
+/**
+ * @brief Send Deauthentication Request or Stop the AdHoc network depending on
+ * mode
+ *
+ * @param pmpriv A pointer to mlan_private structure
+ * @param pioctl_req A pointer to mlan_ioctl_req structure
+ * @param deauth_param A pointer to mlan_deauth_param structure
+ *
+ * @return MLAN_STATUS_SUCCESS--success, MLAN_STATUS_FAILURE--fail,
+ * MLAN_STATUS_PENDING--pending
+ */
+mlan_status wlan_disconnect(mlan_private *pmpriv, mlan_ioctl_req *pioctl_req,
+ mlan_deauth_param *deauth_param)
+{
+ mlan_status ret = MLAN_STATUS_SUCCESS;
+ mlan_deauth_param local_param = {.mac_addr = {0, 0, 0, 0, 0, 0},
+ .reason_code = DEF_DEAUTH_REASON_CODE};
+ t_u8 zero_mac[] = {0, 0, 0, 0, 0, 0};
+
+ ENTER();
+
+ if (deauth_param)
+ memcpy_ext(pmpriv->adapter, &local_param, deauth_param,
+ sizeof(*deauth_param), sizeof(local_param));
+ if (pmpriv->media_connected == MTRUE) {
+ if (pmpriv->bss_mode == MLAN_BSS_MODE_INFRA) {
+ if (!deauth_param ||
+ !memcmp(pmpriv->adapter, deauth_param->mac_addr,
+ zero_mac, sizeof(zero_mac)))
+ memcpy_ext(pmpriv->adapter,
+ local_param.mac_addr,
+ (t_u8 *)&pmpriv->curr_bss_params
+ .bss_descriptor.mac_address,
+ MLAN_MAC_ADDR_LENGTH,
+ MLAN_MAC_ADDR_LENGTH);
+#ifdef WIFI_DIRECT_SUPPORT
+ if (pmpriv->bss_type == MLAN_BSS_TYPE_WIFIDIRECT)
+ ret = wlan_prepare_cmd(
+ pmpriv, HostCmd_CMD_802_11_DISASSOCIATE,
+ HostCmd_ACT_GEN_SET, 0,
+ (t_void *)pioctl_req, &local_param);
+ else
+#endif
+ ret = wlan_prepare_cmd(
+ pmpriv,
+ HostCmd_CMD_802_11_DEAUTHENTICATE,
+ HostCmd_ACT_GEN_SET, 0,
+ (t_void *)pioctl_req, &local_param);
+
+ if (ret == MLAN_STATUS_SUCCESS && pioctl_req)
+ ret = MLAN_STATUS_PENDING;
+
+ } else if (pmpriv->bss_mode == MLAN_BSS_MODE_IBSS) {
+ ret = wlan_prepare_cmd(pmpriv,
+ HostCmd_CMD_802_11_AD_HOC_STOP,
+ HostCmd_ACT_GEN_SET, 0,
+ (t_void *)pioctl_req, MNULL);
+
+ if (ret == MLAN_STATUS_SUCCESS && pioctl_req)
+ ret = MLAN_STATUS_PENDING;
+ }
+ }
+
+ LEAVE();
+ return ret;
+}
+
+/**
+ * @brief Convert band to radio type used in channel TLV
+ *
+ * @param band Band enumeration to convert to a channel TLV radio type
+ *
+ * @return Radio type designator for use in a channel TLV
+ */
+t_u8 wlan_band_to_radio_type(t_u8 band)
+{
+ t_u8 ret_radio_type;
+
+ ENTER();
+
+ switch (band) {
+ case BAND_A:
+ case BAND_AN:
+ case BAND_A | BAND_AN:
+ case BAND_A | BAND_AN | BAND_AAC:
+ ret_radio_type = BAND_5GHZ;
+ break;
+ case BAND_B:
+ case BAND_G:
+ case BAND_B | BAND_G:
+ default:
+ ret_radio_type = BAND_2GHZ;
+ break;
+ }
+
+ LEAVE();
+ return ret_radio_type;
+}
diff --git a/drivers/net/wireless/nxp/mxm_wifiex/wlan_src/mlan/mlan_join.h b/drivers/net/wireless/nxp/mxm_wifiex/wlan_src/mlan/mlan_join.h
new file mode 100644
index 000000000000..99d6027c59d5
--- /dev/null
+++ b/drivers/net/wireless/nxp/mxm_wifiex/wlan_src/mlan/mlan_join.h
@@ -0,0 +1,42 @@
+/** @file mlan_join.h
+ *
+ * @brief This file defines the interface for the WLAN infrastructure
+ * and adhoc join routines.
+ *
+ * Driver interface functions and type declarations for the join module
+ * implemented in mlan_join.c. Process all start/join requests for
+ * both adhoc and infrastructure networks
+ *
+ *
+ * Copyright 2014-2020 NXP
+ *
+ * This software file (the File) is distributed by NXP
+ * under the terms of the GNU General Public License Version 2, June 1991
+ * (the License). You may use, redistribute and/or modify the 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.
+ *
+ */
+
+/******************************************************
+Change log:
+ 10/13/2008: initial version
+******************************************************/
+
+#ifndef _MLAN_JOIN_H_
+#define _MLAN_JOIN_H_
+
+/** Size of buffer allocated to store the association response from firmware */
+#define MRVDRV_ASSOC_RSP_BUF_SIZE 500
+
+/** Size of buffer allocated to store IEs passed to firmware in the assoc req */
+#define MRVDRV_GENIE_BUF_SIZE 256
+
+#endif /* _MLAN_JOIN_H_ */
diff --git a/drivers/net/wireless/nxp/mxm_wifiex/wlan_src/mlan/mlan_main.h b/drivers/net/wireless/nxp/mxm_wifiex/wlan_src/mlan/mlan_main.h
new file mode 100644
index 000000000000..2e3019f47460
--- /dev/null
+++ b/drivers/net/wireless/nxp/mxm_wifiex/wlan_src/mlan/mlan_main.h
@@ -0,0 +1,4137 @@
+/** @file mlan_main.h
+ *
+ * @brief This file defines the private and adapter data
+ * structures and declares global function prototypes used
+ * in MLAN module.
+ *
+ *
+ * Copyright 2014-2020 NXP
+ *
+ * This software file (the File) is distributed by NXP
+ * under the terms of the GNU General Public License Version 2, June 1991
+ * (the License). You may use, redistribute and/or modify the 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.
+ *
+ */
+
+/******************************************************
+Change log:
+ 10/13/2008: initial version
+******************************************************/
+
+#ifndef _MLAN_MAIN_H_
+#define _MLAN_MAIN_H_
+
+#ifdef DEBUG_LEVEL1
+extern t_void (*print_callback)(t_pvoid pmoal_handle, t_u32 level,
+ char *pformat, IN...);
+
+extern mlan_status (*get_sys_time_callback)(t_void *pmoal_handle, t_u32 *psec,
+ t_u32 *pusec);
+
+extern t_u32 mlan_drvdbg;
+
+#ifdef DEBUG_LEVEL2
+#define PRINTM_MINFO(msg...) \
+ do { \
+ if ((mlan_drvdbg & MINFO) && (print_callback)) \
+ print_callback(MNULL, MINFO, msg); \
+ } while (0)
+#define PRINTM_MWARN(msg...) \
+ do { \
+ if ((mlan_drvdbg & MWARN) && (print_callback)) \
+ print_callback(MNULL, MWARN, msg); \
+ } while (0)
+#define PRINTM_MENTRY(msg...) \
+ do { \
+ if ((mlan_drvdbg & MENTRY) && (print_callback)) \
+ print_callback(MNULL, MENTRY, msg); \
+ } while (0)
+#define PRINTM_GET_SYS_TIME(level, psec, pusec) \
+ do { \
+ if ((level & mlan_drvdbg) && (get_sys_time_callback)) \
+ get_sys_time_callback(MNULL, psec, pusec); \
+ } while (0)
+
+/** Hexdump for level-2 debugging */
+#define HEXDUMP(x, y, z) \
+ do { \
+ if ((mlan_drvdbg & (MHEX_DUMP | MINFO)) && (print_callback)) \
+ print_callback(MNULL, MHEX_DUMP | MINFO, x, y, z); \
+ } while (0)
+
+#else
+
+#define PRINTM_MINFO(msg...) \
+ do { \
+ } while (0)
+#define PRINTM_MWARN(msg...) \
+ do { \
+ } while (0)
+#define PRINTM_MENTRY(msg...) \
+ do { \
+ } while (0)
+
+#define PRINTM_GET_SYS_TIME(level, psec, pusec) \
+ do { \
+ if ((level & mlan_drvdbg) && (get_sys_time_callback) && \
+ (level != MINFO) && (level != MWARN)) \
+ get_sys_time_callback(MNULL, psec, pusec); \
+ } while (0)
+
+/** Hexdump for debugging */
+#define HEXDUMP(x, y, z) \
+ do { \
+ } while (0)
+
+#endif /* DEBUG_LEVEL2 */
+
+#define PRINTM_MFW_D(msg...) \
+ do { \
+ if ((mlan_drvdbg & MFW_D) && (print_callback)) \
+ print_callback(MNULL, MFW_D, msg); \
+ } while (0)
+#define PRINTM_MCMD_D(msg...) \
+ do { \
+ if ((mlan_drvdbg & MCMD_D) && (print_callback)) \
+ print_callback(MNULL, MCMD_D, msg); \
+ } while (0)
+#define PRINTM_MDAT_D(msg...) \
+ do { \
+ if ((mlan_drvdbg & MDAT_D) && (print_callback)) \
+ print_callback(MNULL, MDAT_D, msg); \
+ } while (0)
+#define PRINTM_MIF_D(msg...) \
+ do { \
+ if ((mlan_drvdbg & MIF_D) && (print_callback)) \
+ print_callback(MNULL, MIF_D, msg); \
+ } while (0)
+
+#define PRINTM_MIOCTL(msg...) \
+ do { \
+ if ((mlan_drvdbg & MIOCTL) && (print_callback)) \
+ print_callback(MNULL, MIOCTL, msg); \
+ } while (0)
+#define PRINTM_MINTR(msg...) \
+ do { \
+ if ((mlan_drvdbg & MINTR) && (print_callback)) \
+ print_callback(MNULL, MINTR, msg); \
+ } while (0)
+#define PRINTM_MEVENT(msg...) \
+ do { \
+ if ((mlan_drvdbg & MEVENT) && (print_callback)) \
+ print_callback(MNULL, MEVENT, msg); \
+ } while (0)
+#define PRINTM_MCMND(msg...) \
+ do { \
+ if ((mlan_drvdbg & MCMND) && (print_callback)) \
+ print_callback(MNULL, MCMND, msg); \
+ } while (0)
+#define PRINTM_MDATA(msg...) \
+ do { \
+ if ((mlan_drvdbg & MDATA) && (print_callback)) \
+ print_callback(MNULL, MDATA, msg); \
+ } while (0)
+#define PRINTM_MERROR(msg...) \
+ do { \
+ if ((mlan_drvdbg & MERROR) && (print_callback)) \
+ print_callback(MNULL, MERROR, msg); \
+ } while (0)
+#define PRINTM_MFATAL(msg...) \
+ do { \
+ if ((mlan_drvdbg & MFATAL) && (print_callback)) \
+ print_callback(MNULL, MFATAL, msg); \
+ } while (0)
+#define PRINTM_MMSG(msg...) \
+ do { \
+ if ((mlan_drvdbg & MMSG) && (print_callback)) \
+ print_callback(MNULL, MMSG, msg); \
+ } while (0)
+
+#define PRINTM(level, msg...) PRINTM_##level((char *)msg)
+
+/** Log debug message */
+#ifdef __GNUC__
+#define PRINTM_NETINTF(level, pmpriv) \
+ do { \
+ if ((mlan_drvdbg & level) && pmpriv && \
+ pmpriv->adapter->callbacks.moal_print_netintf) \
+ pmpriv->adapter->callbacks.moal_print_netintf( \
+ pmpriv->adapter->pmoal_handle, \
+ pmpriv->bss_index, level); \
+ } while (0)
+#endif /* __GNUC__ */
+
+/** Max hex dump data length */
+#define MAX_DATA_DUMP_LEN 64
+
+/** Debug hexdump for level-1 debugging */
+#define DBG_HEXDUMP(level, x, y, z) \
+ do { \
+ if ((mlan_drvdbg & level) && print_callback) \
+ print_callback(MNULL, MHEX_DUMP | level, x, y, z); \
+ } while (0)
+
+#else /* DEBUG_LEVEL1 */
+
+#define PRINTM(level, msg...) \
+ do { \
+ } while (0)
+
+#define PRINTM_NETINTF(level, pmpriv) \
+ do { \
+ } while (0)
+
+/** Debug hexdump for level-1 debugging */
+#define DBG_HEXDUMP(level, x, y, z) \
+ do { \
+ } while (0)
+
+/** Hexdump for debugging */
+#define HEXDUMP(x, y, z) \
+ do { \
+ } while (0)
+
+#define PRINTM_GET_SYS_TIME(level, psec, pusec) \
+ do { \
+ } while (0)
+
+#endif /* DEBUG_LEVEL1 */
+
+/* Reason Code 3: STA is leaving (or has left) IBSS or ESS */
+#define DEF_DEAUTH_REASON_CODE (0x3)
+
+/** Log entry point for debugging */
+#define ENTER() \
+ do { \
+ PRINTM(MENTRY, "Enter: %s\n", __func__); \
+ } while (0)
+
+/** Log exit point for debugging */
+#define LEAVE() \
+ do { \
+ PRINTM(MENTRY, "Leave: %s\n", __func__); \
+ } while (0)
+
+/** Find minimum */
+#ifndef MIN
+#define MIN(a, b) ((a) < (b) ? (a) : (b))
+#endif
+
+/** Find maximum */
+#ifndef MAX
+#define MAX(a, b) ((a) > (b) ? (a) : (b))
+#endif
+
+#ifdef memset
+#undef memset
+#endif
+/** Memset routine */
+#define memset(adapter, s, c, len) \
+ (adapter->callbacks.moal_memset(adapter->pmoal_handle, s, c, len))
+
+#ifdef memmove
+#undef memmove
+#endif
+/** Memmove routine */
+#define memmove(adapter, dest, src, len) \
+ (adapter->callbacks.moal_memmove(adapter->pmoal_handle, dest, src, len))
+
+#ifdef memcpy
+#undef memcpy
+#endif
+/** Memcpy routine */
+#define memcpy(adapter, to, from, len) \
+ (adapter->callbacks.moal_memcpy(adapter->pmoal_handle, to, from, len))
+/* memcpy_ext rountine */
+#define memcpy_ext(adapter, to, from, len, size) \
+ (adapter->callbacks.moal_memcpy_ext(adapter->pmoal_handle, to, from, \
+ len, size))
+
+#ifdef memcmp
+#undef memcmp
+#endif
+/** Memcmp routine */
+#define memcmp(adapter, s1, s2, len) \
+ (adapter->callbacks.moal_memcmp(adapter->pmoal_handle, s1, s2, len))
+
+/** Find number of elements */
+#ifndef NELEMENTS
+#define NELEMENTS(x) (sizeof(x) / sizeof(x[0]))
+#endif
+
+/** SWAP: swap t_u8 */
+#define SWAP_U8(a, b) \
+ { \
+ t_u8 t; \
+ t = a; \
+ a = b; \
+ b = t; \
+ }
+
+/** SWAP: swap t_u8 */
+#define SWAP_U16(a, b) \
+ { \
+ t_u16 t; \
+ t = a; \
+ a = b; \
+ b = t; \
+ }
+
+/** MLAN MNULL pointer */
+#define MNULL (0)
+
+/** 16 bits byte swap */
+#define swap_byte_16(x) \
+ ((t_u16)((((t_u16)(x)&0x00ffU) << 8) | (((t_u16)(x)&0xff00U) >> 8)))
+
+/** 32 bits byte swap */
+#define swap_byte_32(x) \
+ ((t_u32)((((t_u32)(x)&0x000000ffUL) << 24) | \
+ (((t_u32)(x)&0x0000ff00UL) << 8) | \
+ (((t_u32)(x)&0x00ff0000UL) >> 8) | \
+ (((t_u32)(x)&0xff000000UL) >> 24)))
+
+/** 64 bits byte swap */
+#define swap_byte_64(x) \
+ ((t_u64)((t_u64)(((t_u64)(x)&0x00000000000000ffULL) << 56) | \
+ (t_u64)(((t_u64)(x)&0x000000000000ff00ULL) << 40) | \
+ (t_u64)(((t_u64)(x)&0x0000000000ff0000ULL) << 24) | \
+ (t_u64)(((t_u64)(x)&0x00000000ff000000ULL) << 8) | \
+ (t_u64)(((t_u64)(x)&0x000000ff00000000ULL) >> 8) | \
+ (t_u64)(((t_u64)(x)&0x0000ff0000000000ULL) >> 24) | \
+ (t_u64)(((t_u64)(x)&0x00ff000000000000ULL) >> 40) | \
+ (t_u64)(((t_u64)(x)&0xff00000000000000ULL) >> 56)))
+
+#ifdef BIG_ENDIAN_SUPPORT
+/** Convert ulong n/w to host */
+#define mlan_ntohl(x) x
+/** Convert host ulong to n/w */
+#define mlan_htonl(x) x
+/** Convert n/w to host */
+#define mlan_ntohs(x) x
+/** Convert host to n/w */
+#define mlan_htons(x) x
+/** Convert from 16 bit little endian format to CPU format */
+#define wlan_le16_to_cpu(x) swap_byte_16(x)
+/** Convert from 32 bit little endian format to CPU format */
+#define wlan_le32_to_cpu(x) swap_byte_32(x)
+/** Convert from 64 bit little endian format to CPU format */
+#define wlan_le64_to_cpu(x) swap_byte_64(x)
+/** Convert to 16 bit little endian format from CPU format */
+#define wlan_cpu_to_le16(x) swap_byte_16(x)
+/** Convert to 32 bit little endian format from CPU format */
+#define wlan_cpu_to_le32(x) swap_byte_32(x)
+/** Convert to 64 bit little endian format from CPU format */
+#define wlan_cpu_to_le64(x) swap_byte_64(x)
+
+/** Convert TxPD to little endian format from CPU format */
+#define endian_convert_TxPD(x) \
+ { \
+ (x)->tx_pkt_length = wlan_cpu_to_le16((x)->tx_pkt_length); \
+ (x)->tx_pkt_offset = wlan_cpu_to_le16((x)->tx_pkt_offset); \
+ (x)->tx_pkt_type = wlan_cpu_to_le16((x)->tx_pkt_type); \
+ (x)->tx_control = wlan_cpu_to_le32((x)->tx_control); \
+ (x)->tx_control_1 = wlan_cpu_to_le32((x)->tx_control_1); \
+ }
+/** Convert RxPD from little endian format to CPU format */
+#define endian_convert_RxPD(x) \
+ { \
+ (x)->rx_pkt_length = wlan_le16_to_cpu((x)->rx_pkt_length); \
+ (x)->rx_pkt_offset = wlan_le16_to_cpu((x)->rx_pkt_offset); \
+ (x)->rx_pkt_type = wlan_le16_to_cpu((x)->rx_pkt_type); \
+ (x)->seq_num = wlan_le16_to_cpu((x)->seq_num); \
+ (x)->rx_info = wlan_le32_to_cpu((x)->rx_info); \
+ }
+
+#else
+/** Convert ulong n/w to host */
+#define mlan_ntohl(x) swap_byte_32(x)
+/** Convert host ulong to n/w */
+#define mlan_htonl(x) swap_byte_32(x)
+/** Convert n/w to host */
+#define mlan_ntohs(x) swap_byte_16(x)
+/** Convert host to n/w */
+#define mlan_htons(x) swap_byte_16(x)
+/** Do nothing */
+#define wlan_le16_to_cpu(x) x
+/** Do nothing */
+#define wlan_le32_to_cpu(x) x
+/** Do nothing */
+#define wlan_le64_to_cpu(x) x
+/** Do nothing */
+#define wlan_cpu_to_le16(x) x
+/** Do nothing */
+#define wlan_cpu_to_le32(x) x
+/** Do nothing */
+#define wlan_cpu_to_le64(x) x
+
+/** Convert TxPD to little endian format from CPU format */
+#define endian_convert_TxPD(x) \
+ do { \
+ } while (0)
+/** Convert RxPD from little endian format to CPU format */
+#define endian_convert_RxPD(x) \
+ do { \
+ } while (0)
+#endif /* BIG_ENDIAN_SUPPORT */
+
+/** Global moal_assert_callback */
+extern t_void (*assert_callback)(t_void *pmoal_handle, t_u32 cond);
+
+/** Assertion */
+#define MASSERT(cond) \
+ do { \
+ if (!(cond)) { \
+ PRINTM(MFATAL, "ASSERT: %s: %i\n", __func__, \
+ __LINE__); \
+ if (assert_callback) { \
+ assert_callback(MNULL, (t_ptr)(cond)); \
+ } else { \
+ do { \
+ } while (1); \
+ } \
+ } \
+ } while (0)
+
+/** Maximum event buffer size */
+#define MAX_EVENT_SIZE (3 * 1024)
+
+/** 60 seconds */
+#define MRVDRV_TIMER_60S 60000
+/** 10 seconds */
+#define MRVDRV_TIMER_10S 10000
+/** 5 seconds */
+#define MRVDRV_TIMER_5S 5000
+/** 3 seconds */
+#define MRVDRV_TIMER_3S 3000
+/** 1 second */
+#define MRVDRV_TIMER_1S 1000
+
+/** Maximum size of multicast list */
+#define MRVDRV_MAX_MULTICAST_LIST_SIZE 32
+/** Maximum size of channel */
+#define MRVDRV_MAX_CHANNEL_SIZE 14
+/** Maximum length of SSID */
+#define MRVDRV_MAX_SSID_LENGTH 32
+/** WEP list macros & data structures */
+/** Size of key buffer in bytes */
+#define MRVL_KEY_BUFFER_SIZE_IN_BYTE 16
+/** Maximum length of WPA key */
+#define MRVL_MAX_KEY_WPA_KEY_LENGTH 32
+
+/** Default listen interval */
+#define MLAN_DEFAULT_LISTEN_INTERVAL 20
+
+/** Maximum number of region codes */
+#define MRVDRV_MAX_REGION_CODE 9
+
+/** Maximum number of CFP codes for BG */
+#define MRVDRV_MAX_CFP_CODE_BG 0
+/** Maximum number of CFP codes for A */
+#define MRVDRV_MAX_CFP_CODE_A 5
+
+/** high rx pending packets */
+#define HIGH_RX_PENDING 1000
+/** low rx pending packets */
+#define LOW_RX_PENDING 800
+
+/** Default region code */
+#define MRVDRV_DEFAULT_REGION_CODE 0x10
+/** Default country code */
+#define MRVDRV_DEFAULT_COUNTRY_CODE "US"
+
+/** Japan country code */
+#define COUNTRY_CODE_JP_40 0x40
+/** Japan special country code */
+#define COUNTRY_CODE_JP_FF 0xFF
+
+/** Default factor for calculating beacon average */
+#define DEFAULT_BCN_AVG_FACTOR 8
+/** Default factor for calculating data average */
+#define DEFAULT_DATA_AVG_FACTOR 8
+
+/** The first valid channel for use */
+#define FIRST_VALID_CHANNEL 0xff
+/** Default Ad-Hoc channel */
+#define DEFAULT_AD_HOC_CHANNEL 6
+/** Default Ad-Hoc channel A */
+#define DEFAULT_AD_HOC_CHANNEL_A 36
+
+/** Number of WEP keys */
+#define MRVL_NUM_WEP_KEY (4)
+
+/** Default multiple DTIM */
+#define MRVDRV_DEFAULT_MULTIPLE_DTIM 1
+
+/** Default beacon missing timeout */
+#define DEFAULT_BCN_MISS_TIMEOUT 10
+
+/** Maximum buffer space for beacons retrieved from scan responses */
+#define MAX_SCAN_BEACON_BUFFER 49152
+/** Default buffer space for beacons retrieved from scan responses */
+#define DEFAULT_SCAN_BEACON_BUFFER 4096
+
+/**
+ * @brief Buffer pad space for newly allocated beacons/probe responses
+ *
+ * Beacons are typically 6 bytes longer than an equivalent probe response.
+ * For each scan response stored, allocate an extra byte pad at the end to
+ * allow easy expansion to store a beacon in the same memory a probe response
+ * previously contained
+ */
+#define SCAN_BEACON_ENTRY_PAD 6
+
+/** Scan time specified in the channel TLV
+ * for each channel for passive scans
+ */
+#define MRVDRV_PASSIVE_SCAN_CHAN_TIME 200
+
+/** Scan time specified in the channel TLV
+ * for each channel for active scans
+ */
+#define MRVDRV_ACTIVE_SCAN_CHAN_TIME 200
+
+/** Scan time specified in the channel TLV
+ * for each channel for specific scans
+ */
+#define MRVDRV_SPECIFIC_SCAN_CHAN_TIME 110
+
+/**
+ * Max total scan time in milliseconds
+ * The total scan time should be less than scan command timeout value (20s)
+ */
+#define MRVDRV_MAX_TOTAL_SCAN_TIME (MRVDRV_TIMER_10S * 2 - MRVDRV_TIMER_1S)
+
+/** Offset for GTK as it has version to skip past for GTK */
+#define RSN_GTK_OUI_OFFSET 2
+
+/** If OUI is not found */
+#define MLAN_OUI_NOT_PRESENT 0
+/** If OUI is found */
+#define MLAN_OUI_PRESENT 1
+
+/** Is cmd_resp, event or data packet received? */
+#define IS_CARD_RX_RCVD(adapter) \
+ (adapter->cmd_resp_received || adapter->event_received || \
+ adapter->data_received)
+#ifdef USB
+/** Type length */
+#define MLAN_TYPE_LEN 4
+/** Type Command */
+#define MLAN_USB_TYPE_CMD 0xF00DFACE
+/** Type VDLL */
+#define MLAN_USB_TYPE_VDLL 0xF00DC0DE
+/** Type Data */
+#define MLAN_USB_TYPE_DATA 0xBEADC0DE
+/** Type Event */
+#define MLAN_USB_TYPE_EVENT 0xBEEFFACE
+#endif /* USB */
+/** Type command */
+#define MLAN_TYPE_CMD 1
+/** Type data */
+#define MLAN_TYPE_DATA 0
+/** Type event */
+#define MLAN_TYPE_EVENT 3
+/** Type vdll */
+#define MLAN_TYPE_VDLL 4
+#ifdef SDIO
+/** Type single port aggr data */
+#define MLAN_TYPE_SPA_DATA 10
+/** OFFSET of 512 block number */
+#define OFFSET_OF_BLOCK_NUMBER 15
+/** OFFSET of SDIO Header */
+#define OFFSET_OF_SDIO_HEADER 28
+/** sdio max rx size for cmd53, 255 * 256, reserve 1 block for DMA alignment */
+#define SDIO_CMD53_MAX_SIZE 65280
+#define MAX_SUPPORT_AMSDU_SIZE 4096
+/** Maximum numbfer of registers to read for multiple port */
+#if defined(SD8887) || defined(SD8997) || defined(SD8977) || \
+ defined(SD8987) || defined(SD9098) || defined(SD9097) || \
+ defined(SD8978)
+#define MAX_MP_REGS 196
+#else
+/* upto 0xB7 */
+#define MAX_MP_REGS 184
+#endif
+/** Maximum port */
+#define MAX_PORT 32
+
+/** max MP REGS */
+#define MAX_MP_REGS_MAX (196)
+
+/** Multi port TX aggregation buffer size */
+#define SDIO_MP_TX_AGGR_DEF_BUF_SIZE (65280) /* 64K - 256 */
+
+/** Multi port RX aggregation buffer size */
+#define SDIO_MP_RX_AGGR_DEF_BUF_SIZE (65280) /* 64K - 256 */
+
+#endif /* SDIO */
+
+/** Minimum BA threshold */
+#define MIN_BA_THRESHOLD 16
+
+/** High threshold at which to start drop packets */
+#define RX_HIGH_THRESHOLD 1024
+/** Low threshold to allow Rx BA */
+#define RX_LOW_THRESHOLD 128
+
+#define MFG_CMD_SET_TEST_MODE 1
+#define MFG_CMD_UNSET_TEST_MODE 0
+#define MFG_CMD_TX_ANT 0x1004
+#define MFG_CMD_RX_ANT 0x1005
+#define MFG_CMD_TX_CONT 0x1009
+#define MFG_CMD_RF_CHAN 0x100A
+#define MFG_CMD_CLR_RX_ERR 0x1010
+#define MFG_CMD_TX_FRAME 0x1021
+#define MFG_CMD_RF_BAND_AG 0x1034
+#define MFG_CMD_RF_CHANNELBW 0x1044
+
+/** Debug command number */
+#define DBG_CMD_NUM 10
+
+/** Info for debug purpose */
+typedef struct _wlan_dbg {
+ /** Number of host to card command failures */
+ t_u32 num_cmd_host_to_card_failure;
+ /** Number of host to card sleep confirm failures */
+ t_u32 num_cmd_sleep_cfm_host_to_card_failure;
+ /** Number of host to card Tx failures */
+ t_u32 num_tx_host_to_card_failure;
+ /** Number of card to host command/event failures */
+ t_u32 num_cmdevt_card_to_host_failure;
+ /** Number of card to host Rx failures */
+ t_u32 num_rx_card_to_host_failure;
+ /** Number of interrupt read failures */
+ t_u32 num_int_read_failure;
+ /** Last interrupt status */
+ t_u32 last_int_status;
+ /** Number of allocate buffer failure */
+ t_u32 num_alloc_buffer_failure;
+ /** Number of pkt dropped */
+ t_u32 num_pkt_dropped;
+ /** Number of deauthentication events */
+ t_u32 num_event_deauth;
+ /** Number of disassosiation events */
+ t_u32 num_event_disassoc;
+ /** Number of link lost events */
+ t_u32 num_event_link_lost;
+ /** Number of deauthentication commands */
+ t_u32 num_cmd_deauth;
+ /** Number of association comamnd successes */
+ t_u32 num_cmd_assoc_success;
+ /** Number of association command failures */
+ t_u32 num_cmd_assoc_failure;
+ /** Number of consecutive association command failures */
+ t_u32 num_cons_assoc_failure;
+
+ /** Timeout command ID */
+ t_u16 timeout_cmd_id;
+ /** Timeout command action */
+ t_u16 timeout_cmd_act;
+ /** List of last command IDs */
+ t_u16 last_cmd_id[DBG_CMD_NUM];
+ /** List of last command actions */
+ t_u16 last_cmd_act[DBG_CMD_NUM];
+ /** Last command index */
+ t_u16 last_cmd_index;
+ /** List of last command response IDs */
+ t_u16 last_cmd_resp_id[DBG_CMD_NUM];
+ /** Last command response index */
+ t_u16 last_cmd_resp_index;
+ /** List of last events */
+ t_u16 last_event[DBG_CMD_NUM];
+ /** Last event index */
+ t_u16 last_event_index;
+ /** Number of no free command node */
+ t_u16 num_no_cmd_node;
+} wlan_dbg;
+
+/** Hardware status codes */
+typedef enum _WLAN_HARDWARE_STATUS {
+ WlanHardwareStatusReady,
+ WlanHardwareStatusGetHwSpec,
+ WlanHardwareStatusGetHwSpecdone,
+ WlanHardwareStatusInitializing,
+ WlanHardwareStatusInitdone,
+ WlanHardwareStatusReset,
+ WlanHardwareStatusClosing,
+ WlanHardwareStatusNotReady
+} WLAN_HARDWARE_STATUS;
+
+/** WLAN_802_11_POWER_MODE */
+typedef enum _WLAN_802_11_POWER_MODE {
+ Wlan802_11PowerModeCAM,
+ Wlan802_11PowerModePSP
+} WLAN_802_11_POWER_MODE;
+
+/** tx param */
+typedef struct _mlan_tx_param {
+ /** next packet length */
+ t_u32 next_pkt_len;
+} mlan_tx_param;
+
+/** PS_STATE */
+typedef enum _PS_STATE {
+ PS_STATE_AWAKE,
+ PS_STATE_PRE_SLEEP,
+ PS_STATE_SLEEP_CFM,
+ PS_STATE_SLEEP
+} PS_STATE;
+
+/** Minimum flush timer for win size of 1 is 50 ms */
+#define MIN_FLUSH_TIMER_MS 50
+/** Minimum flush timer for win size of 1 is 15 ms */
+#define MIN_FLUSH_TIMER_15_MS 15
+
+/** Tx BA stream table */
+typedef struct _TxBAStreamTbl TxBAStreamTbl;
+
+/** Add BA parameter data structure */
+typedef struct {
+ /** Window size for initiator */
+ t_u32 tx_win_size;
+ /** Window size for receiver */
+ t_u32 rx_win_size;
+ /** Block ack timeout */
+ t_u32 timeout;
+ /** amsdu support for ADDBA request */
+ t_u8 tx_amsdu;
+ /** amsdu support for ADDBA response */
+ t_u8 rx_amsdu;
+} add_ba_param_t;
+
+/** Tx aggregation data structure */
+typedef struct _txAggr_t {
+ /** AMPDU user */
+ t_u8 ampdu_user;
+ /** AMPDU AP */
+ t_u8 ampdu_ap;
+ /** AMSDU */
+ t_u8 amsdu;
+} tx_aggr_t;
+
+/** del ba threshold */
+#define DEL_BA_THRESHOLD 10
+/** BA stream status */
+typedef enum _baStatus_e {
+ BA_STREAM_NOT_SETUP = 0,
+ BA_STREAM_SETUP_INPROGRESS,
+ BA_STREAM_SETUP_COMPLETE
+} baStatus_e;
+
+/** RA list table */
+typedef struct _raListTbl raListTbl, *praListTbl;
+
+/** RA list table */
+struct _raListTbl {
+ /** Pointer to previous node */
+ raListTbl *pprev;
+ /** Pointer to next node */
+ raListTbl *pnext;
+ /** Buffer list head */
+ mlan_list_head buf_head;
+ /** RA list buffer */
+ t_u8 ra[MLAN_MAC_ADDR_LENGTH];
+ /** total packets in RA list */
+ t_u16 total_pkts;
+ /** packets received */
+ t_u16 packet_count;
+ /** packet count threshold to setup BA */
+ t_u8 ba_packet_threshold;
+ /** is 11n enabled */
+ t_u8 is_11n_enabled;
+ /** max amsdu size */
+ t_u16 max_amsdu;
+ /** BA stream status */
+ baStatus_e ba_status;
+ /** del ba count */
+ t_u8 del_ba_count;
+ /** amsdu in ampdu flag */
+ t_u8 amsdu_in_ampdu;
+ /** tx_pause flag */
+ t_u8 tx_pause;
+};
+
+/** TID table */
+typedef struct _tidTbl {
+ /** RA list head */
+ mlan_list_head ra_list;
+ /** Current RA list */
+ raListTbl *ra_list_curr;
+} tid_tbl_t;
+
+/** Highest priority setting for a packet (uses voice AC) */
+#define WMM_HIGHEST_PRIORITY 7
+/** Highest priority TID */
+#define HIGH_PRIO_TID 7
+/** Lowest priority TID */
+#define LOW_PRIO_TID 0
+/** No packet priority (< lowest) */
+#define NO_PKT_PRIO_TID -1
+
+/** Max driver packet delay in msec */
+#define WMM_DRV_DELAY_MAX 510
+
+/** Struct of WMM DESC */
+typedef struct _wmm_desc {
+ /** TID table */
+ tid_tbl_t tid_tbl_ptr[MAX_NUM_TID];
+ /** Packets out */
+ t_u32 packets_out[MAX_NUM_TID];
+ /** Packets queued */
+ t_u32 pkts_queued[MAX_NUM_TID];
+ /** Packets paused */
+ t_u32 pkts_paused[MAX_NUM_TID];
+ /** Spin lock to protect ra_list */
+ t_void *ra_list_spinlock;
+
+ /** AC status */
+ WmmAcStatus_t ac_status[MAX_AC_QUEUES];
+ /** AC downgraded values */
+ mlan_wmm_ac_e ac_down_graded_vals[MAX_AC_QUEUES];
+
+ /** Max driver packet delay sent to the firmware for expiry eval */
+ t_u32 drv_pkt_delay_max;
+
+ /** WMM queue priority table */
+ t_u8 queue_priority[MAX_AC_QUEUES];
+ /** User priority packet transmission control */
+ t_u32 user_pri_pkt_tx_ctrl[WMM_HIGHEST_PRIORITY + 1]; /* UP: 0 to 7 */
+
+ /** Number of transmit packets queued */
+ mlan_scalar tx_pkts_queued;
+ /** Tracks highest priority with a packet queued */
+ mlan_scalar highest_queued_prio;
+} wmm_desc_t;
+
+/** Security structure */
+typedef struct _wlan_802_11_security_t {
+ /** WPA enabled flag */
+ t_u8 wpa_enabled;
+ /** E-Supplicant enabled flag */
+ t_u8 ewpa_enabled;
+ /** WPA2 enabled flag */
+ t_u8 wpa2_enabled;
+ /** WAPI enabled flag */
+ t_u8 wapi_enabled;
+ /** WAPI key on flag */
+ t_u8 wapi_key_on;
+ /** WEP status */
+ WLAN_802_11_WEP_STATUS wep_status;
+ /** Authentication mode */
+ t_u32 authentication_mode;
+ /** Encryption mode */
+ t_u32 encryption_mode;
+ /** Hotspot OSEN enabled */
+ t_u8 osen_enabled;
+} wlan_802_11_security_t;
+
+/** Current Basic Service Set State Structure */
+typedef struct {
+ /** BSS descriptor */
+ BSSDescriptor_t bss_descriptor;
+ /** WMM enable? */
+ t_u8 wmm_enabled;
+ /** Uapsd enable?*/
+ t_u8 wmm_uapsd_enabled;
+ /** Band */
+ t_u8 band;
+ /** Number of rates supported */
+ t_u32 num_of_rates;
+ /** Supported rates*/
+ t_u8 data_rates[WLAN_SUPPORTED_RATES];
+ /** Host MLME flag*/
+ t_u8 host_mlme;
+ t_u8 use_mfp;
+} current_bss_params_t;
+
+/** Sleep_params */
+typedef struct _sleep_params_t {
+ /** Sleep parameter error */
+ t_u16 sp_error;
+ /** Sleep parameter offset */
+ t_u16 sp_offset;
+ /** Sleep parameter stable time */
+ t_u16 sp_stable_time;
+ /** Sleep parameter calibration control */
+ t_u8 sp_cal_control;
+ /** Sleep parameter external sleep clock */
+ t_u8 sp_ext_sleep_clk;
+ /** Sleep parameter reserved */
+ t_u16 sp_reserved;
+} sleep_params_t;
+
+/** Sleep_period */
+typedef struct sleep_period_t {
+ /** Sleep period */
+ t_u16 period;
+ /** Reserved */
+ t_u16 reserved;
+} sleep_period_t;
+
+/** mrvl_wep_key_t */
+typedef struct _mrvl_wep_key_t {
+ /** Length */
+ t_u32 length;
+ /** WEP key index */
+ t_u32 key_index;
+ /** WEP key length */
+ t_u32 key_length;
+ /** WEP keys */
+ t_u8 key_material[MRVL_KEY_BUFFER_SIZE_IN_BYTE];
+} mrvl_wep_key_t;
+
+/** Maximum number of region channel */
+#define MAX_REGION_CHANNEL_NUM 2
+
+/** Region-band mapping table */
+typedef struct _region_chan_t {
+ /** TRUE if this entry is valid */
+ t_u8 valid;
+ /** Region code for US, Japan ... */
+ t_u8 region;
+ /** Band B/G/A, used for BAND_CONFIG cmd */
+ t_u8 band;
+ /** Actual No. of elements in the array below */
+ t_u8 num_cfp;
+ /** chan-freq-txpower mapping table */
+ chan_freq_power_t *pcfp;
+} region_chan_t;
+
+/** State of 11d */
+typedef enum _state_11d_t {
+ DISABLE_11D = 0,
+ ENABLE_11D = 1,
+} state_11d_t;
+
+#define DEFAULT_11D_STATE DISABLE_11D
+
+/** Domain regulatory information */
+typedef struct _wlan_802_11d_domain_reg {
+ /** Country Code */
+ t_u8 country_code[COUNTRY_CODE_LEN];
+ /** band that channels in sub_band belong to */
+ t_u8 band;
+ /** No. of subband in below */
+ t_u8 no_of_sub_band;
+ /** Subband data to send/last sent */
+ IEEEtypes_SubbandSet_t sub_band[MRVDRV_MAX_SUBBAND_802_11D];
+} wlan_802_11d_domain_reg_t;
+
+/** Data for state machine */
+typedef struct _wlan_802_11d_state {
+ /** True for enabling 11D */
+ state_11d_t enable_11d;
+ /** True for user enabling 11D */
+ state_11d_t user_enable_11d;
+} wlan_802_11d_state_t;
+
+/** 802.11h State information kept in the 'mlan_private' driver structure */
+typedef struct {
+ /** Indicate 11h is enabled from host */
+ t_bool is_11h_host;
+ /** Indicates whether 11h is enabled in the driver */
+ t_bool is_11h_enabled;
+ /** Indicates whether 11h is active in the firmware */
+ t_bool is_11h_active;
+ /** Master device using automatic channel select */
+ t_bool adhoc_auto_sel_chan;
+ /** Set when driver receives a STOP TX event from fw */
+ t_bool tx_disabled;
+ /** Channel that ChanSwAnn was received for, non-zero = active */
+ t_u8 dfs_slave_csa_chan;
+ /** Expiry for above variable, seconds in system time */
+ t_u32 dfs_slave_csa_expire_at_sec;
+} wlan_11h_interface_state_t;
+
+#if defined(UAP_SUPPORT)
+/** UAP get info callback state kept in the 'mlan_private' driver structure */
+typedef struct {
+ /** UAP internal callback after wlan_uap_get_channel */
+ /** (parameter is really pointer to mlan_private) */
+ mlan_status (*get_chan_callback)(t_void *);
+ /** current ioctl_req (to be completed in callback) */
+ pmlan_ioctl_req pioctl_req_curr;
+ /** band config from MrvlIEtypes_channel_band_t */
+ Band_Config_t bandcfg;
+ /** channel from MrvlIEtypes_channel_band_t */
+ t_u8 channel;
+ /** beacon period (in msec) from MrvlIEtypes_beacon_period_t */
+ t_u16 beacon_period;
+ /** dtim period (no unit) from MrvlIEtypes_dtim_period_t */
+ t_u8 dtim_period;
+} wlan_uap_get_info_cb_t;
+#endif
+
+/** Data structure for WPS information */
+typedef struct {
+ /** WPS IE */
+ IEEEtypes_VendorSpecific_t wps_ie;
+ /** Session enable flag */
+ t_u8 session_enable;
+} wps_t;
+
+/** mlan_operations data structure */
+typedef struct _mlan_operations {
+ /** cmd init handler */
+ mlan_status (*init_cmd)(t_void *priv, t_u8 first_bss);
+ /** ioctl handler */
+ mlan_status (*ioctl)(t_void *adapter, pmlan_ioctl_req pioctl_req);
+ /** cmd handler */
+ mlan_status (*prepare_cmd)(t_void *priv, t_u16 cmd_no, t_u16 cmd_action,
+ t_u32 cmd_oid, t_void *pioctl_buf,
+ t_void *pdata_buf, t_void *pcmd_buf);
+ /** cmdresp handler */
+ mlan_status (*process_cmdresp)(t_void *priv, t_u16 cmdresp_no,
+ t_void *pcmd_buf, t_void *pioctl);
+ /** rx handler */
+ mlan_status (*process_rx_packet)(t_void *adapter, pmlan_buffer pmbuf);
+ /** event handler */
+ mlan_status (*process_event)(t_void *priv);
+ /** txpd handler */
+ t_void *(*process_txpd)(t_void *priv, pmlan_buffer pmbuf);
+ /** BSS role */
+ mlan_bss_role bss_role;
+} mlan_operations, *pmlan_operations;
+
+/** Private structure for MLAN */
+typedef struct _mlan_private {
+ /** Pointer to mlan_adapter */
+ struct _mlan_adapter *adapter;
+ /** BSS index */
+ t_u8 bss_index;
+ /** BSS type */
+ t_u8 bss_type;
+ /** BSS role */
+ t_u8 bss_role;
+ /** BSS virtual flag */
+ t_u8 bss_virtual;
+ /** BSS Priority */
+ t_u8 bss_priority;
+ /** BSS number */
+ t_u8 bss_num;
+ /** Frame type */
+ t_u8 frame_type;
+ /** MAC address information */
+ t_u8 curr_addr[MLAN_MAC_ADDR_LENGTH];
+ /** Media connection status */
+ t_bool media_connected;
+
+ /** Current packet filter */
+ t_u32 curr_pkt_filter;
+ /** Infrastructure mode */
+ t_u32 bss_mode;
+
+ /** Tx packet control */
+ t_u32 pkt_tx_ctrl;
+
+ /** Tx power level */
+ t_s16 tx_power_level;
+ /** Maximum Tx power level */
+ t_s8 max_tx_power_level;
+ /** Minimum Tx power level */
+ t_s8 min_tx_power_level;
+ /** Tx rate */
+ t_u8 tx_rate;
+ t_u8 tx_rate_info;
+ /*HE tx tone mode and DCM info*/
+ t_u8 ext_tx_rate_info;
+ /*HE rx tone mode and DCM info*/
+ t_u8 rxpd_rx_info;
+ /** rxpd_htinfo */
+ t_u8 rxpd_rate_info;
+ /** max amsdu size */
+ t_u16 max_amsdu;
+ /** amsdu disable flag */
+ t_u8 amsdu_disable;
+ /** 802.11n Device Capabilities for 2.4GHz */
+ t_u32 usr_dot_11n_dev_cap_bg;
+ /** 802.11n Device Capabilities for 5GHz */
+ t_u32 usr_dot_11n_dev_cap_a;
+ /** MIMO abstraction of MCSs supported by device */
+ t_u8 usr_dev_mcs_support;
+#ifdef UAP_SUPPORT
+ /** UAP 11n flag */
+ t_u8 is_11n_enabled;
+#endif /* UAP_SUPPORT */
+ /** UAP 11ac flag */
+ t_u8 is_11ac_enabled;
+ /** UAP 11ax flag */
+ t_u8 is_11ax_enabled;
+ /** tx vht_info */
+ t_u8 tx_vhtinfo;
+ /** rxpd_vhtinfo */
+ t_u8 rxpd_vhtinfo;
+ /** 802.11ac Device Capabilities for 2.4GHz */
+ t_u32 usr_dot_11ac_dev_cap_bg;
+ /** 802.11ac Device Capabilities for 5GHz */
+ t_u32 usr_dot_11ac_dev_cap_a;
+ /** MIMO abstraction of MCSs supported by device */
+ t_u32 usr_dot_11ac_mcs_support;
+ /** user dot 11ac_BW */
+ t_u8 usr_dot_11ac_bw;
+ /** user dot 11ac_opermode_BW */
+ t_u8 usr_dot_11ac_opermode_bw;
+ /** user dot 11ac_opermode_nss */
+ t_u8 usr_dot_11ac_opermode_nss;
+ /** length of hw he capability */
+ t_u8 user_hecap_len;
+ /** user configured 802.11ax HE capability */
+ t_u8 user_he_cap[54];
+ /** length of hw he capability */
+ t_u8 user_2g_hecap_len;
+ /** user configured 802.11ax HE capability */
+ t_u8 user_2g_he_cap[54];
+ /** dropped pkts */
+ t_u32 num_drop_pkts;
+#ifdef UAP_SUPPORT
+ /** packet forward control */
+ t_u8 pkt_fwd;
+#endif
+ /** TX beamforming capability */
+ t_u32 tx_bf_cap;
+ /** Rx PD rate */
+ t_u8 rxpd_rate;
+ /** Bitmap rates */
+ t_u16 bitmap_rates[MAX_BITMAP_RATES_SIZE];
+ /** Data rate */
+ t_u32 data_rate;
+ /** Automatic data rate flag */
+ t_u8 is_data_rate_auto;
+ /** Factor for calculating beacon average */
+ t_u16 bcn_avg_factor;
+ /** Factor for calculating data average */
+ t_u16 data_avg_factor;
+ /** SNR */
+ t_s8 snr;
+ /** Noise Floor */
+ t_s8 nf;
+ /** Last data RSSI */
+ t_s16 data_rssi_last;
+ /** Last data Noise Floor */
+ t_s16 data_nf_last;
+ /** Average data RSSI */
+ t_s16 data_rssi_avg;
+ /** Averag data Noise Floor */
+ t_s16 data_nf_avg;
+ /** Last beacon RSSI */
+ t_s16 bcn_rssi_last;
+ /** Last beacon Noise Floor */
+ t_s16 bcn_nf_last;
+ /** Average beacon RSSI */
+ t_s16 bcn_rssi_avg;
+ /** Average beacon Noise Floor */
+ t_s16 bcn_nf_avg;
+ /** Attempted BSS descriptor */
+ BSSDescriptor_t *pattempted_bss_desc;
+
+ /** GTK rekey data*/
+ mlan_ds_misc_gtk_rekey_data gtk_rekey;
+
+ /** Current SSID/BSSID related parameters*/
+ current_bss_params_t curr_bss_params;
+ /** current channel flags */
+ t_u32 curr_chan_flags;
+ /** User selected bands */
+ t_u16 config_bands;
+
+ /** Beacon period */
+ t_u16 beacon_period;
+ /** Listen interval */
+ t_u16 listen_interval;
+ /** ATIM window */
+ t_u16 atim_window;
+
+ /** AdHoc channel */
+ t_u8 adhoc_channel;
+ /** AdHoc link sensed flag */
+ t_u8 adhoc_is_link_sensed;
+ /** AdHoc operating state */
+ t_u8 adhoc_state;
+#if defined(STA_SUPPORT)
+ /** AdHoc operating state backup */
+ t_u8 adhoc_state_prev;
+ /** AdHoc previous ssid used for Start */
+ mlan_802_11_ssid adhoc_last_start_ssid;
+#endif
+ /** FSM variable for 11d support */
+ wlan_802_11d_state_t state_11d;
+ /** FSM variable for 11h support */
+ wlan_11h_interface_state_t intf_state_11h;
+#ifdef UAP_SUPPORT
+ /** Whether UAP interface has started */
+ t_bool uap_bss_started;
+ /** Whether UAP interface start from hostapd */
+ t_bool uap_host_based;
+ /**UAP operating channel*/
+ t_u8 uap_channel;
+ /** state variable for UAP Get Info callback */
+ wlan_uap_get_info_cb_t uap_state_chan_cb;
+#endif /* UAP_SUPPORT */
+
+ /** Security related */
+ /** Encryption parameter */
+ wlan_802_11_security_t sec_info;
+ /** WEP keys */
+ mrvl_wep_key_t wep_key[MRVL_NUM_WEP_KEY];
+ /** Current WEP key index */
+ t_u16 wep_key_curr_index;
+ /** EWPA query 0: disable, 1: enable */
+ t_u8 ewpa_query;
+ /** Encryption Key*/
+ t_u8 wpa_ie[256];
+ /** WPA IE length */
+ t_u8 wpa_ie_len;
+ /** GTK set flag */
+ t_u8 wpa_is_gtk_set;
+ /** AES key material */
+ mlan_ds_encrypt_key aes_key;
+#if defined(STA_SUPPORT)
+ /* Mgmt Frame Protection config */
+ mlan_ds_misc_pmfcfg pmfcfg;
+#endif
+ /** WAPI IE */
+ t_u8 wapi_ie[256];
+ /** WAPI IE length */
+ t_u8 wapi_ie_len;
+ /** OSEN IE */
+ t_u8 osen_ie[256];
+ /** OSEN IE length */
+ t_u8 osen_ie_len;
+ /** Pointer to the station table */
+ mlan_list_head sta_list;
+
+ /** MGMT IE */
+ custom_ie mgmt_ie[MAX_MGMT_IE_INDEX];
+ /** mgmt frame passthru mask */
+ t_u32 mgmt_frame_passthru_mask;
+ /** WMM required */
+ t_u8 wmm_required;
+ /** WMM enabled */
+ t_u8 wmm_enabled;
+ /** WMM qos info */
+ t_u8 wmm_qosinfo;
+ /** WMM related variable*/
+ wmm_desc_t wmm;
+
+ /** Pointer to the Transmit BA stream table*/
+ mlan_list_head tx_ba_stream_tbl_ptr;
+ /** Pointer to the priorities for AMSDU/AMPDU table*/
+ tx_aggr_t aggr_prio_tbl[MAX_NUM_TID];
+ /** Pointer to the priorities for AMSDU/AMPDU table*/
+ t_u8 addba_reject[MAX_NUM_TID];
+ /** Pointer to the priorities for AMSDU/AMPDU table*/
+ t_u8 ibss_ampdu[MAX_NUM_TID];
+ /** Pointer to the priorities for AMSDU/AMPDU table*/
+ t_u8 ibss_addba_reject[MAX_NUM_TID];
+ /** Struct to store ADDBA parameters */
+ add_ba_param_t add_ba_param;
+ /** user rx_win_size */
+ t_u32 user_rxwinsize;
+ /** last rx_seq */
+ t_u16 rx_seq[MAX_NUM_TID];
+ /** Pointer to the Receive Reordering table*/
+ mlan_list_head rx_reorder_tbl_ptr;
+ /** Lock for Rx packets */
+ t_void *rx_pkt_lock;
+
+#ifdef STA_SUPPORT
+ /** Buffer to store the association response for application retrieval
+ */
+ t_u8 assoc_rsp_buf[MRVDRV_ASSOC_RSP_BUF_SIZE];
+ /** Length of the data stored in assoc_rsp_buf */
+ t_u32 assoc_rsp_size;
+
+ /** Generic IEEE IEs passed from the application to be inserted into the
+ * association request to firmware
+ */
+ t_u8 gen_ie_buf[MRVDRV_GENIE_BUF_SIZE];
+ /** Length of the data stored in gen_ie_buf */
+ t_u8 gen_ie_buf_len;
+
+ /** disconnect reason code*/
+ t_u16 disconnect_reason_code;
+ t_u8 *pcurr_bcn_buf;
+ t_u32 curr_bcn_size;
+ t_void *curr_bcn_buf_lock;
+
+ /** WPS */
+ wps_t wps;
+#endif /* STA_SUPPORT */
+
+ /** function table */
+ mlan_operations ops;
+ /** tx pause flag */
+ t_u8 tx_pause;
+ /** Port Control mode */
+ t_u8 port_ctrl_mode;
+
+ /** Port open flag */
+ t_u8 port_open;
+
+ /** Port open flag state at time of association attempt */
+ t_u8 prior_port_status;
+ /** Bypass TX queue */
+ mlan_list_head bypass_txq;
+ /** IP address operation */
+ t_u32 op_code;
+ /** IP address */
+ t_u8 ip_addr[IPADDR_LEN];
+ t_u32 hotspot_cfg;
+#ifdef STA_SUPPORT
+ ExtCap_t ext_cap;
+ ExtCap_t def_ext_cap;
+#endif
+ /** interface header len */
+ t_u8 intf_hr_len;
+#ifdef USB
+ /** USB data port */
+ t_u32 port;
+#endif
+#if defined(DRV_EMBEDDED_AUTHENTICATOR) || defined(DRV_EMBEDDED_SUPPLICANT)
+ t_void *psapriv;
+#endif
+ /** rx per packet info */
+ t_u8 rx_pkt_info;
+ /** received amsdu count*/
+ t_u32 amsdu_rx_cnt;
+ /** received msdu count in amsdu*/
+ t_u32 msdu_in_rx_amsdu_cnt;
+ /** tx amsdu count*/
+ t_u32 amsdu_tx_cnt;
+ /** tx msdu count in amsdu*/
+ t_u32 msdu_in_tx_amsdu_cnt;
+} mlan_private, *pmlan_private;
+
+typedef struct _assoc_logger {
+ /** vendor specific */
+ t_u8 oui[3];
+ t_u8 bssid[MLAN_MAC_ADDR_LENGTH];
+ t_u8 ssid[MLAN_MAX_SSID_LENGTH];
+ t_s32 rssi;
+ t_u32 channel;
+} assoc_logger_data;
+
+/** Tx BA stream table */
+struct _TxBAStreamTbl {
+ /** TxBAStreamTbl previous node */
+ TxBAStreamTbl *pprev;
+ /** TxBAStreamTbl next node */
+ TxBAStreamTbl *pnext;
+ /** TID */
+ int tid;
+ /** RA */
+ t_u8 ra[MLAN_MAC_ADDR_LENGTH];
+ /** BA stream status */
+ baStatus_e ba_status;
+ t_u8 amsdu;
+};
+
+/** RX reorder table */
+typedef struct _RxReorderTbl RxReorderTbl;
+
+typedef struct {
+ /** Timer for flushing */
+ t_void *timer;
+ /** Timer set flag */
+ t_u8 timer_is_set;
+ /** RxReorderTbl ptr */
+ RxReorderTbl *ptr;
+ /** Priv pointer */
+ mlan_private *priv;
+} reorder_tmr_cnxt_t;
+
+/** RX reorder table */
+struct _RxReorderTbl {
+ /** RxReorderTbl previous node */
+ RxReorderTbl *pprev;
+ /** RxReorderTbl next node */
+ RxReorderTbl *pnext;
+ /** TID */
+ int tid;
+ /** TA */
+ t_u8 ta[MLAN_MAC_ADDR_LENGTH];
+ /** Start window */
+ int start_win;
+ /** last_seq */
+ int last_seq;
+ /** Window size */
+ int win_size;
+ /** Pointer to pointer to RxReorderTbl */
+ t_void **rx_reorder_ptr;
+ /** Timer context */
+ reorder_tmr_cnxt_t timer_context;
+ /** BA stream status */
+ baStatus_e ba_status;
+ t_u8 amsdu;
+ /** no packet drop flag for rx_reorder_tbl */
+ t_u8 force_no_drop;
+ /** flag for check start win */
+ t_u8 check_start_win;
+ /** pkt receive after BA setup */
+ t_u8 pkt_count;
+ /** flush data flag */
+ t_u8 flush_data;
+};
+
+/** BSS priority node */
+typedef struct _mlan_bssprio_node mlan_bssprio_node;
+
+/** BSS priority node */
+struct _mlan_bssprio_node {
+ /** Pointer to previous node */
+ mlan_bssprio_node *pprev;
+ /** Pointer to next node */
+ mlan_bssprio_node *pnext;
+ /** Pointer to priv */
+ pmlan_private priv;
+};
+
+/** BSS priority table */
+typedef struct _mlan_bssprio_tbl mlan_bssprio_tbl;
+
+/** BSS priority table */
+struct _mlan_bssprio_tbl {
+ /** BSS priority list head */
+ mlan_list_head bssprio_head;
+ /** Current priority node */
+ mlan_bssprio_node *bssprio_cur;
+};
+
+/** cmd_ctrl_node */
+typedef struct _cmd_ctrl_node cmd_ctrl_node;
+
+/** _cmd_ctrl_node */
+struct _cmd_ctrl_node {
+ /** Pointer to previous node */
+ cmd_ctrl_node *pprev;
+ /** Pointer to next node */
+ cmd_ctrl_node *pnext;
+ /** Pointer to priv */
+ pmlan_private priv;
+ /** Command number */
+ t_u32 cmd_no;
+ /** Command flag */
+ t_u32 cmd_flag;
+ /** Pointer to mlan_buffer */
+ mlan_buffer *cmdbuf;
+ /** Pointer to mlan_buffer */
+ mlan_buffer *respbuf;
+ /** Command parameter */
+ t_void *pdata_buf;
+ /** Pointer to mlan_ioctl_req if command is from IOCTL */
+ t_void *pioctl_buf;
+#if defined(PCIE) || defined(SDIO)
+ /** pre_allocated mlan_buffer for cmd */
+ mlan_buffer *pmbuf;
+#endif
+};
+
+/** station node */
+typedef struct _sta_node sta_node, *psta_node;
+
+/** station node*/
+struct _sta_node {
+ /** previous node */
+ sta_node *pprev;
+ /** next node */
+ sta_node *pnext;
+ /** station mac address */
+ t_u8 mac_addr[MLAN_MAC_ADDR_LENGTH];
+ /** wmm flag */
+ t_u8 is_wmm_enabled;
+ /** 11n flag */
+ t_u8 is_11n_enabled;
+ /** AMPDU STA */
+ t_u8 ampdu_sta[MAX_NUM_TID];
+ /** last rx_seq */
+ t_u16 rx_seq[MAX_NUM_TID];
+ /** max amsdu size */
+ t_u16 max_amsdu;
+ /** HT cap */
+ IEEEtypes_HTCap_t HTcap;
+ /** 11ac flag */
+ t_u8 is_11ac_enabled;
+ /** UAP 11ax flag */
+ t_u8 is_11ax_enabled;
+ /** SNR */
+ t_s8 snr;
+ /** Noise Floor */
+ t_s8 nf;
+ /** peer capability */
+ t_u16 capability;
+ /** wapi key on off flag */
+ t_u8 wapi_key_on;
+ /** tx pause status */
+ t_u8 tx_pause;
+ /** station band mode */
+ t_u16 bandmode;
+#if defined(DRV_EMBEDDED_AUTHENTICATOR) || defined(DRV_EMBEDDED_SUPPLICANT)
+ t_void *cm_connectioninfo;
+#endif
+ sta_stats stats;
+};
+
+/** 802.11h State information kept in the 'mlan_adapter' driver structure */
+typedef struct {
+ /** Min TX Power capability sent to FW for 11h use and fw power control
+ */
+ t_s8 min_tx_power_capability;
+ /** Max TX Power capability sent to FW for 11h use and fw power control
+ */
+ t_s8 max_tx_power_capability;
+ /** User provisioned local power constraint sent in association requests
+ */
+ t_s8 usr_def_power_constraint;
+ /** Received CHANNEL_SWITCH_ANN event */
+ t_bool recvd_chanswann_event;
+ /** Indicates an interface wants to enable master radar detection */
+ t_bool master_radar_det_enable_pending;
+ /** Indicates an interface wants to enable slave radar detection */
+ t_bool slave_radar_det_enable_pending;
+ /** Indicates whether master radar detection active in the firmware */
+ t_bool is_master_radar_det_active;
+ /** Indicates whether slave radar detection active in the firmware */
+ t_bool is_slave_radar_det_active;
+ /** Quiet IE */
+ IEEEtypes_Quiet_t quiet_ie;
+} wlan_11h_device_state_t;
+
+/** Enumeration for DFS Timestamp represents field */
+enum _dfs_timestamp_repr_e {
+ /** Ignore entry */
+ DFS_TS_REPR_NOT_IN_USE = 0,
+ /** NOP (Non-Occupancy Period) start time */
+ DFS_TS_REPR_NOP_START = 1,
+ /** CAC (Channel Availability Check) completion time */
+ DFS_TS_REPR_CAC_COMPLETION
+};
+
+/** DFS Timestamp type used for marking NOP/CAC events */
+typedef struct _wlan_dfs_timestamp_t wlan_dfs_timestamp_t;
+
+/** DFS Timestamp type used for marking NOP/CAC events */
+struct _wlan_dfs_timestamp_t {
+ /** Pointer to previous node */
+ wlan_dfs_timestamp_t *pprev;
+ /** Pointer to next node */
+ wlan_dfs_timestamp_t *pnext;
+ /** WLAN Channel number */
+ t_u8 channel;
+ /** What this timestamp represents */
+ t_u8 represents;
+ /** reserved field */
+ t_u16 reserved;
+ /** timestamp - seconds */
+ t_u32 ts_sec;
+ /** timestamp - microseconds */
+ t_u32 ts_usec;
+};
+
+/** DFS State information kept in the 'mlan_adapter' driver structure */
+typedef struct {
+ /** Indicates whether DFS channel check is occurring in firmware */
+ t_bool dfs_check_pending;
+ /** Indicates whether DFS channel check found radar */
+ t_bool dfs_radar_found;
+ /** Channel radar is being checked on. BAND_A is assumed. */
+ t_u8 dfs_check_channel;
+ /** point to the priv which start the DFS check */
+ t_void *dfs_check_priv;
+ /** Timestamp when we got last report,
+ * to determine if data is old or not.
+ */
+ t_u32 dfs_report_time_sec;
+ /** List for holding dfs_timestamps for NOP/CAC events */
+ mlan_list_head dfs_ts_head;
+} wlan_dfs_device_state_t;
+
+/** Enumeration for mlan_ds_11h_radar_det_hndlg stages */
+enum _mlan_ds_11h_rdh_stages {
+ RDH_OFF = 0,
+ RDH_CHK_INTFS = 1,
+ RDH_STOP_TRAFFIC,
+ RDH_GET_INFO_CHANNEL,
+ RDH_GET_INFO_BEACON_DTIM,
+ RDH_SET_CUSTOM_IE,
+ RDH_REM_CUSTOM_IE,
+ RDH_STOP_INTFS,
+ RDH_SET_NEW_CHANNEL,
+ RDH_RESTART_INTFS,
+ RDH_RESTART_TRAFFIC
+};
+
+/** State info for Radar Detected Handling kept in 'mlan_adapter' */
+typedef struct {
+ /** Stage (of Operation) */
+ t_u8 stage;
+ /** Number of interfaces to handle */
+ t_u8 priv_list_count;
+ /** Index of interface in process (used by some stages) */
+ t_u8 priv_curr_idx;
+ /** Current Channel (to leave) */
+ t_u8 curr_channel;
+ /** New Channel (to switch to) */
+ t_u8 new_channel;
+ /** UAP band_config */
+ Band_Config_t uap_band_cfg;
+ /** BEACON*DTIM period (in msec; max of STA/UAP) */
+ t_u16 max_bcn_dtim_ms;
+ /** tx block flag */
+ t_u8 tx_block;
+ /** List of interfaces to handle */
+ mlan_private *priv_list[MLAN_MAX_BSS_NUM];
+} wlan_radar_det_hndlg_state_t;
+
+/** DFS/RDH testing exception settings kept in 'mlan_adapter' */
+typedef struct {
+ /** user-configured CAC period (in msec) */
+ t_u32 user_cac_period_msec;
+ /** user-configured NOP period (in sec) */
+ t_u16 user_nop_period_sec;
+ /** user-configured skip channel change on radar */
+ t_bool no_channel_change_on_radar;
+ /** user-configured new channel to change to on radar */
+ t_u8 fixed_new_channel_on_radar;
+ /** user-configured cac restart */
+ t_u8 cac_restart;
+ /** cac channel */
+ t_u8 chan;
+ /** band cfg */
+ Band_Config_t bandcfg;
+ /** cac time */
+ t_u32 millisec_dwell_time;
+} wlan_dfs_testing_settings_t;
+
+/**
+ * @brief Driver measurement state held in 'mlan_adapter' structure
+ *
+ * Used to record a measurement request that the driver is pending on
+ * the result (received measurement report).
+ */
+typedef struct {
+ /**
+ * Dialog token of a pending measurement request/report. Used to
+ * block execution while waiting for the specific dialog token
+ */
+ t_u8 meas_rpt_pend_on;
+
+ /**
+ * Measurement report received from the firmware that we were pending on
+ */
+ HostCmd_DS_MEASUREMENT_REPORT meas_rpt_returned;
+
+} wlan_meas_state_t;
+
+#ifdef SDIO
+/**
+ * @brief Link buffer into aggregate head buffer
+ *
+ * @param pmbuf_aggr Pointer to aggregation buffer
+ * @param pmbuf Pointer to buffer to copy
+ */
+static inline t_void wlan_link_buf_to_aggr(pmlan_buffer pmbuf_aggr,
+ pmlan_buffer pmbuf)
+{
+ /* link new buf at end of list */
+ pmbuf->pnext = pmbuf_aggr;
+ pmbuf->pprev = pmbuf_aggr->pprev;
+ pmbuf->pparent = pmbuf_aggr;
+ pmbuf_aggr->pprev->pnext = pmbuf;
+ pmbuf_aggr->pprev = pmbuf;
+ pmbuf_aggr->use_count++;
+}
+
+/** data structure for SDIO MPA TX */
+typedef struct _sdio_mpa_tx {
+ /** allocated buf for tx aggreation */
+ t_u8 *head_ptr;
+ /** multiport tx aggregation buffer pointer */
+ t_u8 *buf;
+ /** multiport tx aggregation buffer length */
+ t_u32 buf_len;
+ /** multiport tx aggregation packet count */
+ t_u32 pkt_cnt;
+ /** multiport tx aggregation ports */
+ t_u32 ports;
+ /** multiport tx aggregation starting port */
+ t_u16 start_port;
+ /** multiport tx aggregation enable/disable flag */
+ t_u8 enabled;
+ /** multiport tx aggregation buffer size */
+ t_u32 buf_size;
+ /** multiport tx aggregation pkt aggr limit */
+ t_u32 pkt_aggr_limit;
+ /** multiport write info */
+ t_u16 mp_wr_info[SDIO_MP_AGGR_DEF_PKT_LIMIT_MAX];
+ /** multiport rx aggregation mbuf array */
+ pmlan_buffer mbuf_arr[SDIO_MP_AGGR_DEF_PKT_LIMIT_MAX];
+} sdio_mpa_tx;
+
+/** data structure for SDIO MPA RX */
+typedef struct _sdio_mpa_rx {
+ /** allocated buf for rx aggreation */
+ t_u8 *head_ptr;
+ /** multiport rx aggregation buffer pointer */
+ t_u8 *buf;
+ /** multiport rx aggregation buffer length */
+ t_u32 buf_len;
+ /** multiport rx aggregation packet count */
+ t_u32 pkt_cnt;
+ /** multiport rx aggregation ports */
+ t_u32 ports;
+ /** multiport rx aggregation starting port */
+ t_u16 start_port;
+
+ /** multiport rx aggregation mbuf array */
+ pmlan_buffer mbuf_arr[SDIO_MP_AGGR_DEF_PKT_LIMIT_MAX];
+ /** multiport rx aggregation pkt len array */
+ t_u32 len_arr[SDIO_MP_AGGR_DEF_PKT_LIMIT_MAX];
+
+ /** multiport rx aggregation enable/disable flag */
+ t_u8 enabled;
+ /** multiport rx aggregation buffer size */
+ t_u32 buf_size;
+ /** multiport rx aggregation pkt aggr limit */
+ t_u32 pkt_aggr_limit;
+} sdio_mpa_rx;
+#endif
+
+#ifdef USB
+/** data structure for USB Rx Deaggregation */
+typedef struct _usb_rx_deaggr_params {
+ /** Rx aggregation control */
+ usb_aggr_ctrl aggr_ctrl;
+} usb_rx_deaggr_params;
+
+#define MAX_USB_TX_PORT_NUM 1
+/** data structure for USB Tx Aggregation */
+typedef struct _usb_tx_aggr_params {
+ /** Tx aggregation control */
+ usb_aggr_ctrl aggr_ctrl;
+ /** allocated pmbuf for tx aggreation */
+ pmlan_buffer pmbuf_aggr;
+ /** packet len used in pmbuf_aggr */
+ t_u32 aggr_len;
+ /** usb_tx_aggr timer */
+ t_void *paggr_hold_timer;
+ /** usb_tx_aggr timer set flag */
+ t_u8 aggr_hold_timer_is_set;
+ /** Timeout duration in milliseconds to wait for aggregation */
+ t_u32 hold_timeout_msec;
+ /** lock for transmission */
+ t_void *paggr_lock;
+ /** port for data transmission */
+ t_u32 port;
+ /** pointer to moal_adatper structure */
+ t_void *phandle;
+} usb_tx_aggr_params, *pusb_tx_aggr_params;
+#endif
+
+/** Type definition of mef_entry*/
+typedef struct _mef_cfg {
+ /** criteria*/
+ t_u32 criteria;
+ /** entry num*/
+ t_u16 entry_num;
+ /** entry pointer*/
+ mef_entry_t *pentry;
+} mef_cfg;
+
+/** Type definition of mef_entry*/
+typedef struct _mef_entry {
+ /** Num for wowlan entry*/
+ int num_wowlan_entry;
+ /** Num for IPv6 neighbor solicitation message offload */
+ int num_ipv6_ns_offload;
+
+ /** criteria*/
+ t_u32 criteria;
+ /** MEF CFG Array to store etted_entry_bitmap;
+ * Caution: 0-3 is for NVIDIA WHITE/BLACK list entries
+ * Caution: 4 is for NVIDIA ping entry
+ * Caution: 5 is for Auto Arp Entry
+ * Caution: 6 is for wowlan Entry
+ * Caution: 7 is for IPv6 Neighbor Solicitation offload Entry
+ */
+ mef_entry_t entry[MAX_NUM_ENTRIES];
+} mef_entry;
+
+/** vdll_dnld_ctrl structure */
+typedef struct _vdll_dnld_ctrl {
+ /** pending VDLL block */
+ t_u8 *pending_block;
+ /* pending VDLL block len */
+ t_u16 pending_block_len;
+ /** memory for VDLL fw image */
+ t_u8 *vdll_mem;
+ /** VDLL fw image len */
+ t_u32 vdll_len;
+#if defined(SDIO) || defined(PCIE)
+ /** mlan_buffer for VDLL download */
+ mlan_buffer *cmd_buf;
+#endif
+} vdll_dnld_ctrl, *pvdll_dnld_ctrl;
+
+/** mlan_init_para structure */
+typedef struct _mlan_init_para {
+#ifdef MFG_CMD_SUPPORT
+ /** MFG mode */
+ t_u32 mfg_mode;
+#endif
+#ifdef SDIO
+ /** SDIO interrupt mode (0: INT_MODE_SDIO, 1: INT_MODE_GPIO) */
+ t_u32 int_mode;
+ /** GPIO interrupt pin number */
+ t_u32 gpio_pin;
+ /** SDIO MPA Tx */
+ t_u32 mpa_tx_cfg;
+ /** SDIO MPA Rx */
+ t_u32 mpa_rx_cfg;
+#endif
+ /** Auto deep sleep */
+ t_u32 auto_ds;
+ /** IEEE PS mode */
+ t_u32 ps_mode;
+ /** Max Tx buffer size */
+ t_u32 max_tx_buf;
+ /** 802.11d configuration */
+ t_u32 cfg_11d;
+ /** 802.11H DFS Master Radar Detect */
+ t_u32 dfs_master_radar_det_en;
+ /** 802.11H DFS Slave Radar Detect */
+ t_u32 dfs_slave_radar_det_en;
+ /** dev cap mask */
+ t_u32 dev_cap_mask;
+ /** oob independent reset mode */
+ t_u32 indrstcfg;
+ /** fw region */
+ t_bool fw_region;
+ /** passive to active scan */
+ t_u8 passive_to_active_scan;
+ /** uap max sta */
+ t_u8 uap_max_sta;
+ /** dfs w53 cfg */
+ t_u8 dfs53cfg;
+} mlan_init_para, *pmlan_init_para;
+
+#ifdef SDIO
+typedef struct _mlan_sdio_card_reg {
+ t_u8 start_rd_port;
+ t_u8 start_wr_port;
+ t_u8 base_0_reg;
+ t_u8 base_1_reg;
+ t_u8 poll_reg;
+ t_u8 host_int_enable;
+ t_u8 host_int_status;
+ t_u8 status_reg_0;
+ t_u8 status_reg_1;
+ t_u8 sdio_int_mask;
+ t_u32 data_port_mask;
+ t_u8 max_mp_regs;
+ t_u8 rd_bitmap_l;
+ t_u8 rd_bitmap_u;
+ t_u8 rd_bitmap_1l;
+ t_u8 rd_bitmap_1u;
+ t_u8 wr_bitmap_l;
+ t_u8 wr_bitmap_u;
+ t_u8 wr_bitmap_1l;
+ t_u8 wr_bitmap_1u;
+ t_u8 rd_len_p0_l;
+ t_u8 rd_len_p0_u;
+ t_u8 card_config_2_1_reg;
+ t_u8 cmd_config_0;
+ t_u8 cmd_config_1;
+ t_u8 cmd_config_2;
+ t_u8 cmd_config_3;
+ t_u8 cmd_rd_len_0;
+ t_u8 cmd_rd_len_1;
+ t_u8 cmd_rd_len_2;
+ t_u8 cmd_rd_len_3;
+ t_u8 io_port_0_reg;
+ t_u8 io_port_1_reg;
+ t_u8 io_port_2_reg;
+ t_u8 host_int_rsr_reg;
+ t_u8 host_int_mask_reg;
+ t_u8 host_int_status_reg;
+ t_u8 host_restart_reg;
+ t_u8 card_to_host_event_reg;
+ t_u8 host_interrupt_mask_reg;
+ t_u8 card_interrupt_status_reg;
+ t_u8 card_interrupt_rsr_reg;
+ t_u8 card_revision_reg;
+ t_u8 card_ocr_0_reg;
+ t_u8 card_ocr_1_reg;
+ t_u8 card_ocr_3_reg;
+ t_u8 card_config_reg;
+ t_u8 card_misc_cfg_reg;
+ t_u8 debug_0_reg;
+ t_u8 debug_1_reg;
+ t_u8 debug_2_reg;
+ t_u8 debug_3_reg;
+ t_u32 fw_reset_reg;
+ t_u8 fw_reset_val;
+ t_u8 fw_dnld_offset_0_reg;
+ t_u8 fw_dnld_offset_1_reg;
+ t_u8 fw_dnld_offset_2_reg;
+ t_u8 fw_dnld_offset_3_reg;
+ t_u8 fw_dnld_status_0_reg;
+ t_u8 fw_dnld_status_1_reg;
+ t_u8 winner_check_reg;
+} mlan_sdio_card_reg, *pmlan_sdio_card_reg;
+
+typedef struct _mlan_sdio_card {
+ const mlan_sdio_card_reg *reg;
+
+ /** IO port */
+ t_u32 ioport;
+ /** number of interrupt receive */
+ t_u32 num_of_irq;
+ /** max SDIO single port tx size */
+ t_u16 max_sp_tx_size;
+ /** max SDIO single port rx size */
+ t_u16 max_sp_rx_size;
+ /** SDIO multiple port read bitmap */
+ t_u32 mp_rd_bitmap;
+ /** SDIO multiple port write bitmap */
+ t_u32 mp_wr_bitmap;
+ /** SDIO end port from txbufcfg */
+ t_u16 mp_end_port;
+ /** SDIO port mask calculated based on txbufcfg end port */
+ t_u32 mp_data_port_mask;
+ /** Current available port for read */
+ t_u8 curr_rd_port;
+ /** Current available port for write */
+ t_u8 curr_wr_port;
+ /** FW update port number */
+ t_u32 mp_update[SDIO_MP_AGGR_DEF_PKT_LIMIT_MAX * 2];
+ /** Invalid port update count */
+ t_u32 mp_invalid_update;
+ /** Array to store values of SDIO multiple port group registers */
+ t_u8 *mp_regs;
+ /** allocated buf to read SDIO multiple port group registers */
+ t_u8 *mp_regs_buf;
+ /** buffer to handle receive packet */
+ t_u8 *rx_buf;
+ /** allocated buf for receive */
+ t_u8 *rx_buffer;
+ /* see blk_queue_max_segment_size */
+ t_u32 max_seg_size;
+ /* see blk_queue_max_segments */
+ t_u16 max_segs;
+
+ /** data structure for SDIO MPA TX */
+ sdio_mpa_tx mpa_tx;
+ /** packet number for tx aggr */
+ t_u32 mpa_tx_count[SDIO_MP_AGGR_DEF_PKT_LIMIT_MAX];
+ /** no more packets count*/
+ t_u32 mpa_sent_last_pkt;
+ /** no write_ports count */
+ t_u32 mpa_sent_no_ports;
+ /** last wr_bitmap from FW */
+ t_u32 last_recv_wr_bitmap;
+ /** last mp_wr_bitmap */
+ t_u32 last_mp_wr_bitmap[SDIO_MP_DBG_NUM];
+ /** last ports for cmd53 write data */
+ t_u32 last_mp_wr_ports[SDIO_MP_DBG_NUM];
+ /** last length for cmd53 write data */
+ t_u32 last_mp_wr_len[SDIO_MP_DBG_NUM];
+ /** length info for cmd53 write data */
+ t_u16 last_mp_wr_info[SDIO_MP_DBG_NUM * SDIO_MP_AGGR_DEF_PKT_LIMIT_MAX];
+ /** last curr_wr_port */
+ t_u8 last_curr_wr_port[SDIO_MP_DBG_NUM];
+
+ /** buffer for mp debug */
+ t_u8 *mpa_buf;
+ /** length info for mp buf size */
+ t_u32 mpa_buf_size;
+
+ /** last mp_index */
+ t_u8 last_mp_index;
+
+ /** data structure for SDIO MPA RX */
+ sdio_mpa_rx mpa_rx;
+ /** packet number for tx aggr */
+ t_u32 mpa_rx_count[SDIO_MP_AGGR_DEF_PKT_LIMIT_MAX];
+
+ /** SDIO interrupt mode (0: INT_MODE_SDIO, 1: INT_MODE_GPIO) */
+ t_u32 int_mode;
+ /** GPIO interrupt pin number */
+ t_u32 gpio_pin;
+
+ /** flag for sdio rx aggr */
+ t_bool sdio_rx_aggr_enable;
+ /** fw rx block size */
+ t_u16 sdio_rx_block_size;
+} mlan_sdio_card, *pmlan_sdio_card;
+#endif
+
+#ifdef PCIE
+/** 8 Event buffer ring */
+#define MLAN_MAX_EVT_BD 0x08
+/** 32 entry will mapping to 5*/
+#define TX_RX_NUM_DESC 5
+/** 8 entry will mapping to 3 */
+#define EVT_NUM_DESC 3
+typedef struct _mlan_pcie_card_reg {
+ /* TX buffer description rd pointer */
+ t_u32 reg_txbd_rdptr;
+ /* TX buffer description wr pointer */
+ t_u32 reg_txbd_wrptr;
+ /* RX buffer description rd pointer */
+ t_u32 reg_rxbd_rdptr;
+ /* RX buffer description wr pointer */
+ t_u32 reg_rxbd_wrptr;
+ /** evtbd rdptr register */
+ t_u32 reg_evtbd_rdptr;
+ /** evtbd wrptr register */
+ t_u32 reg_evtbd_wrptr;
+ /** host int mask register */
+ t_u16 reg_host_int_mask;
+ /** host int status mask register*/
+ t_u16 reg_host_int_status_mask;
+ /** host int status register */
+ t_u16 reg_host_int_status;
+ /** host int status clr selection */
+ t_u32 reg_host_int_clr_sel;
+ /** cpu int event register */
+ t_u16 reg_cpu_int_event;
+ /** ip revision register */
+ t_u16 reg_ip_rev;
+ /** revision id register */
+ t_u32 reg_rev_id;
+ /** driver ready register */
+ t_u16 reg_drv_ready;
+ /** cpu int status register */
+ t_u16 reg_cpu_int_status;
+ /** scratch 0 register */
+ t_u16 reg_scratch_0;
+ /** scratch 1 register */
+ t_u16 reg_scratch_1;
+ /** scratch 2 register */
+ t_u16 reg_scratch_2;
+ /** scratch 3 register */
+ t_u16 reg_scratch_3;
+ /** scratch 6 register */
+ t_u16 reg_scratch_6;
+ /** scratch 7 register */
+ t_u16 reg_scratch_7;
+ /** host interrupt mask*/
+ t_u32 host_intr_mask;
+ /** data send interrupt for host*/
+ t_u32 host_intr_dnld_done;
+ /** Data receive interrupt for host */
+ t_u32 host_intr_upld_rdy;
+ /** Command sent interrupt for host */
+ t_u32 host_intr_cmd_done;
+ /** Event ready interrupt for host */
+ t_u32 host_intr_event_rdy;
+ t_u32 host_intr_cmd_dnld;
+ /* TX/RX buffer description mask */
+ t_u32 txrx_rw_ptr_mask;
+ /* TX/RX buffer description wrap mask */
+ t_u32 txrx_rw_ptr_wrap_mask;
+ /* TX/RX buffer description indication */
+ t_u32 txrx_rw_ptr_rollover_ind;
+ /** ADMA feature */
+ t_u8 use_adma;
+ /** write to clear interrupt status flag */
+ t_u8 msi_int_wr_clr;
+} mlan_pcie_card_reg, *pmlan_pcie_card_reg;
+
+typedef struct _mlan_pcie_card {
+ const mlan_pcie_card_reg *reg;
+ /** PCIE interrupt modes 0: Legacy, 1: MSI, 2:MSI-X */
+ t_u32 pcie_int_mode;
+ /** PCIE function number */
+ t_u8 func_num;
+ /** pending num of tx ring buffer in firmware */
+ t_u8 txbd_pending;
+ /** Write pointer for TXBD ring */
+ t_u32 txbd_wrptr;
+ /** Shadow copy of TXBD read pointer */
+ t_u32 txbd_rdptr;
+ /** TXBD ring size */
+ t_u32 txbd_ring_size;
+ /** Lock for protecting the TX ring */
+ t_void *tx_ring_lock;
+ /** Virtual base address of txbd_ring */
+ t_u8 *txbd_ring_vbase;
+ /** Physical base address of txbd_ring */
+ t_u64 txbd_ring_pbase;
+ /** Ring of buffer descriptors for TX */
+ t_void *txbd_ring[MLAN_MAX_TXRX_BD];
+ /** A list of mlan_buffer objects used for data tx */
+ mlan_buffer *tx_buf_list[MLAN_MAX_TXRX_BD];
+ /** Flush indicator for txbd_ring */
+ t_bool txbd_flush;
+
+ /** Shadow copy of RXBD write pointer */
+ t_u32 rxbd_wrptr;
+ /** RxBD read pointer */
+ t_u32 rxbd_rdptr;
+ /** RXBD ring size */
+ t_u32 rxbd_ring_size;
+ /** A spinlock for rxbd_ring */
+ t_void *rx_ring_lock;
+ /** Virtual base address of rxbd_ring */
+ t_u8 *rxbd_ring_vbase;
+ /** Physical base address of rxbd_ring */
+ t_u64 rxbd_ring_pbase;
+ /** Ring of buffer descriptors for RX */
+ t_void *rxbd_ring[MLAN_MAX_TXRX_BD];
+ /** A list of mlan_buffer objects used for data rx */
+ mlan_buffer *rx_buf_list[MLAN_MAX_TXRX_BD];
+
+ /** Shadow copy of cmdrsp/evt write pointer */
+ t_u32 evtbd_wrptr;
+ /** Read pointer for cmdrsp/evt ring */
+ t_u32 evtbd_rdptr;
+ /** Size of the cmdrsp/evt ring */
+ t_u32 evtbd_ring_size;
+ /** Virtual base address of evtbd_bd_ring */
+ t_u8 *evtbd_ring_vbase;
+ /** Physical base address of evtbd_bd_ring */
+ t_u64 evtbd_ring_pbase;
+ /** Ring of buffer descriptors for EVENT */
+ t_void *evtbd_ring[MLAN_MAX_EVT_BD];
+ /** A list of mlan_buffer objects used for EVENT */
+ mlan_buffer *evt_buf_list[MLAN_MAX_EVT_BD];
+
+ /** Command buffer */
+ mlan_buffer *cmd_buf;
+ /** Command response buffer */
+ mlan_buffer *cmdrsp_buf;
+ /** Command buffer */
+ mlan_buffer *vdll_cmd_buf;
+ /** last tx_pkt_size */
+ t_u32 last_tx_pkt_size[MLAN_MAX_TXRX_BD];
+} mlan_pcie_card, *pmlan_pcie_card;
+#endif
+
+#ifdef USB
+typedef struct _mlan_usb_card {
+ /** data structure for USB Rx Deaggregation */
+ usb_rx_deaggr_params usb_rx_deaggr;
+ /** data structure for USB Tx Aggregation */
+ usb_tx_aggr_params usb_tx_aggr[MAX_USB_TX_PORT_NUM];
+ /** USB sggregation supported by FW */
+ t_u8 fw_usb_aggr;
+
+} mlan_usb_card, *pmlan_usb_card;
+
+#endif
+
+typedef struct _mlan_card_info {
+ /** Max Tx buffer size */
+ t_u32 max_tx_buf_size;
+ /** support V16_FW_API */
+ t_u8 v16_fw_api;
+ /** support V17_FW_API */
+ t_u8 v17_fw_api;
+ /** suppress PS handshake */
+ t_u8 supp_ps_handshake;
+ /** DEFAULT_11N_TX_BF_CAP */
+ t_u32 default_11n_tx_bf_cap;
+} mlan_card_info, *pmlan_card_info;
+
+typedef struct _mlan_adapter mlan_adapter, *pmlan_adapter;
+
+/**Adapter_operations data structure*/
+typedef struct _adapter_operations {
+ /**firmware download handler*/
+ mlan_status (*dnld_fw)(pmlan_adapter pmadapter, pmlan_fw_image pmfw);
+ /**interrupt handler*/
+ mlan_status (*interrupt)(t_u16 msg_id, pmlan_adapter pmadapter);
+ /**INT process handler*/
+ mlan_status (*process_int_status)(pmlan_adapter pmadapter);
+ /**host to card handler*/
+ mlan_status (*host_to_card)(pmlan_private pmpriv, t_u8 type,
+ mlan_buffer *pmbuf,
+ mlan_tx_param *tx_param);
+ /*wakeup card*/
+ mlan_status (*wakeup_card)(pmlan_adapter pmadapter, t_u8 timeout);
+ /*reset the PM setting of card*/
+ mlan_status (*reset_card)(pmlan_adapter adapter);
+ /** Handle event/cmd complete*/
+ mlan_status (*event_complete)(mlan_adapter *pmlan_adapter,
+ pmlan_buffer pmbuf, mlan_status status);
+ /** Handle complete receiving data */
+ mlan_status (*data_complete)(mlan_adapter *pmlan_adapter,
+ pmlan_buffer pmbuf, mlan_status status);
+ /** Handle command response complete */
+ mlan_status (*cmdrsp_complete)(mlan_adapter *pmlan_adapter,
+ pmlan_buffer pmbuf, mlan_status status);
+ /** Handle rx packet */
+ mlan_status (*handle_rx_packet)(mlan_adapter *pmadapter,
+ pmlan_buffer pmbuf);
+ /** handle dump interface specific info */
+ mlan_status (*debug_dump)(mlan_adapter *pmadapter);
+ /**Interface header length*/
+ t_u32 intf_header_len;
+} mlan_adapter_operations;
+
+/** Adapter data structure for MLAN */
+typedef struct _mlan_adapter {
+ /** MOAL handle structure */
+ t_void *pmoal_handle;
+ /** BSS Attributes */
+ mlan_bss_attr bss_attr[MLAN_MAX_BSS_NUM];
+ /** Private pointer */
+ pmlan_private priv[MLAN_MAX_BSS_NUM];
+ /** Total number of Priv number */
+ t_u8 priv_num;
+ /** Priority table for bss */
+ mlan_bssprio_tbl bssprio_tbl[MLAN_MAX_BSS_NUM];
+ /** Callback table */
+ mlan_callbacks callbacks;
+ /** Init parameters */
+ mlan_init_para init_para;
+ /** mlan_lock for init/shutdown */
+ t_void *pmlan_lock;
+ /** main_proc_lock for main_process */
+ t_void *pmain_proc_lock;
+ /** mlan_processing */
+ t_u32 mlan_processing;
+ /** main_process_cnt */
+ t_u32 main_process_cnt;
+ /** mlan_rx_processing */
+ t_u32 mlan_rx_processing;
+ /** rx_proc_lock for main_rx_process */
+ t_void *prx_proc_lock;
+ /** more_rx_task_flag */
+ t_u32 more_rx_task_flag;
+ /** rx work enable flag */
+ t_u8 rx_work_flag;
+ /* number of rx pkts queued */
+ t_u16 rx_pkts_queued;
+ /** more task flag */
+ t_u32 more_task_flag;
+ /** delay task flag */
+ t_u32 delay_task_flag;
+ /** Max tx buf size */
+ t_u16 max_tx_buf_size;
+ /** Tx buf size */
+ t_u16 tx_buf_size;
+ /** current tx buf size in fw */
+ t_u16 curr_tx_buf_size;
+ /** flush data flag */
+ t_u8 flush_data;
+ /** STATUS variables */
+ WLAN_HARDWARE_STATUS hw_status;
+ /** PnP SUPPORT */
+ t_u8 surprise_removed;
+ /** FW hang report */
+ t_u8 fw_hang_report;
+
+ /** ECSA support */
+ t_u8 ecsa_enable;
+
+ /** Get log support */
+ t_u8 getlog_enable;
+
+ /** Radio on flag */
+ t_u16 radio_on;
+
+ /** Firmware release number */
+ t_u32 fw_release_number;
+ /** firmware version */
+ t_u8 fw_ver;
+ /** firmware minor version */
+ t_u8 fw_min_ver;
+ /** uap firmware version */
+ t_u8 uap_fw_ver;
+ /** mac address retrun from get_hw_spec */
+ t_u8 permanent_addr[MLAN_MAC_ADDR_LENGTH];
+ /** Number of antenna used */
+ t_u16 number_of_antenna;
+ /** antenna info */
+ t_u8 antinfo;
+ /** Firmware capability information */
+ t_u32 fw_cap_info;
+ /** Extended firmware capability information */
+ t_u32 fw_cap_ext;
+#if defined(PCIE9098) || defined(SD9098) || defined(USB9098) || \
+ defined(PCIE9097) || defined(SD9097) || defined(USB9097)
+ /** High byte for 5G, low byte for 2G, like 0x2211 0x22 for 5G, 0x11 for
+ * 2G */
+ t_u16 user_htstream;
+#endif
+ /** vdll ctrl */
+ vdll_dnld_ctrl vdll_ctrl;
+#if defined(SDIO) || defined(PCIE)
+ /** pint_lock for interrupt handling */
+ t_void *pint_lock;
+ /** Interrupt status */
+ t_u32 ireg;
+#endif
+ /** card type */
+ t_u16 card_type;
+ /** card rev */
+ t_u8 card_rev;
+ const mlan_card_info *pcard_info;
+#ifdef SDIO
+ pmlan_sdio_card pcard_sd;
+#endif
+#ifdef PCIE
+ pmlan_pcie_card pcard_pcie;
+#endif
+#ifdef USB
+ pmlan_usb_card pcard_usb;
+#endif
+
+ /** Event cause */
+ t_u32 event_cause;
+ /** Event buffer */
+ pmlan_buffer pmlan_buffer_event;
+ /** Upload length */
+ t_u32 upld_len;
+ /** Upload buffer*/
+ t_u8 upld_buf[WLAN_UPLD_SIZE];
+ /** Data sent:
+ * TRUE - Data is sent to fw, no Tx Done received
+ * FALSE - Tx done received for previous Tx
+ */
+ t_u8 data_sent;
+ /** CMD sent:
+ * TRUE - CMD is sent to fw, no CMD Done received
+ * FALSE - CMD done received for previous CMD
+ */
+ t_u8 cmd_sent;
+ /** CMD Response received:
+ * TRUE - CMD is response is received from fw, and yet to process
+ * FALSE - No cmd response to process
+ */
+ t_u8 cmd_resp_received;
+ /** Event received:
+ * TRUE - Event received from fw, and yet to process
+ * FALSE - No events to process
+ */
+ t_u8 event_received;
+
+ /** Data received:
+ * TRUE - Data received from fw
+ * FALSE - No Data received
+ */
+ t_u8 data_received;
+
+ /** Command-related variables */
+ /** Command sequence number */
+ t_u16 seq_num;
+ /** Command controller nodes */
+ cmd_ctrl_node *cmd_pool;
+ /** Current Command */
+ cmd_ctrl_node *curr_cmd;
+ /** mlan_lock for command */
+ t_void *pmlan_cmd_lock;
+ /** Number of command timeouts */
+ t_u32 num_cmd_timeout;
+ /** Last init fw command id */
+ t_u16 last_init_cmd;
+ /** Command timer */
+ t_void *pmlan_cmd_timer;
+ /** Command timer set flag */
+ t_u8 cmd_timer_is_set;
+ /** time stamp for command dnld */
+ t_u32 dnld_cmd_in_secs;
+
+ /** Command Queues */
+ /** Free command buffers */
+ mlan_list_head cmd_free_q;
+ /** Pending command buffers */
+ mlan_list_head cmd_pending_q;
+ /** Command queue for scanning */
+ mlan_list_head scan_pending_q;
+ /** ioctl pending queue */
+ mlan_list_head ioctl_pending_q;
+ /** pending_ioctl flag */
+ t_u8 pending_ioctl;
+ pmlan_private pending_disconnect_priv;
+ /** mlan_processing */
+ t_u32 scan_processing;
+ /** ext_scan enh support flag */
+ t_u8 ext_scan_enh;
+ /** scan type: 0 legacy, 1: enhance scan*/
+ t_u8 ext_scan_type;
+ /** ext scan timeout */
+ t_u8 ext_scan_timeout;
+ /** coex scan flag */
+ t_u8 coex_scan;
+ /** coex min scan time */
+ t_u8 coex_min_scan_time;
+ /** coex max scan time */
+ t_u8 coex_max_scan_time;
+ /** coex win size flag */
+ t_u8 coex_win_size;
+ /** coex amdpdu tx win size */
+ t_u8 coex_tx_win_size;
+ /** coex ampdu rx win size */
+ t_u8 coex_rx_win_size;
+ /** Region code */
+ t_u16 region_code;
+ /** Region Channel data */
+ region_chan_t region_channel[MAX_REGION_CHANNEL_NUM];
+ /** CFP table code for 2.4GHz */
+ t_u8 cfp_code_bg;
+ /** CFP table code for 5GHz */
+ t_u8 cfp_code_a;
+ wmm_ac_parameters_t ac_params[MAX_AC_QUEUES];
+ /** Minimum BA Threshold */
+ t_u8 min_ba_threshold;
+#ifdef STA_SUPPORT
+ /** Universal Channel data */
+ region_chan_t universal_channel[MAX_REGION_CHANNEL_NUM];
+ /** Parsed region channel */
+ parsed_region_chan_11d_t parsed_region_chan;
+#endif /* STA_SUPPORT */
+ /** 11D and Domain Regulatory Data */
+ wlan_802_11d_domain_reg_t domain_reg;
+ /** Country Code */
+ t_u8 country_code[COUNTRY_CODE_LEN];
+ /** FSM variable for 11h support */
+ wlan_11h_device_state_t state_11h;
+ /** FSM variable for DFS support */
+ wlan_dfs_device_state_t state_dfs;
+ /** FSM variable for RDH support */
+ wlan_radar_det_hndlg_state_t state_rdh;
+ /** variable to configure dfs channel switch count */
+ t_s8 dfs_cs_count;
+ /** User configured settings for DFS testing */
+ wlan_dfs_testing_settings_t dfs_test_params;
+ /** dfs w53 cfg */
+ t_u8 dfs53cfg;
+ /** FSM variable for MEAS support */
+ wlan_meas_state_t state_meas;
+ /** Scan table */
+ BSSDescriptor_t *pscan_table;
+ /** scan age in secs */
+ t_u32 age_in_secs;
+ /** Active scan for hidden ssid triggered */
+ t_u8 active_scan_triggered;
+ /** channel statstics */
+ ChanStatistics_t *pchan_stats;
+ /** Number of records in the chan_stats */
+ t_u32 num_in_chan_stats;
+ /** index of chan stats */
+ t_u32 idx_chan_stats;
+ t_u8 bgscan_reported;
+
+ /** Number of records in the scan table */
+ t_u32 num_in_scan_table;
+ /** Scan probes */
+ t_u16 scan_probes;
+
+ /** Scan type */
+ t_u8 scan_type;
+ /** Scan mode */
+ t_u32 scan_mode;
+ /** Specific scan time */
+ t_u16 specific_scan_time;
+ /** Active scan time */
+ t_u16 active_scan_time;
+ /** Passive scan time */
+ t_u16 passive_scan_time;
+ /** Passive scan to active scan */
+ t_u8 passive_to_active_scan;
+ /** scan channel gap time */
+ t_u16 scan_chan_gap;
+ /** Scan block flag */
+ t_u8 scan_block;
+ /** Extended scan or legacy scan */
+ t_u8 ext_scan;
+ t_u16 bcn_buf_size;
+ /** Beacon buffer */
+ t_u8 *bcn_buf;
+ /** Pointer to valid beacon buffer end */
+ t_u8 *pbcn_buf_end;
+ /** allocate fixed scan beacon buffer size*/
+ t_u32 fixed_beacon_buffer;
+
+ /** F/W supported bands */
+ t_u16 fw_bands;
+ /** User selected band to start adhoc network */
+ t_u16 adhoc_start_band;
+ /** User selected bands */
+ t_u16 config_bands;
+ /** Pointer to channel list last sent to the firmware for scanning */
+ ChanScanParamSet_t *pscan_channels;
+
+ /** Tx lock flag */
+ t_u8 tx_lock_flag;
+ /** Rx lock flag */
+ t_u8 rx_lock_flag;
+ /** main lock flag */
+ t_u8 main_lock_flag;
+#ifdef USB
+ /** Tx CMD endpoint address */
+ t_u8 tx_cmd_ep;
+ /** Rx CMD/EVT endpoint address */
+ t_u8 rx_cmd_ep;
+ /** Rx data endpoint address */
+ t_u8 rx_data_ep;
+ /** Tx data endpoint address */
+ t_u8 tx_data_ep;
+#endif
+
+ /** sleep_params_t */
+ sleep_params_t sleep_params;
+ /** sleep_period_t (Enhanced Power Save) */
+ sleep_period_t sleep_period;
+
+ /** Power Save mode */
+ /**
+ * Wlan802_11PowerModeCAM = disable
+ * Wlan802_11PowerModePSP = enable
+ */
+ t_u16 ps_mode;
+ /** Power Save state */
+ t_u32 ps_state;
+ /** Need to wakeup flag */
+ t_u8 need_to_wakeup;
+ /** keep_wakeup */
+ t_u8 keep_wakeup;
+
+ /** Multiple DTIM */
+ t_u16 multiple_dtim;
+ /** Local listen interval */
+ t_u16 local_listen_interval;
+ /** Null packet interval */
+ t_u16 null_pkt_interval;
+
+ /** IEEE ps inactivity timout value */
+ t_u16 inact_tmo;
+ /** Power save confirm sleep command buffer */
+ pmlan_buffer psleep_cfm;
+ /** Beacon miss timeout */
+ t_u16 bcn_miss_time_out;
+
+ /** Deep Sleep flag */
+ t_u8 is_deep_sleep;
+ /** Idle time */
+ t_u16 idle_time;
+ /** Auto Deep Sleep enabled at init time */
+ t_u8 init_auto_ds;
+
+ /** delay null pkt flag */
+ t_u8 delay_null_pkt;
+ /** Delay to PS in milliseconds */
+ t_u16 delay_to_ps;
+ /** Enhanced PS mode */
+ t_u16 enhanced_ps_mode;
+ /** Device wakeup required flag */
+ t_u8 pm_wakeup_card_req;
+
+ /** Gen NULL pkg */
+ t_u16 gen_null_pkt;
+
+ /** PPS/UAPSD mode flag */
+ t_u16 pps_uapsd_mode;
+ /** Number of wakeup tries */
+ t_u32 pm_wakeup_fw_try;
+ /** time stamp when host try to wake up firmware */
+ t_u32 pm_wakeup_in_secs;
+ /** Card wakeup timer */
+ t_void *pwakeup_fw_timer;
+ /** Card wakeup timer */
+ t_u8 wakeup_fw_timer_is_set;
+ /** Number of wake up timeouts */
+ t_u32 pm_wakeup_timeout;
+
+ /** Host Sleep configured flag */
+ t_u8 is_hs_configured;
+ /** Host Sleep configuration */
+ hs_config_param hs_cfg;
+ /** Host Sleep activated flag */
+ t_u8 hs_activated;
+ /** mef_flt_cfg_mef configuration */
+ mef_entry entry_cfg;
+ /** Event body */
+ t_u8 event_body[MAX_EVENT_SIZE];
+ /** 802.11n device capabilities */
+ t_u32 hw_dot_11n_dev_cap;
+ /** Device support for MIMO abstraction of MCSs */
+ t_u8 hw_dev_mcs_support;
+#ifdef STA_SUPPORT
+ /** Adhoc Secondary Channel Bandwidth */
+ t_u8 chan_bandwidth;
+#endif /* STA_SUPPORT */
+
+ /** 802.11ac device capabilities */
+ t_u32 hw_dot_11ac_dev_cap;
+ /** 802.11ac device support for MIMO abstraction of MCSs */
+ t_u32 hw_dot_11ac_mcs_support;
+ /** length of hw he capability */
+ t_u8 hw_hecap_len;
+ /** 802.11ax HE capability */
+ t_u8 hw_he_cap[54];
+ /** length of hw 2.4G he capability */
+ t_u8 hw_2g_hecap_len;
+ /** 802.11ax 2.4G HE capability */
+ t_u8 hw_2g_he_cap[54];
+ /** max mgmt IE index in device */
+ t_u16 max_mgmt_ie_index;
+ /** Head of Rx data queue */
+ mlan_list_head rx_data_queue;
+#ifdef MFG_CMD_SUPPORT
+ t_u32 mfg_mode;
+#endif
+ /** Debug */
+ wlan_dbg dbg;
+
+ /** RX pending for forwarding packets */
+ mlan_scalar pending_bridge_pkts;
+
+ /** Minimum delay between HsActive and HostWake (in msec) */
+ t_u16 min_wake_holdoff;
+ /** Host sleep wake interval(in msec) */
+ t_u32 hs_wake_interval;
+ /** Host sleep inactivity timeout (in msec) */
+ t_u32 hs_inactivity_timeout;
+ /** Parameter type for indication gpio*/
+ t_u8 param_type_ind;
+ /** GPIO pin for indication wakeup source */
+ t_u32 ind_gpio;
+ /** Level on ind_gpio pin for indication normal wakeup source */
+ t_u32 level;
+ /** Parameter type for extend hscfg*/
+ t_u8 param_type_ext;
+ /** Events that will be forced ignore */
+ t_u32 event_force_ignore;
+ /** Events that will use extend gap to inform host*/
+ t_u32 event_use_ext_gap;
+ /** Extend gap*/
+ t_u8 ext_gap;
+ /** GPIO wave level for extend hscfg */
+ t_u8 gpio_wave;
+ /** Dynamic MIMO-SISO switch for hscfg*/
+ t_u8 hs_mimo_switch;
+ /** management frame wakeup filter config */
+ mlan_mgmt_frame_wakeup mgmt_filter[MAX_MGMT_FRAME_FILTER];
+ /** Bypass TX queue pkt count */
+ t_u16 bypass_pkt_count;
+#ifdef STA_SUPPORT
+ /** warm-reset IOCTL request buffer pointer */
+ pmlan_ioctl_req pwarm_reset_ioctl_req;
+#endif
+ /** SCAN IOCTL request buffer pointer */
+ pmlan_ioctl_req pscan_ioctl_req;
+ /** DPD data pointer */
+ t_u8 *pdpd_data;
+ /** DPD data length */
+ t_u32 dpd_data_len;
+ /** region txpowerlimit cfg data buf pointer */
+ t_u8 *ptxpwr_data;
+ /** region txpowerlimit cfg data len */
+ t_u32 txpwr_data_len;
+ /** Cal data pointer */
+ t_u8 *pcal_data;
+ /** Cal data length */
+ t_u32 cal_data_len;
+ /** Feature control bitmask */
+ t_u32 feature_control;
+
+ /** Control coex RX window size configuration */
+ t_u8 coex_rx_winsize;
+ t_bool dfs_repeater;
+ t_u32 dfsr_channel;
+ t_u8 chanrpt_param_bandcfg;
+#if defined(PCIE)
+ mlan_buffer *ssu_buf;
+#endif
+ /** maximum sta connection */
+ t_u8 max_sta_conn;
+ otp_region_info_t *otp_region;
+ chan_freq_power_t *cfp_otp_bg;
+ t_u8 *tx_power_table_bg;
+ t_u32 tx_power_table_bg_size;
+ t_u8 tx_power_table_bg_rows;
+ t_u8 tx_power_table_bg_cols;
+ chan_freq_power_t *cfp_otp_a;
+ t_u8 *tx_power_table_a;
+ t_u32 tx_power_table_a_size;
+ t_u8 tx_power_table_a_rows;
+ t_u8 tx_power_table_a_cols;
+ /**mlan adapter operations*/
+ mlan_adapter_operations ops;
+#ifdef DRV_EMBEDDED_AUTHENTICATOR
+ /** authenticator_priv */
+ pmlan_private authenticator_priv;
+#endif
+ /** TP accounting mode 1-enable 0-disable */
+ t_u32 tp_state_on;
+ /** Packet drop point */
+ t_u32 tp_state_drop_point;
+} mlan_adapter, *pmlan_adapter;
+
+/** Check if stream 2X2 enabled */
+#define IS_STREAM_2X2(x) ((x)&FEATURE_CTRL_STREAM_2X2)
+/** Check if DFS support enabled */
+#define IS_DFS_SUPPORT(x) ((x)&FEATURE_CTRL_DFS_SUPPORT)
+#ifdef USB
+/** Check if winner check & not wait for FW ready event */
+#define IS_USB_NEW_INIT(x) ((x)&FEATURE_CTRL_USB_NEW_INIT)
+#endif
+
+/** Ethernet packet type for EAPOL */
+#define MLAN_ETHER_PKT_TYPE_EAPOL (0x888E)
+#define MLAN_ETHER_PKT_TYPE_ARP (0x0806)
+/** Ethernet packet type for WAPI */
+#define MLAN_ETHER_PKT_TYPE_WAPI (0x88B4)
+/** Ethernet packet type offset */
+#define MLAN_ETHER_PKT_TYPE_OFFSET (12)
+
+mlan_status wlan_init_lock_list(pmlan_adapter pmadapter);
+mlan_status wlan_init_priv_lock_list(pmlan_adapter pmadapter, t_u8 start_index);
+t_void wlan_free_lock_list(pmlan_adapter pmadapter);
+mlan_status wlan_init_timer(pmlan_adapter pmadapter);
+t_void wlan_free_timer(pmlan_adapter pmadapter);
+
+/* Function prototype */
+/** Initialize firmware */
+mlan_status wlan_init_fw(pmlan_adapter pmadapter);
+
+/** get hw spec complete */
+mlan_status wlan_get_hw_spec_complete(pmlan_adapter pmadapter);
+
+/** Initialize firmware complete */
+mlan_status wlan_init_fw_complete(pmlan_adapter pmadapter);
+
+/** Shutdown firmware complete */
+mlan_status wlan_shutdown_fw_complete(pmlan_adapter pmadapter);
+
+/** Receive event */
+mlan_status wlan_recv_event(pmlan_private priv, mlan_event_id event_id,
+ t_void *pmevent);
+
+/** Initialize mlan_adapter structure */
+t_void wlan_init_adapter(pmlan_adapter pmadapter);
+
+/** Initialize mlan_private structure */
+mlan_status wlan_init_priv(pmlan_private priv);
+
+mlan_status wlan_download_vdll_block(mlan_adapter *pmadapter, t_u8 *block,
+ t_u16 block_len);
+mlan_status wlan_process_vdll_event(pmlan_private pmpriv, pmlan_buffer pevent);
+/** Process event */
+mlan_status wlan_process_event(pmlan_adapter pmadapter);
+
+/** Prepare command */
+mlan_status wlan_prepare_cmd(pmlan_private priv, t_u16 cmd_no, t_u16 cmd_action,
+ t_u32 cmd_oid, t_void *pioctl_buf,
+ t_void *pdata_buf);
+
+/** cmd timeout handler */
+t_void wlan_cmd_timeout_func(t_void *function_context);
+
+/**
+ * @brief check if Tx pending
+ *
+ * @param pmadapter Pointer to mlan_adapter
+ * @return MTRUE/MFALSE;
+ */
+static inline t_u8 wlan_is_tx_pending(mlan_adapter *pmadapter)
+{
+#ifdef PCIE
+ if (IS_PCIE(pmadapter->card_type) &&
+ pmadapter->pcard_pcie->txbd_pending)
+ return MTRUE;
+#endif
+ return MFALSE;
+}
+
+/** process host cmd */
+mlan_status wlan_misc_ioctl_host_cmd(pmlan_adapter pmadapter,
+ pmlan_ioctl_req pioctl_req);
+/** process init/shutdown cmd*/
+mlan_status wlan_misc_ioctl_init_shutdown(pmlan_adapter pmadapter,
+ pmlan_ioctl_req pioctl_req);
+/** process debug info */
+mlan_status wlan_get_info_debug_info(pmlan_adapter pmadapter,
+ pmlan_ioctl_req pioctl_req);
+
+#if defined(STA_SUPPORT) && defined(UAP_SUPPORT)
+/** Set/Get BSS role */
+mlan_status wlan_bss_ioctl_bss_role(pmlan_adapter pmadapter,
+ pmlan_ioctl_req pioctl_req);
+#endif
+
+#if defined(PCIE)
+mlan_status wlan_misc_ssu(pmlan_adapter pmadapter, pmlan_ioctl_req pioctl_req);
+#endif
+
+mlan_status wlan_set_ewpa_mode(mlan_private *priv, pmlan_ds_passphrase psec_pp);
+mlan_status wlan_find_bss(mlan_private *pmpriv, pmlan_ioctl_req pioctl_req);
+
+/* block main process */
+void mlan_block_main_process(mlan_adapter *pmadapter, t_u8 block);
+/* block rx process */
+void mlan_block_rx_process(mlan_adapter *pmadapter, t_u8 block);
+/** check pending command */
+int wlan_check_pending_cmd(mlan_adapter *pmadapter);
+/** Allocate memory for adapter structure members */
+mlan_status wlan_allocate_adapter(pmlan_adapter pmadapter);
+/** Free adapter */
+t_void wlan_free_adapter(pmlan_adapter pmadapter);
+/** Free priv */
+t_void wlan_free_priv(mlan_private *pmpriv);
+/** Allocate command buffer */
+mlan_status wlan_alloc_cmd_buffer(mlan_adapter *pmadapter);
+/** Free command buffer */
+mlan_status wlan_free_cmd_buffer(mlan_adapter *pmadapter);
+/** Request command lock */
+t_void wlan_request_cmd_lock(mlan_adapter *pmadapter);
+/** Release command lock */
+t_void wlan_release_cmd_lock(mlan_adapter *pmadapter);
+#ifdef STA_SUPPORT
+/** Flush the scan pending queue */
+t_void wlan_flush_scan_queue(pmlan_adapter pmadapter);
+mlan_status wlan_cancel_pending_scan_cmd(pmlan_adapter pmadapter,
+ pmlan_ioctl_req pioctl_req);
+#endif
+/**Cancel pending command */
+t_void wlan_cancel_all_pending_cmd(pmlan_adapter pmadapter, t_u8 flag);
+/**Cancel pending ioctl */
+t_void wlan_cancel_pending_ioctl(pmlan_adapter pmadapter,
+ pmlan_ioctl_req pioctl_req);
+/**Cancel bss pending ioctl */
+t_void wlan_cancel_bss_pending_cmd(pmlan_adapter pmadapter, t_u32 bss_index);
+
+/** Insert command to free queue */
+t_void wlan_insert_cmd_to_free_q(mlan_adapter *pmadapter,
+ cmd_ctrl_node *pcmd_node);
+
+/** Insert command to pending queue */
+t_void wlan_insert_cmd_to_pending_q(mlan_adapter *pmadapter,
+ cmd_ctrl_node *pcmd_node, t_u32 addtail);
+
+/** Execute next command */
+mlan_status wlan_exec_next_cmd(mlan_adapter *pmadapter);
+/** Proecess command response */
+mlan_status wlan_process_cmdresp(mlan_adapter *pmadapter);
+/** Handle received packet, has extra handling for aggregate packets */
+mlan_status wlan_handle_rx_packet(pmlan_adapter pmadapter, pmlan_buffer pmbuf);
+/** Process transmission */
+mlan_status wlan_process_tx(pmlan_private priv, pmlan_buffer pmbuf,
+ mlan_tx_param *tx_param);
+/** Transmit a null data packet */
+mlan_status wlan_send_null_packet(pmlan_private priv, t_u8 flags);
+
+#ifdef SDIO
+mlan_status wlan_alloc_sdio_mpa_buffers(mlan_adapter *pmadapter,
+ t_u32 mpa_tx_buf_size,
+ t_u32 mpa_rx_buf_size);
+
+mlan_status wlan_free_sdio_mpa_buffers(mlan_adapter *pmadapter);
+#endif
+
+/** Process write data complete */
+mlan_status wlan_write_data_complete(pmlan_adapter pmlan_adapter,
+ pmlan_buffer pmbuf, mlan_status status);
+
+#ifdef USB
+mlan_status wlan_usb_deaggr_rx_pkt(pmlan_adapter pmadapter, pmlan_buffer pmbuf);
+
+/**
+ * @brief This function resets USB Tx Aggregation buffers
+ *
+ * @param pmadapter A pointer to mlan_adapter
+ *
+ * @return N/A
+ */
+static INLINE t_void wlan_reset_usb_tx_aggr(pmlan_adapter pmadapter)
+{
+ t_s32 i = 0;
+ pmlan_callbacks pcb = &pmadapter->callbacks;
+ ENTER();
+ for (i = 0; i < MAX_USB_TX_PORT_NUM; i++) {
+ pcb->moal_spin_lock(
+ pmadapter->pmoal_handle,
+ pmadapter->pcard_usb->usb_tx_aggr[i].paggr_lock);
+ if (pmadapter->pcard_usb->usb_tx_aggr[i].aggr_hold_timer_is_set) {
+ pcb->moal_stop_timer(pmadapter->pmoal_handle,
+ pmadapter->pcard_usb
+ ->usb_tx_aggr[i]
+ .paggr_hold_timer);
+ pmadapter->pcard_usb->usb_tx_aggr[i]
+ .aggr_hold_timer_is_set = MFALSE;
+ }
+ if (pmadapter->pcard_usb->usb_tx_aggr[i].aggr_ctrl.enable &&
+ pmadapter->pcard_usb->usb_tx_aggr[i].pmbuf_aggr != MNULL) {
+ wlan_write_data_complete(
+ pmadapter,
+ pmadapter->pcard_usb->usb_tx_aggr[i].pmbuf_aggr,
+ MLAN_STATUS_FAILURE); /* did not get sent */
+ pmadapter->pcard_usb->usb_tx_aggr[i].pmbuf_aggr = MNULL;
+ pmadapter->pcard_usb->usb_tx_aggr[i].aggr_len = 0;
+ }
+ pcb->moal_spin_unlock(
+ pmadapter->pmoal_handle,
+ pmadapter->pcard_usb->usb_tx_aggr[i].paggr_lock);
+ }
+ LEAVE();
+}
+
+/**
+ * @brief This function get usb_tx_aggr_params
+ *
+ * @param pmadapter A pointer to mlan_adapter
+ * @param port port for TX
+ *
+ * @return A pointer to usb_tx_aggr_params
+ */
+static INLINE usb_tx_aggr_params *
+wlan_get_usb_tx_aggr_params(pmlan_adapter pmadapter, t_u32 port)
+{
+ int i;
+ ENTER();
+ for (i = 0; i < MAX_USB_TX_PORT_NUM; i++) {
+ if (pmadapter->pcard_usb->usb_tx_aggr[i].aggr_ctrl.enable &&
+ pmadapter->pcard_usb->usb_tx_aggr[i].port == port)
+ return &pmadapter->pcard_usb->usb_tx_aggr[i];
+ }
+ LEAVE();
+ return MNULL;
+}
+
+t_void wlan_usb_tx_aggr_timeout_func(t_void *function_context);
+mlan_status wlan_usb_host_to_card_aggr(pmlan_adapter pmadapter,
+ pmlan_buffer pmbuf,
+ mlan_tx_param *tx_param,
+ usb_tx_aggr_params *aggr_params);
+#endif
+
+/** Process receive packet complete */
+mlan_status wlan_recv_packet_complete(pmlan_adapter pmadapter,
+ pmlan_buffer pmbuf, mlan_status status);
+/** Clean Tx Rx queues */
+t_void wlan_clean_txrx(pmlan_private priv);
+
+t_void wlan_add_buf_bypass_txqueue(mlan_adapter *pmadapter, pmlan_buffer pmbuf);
+t_void wlan_process_bypass_tx(mlan_adapter *pmadapter);
+t_void wlan_cleanup_bypass_txq(pmlan_private priv);
+t_u8 wlan_bypass_tx_list_empty(mlan_adapter *pmadapter);
+
+/** Check if this is the last packet */
+t_u8 wlan_check_last_packet_indication(pmlan_private priv);
+
+#define MOAL_ALLOC_MLAN_BUFFER (0)
+#define MOAL_MALLOC_BUFFER (1)
+
+#ifdef PCIE
+/* This defines the direction arg to the DMA mapping routines. */
+#define PCI_DMA_BIDIRECTIONAL 0
+#define PCI_DMA_TODEVICE 1
+#define PCI_DMA_FROMDEVICE 2
+#define PCI_DMA_NONE 3
+#endif
+
+/** function to allocate a mlan_buffer */
+pmlan_buffer wlan_alloc_mlan_buffer(mlan_adapter *pmadapter, t_u32 data_len,
+ t_u32 head_room, t_u32 malloc_flag);
+/** function to free a mlan_buffer */
+t_void wlan_free_mlan_buffer(mlan_adapter *pmadapter, pmlan_buffer pmbuf);
+
+/** command resp handler for version ext */
+mlan_status wlan_ret_ver_ext(pmlan_private pmpriv, HostCmd_DS_COMMAND *resp,
+ mlan_ioctl_req *pioctl_buf);
+
+/** command resp handler for rx mgmt forward registration */
+mlan_status wlan_ret_rx_mgmt_ind(pmlan_private pmpriv, HostCmd_DS_COMMAND *resp,
+ mlan_ioctl_req *pioctl_buf);
+
+/** Check Power Save condition */
+t_void wlan_check_ps_cond(mlan_adapter *pmadapter);
+
+/** handle command for enhanced power save mode */
+mlan_status wlan_cmd_enh_power_mode(pmlan_private pmpriv,
+ HostCmd_DS_COMMAND *cmd, t_u16 cmd_action,
+ t_u16 ps_bitmap, t_void *pdata_buf);
+/** handle command resp for enhanced power save mode */
+mlan_status wlan_ret_enh_power_mode(pmlan_private pmpriv,
+ HostCmd_DS_COMMAND *resp,
+ mlan_ioctl_req *pioctl_buf);
+
+/** handle commnand for cfg data */
+mlan_status wlan_cmd_cfg_data(pmlan_private pmpriv, HostCmd_DS_COMMAND *pcmd,
+ t_u16 cmd_action, t_u32 cmd_oid,
+ t_void *pdata_buf);
+/** handle command resp for cfg data */
+mlan_status wlan_ret_cfg_data(pmlan_private pmpriv, HostCmd_DS_COMMAND *resp,
+ t_void *pioctl_buf);
+
+/** Process sleep confirm command response */
+void wlan_process_sleep_confirm_resp(pmlan_adapter pmadapter, t_u8 *pbuf,
+ t_u32 len);
+
+/** Perform hs related activities on receving the power up interrupt */
+void wlan_process_hs_config(pmlan_adapter pmadapter);
+
+t_void wlan_wakeup_card_timeout_func(void *function_context);
+
+mlan_status wlan_process_802dot11_mgmt_pkt(mlan_private *priv, t_u8 *payload,
+ t_u32 payload_len, RxPD *prx_pd);
+
+mlan_status wlan_pm_ioctl_hscfg(pmlan_adapter pmadapter,
+ pmlan_ioctl_req pioctl_req);
+
+mlan_status wlan_radio_ioctl_remain_chan_cfg(pmlan_adapter pmadapter,
+ pmlan_ioctl_req pioctl_req);
+mlan_status wlan_cmd_remain_on_channel(pmlan_private pmpriv,
+ HostCmd_DS_COMMAND *cmd,
+ t_u16 cmd_action, t_void *pdata_buf);
+mlan_status wlan_ret_remain_on_channel(pmlan_private pmpriv,
+ HostCmd_DS_COMMAND *resp,
+ mlan_ioctl_req *pioctl_buf);
+
+#ifdef WIFI_DIRECT_SUPPORT
+mlan_status wlan_bss_ioctl_wifi_direct_mode(pmlan_adapter pmadapter,
+ pmlan_ioctl_req pioctl_req);
+
+mlan_status wlan_cmd_wifi_direct_mode(pmlan_private pmpriv,
+ HostCmd_DS_COMMAND *cmd, t_u16 cmd_action,
+ t_void *pdata_buf);
+mlan_status wlan_ret_wifi_direct_mode(pmlan_private pmpriv,
+ HostCmd_DS_COMMAND *resp,
+ mlan_ioctl_req *pioctl_buf);
+mlan_status wlan_cmd_p2p_params_config(pmlan_private pmpriv,
+ HostCmd_DS_COMMAND *cmd,
+ t_u16 cmd_action, t_void *pdata_buf);
+mlan_status wlan_ret_p2p_params_config(pmlan_private pmpriv,
+ HostCmd_DS_COMMAND *resp,
+ mlan_ioctl_req *pioctl_buf);
+mlan_status wlan_misc_p2p_config(pmlan_adapter pmadapter,
+ pmlan_ioctl_req pioctl_req);
+#endif
+/** get ralist info */
+int wlan_get_ralist_info(mlan_private *priv, pralist_info buf);
+/** dump ralist */
+void wlan_dump_ralist(mlan_private *priv);
+
+/** get pm info */
+mlan_status wlan_get_pm_info(pmlan_adapter pmadapter,
+ pmlan_ioctl_req pioctl_req);
+
+mlan_status wlan_bss_ioctl_bss_remove(pmlan_adapter pmadapter,
+ pmlan_ioctl_req pioctl_req);
+
+mlan_status wlan_radio_ioctl_mimo_switch_cfg(pmlan_adapter pmadapter,
+ pmlan_ioctl_req pioctl_req);
+mlan_status wlan_cmd_802_11_mimo_switch(pmlan_private pmpriv,
+ HostCmd_DS_COMMAND *cmd,
+ t_void *pdata_buf);
+
+mlan_status wlan_misc_per_pkt_cfg(pmlan_adapter pmadapter,
+ pmlan_ioctl_req pioctl_req);
+
+mlan_status wlan_config_mgmt_filter(pmlan_adapter pmadapter,
+ pmlan_ioctl_req pioctl_req);
+mlan_status wlan_get_hs_wakeup_reason(pmlan_adapter pmadapter,
+ pmlan_ioctl_req pioctl_req);
+
+mlan_status wlan_cmd_hs_wakeup_reason(pmlan_private pmpriv,
+ HostCmd_DS_COMMAND *cmd,
+ t_void *pdata_buf);
+
+mlan_status wlan_ret_hs_wakeup_reason(pmlan_private pmpriv,
+ HostCmd_DS_COMMAND *resp,
+ mlan_ioctl_req *pioctl_buf);
+
+mlan_status wlan_get_tx_rx_histogram(pmlan_adapter pmadapter,
+ pmlan_ioctl_req pioctl_req);
+mlan_status wlan_cmd_tx_rx_pkt_stats(pmlan_private pmpriv,
+ HostCmd_DS_COMMAND *cmd,
+ pmlan_ioctl_req pioctl_buf,
+ t_void *pdata_buf);
+mlan_status wlan_ret_tx_rx_pkt_stats(pmlan_private pmpriv,
+ HostCmd_DS_COMMAND *resp,
+ mlan_ioctl_req *pioctl_buf);
+
+mlan_status wlan_radio_ioctl_radio_ctl(pmlan_adapter pmadapter,
+ pmlan_ioctl_req pioctl_req);
+
+mlan_status wlan_radio_ioctl_ant_cfg(pmlan_adapter pmadapter,
+ pmlan_ioctl_req pioctl_req);
+
+mlan_status wlan_cmd_tx_rate_cfg(pmlan_private pmpriv, HostCmd_DS_COMMAND *cmd,
+ t_u16 cmd_action, t_void *pdata_buf,
+ mlan_ioctl_req *pioctl_buf);
+mlan_status wlan_ret_tx_rate_cfg(pmlan_private pmpriv, HostCmd_DS_COMMAND *resp,
+ mlan_ioctl_req *pioctl_buf);
+
+mlan_status wlan_rate_ioctl_cfg(pmlan_adapter pmadapter,
+ pmlan_ioctl_req pioctl_req);
+mlan_status wlan_ret_802_11_tx_rate_query(pmlan_private pmpriv,
+ HostCmd_DS_COMMAND *resp,
+ mlan_ioctl_req *pioctl_buf);
+
+mlan_status wlan_rate_ioctl_get_data_rate(pmlan_adapter pmadapter,
+ pmlan_ioctl_req pioctl_req);
+
+t_void wlan_host_sleep_activated_event(pmlan_private priv, t_u8 activated);
+/** Handles the command response of hs_cfg */
+mlan_status wlan_ret_802_11_hs_cfg(pmlan_private pmpriv,
+ HostCmd_DS_COMMAND *resp,
+ mlan_ioctl_req *pioctl_buf);
+/** Sends HS_WAKEUP event to applications */
+t_void wlan_host_sleep_wakeup_event(pmlan_private priv);
+
+/** Prepares command of robustcoex */
+mlan_status wlan_cmd_robustcoex(pmlan_private pmpriv, HostCmd_DS_COMMAND *cmd,
+ t_u16 cmd_action, t_u16 *pdata_buf);
+/** Set Robustcoex gpiocfg */
+mlan_status wlan_misc_robustcoex(pmlan_adapter pmadapter,
+ pmlan_ioctl_req pioctl_req);
+
+/** Set mapping policy/get DMCS status */
+mlan_status wlan_misc_dmcs_config(pmlan_adapter pmadapter,
+ pmlan_ioctl_req pioctl_req);
+/** Prepares command of DMCS config */
+mlan_status wlan_cmd_dmcs_config(pmlan_private pmpriv, HostCmd_DS_COMMAND *cmd,
+ t_u16 cmd_action, t_void *pdata_buf);
+/** Handles command response of DMCS config */
+mlan_status wlan_ret_dmcs_config(pmlan_private pmpriv, HostCmd_DS_COMMAND *resp,
+ mlan_ioctl_req *pioctl_buf);
+
+#if defined(PCIE)
+mlan_status wlan_cmd_ssu(pmlan_private pmpriv, HostCmd_DS_COMMAND *cmd,
+ t_u16 cmd_action, t_u16 *pdata_buf);
+#endif
+
+/** send get hw spec command to firmware */
+mlan_status wlan_adapter_get_hw_spec(pmlan_adapter pmadapter);
+/** send adapter specific init cmd to firmware */
+mlan_status wlan_adapter_init_cmd(pmlan_adapter pmadapter);
+/** get/set bandcfg */
+mlan_status wlan_radio_ioctl_band_cfg(pmlan_adapter pmadapter,
+ pmlan_ioctl_req pioctl_req);
+
+#ifdef RX_PACKET_COALESCE
+mlan_status wlan_cmd_rx_pkt_coalesce_cfg(pmlan_private pmpriv,
+ HostCmd_DS_COMMAND *cmd,
+ t_u16 cmd_action, t_void *pdata_buf);
+mlan_status wlan_ret_rx_pkt_coalesce_cfg(pmlan_private pmpriv,
+ const HostCmd_DS_COMMAND *resp,
+ mlan_ioctl_req *pioctl_buf);
+#endif
+
+#ifdef STA_SUPPORT
+/** warm reset */
+mlan_status wlan_misc_ioctl_warm_reset(pmlan_adapter pmadapter,
+ pmlan_ioctl_req pioctl_req);
+/** Process received packet */
+mlan_status wlan_process_rx_packet(pmlan_adapter pmadapter, pmlan_buffer pmbuf);
+/** ioctl handler for station mode */
+mlan_status wlan_ops_sta_ioctl(t_void *adapter, pmlan_ioctl_req pioctl_req);
+
+/** cmd handler for station mode */
+mlan_status wlan_ops_sta_prepare_cmd(t_void *priv, t_u16 cmd_no,
+ t_u16 cmd_action, t_u32 cmd_oid,
+ t_void *pioctl_buf, t_void *pdata_buf,
+ t_void *pcmd_buf);
+
+/** cmdresp handler for station mode */
+mlan_status wlan_ops_sta_process_cmdresp(t_void *priv, t_u16 cmdresp_no,
+ t_void *pcmd_buf, t_void *pioctl);
+
+/** rx handler for station mode */
+mlan_status wlan_ops_sta_process_rx_packet(t_void *adapter, pmlan_buffer pmbuf);
+
+/** event handler for station mode */
+mlan_status wlan_ops_sta_process_event(t_void *priv);
+
+/** fill txpd for station mode */
+t_void *wlan_ops_sta_process_txpd(t_void *priv, pmlan_buffer pmbuf);
+
+/** send init cmd to firmware for station mode */
+mlan_status wlan_ops_sta_init_cmd(t_void *priv, t_u8 first_bss);
+
+/** Flush the scan table */
+mlan_status wlan_flush_scan_table(pmlan_adapter pmadapter);
+
+/** Scan for networks */
+mlan_status wlan_scan_networks(mlan_private *pmpriv, t_void *pioctl_buf,
+ wlan_user_scan_cfg *puser_scan_in);
+
+/** Scan for specific SSID */
+mlan_status wlan_scan_specific_ssid(mlan_private *pmpriv, t_void *pioctl_buf,
+ mlan_802_11_ssid *preq_ssid);
+
+/** Scan command handler */
+mlan_status wlan_cmd_802_11_scan(pmlan_private pmpriv, HostCmd_DS_COMMAND *pcmd,
+ t_void *pdata_buf);
+
+/** Handler for scan command response */
+mlan_status wlan_ret_802_11_scan(pmlan_private pmpriv, HostCmd_DS_COMMAND *resp,
+ t_void *pioctl_buf);
+
+/** Extended scan command handler */
+mlan_status wlan_cmd_802_11_scan_ext(pmlan_private pmpriv,
+ HostCmd_DS_COMMAND *pcmd,
+ t_void *pdata_buf);
+/** Handler for extended scan command response */
+mlan_status wlan_ret_802_11_scan_ext(pmlan_private pmpriv,
+ HostCmd_DS_COMMAND *resp,
+ t_void *pioctl_buf);
+/** Handler event for extended scan report */
+mlan_status wlan_handle_event_ext_scan_report(mlan_private *pmpriv,
+ mlan_buffer *pmbuf);
+mlan_status wlan_handle_event_ext_scan_status(mlan_private *pmpriv,
+ mlan_buffer *pmbuf);
+
+/** check network compatibility */
+t_s32 wlan_is_network_compatible(mlan_private *pmpriv, t_u32 index, t_u32 mode);
+
+/** Find an SSID in a list */
+t_s32 wlan_find_ssid_in_list(pmlan_private pmpriv, mlan_802_11_ssid *ssid,
+ t_u8 *bssid, t_u32 mode);
+
+/** Find a BSSID in a list */
+t_s32 wlan_find_bssid_in_list(mlan_private *pmpriv, t_u8 *bssid, t_u32 mode);
+
+/** Find best network */
+mlan_status wlan_find_best_network(mlan_private *pmpriv,
+ mlan_ssid_bssid *preq_ssid_bssid);
+
+/** Compare two SSIDs */
+t_s32 wlan_ssid_cmp(pmlan_adapter pmadapter, mlan_802_11_ssid *ssid1,
+ mlan_802_11_ssid *ssid2);
+
+/** Associate */
+mlan_status wlan_associate(mlan_private *pmpriv, IN t_void *pioctl_buf,
+ IN BSSDescriptor_t *pBSSDesc);
+
+/** Associate command handler */
+mlan_status wlan_cmd_802_11_associate(mlan_private *pmpriv,
+ HostCmd_DS_COMMAND *cmd,
+ t_void *pdata_buf);
+
+/** Handler for association command response */
+mlan_status wlan_ret_802_11_associate(mlan_private *pmpriv,
+ HostCmd_DS_COMMAND *resp,
+ t_void *pioctl_buf);
+
+/** Reset connected state */
+t_void wlan_reset_connect_state(pmlan_private priv, t_u8 drv_disconnect);
+
+t_void wlan_2040_coex_event(pmlan_private pmpriv);
+
+/** convert band to radio type */
+t_u8 wlan_band_to_radio_type(t_u8 band);
+/** convert radio_type to band */
+t_u8 radio_type_to_band(t_u8 chanBand);
+
+/** Disconnect */
+mlan_status wlan_disconnect(mlan_private *pmpriv, mlan_ioctl_req *pioctl_req,
+ mlan_deauth_param *deauth_param);
+
+/** Ad-Hoc start */
+mlan_status wlan_adhoc_start(mlan_private *pmpriv, t_void *pioctl_buf,
+ mlan_802_11_ssid *padhoc_ssid);
+
+/** Ad-Hoc join */
+mlan_status wlan_adhoc_join(mlan_private *pmpriv, t_void *pioctl_buf,
+ BSSDescriptor_t *pBSSDesc);
+
+/** Ad-Hoc start command handler */
+mlan_status wlan_cmd_802_11_ad_hoc_start(mlan_private *pmpriv,
+ HostCmd_DS_COMMAND *cmd,
+ t_void *pdata_buf);
+
+/** Ad-Hoc command handler */
+mlan_status wlan_cmd_802_11_ad_hoc_join(mlan_private *pmpriv,
+ HostCmd_DS_COMMAND *cmd,
+ t_void *pdata_buf);
+
+/** Handler for Ad-Hoc commands */
+mlan_status wlan_ret_802_11_ad_hoc(mlan_private *pmpriv,
+ HostCmd_DS_COMMAND *resp,
+ t_void *pioctl_buf);
+
+/** Handler for bgscan query commands */
+mlan_status wlan_cmd_802_11_bg_scan_query(mlan_private *pmpriv,
+ HostCmd_DS_COMMAND *pcmd,
+ t_void *pdata_buf);
+/** Handler for bgscan config command */
+mlan_status wlan_cmd_bgscan_config(mlan_private *pmpriv,
+ HostCmd_DS_COMMAND *pcmd, t_void *pdata_buf);
+/** Hander for bgscan config command response */
+mlan_status wlan_ret_bgscan_config(mlan_private *pmpriv,
+ HostCmd_DS_COMMAND *resp,
+ mlan_ioctl_req *pioctl_buf);
+mlan_status wlan_ret_802_11_bgscan_query(mlan_private *pmpriv,
+ HostCmd_DS_COMMAND *resp,
+ mlan_ioctl_req *pioctl_buf);
+
+/** Get Channel-Frequency-Power by band and channel */
+chan_freq_power_t *
+wlan_get_cfp_by_band_and_channel(pmlan_adapter pmadapter, t_u8 band,
+ t_u16 channel, region_chan_t *region_channel);
+/** Find Channel-Frequency-Power by band and channel */
+chan_freq_power_t *wlan_find_cfp_by_band_and_channel(mlan_adapter *pmadapter,
+ t_u8 band, t_u16 channel);
+/** Find Channel-Frequency-Power by band and frequency */
+chan_freq_power_t *wlan_find_cfp_by_band_and_freq(mlan_adapter *pmadapter,
+ t_u8 band, t_u32 freq);
+/** Get Tx power of channel from Channel-Frequency-Power */
+t_u8 wlan_get_txpwr_of_chan_from_cfp(mlan_private *pmpriv, t_u8 channel);
+/** find frequency from band and channel */
+t_u32 wlan_find_freq_from_band_chan(t_u8, t_u8);
+
+/* Save a beacon buffer of the current bss descriptor */
+t_void wlan_save_curr_bcn(mlan_private *pmpriv);
+/* Free a beacon buffer of the current bss descriptor */
+t_void wlan_free_curr_bcn(mlan_private *pmpriv);
+
+#endif /* STA_SUPPORT */
+
+/* Rate related functions */
+/** Convert index into data rate */
+t_u32 wlan_index_to_data_rate(pmlan_adapter pmadapter, t_u8 index,
+ t_u8 rate_info, t_u8 ext_rate_info);
+/** Get active data rates */
+t_u32 wlan_get_active_data_rates(mlan_private *pmpriv, t_u32 bss_mode,
+ t_u16 config_bands, WLAN_802_11_RATES rates);
+/** Get supported data rates */
+t_u32 wlan_get_supported_rates(mlan_private *pmpriv, t_u32 bss_mode,
+ t_u16 config_bands, WLAN_802_11_RATES rates);
+/** Convert data rate to index */
+t_u8 wlan_data_rate_to_index(pmlan_adapter pmadapter, t_u32 rate);
+/** Check if rate is auto */
+t_u8 wlan_is_rate_auto(mlan_private *pmpriv);
+/** Get rate index */
+int wlan_get_rate_index(pmlan_adapter pmadapter, t_u16 *rateBitmap, int size);
+mlan_status wlan_cmd_rxabortcfg(pmlan_private pmpriv, HostCmd_DS_COMMAND *cmd,
+ t_u16 cmd_action, t_void *pdata_buf);
+mlan_status wlan_ret_rxabortcfg(pmlan_private pmpriv, HostCmd_DS_COMMAND *resp,
+ mlan_ioctl_req *pioctl_buf);
+mlan_status wlan_cmd_rxabortcfg_ext(pmlan_private pmpriv,
+ HostCmd_DS_COMMAND *cmd, t_u16 cmd_action,
+ t_void *pdata_buf);
+mlan_status wlan_ret_rxabortcfg_ext(pmlan_private pmpriv,
+ HostCmd_DS_COMMAND *resp,
+ mlan_ioctl_req *pioctl_buf);
+mlan_status wlan_cmd_tx_ampdu_prot_mode(pmlan_private pmpriv,
+ HostCmd_DS_COMMAND *cmd,
+ t_u16 cmd_action, t_void *pdata_buf);
+mlan_status wlan_ret_tx_ampdu_prot_mode(pmlan_private pmpriv,
+ HostCmd_DS_COMMAND *resp,
+ mlan_ioctl_req *pioctl_buf);
+mlan_status wlan_cmd_dot11mc_unassoc_ftm_cfg(pmlan_private pmpriv,
+ HostCmd_DS_COMMAND *cmd,
+ t_u16 cmd_action,
+ t_void *pdata_buf);
+mlan_status wlan_ret_dot11mc_unassoc_ftm_cfg(pmlan_private pmpriv,
+ HostCmd_DS_COMMAND *resp,
+ mlan_ioctl_req *pioctl_buf);
+
+mlan_status wlan_cmd_rate_adapt_cfg(pmlan_private pmpriv,
+ HostCmd_DS_COMMAND *cmd, t_u16 cmd_action,
+ t_void *pdata_buf);
+mlan_status wlan_ret_rate_adapt_cfg(pmlan_private pmpriv,
+ HostCmd_DS_COMMAND *resp,
+ mlan_ioctl_req *pioctl_buf);
+mlan_status wlan_cmd_cck_desense_cfg(pmlan_private pmpriv,
+ HostCmd_DS_COMMAND *cmd, t_u16 cmd_action,
+ t_void *pdata_buf);
+
+mlan_status wlan_ret_cck_desense_cfg(pmlan_private pmpriv,
+ HostCmd_DS_COMMAND *resp,
+ mlan_ioctl_req *pioctl_buf);
+
+mlan_status wlan_cmd_arb_cfg(pmlan_private pmpriv, HostCmd_DS_COMMAND *cmd,
+ t_u16 cmd_action, t_void *pdata_buf);
+mlan_status wlan_ret_arb_cfg(pmlan_private pmpriv, HostCmd_DS_COMMAND *resp,
+ mlan_ioctl_req *pioctl_buf);
+
+mlan_status wlan_misc_ioctl_rxabortcfg(pmlan_adapter pmadapter,
+ pmlan_ioctl_req pioctl_req);
+mlan_status wlan_misc_ioctl_rxabortcfg_ext(pmlan_adapter pmadapter,
+ pmlan_ioctl_req pioctl_req);
+mlan_status wlan_misc_ioctl_tx_ampdu_prot_mode(pmlan_adapter pmadapter,
+ pmlan_ioctl_req pioctl_req);
+mlan_status wlan_misc_ioctl_dot11mc_unassoc_ftm_cfg(pmlan_adapter pmadapter,
+ pmlan_ioctl_req pioctl_req);
+mlan_status wlan_misc_ioctl_rate_adapt_cfg(pmlan_adapter pmadapter,
+ pmlan_ioctl_req pioctl_req);
+mlan_status wlan_misc_ioctl_cck_desense_cfg(pmlan_adapter pmadapter,
+ pmlan_ioctl_req pioctl_req);
+mlan_status wlan_cmd_mfg(pmlan_private pmpriv, pHostCmd_DS_COMMAND cmd,
+ t_u16 cmd_action, t_pvoid pdata_buf);
+mlan_status wlan_ret_mfg(pmlan_private pmpriv, HostCmd_DS_COMMAND *resp,
+ mlan_ioctl_req *pioctl_buf);
+mlan_status wlan_misc_ioctl_rf_test_cfg(pmlan_adapter pmadapter,
+ pmlan_ioctl_req pioctl_req);
+mlan_status wlan_misc_ioctl_range_ext(pmlan_adapter pmadapter,
+ pmlan_ioctl_req pioctl_req);
+mlan_status wlan_misc_ioctl_arb_cfg(pmlan_adapter pmadapter,
+ pmlan_ioctl_req pioctl_req);
+mlan_status wlan_misc_ioctl_tp_state(pmlan_adapter pmadapter,
+ pmlan_ioctl_req pioctl_req);
+/* CFP related functions */
+/** Region code index table */
+extern t_u16 region_code_index[MRVDRV_MAX_REGION_CODE];
+/** The table to keep CFP code for BG */
+extern t_u16 cfp_code_index_bg[MRVDRV_MAX_CFP_CODE_BG];
+/** The table to keep CFP code for A */
+extern t_u16 cfp_code_index_a[MRVDRV_MAX_CFP_CODE_A];
+
+/** Set region table */
+mlan_status wlan_set_regiontable(mlan_private *pmpriv, t_u8 region, t_u8 band);
+/** Get radar detection requirements*/
+t_bool wlan_get_cfp_radar_detect(mlan_private *priv, t_u8 chnl);
+/** check if scan type is passive for b/g band*/
+t_bool wlan_bg_scan_type_is_passive(mlan_private *priv, t_u8 chnl);
+/** check if channel is NO_IR (passive) */
+t_bool wlan_is_chan_passive(mlan_private *priv, t_u8 band, t_u8 chan);
+/** check if channel is disabled */
+t_bool wlan_is_chan_disabled(mlan_private *priv, t_u8 band, t_u8 chan);
+/** check if channel is blacklisted */
+t_bool wlan_is_chan_blacklisted(mlan_private *priv, t_u8 band, t_u8 chan);
+/** set blacklist setting for a channel */
+t_bool wlan_set_chan_blacklist(mlan_private *priv, t_u8 band, t_u8 chan,
+ t_bool bl);
+
+/* 802.11D related functions */
+/** Initialize 11D */
+t_void wlan_11d_priv_init(mlan_private *pmpriv);
+/** Initialize 11D */
+t_void wlan_11d_init(mlan_adapter *pmadapter);
+/** Enable 11D */
+mlan_status wlan_11d_enable(mlan_private *pmpriv, t_void *pioctl_buf,
+ state_11d_t flag);
+/** Get if 11D is enabled */
+t_bool wlan_11d_is_enabled(mlan_private *pmpriv);
+/** Get if FW 11D is enabled */
+t_bool wlan_fw_11d_is_enabled(mlan_private *pmpriv);
+/** Get if priv is station */
+t_bool wlan_is_station(mlan_private *pmpriv);
+/** Command handler for 11D country info */
+mlan_status wlan_cmd_802_11d_domain_info(mlan_private *pmpriv,
+ HostCmd_DS_COMMAND *pcmd,
+ t_u16 cmd_action);
+/** Handler for 11D country info command response */
+mlan_status wlan_ret_802_11d_domain_info(mlan_private *pmpriv,
+ HostCmd_DS_COMMAND *resp);
+/** Convert channel to frequency */
+t_u32 wlan_11d_chan_2_freq(pmlan_adapter pmadapter, t_u8 chan, t_u8 band);
+#ifdef STA_SUPPORT
+/** Set 11D universal table */
+mlan_status wlan_11d_set_universaltable(mlan_private *pmpriv, t_u8 band);
+/** Clear 11D region table */
+mlan_status wlan_11d_clear_parsedtable(mlan_private *pmpriv);
+/** Create 11D country information for downloading */
+mlan_status wlan_11d_create_dnld_countryinfo(mlan_private *pmpriv, t_u8 band);
+/** Get scan type from 11D info */
+t_u8 wlan_11d_get_scan_type(pmlan_adapter pmadapter, t_u8 band, t_u8 chan,
+ parsed_region_chan_11d_t *parsed_region_chan);
+/** Parse 11D country info */
+mlan_status wlan_11d_parse_dnld_countryinfo(mlan_private *pmpriv,
+ BSSDescriptor_t *pBSSDesc);
+/** Prepare 11D domain information for download */
+mlan_status wlan_11d_prepare_dnld_domain_info_cmd(mlan_private *pmpriv);
+/** Parse 11D country information into domain info */
+mlan_status wlan_11d_parse_domain_info(
+ pmlan_adapter pmadapter, IEEEtypes_CountryInfoFullSet_t *country_info,
+ t_u8 band, parsed_region_chan_11d_t *parsed_region_chan);
+#endif /* STA_SUPPORT */
+#ifdef UAP_SUPPORT
+/** Handle 11D domain information from UAP */
+mlan_status wlan_11d_handle_uap_domain_info(mlan_private *pmpriv, t_u8 band,
+ t_u8 *domain_tlv,
+ t_void *pioctl_buf);
+#endif
+/** Configure 11D domain info command */
+mlan_status wlan_11d_cfg_domain_info(pmlan_adapter pmadapter,
+ mlan_ioctl_req *pioctl_req);
+
+/** This function converts region string to CFP table code */
+mlan_status wlan_misc_country_2_cfp_table_code(pmlan_adapter pmadapter,
+ t_u8 *country_code, t_u8 *cfp_bg,
+ t_u8 *cfp_a);
+
+/** This function finds if given country code is in EU table */
+t_bool wlan_is_etsi_country(pmlan_adapter pmadapter, t_u8 *country_code);
+
+/** check if station list is empty */
+t_u8 wlan_is_station_list_empty(mlan_private *priv);
+/** get station node */
+sta_node *wlan_get_station_entry(mlan_private *priv, t_u8 *mac);
+/** delete station list */
+t_void wlan_delete_station_list(pmlan_private priv);
+/** delete station entry */
+t_void wlan_delete_station_entry(mlan_private *priv, t_u8 *mac);
+/** add station entry */
+sta_node *wlan_add_station_entry(mlan_private *priv, t_u8 *mac);
+/** process uap rx packet */
+
+void wlan_check_sta_capability(pmlan_private priv, pmlan_buffer pevent,
+ sta_node *sta_ptr);
+/** find specific ie */
+t_u8 *wlan_get_specific_ie(pmlan_private priv, t_u8 *ie_buf, t_u8 ie_len,
+ IEEEtypes_ElementId_e id, t_u8 ext_id);
+t_u8 wlan_is_wmm_ie_present(pmlan_adapter pmadapter, t_u8 *pbuf, t_u16 buf_len);
+
+/**
+ * @brief This function checks tx_pause flag for peer
+ *
+ * @param priv A pointer to mlan_private
+ * @param ra Address of the receiver STA
+ *
+ * @return MTRUE or MFALSE
+ */
+static INLINE int wlan_is_tx_pause(mlan_private *priv, t_u8 *ra)
+{
+ sta_node *sta_ptr = MNULL;
+ sta_ptr = wlan_get_station_entry(priv, ra);
+ if (sta_ptr)
+ return sta_ptr->tx_pause;
+ return MFALSE;
+}
+t_u16 wlan_update_ralist_tx_pause(pmlan_private priv, t_u8 *mac, t_u8 tx_pause);
+
+#ifdef UAP_SUPPORT
+mlan_status wlan_process_uap_rx_packet(mlan_private *priv, pmlan_buffer pmbuf);
+t_void wlan_drop_tx_pkts(pmlan_private priv);
+#endif /* UAP_SUPPORT */
+
+#ifdef UAP_SUPPORT
+/* process the recevied packet and bridge the packet */
+mlan_status wlan_uap_recv_packet(mlan_private *priv, pmlan_buffer pmbuf);
+#endif /* UAP_SUPPORT */
+
+mlan_status wlan_misc_ioctl_custom_ie_list(pmlan_adapter pmadapter,
+ pmlan_ioctl_req pioctl_req,
+ t_bool send_ioctl);
+
+mlan_status wlan_cmd_get_hw_spec(pmlan_private pmpriv,
+ HostCmd_DS_COMMAND *pcmd);
+mlan_status wlan_ret_get_hw_spec(pmlan_private pmpriv, HostCmd_DS_COMMAND *resp,
+ t_void *pioctl_buf);
+#ifdef SDIO
+mlan_status wlan_cmd_sdio_rx_aggr_cfg(HostCmd_DS_COMMAND *pcmd,
+ t_u16 cmd_action, t_void *pdata_buf);
+mlan_status wlan_ret_sdio_rx_aggr_cfg(pmlan_private pmpriv,
+ HostCmd_DS_COMMAND *resp);
+#endif
+
+mlan_status wlan_misc_ioctl_mac_control(pmlan_adapter pmadapter,
+ pmlan_ioctl_req pioctl_req);
+mlan_status wlan_cmd_mac_control(pmlan_private pmpriv, HostCmd_DS_COMMAND *pcmd,
+ t_u16 cmd_action, t_void *pdata_buf);
+mlan_status wlan_ret_mac_control(pmlan_private pmpriv, HostCmd_DS_COMMAND *resp,
+ mlan_ioctl_req *pioctl_buf);
+
+mlan_status wlan_cmd_cw_mode_ctrl(pmlan_private pmpriv, HostCmd_DS_COMMAND *cmd,
+ t_u16 cmd_action, t_void *pdata_buf);
+mlan_status wlan_ret_cw_mode_ctrl(pmlan_private pmpriv,
+ HostCmd_DS_COMMAND *resp,
+ mlan_ioctl_req *pioctl_buf);
+
+mlan_status wlan_cmd_802_11_radio_control(pmlan_private pmpriv,
+ HostCmd_DS_COMMAND *cmd,
+ t_u16 cmd_action, t_void *pdata_buf);
+mlan_status wlan_ret_802_11_radio_control(pmlan_private pmpriv,
+ HostCmd_DS_COMMAND *resp,
+ mlan_ioctl_req *pioctl_buf);
+
+mlan_status wlan_cmd_802_11_rf_antenna(pmlan_private pmpriv,
+ HostCmd_DS_COMMAND *cmd,
+ t_u16 cmd_action, t_void *pdata_buf);
+mlan_status wlan_ret_802_11_rf_antenna(pmlan_private pmpriv,
+ HostCmd_DS_COMMAND *resp,
+ mlan_ioctl_req *pioctl_buf);
+
+mlan_status wlan_ret_reg_access(mlan_adapter *pmadapter, t_u16 type,
+ HostCmd_DS_COMMAND *resp,
+ mlan_ioctl_req *pioctl_buf);
+mlan_status wlan_ret_mem_access(pmlan_private pmpriv, HostCmd_DS_COMMAND *resp,
+ mlan_ioctl_req *pioctl_buf);
+
+mlan_status wlan_reg_mem_ioctl_reg_rw(pmlan_adapter pmadapter,
+ pmlan_ioctl_req pioctl_req);
+mlan_status wlan_reg_mem_ioctl_read_eeprom(pmlan_adapter pmadapter,
+ pmlan_ioctl_req pioctl_req);
+mlan_status wlan_reg_mem_ioctl_mem_rw(pmlan_adapter pmadapter,
+ pmlan_ioctl_req pioctl_req);
+mlan_status wlan_cmd_reg_access(pmlan_private pmpriv, HostCmd_DS_COMMAND *cmd,
+ t_u16 cmd_action, t_void *pdata_buf);
+mlan_status wlan_cmd_mem_access(HostCmd_DS_COMMAND *cmd, t_u16 cmd_action,
+ t_void *pdata_buf);
+mlan_status wlan_cmd_802_11_mac_address(pmlan_private pmpriv,
+ HostCmd_DS_COMMAND *cmd,
+ t_u16 cmd_action);
+mlan_status wlan_ret_802_11_mac_address(pmlan_private pmpriv,
+ HostCmd_DS_COMMAND *resp,
+ mlan_ioctl_req *pioctl_buf);
+
+mlan_status wlan_get_info_ver_ext(pmlan_adapter pmadapter,
+ pmlan_ioctl_req pioctl_req);
+
+mlan_status wlan_ioctl_link_statistic(mlan_private *pmpriv,
+ pmlan_ioctl_req pioctl_req);
+
+mlan_status wlan_cmd_802_11_link_statistic(pmlan_private pmpriv,
+ HostCmd_DS_COMMAND *cmd,
+ t_u16 cmd_action,
+ mlan_ioctl_req *pioctl_buf);
+
+mlan_status wlan_ret_get_link_statistic(pmlan_private pmpriv,
+ HostCmd_DS_COMMAND *resp,
+ mlan_ioctl_req *pioctl_buf);
+
+mlan_status wlan_reg_rx_mgmt_ind(pmlan_adapter pmadapter,
+ pmlan_ioctl_req pioctl_req);
+
+#ifdef DEBUG_LEVEL1
+mlan_status wlan_set_drvdbg(pmlan_adapter pmadapter,
+ pmlan_ioctl_req pioctl_req);
+#endif
+
+mlan_status wlan_misc_hotspot_cfg(pmlan_adapter pmadapter,
+ pmlan_ioctl_req pioctl_req);
+#ifdef STA_SUPPORT
+mlan_status wlan_misc_ext_capa_cfg(pmlan_adapter pmadapter,
+ pmlan_ioctl_req pioctl_req);
+
+t_u32 wlan_is_ext_capa_support(mlan_private *pmpriv);
+#endif
+
+#ifdef STA_SUPPORT
+void wlan_add_ext_capa_info_ie(mlan_private *pmpriv, BSSDescriptor_t *pbss_desc,
+ t_u8 **pptlv_out);
+#endif
+
+mlan_status wlan_cmd_boot_sleep(pmlan_private pmpriv, HostCmd_DS_COMMAND *cmd,
+ t_u16 cmd_action, t_void *pdata_buf);
+
+mlan_status wlan_ret_boot_sleep(pmlan_private pmpriv, HostCmd_DS_COMMAND *resp,
+ mlan_ioctl_req *pioctl_buf);
+
+#if defined(DRV_EMBEDDED_AUTHENTICATOR) || defined(DRV_EMBEDDED_SUPPLICANT)
+mlan_status wlan_cmd_crypto(pmlan_private pmpriv, HostCmd_DS_COMMAND *cmd,
+ t_u16 cmd_action, t_u16 *pdata_buf);
+
+mlan_status wlan_ret_crypto(pmlan_private pmpriv, HostCmd_DS_COMMAND *resp,
+ mlan_ioctl_req *pioctl_buf);
+#endif
+
+#define BW_20MHZ 0
+#define BW_40MHZ 1
+#define BW_80MHZ 2
+#define BW_160MHZ 3
+int wlan_add_supported_oper_class_ie(mlan_private *pmpriv, t_u8 **pptlv_out,
+ t_u8 curr_oper_class);
+mlan_status wlan_get_curr_oper_class(mlan_private *pmpriv, t_u8 channel,
+ t_u8 bw, t_u8 *oper_class);
+mlan_status wlan_check_operclass_validation(mlan_private *pmpriv, t_u8 channel,
+ t_u8 oper_class);
+mlan_status wlan_misc_ioctl_operclass_validation(pmlan_adapter pmadapter,
+ mlan_ioctl_req *pioctl_req);
+mlan_status wlan_misc_ioctl_oper_class(pmlan_adapter pmadapter,
+ mlan_ioctl_req *pioctl_req);
+
+t_u16 wlan_adjust_data_rate(mlan_private *priv, t_u8 rx_rate, t_u8 rate_info);
+t_u8 wlan_adjust_antenna(pmlan_private priv, RxPD *prx_pd);
+
+mlan_status wlan_misc_otp_user_data(pmlan_adapter pmadapter,
+ pmlan_ioctl_req pioctl_req);
+
+#ifdef USB
+mlan_status wlan_misc_ioctl_usb_aggr_ctrl(pmlan_adapter pmadapter,
+ pmlan_ioctl_req pioctl_req);
+#endif
+
+mlan_status wlan_misc_ioctl_aggr_ctrl(pmlan_adapter pmadapter,
+ pmlan_ioctl_req pioctl_req);
+mlan_status wlan_cmd_packet_aggr_ctrl(pmlan_private pmpriv,
+ HostCmd_DS_COMMAND *cmd, t_u16 cmd_action,
+ t_void *pdata_buf);
+mlan_status wlan_ret_packet_aggr_ctrl(pmlan_private pmpriv,
+ HostCmd_DS_COMMAND *resp,
+ mlan_ioctl_req *pioctl_buf);
+mlan_status wlan_misc_ioctl_txcontrol(pmlan_adapter pmadapter,
+ pmlan_ioctl_req pioctl_req);
+
+mlan_status wlan_misc_ioctl_region(pmlan_adapter pmadapter,
+ pmlan_ioctl_req pioctl_req);
+
+#ifdef RX_PACKET_COALESCE
+mlan_status wlan_misc_ioctl_rx_pkt_coalesce_config(pmlan_adapter pmadapter,
+ pmlan_ioctl_req pioctl_req);
+#endif
+
+void wlan_bt_coex_wlan_param_update_event(pmlan_private priv,
+ pmlan_buffer pevent);
+
+mlan_status wlan_misc_ioctl_dfs_repeater_cfg(pmlan_adapter pmadapter,
+ pmlan_ioctl_req pioctl_req);
+
+t_bool wlan_check_interface_active(mlan_adapter *pmadapter);
+
+mlan_status wlan_misc_ioctl_coalesce_cfg(pmlan_adapter pmadapter,
+ pmlan_ioctl_req pioctl_req);
+
+mlan_status wlan_misc_ioctl_low_pwr_mode(pmlan_adapter pmadapter,
+ pmlan_ioctl_req pioctl_req);
+
+mlan_status wlan_misc_ioctl_pmic_configure(pmlan_adapter pmadapter,
+ pmlan_ioctl_req pioctl_req);
+
+mlan_status wlan_misc_ioctl_cwmode_ctrl(pmlan_adapter pmadapter,
+ pmlan_ioctl_req pioctl_req);
+
+mlan_status wlan_set_mef_entry(mlan_private *pmpriv, pmlan_adapter pmadapter,
+ mef_cfg *pmef);
+mlan_status wlan_process_mef_cfg_cmd(mlan_private *pmpriv,
+ pmlan_adapter pmadapter);
+mlan_status wlan_misc_ioctl_mef_flt_cfg(pmlan_adapter pmadapter,
+ pmlan_ioctl_req pioctl_req);
+
+mlan_status wlan_misc_ioctl_ind_rst_cfg(pmlan_adapter pmadapter,
+ pmlan_ioctl_req pioctl_req);
+mlan_status wlan_cmd_ind_rst_cfg(HostCmd_DS_COMMAND *cmd, t_u16 cmd_action,
+ t_void *pdata_buf);
+mlan_status wlan_ret_ind_rst_cfg(pmlan_private pmpriv, HostCmd_DS_COMMAND *resp,
+ mlan_ioctl_req *pioctl_buf);
+
+mlan_status wlan_cmd_802_11_supplicant_pmk(pmlan_private pmpriv,
+ HostCmd_DS_COMMAND *cmd,
+ t_u16 cmd_action, t_void *pdata_buf);
+
+mlan_status wlan_ret_802_11_supplicant_pmk(pmlan_private pmpriv,
+ HostCmd_DS_COMMAND *resp,
+ mlan_ioctl_req *pioctl_buf);
+
+mlan_status wlan_sec_ioctl_passphrase(pmlan_adapter pmadapter,
+ pmlan_ioctl_req pioctl_req);
+
+mlan_status wlan_misc_ioctl_get_tsf(pmlan_adapter pmadapter,
+ pmlan_ioctl_req pioctl_req);
+void wlan_add_fw_cfp_tables(pmlan_private pmpriv, t_u8 *buf, t_u16 buf_left);
+
+void wlan_free_fw_cfp_tables(mlan_adapter *pmadapter);
+
+mlan_status wlan_misc_chan_reg_cfg(pmlan_adapter pmadapter,
+ pmlan_ioctl_req pioctl_req);
+
+mlan_status wlan_get_cfp_table(pmlan_adapter pmadapter,
+ pmlan_ioctl_req pioctl_req);
+mlan_status wlan_get_cfpinfo(pmlan_adapter pmadapter,
+ pmlan_ioctl_req pioctl_req);
+
+mlan_status wlan_cmd_get_tsf(pmlan_private pmpriv, HostCmd_DS_COMMAND *cmd,
+ t_u16 cmd_action);
+mlan_status wlan_ret_get_tsf(pmlan_private pmpriv, HostCmd_DS_COMMAND *resp,
+ mlan_ioctl_req *pioctl_buf);
+
+t_u8 wlan_ft_akm_is_used(mlan_private *pmpriv, t_u8 *rsn_ie);
+
+mlan_status wlan_get_rgchnpwr_cfg(pmlan_adapter pmadapter,
+ mlan_ioctl_req *pioctl_req);
+mlan_status wlan_get_chan_trpc_cfg(pmlan_adapter pmadapter,
+ mlan_ioctl_req *pioctl_req);
+mlan_status wlan_cmd_get_chan_trpc_config(pmlan_private pmpriv,
+ HostCmd_DS_COMMAND *cmd,
+ t_u16 cmd_action, t_void *pdata_buf);
+mlan_status wlan_ret_get_chan_trpc_config(pmlan_private pmpriv,
+ HostCmd_DS_COMMAND *resp,
+ mlan_ioctl_req *pioctl_buf);
+
+mlan_status wlan_cmd_ps_inactivity_timeout(pmlan_private pmpriv,
+ HostCmd_DS_COMMAND *cmd,
+ t_u16 cmd_action, t_void *pdata_buf);
+
+t_u8 wlan_ieee_rateid_to_mrvl_rateid(mlan_private *priv, t_u16 IeeeMacRate,
+ t_u8 *dst_mac);
+t_u8 wlan_mrvl_rateid_to_ieee_rateid(t_u8 rate);
+
+t_u8 wlan_get_center_freq_idx(mlan_private *pmpriv, t_u16 band, t_u32 pri_chan,
+ t_u8 chan_bw);
+
+mlan_status wlan_ret_chan_region_cfg(pmlan_private pmpriv,
+ HostCmd_DS_COMMAND *resp,
+ mlan_ioctl_req *pioctl_buf);
+
+mlan_status wlan_misc_ioctl_fw_dump_event(pmlan_adapter pmadapter,
+ mlan_ioctl_req *pioctl_req);
+mlan_status wlan_cmd_fw_dump_event(pmlan_private pmpriv,
+ HostCmd_DS_COMMAND *cmd, t_u16 cmd_action,
+ t_void *pdata_buf);
+
+mlan_status wlan_misc_bootsleep(pmlan_adapter pmadapter,
+ pmlan_ioctl_req pioctl_req);
+
+mlan_status wlan_misc_ioctl_dyn_bw(pmlan_adapter pmadapter,
+ mlan_ioctl_req *pioctl_req);
+mlan_status wlan_cmd_config_dyn_bw(pmlan_private pmpriv,
+ HostCmd_DS_COMMAND *cmd, t_u16 cmd_action,
+ t_void *pdata_buf);
+mlan_status wlan_ret_dyn_bw(pmlan_private pmpriv, HostCmd_DS_COMMAND *resp,
+ mlan_ioctl_req *pioctl_buf);
+
+mlan_status wlan_power_ioctl_set_get_lpm(pmlan_adapter pmadapter,
+ pmlan_ioctl_req pioctl_req);
+mlan_status wlan_cmd_set_get_low_power_mode_cfg(pmlan_private pmpriv,
+ HostCmd_DS_COMMAND *cmd,
+ t_u16 cmd_action,
+ t_void *pdata_buf);
+mlan_status wlan_ret_set_get_low_power_mode_cfg(pmlan_private pmpriv,
+ HostCmd_DS_COMMAND *resp,
+ mlan_ioctl_req *pioctl_buf);
+
+mlan_status wlan_cmd_range_ext(pmlan_private pmpriv, HostCmd_DS_COMMAND *cmd,
+ t_u16 cmd_action, t_void *pdata_buf);
+mlan_status wlan_ret_range_ext(pmlan_private pmpriv, HostCmd_DS_COMMAND *resp,
+ mlan_ioctl_req *pioctl_buf);
+
+/**
+ * @brief RA based queueing
+ *
+ * @param priv A pointer to mlan_private structure
+ *
+ * @return MTRUE or MFALSE
+ */
+static INLINE t_u8 queuing_ra_based(pmlan_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 == MLAN_BSS_MODE_INFRA) &&
+ (GET_BSS_ROLE(priv) == MLAN_BSS_ROLE_STA))
+ return MFALSE;
+
+ return MTRUE;
+}
+
+/**
+ * @brief Copy Rates
+ *
+ * @param dest A pointer to Dest Buf
+ * @param pos The position for copy
+ * @param src A pointer to Src Buf
+ * @param len The len of Src Buf
+ *
+ * @return Number of Rates copied
+ */
+static INLINE t_u32 wlan_copy_rates(t_u8 *dest, t_u32 pos, t_u8 *src, int len)
+{
+ int i;
+
+ for (i = 0; i < len && src[i]; i++, pos++) {
+ if (pos >= sizeof(WLAN_802_11_RATES))
+ break;
+ dest[pos] = src[i];
+ }
+
+ return pos;
+}
+
+/**
+ * @brief strlen
+ *
+ * @param str A pointer to string
+ *
+ * @return Length of string
+ */
+static INLINE t_u32 wlan_strlen(const char *str)
+{
+ t_u32 i;
+
+ for (i = 0; str[i] != 0; i++)
+ ;
+
+ return i;
+}
+
+/**
+ * @brief iscdigit
+ *
+ * @param chr A char
+ *
+ * @return Non zero if chr is a hex, else 0
+ */
+static INLINE t_u32 wlan_isxdigit(t_u8 chr)
+{
+ return (chr <= 'f' && chr >= 'a') || (chr <= 'F' && chr >= 'A') ||
+ (chr <= '9' && chr >= '0');
+}
+
+/**
+ * @brief isspace
+ *
+ * @param A chr
+ *
+ * @return Non zero if chr is space etc, else 0
+ */
+static INLINE t_u32 wlan_isspace(t_u8 chr)
+{
+ return chr <= ' ' && (chr == ' ' || (chr <= 13 && chr >= 9));
+}
+
+/** delay unit */
+typedef enum _delay_unit {
+ USEC,
+ MSEC,
+ SEC,
+} t_delay_unit;
+
+/** delay function */
+t_void wlan_delay_func(mlan_adapter *pmadapter, t_u32 delay, t_delay_unit u);
+
+/** delay function wrapper */
+#define wlan_delay(p, n) wlan_delay_func(p, n, SEC)
+/** delay function wrapper */
+#define wlan_mdelay(p, n) wlan_delay_func(p, n, MSEC)
+/** delay function wrapper */
+#define wlan_udelay(p, n) wlan_delay_func(p, n, USEC)
+
+/**
+ * @brief This function check if there are pending cmd
+ * in cmd pending Q
+ *
+ * @param pmadapter A pointer to mlan_adapter structure
+ *
+ * @return MTRUE -- cmd pending
+ * MFALSE -- no pending cmd
+ */
+static INLINE int wlan_is_cmd_pending(mlan_adapter *pmadapter)
+{
+ int ret;
+ cmd_ctrl_node *pcmd_node = MNULL;
+ wlan_request_cmd_lock(pmadapter);
+ pcmd_node = (cmd_ctrl_node *)util_peek_list(pmadapter->pmoal_handle,
+ &pmadapter->cmd_pending_q,
+ MNULL, MNULL);
+ if (pcmd_node)
+ ret = MTRUE;
+ else
+ ret = MFALSE;
+ wlan_release_cmd_lock(pmadapter);
+ return ret;
+}
+
+/** Get BSS number from priv */
+#define GET_BSS_NUM(priv) ((priv)->bss_num)
+
+/**
+ * @brief This function returns priv based on the BSS num and BSS type
+ *
+ * @param pmadapter A pointer to mlan_adapter
+ * @param bss_num BSS number
+ * @param bss_type BSS type
+ *
+ * @return Pointer to mlan_private
+ */
+static INLINE mlan_private *wlan_get_priv_by_id(mlan_adapter *pmadapter,
+ t_u32 bss_num, t_u32 bss_type)
+{
+ int i;
+
+ for (i = 0; i < MIN(pmadapter->priv_num, MLAN_MAX_BSS_NUM); i++) {
+ if (pmadapter->priv[i]) {
+ if ((pmadapter->priv[i]->bss_num == bss_num) &&
+ (pmadapter->priv[i]->bss_type == bss_type))
+ return pmadapter->priv[i];
+ }
+ }
+ return MNULL;
+}
+
+/**
+ * @brief This function returns first available priv
+ * based on the BSS role
+ *
+ * @param pmadapter A pointer to mlan_adapter
+ * @param bss_role BSS role or MLAN_BSS_ROLE_ANY
+ *
+ * @return Pointer to mlan_private
+ */
+static INLINE mlan_private *wlan_get_priv(mlan_adapter *pmadapter,
+ mlan_bss_role bss_role)
+{
+ int i;
+
+ for (i = 0; i < MIN(pmadapter->priv_num, MLAN_MAX_BSS_NUM); i++) {
+ if (pmadapter->priv[i]) {
+ if (bss_role == MLAN_BSS_ROLE_ANY ||
+ GET_BSS_ROLE(pmadapter->priv[i]) == bss_role)
+ return pmadapter->priv[i];
+ }
+ }
+ return MNULL;
+}
+
+/**
+ * @brief This function counts the number of occurences for a certain
+ * condition among privs. Which privs are checked can be configured
+ * via a second condition.
+ *
+ * @param pmadapter A pointer to mlan_adapter
+ * @param count_cond Function pointer to condition to count on privs
+ * @param check_cond Function pointer to condition to decide whether priv
+ * should be counted or not. Use MNULL to check all privs.
+ *
+ * @return Count of privs where count_cond returned MTRUE.
+ */
+static INLINE int
+wlan_count_priv_cond(mlan_adapter *pmadapter,
+ t_bool (*count_cond)(pmlan_private pmpriv),
+ t_bool (*check_cond)(pmlan_private pmpriv))
+{
+ pmlan_private pmpriv;
+ int count = 0;
+ int i;
+
+ if (pmadapter == MNULL || count_cond == MNULL)
+ return 0;
+
+ for (i = 0; i < pmadapter->priv_num; i++) {
+ pmpriv = pmadapter->priv[i];
+ if (pmpriv) {
+ if ((check_cond == MNULL) ||
+ (check_cond && check_cond(pmpriv))) {
+ if (count_cond(pmpriv))
+ count++;
+ }
+ }
+ }
+
+ return count;
+}
+
+/**
+ * @brief This function runs a procedure on each priv.
+ * Which privs it is run on can be configured via a condition.
+ *
+ * @param pmadapter A pointer to mlan_adapter
+ * @param operation Function pointer to produedure to operate on priv
+ * @param check_cond Function pointer to condition to decide whether priv
+ * operated on or not. Use MNULL to run on all privs.
+ *
+ * @return Number of privs that operation was run on.
+ */
+static INLINE int
+wlan_do_task_on_privs(mlan_adapter *pmadapter,
+ t_void (*operation)(pmlan_private pmpriv),
+ t_bool (*check_cond)(pmlan_private pmpriv))
+{
+ pmlan_private pmpriv;
+ int count = 0;
+ int i;
+
+ if (pmadapter == MNULL || operation == MNULL)
+ return 0;
+
+ for (i = 0; i < pmadapter->priv_num; i++) {
+ pmpriv = pmadapter->priv[i];
+ if (pmpriv) {
+ if ((check_cond == MNULL) ||
+ (check_cond && check_cond(pmpriv))) {
+ operation(pmpriv);
+ count++;
+ }
+ }
+ }
+
+ return count;
+}
+
+/**
+ * @brief This function builds a list of privs that test for a condition
+ * This is useful if you need to do a number of operations on the same set
+ * of privs. For one-off tasks, the above two functions might be better.
+ *
+ * @param pmadapter A pointer to mlan_adapter
+ * @param check_cond Function pointer to condition to decide whether priv
+ * should be placed in the list.
+ * @param ppriv_list Output param. Externally supplied array of mlan_private*
+ * to hold priv's that test positive with check_cond.
+ * Array size should be at least pmadapter->priv_num.
+ *
+ * @return Number of privs in ppriv_list
+ *
+ * @sa wlan_count_priv_cond
+ */
+static INLINE int
+wlan_get_privs_by_cond(mlan_adapter *pmadapter,
+ t_bool (*check_cond)(pmlan_private pmpriv),
+ mlan_private **ppriv_list)
+{
+ pmlan_private pmpriv;
+ int count = 0;
+ int i;
+
+ if (pmadapter == MNULL || check_cond == MNULL || ppriv_list == MNULL)
+ return 0;
+
+ for (i = 0; i < pmadapter->priv_num; i++) {
+ pmpriv = pmadapter->priv[i];
+ if (pmpriv) {
+ if (check_cond(pmpriv))
+ ppriv_list[count++] = pmpriv;
+ }
+ }
+
+ return count;
+}
+
+/**
+ * @brief This function builds a list of privs that test against two conditions
+ * This is useful if you need to do a number of operations on the same set
+ * of privs. Can choose whether both conditions (AND) or either condition (OR)
+ * is required.
+ *
+ * @param pmadapter A pointer to mlan_adapter
+ * @param check_cond Function pointer to condition to decide whether priv
+ * should be placed in the list.
+ * @param check_cond_2 Function pointer to second condition to check.
+ * @param and_conditions If MTRUE, both conditions must be met (AND),
+ * else either condition can be met (OR).
+ * @param ppriv_list Output param. Externally supplied array of
+ * mlan_private* to hold priv's that test positive with check_cond. Array size
+ * should be at least pmadapter->priv_num.
+ *
+ * @return Number of privs in ppriv_list
+ *
+ * @sa wlan_count_priv_cond, wlan_get_privs_by_cond
+ */
+static INLINE int
+wlan_get_privs_by_two_cond(mlan_adapter *pmadapter,
+ t_bool (*check_cond)(pmlan_private pmpriv),
+ t_bool (*check_cond_2)(pmlan_private pmpriv),
+ t_bool and_conditions, mlan_private **ppriv_list)
+{
+ pmlan_private pmpriv;
+ int count = 0;
+ int i;
+
+ if (pmadapter == MNULL || check_cond == MNULL ||
+ check_cond_2 == MNULL || ppriv_list == MNULL)
+ return 0;
+
+ for (i = 0; i < pmadapter->priv_num; i++) {
+ pmpriv = pmadapter->priv[i];
+ if (pmpriv) {
+ if (and_conditions) {
+ if (check_cond(pmpriv) && check_cond_2(pmpriv))
+ ppriv_list[count++] = pmpriv;
+ } else {
+ if (check_cond(pmpriv) || check_cond_2(pmpriv))
+ ppriv_list[count++] = pmpriv;
+ }
+ }
+ }
+
+ return count;
+}
+#endif /* !_MLAN_MAIN_H_ */
diff --git a/drivers/net/wireless/nxp/mxm_wifiex/wlan_src/mlan/mlan_meas.c b/drivers/net/wireless/nxp/mxm_wifiex/wlan_src/mlan/mlan_meas.c
new file mode 100644
index 000000000000..38d16af57732
--- /dev/null
+++ b/drivers/net/wireless/nxp/mxm_wifiex/wlan_src/mlan/mlan_meas.c
@@ -0,0 +1,465 @@
+/**
+ * @file mlan_meas.c
+ *
+ * @brief Implementation of measurement interface code with the app/firmware
+ *
+ * Driver implementation for sending and retrieving measurement requests
+ * and responses.
+ *
+ * Current use is limited to 802.11h.
+ *
+ * Requires use of the following preprocessor define:
+ * - ENABLE_MEAS
+ *
+ *
+ * Copyright 2014-2020 NXP
+ *
+ * This software file (the File) is distributed by NXP
+ * under the terms of the GNU General Public License Version 2, June 1991
+ * (the License). You may use, redistribute and/or modify the 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.
+ *
+ */
+
+/*************************************************************
+Change Log:
+ 03/24/2009: initial version
+************************************************************/
+
+#include "mlan.h"
+#include "mlan_join.h"
+#include "mlan_util.h"
+#include "mlan_fw.h"
+#include "mlan_main.h"
+#include "mlan_ioctl.h"
+#include "mlan_meas.h"
+
+/** Default measurement duration when not provided by the application */
+#define WLAN_MEAS_DEFAULT_MEAS_DURATION 1000U /* TUs */
+
+#ifdef DEBUG_LEVEL2
+/** String descriptions of the different measurement enums. Debug display */
+static const char *meas_type_str[WLAN_MEAS_NUM_TYPES] = {
+ "basic",
+};
+
+/********************************************************
+ Local Functions
+********************************************************/
+
+/**
+ * @brief Retrieve the measurement string representation of a meas_type enum
+ * Used for debug display only
+ *
+ * @param meas_type Measurement type enumeration input for string lookup
+ *
+ * @return Constant string representing measurement type
+ */
+static const char *wlan_meas_get_meas_type_str(MeasType_t meas_type)
+{
+ if (meas_type <= WLAN_MEAS_11H_MAX_TYPE)
+ return meas_type_str[meas_type];
+
+ return "Invld";
+}
+#endif
+
+/**
+ * @brief Debug print display of the input measurement request
+ *
+ * @param pmeas_req Pointer to the measurement request to display
+ *
+ * @return N/A
+ */
+static void
+wlan_meas_dump_meas_req(const HostCmd_DS_MEASUREMENT_REQUEST *pmeas_req)
+{
+ ENTER();
+
+ PRINTM(MINFO, "Meas: Req: ------------------------------\n");
+
+ PRINTM(MINFO, "Meas: Req: mac_addr: " MACSTR "\n",
+ MAC2STR(pmeas_req->mac_addr));
+
+ PRINTM(MINFO, "Meas: Req: dlgTkn: %d\n", pmeas_req->dialog_token);
+ PRINTM(MINFO, "Meas: Req: mode: dm[%c] rpt[%c] req[%c]\n",
+ pmeas_req->req_mode.duration_mandatory ? 'X' : ' ',
+ pmeas_req->req_mode.report ? 'X' : ' ',
+ pmeas_req->req_mode.request ? 'X' : ' ');
+ PRINTM(MINFO, "Meas: Req: : en[%c] par[%c]\n",
+ pmeas_req->req_mode.enable ? 'X' : ' ',
+ pmeas_req->req_mode.parallel ? 'X' : ' ');
+#ifdef DEBUG_LEVEL2
+ PRINTM(MINFO, "Meas: Req: measTyp: %s\n",
+ wlan_meas_get_meas_type_str(pmeas_req->meas_type));
+#endif
+
+ switch (pmeas_req->meas_type) {
+ case WLAN_MEAS_BASIC:
+ /* Lazy cheat, fields of bas, cca, rpi union match on the
+ * request */
+ PRINTM(MINFO, "Meas: Req: chan: %u\n",
+ pmeas_req->req.basic.channel);
+ PRINTM(MINFO, "Meas: Req: strt: %llu\n",
+ wlan_le64_to_cpu(pmeas_req->req.basic.start_time));
+ PRINTM(MINFO, "Meas: Req: dur: %u\n",
+ wlan_le16_to_cpu(pmeas_req->req.basic.duration));
+ break;
+ default:
+ PRINTM(MINFO, "Meas: Req: <unhandled>\n");
+ break;
+ }
+
+ PRINTM(MINFO, "Meas: Req: ------------------------------\n");
+ LEAVE();
+}
+
+/**
+ * @brief Debug print display of the input measurement report
+ *
+ * @param pmeas_rpt Pointer to measurement report to display
+ *
+ * @return N/A
+ */
+static void
+wlan_meas_dump_meas_rpt(const HostCmd_DS_MEASUREMENT_REPORT *pmeas_rpt)
+{
+ MeasType_t type;
+ ENTER();
+
+ PRINTM(MINFO, "Meas: Rpt: ------------------------------\n");
+ PRINTM(MINFO, "Meas: Rpt: mac_addr: " MACSTR "\n",
+ MAC2STR(pmeas_rpt->mac_addr));
+
+ PRINTM(MINFO, "Meas: Rpt: dlgTkn: %d\n", pmeas_rpt->dialog_token);
+
+ PRINTM(MINFO, "Meas: Rpt: rptMode: (%x): Rfs[%c] ICp[%c] Lt[%c]\n",
+ *(t_u8 *)&pmeas_rpt->rpt_mode,
+ pmeas_rpt->rpt_mode.refused ? 'X' : ' ',
+ pmeas_rpt->rpt_mode.incapable ? 'X' : ' ',
+ pmeas_rpt->rpt_mode.late ? 'X' : ' ');
+#ifdef DEBUG_LEVEL2
+ PRINTM(MINFO, "Meas: Rpt: measTyp: %s\n",
+ wlan_meas_get_meas_type_str(pmeas_rpt->meas_type));
+#endif
+
+ type = wlan_le32_to_cpu(pmeas_rpt->meas_type);
+ switch (type) {
+ case WLAN_MEAS_BASIC:
+ PRINTM(MINFO, "Meas: Rpt: chan: %u\n",
+ pmeas_rpt->rpt.basic.channel);
+ PRINTM(MINFO, "Meas: Rpt: strt: %llu\n",
+ wlan_le64_to_cpu(pmeas_rpt->rpt.basic.start_time));
+ PRINTM(MINFO, "Meas: Rpt: dur: %u\n",
+ wlan_le16_to_cpu(pmeas_rpt->rpt.basic.duration));
+ PRINTM(MINFO, "Meas: Rpt: bas: (%x): unmsd[%c], radar[%c]\n",
+ *(t_u8 *)&(pmeas_rpt->rpt.basic.map),
+ pmeas_rpt->rpt.basic.map.unmeasured ? 'X' : ' ',
+ pmeas_rpt->rpt.basic.map.radar ? 'X' : ' ');
+ PRINTM(MINFO, "Meas: Rpt: bas: unidSig[%c] ofdm[%c] bss[%c]\n",
+ pmeas_rpt->rpt.basic.map.unidentified_sig ? 'X' : ' ',
+ pmeas_rpt->rpt.basic.map.ofdm_preamble ? 'X' : ' ',
+ pmeas_rpt->rpt.basic.map.bss ? 'X' : ' ');
+ break;
+ default:
+ PRINTM(MINFO, "Meas: Rpt: <unhandled>\n");
+ break;
+ }
+
+ PRINTM(MINFO, "Meas: Rpt: ------------------------------\n");
+ LEAVE();
+}
+
+/**
+ * @brief Retrieve a measurement report from the firmware
+ *
+ * Callback from command processing when a measurement report is received
+ * from the firmware. Perform the following when a report is received:
+ *
+ * -# Debug displays the report if compiled with the appropriate flags
+ * -# If we are pending on a specific measurement report token, and it
+ * matches the received report's token, store the report and wake up
+ * any pending threads
+ *
+ * @param pmpriv Private driver information structure
+ * @param resp HostCmd_DS_COMMAND struct returned from the firmware command
+ * passing a HostCmd_DS_MEASUREMENT_REPORT structure.
+ *
+ * @return MLAN_STATUS_SUCCESS
+ */
+static int wlan_meas_cmdresp_get_report(mlan_private *pmpriv,
+ const HostCmd_DS_COMMAND *resp)
+{
+ mlan_adapter *pmadapter = pmpriv->adapter;
+ const HostCmd_DS_MEASUREMENT_REPORT *pmeas_rpt = &resp->params.meas_rpt;
+
+ ENTER();
+
+ PRINTM(MINFO, "Meas: Rpt: %#x-%u, Seq=%u, Ret=%u\n", resp->command,
+ resp->size, resp->seq_num, resp->result);
+
+ /* Debug displays the measurement report */
+ wlan_meas_dump_meas_rpt(pmeas_rpt);
+
+ /*
+ * Check if we are pending on a measurement report and it matches
+ * the dialog token of the received report:
+ */
+ if (pmadapter->state_meas.meas_rpt_pend_on &&
+ pmadapter->state_meas.meas_rpt_pend_on == pmeas_rpt->dialog_token) {
+ PRINTM(MINFO, "Meas: Rpt: RCV'd Pend on meas #%d\n",
+ pmadapter->state_meas.meas_rpt_pend_on);
+
+ /* Clear the pending report indicator */
+ pmadapter->state_meas.meas_rpt_pend_on = 0;
+
+ /* Copy the received report into the measurement state for
+ * retrieval */
+ memcpy_ext(pmadapter, &pmadapter->state_meas.meas_rpt_returned,
+ pmeas_rpt,
+ sizeof(pmadapter->state_meas.meas_rpt_returned),
+ sizeof(pmadapter->state_meas.meas_rpt_returned));
+
+ /*
+ * Wake up any threads pending on the wait queue
+ */
+ wlan_recv_event(pmpriv, MLAN_EVENT_ID_DRV_MEAS_REPORT, MNULL);
+ }
+
+ LEAVE();
+
+ return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ * @brief Prepare CMD_MEASURMENT_REPORT firmware command
+ *
+ * @param pmpriv Private driver information structure
+ * @param pcmd_ptr Output parameter: Pointer to the command being prepared
+ * for the firmware
+ * @param pinfo_buf HostCmd_DS_MEASUREMENT_REQUEST passed as void data block
+ *
+ * @return MLAN_STATUS_SUCCESS
+ */
+static int wlan_meas_cmd_request(mlan_private *pmpriv,
+ HostCmd_DS_COMMAND *pcmd_ptr,
+ const void *pinfo_buf)
+{
+ const HostCmd_DS_MEASUREMENT_REQUEST *pmeas_req =
+ (HostCmd_DS_MEASUREMENT_REQUEST *)pinfo_buf;
+
+ ENTER();
+
+ pcmd_ptr->command = HostCmd_CMD_MEASUREMENT_REQUEST;
+ pcmd_ptr->size = sizeof(HostCmd_DS_MEASUREMENT_REQUEST) + S_DS_GEN;
+
+ memcpy_ext(pmpriv->adapter, &pcmd_ptr->params.meas_req, pmeas_req,
+ sizeof(pcmd_ptr->params.meas_req),
+ sizeof(pcmd_ptr->params.meas_req));
+
+ PRINTM(MINFO, "Meas: Req: %#x-%u, Seq=%u, Ret=%u\n", pcmd_ptr->command,
+ pcmd_ptr->size, pcmd_ptr->seq_num, pcmd_ptr->result);
+
+ wlan_meas_dump_meas_req(pmeas_req);
+
+ LEAVE();
+
+ return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ * @brief Retrieve a measurement report from the firmware
+ *
+ * The firmware will send a EVENT_MEAS_REPORT_RDY event when it
+ * completes or receives a measurement report. The event response
+ * handler will then start a HostCmd_CMD_MEASUREMENT_REPORT firmware command
+ * which gets completed for transmission to the firmware in this routine.
+ *
+ * @param pmpriv Private driver information structure
+ * @param pcmd_ptr Output parameter: Pointer to the command being prepared
+ * for the firmware
+ *
+ * @return MLAN_STATUS_SUCCESS
+ */
+static int wlan_meas_cmd_get_report(mlan_private *pmpriv,
+ HostCmd_DS_COMMAND *pcmd_ptr)
+{
+ ENTER();
+
+ pcmd_ptr->command = HostCmd_CMD_MEASUREMENT_REPORT;
+ pcmd_ptr->size = sizeof(HostCmd_DS_MEASUREMENT_REPORT) + S_DS_GEN;
+
+ memset(pmpriv->adapter, &pcmd_ptr->params.meas_rpt, 0x00,
+ sizeof(pcmd_ptr->params.meas_rpt));
+
+ /*
+ * Set the meas_rpt.mac_addr to our mac address to get a meas report,
+ * setting the mac to another STA address instructs the firmware
+ * to transmit this measurement report frame instead
+ */
+ memcpy_ext(pmpriv->adapter, pcmd_ptr->params.meas_rpt.mac_addr,
+ pmpriv->curr_addr,
+ sizeof(pcmd_ptr->params.meas_rpt.mac_addr),
+ sizeof(pcmd_ptr->params.meas_rpt.mac_addr));
+
+ LEAVE();
+
+ return MLAN_STATUS_SUCCESS;
+}
+
+/********************************************************
+ Global functions
+********************************************************/
+
+/**
+ * @brief Send the input measurement request to the firmware.
+ *
+ * If the dialog token in the measurement request is set to 0, the function
+ * will use an local static auto-incremented token in the measurement
+ * request. This ensures the dialog token is always set.
+ *
+ * If wait_for_resp_timeout is set, the function will block its return on
+ * a timeout or returned measurement report that matches the requests
+ * dialog token.
+ *
+ * @param pmpriv Private driver information structure
+ * @param pmeas_req Pointer to the measurement request to send
+ * @param wait_for_resp_timeout Timeout value of the measurement request
+ * in ms.
+ * @param pioctl_req Pointer to IOCTL request buffer
+ * @param pmeas_rpt Output parameter: Pointer for the resulting
+ * measurement report
+ *
+ * @return
+ * - 0 for success
+ * - -ETIMEDOUT if the measurement report does not return before
+ * the timeout expires
+ * - Error return from wlan_prepare_cmd routine otherwise
+ */
+int wlan_meas_util_send_req(mlan_private *pmpriv,
+ HostCmd_DS_MEASUREMENT_REQUEST *pmeas_req,
+ t_u32 wait_for_resp_timeout,
+ pmlan_ioctl_req pioctl_req,
+ HostCmd_DS_MEASUREMENT_REPORT *pmeas_rpt)
+{
+ static t_u8 auto_dialog_tok;
+ wlan_meas_state_t *pmeas_state = &pmpriv->adapter->state_meas;
+ int ret;
+
+ ENTER();
+
+ /* If dialogTok was set to 0 or not provided, autoset */
+ pmeas_req->dialog_token =
+ (pmeas_req->dialog_token ? pmeas_req->dialog_token :
+ ++auto_dialog_tok);
+
+ /* Check for rollover of the dialog token. Avoid using 0 as a token */
+ pmeas_req->dialog_token =
+ (pmeas_req->dialog_token ? pmeas_req->dialog_token : 1);
+
+ /*
+ * If the request is to pend waiting for the result, set the dialog
+ * token of this measurement request in the state structure. The
+ * measurement report handling routines can then check the incoming
+ * measurement reports for a match with this dialog token.
+ */
+ if (wait_for_resp_timeout) {
+ pmeas_state->meas_rpt_pend_on = pmeas_req->dialog_token;
+ PRINTM(MINFO, "Meas: Req: START Pend on meas #%d\n",
+ pmeas_req->dialog_token);
+ }
+
+ /* Send the measurement request to the firmware */
+ ret = wlan_prepare_cmd(pmpriv, HostCmd_CMD_MEASUREMENT_REQUEST,
+ HostCmd_ACT_GEN_SET, 0, (t_void *)pioctl_req,
+ (void *)pmeas_req);
+
+ LEAVE();
+ return ret;
+}
+
+/**
+ * @brief Prepare the HostCmd_DS_Command structure for a measurement command.
+ *
+ * Use the Command field to determine if the command being set up is for
+ * 11h and call one of the local command handlers accordingly for:
+ *
+ * - HostCmd_CMD_MEASUREMENT_REQUEST
+ * - HostCmd_CMD_MEASUREMENT_REPORT
+ *
+ * @param pmpriv Private driver information structure
+ * @param pcmd_ptr Output parameter: Pointer to the command being prepared
+ * for the firmware
+ * @param pinfo_buf Void buffer passthrough with data necessary for a
+ * specific command type
+ *
+ * @return MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ *
+ */
+int wlan_meas_cmd_process(mlan_private *pmpriv, HostCmd_DS_COMMAND *pcmd_ptr,
+ const void *pinfo_buf)
+{
+ int ret = MLAN_STATUS_SUCCESS;
+
+ ENTER();
+ switch (pcmd_ptr->command) {
+ case HostCmd_CMD_MEASUREMENT_REQUEST:
+ ret = wlan_meas_cmd_request(pmpriv, pcmd_ptr, pinfo_buf);
+ break;
+ case HostCmd_CMD_MEASUREMENT_REPORT:
+ ret = wlan_meas_cmd_get_report(pmpriv, pcmd_ptr);
+ break;
+ default:
+ ret = MLAN_STATUS_FAILURE;
+ }
+
+ pcmd_ptr->command = wlan_cpu_to_le16(pcmd_ptr->command);
+ pcmd_ptr->size = wlan_cpu_to_le16(pcmd_ptr->size);
+ LEAVE();
+ return ret;
+}
+
+/**
+ * @brief Handle the command response from the firmware for a measurement
+ * command
+ *
+ * Use the Command field to determine if the command response being
+ * is for meas. Call the local command response handler accordingly for:
+ *
+ * - HostCmd_CMD_802_MEASUREMENT_REQUEST
+ * - HostCmd_CMD_802_MEASUREMENT_REPORT
+ *
+ * @param pmpriv Private driver information structure
+ * @param resp HostCmd_DS_COMMAND struct returned from the firmware command
+ *
+ * @return MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ */
+int wlan_meas_cmdresp_process(mlan_private *pmpriv,
+ const HostCmd_DS_COMMAND *resp)
+{
+ int ret = MLAN_STATUS_SUCCESS;
+
+ ENTER();
+ switch (resp->command) {
+ case HostCmd_CMD_MEASUREMENT_REQUEST:
+ PRINTM(MINFO, "Meas: Req Resp: Sz=%u, Seq=%u, Ret=%u\n",
+ resp->size, resp->seq_num, resp->result);
+ break;
+ case HostCmd_CMD_MEASUREMENT_REPORT:
+ ret = wlan_meas_cmdresp_get_report(pmpriv, resp);
+ break;
+ default:
+ ret = MLAN_STATUS_FAILURE;
+ }
+
+ LEAVE();
+ return ret;
+}
diff --git a/drivers/net/wireless/nxp/mxm_wifiex/wlan_src/mlan/mlan_meas.h b/drivers/net/wireless/nxp/mxm_wifiex/wlan_src/mlan/mlan_meas.h
new file mode 100644
index 000000000000..c69f41890787
--- /dev/null
+++ b/drivers/net/wireless/nxp/mxm_wifiex/wlan_src/mlan/mlan_meas.h
@@ -0,0 +1,55 @@
+/**
+ * @file mlan_meas.h
+ *
+ * @brief Interface for the measurement module implemented in mlan_meas.c
+ *
+ * Driver interface functions and type declarations for the measurement module
+ * implemented in mlan_meas.c
+ *
+ * @sa mlan_meas.c
+ *
+ *
+ * Copyright 2014-2020 NXP
+ *
+ * This software file (the File) is distributed by NXP
+ * under the terms of the GNU General Public License Version 2, June 1991
+ * (the License). You may use, redistribute and/or modify the 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.
+ *
+ */
+
+/*************************************************************
+Change Log:
+ 03/25/2009: initial version
+************************************************************/
+
+#ifndef _MLAN_MEAS_H_
+#define _MLAN_MEAS_H_
+
+#include "mlan_fw.h"
+
+/* Send a given measurement request to the firmware, report back the result */
+extern int wlan_meas_util_send_req(pmlan_private pmpriv,
+ pHostCmd_DS_MEASUREMENT_REQUEST pmeas_req,
+ t_u32 wait_for_resp_timeout,
+ pmlan_ioctl_req pioctl_req,
+ pHostCmd_DS_MEASUREMENT_REPORT pmeas_rpt);
+
+/* Setup a measurement command before it is sent to the firmware */
+extern int wlan_meas_cmd_process(mlan_private *pmpriv,
+ HostCmd_DS_COMMAND *pcmd_ptr,
+ const t_void *pinfo_buf);
+
+/* Handle a given measurement command response from the firmware */
+extern int wlan_meas_cmdresp_process(mlan_private *pmpriv,
+ const HostCmd_DS_COMMAND *resp);
+
+#endif /* _MLAN_MEAS_H_ */
diff --git a/drivers/net/wireless/nxp/mxm_wifiex/wlan_src/mlan/mlan_misc.c b/drivers/net/wireless/nxp/mxm_wifiex/wlan_src/mlan/mlan_misc.c
new file mode 100644
index 000000000000..a6208fa5e5e9
--- /dev/null
+++ b/drivers/net/wireless/nxp/mxm_wifiex/wlan_src/mlan/mlan_misc.c
@@ -0,0 +1,5866 @@
+/**
+ * @file mlan_misc.c
+ *
+ * @brief This file include miscellaneous functions for MLAN module
+ *
+ *
+ * Copyright 2014-2020 NXP
+ *
+ * This software file (the File) is distributed by NXP
+ * under the terms of the GNU General Public License Version 2, June 1991
+ * (the License). You may use, redistribute and/or modify the 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.
+ *
+ */
+
+/*************************************************************
+Change Log:
+ 05/11/2009: initial version
+************************************************************/
+#include "mlan.h"
+#ifdef STA_SUPPORT
+#include "mlan_join.h"
+#endif /* STA_SUPPORT */
+#include "mlan_util.h"
+#include "mlan_fw.h"
+#include "mlan_main.h"
+#include "mlan_wmm.h"
+#include "mlan_11n.h"
+#include "mlan_11ac.h"
+#include "mlan_11ax.h"
+#ifdef UAP_SUPPORT
+#include "mlan_uap.h"
+#endif
+#ifdef DRV_EMBEDDED_AUTHENTICATOR
+#include "authenticator_api.h"
+#endif
+/********************************************************
+ Local Variables
+********************************************************/
+
+/********************************************************
+ Global Variables
+********************************************************/
+#if defined(STA_SUPPORT) && defined(UAP_SUPPORT)
+extern pmlan_operations mlan_ops[];
+#endif
+extern t_u8 ac_to_tid[4][2];
+
+/********************************************************
+ Local Functions
+********************************************************/
+#if defined(PCIE) || defined(SDIO)
+/**
+ * @brief Check pending irq
+ *
+ * @param pmadapter A pointer to mlan_adapter structure
+ *
+ * @return MTRUE/MFALSE;
+ */
+t_u8 wlan_pending_interrupt(pmlan_adapter pmadapter)
+{
+ if (!IS_USB(pmadapter->card_type) && pmadapter->ireg)
+ return MTRUE;
+ return MFALSE;
+}
+#endif
+
+/** Custom IE auto index and mask */
+#define MLAN_CUSTOM_IE_AUTO_IDX_MASK 0xffff
+/** Custom IE mask for delete operation */
+#define MLAN_CUSTOM_IE_DELETE_MASK 0
+/** Custom IE mask for create new index */
+#define MLAN_CUSTOM_IE_NEW_MASK 0x8000
+/** Custom IE header size */
+#define MLAN_CUSTOM_IE_HDR_SIZE (sizeof(custom_ie) - MAX_IE_SIZE)
+
+/**
+ * @brief Check if current custom IE index is used on other interfaces.
+ *
+ * @param pmpriv A pointer to mlan_private structure
+ * @param idx index to check for in use
+ *
+ * @return MLAN_STATUS_SUCCESS --unused, otherwise used.
+ */
+static mlan_status wlan_is_custom_ie_index_unused(pmlan_private pmpriv,
+ t_u16 idx)
+{
+ t_u8 i = 0;
+ pmlan_adapter pmadapter = pmpriv->adapter;
+ pmlan_private priv;
+ ENTER();
+
+ for (i = 0; i < pmadapter->priv_num; i++) {
+ priv = pmadapter->priv[i];
+ /* Check for other interfaces only */
+ if (priv && priv->bss_index != pmpriv->bss_index) {
+ if (priv->mgmt_ie[idx].mgmt_subtype_mask &&
+ priv->mgmt_ie[idx].ie_length) {
+ /* used entry found */
+ LEAVE();
+ return MLAN_STATUS_FAILURE;
+ }
+ }
+ }
+ LEAVE();
+ return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ * @brief Get the custom IE index
+ *
+ * @param pmpriv A pointer to mlan_private structure
+ * @param pioctl_req A pointer to ioctl request buffer
+ * @param mask mask value for which the index to be returned
+ * @param ie_data a pointer to custom_ie structure
+ * @param idx will hold the computed index
+ *
+ * @return MLAN_STATUS_SUCCESS --success, otherwise fail
+ */
+static mlan_status wlan_custom_ioctl_get_autoidx(pmlan_private pmpriv,
+ pmlan_ioctl_req pioctl_req,
+ t_u16 mask, custom_ie *ie_data,
+ t_u16 *idx)
+{
+ t_u16 index = 0, insert = MFALSE;
+ mlan_status ret = MLAN_STATUS_SUCCESS;
+
+ ENTER();
+ /* Determine the index where the IE needs to be inserted */
+ while (!insert) {
+ while (index < MIN(pmpriv->adapter->max_mgmt_ie_index,
+ MAX_MGMT_IE_INDEX)) {
+ if (pmpriv->mgmt_ie[index].mgmt_subtype_mask ==
+ MLAN_CUSTOM_IE_AUTO_IDX_MASK) {
+ index++;
+ continue;
+ }
+ if (pmpriv->mgmt_ie[index].mgmt_subtype_mask == mask) {
+ /* Duplicate IE should be avoided */
+ if (pmpriv->mgmt_ie[index].ie_length) {
+ if (!memcmp(pmpriv->adapter,
+ pmpriv->mgmt_ie[index]
+ .ie_buffer,
+ ie_data->ie_buffer,
+ pmpriv->mgmt_ie[index]
+ .ie_length)) {
+ PRINTM(MINFO,
+ "IE with the same mask exists at index %d mask=0x%x\n",
+ index, mask);
+ *idx = MLAN_CUSTOM_IE_AUTO_IDX_MASK;
+ goto done;
+ }
+ }
+ /* Check if enough space is available */
+ if (pmpriv->mgmt_ie[index].ie_length +
+ ie_data->ie_length >
+ MAX_IE_SIZE) {
+ index++;
+ continue;
+ }
+ insert = MTRUE;
+ break;
+ }
+ index++;
+ }
+ if (!insert) {
+ for (index = 0;
+ index < MIN(pmpriv->adapter->max_mgmt_ie_index,
+ MAX_MGMT_IE_INDEX);
+ index++) {
+ if (pmpriv->mgmt_ie[index].ie_length == 0) {
+ /*
+ * Check if this index is in use
+ * by other interface If yes,
+ * move ahead to next index
+ */
+ if (MLAN_STATUS_SUCCESS ==
+ wlan_is_custom_ie_index_unused(
+ pmpriv, index)) {
+ insert = MTRUE;
+ break;
+ } else {
+ PRINTM(MINFO,
+ "Skipping IE index %d in use.\n",
+ index);
+ }
+ }
+ }
+ }
+ if (index == pmpriv->adapter->max_mgmt_ie_index && !insert) {
+ PRINTM(MERROR, "Failed to Set the IE buffer\n");
+ if (pioctl_req)
+ pioctl_req->status_code = MLAN_ERROR_IOCTL_FAIL;
+ ret = MLAN_STATUS_FAILURE;
+ goto done;
+ }
+ }
+
+ *idx = index;
+done:
+ LEAVE();
+ return ret;
+}
+
+/**
+ * @brief Delete custom IE
+ *
+ * @param pmpriv A pointer to mlan_private structure
+ * @param pioctl_req A pointer to ioctl request buffer
+ * @param ie_data a pointer to custom_ie structure
+ * @param idx index supplied
+ *
+ * @return MLAN_STATUS_SUCCESS --success, otherwise fail
+ */
+
+static mlan_status wlan_custom_ioctl_auto_delete(pmlan_private pmpriv,
+ pmlan_ioctl_req pioctl_req,
+ custom_ie *ie_data, t_u16 idx)
+{
+ mlan_status ret = MLAN_STATUS_SUCCESS;
+ pmlan_adapter pmadapter = pmpriv->adapter;
+ t_u16 index = 0, insert = MFALSE, del_len;
+ t_u8 del_ie[MAX_IE_SIZE], ie[MAX_IE_SIZE];
+ t_s32 cnt, tmp_len = 0;
+ t_u8 *tmp_ie;
+
+ ENTER();
+ memset(pmpriv->adapter, del_ie, 0, MAX_IE_SIZE);
+ memcpy_ext(pmpriv->adapter, del_ie, ie_data->ie_buffer,
+ ie_data->ie_length, MAX_IE_SIZE);
+ del_len = MIN(MAX_IE_SIZE - 1, ie_data->ie_length);
+
+ if (MLAN_CUSTOM_IE_AUTO_IDX_MASK == idx)
+ ie_data->ie_index = 0;
+
+ for (index = 0;
+ index < MIN(pmadapter->max_mgmt_ie_index, MAX_MGMT_IE_INDEX);
+ index++) {
+ if (MLAN_CUSTOM_IE_AUTO_IDX_MASK != idx &&
+ idx < MAX_MGMT_IE_INDEX)
+ index = idx;
+ tmp_ie = pmpriv->mgmt_ie[index].ie_buffer;
+ tmp_len = pmpriv->mgmt_ie[index].ie_length;
+ cnt = 0;
+ while (tmp_len) {
+ if (!memcmp(pmpriv->adapter, tmp_ie, del_ie, del_len)) {
+ memcpy_ext(pmpriv->adapter, ie,
+ pmpriv->mgmt_ie[index].ie_buffer,
+ cnt, MAX_IE_SIZE);
+ if (pmpriv->mgmt_ie[index].ie_length >
+ (cnt + del_len))
+ memcpy_ext(
+ pmpriv->adapter, &ie[cnt],
+ &pmpriv->mgmt_ie[index].ie_buffer
+ [MIN((MAX_IE_SIZE - 1),
+ (cnt + del_len))],
+ (pmpriv->mgmt_ie[index]
+ .ie_length -
+ (cnt + del_len)),
+ MAX_IE_SIZE - cnt);
+ memset(pmpriv->adapter,
+ &pmpriv->mgmt_ie[index].ie_buffer, 0,
+ sizeof(pmpriv->mgmt_ie[index].ie_buffer));
+ memcpy_ext(pmpriv->adapter,
+ &pmpriv->mgmt_ie[index].ie_buffer,
+ ie,
+ pmpriv->mgmt_ie[index].ie_length -
+ del_len,
+ MAX_IE_SIZE);
+ pmpriv->mgmt_ie[index].ie_length -= del_len;
+ if (MLAN_CUSTOM_IE_AUTO_IDX_MASK == idx)
+ /* set a bit to indicate caller about
+ * update */
+ ie_data->ie_index |=
+ (((t_u16)1) << index);
+ insert = MTRUE;
+ tmp_ie = pmpriv->mgmt_ie[index].ie_buffer;
+ tmp_len = pmpriv->mgmt_ie[index].ie_length;
+ cnt = 0;
+ continue;
+ }
+ tmp_ie++;
+ tmp_len--;
+ cnt++;
+ }
+ if (MLAN_CUSTOM_IE_AUTO_IDX_MASK != idx)
+ break;
+ }
+ if (index == pmadapter->max_mgmt_ie_index && !insert) {
+ PRINTM(MERROR, "Failed to Clear IE buffer\n");
+ if (pioctl_req)
+ pioctl_req->status_code = MLAN_ERROR_IOCTL_FAIL;
+ ret = MLAN_STATUS_FAILURE;
+ }
+ LEAVE();
+ return ret;
+}
+
+/********************************************************
+ Global Functions
+********************************************************/
+
+/**
+ * @brief send host cmd
+ *
+ * @param pmadapter A pointer to mlan_adapter structure
+ * @param pioctl_req A pointer to ioctl request buffer
+ *
+ * @return MLAN_STATUS_PENDING --success, otherwise fail
+ */
+mlan_status wlan_misc_ioctl_host_cmd(pmlan_adapter pmadapter,
+ pmlan_ioctl_req pioctl_req)
+{
+ mlan_status ret = MLAN_STATUS_SUCCESS;
+ mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index];
+ mlan_ds_misc_cfg *misc = MNULL;
+
+ ENTER();
+
+ misc = (mlan_ds_misc_cfg *)pioctl_req->pbuf;
+
+ /* Send request to firmware */
+ ret = wlan_prepare_cmd(pmpriv, 0, 0, 0, (t_void *)pioctl_req,
+ (t_void *)&misc->param.hostcmd);
+ if (ret == MLAN_STATUS_SUCCESS)
+ ret = MLAN_STATUS_PENDING;
+
+ LEAVE();
+ return ret;
+}
+
+/**
+ * @brief Send function init/shutdown command to firmware
+ *
+ * @param pmadapter A pointer to mlan_adapter structure
+ * @param pioctl_req A pointer to ioctl request buffer
+ *
+ * @return MLAN_STATUS_PENDING --success, otherwise fail
+ */
+mlan_status wlan_misc_ioctl_init_shutdown(pmlan_adapter pmadapter,
+ pmlan_ioctl_req pioctl_req)
+{
+ mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index];
+ mlan_status ret = MLAN_STATUS_SUCCESS;
+ mlan_ds_misc_cfg *misc_cfg = MNULL;
+ t_u16 cmd;
+
+ ENTER();
+
+ misc_cfg = (mlan_ds_misc_cfg *)pioctl_req->pbuf;
+ if (misc_cfg->param.func_init_shutdown == MLAN_FUNC_INIT)
+ cmd = HostCmd_CMD_FUNC_INIT;
+ else if (misc_cfg->param.func_init_shutdown == MLAN_FUNC_SHUTDOWN)
+ cmd = HostCmd_CMD_FUNC_SHUTDOWN;
+ else {
+ PRINTM(MERROR, "Unsupported parameter\n");
+ pioctl_req->status_code = MLAN_ERROR_INVALID_PARAMETER;
+ ret = MLAN_STATUS_FAILURE;
+ goto exit;
+ }
+
+ /* Send command to firmware */
+ ret = wlan_prepare_cmd(pmpriv, cmd, HostCmd_ACT_GEN_SET, 0,
+ (t_void *)pioctl_req, MNULL);
+
+ if (ret == MLAN_STATUS_SUCCESS)
+ ret = MLAN_STATUS_PENDING;
+
+exit:
+ LEAVE();
+ return ret;
+}
+
+/**
+ * @brief Get debug information
+ *
+ * @param pmadapter A pointer to mlan_adapter structure
+ * @param pioctl_req A pointer to ioctl request buffer
+ *
+ * @return MLAN_STATUS_SUCCESS --success
+ */
+mlan_status wlan_get_info_debug_info(pmlan_adapter pmadapter,
+ pmlan_ioctl_req pioctl_req)
+{
+ pmlan_private pmpriv = pmadapter->priv[pioctl_req->bss_index];
+ mlan_status ret = MLAN_STATUS_SUCCESS;
+ mlan_ds_get_info *info;
+ mlan_debug_info *debug_info = MNULL;
+ t_u32 i;
+ t_u8 *ptid;
+
+ ENTER();
+
+ info = (mlan_ds_get_info *)pioctl_req->pbuf;
+ debug_info = (mlan_debug_info *)info->param.debug_info;
+
+ if (pioctl_req->action == MLAN_ACT_GET) {
+ ptid = ac_to_tid[WMM_AC_BK];
+ debug_info->wmm_ac_bk = pmpriv->wmm.packets_out[ptid[0]] +
+ pmpriv->wmm.packets_out[ptid[1]];
+ ptid = ac_to_tid[WMM_AC_BE];
+ debug_info->wmm_ac_be = pmpriv->wmm.packets_out[ptid[0]] +
+ pmpriv->wmm.packets_out[ptid[1]];
+ ptid = ac_to_tid[WMM_AC_VI];
+ debug_info->wmm_ac_vi = pmpriv->wmm.packets_out[ptid[0]] +
+ pmpriv->wmm.packets_out[ptid[1]];
+ ptid = ac_to_tid[WMM_AC_VO];
+ debug_info->wmm_ac_vo = pmpriv->wmm.packets_out[ptid[0]] +
+ pmpriv->wmm.packets_out[ptid[1]];
+ debug_info->max_tx_buf_size = (t_u32)pmadapter->max_tx_buf_size;
+ debug_info->tx_buf_size = (t_u32)pmadapter->tx_buf_size;
+ debug_info->curr_tx_buf_size =
+ (t_u32)pmadapter->curr_tx_buf_size;
+ debug_info->rx_tbl_num =
+ wlan_get_rxreorder_tbl(pmpriv, debug_info->rx_tbl);
+ debug_info->tx_tbl_num =
+ wlan_get_txbastream_tbl(pmpriv, debug_info->tx_tbl);
+ debug_info->ralist_num =
+ wlan_get_ralist_info(pmpriv, debug_info->ralist);
+ debug_info->ps_mode = pmadapter->ps_mode;
+ debug_info->ps_state = pmadapter->ps_state;
+#ifdef STA_SUPPORT
+ debug_info->is_deep_sleep = pmadapter->is_deep_sleep;
+#endif /* STA_SUPPORT */
+ debug_info->pm_wakeup_card_req = pmadapter->pm_wakeup_card_req;
+ debug_info->pm_wakeup_fw_try = pmadapter->pm_wakeup_fw_try;
+ debug_info->pm_wakeup_in_secs = pmadapter->pm_wakeup_in_secs;
+ debug_info->pm_wakeup_timeout = pmadapter->pm_wakeup_timeout;
+ debug_info->is_hs_configured = pmadapter->is_hs_configured;
+ debug_info->hs_activated = pmadapter->hs_activated;
+ debug_info->pps_uapsd_mode = pmadapter->pps_uapsd_mode;
+ debug_info->sleep_pd = pmadapter->sleep_period.period;
+ debug_info->qos_cfg = pmpriv->wmm_qosinfo;
+ debug_info->tx_lock_flag = pmadapter->tx_lock_flag;
+ debug_info->port_open = pmpriv->port_open;
+ debug_info->bypass_pkt_count = pmadapter->bypass_pkt_count;
+ debug_info->scan_processing = pmadapter->scan_processing;
+ debug_info->mlan_processing = pmadapter->mlan_processing;
+ debug_info->main_lock_flag = pmadapter->main_lock_flag;
+ debug_info->main_process_cnt = pmadapter->main_process_cnt;
+ debug_info->delay_task_flag = pmadapter->delay_task_flag;
+ debug_info->num_cmd_host_to_card_failure =
+ pmadapter->dbg.num_cmd_host_to_card_failure;
+ debug_info->num_cmd_sleep_cfm_host_to_card_failure =
+ pmadapter->dbg.num_cmd_sleep_cfm_host_to_card_failure;
+ debug_info->num_tx_host_to_card_failure =
+ pmadapter->dbg.num_tx_host_to_card_failure;
+ debug_info->num_alloc_buffer_failure =
+ pmadapter->dbg.num_alloc_buffer_failure;
+ debug_info->num_pkt_dropped = pmadapter->dbg.num_pkt_dropped;
+
+ debug_info->num_event_deauth = pmadapter->dbg.num_event_deauth;
+ debug_info->num_event_disassoc =
+ pmadapter->dbg.num_event_disassoc;
+ debug_info->num_event_link_lost =
+ pmadapter->dbg.num_event_link_lost;
+ debug_info->num_cmd_deauth = pmadapter->dbg.num_cmd_deauth;
+ debug_info->num_cmd_assoc_success =
+ pmadapter->dbg.num_cmd_assoc_success;
+ debug_info->num_cmd_assoc_failure =
+ pmadapter->dbg.num_cmd_assoc_failure;
+ debug_info->num_cmd_timeout = pmadapter->num_cmd_timeout;
+ debug_info->timeout_cmd_id = pmadapter->dbg.timeout_cmd_id;
+ debug_info->timeout_cmd_act = pmadapter->dbg.timeout_cmd_act;
+ memcpy_ext(pmadapter, debug_info->last_cmd_id,
+ pmadapter->dbg.last_cmd_id,
+ sizeof(pmadapter->dbg.last_cmd_id),
+ sizeof(debug_info->last_cmd_id));
+ memcpy_ext(pmadapter, debug_info->last_cmd_act,
+ pmadapter->dbg.last_cmd_act,
+ sizeof(pmadapter->dbg.last_cmd_act),
+ sizeof(debug_info->last_cmd_act));
+ debug_info->last_cmd_index = pmadapter->dbg.last_cmd_index;
+ memcpy_ext(pmadapter, debug_info->last_cmd_resp_id,
+ pmadapter->dbg.last_cmd_resp_id,
+ sizeof(pmadapter->dbg.last_cmd_resp_id),
+ sizeof(debug_info->last_cmd_resp_id));
+ debug_info->last_cmd_resp_index =
+ pmadapter->dbg.last_cmd_resp_index;
+ memcpy_ext(pmadapter, debug_info->last_event,
+ pmadapter->dbg.last_event,
+ sizeof(pmadapter->dbg.last_event),
+ sizeof(debug_info->last_event));
+ debug_info->last_event_index = pmadapter->dbg.last_event_index;
+ debug_info->num_no_cmd_node = pmadapter->dbg.num_no_cmd_node;
+ debug_info->pending_cmd =
+ (pmadapter->curr_cmd) ?
+ pmadapter->dbg.last_cmd_id
+ [pmadapter->dbg.last_cmd_index] :
+ 0;
+ debug_info->dnld_cmd_in_secs = pmadapter->dnld_cmd_in_secs;
+#ifdef SDIO
+ if (IS_SD(pmadapter->card_type)) {
+ debug_info->num_cmdevt_card_to_host_failure =
+ pmadapter->dbg.num_cmdevt_card_to_host_failure;
+ debug_info->num_rx_card_to_host_failure =
+ pmadapter->dbg.num_rx_card_to_host_failure;
+ debug_info->num_int_read_failure =
+ pmadapter->dbg.num_int_read_failure;
+ debug_info->last_int_status =
+ pmadapter->dbg.last_int_status;
+ debug_info->mp_rd_bitmap =
+ pmadapter->pcard_sd->mp_rd_bitmap;
+ debug_info->mp_wr_bitmap =
+ pmadapter->pcard_sd->mp_wr_bitmap;
+ debug_info->curr_rd_port =
+ pmadapter->pcard_sd->curr_rd_port;
+ debug_info->curr_wr_port =
+ pmadapter->pcard_sd->curr_wr_port;
+ debug_info->mp_invalid_update =
+ pmadapter->pcard_sd->mp_invalid_update;
+ debug_info->num_of_irq =
+ pmadapter->pcard_sd->num_of_irq;
+ memcpy_ext(pmadapter, debug_info->mp_update,
+ pmadapter->pcard_sd->mp_update,
+ sizeof(pmadapter->pcard_sd->mp_update),
+ sizeof(debug_info->mp_update));
+ memcpy_ext(pmadapter, debug_info->mpa_tx_count,
+ pmadapter->pcard_sd->mpa_tx_count,
+ sizeof(pmadapter->pcard_sd->mpa_tx_count),
+ sizeof(debug_info->mpa_tx_count));
+ debug_info->mpa_sent_last_pkt =
+ pmadapter->pcard_sd->mpa_sent_last_pkt;
+ debug_info->mpa_sent_no_ports =
+ pmadapter->pcard_sd->mpa_sent_no_ports;
+ debug_info->last_recv_wr_bitmap =
+ pmadapter->pcard_sd->last_recv_wr_bitmap;
+ debug_info->last_mp_index =
+ pmadapter->pcard_sd->last_mp_index;
+ memcpy_ext(
+ pmadapter, debug_info->last_mp_wr_bitmap,
+ pmadapter->pcard_sd->last_mp_wr_bitmap,
+ sizeof(pmadapter->pcard_sd->last_mp_wr_bitmap),
+ sizeof(debug_info->last_mp_wr_bitmap));
+ memcpy_ext(
+ pmadapter, debug_info->last_mp_wr_ports,
+ pmadapter->pcard_sd->last_mp_wr_ports,
+ sizeof(pmadapter->pcard_sd->last_mp_wr_ports),
+ sizeof(debug_info->last_mp_wr_ports));
+ memcpy_ext(pmadapter, debug_info->last_mp_wr_len,
+ pmadapter->pcard_sd->last_mp_wr_len,
+ sizeof(pmadapter->pcard_sd->last_mp_wr_len),
+ sizeof(debug_info->last_mp_wr_len));
+ memcpy_ext(pmadapter, debug_info->last_mp_wr_info,
+ pmadapter->pcard_sd->last_mp_wr_info,
+ sizeof(pmadapter->pcard_sd->last_mp_wr_info),
+ sizeof(debug_info->last_mp_wr_info));
+ memcpy_ext(
+ pmadapter, debug_info->last_curr_wr_port,
+ pmadapter->pcard_sd->last_curr_wr_port,
+ sizeof(pmadapter->pcard_sd->last_curr_wr_port),
+ sizeof(debug_info->last_curr_wr_port));
+ debug_info->mpa_buf = pmadapter->pcard_sd->mpa_buf;
+ debug_info->mpa_buf_size =
+ pmadapter->pcard_sd->mpa_buf_size;
+ debug_info->sdio_rx_aggr =
+ pmadapter->pcard_sd->sdio_rx_aggr_enable;
+ memcpy_ext(pmadapter, debug_info->mpa_rx_count,
+ pmadapter->pcard_sd->mpa_rx_count,
+ sizeof(pmadapter->pcard_sd->mpa_rx_count),
+ sizeof(debug_info->mpa_rx_count));
+ debug_info->mp_aggr_pkt_limit =
+ SDIO_MP_AGGR_DEF_PKT_LIMIT;
+ }
+#endif
+#ifdef PCIE
+ if (IS_PCIE(pmadapter->card_type)) {
+ debug_info->txbd_rdptr =
+ pmadapter->pcard_pcie->txbd_rdptr;
+ debug_info->txbd_wrptr =
+ pmadapter->pcard_pcie->txbd_wrptr;
+ debug_info->rxbd_rdptr =
+ pmadapter->pcard_pcie->rxbd_rdptr;
+ debug_info->rxbd_wrptr =
+ pmadapter->pcard_pcie->rxbd_wrptr;
+ debug_info->eventbd_rdptr =
+ pmadapter->pcard_pcie->evtbd_rdptr;
+ debug_info->eventbd_wrptr =
+ pmadapter->pcard_pcie->evtbd_wrptr;
+ debug_info->txbd_ring_vbase =
+ pmadapter->pcard_pcie->txbd_ring_vbase;
+ debug_info->txbd_ring_size =
+ pmadapter->pcard_pcie->txbd_ring_size;
+ debug_info->rxbd_ring_vbase =
+ pmadapter->pcard_pcie->rxbd_ring_vbase;
+ debug_info->rxbd_ring_size =
+ pmadapter->pcard_pcie->rxbd_ring_size;
+ debug_info->evtbd_ring_vbase =
+ pmadapter->pcard_pcie->evtbd_ring_vbase;
+ debug_info->evtbd_ring_size =
+ pmadapter->pcard_pcie->evtbd_ring_size;
+ memcpy_ext(
+ pmadapter, debug_info->last_tx_pkt_size,
+ pmadapter->pcard_pcie->last_tx_pkt_size,
+ sizeof(pmadapter->pcard_pcie->last_tx_pkt_size),
+ sizeof(debug_info->last_tx_pkt_size));
+ }
+#endif
+ debug_info->data_sent = pmadapter->data_sent;
+ debug_info->cmd_sent = pmadapter->cmd_sent;
+ debug_info->cmd_resp_received = pmadapter->cmd_resp_received;
+ debug_info->tx_pkts_queued =
+ util_scalar_read(pmadapter->pmoal_handle,
+ &pmpriv->wmm.tx_pkts_queued, MNULL,
+ MNULL);
+#ifdef UAP_SUPPORT
+ debug_info->num_bridge_pkts =
+ util_scalar_read(pmadapter->pmoal_handle,
+ &pmadapter->pending_bridge_pkts,
+ pmadapter->callbacks.moal_spin_lock,
+ pmadapter->callbacks.moal_spin_unlock);
+ debug_info->num_drop_pkts = pmpriv->num_drop_pkts;
+#endif
+ debug_info->fw_hang_report = pmadapter->fw_hang_report;
+ debug_info->mlan_processing = pmadapter->mlan_processing;
+ debug_info->mlan_rx_processing = pmadapter->mlan_rx_processing;
+ debug_info->rx_pkts_queued = pmadapter->rx_pkts_queued;
+ debug_info->mlan_adapter = pmadapter;
+ debug_info->mlan_adapter_size = sizeof(mlan_adapter);
+ debug_info->mlan_priv_num = pmadapter->priv_num;
+ for (i = 0; i < pmadapter->priv_num; i++) {
+ debug_info->mlan_priv[i] = pmadapter->priv[i];
+ debug_info->mlan_priv_size[i] = sizeof(mlan_private);
+ }
+ }
+
+ pioctl_req->data_read_written =
+ sizeof(mlan_debug_info) + MLAN_SUB_COMMAND_SIZE;
+
+ LEAVE();
+ return ret;
+}
+
+/**
+ * @brief Set/Get the MAC control configuration.
+ *
+ * @param pmadapter A pointer to mlan_adapter structure
+ * @param pioctl_req A pointer to ioctl request buffer
+ *
+ * @return MLAN_STATUS_PENDING -- success, otherwise fail
+ */
+mlan_status wlan_misc_ioctl_mac_control(pmlan_adapter pmadapter,
+ pmlan_ioctl_req pioctl_req)
+{
+ mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index];
+ mlan_ds_misc_cfg *misc = (mlan_ds_misc_cfg *)pioctl_req->pbuf;
+ mlan_status ret = MLAN_STATUS_SUCCESS;
+ t_u16 cmd_action = 0;
+
+ ENTER();
+
+ misc = (mlan_ds_misc_cfg *)pioctl_req->pbuf;
+
+ if (pioctl_req->action == MLAN_ACT_GET) {
+ misc->param.mac_ctrl = pmpriv->curr_pkt_filter;
+ } else {
+ pmpriv->curr_pkt_filter = misc->param.mac_ctrl;
+ cmd_action = HostCmd_ACT_GEN_SET;
+
+ /* Send command to firmware */
+ ret = wlan_prepare_cmd(pmpriv, HostCmd_CMD_MAC_CONTROL,
+ cmd_action, 0, (t_void *)pioctl_req,
+ &misc->param.mac_ctrl);
+
+ if (ret == MLAN_STATUS_SUCCESS)
+ ret = MLAN_STATUS_PENDING;
+ }
+
+ LEAVE();
+ return ret;
+}
+
+/**
+ * @brief This timer function handles wakeup card timeout.
+ *
+ * @param function_context A pointer to function_context
+ * @return N/A
+ */
+t_void wlan_wakeup_card_timeout_func(void *function_context)
+{
+ pmlan_adapter pmadapter = (pmlan_adapter)function_context;
+
+ ENTER();
+
+ PRINTM(MERROR, "%s: ps_state=%d\n", __FUNCTION__, pmadapter->ps_state);
+ if (pmadapter->ps_state != PS_STATE_AWAKE) {
+ PRINTM(MERROR, "Wakeup card timeout!\n");
+ pmadapter->pm_wakeup_timeout++;
+ wlan_recv_event(wlan_get_priv(pmadapter, MLAN_BSS_ROLE_ANY),
+ MLAN_EVENT_ID_DRV_DBG_DUMP, MNULL);
+ }
+ pmadapter->wakeup_fw_timer_is_set = MFALSE;
+
+ LEAVE();
+}
+
+/**
+ * @brief Set/Get HS configuration
+ *
+ * @param pmadapter A pointer to mlan_adapter structure
+ * @param pioctl_req A pointer to ioctl request buffer
+ *
+ * @return MLAN_STATUS_SUCCESS/MLAN_STATUS_PENDING --success,
+ * otherwise fail
+ */
+mlan_status wlan_pm_ioctl_hscfg(pmlan_adapter pmadapter,
+ pmlan_ioctl_req pioctl_req)
+{
+ mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index];
+ mlan_ds_pm_cfg *pm = MNULL;
+ mlan_status status = MLAN_STATUS_SUCCESS;
+ t_u32 prev_cond = 0;
+
+ ENTER();
+
+ pm = (mlan_ds_pm_cfg *)pioctl_req->pbuf;
+
+ switch (pioctl_req->action) {
+ case MLAN_ACT_SET:
+#ifdef STA_SUPPORT
+ if (pmadapter->pps_uapsd_mode) {
+ PRINTM(MINFO,
+ "Host Sleep IOCTL is blocked in UAPSD/PPS mode\n");
+ pioctl_req->status_code = MLAN_ERROR_IOCTL_INVALID;
+ status = MLAN_STATUS_FAILURE;
+ break;
+ }
+#endif /* STA_SUPPORT */
+ if (pm->param.hs_cfg.is_invoke_hostcmd == MTRUE) {
+ if (pm->param.hs_cfg.conditions ==
+ HOST_SLEEP_CFG_CANCEL) {
+ if (pmadapter->is_hs_configured == MFALSE) {
+ /* Already cancelled */
+ break;
+ }
+ /* Save previous condition */
+ prev_cond = pmadapter->hs_cfg.conditions;
+ pmadapter->hs_cfg.conditions =
+ pm->param.hs_cfg.conditions;
+ } else if (pmadapter->hs_cfg.conditions ==
+ HOST_SLEEP_CFG_CANCEL) {
+ /* Return failure if no parameters for HS enable
+ */
+ pioctl_req->status_code =
+ MLAN_ERROR_INVALID_PARAMETER;
+ status = MLAN_STATUS_FAILURE;
+ break;
+ }
+ status = wlan_prepare_cmd(
+ pmpriv, HostCmd_CMD_802_11_HS_CFG_ENH,
+ HostCmd_ACT_GEN_SET, 0, (t_void *)pioctl_req,
+ (t_void *)(&pmadapter->hs_cfg));
+ if (status == MLAN_STATUS_SUCCESS)
+ status = MLAN_STATUS_PENDING;
+ if (pm->param.hs_cfg.conditions ==
+ HOST_SLEEP_CFG_CANCEL) {
+ /* Restore previous condition */
+ pmadapter->hs_cfg.conditions = prev_cond;
+ }
+ } else {
+ pmadapter->hs_cfg.conditions =
+ pm->param.hs_cfg.conditions;
+ pmadapter->hs_cfg.gpio = (t_u8)pm->param.hs_cfg.gpio;
+ pmadapter->hs_cfg.gap = (t_u8)pm->param.hs_cfg.gap;
+ pmadapter->param_type_ind =
+ (t_u8)pm->param.hs_cfg.param_type_ind;
+ pmadapter->ind_gpio = (t_u8)pm->param.hs_cfg.ind_gpio;
+ pmadapter->level = (t_u8)pm->param.hs_cfg.level;
+ pmadapter->param_type_ext =
+ (t_u8)pm->param.hs_cfg.param_type_ext;
+ pmadapter->event_force_ignore =
+ pm->param.hs_cfg.event_force_ignore;
+ pmadapter->event_use_ext_gap =
+ pm->param.hs_cfg.event_use_ext_gap;
+ pmadapter->ext_gap = pm->param.hs_cfg.ext_gap;
+ pmadapter->gpio_wave = pm->param.hs_cfg.gpio_wave;
+ pmadapter->hs_wake_interval =
+ pm->param.hs_cfg.hs_wake_interval;
+ }
+ break;
+ case MLAN_ACT_GET:
+ pm->param.hs_cfg.conditions = pmadapter->hs_cfg.conditions;
+ pm->param.hs_cfg.gpio = pmadapter->hs_cfg.gpio;
+ pm->param.hs_cfg.gap = pmadapter->hs_cfg.gap;
+ pm->param.hs_cfg.param_type_ind = pmadapter->param_type_ind;
+ pm->param.hs_cfg.ind_gpio = pmadapter->ind_gpio;
+ pm->param.hs_cfg.level = pmadapter->level;
+ pm->param.hs_cfg.param_type_ext = pmadapter->param_type_ext;
+ pm->param.hs_cfg.event_force_ignore =
+ pmadapter->event_force_ignore;
+ pm->param.hs_cfg.event_use_ext_gap =
+ pmadapter->event_use_ext_gap;
+ pm->param.hs_cfg.ext_gap = pmadapter->ext_gap;
+ pm->param.hs_cfg.gpio_wave = pmadapter->gpio_wave;
+ pm->param.hs_cfg.hs_wake_interval = pmadapter->hs_wake_interval;
+ break;
+ default:
+ pioctl_req->status_code = MLAN_ERROR_IOCTL_INVALID;
+ status = MLAN_STATUS_FAILURE;
+ break;
+ }
+
+ LEAVE();
+ return status;
+}
+
+/**
+ * @brief Set Robustcoex gpiocfg
+ *
+ * @param pmadapter A pointer to mlan_adapter structure
+ * @param pioctl_req A pointer to ioctl request buffer
+ *
+ * @return MLAN_STATUS_SUCCESS/MLAN_STATUS_PENDING --success,
+ * otherwise fail
+ */
+mlan_status wlan_misc_robustcoex(pmlan_adapter pmadapter,
+ pmlan_ioctl_req pioctl_req)
+{
+ mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index];
+ mlan_status ret = MLAN_STATUS_SUCCESS;
+ t_u16 cmd_action;
+ mlan_ds_misc_cfg *robust_coex_cfg =
+ (mlan_ds_misc_cfg *)pioctl_req->pbuf;
+
+ ENTER();
+
+ if (pioctl_req->action == MLAN_ACT_SET)
+ cmd_action = HostCmd_ACT_GEN_SET;
+ else
+ cmd_action = HostCmd_ACT_GEN_GET;
+
+ ret = wlan_prepare_cmd(pmpriv, HostCmd_CMD_802_11_ROBUSTCOEX,
+ cmd_action, 0, (t_void *)pioctl_req,
+ &robust_coex_cfg->param.robustcoexparams);
+
+ if (ret == MLAN_STATUS_SUCCESS)
+ ret = MLAN_STATUS_PENDING;
+ LEAVE();
+ return ret;
+}
+
+/**
+ * @brief Set/get DMCS config
+ *
+ * @param pmadapter A pointer to mlan_adapter structure
+ * @param pioctl_req A pointer to ioctl request buffer
+ *
+ * @return MLAN_STATUS_SUCCESS/MLAN_STATUS_PENDING --success, otherwise fail
+ */
+mlan_status wlan_misc_dmcs_config(pmlan_adapter pmadapter,
+ pmlan_ioctl_req pioctl_req)
+{
+ mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index];
+ mlan_status ret = MLAN_STATUS_SUCCESS;
+ t_u16 cmd_action;
+ mlan_ds_misc_cfg *dmcs_cfg = (mlan_ds_misc_cfg *)pioctl_req->pbuf;
+
+ ENTER();
+
+ if (pioctl_req->action == MLAN_ACT_SET)
+ cmd_action = HostCmd_ACT_GEN_SET;
+ else
+ cmd_action = HostCmd_ACT_GEN_GET;
+
+ ret = wlan_prepare_cmd(pmpriv, HostCmd_CMD_DMCS_CONFIG, cmd_action, 0,
+ (t_void *)pioctl_req,
+ &dmcs_cfg->param.dmcs_policy);
+
+ if (ret == MLAN_STATUS_SUCCESS)
+ ret = MLAN_STATUS_PENDING;
+ LEAVE();
+ return ret;
+}
+
+#if defined(PCIE)
+/**
+ * @brief Enable SSU support
+ *
+ * @param pmadapter A pointer to mlan_adapter structure
+ * @param pioctl_req A pointer to ioctl request buffer
+ *
+ * @return MLAN_STATUS_SUCCESS/MLAN_STATUS_PENDING --success,
+ * otherwise fail
+ */
+mlan_status wlan_misc_ssu(pmlan_adapter pmadapter, pmlan_ioctl_req pioctl_req)
+{
+ mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index];
+ mlan_status ret = MLAN_STATUS_SUCCESS;
+ t_u16 cmd_action = HostCmd_ACT_GEN_GET;
+ mlan_ds_misc_cfg *ssu_cfg = (mlan_ds_misc_cfg *)pioctl_req->pbuf;
+
+ ENTER();
+
+ if (pioctl_req->action == MLAN_ACT_SET)
+ cmd_action = HostCmd_ACT_GEN_SET;
+ else if (pioctl_req->action == MLAN_ACT_DEFAULT)
+ cmd_action = HostCmd_ACT_GEN_SET_DEFAULT;
+ else if (pioctl_req->action == MLAN_ACT_GET)
+ cmd_action = HostCmd_ACT_GEN_GET;
+
+ ret = wlan_prepare_cmd(pmpriv, HostCmd_CMD_SSU, cmd_action, 0,
+ (t_void *)pioctl_req,
+ &ssu_cfg->param.ssu_params);
+
+ if (ret == MLAN_STATUS_SUCCESS)
+ ret = MLAN_STATUS_PENDING;
+ LEAVE();
+ return ret;
+}
+#endif
+
+/**
+ * @brief This function allocates a mlan_buffer.
+ *
+ * @param pmadapter Pointer to mlan_adapter
+ * @param data_len Data length
+ * @param head_room head_room reserved in mlan_buffer
+ * @param malloc_flag flag to user moal_malloc
+ * @return mlan_buffer pointer or MNULL
+ */
+pmlan_buffer wlan_alloc_mlan_buffer(mlan_adapter *pmadapter, t_u32 data_len,
+ t_u32 head_room, t_u32 malloc_flag)
+{
+ mlan_status ret = MLAN_STATUS_SUCCESS;
+ pmlan_buffer pmbuf = MNULL;
+ t_u32 buf_size = 0;
+ t_u8 *tmp_buf = MNULL;
+ pmlan_callbacks pcb = &pmadapter->callbacks;
+
+ ENTER();
+
+#ifdef SDIO
+ /* make sure that the data length is at least SDIO block size */
+ if (IS_SD(pmadapter->card_type))
+ data_len = (data_len + MLAN_SDIO_BLOCK_SIZE - 1) /
+ MLAN_SDIO_BLOCK_SIZE * MLAN_SDIO_BLOCK_SIZE;
+#endif
+
+ /* head_room is not implemented for malloc mlan buffer */
+
+ switch (malloc_flag) {
+ case MOAL_MALLOC_BUFFER:
+ buf_size = sizeof(mlan_buffer) + data_len + DMA_ALIGNMENT;
+ ret = pcb->moal_malloc(pmadapter->pmoal_handle, buf_size,
+ MLAN_MEM_DEF | MLAN_MEM_DMA,
+ (t_u8 **)&pmbuf);
+ if ((ret != MLAN_STATUS_SUCCESS) || !pmbuf) {
+ pmbuf = MNULL;
+ goto exit;
+ }
+ memset(pmadapter, pmbuf, 0, sizeof(mlan_buffer));
+
+ pmbuf->pdesc = MNULL;
+ /* Align address */
+ pmbuf->pbuf = (t_u8 *)ALIGN_ADDR(
+ (t_u8 *)pmbuf + sizeof(mlan_buffer), DMA_ALIGNMENT);
+ pmbuf->data_offset = 0;
+ pmbuf->data_len = data_len;
+ pmbuf->flags |= MLAN_BUF_FLAG_MALLOC_BUF;
+ break;
+
+ case MOAL_ALLOC_MLAN_BUFFER:
+ /* use moal_alloc_mlan_buffer, head_room supported */
+ ret = pcb->moal_alloc_mlan_buffer(
+ pmadapter->pmoal_handle,
+ data_len + DMA_ALIGNMENT + head_room, &pmbuf);
+ if ((ret != MLAN_STATUS_SUCCESS) || !pmbuf) {
+ PRINTM(MERROR, "Failed to allocate 'mlan_buffer'\n");
+ goto exit;
+ }
+ pmbuf->data_offset = head_room;
+ tmp_buf = (t_u8 *)ALIGN_ADDR(pmbuf->pbuf + pmbuf->data_offset,
+ DMA_ALIGNMENT);
+ pmbuf->data_offset +=
+ (t_u32)(tmp_buf - (pmbuf->pbuf + pmbuf->data_offset));
+ pmbuf->data_len = data_len;
+ pmbuf->flags = 0;
+ break;
+ }
+
+exit:
+ LEAVE();
+ return pmbuf;
+}
+
+/**
+ * @brief This function frees a mlan_buffer.
+ *
+ * @param pmadapter Pointer to mlan_adapter
+ * @param pmbuf Pointer to mlan_buffer
+ *
+ * @return N/A
+ */
+t_void wlan_free_mlan_buffer(mlan_adapter *pmadapter, pmlan_buffer pmbuf)
+{
+ pmlan_callbacks pcb = &pmadapter->callbacks;
+ ENTER();
+
+ if (pcb && pmbuf) {
+ if (pmbuf->flags & MLAN_BUF_FLAG_BRIDGE_BUF)
+ util_scalar_decrement(
+ pmadapter->pmoal_handle,
+ &pmadapter->pending_bridge_pkts,
+ pmadapter->callbacks.moal_spin_lock,
+ pmadapter->callbacks.moal_spin_unlock);
+ if (pmbuf->flags & MLAN_BUF_FLAG_MALLOC_BUF)
+ pcb->moal_mfree(pmadapter->pmoal_handle, (t_u8 *)pmbuf);
+ else
+ pcb->moal_free_mlan_buffer(pmadapter->pmoal_handle,
+ pmbuf);
+ }
+
+ LEAVE();
+ return;
+}
+
+/**
+ * @brief Delay function implementation
+ *
+ * @param pmadapter A pointer to mlan_adapter structure
+ * @param delay Delay value
+ * @param u Units of delay (sec, msec or usec)
+ *
+ * @return N/A
+ */
+t_void wlan_delay_func(mlan_adapter *pmadapter, t_u32 delay, t_delay_unit u)
+{
+ t_u32 now_tv_sec, now_tv_usec;
+ t_u32 upto_tv_sec, upto_tv_usec;
+ pmlan_callbacks pcb = &pmadapter->callbacks;
+
+ ENTER();
+
+ if (pcb->moal_udelay) {
+ if (u == SEC)
+ delay *= 1000000;
+ else if (u == MSEC)
+ delay *= 1000;
+ pcb->moal_udelay(pmadapter->pmoal_handle, delay);
+ } else {
+ pcb->moal_get_system_time(pmadapter->pmoal_handle, &upto_tv_sec,
+ &upto_tv_usec);
+
+ switch (u) {
+ case SEC:
+ upto_tv_sec += delay;
+ break;
+ case MSEC:
+ delay *= 1000;
+ /* fall through */
+ case USEC:
+ upto_tv_sec += (delay / 1000000);
+ upto_tv_usec += (delay % 1000000);
+ break;
+ }
+
+ do {
+ pcb->moal_get_system_time(pmadapter->pmoal_handle,
+ &now_tv_sec, &now_tv_usec);
+ if (now_tv_sec > upto_tv_sec) {
+ LEAVE();
+ return;
+ }
+
+ if ((now_tv_sec == upto_tv_sec) &&
+ (now_tv_usec >= upto_tv_usec)) {
+ LEAVE();
+ return;
+ }
+ } while (MTRUE);
+ }
+
+ LEAVE();
+ return;
+}
+
+/**
+ * @brief BSS remove
+ *
+ * @param pmadapter A pointer to mlan_adapter structure
+ * @param pioctl_req A pointer to ioctl request buffer
+ *
+ * @return MLAN_STATUS_PENDING --success, MLAN_STATUS_FAILURE
+ */
+mlan_status wlan_bss_ioctl_bss_remove(pmlan_adapter pmadapter,
+ pmlan_ioctl_req pioctl_req)
+{
+ ENTER();
+ wlan_cancel_bss_pending_cmd(pmadapter, pioctl_req->bss_index);
+ LEAVE();
+ return MLAN_STATUS_SUCCESS;
+}
+
+#if defined(STA_SUPPORT) && defined(UAP_SUPPORT)
+/**
+ * @brief Set/Get BSS role
+ *
+ * @param pmadapter A pointer to mlan_adapter structure
+ * @param pioctl_req A pointer to ioctl request buffer
+ *
+ * @return MLAN_STATUS_PENDING --success, MLAN_STATUS_FAILURE
+ */
+mlan_status wlan_bss_ioctl_bss_role(pmlan_adapter pmadapter,
+ pmlan_ioctl_req pioctl_req)
+{
+ mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index];
+ mlan_ds_bss *bss = MNULL;
+ mlan_status ret = MLAN_STATUS_SUCCESS;
+ HostCmd_DS_VERSION_EXT dummy;
+#ifdef USB
+ pmlan_callbacks pcb = &pmadapter->callbacks;
+ pmlan_buffer pmbuf;
+#endif
+#if defined(WIFI_DIRECT_SUPPORT)
+ t_u8 bss_mode;
+#endif
+ t_u8 i, global_band = 0;
+ int j;
+
+ ENTER();
+
+ bss = (mlan_ds_bss *)pioctl_req->pbuf;
+ if (pioctl_req->action == MLAN_ACT_GET) {
+ bss->param.bss_role = GET_BSS_ROLE(pmpriv);
+ } else {
+ if (GET_BSS_ROLE(pmpriv) == bss->param.bss_role) {
+ PRINTM(MIOCTL, "BSS ie already in the desired role!\n");
+ goto done;
+ }
+ mlan_block_rx_process(pmadapter, MTRUE);
+ /** Switch BSS role */
+ wlan_free_priv(pmpriv);
+
+#ifdef USB
+ if (IS_USB(pmadapter->card_type)) {
+ while ((pmbuf = (pmlan_buffer)util_dequeue_list(
+ pmadapter->pmoal_handle,
+ &pmadapter->rx_data_queue,
+ pcb->moal_spin_lock,
+ pcb->moal_spin_unlock))) {
+ pcb->moal_recv_complete(pmadapter->pmoal_handle,
+ pmbuf,
+ pmadapter->rx_data_ep,
+ MLAN_STATUS_FAILURE);
+ }
+ }
+#endif
+ pmpriv->bss_role = bss->param.bss_role;
+ if (pmpriv->bss_type == MLAN_BSS_TYPE_UAP)
+ pmpriv->bss_type = MLAN_BSS_TYPE_STA;
+ else if (pmpriv->bss_type == MLAN_BSS_TYPE_STA)
+ pmpriv->bss_type = MLAN_BSS_TYPE_UAP;
+ /* Initialize private structures */
+ wlan_init_priv(pmpriv);
+ mlan_block_rx_process(pmadapter, MFALSE);
+ /* Initialize function table */
+ for (j = 0; mlan_ops[j]; j++) {
+ if (mlan_ops[j]->bss_role == GET_BSS_ROLE(pmpriv)) {
+ memcpy_ext(pmadapter, &pmpriv->ops, mlan_ops[j],
+ sizeof(mlan_operations),
+ sizeof(mlan_operations));
+ }
+ }
+
+ for (i = 0; i < pmadapter->priv_num; i++) {
+ if (pmadapter->priv[i] &&
+ GET_BSS_ROLE(pmadapter->priv[i]) ==
+ MLAN_BSS_ROLE_STA)
+ global_band |= pmadapter->priv[i]->config_bands;
+ }
+
+ if (global_band != pmadapter->config_bands) {
+ if (wlan_set_regiontable(
+ pmpriv, (t_u8)pmadapter->region_code,
+ global_band |
+ pmadapter->adhoc_start_band)) {
+ pioctl_req->status_code = MLAN_ERROR_IOCTL_FAIL;
+ LEAVE();
+ return MLAN_STATUS_FAILURE;
+ }
+
+ if (wlan_11d_set_universaltable(
+ pmpriv,
+ global_band |
+ pmadapter->adhoc_start_band)) {
+ pioctl_req->status_code = MLAN_ERROR_IOCTL_FAIL;
+ LEAVE();
+ return MLAN_STATUS_FAILURE;
+ }
+ pmadapter->config_bands = global_band;
+ }
+
+ /* Issue commands to initialize firmware */
+#if defined(WIFI_DIRECT_SUPPORT)
+ if (GET_BSS_ROLE(pmpriv) == MLAN_BSS_ROLE_STA)
+ bss_mode = BSS_MODE_WIFIDIRECT_CLIENT;
+ else
+ bss_mode = BSS_MODE_WIFIDIRECT_GO;
+ ret = wlan_prepare_cmd(pmpriv, HostCmd_CMD_SET_BSS_MODE,
+ HostCmd_ACT_GEN_SET, 0, MNULL,
+ &bss_mode);
+ if (ret)
+ goto done;
+#endif
+ ret = pmpriv->ops.init_cmd(pmpriv, MFALSE);
+ if (ret == MLAN_STATUS_FAILURE)
+ goto done;
+
+ /* Issue dummy Get command to complete the ioctl */
+ memset(pmadapter, &dummy, 0, sizeof(HostCmd_DS_VERSION_EXT));
+ ret = wlan_prepare_cmd(pmpriv, HostCmd_CMD_VERSION_EXT,
+ HostCmd_ACT_GEN_GET, 0,
+ (t_void *)pioctl_req, (t_void *)&dummy);
+ if (ret == MLAN_STATUS_SUCCESS)
+ ret = MLAN_STATUS_PENDING;
+ }
+
+done:
+ LEAVE();
+ return ret;
+}
+#endif
+
+/**
+ * @brief Set the custom IE
+ *
+ * @param pmadapter A pointer to mlan_adapter structure
+ * @param pioctl_req A pointer to ioctl request buffer
+ * @param send_ioctl Flag to indicate if ioctl should be sent with cmd
+ * (MTRUE if from moal/user, MFALSE if internal)
+ *
+ * @return MLAN_STATUS_PENDING --success, otherwise fail
+ */
+mlan_status wlan_misc_ioctl_custom_ie_list(pmlan_adapter pmadapter,
+ pmlan_ioctl_req pioctl_req,
+ t_bool send_ioctl)
+{
+ mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index];
+ mlan_status ret = MLAN_STATUS_SUCCESS;
+ mlan_ds_misc_cfg *misc = (mlan_ds_misc_cfg *)pioctl_req->pbuf;
+ custom_ie *ie_data = MNULL;
+ t_u16 cmd_action = 0, index, mask, i, len, app_data_len;
+ t_s32 ioctl_len;
+ t_u8 *tmp_ie;
+
+ ENTER();
+
+ if ((misc->param.cust_ie.len == 0) ||
+ (misc->param.cust_ie.len == sizeof(t_u16))) {
+ pioctl_req->action = MLAN_ACT_GET;
+ /* Get the IE */
+ cmd_action = HostCmd_ACT_GEN_GET;
+ } else {
+ /* ioctl_len : ioctl length from application, start with
+ * misc->param.cust_ie.len and reach upto 0 */
+ ioctl_len = misc->param.cust_ie.len;
+
+ /* app_data_len : length from application, start with 0
+ * and reach upto ioctl_len */
+ app_data_len = sizeof(MrvlIEtypesHeader_t);
+ misc->param.cust_ie.len = 0;
+
+ while (ioctl_len > 0) {
+ ie_data = (custom_ie *)(((t_u8 *)&misc->param.cust_ie) +
+ app_data_len);
+ ioctl_len -=
+ (ie_data->ie_length + MLAN_CUSTOM_IE_HDR_SIZE);
+ app_data_len +=
+ (ie_data->ie_length + MLAN_CUSTOM_IE_HDR_SIZE);
+
+ index = ie_data->ie_index;
+ mask = ie_data->mgmt_subtype_mask;
+
+ /* Need to be Autohandled */
+ if (MLAN_CUSTOM_IE_AUTO_IDX_MASK == index) {
+ /* Automatic Deletion */
+ if (mask == MLAN_CUSTOM_IE_DELETE_MASK) {
+ ret = wlan_custom_ioctl_auto_delete(
+ pmpriv, pioctl_req, ie_data,
+ index);
+ /* if IE to delete is not found, return
+ * error */
+ if (ret == MLAN_STATUS_FAILURE)
+ goto done;
+ index = ie_data->ie_index;
+ memset(pmadapter, ie_data, 0,
+ sizeof(custom_ie) *
+ MAX_MGMT_IE_INDEX_TO_FW);
+ len = 0;
+ for (i = 0;
+ i < pmadapter->max_mgmt_ie_index;
+ i++) {
+ /* Check if index is updated
+ * before sending to FW */
+ if (index & ((t_u16)1) << i) {
+ memcpy_ext(
+ pmadapter,
+ (t_u8 *)ie_data +
+ len,
+ &i,
+ sizeof(ie_data->ie_index),
+ sizeof(ie_data->ie_index));
+ len += sizeof(
+ ie_data->ie_index);
+ memcpy_ext(
+ pmadapter,
+ (t_u8 *)ie_data +
+ len,
+ &pmpriv->mgmt_ie[i]
+ .mgmt_subtype_mask,
+ sizeof(ie_data->mgmt_subtype_mask),
+ sizeof(ie_data->mgmt_subtype_mask));
+ len += sizeof(
+ ie_data->mgmt_subtype_mask);
+ memcpy_ext(
+ pmadapter,
+ (t_u8 *)ie_data +
+ len,
+ &pmpriv->mgmt_ie[i]
+ .ie_length,
+ sizeof(ie_data->ie_length),
+ sizeof(ie_data->ie_length));
+ len += sizeof(
+ ie_data->ie_length);
+ if (pmpriv->mgmt_ie[i]
+ .ie_length) {
+ memcpy_ext(
+ pmadapter,
+ (t_u8 *)ie_data +
+ len,
+ &pmpriv->mgmt_ie[i]
+ .ie_buffer,
+ pmpriv->mgmt_ie[i]
+ .ie_length,
+ pmpriv->mgmt_ie[i]
+ .ie_length);
+ len += pmpriv->mgmt_ie[i]
+ .ie_length;
+ }
+ }
+ }
+ misc->param.cust_ie.len += len;
+ pioctl_req->action = MLAN_ACT_SET;
+ cmd_action = HostCmd_ACT_GEN_SET;
+ } else { /* Automatic Addition */
+ if (MLAN_STATUS_FAILURE ==
+ wlan_custom_ioctl_get_autoidx(
+ pmpriv, pioctl_req, mask,
+ ie_data, &index)) {
+ PRINTM(MERROR,
+ "Failed to Set the IE buffer\n");
+ ret = MLAN_STATUS_FAILURE;
+ goto done;
+ }
+ mask &= ~MLAN_CUSTOM_IE_NEW_MASK;
+ if (MLAN_CUSTOM_IE_AUTO_IDX_MASK ==
+ index ||
+ index >= MAX_MGMT_IE_INDEX) {
+ ret = MLAN_STATUS_SUCCESS;
+ goto done;
+ }
+ tmp_ie = (t_u8 *)&pmpriv->mgmt_ie[index]
+ .ie_buffer;
+ memcpy_ext(
+ pmadapter,
+ tmp_ie + pmpriv->mgmt_ie[index]
+ .ie_length,
+ &ie_data->ie_buffer,
+ ie_data->ie_length,
+ ie_data->ie_length);
+ pmpriv->mgmt_ie[index].ie_length +=
+ ie_data->ie_length;
+ pmpriv->mgmt_ie[index].ie_index = index;
+ pmpriv->mgmt_ie[index]
+ .mgmt_subtype_mask = mask;
+
+ pioctl_req->action = MLAN_ACT_SET;
+ cmd_action = HostCmd_ACT_GEN_SET;
+ ie_data->ie_index = index;
+ ie_data->ie_length =
+ pmpriv->mgmt_ie[index].ie_length;
+ memcpy_ext(
+ pmadapter, &ie_data->ie_buffer,
+ &pmpriv->mgmt_ie[index]
+ .ie_buffer,
+ pmpriv->mgmt_ie[index].ie_length,
+ MAX_IE_SIZE);
+ misc->param.cust_ie.len +=
+ pmpriv->mgmt_ie[index]
+ .ie_length +
+ MLAN_CUSTOM_IE_HDR_SIZE;
+ }
+ } else {
+ if (index >= pmadapter->max_mgmt_ie_index ||
+ index >= MAX_MGMT_IE_INDEX) {
+ PRINTM(MERROR,
+ "Invalid custom IE index %d\n",
+ index);
+ ret = MLAN_STATUS_FAILURE;
+ goto done;
+ }
+ /* Set/Clear the IE and save it */
+ if (ie_data->mgmt_subtype_mask ==
+ MLAN_CUSTOM_IE_DELETE_MASK &&
+ ie_data->ie_length) {
+ PRINTM(MINFO, "Clear the IE buffer\n");
+ ret = wlan_custom_ioctl_auto_delete(
+ pmpriv, pioctl_req, ie_data,
+ index);
+ /* if IE to delete is not found, return
+ * error */
+ if (ret == MLAN_STATUS_FAILURE)
+ goto done;
+ memset(pmadapter, ie_data, 0,
+ sizeof(custom_ie) *
+ MAX_MGMT_IE_INDEX_TO_FW);
+ memcpy_ext(
+ pmadapter, (t_u8 *)ie_data,
+ &pmpriv->mgmt_ie[index],
+ pmpriv->mgmt_ie[index].ie_length +
+ MLAN_CUSTOM_IE_HDR_SIZE,
+ pmpriv->mgmt_ie[index].ie_length +
+ MLAN_CUSTOM_IE_HDR_SIZE);
+ } else {
+ /*
+ * Check if this index is being used on
+ * any other interfaces. If yes, then
+ * the request needs to be rejected.
+ */
+ ret = wlan_is_custom_ie_index_unused(
+ pmpriv, index);
+ if (ret == MLAN_STATUS_FAILURE) {
+ PRINTM(MERROR,
+ "IE index is used by other interface.\n");
+ PRINTM(MERROR,
+ "Set or delete on index %d is not allowed.\n",
+ index);
+ pioctl_req->status_code =
+ MLAN_ERROR_IOCTL_FAIL;
+ goto done;
+ }
+ PRINTM(MINFO, "Set the IE buffer\n");
+ if (ie_data->mgmt_subtype_mask ==
+ MLAN_CUSTOM_IE_DELETE_MASK)
+ ie_data->ie_length = 0;
+ else {
+ if ((pmpriv->mgmt_ie[index]
+ .mgmt_subtype_mask ==
+ ie_data->mgmt_subtype_mask) &&
+ (pmpriv->mgmt_ie[index]
+ .ie_length ==
+ ie_data->ie_length) &&
+ !memcmp(pmpriv->adapter,
+ pmpriv->mgmt_ie[index]
+ .ie_buffer,
+ ie_data->ie_buffer,
+ ie_data->ie_length)) {
+ PRINTM(MIOCTL,
+ "same custom ie already configured!\n");
+ if (ioctl_len <= 0 &&
+ misc->param.cust_ie
+ .len ==
+ 0) {
+ goto done;
+ } else {
+ /* remove
+ * matching IE
+ * from app
+ * buffer */
+ app_data_len -=
+ ie_data->ie_length +
+ MLAN_CUSTOM_IE_HDR_SIZE;
+ memmove(pmadapter,
+ (t_u8 *)ie_data,
+ ie_data->ie_buffer +
+ ie_data->ie_length,
+ ioctl_len);
+ continue;
+ }
+ }
+ }
+ memset(pmadapter,
+ &pmpriv->mgmt_ie[index], 0,
+ sizeof(custom_ie));
+ memcpy_ext(pmadapter,
+ &pmpriv->mgmt_ie[index],
+ ie_data, sizeof(custom_ie),
+ sizeof(custom_ie));
+ }
+
+ misc->param.cust_ie.len +=
+ pmpriv->mgmt_ie[index].ie_length +
+ MLAN_CUSTOM_IE_HDR_SIZE;
+ pioctl_req->action = MLAN_ACT_SET;
+ cmd_action = HostCmd_ACT_GEN_SET;
+ }
+ }
+ }
+
+ /* Send command to firmware */
+ if (GET_BSS_ROLE(pmpriv) == MLAN_BSS_ROLE_STA) {
+ ret = wlan_prepare_cmd(
+ pmpriv, HostCmd_CMD_MGMT_IE_LIST, cmd_action, 0,
+ (send_ioctl) ? (t_void *)pioctl_req : MNULL,
+ &misc->param.cust_ie);
+ }
+#ifdef UAP_SUPPORT
+ else if (GET_BSS_ROLE(pmpriv) == MLAN_BSS_ROLE_UAP) {
+ ret = wlan_prepare_cmd(
+ pmpriv, HOST_CMD_APCMD_SYS_CONFIGURE, cmd_action, 0,
+ (send_ioctl) ? (t_void *)pioctl_req : MNULL,
+ (send_ioctl) ? MNULL : &misc->param.cust_ie);
+ }
+#endif
+ if (ret == MLAN_STATUS_SUCCESS)
+ ret = MLAN_STATUS_PENDING;
+done:
+ LEAVE();
+ return ret;
+}
+
+/**
+ * @brief Read/write adapter register
+ *
+ * @param pmadapter A pointer to mlan_adapter structure
+ * @param pioctl_req A pointer to ioctl request buffer
+ *
+ * @return MLAN_STATUS_PENDING --success, otherwise fail
+ */
+mlan_status wlan_reg_mem_ioctl_reg_rw(pmlan_adapter pmadapter,
+ pmlan_ioctl_req pioctl_req)
+{
+ mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index];
+ mlan_ds_reg_mem *reg_mem = MNULL;
+ mlan_status ret = MLAN_STATUS_SUCCESS;
+ t_u16 cmd_action = 0, cmd_no;
+
+ ENTER();
+
+ reg_mem = (mlan_ds_reg_mem *)pioctl_req->pbuf;
+ if (pioctl_req->action == MLAN_ACT_GET)
+ cmd_action = HostCmd_ACT_GEN_GET;
+ else
+ cmd_action = HostCmd_ACT_GEN_SET;
+
+ switch (reg_mem->param.reg_rw.type) {
+ case MLAN_REG_MAC:
+#if defined(PCIE9098) || defined(SD9098) || defined(USB9098) || \
+ defined(PCIE9097) || defined(USB9097) || defined(SD9097)
+ case MLAN_REG_MAC2:
+#endif
+ cmd_no = HostCmd_CMD_MAC_REG_ACCESS;
+ break;
+ case MLAN_REG_BBP:
+#if defined(PCIE9098) || defined(SD9098) || defined(USB9098) || \
+ defined(PCIE9097) || defined(USB9097) || defined(SD9097)
+ case MLAN_REG_BBP2:
+#endif
+ cmd_no = HostCmd_CMD_BBP_REG_ACCESS;
+ break;
+ case MLAN_REG_RF:
+#if defined(PCIE9098) || defined(SD9098) || defined(USB9098) || \
+ defined(PCIE9097) || defined(USB9097) || defined(SD9097)
+ case MLAN_REG_RF2:
+#endif
+ cmd_no = HostCmd_CMD_RF_REG_ACCESS;
+ break;
+ case MLAN_REG_CAU:
+ cmd_no = HostCmd_CMD_CAU_REG_ACCESS;
+ break;
+ case MLAN_REG_PSU:
+ cmd_no = HostCmd_CMD_TARGET_ACCESS;
+ break;
+ case MLAN_REG_BCA:
+#if defined(PCIE9098) || defined(SD9098) || defined(USB9098) || \
+ defined(PCIE9097) || defined(USB9097) || defined(SD9097)
+ case MLAN_REG_BCA2:
+#endif
+ cmd_no = HostCmd_CMD_BCA_REG_ACCESS;
+ break;
+ default:
+ pioctl_req->status_code = MLAN_ERROR_IOCTL_INVALID;
+ ret = MLAN_STATUS_FAILURE;
+ goto exit;
+ }
+
+ /* Send request to firmware */
+ ret = wlan_prepare_cmd(pmpriv, cmd_no, cmd_action, 0,
+ (t_void *)pioctl_req,
+ (t_void *)&reg_mem->param.reg_rw);
+
+ if (ret == MLAN_STATUS_SUCCESS)
+ ret = MLAN_STATUS_PENDING;
+
+exit:
+ LEAVE();
+ return ret;
+}
+
+/**
+ * @brief Read the EEPROM contents of the card
+ *
+ * @param pmadapter A pointer to mlan_adapter structure
+ * @param pioctl_req A pointer to ioctl request buffer
+ *
+ * @return MLAN_STATUS_PENDING --success, otherwise fail
+ */
+mlan_status wlan_reg_mem_ioctl_read_eeprom(pmlan_adapter pmadapter,
+ pmlan_ioctl_req pioctl_req)
+{
+ mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index];
+ mlan_ds_reg_mem *reg_mem = MNULL;
+ mlan_status ret = MLAN_STATUS_SUCCESS;
+ t_u16 cmd_action = 0;
+
+ ENTER();
+
+ reg_mem = (mlan_ds_reg_mem *)pioctl_req->pbuf;
+ if (pioctl_req->action == MLAN_ACT_GET)
+ cmd_action = HostCmd_ACT_GEN_GET;
+
+ /* Send request to firmware */
+ ret = wlan_prepare_cmd(pmpriv, HostCmd_CMD_802_11_EEPROM_ACCESS,
+ cmd_action, 0, (t_void *)pioctl_req,
+ (t_void *)&reg_mem->param.rd_eeprom);
+
+ if (ret == MLAN_STATUS_SUCCESS)
+ ret = MLAN_STATUS_PENDING;
+
+ LEAVE();
+ return ret;
+}
+
+/**
+ * @brief Read/write memory of device
+ *
+ * @param pmadapter A pointer to mlan_adapter structure
+ * @param pioctl_req A pointer to ioctl request buffer
+ *
+ * @return MLAN_STATUS_PENDING --success, otherwise fail
+ */
+mlan_status wlan_reg_mem_ioctl_mem_rw(pmlan_adapter pmadapter,
+ pmlan_ioctl_req pioctl_req)
+{
+ mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index];
+ mlan_ds_reg_mem *reg_mem = MNULL;
+ mlan_status ret = MLAN_STATUS_SUCCESS;
+ t_u16 cmd_action = 0;
+
+ ENTER();
+
+ reg_mem = (mlan_ds_reg_mem *)pioctl_req->pbuf;
+ if (pioctl_req->action == MLAN_ACT_GET)
+ cmd_action = HostCmd_ACT_GEN_GET;
+ else
+ cmd_action = HostCmd_ACT_GEN_SET;
+
+ /* Send request to firmware */
+ ret = wlan_prepare_cmd(pmpriv, HostCmd_CMD_MEM_ACCESS, cmd_action, 0,
+ (t_void *)pioctl_req,
+ (t_void *)&reg_mem->param.mem_rw);
+
+ if (ret == MLAN_STATUS_SUCCESS)
+ ret = MLAN_STATUS_PENDING;
+
+ LEAVE();
+ return ret;
+}
+
+/**
+ * @brief This function will check if station list is empty
+ *
+ * @param priv A pointer to mlan_private
+ *
+ * @return MFALSE/MTRUE
+ */
+t_u8 wlan_is_station_list_empty(mlan_private *priv)
+{
+ ENTER();
+ if (!(util_peek_list(priv->adapter->pmoal_handle, &priv->sta_list,
+ priv->adapter->callbacks.moal_spin_lock,
+ priv->adapter->callbacks.moal_spin_unlock))) {
+ LEAVE();
+ return MTRUE;
+ }
+ LEAVE();
+ return MFALSE;
+}
+
+/**
+ * @brief This function will return the pointer to station entry in station
+ * list table which matches the give mac address
+ *
+ * @param priv A pointer to mlan_private
+ * @param mac mac address to find in station list table
+ *
+ * @return A pointer to structure sta_node
+ */
+sta_node *wlan_get_station_entry(mlan_private *priv, t_u8 *mac)
+{
+ sta_node *sta_ptr;
+
+ ENTER();
+
+ if (!mac) {
+ LEAVE();
+ return MNULL;
+ }
+ sta_ptr = (sta_node *)util_peek_list(
+ priv->adapter->pmoal_handle, &priv->sta_list,
+ priv->adapter->callbacks.moal_spin_lock,
+ priv->adapter->callbacks.moal_spin_unlock);
+
+ while (sta_ptr && (sta_ptr != (sta_node *)&priv->sta_list)) {
+ if (!memcmp(priv->adapter, sta_ptr->mac_addr, mac,
+ MLAN_MAC_ADDR_LENGTH)) {
+ LEAVE();
+ return sta_ptr;
+ }
+ sta_ptr = sta_ptr->pnext;
+ }
+ LEAVE();
+ return MNULL;
+}
+
+/**
+ * @brief This function will add a pointer to station entry in station list
+ * table with the give mac address, if it does not exist already
+ *
+ * @param priv A pointer to mlan_private
+ * @param mac mac address to find in station list table
+ *
+ * @return A pointer to structure sta_node
+ */
+sta_node *wlan_add_station_entry(mlan_private *priv, t_u8 *mac)
+{
+ sta_node *sta_ptr = MNULL;
+ mlan_adapter *pmadapter = priv->adapter;
+
+ ENTER();
+ pmadapter->callbacks.moal_spin_lock(pmadapter->pmoal_handle,
+ priv->wmm.ra_list_spinlock);
+
+ sta_ptr = wlan_get_station_entry(priv, mac);
+ if (sta_ptr)
+ goto done;
+ if (priv->adapter->callbacks.moal_malloc(priv->adapter->pmoal_handle,
+ sizeof(sta_node), MLAN_MEM_DEF,
+ (t_u8 **)&sta_ptr)) {
+ PRINTM(MERROR, "Failed to allocate memory for station node\n");
+ pmadapter->callbacks.moal_spin_unlock(
+ pmadapter->pmoal_handle, priv->wmm.ra_list_spinlock);
+ LEAVE();
+ return MNULL;
+ }
+ memset(priv->adapter, sta_ptr, 0, sizeof(sta_node));
+ memcpy_ext(priv->adapter, sta_ptr->mac_addr, mac, MLAN_MAC_ADDR_LENGTH,
+ MLAN_MAC_ADDR_LENGTH);
+ util_enqueue_list_tail(priv->adapter->pmoal_handle, &priv->sta_list,
+ (pmlan_linked_list)sta_ptr,
+ priv->adapter->callbacks.moal_spin_lock,
+ priv->adapter->callbacks.moal_spin_unlock);
+#ifdef DRV_EMBEDDED_AUTHENTICATOR
+ if ((GET_BSS_ROLE(priv) == MLAN_BSS_ROLE_UAP) &&
+ IsAuthenticatorEnabled(priv->psapriv))
+ authenticator_init_client(priv->psapriv,
+ &sta_ptr->cm_connectioninfo, mac);
+#endif
+done:
+ pmadapter->callbacks.moal_spin_unlock(pmadapter->pmoal_handle,
+ priv->wmm.ra_list_spinlock);
+ LEAVE();
+ return sta_ptr;
+}
+
+/**
+ * @brief This function will delete a station entry from station list
+ *
+ *
+ * @param priv A pointer to mlan_private
+ * @param mac station's mac address
+ *
+ * @return N/A
+ */
+t_void wlan_delete_station_entry(mlan_private *priv, t_u8 *mac)
+{
+ sta_node *sta_ptr = MNULL;
+ mlan_adapter *pmadapter = priv->adapter;
+ ENTER();
+ pmadapter->callbacks.moal_spin_lock(pmadapter->pmoal_handle,
+ priv->wmm.ra_list_spinlock);
+ sta_ptr = wlan_get_station_entry(priv, mac);
+ if (sta_ptr) {
+#ifdef DRV_EMBEDDED_AUTHENTICATOR
+ if ((GET_BSS_ROLE(priv) == MLAN_BSS_ROLE_UAP) &&
+ IsAuthenticatorEnabled(priv->psapriv))
+ authenticator_free_client(priv->psapriv,
+ sta_ptr->cm_connectioninfo);
+#endif
+ util_unlink_list(priv->adapter->pmoal_handle, &priv->sta_list,
+ (pmlan_linked_list)sta_ptr,
+ priv->adapter->callbacks.moal_spin_lock,
+ priv->adapter->callbacks.moal_spin_unlock);
+ priv->adapter->callbacks.moal_mfree(priv->adapter->pmoal_handle,
+ (t_u8 *)sta_ptr);
+ }
+ pmadapter->callbacks.moal_spin_unlock(pmadapter->pmoal_handle,
+ priv->wmm.ra_list_spinlock);
+ LEAVE();
+ return;
+}
+
+/**
+ * @brief Clean up wapi station list
+ *
+ * @param priv Pointer to the mlan_private driver data struct
+ *
+ * @return N/A
+ */
+t_void wlan_delete_station_list(pmlan_private priv)
+{
+ sta_node *sta_ptr;
+
+ ENTER();
+ while ((sta_ptr = (sta_node *)util_dequeue_list(
+ priv->adapter->pmoal_handle, &priv->sta_list,
+ priv->adapter->callbacks.moal_spin_lock,
+ priv->adapter->callbacks.moal_spin_unlock))) {
+#ifdef DRV_EMBEDDED_AUTHENTICATOR
+ if ((GET_BSS_ROLE(priv) == MLAN_BSS_ROLE_UAP) &&
+ IsAuthenticatorEnabled(priv->psapriv))
+ authenticator_free_client(priv->psapriv,
+ sta_ptr->cm_connectioninfo);
+#endif
+ priv->adapter->callbacks.moal_mfree(priv->adapter->pmoal_handle,
+ (t_u8 *)sta_ptr);
+ }
+ LEAVE();
+ return;
+}
+
+/**
+ * @brief Set mimo switch configuration
+ *
+ * @param pmadapter A pointer to mlan_adapter structure
+ * @param pioctl_req A pointer to ioctl request buffer
+ *
+ * @return MLAN_STATUS_PENDING --success, otherwise fail
+ */
+mlan_status wlan_radio_ioctl_mimo_switch_cfg(pmlan_adapter pmadapter,
+ pmlan_ioctl_req pioctl_req)
+{
+ pmlan_private pmpriv = pmadapter->priv[pioctl_req->bss_index];
+ mlan_ds_radio_cfg *radio_cfg = (mlan_ds_radio_cfg *)pioctl_req->pbuf;
+ mlan_status ret = MLAN_STATUS_SUCCESS;
+
+ ENTER();
+
+ /* Send request to firmware */
+ ret = wlan_prepare_cmd(pmpriv, HostCmd_CMD_802_11_MIMO_SWITCH, 0, 0,
+ (t_void *)pioctl_req,
+ &(radio_cfg->param.mimo_switch_cfg));
+
+ if (ret == MLAN_STATUS_SUCCESS)
+ ret = MLAN_STATUS_PENDING;
+
+ LEAVE();
+ return ret;
+}
+
+/**
+ * @brief Get extended version information
+ *
+ * @param pmadapter A pointer to mlan_adapter structure
+ * @param pioctl_req A pointer to ioctl request buffer
+ *
+ * @return MLAN_STATUS_PENDING --success, otherwise fail
+ */
+mlan_status wlan_get_info_ver_ext(pmlan_adapter pmadapter,
+ pmlan_ioctl_req pioctl_req)
+{
+ pmlan_private pmpriv = pmadapter->priv[pioctl_req->bss_index];
+ mlan_ds_get_info *pinfo = (mlan_ds_get_info *)pioctl_req->pbuf;
+ mlan_status ret = MLAN_STATUS_SUCCESS;
+
+ ENTER();
+
+ /* Send request to firmware */
+ ret = wlan_prepare_cmd(pmpriv, HostCmd_CMD_VERSION_EXT,
+ HostCmd_ACT_GEN_GET, 0, (t_void *)pioctl_req,
+ &pinfo->param.ver_ext.version_str_sel);
+
+ if (ret == MLAN_STATUS_SUCCESS)
+ ret = MLAN_STATUS_PENDING;
+
+ LEAVE();
+ return ret;
+}
+
+/**
+ * @brief This function convert mlan_wifi_rate to wifi_rate.
+ *
+ * @param pmpriv A pointer to mlan_private structure
+ * @param rateStats wifi_rate_stat array
+ * @param pnum_rate A pointer to num_rate
+ *
+ * @return N/A
+ */
+t_void wlan_fill_hal_wifi_rate_in_host(pmlan_private pmpriv,
+ OUT wifi_rate_stat rateStats[],
+ t_u32 *pnumRate)
+{
+ t_u32 total_num_rate = 0;
+ t_u32 mcs_idx = 0;
+ t_u8 index = 0;
+ t_u8 rate_info = 0;
+
+ ENTER();
+
+ /* HT MCS */
+ for (mcs_idx = 0; mcs_idx < MCS_NUM_SUPP; mcs_idx++) {
+ /* 0: OFDM, 1:CCK, 2:HT 3:VHT 4..7 reserved */
+ rateStats[total_num_rate].rate.preamble = 2;
+ /* 0:20MHz, 1:40Mhz, 2:80Mhz, 3:160Mhz */
+ rateStats[total_num_rate].rate.bw = 0;
+ rateStats[total_num_rate].rate.rateMcsIdx = mcs_idx;
+ index = rateStats[total_num_rate].rate.rateMcsIdx;
+ rate_info = MLAN_RATE_FORMAT_HT |
+ (rateStats[total_num_rate].rate.bw << 2);
+ rateStats[total_num_rate].rate.bitrate =
+ wlan_index_to_data_rate(pmpriv->adapter, index,
+ rate_info, 0) *
+ 5;
+ PRINTM(MINFO, "HT[%d] index=0x%x rate_info=0x%x bitrate=0x%x\n",
+ total_num_rate, index, rate_info,
+ rateStats[total_num_rate].rate.bitrate / 5);
+
+ /* Get Tx mpdu */
+ rateStats[total_num_rate].tx_mpdu = 0;
+ rateStats[total_num_rate].rx_mpdu = 0;
+
+ /* Todo: mpdu_lost/retries*, need extend GetTxRxRateInfo */
+ rateStats[total_num_rate].mpdu_lost = 0xC1;
+ rateStats[total_num_rate].retries = 0xC2;
+ rateStats[total_num_rate].retries_short = 0xC3;
+ rateStats[total_num_rate].retries_long = 0xC4;
+
+ total_num_rate++;
+ }
+
+ /* VHT MCS */
+ for (mcs_idx = 0; mcs_idx < VHT_NUM_SUPPORT_MCS; mcs_idx++) {
+ /* 0: OFDM, 1:CCK, 2:HT 3:VHT 4..7 reserved */
+ rateStats[total_num_rate].rate.preamble = 3;
+ /* 0:1x1, 1:2x2, 3:3x3, 4:4x4 */
+ rateStats[total_num_rate].rate.nss = 0;
+ /* 0:20MHz, 1:40Mhz, 2:80Mhz, 3:160Mhz */
+ rateStats[total_num_rate].rate.bw = 0;
+ rateStats[total_num_rate].rate.rateMcsIdx = mcs_idx;
+ /* nss 2 ? bw 20MHZ ? */
+ index = rateStats[total_num_rate].rate.rateMcsIdx |
+ (rateStats[total_num_rate].rate.nss << 4);
+ rate_info = MLAN_RATE_FORMAT_VHT |
+ (rateStats[total_num_rate].rate.bw << 2);
+ rateStats[total_num_rate].rate.bitrate =
+ wlan_index_to_data_rate(pmpriv->adapter, index,
+ rate_info, 0) *
+ 5;
+ PRINTM(MINFO,
+ "VHT[%d] index=0x%x rate_info=0x%x bitrate=0x%x\n",
+ total_num_rate, index, rate_info,
+ rateStats[total_num_rate].rate.bitrate / 5);
+
+ rateStats[total_num_rate].tx_mpdu = 0;
+ rateStats[total_num_rate].rx_mpdu = 0;
+
+ /* Todo: mpdu_lost/retries*, need extend GetTxRxRateInfo */
+ rateStats[total_num_rate].mpdu_lost = 0xC1;
+ rateStats[total_num_rate].retries = 0xC2;
+ rateStats[total_num_rate].retries_short = 0xC3;
+ rateStats[total_num_rate].retries_long = 0xC4;
+
+ total_num_rate++;
+ }
+
+ *pnumRate = total_num_rate;
+
+ LEAVE();
+}
+
+/**
+ * @brief This function fill link layer statistic from firmware
+ *
+ * @param priv A pointer to
+ * mlan_private structure
+ * @param link_statistic_ioctl_buf, A pointer to fill ioctl buffer
+ *
+ * @return MLAN_STATUS_SUCCESS
+ */
+static void wlan_fill_link_statistic_in_host(mlan_private *priv,
+ char *link_statistic_ioctl_buf)
+{
+ char *link_statistic = link_statistic_ioctl_buf;
+ wifi_radio_stat *radio_stat = MNULL;
+ wifi_iface_stat *iface_stat = MNULL;
+ t_u32 num_radio = MAX_RADIO;
+ int i = 0, chan_idx = 0;
+ t_u32 num_peers = 0;
+ sta_node *sta_ptr = MNULL;
+#ifdef WMM
+ t_u8 *ptid = MNULL;
+#endif
+
+ ENTER();
+
+ *((t_u32 *)link_statistic) = num_radio;
+ link_statistic += sizeof(num_radio);
+
+ /* Fill radio stats array */
+ for (i = 0; i < num_radio; i++) {
+ radio_stat = (wifi_radio_stat *)link_statistic;
+ link_statistic += sizeof(wifi_radio_stat);
+
+ radio_stat->radio = 0xF0;
+
+ radio_stat->on_time = 0;
+ radio_stat->tx_time = 0;
+ radio_stat->reserved0 = 0;
+ radio_stat->rx_time = 0;
+ radio_stat->on_time_scan = 0;
+ radio_stat->on_time_nbd = 0;
+ radio_stat->on_time_gscan = 0;
+ radio_stat->on_time_roam_scan = 0;
+ radio_stat->on_time_pno_scan = 0;
+ radio_stat->on_time_hs20 = 0;
+
+ radio_stat->num_channels = 1;
+ for (chan_idx = 0; chan_idx < radio_stat->num_channels;
+ chan_idx++) {
+ if (radio_stat->num_channels > MAX_NUM_CHAN) {
+ radio_stat->num_channels = MAX_NUM_CHAN;
+ PRINTM(MERROR,
+ "%s : radio_stat->num_channels=%d\n",
+ __func__, radio_stat->num_channels);
+ break;
+ }
+
+ if (priv->bss_role == MLAN_BSS_ROLE_STA) {
+ if (priv->media_connected) {
+ radio_stat->channels[chan_idx]
+ .channel.width =
+ priv->curr_bss_params
+ .bss_descriptor
+ .curr_bandwidth;
+ radio_stat->channels[chan_idx]
+ .channel.center_freq =
+ priv->curr_bss_params
+ .bss_descriptor.freq;
+ radio_stat->channels[chan_idx]
+ .channel.center_freq0 = 0;
+ radio_stat->channels[chan_idx]
+ .channel.center_freq1 = 0;
+ }
+ } else {
+ radio_stat->channels[chan_idx].channel.width =
+ priv->uap_state_chan_cb.bandcfg
+ .chanWidth;
+ radio_stat->channels[chan_idx]
+ .channel
+ .center_freq = wlan_11d_chan_2_freq(
+ priv->adapter,
+ priv->uap_state_chan_cb.channel,
+ (priv->uap_state_chan_cb.channel > 14) ?
+ BAND_A :
+ BAND_G);
+ radio_stat->channels[chan_idx]
+ .channel.center_freq0 = 0;
+ radio_stat->channels[chan_idx]
+ .channel.center_freq1 = 0;
+ }
+ radio_stat->channels[chan_idx].on_time = 0xE3;
+ radio_stat->channels[chan_idx].cca_busy_time = 0xE4;
+ }
+ }
+
+ /* Fill iface stats*/
+ iface_stat = (wifi_iface_stat *)link_statistic;
+
+ /* get wifi_interface_link_layer_info in driver, not in firmware */
+ if (priv->bss_role == MLAN_BSS_ROLE_STA) {
+ iface_stat->info.mode = MLAN_INTERFACE_STA;
+ if (priv->media_connected)
+ iface_stat->info.state = MLAN_ASSOCIATING;
+ else
+ iface_stat->info.state = MLAN_DISCONNECTED;
+ iface_stat->info.roaming = MLAN_ROAMING_IDLE;
+ iface_stat->info.capabilities = MLAN_CAPABILITY_QOS;
+ memcpy_ext(priv->adapter, iface_stat->info.ssid,
+ priv->curr_bss_params.bss_descriptor.ssid.ssid,
+ MLAN_MAX_SSID_LENGTH, MLAN_MAX_SSID_LENGTH);
+ memcpy_ext(priv->adapter, iface_stat->info.bssid,
+ priv->curr_bss_params.bss_descriptor.mac_address,
+ MLAN_MAC_ADDR_LENGTH, MLAN_MAC_ADDR_LENGTH);
+ } else {
+ iface_stat->info.mode = MLAN_INTERFACE_SOFTAP;
+ iface_stat->info.capabilities = MLAN_CAPABILITY_QOS;
+ }
+ memcpy_ext(priv->adapter, iface_stat->info.mac_addr, priv->curr_addr,
+ MLAN_MAC_ADDR_LENGTH, MLAN_MAC_ADDR_LENGTH);
+ memcpy_ext(priv->adapter, iface_stat->info.ap_country_str,
+ priv->adapter->country_code, COUNTRY_CODE_LEN,
+ COUNTRY_CODE_LEN);
+ memcpy_ext(priv->adapter, iface_stat->info.country_str,
+ priv->adapter->country_code, COUNTRY_CODE_LEN,
+ COUNTRY_CODE_LEN);
+
+ iface_stat->beacon_rx = 0;
+ iface_stat->average_tsf_offset = 0;
+ iface_stat->leaky_ap_detected = 0;
+ iface_stat->leaky_ap_avg_num_frames_leaked = 0;
+ iface_stat->leaky_ap_guard_time = 0;
+
+ /* Value of iface_stat should be Reaccumulate by each peer */
+ iface_stat->mgmt_rx = 0;
+ iface_stat->mgmt_action_rx = 0;
+ iface_stat->mgmt_action_tx = 0;
+
+ iface_stat->rssi_mgmt = 0;
+ iface_stat->rssi_data = 0;
+ iface_stat->rssi_ack = 0;
+
+#ifdef WMM
+ for (i = WMM_AC_BK; i <= WMM_AC_VO; i++) {
+ iface_stat->ac[i].ac = i;
+ ptid = ac_to_tid[i];
+ iface_stat->ac[i].tx_mpdu = priv->wmm.packets_out[ptid[0]] +
+ priv->wmm.packets_out[ptid[1]];
+ iface_stat->ac[i].rx_mpdu = 0;
+ iface_stat->ac[i].tx_mcast = 0;
+ iface_stat->ac[i].rx_mcast = 0;
+ iface_stat->ac[i].rx_ampdu = 0;
+ iface_stat->ac[i].tx_ampdu = 0;
+ iface_stat->ac[i].mpdu_lost = 0;
+ iface_stat->ac[i].retries = 0;
+ iface_stat->ac[i].retries_short = 0;
+ iface_stat->ac[i].retries_long = 0;
+ iface_stat->ac[i].contention_time_min = 0;
+ iface_stat->ac[i].contention_time_max = 0;
+ iface_stat->ac[i].contention_time_avg = 0;
+ iface_stat->ac[i].contention_num_samples = 0;
+ }
+#endif
+
+ if (priv->bss_role == MLAN_BSS_ROLE_STA) {
+ if (priv->media_connected) {
+ iface_stat->peer_info[0].type = WIFI_PEER_AP;
+ memcpy_ext(
+ priv->adapter,
+ iface_stat->peer_info[0].peer_mac_address,
+ priv->curr_bss_params.bss_descriptor.mac_address,
+ MLAN_MAC_ADDR_LENGTH, MLAN_MAC_ADDR_LENGTH);
+ iface_stat->peer_info[0].capabilities =
+ MLAN_CAPABILITY_QOS;
+ wlan_fill_hal_wifi_rate_in_host(
+ priv, iface_stat->peer_info[0].rate_stats,
+ &(iface_stat->peer_info[0].num_rate));
+ num_peers = 1;
+ }
+ } else {
+ sta_ptr = (sta_node *)util_peek_list(
+ priv->adapter->pmoal_handle, &priv->sta_list,
+ priv->adapter->callbacks.moal_spin_lock,
+ priv->adapter->callbacks.moal_spin_unlock);
+ if (sta_ptr) {
+ while (sta_ptr != (sta_node *)&priv->sta_list) {
+ iface_stat->peer_info[num_peers].type =
+ WIFI_PEER_STA;
+ memcpy_ext(priv->adapter,
+ iface_stat->peer_info[num_peers]
+ .peer_mac_address,
+ sta_ptr->mac_addr,
+ MLAN_MAC_ADDR_LENGTH,
+ MLAN_MAC_ADDR_LENGTH);
+ iface_stat->peer_info[num_peers].capabilities =
+ MLAN_CAPABILITY_QOS;
+ wlan_fill_hal_wifi_rate_in_host(
+ priv,
+ iface_stat->peer_info[num_peers]
+ .rate_stats,
+ &(iface_stat->peer_info[num_peers]
+ .num_rate));
+ num_peers++;
+
+ sta_ptr = sta_ptr->pnext;
+ }
+ }
+ }
+ iface_stat->num_peers = num_peers;
+
+ LEAVE();
+}
+
+/**
+ * @brief Set/Get link layer statistics
+ *
+ * @param pmadapter A pointer to mlan_adapter structure
+ * @param pioctl_req A pointer to ioctl request buffer
+ *
+ * @return MLAN_STATUS_PENDING --success, otherwise fail
+ */
+mlan_status wlan_ioctl_link_statistic(mlan_private *pmpriv,
+ pmlan_ioctl_req pioctl_req)
+{
+ mlan_status ret = MLAN_STATUS_SUCCESS;
+ mlan_ds_get_info *info = MNULL;
+ t_u8 *link_statistic = MNULL;
+
+ ENTER();
+
+ /* Check buffer length of MLAN IOCTL */
+ if (pioctl_req->buf_len < sizeof(mlan_ds_get_stats)) {
+ PRINTM(MWARN,
+ "MLAN IOCTL information buffer length is too short.\n");
+ pioctl_req->data_read_written = 0;
+ pioctl_req->buf_len_needed = sizeof(mlan_ds_get_stats);
+ pioctl_req->status_code = MLAN_ERROR_INVALID_PARAMETER;
+ ret = MLAN_STATUS_RESOURCE;
+ goto exit;
+ }
+
+ /** We will not send HostCmd_CMD_802_11_LINK_STATS to FW */
+ if (pioctl_req->action == MLAN_ACT_GET) {
+ info = (mlan_ds_get_info *)pioctl_req->pbuf;
+ link_statistic = info->param.link_statistic;
+ /** Get the LL STATS from driver */
+ wlan_fill_link_statistic_in_host(pmpriv, link_statistic);
+ DBG_HEXDUMP(
+ MCMD_D,
+ "wlan_ioctl_link_statistic() link_statistic in host",
+ (t_u8 *)link_statistic, 800);
+ }
+ ret = MLAN_STATUS_SUCCESS;
+
+exit:
+ LEAVE();
+ return ret;
+}
+
+/**
+ * @brief Get TX/RX histogram statistic
+ *
+ * @param pmadapter A pointer to mlan_adapter structure
+ * @param pioctl_req A pointer to ioctl request buffer
+ *
+ * @return MLAN_STATUS_PENDING --success, otherwise fail
+ */
+mlan_status wlan_get_tx_rx_histogram(pmlan_adapter pmadapter,
+ pmlan_ioctl_req pioctl_req)
+{
+ pmlan_private pmpriv = pmadapter->priv[pioctl_req->bss_index];
+ mlan_ds_misc_cfg *pmisc = (mlan_ds_misc_cfg *)pioctl_req->pbuf;
+ mlan_status ret = MLAN_STATUS_SUCCESS;
+
+ ENTER();
+
+ /* Send request to firmware */
+ ret = wlan_prepare_cmd(pmpriv, HOST_CMD_TX_RX_PKT_STATS,
+ HostCmd_ACT_GEN_GET, 0, (t_void *)pioctl_req,
+ &(pmisc->param.tx_rx_histogram));
+
+ if (ret == MLAN_STATUS_SUCCESS)
+ ret = MLAN_STATUS_PENDING;
+
+ LEAVE();
+ return ret;
+}
+
+#ifdef DEBUG_LEVEL1
+/**
+ * @brief Set driver debug bit masks in order to enhance performance
+ *
+ * @param pmadapter A pointer to mlan_adapter structure
+ * @param pioctl_req A pointer to ioctl request buffer
+ *
+ * @return MLAN_STATUS_PENDING --success, otherwise fail
+ */
+mlan_status wlan_set_drvdbg(pmlan_adapter pmadapter, pmlan_ioctl_req pioctl_req)
+{
+ mlan_ds_misc_cfg *misc = (mlan_ds_misc_cfg *)pioctl_req->pbuf;
+ mlan_status ret = MLAN_STATUS_SUCCESS;
+
+ ENTER();
+
+ /* Set driver debug bit masks */
+ mlan_drvdbg = misc->param.drvdbg;
+
+ LEAVE();
+ return ret;
+}
+#endif
+
+/**
+ * @brief Rx mgmt frame forward register
+ *
+ * @param pmadapter A pointer to mlan_adapter structure
+ * @param pioctl_req A pointer to ioctl request buffer
+ *
+ * @return MLAN_STATUS_PENDING --success, otherwise fail
+ */
+mlan_status wlan_reg_rx_mgmt_ind(pmlan_adapter pmadapter,
+ pmlan_ioctl_req pioctl_req)
+{
+ pmlan_private pmpriv = pmadapter->priv[pioctl_req->bss_index];
+ mlan_ds_misc_cfg *misc = (mlan_ds_misc_cfg *)pioctl_req->pbuf;
+ mlan_status ret = MLAN_STATUS_SUCCESS;
+
+ ENTER();
+
+ /* Set passthru mask for mgmt frame */
+ pmpriv->mgmt_frame_passthru_mask = misc->param.mgmt_subtype_mask;
+
+ /* Send request to firmware */
+ ret = wlan_prepare_cmd(pmpriv, HostCmd_CMD_RX_MGMT_IND,
+ pioctl_req->action, 0, (t_void *)pioctl_req,
+ &misc->param.mgmt_subtype_mask);
+
+ if (ret == MLAN_STATUS_SUCCESS)
+ ret = MLAN_STATUS_PENDING;
+
+ LEAVE();
+ return ret;
+}
+
+/**
+ * @brief This function processes the 802.11 mgmt Frame
+ *
+ * @param priv A pointer to mlan_private
+ *
+ * @param payload A pointer to the received buffer
+ * @param payload_len Length of the received buffer
+ * @param prx_pd A pointer to RxPD
+ *
+ * @return MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ */
+mlan_status wlan_process_802dot11_mgmt_pkt(mlan_private *priv, t_u8 *payload,
+ t_u32 payload_len, RxPD *prx_pd)
+{
+ pmlan_adapter pmadapter = priv->adapter;
+ pmlan_callbacks pcb = &pmadapter->callbacks;
+ mlan_status ret = MLAN_STATUS_SUCCESS;
+ wlan_802_11_header *pieee_pkt_hdr = MNULL;
+ t_u16 sub_type = 0;
+ t_u8 *event_buf = MNULL;
+ mlan_event *pevent = MNULL;
+ t_u8 unicast = 0;
+ t_u8 broadcast[] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
+ IEEE80211_MGMT *mgmt = MNULL;
+ t_u8 category = 0;
+ t_u8 action_code = 0;
+#ifdef UAP_SUPPORT
+ sta_node *sta_ptr = MNULL;
+ MrvlIETypes_MgmtFrameSet_t *tlv;
+ pmlan_buffer pmbuf;
+#endif
+
+ ENTER();
+ if (payload_len > (MAX_EVENT_SIZE - sizeof(mlan_event))) {
+ PRINTM(MERROR, "Dropping large mgmt frame,len =%d\n",
+ payload_len);
+ LEAVE();
+ return ret;
+ }
+ /* Check packet type-subtype and compare with mgmt_passthru_mask
+ * If event is needed to host, just eventify it */
+ pieee_pkt_hdr = (wlan_802_11_header *)payload;
+ sub_type = IEEE80211_GET_FC_MGMT_FRAME_SUBTYPE(pieee_pkt_hdr->frm_ctl);
+ if (((1 << sub_type) & priv->mgmt_frame_passthru_mask) == 0) {
+ PRINTM(MINFO, "Dropping mgmt frame for subtype %d snr=%d.\n",
+ sub_type, prx_pd->snr);
+ LEAVE();
+ return ret;
+ }
+ switch (sub_type) {
+ case SUBTYPE_ASSOC_REQUEST:
+ case SUBTYPE_REASSOC_REQUEST:
+#ifdef UAP_SUPPORT
+ if (priv->uap_host_based & UAP_FLAG_HOST_MLME) {
+ PRINTM_NETINTF(MMSG, priv);
+ if (!memcmp(pmadapter, pieee_pkt_hdr->addr3,
+ priv->curr_addr, MLAN_MAC_ADDR_LENGTH)) {
+ PRINTM(MMSG,
+ "wlan: HostMlme MICRO_AP_STA_ASSOC " MACSTR
+ "\n",
+ MAC2STR(pieee_pkt_hdr->addr2));
+ mgmt = (IEEE80211_MGMT *)payload;
+ sta_ptr = wlan_add_station_entry(
+ priv, pieee_pkt_hdr->addr2);
+ if (sta_ptr) {
+ sta_ptr->capability = wlan_le16_to_cpu(
+ mgmt->u.assoc_req.capab_info);
+ pmbuf = wlan_alloc_mlan_buffer(
+ pmadapter, payload_len, 0,
+ MOAL_MALLOC_BUFFER);
+ if (pmbuf) {
+ PRINTM(MCMND,
+ "check sta capability\n");
+ pmbuf->data_len =
+ ASSOC_EVENT_FIX_SIZE;
+ tlv = (MrvlIETypes_MgmtFrameSet_t
+ *)(pmbuf->pbuf +
+ pmbuf->data_offset +
+ pmbuf->data_len);
+ tlv->type = wlan_cpu_to_le16(
+ TLV_TYPE_MGMT_FRAME);
+ tlv->len = sizeof(
+ IEEEtypes_FrameCtl_t);
+ memcpy_ext(
+ pmadapter,
+ (t_u8 *)&tlv
+ ->frame_control,
+ &pieee_pkt_hdr->frm_ctl,
+ sizeof(IEEEtypes_FrameCtl_t),
+ sizeof(IEEEtypes_FrameCtl_t));
+ pmbuf->data_len += sizeof(
+ MrvlIETypes_MgmtFrameSet_t);
+ memcpy_ext(
+ pmadapter,
+ pmbuf->pbuf +
+ pmbuf->data_offset +
+ pmbuf->data_len,
+ payload +
+ sizeof(wlan_802_11_header),
+ payload_len -
+ sizeof(wlan_802_11_header),
+ payload_len -
+ sizeof(wlan_802_11_header));
+ pmbuf->data_len +=
+ payload_len -
+ sizeof(wlan_802_11_header);
+ tlv->len +=
+ payload_len -
+ sizeof(wlan_802_11_header);
+ tlv->len = wlan_cpu_to_le16(
+ tlv->len);
+ DBG_HEXDUMP(
+ MCMD_D, "assoc_req",
+ pmbuf->pbuf +
+ pmbuf->data_offset,
+ pmbuf->data_len);
+ wlan_check_sta_capability(
+ priv, pmbuf, sta_ptr);
+ wlan_free_mlan_buffer(pmadapter,
+ pmbuf);
+ }
+ }
+ } else {
+ PRINTM(MMSG,
+ "wlan: Drop MICRO_AP_STA_ASSOC " MACSTR
+ " from unknown BSSID " MACSTR "\n",
+ MAC2STR(pieee_pkt_hdr->addr2),
+ MAC2STR(pieee_pkt_hdr->addr3));
+ }
+ }
+ unicast = MTRUE;
+ break;
+#endif
+ case SUBTYPE_AUTH:
+ unicast = MTRUE;
+ PRINTM_NETINTF(MMSG, priv);
+ PRINTM(MMSG, "wlan: HostMlme Auth received from " MACSTR "\n",
+ MAC2STR(pieee_pkt_hdr->addr2));
+ break;
+ case SUBTYPE_PROBE_RESP:
+ unicast = MTRUE;
+ break;
+ case SUBTYPE_DISASSOC:
+ case SUBTYPE_DEAUTH:
+ if (memcmp(pmadapter, pieee_pkt_hdr->addr1, broadcast,
+ MLAN_MAC_ADDR_LENGTH))
+ unicast = MTRUE;
+#ifdef UAP_SUPPORT
+ if (priv->uap_host_based & UAP_FLAG_HOST_MLME) {
+ if (!memcmp(pmadapter, pieee_pkt_hdr->addr3,
+ priv->curr_addr, MLAN_MAC_ADDR_LENGTH)) {
+ PRINTM_NETINTF(MMSG, priv);
+ PRINTM(MMSG,
+ "wlan: HostMlme Deauth Receive from " MACSTR
+ "\n",
+ MAC2STR(pieee_pkt_hdr->addr2));
+ }
+ }
+#endif
+ if (priv->bss_role == MLAN_BSS_ROLE_STA) {
+ if (priv->curr_bss_params.host_mlme) {
+ if (memcmp(pmadapter, pieee_pkt_hdr->addr2,
+ (t_u8 *)priv->curr_bss_params
+ .bss_descriptor.mac_address,
+ MLAN_MAC_ADDR_LENGTH)) {
+ PRINTM(MINFO,
+ "Dropping mgmt frame from others: type=%d " MACSTR
+ "\n",
+ sub_type,
+ MAC2STR(pieee_pkt_hdr->addr2));
+ LEAVE();
+ return ret;
+ }
+ PRINTM_NETINTF(MMSG, priv);
+ PRINTM(MMSG,
+ "wlan: HostMlme Disconnected: sub_type=%d\n",
+ sub_type);
+ pmadapter->pending_disconnect_priv = priv;
+ wlan_recv_event(
+ priv, MLAN_EVENT_ID_DRV_DEFER_HANDLING,
+ MNULL);
+ }
+ }
+ break;
+ case SUBTYPE_ACTION:
+ category = *(payload + sizeof(wlan_802_11_header));
+ action_code = *(payload + sizeof(wlan_802_11_header) + 1);
+ if (category == IEEE_MGMT_ACTION_CATEGORY_BLOCK_ACK) {
+ PRINTM(MINFO,
+ "Drop BLOCK ACK action frame: action_code=%d\n",
+ action_code);
+ LEAVE();
+ return ret;
+ }
+ if ((category == IEEE_MGMT_ACTION_CATEGORY_PUBLIC) &&
+ (action_code == BSS_20_40_COEX)) {
+ PRINTM(MINFO,
+ "Drop 20/40 BSS Coexistence Management frame\n");
+ LEAVE();
+ return ret;
+ }
+ if (memcmp(pmadapter, pieee_pkt_hdr->addr1, broadcast,
+ MLAN_MAC_ADDR_LENGTH))
+ unicast = MTRUE;
+ break;
+ default:
+ break;
+ }
+ if (unicast == MTRUE) {
+ if (memcmp(pmadapter, pieee_pkt_hdr->addr1, priv->curr_addr,
+ MLAN_MAC_ADDR_LENGTH)) {
+ PRINTM(MINFO,
+ "Dropping mgmt frame for others: type=%d " MACSTR
+ "\n",
+ sub_type, MAC2STR(pieee_pkt_hdr->addr1));
+ LEAVE();
+ return ret;
+ }
+ }
+ /* Allocate memory for event buffer */
+ ret = pcb->moal_malloc(pmadapter->pmoal_handle, MAX_EVENT_SIZE,
+ MLAN_MEM_DEF, &event_buf);
+ if ((ret != MLAN_STATUS_SUCCESS) || !event_buf) {
+ PRINTM(MERROR, "Could not allocate buffer for event buf\n");
+ LEAVE();
+ return MLAN_STATUS_FAILURE;
+ }
+ pevent = (pmlan_event)event_buf;
+ pevent->bss_index = priv->bss_index;
+ mgmt = (IEEE80211_MGMT *)payload;
+ if (!priv->curr_bss_params.host_mlme && sub_type == SUBTYPE_ACTION &&
+ mgmt->u.ft_resp.category == FT_CATEGORY &&
+ mgmt->u.ft_resp.action == FT_ACTION_RESPONSE &&
+ mgmt->u.ft_resp.status_code == 0) {
+ PRINTM(MCMND, "FT Action response received\n");
+#define FT_ACTION_HEAD_LEN (24 + 6 + 16)
+ pevent->event_id = MLAN_EVENT_ID_DRV_FT_RESPONSE;
+ pevent->event_len =
+ payload_len + MLAN_MAC_ADDR_LENGTH - FT_ACTION_HEAD_LEN;
+ memcpy_ext(pmadapter, (t_u8 *)pevent->event_buf,
+ &mgmt->u.ft_resp.target_ap_addr,
+ MLAN_MAC_ADDR_LENGTH, MLAN_MAC_ADDR_LENGTH);
+ memcpy_ext(pmadapter,
+ (t_u8 *)(pevent->event_buf + MLAN_MAC_ADDR_LENGTH),
+ payload + FT_ACTION_HEAD_LEN,
+ payload_len - FT_ACTION_HEAD_LEN,
+ pevent->event_len - MLAN_MAC_ADDR_LENGTH);
+ } else if (!priv->curr_bss_params.host_mlme &&
+ sub_type == SUBTYPE_AUTH &&
+ mgmt->u.auth.auth_alg == MLAN_AUTH_MODE_FT &&
+ mgmt->u.auth.auth_transaction == 2 &&
+ mgmt->u.auth.status_code == 0) {
+ PRINTM(MCMND, "FT auth response received \n");
+#define AUTH_PACKET_LEN (24 + 6 + 6)
+ pevent->event_id = MLAN_EVENT_ID_DRV_FT_RESPONSE;
+ pevent->event_len =
+ payload_len + MLAN_MAC_ADDR_LENGTH - AUTH_PACKET_LEN;
+ memcpy_ext(pmadapter, (t_u8 *)pevent->event_buf, mgmt->sa,
+ MLAN_MAC_ADDR_LENGTH, MLAN_MAC_ADDR_LENGTH);
+ memcpy_ext(pmadapter,
+ (t_u8 *)(pevent->event_buf + MLAN_MAC_ADDR_LENGTH),
+ payload + AUTH_PACKET_LEN,
+ payload_len - AUTH_PACKET_LEN,
+ pevent->event_len - MLAN_MAC_ADDR_LENGTH);
+ } else {
+ pevent->event_id = MLAN_EVENT_ID_DRV_MGMT_FRAME;
+ pevent->event_len = payload_len + sizeof(pevent->event_id);
+ memcpy_ext(pmadapter, (t_u8 *)pevent->event_buf,
+ (t_u8 *)&pevent->event_id, sizeof(pevent->event_id),
+ pevent->event_len);
+ memcpy_ext(
+ pmadapter,
+ (t_u8 *)(pevent->event_buf + sizeof(pevent->event_id)),
+ payload, payload_len, payload_len);
+ }
+ wlan_recv_event(priv, pevent->event_id, pevent);
+ if (event_buf)
+ pcb->moal_mfree(pmadapter->pmoal_handle, event_buf);
+ LEAVE();
+ return MLAN_STATUS_SUCCESS;
+}
+
+#ifdef STA_SUPPORT
+/**
+ * @brief Extended capabilities configuration
+ *
+ * @param pmadapter A pointer to mlan_adapter structure
+ * @param pioctl_req A pointer to ioctl request buffer
+ *
+ * @return MLAN_STATUS_PENDING --success, otherwise fail
+ */
+mlan_status wlan_misc_ext_capa_cfg(pmlan_adapter pmadapter,
+ pmlan_ioctl_req pioctl_req)
+{
+ pmlan_private pmpriv = pmadapter->priv[pioctl_req->bss_index];
+ mlan_ds_misc_cfg *misc = (mlan_ds_misc_cfg *)pioctl_req->pbuf;
+ mlan_status ret = MLAN_STATUS_SUCCESS;
+
+ ENTER();
+
+ if (MLAN_ACT_GET == pioctl_req->action)
+ memcpy_ext(pmpriv->adapter, &misc->param.ext_cap,
+ &pmpriv->def_ext_cap, sizeof(misc->param.ext_cap),
+ sizeof(misc->param.ext_cap));
+ else if (MLAN_ACT_SET == pioctl_req->action) {
+ memcpy_ext(pmpriv->adapter, &pmpriv->ext_cap,
+ &misc->param.ext_cap, sizeof(misc->param.ext_cap),
+ sizeof(pmpriv->ext_cap));
+ /* Save default Extended Capability */
+ memcpy_ext(pmpriv->adapter, &pmpriv->def_ext_cap,
+ &pmpriv->ext_cap, sizeof(pmpriv->ext_cap),
+ sizeof(pmpriv->def_ext_cap));
+ if (pmpriv->config_bands & BAND_AAC)
+ SET_EXTCAP_OPERMODENTF(pmpriv->ext_cap);
+ }
+
+ LEAVE();
+ return ret;
+}
+
+/**
+ * @brief Check whether Extended Capabilities IE support
+ *
+ * @param pmpriv A pointer to mlan_private structure
+ *
+ * @return MTRUE or MFALSE;
+ */
+t_u32 wlan_is_ext_capa_support(mlan_private *pmpriv)
+{
+ ENTER();
+
+ if (ISSUPP_EXTCAP_TDLS(pmpriv->ext_cap) ||
+ ISSUPP_EXTCAP_INTERWORKING(pmpriv->ext_cap) ||
+ ISSUPP_EXTCAP_BSS_TRANSITION(pmpriv->ext_cap) ||
+ ISSUPP_EXTCAP_QOS_MAP(pmpriv->ext_cap) ||
+ ISSUPP_EXTCAP_OPERMODENTF(pmpriv->ext_cap)) {
+ LEAVE();
+ return MTRUE;
+ } else {
+ LEAVE();
+ return MFALSE;
+ }
+}
+#endif
+
+/**
+ * @brief Set hotspot enable/disable
+ *
+ * @param pmadapter A pointer to mlan_adapter structure
+ * @param pioctl_req A pointer to ioctl request buffer
+ *
+ * @return MLAN_STATUS_PENDING --success, otherwise fail
+ */
+mlan_status wlan_misc_hotspot_cfg(pmlan_adapter pmadapter,
+ pmlan_ioctl_req pioctl_req)
+{
+ pmlan_private pmpriv = pmadapter->priv[pioctl_req->bss_index];
+ mlan_ds_misc_cfg *misc = (mlan_ds_misc_cfg *)pioctl_req->pbuf;
+ mlan_status ret = MLAN_STATUS_SUCCESS;
+
+ ENTER();
+
+ if (MLAN_ACT_GET == pioctl_req->action)
+ misc->param.hotspot_cfg = pmpriv->hotspot_cfg;
+ else if (MLAN_ACT_SET == pioctl_req->action)
+ pmpriv->hotspot_cfg = misc->param.hotspot_cfg;
+
+ LEAVE();
+ return ret;
+}
+
+#ifdef STA_SUPPORT
+/**
+ * @brief Add Extended Capabilities IE
+ *
+ * @param pmpriv A pointer to mlan_private structure
+ * @param pbss_desc A pointer to BSSDescriptor_t structure
+ * @param pptlv_out A pointer to TLV to fill in
+ *
+ * @return N/A
+ */
+void wlan_add_ext_capa_info_ie(mlan_private *pmpriv, BSSDescriptor_t *pbss_desc,
+ t_u8 **pptlv_out)
+{
+ MrvlIETypes_ExtCap_t *pext_cap = MNULL;
+
+ ENTER();
+
+ pext_cap = (MrvlIETypes_ExtCap_t *)*pptlv_out;
+ memset(pmpriv->adapter, pext_cap, 0, sizeof(MrvlIETypes_ExtCap_t));
+ pext_cap->header.type = wlan_cpu_to_le16(EXT_CAPABILITY);
+ pext_cap->header.len = wlan_cpu_to_le16(sizeof(ExtCap_t));
+ if (pmpriv->adapter->ecsa_enable)
+ SET_EXTCAP_EXT_CHANNEL_SWITCH(pmpriv->ext_cap);
+ else
+ RESET_EXTCAP_EXT_CHANNEL_SWITCH(pmpriv->ext_cap);
+ if (wlan_check_11ax_twt_supported(pmpriv, pbss_desc))
+ SET_EXTCAP_TWT_REQ(pmpriv->ext_cap);
+ memcpy_ext(pmpriv->adapter, &pext_cap->ext_cap, &pmpriv->ext_cap,
+ sizeof(pmpriv->ext_cap), sizeof(pext_cap->ext_cap));
+ *pptlv_out += sizeof(MrvlIETypes_ExtCap_t);
+
+ LEAVE();
+}
+#endif
+
+/**
+ * @brief Get OTP user data
+ *
+ * @param pmadapter A pointer to mlan_adapter structure
+ * @param pioctl_req A pointer to ioctl request buffer
+ *
+ * @return MLAN_STATUS_PENDING --success, otherwise fail
+ */
+mlan_status wlan_misc_otp_user_data(pmlan_adapter pmadapter,
+ pmlan_ioctl_req pioctl_req)
+{
+ pmlan_private pmpriv = pmadapter->priv[pioctl_req->bss_index];
+ mlan_ds_misc_cfg *misc = (mlan_ds_misc_cfg *)pioctl_req->pbuf;
+ mlan_status ret = MLAN_STATUS_FAILURE;
+
+ ENTER();
+
+ if (misc->param.otp_user_data.user_data_length >
+ MAX_OTP_USER_DATA_LEN) {
+ PRINTM(MERROR, "Invalid OTP user data length\n");
+ pioctl_req->status_code = MLAN_ERROR_INVALID_PARAMETER;
+ LEAVE();
+ return ret;
+ }
+
+ ret = wlan_prepare_cmd(pmpriv, HostCmd_CMD_OTP_READ_USER_DATA,
+ HostCmd_ACT_GEN_GET, 0, (t_void *)pioctl_req,
+ &misc->param.otp_user_data);
+
+ if (ret == MLAN_STATUS_SUCCESS)
+ ret = MLAN_STATUS_PENDING;
+
+ LEAVE();
+ return ret;
+}
+
+/**
+ * @brief This function will search for the specific ie
+ *
+ * @param priv A pointer to mlan_private
+ * @param pevent A pointer to event buf
+ * @param sta_ptr A pointer to sta_node
+ *
+ * @return N/A
+ */
+void wlan_check_sta_capability(pmlan_private priv, pmlan_buffer pevent,
+ sta_node *sta_ptr)
+{
+ t_u16 tlv_type, tlv_len;
+ t_u16 frame_control, frame_sub_type = 0;
+ t_u8 *assoc_req_ie = MNULL;
+ t_u8 ie_len = 0, assoc_ie_len = 0;
+ IEEEtypes_HTCap_t *pht_cap = MNULL;
+ IEEEtypes_VHTCap_t *pvht_cap = MNULL;
+ IEEEtypes_Extension_t *phe_cap = MNULL;
+#ifdef UAP_SUPPORT
+ t_u8 *ext_rate = MNULL, *erp = MNULL;
+#endif
+
+ int tlv_buf_left = pevent->data_len - ASSOC_EVENT_FIX_SIZE;
+ MrvlIEtypesHeader_t *tlv =
+ (MrvlIEtypesHeader_t *)(pevent->pbuf + pevent->data_offset +
+ ASSOC_EVENT_FIX_SIZE);
+ MrvlIETypes_MgmtFrameSet_t *mgmt_tlv = MNULL;
+
+ ENTER();
+ while (tlv_buf_left >= (int)sizeof(MrvlIEtypesHeader_t)) {
+ tlv_type = wlan_le16_to_cpu(tlv->type);
+ tlv_len = wlan_le16_to_cpu(tlv->len);
+ if ((sizeof(MrvlIEtypesHeader_t) + tlv_len) >
+ (unsigned int)tlv_buf_left) {
+ PRINTM(MERROR, "wrong tlv: tlvLen=%d, tlvBufLeft=%d\n",
+ tlv_len, tlv_buf_left);
+ break;
+ }
+ if (tlv_type == TLV_TYPE_MGMT_FRAME) {
+ mgmt_tlv = (MrvlIETypes_MgmtFrameSet_t *)tlv;
+ memcpy_ext(priv->adapter, &frame_control,
+ (t_u8 *)&(mgmt_tlv->frame_control),
+ sizeof(frame_control),
+ sizeof(frame_control));
+ frame_sub_type = IEEE80211_GET_FC_MGMT_FRAME_SUBTYPE(
+ frame_control);
+ if ((mgmt_tlv->frame_control.type == 0) &&
+ ((frame_sub_type == SUBTYPE_BEACON)
+#ifdef UAP_SUPPORT
+ || (frame_sub_type == SUBTYPE_ASSOC_REQUEST) ||
+ (frame_sub_type == SUBTYPE_REASSOC_REQUEST)
+#endif
+ )) {
+ if (frame_sub_type == SUBTYPE_BEACON)
+ assoc_ie_len =
+ sizeof(IEEEtypes_Beacon_t);
+#ifdef UAP_SUPPORT
+ else if (frame_sub_type ==
+ SUBTYPE_ASSOC_REQUEST)
+ assoc_ie_len =
+ sizeof(IEEEtypes_AssocRqst_t);
+ else if (frame_sub_type ==
+ SUBTYPE_REASSOC_REQUEST)
+ assoc_ie_len =
+ sizeof(IEEEtypes_ReAssocRqst_t);
+#endif
+ ie_len = tlv_len -
+ sizeof(IEEEtypes_FrameCtl_t) -
+ assoc_ie_len;
+ assoc_req_ie =
+ (t_u8 *)tlv +
+ sizeof(MrvlIETypes_MgmtFrameSet_t) +
+ assoc_ie_len;
+ sta_ptr->is_wmm_enabled =
+ wlan_is_wmm_ie_present(priv->adapter,
+ assoc_req_ie,
+ ie_len);
+ PRINTM(MCMND, "STA: is_wmm_enabled=%d\n",
+ sta_ptr->is_wmm_enabled);
+ pht_cap = (IEEEtypes_HTCap_t *)
+ wlan_get_specific_ie(priv, assoc_req_ie,
+ ie_len,
+ HT_CAPABILITY, 0);
+ if (pht_cap) {
+ PRINTM(MCMND, "STA supports 11n\n");
+ sta_ptr->is_11n_enabled = MTRUE;
+ memcpy_ext(priv->adapter,
+ (t_u8 *)&sta_ptr->HTcap,
+ pht_cap,
+ sizeof(IEEEtypes_HTCap_t),
+ sizeof(IEEEtypes_HTCap_t));
+ if (GETHT_MAXAMSDU(wlan_le16_to_cpu(
+ pht_cap->ht_cap
+ .ht_cap_info)))
+ sta_ptr->max_amsdu =
+ MLAN_TX_DATA_BUF_SIZE_8K;
+ else
+ sta_ptr->max_amsdu =
+ MLAN_TX_DATA_BUF_SIZE_4K;
+ } else {
+ PRINTM(MCMND,
+ "STA doesn't support 11n\n");
+ }
+ pvht_cap = (IEEEtypes_VHTCap_t *)
+ wlan_get_specific_ie(priv, assoc_req_ie,
+ ie_len,
+ VHT_CAPABILITY, 0);
+ if (pvht_cap &&
+ (priv->is_11ac_enabled == MTRUE)) {
+ PRINTM(MCMND, "STA supports 11ac\n");
+ sta_ptr->is_11ac_enabled = MTRUE;
+ if (GET_VHTCAP_MAXMPDULEN(wlan_le32_to_cpu(
+ pvht_cap->vht_cap
+ .vht_cap_info)) ==
+ 2)
+ sta_ptr->max_amsdu =
+ MLAN_TX_DATA_BUF_SIZE_12K;
+ else if (GET_VHTCAP_MAXMPDULEN(wlan_le32_to_cpu(
+ pvht_cap->vht_cap
+ .vht_cap_info)) ==
+ 1)
+ sta_ptr->max_amsdu =
+ MLAN_TX_DATA_BUF_SIZE_8K;
+ else
+ sta_ptr->max_amsdu =
+ MLAN_TX_DATA_BUF_SIZE_4K;
+ } else {
+ PRINTM(MCMND,
+ "STA doesn't support 11ac\n");
+ }
+ phe_cap = (IEEEtypes_Extension_t *)
+ wlan_get_specific_ie(priv, assoc_req_ie,
+ ie_len, EXTENSION,
+ HE_CAPABILITY);
+ if (phe_cap &&
+ (priv->is_11ax_enabled == MTRUE)) {
+ PRINTM(MCMND, "STA supports 11ax\n");
+ sta_ptr->is_11ax_enabled = MTRUE;
+ } else {
+ PRINTM(MCMND,
+ "STA doesn't support 11ax\n");
+ }
+#ifdef UAP_SUPPORT
+ /* Note: iphone6 does not have ERP_INFO */
+ ext_rate = wlan_get_specific_ie(
+ priv, assoc_req_ie, ie_len,
+ EXTENDED_SUPPORTED_RATES, 0);
+ erp = wlan_get_specific_ie(priv, assoc_req_ie,
+ ie_len, ERP_INFO, 0);
+ if (!ext_rate)
+ PRINTM(MCMND,
+ "STA doesn't support EXTENDED_SUPPORTED_RATES\n");
+ if (!erp)
+ PRINTM(MCMND,
+ "STA doesn't support ERP_INFO\n");
+ if (sta_ptr->is_11ax_enabled) {
+ if (priv->uap_channel <= 14)
+ sta_ptr->bandmode = BAND_GAX;
+ else
+ sta_ptr->bandmode = BAND_AAX;
+ } else if (sta_ptr->is_11ac_enabled) {
+ if (priv->uap_channel <= 14)
+ sta_ptr->bandmode = BAND_GAC;
+ else
+ sta_ptr->bandmode = BAND_AAC;
+ } else if (sta_ptr->is_11n_enabled) {
+ if (priv->uap_channel <= 14)
+ sta_ptr->bandmode = BAND_GN;
+ else
+ sta_ptr->bandmode = BAND_AN;
+ } else if (ext_rate || erp) {
+ if (priv->uap_channel <= 14)
+ sta_ptr->bandmode = BAND_G;
+ else
+ sta_ptr->bandmode = BAND_A;
+ } else
+ sta_ptr->bandmode = BAND_B;
+#endif
+#ifdef DRV_EMBEDDED_AUTHENTICATOR
+ if (IsAuthenticatorEnabled(priv->psapriv))
+ authenticator_get_sta_security_info(
+ priv->psapriv,
+ sta_ptr->cm_connectioninfo,
+ assoc_req_ie, ie_len);
+#endif
+ break;
+ }
+ }
+ tlv_buf_left -= (sizeof(MrvlIEtypesHeader_t) + tlv_len);
+ tlv = (MrvlIEtypesHeader_t *)((t_u8 *)tlv + tlv_len +
+ sizeof(MrvlIEtypesHeader_t));
+ }
+ LEAVE();
+
+ return;
+}
+
+/**
+ * @brief check if WMM ie present.
+ *
+ * @param pmadapter A pointer to mlan_adapter structure
+ * @param pbuf A pointer to IE buffer
+ * @param buf_len IE buffer len
+ *
+ * @return MTRUE/MFALSE
+ */
+t_u8 wlan_is_wmm_ie_present(pmlan_adapter pmadapter, t_u8 *pbuf, t_u16 buf_len)
+{
+ t_u16 bytes_left = buf_len;
+ IEEEtypes_ElementId_e element_id;
+ t_u8 *pcurrent_ptr = pbuf;
+ t_u8 element_len;
+ t_u16 total_ie_len;
+ IEEEtypes_VendorSpecific_t *pvendor_ie;
+ const t_u8 wmm_oui[4] = {0x00, 0x50, 0xf2, 0x02};
+ t_u8 find_wmm_ie = MFALSE;
+
+ ENTER();
+
+ /* Process variable IE */
+ while (bytes_left >= 2) {
+ element_id = (IEEEtypes_ElementId_e)(*((t_u8 *)pcurrent_ptr));
+ element_len = *((t_u8 *)pcurrent_ptr + 1);
+ total_ie_len = element_len + sizeof(IEEEtypes_Header_t);
+
+ if (bytes_left < total_ie_len) {
+ PRINTM(MERROR, "InterpretIE: Error in processing IE, "
+ "bytes left < IE length\n");
+ bytes_left = 0;
+ continue;
+ }
+ switch (element_id) {
+ case VENDOR_SPECIFIC_221:
+ pvendor_ie = (IEEEtypes_VendorSpecific_t *)pcurrent_ptr;
+ if (!memcmp(pmadapter, pvendor_ie->vend_hdr.oui,
+ wmm_oui, sizeof(wmm_oui))) {
+ find_wmm_ie = MTRUE;
+ PRINTM(MINFO, "find WMM IE\n");
+ }
+ break;
+ default:
+ break;
+ }
+ pcurrent_ptr += element_len + 2;
+ /* Need to account for IE ID and IE Len */
+ bytes_left -= (element_len + 2);
+ if (find_wmm_ie)
+ break;
+ }
+
+ LEAVE();
+ return find_wmm_ie;
+}
+
+/**
+ * @brief This function will search for the specific ie
+ *
+ *
+ * @param priv A pointer to mlan_private
+ * @param ie_buf A pointer to ie_buf
+ * @param ie_len total ie length
+ * @param id ie's id
+ * @param ext_id ie's extension id
+ *
+ * @return ie's poiner or MNULL
+ */
+t_u8 *wlan_get_specific_ie(pmlan_private priv, t_u8 *ie_buf, t_u8 ie_len,
+ IEEEtypes_ElementId_e id, t_u8 ext_id)
+{
+ t_u32 bytes_left = ie_len;
+ t_u8 *pcurrent_ptr = ie_buf;
+ t_u16 total_ie_len;
+ t_u8 *ie_ptr = MNULL;
+ IEEEtypes_ElementId_e element_id;
+ t_u8 element_len;
+ t_u8 element_eid;
+
+ ENTER();
+
+ DBG_HEXDUMP(MDAT_D, "ie", ie_buf, ie_len);
+ while (bytes_left >= 2) {
+ element_id = (IEEEtypes_ElementId_e)(*((t_u8 *)pcurrent_ptr));
+ element_len = *((t_u8 *)pcurrent_ptr + 1);
+ element_eid = *((t_u8 *)pcurrent_ptr + 2);
+ total_ie_len = element_len + sizeof(IEEEtypes_Header_t);
+ if (bytes_left < total_ie_len) {
+ PRINTM(MERROR, "InterpretIE: Error in processing IE, "
+ "bytes left < IE length\n");
+ break;
+ }
+ if ((!ext_id && element_id == id) ||
+ (id == EXTENSION && element_id == id &&
+ ext_id == element_eid)) {
+ PRINTM(MCMND, "Find IE: id=%d ext_id=%d\n", id, ext_id);
+ DBG_HEXDUMP(MCMD_D, "IE", pcurrent_ptr, total_ie_len);
+ ie_ptr = pcurrent_ptr;
+ break;
+ }
+ pcurrent_ptr += element_len + 2;
+ /* Need to account for IE ID and IE Len */
+ bytes_left -= (element_len + 2);
+ }
+
+ LEAVE();
+
+ return ie_ptr;
+}
+
+/**
+ * @brief Get pm info
+ *
+ * @param pmadapter A pointer to mlan_adapter structure
+ * @param pioctl_req A pointer to ioctl request buffer
+ *
+ * @return MLAN_STATUS_SUCCESS --success
+ */
+mlan_status wlan_get_pm_info(pmlan_adapter pmadapter,
+ pmlan_ioctl_req pioctl_req)
+{
+ mlan_status ret = MLAN_STATUS_SUCCESS;
+ mlan_ds_pm_cfg *pm_cfg = MNULL;
+
+ ENTER();
+
+ pm_cfg = (mlan_ds_pm_cfg *)pioctl_req->pbuf;
+ pm_cfg->param.ps_info.is_suspend_allowed = MTRUE;
+ wlan_request_cmd_lock(pmadapter);
+ if (util_peek_list(pmadapter->pmoal_handle, &pmadapter->cmd_pending_q,
+ MNULL, MNULL) ||
+ pmadapter->curr_cmd || !wlan_bypass_tx_list_empty(pmadapter) ||
+ !wlan_wmm_lists_empty(pmadapter)
+#if defined(SDIO) || defined(PCIE)
+ || wlan_pending_interrupt(pmadapter)
+#endif
+ ) {
+ pm_cfg->param.ps_info.is_suspend_allowed = MFALSE;
+#if defined(SDIO) || defined(PCIE)
+ PRINTM(MIOCTL,
+ "PM: cmd_pending_q=%p,curr_cmd=%p,wmm_list_empty=%d, by_pass=%d irq_pending=%d\n",
+ util_peek_list(pmadapter->pmoal_handle,
+ &pmadapter->cmd_pending_q, MNULL, MNULL),
+ pmadapter->curr_cmd, wlan_wmm_lists_empty(pmadapter),
+ wlan_bypass_tx_list_empty(pmadapter),
+ wlan_pending_interrupt(pmadapter));
+#else
+ PRINTM(MIOCTL,
+ "PM: cmd_pending_q=%p,curr_cmd=%p,wmm_list_empty=%d, by_pass=%d\n",
+ util_peek_list(pmadapter->pmoal_handle,
+ &pmadapter->cmd_pending_q, MNULL, MNULL),
+ pmadapter->curr_cmd, wlan_wmm_lists_empty(pmadapter),
+ wlan_bypass_tx_list_empty(pmadapter));
+#endif
+ }
+ wlan_release_cmd_lock(pmadapter);
+ LEAVE();
+ return ret;
+}
+
+/**
+ * @brief Get hs wakeup reason
+ *
+ * @param pmadapter A pointer to mlan_adapter structure
+ * @param pioctl_req A pointer to ioctl request buffer
+ *
+ * @return MLAN_STATUS_SUCCESS --success
+ */
+mlan_status wlan_get_hs_wakeup_reason(pmlan_adapter pmadapter,
+ pmlan_ioctl_req pioctl_req)
+{
+ pmlan_private pmpriv = pmadapter->priv[pioctl_req->bss_index];
+ pmlan_ds_pm_cfg pm_cfg = MNULL;
+ mlan_status ret = MLAN_STATUS_FAILURE;
+
+ ENTER();
+
+ pm_cfg = (mlan_ds_pm_cfg *)pioctl_req->pbuf;
+
+ /* Send command to firmware */
+ ret = wlan_prepare_cmd(pmpriv, HostCmd_CMD_HS_WAKEUP_REASON,
+ HostCmd_ACT_GEN_GET, 0, (t_void *)pioctl_req,
+ &pm_cfg->param.wakeup_reason);
+
+ if (ret == MLAN_STATUS_SUCCESS)
+ ret = MLAN_STATUS_PENDING;
+
+ LEAVE();
+ return ret;
+}
+
+/**
+ * @brief Set/Get radio status
+ *
+ * @param pmadapter A pointer to mlan_adapter structure
+ * @param pioctl_req A pointer to ioctl request buffer
+ *
+ * @return MLAN_STATUS_SUCCESS --success, otherwise fail
+ */
+mlan_status wlan_radio_ioctl_radio_ctl(pmlan_adapter pmadapter,
+ pmlan_ioctl_req pioctl_req)
+{
+ mlan_status ret = MLAN_STATUS_SUCCESS;
+ mlan_ds_radio_cfg *radio_cfg = MNULL;
+ t_u16 cmd_action = 0;
+ mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index];
+
+ ENTER();
+
+ radio_cfg = (mlan_ds_radio_cfg *)pioctl_req->pbuf;
+ if (pioctl_req->action == MLAN_ACT_SET) {
+ if (pmadapter->radio_on == radio_cfg->param.radio_on_off) {
+ ret = MLAN_STATUS_SUCCESS;
+ goto exit;
+ } else {
+ if (pmpriv->media_connected == MTRUE) {
+ ret = MLAN_STATUS_FAILURE;
+ goto exit;
+ }
+ cmd_action = HostCmd_ACT_GEN_SET;
+ }
+ } else
+ cmd_action = HostCmd_ACT_GEN_GET;
+
+ /* Send request to firmware */
+ ret = wlan_prepare_cmd(pmpriv, HostCmd_CMD_802_11_RADIO_CONTROL,
+ cmd_action, 0, (t_void *)pioctl_req,
+ &radio_cfg->param.radio_on_off);
+
+ if (ret == MLAN_STATUS_SUCCESS)
+ ret = MLAN_STATUS_PENDING;
+
+exit:
+ LEAVE();
+ return ret;
+}
+
+/**
+ * @brief Set/Get antenna configuration
+ *
+ * @param pmadapter A pointer to mlan_adapter structure
+ * @param pioctl_req A pointer to ioctl request buffer
+ *
+ * @return MLAN_STATUS_PENDING --success, otherwise fail
+ */
+mlan_status wlan_radio_ioctl_ant_cfg(pmlan_adapter pmadapter,
+ pmlan_ioctl_req pioctl_req)
+{
+ mlan_status ret = MLAN_STATUS_SUCCESS;
+ mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index];
+ mlan_ds_radio_cfg *radio_cfg = MNULL;
+ t_u16 cmd_action = 0;
+ mlan_ds_ant_cfg *ant_cfg = MNULL;
+ mlan_ds_ant_cfg_1x1 *ant_cfg_1x1 = MNULL;
+
+ ENTER();
+
+ radio_cfg = (mlan_ds_radio_cfg *)pioctl_req->pbuf;
+ if (IS_STREAM_2X2(pmadapter->feature_control))
+ ant_cfg = &radio_cfg->param.ant_cfg;
+
+ if (pioctl_req->action == MLAN_ACT_SET) {
+ /* User input validation */
+ if (IS_STREAM_2X2(pmadapter->feature_control)) {
+#if defined(PCIE9098) || defined(SD9098) || defined(USB9098) || \
+ defined(PCIE9097) || defined(SD9097) || defined(USB9097)
+ if (IS_CARD9098(pmadapter->card_type) ||
+ IS_CARD9097(pmadapter->card_type)) {
+ ant_cfg->tx_antenna &= 0x0303;
+ ant_cfg->rx_antenna &= 0x0303;
+ /** 2G antcfg TX */
+ if (ant_cfg->tx_antenna & 0x00FF) {
+ pmadapter->user_htstream &= ~0xF0;
+ pmadapter->user_htstream |=
+ (bitcount(ant_cfg->tx_antenna &
+ 0x00FF)
+ << 4);
+ }
+ /* 5G antcfg tx */
+ if (ant_cfg->tx_antenna & 0xFF00) {
+ pmadapter->user_htstream &= ~0xF000;
+ pmadapter->user_htstream |=
+ (bitcount(ant_cfg->tx_antenna &
+ 0xFF00)
+ << 12);
+ }
+ /* 2G antcfg RX */
+ if (ant_cfg->rx_antenna & 0x00FF) {
+ pmadapter->user_htstream &= ~0xF;
+ pmadapter->user_htstream |= bitcount(
+ ant_cfg->rx_antenna & 0x00FF);
+ }
+ /* 5G antcfg RX */
+ if (ant_cfg->rx_antenna & 0xFF00) {
+ pmadapter->user_htstream &= ~0xF00;
+ pmadapter->user_htstream |=
+ (bitcount(ant_cfg->rx_antenna &
+ 0xFF00)
+ << 8);
+ }
+ PRINTM(MCMND,
+ "user_htstream=0x%x, tx_antenna=0x%x >rx_antenna=0x%x\n",
+ pmadapter->user_htstream,
+ ant_cfg->tx_antenna,
+ ant_cfg->rx_antenna);
+ } else {
+#endif
+
+ ant_cfg->tx_antenna &= 0x0003;
+ ant_cfg->rx_antenna &= 0x0003;
+#if defined(PCIE9098) || defined(SD9098) || defined(USB9098) || \
+ defined(PCIE9097) || defined(SD9097) || defined(USB9097)
+ }
+#endif
+ if (!ant_cfg->tx_antenna ||
+ bitcount(ant_cfg->tx_antenna & 0x00FF) >
+ pmadapter->number_of_antenna ||
+ bitcount(ant_cfg->tx_antenna & 0xFF00) >
+ pmadapter->number_of_antenna) {
+ PRINTM(MERROR,
+ "Invalid TX antenna setting: 0x%x\n",
+ ant_cfg->tx_antenna);
+ pioctl_req->status_code =
+ MLAN_ERROR_INVALID_PARAMETER;
+ ret = MLAN_STATUS_FAILURE;
+ goto exit;
+ }
+ if (ant_cfg->rx_antenna) {
+ if (bitcount(ant_cfg->rx_antenna & 0x00FF) >
+ pmadapter->number_of_antenna ||
+ bitcount(ant_cfg->rx_antenna & 0xFF00) >
+ pmadapter->number_of_antenna) {
+ PRINTM(MERROR,
+ "Invalid RX antenna setting: 0x%x\n",
+ ant_cfg->rx_antenna);
+ pioctl_req->status_code =
+ MLAN_ERROR_INVALID_PARAMETER;
+ ret = MLAN_STATUS_FAILURE;
+ goto exit;
+ }
+ } else
+ ant_cfg->rx_antenna = ant_cfg->tx_antenna;
+ } else if (!radio_cfg->param.ant_cfg_1x1.antenna ||
+ ((radio_cfg->param.ant_cfg_1x1.antenna !=
+ RF_ANTENNA_AUTO) &&
+ (radio_cfg->param.ant_cfg_1x1.antenna & 0xFFFC))) {
+ PRINTM(MERROR, "Invalid antenna setting\n");
+ pioctl_req->status_code = MLAN_ERROR_INVALID_PARAMETER;
+ ret = MLAN_STATUS_FAILURE;
+ goto exit;
+ }
+ cmd_action = HostCmd_ACT_GEN_SET;
+ } else
+ cmd_action = HostCmd_ACT_GEN_GET;
+
+ /* Cast it to t_u16, antenna mode for command
+ * HostCmd_CMD_802_11_RF_ANTENNA requires 2 bytes */
+ if (!IS_STREAM_2X2(pmadapter->feature_control))
+ ant_cfg_1x1 = &radio_cfg->param.ant_cfg_1x1;
+
+ /* Send request to firmware */
+ ret = wlan_prepare_cmd(pmpriv, HostCmd_CMD_802_11_RF_ANTENNA,
+ cmd_action, 0, (t_void *)pioctl_req,
+ (IS_STREAM_2X2(pmadapter->feature_control)) ?
+ (t_void *)ant_cfg :
+ (t_void *)ant_cfg_1x1);
+
+ if (ret == MLAN_STATUS_SUCCESS)
+ ret = MLAN_STATUS_PENDING;
+
+exit:
+ LEAVE();
+ return ret;
+}
+
+/**
+ * @brief Get rate bitmap
+ *
+ * @param pmadapter A pointer to mlan_adapter structure
+ * @param pioctl_req A pointer to ioctl request buffer
+ *
+ * @return MLAN_STATUS_PENDING --success, otherwise fail
+ */
+static mlan_status wlan_rate_ioctl_get_rate_bitmap(pmlan_adapter pmadapter,
+ pmlan_ioctl_req pioctl_req)
+{
+ mlan_status ret = MLAN_STATUS_SUCCESS;
+ mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index];
+
+ ENTER();
+
+ /* Send request to firmware */
+ ret = wlan_prepare_cmd(pmpriv, HostCmd_CMD_TX_RATE_CFG,
+ HostCmd_ACT_GEN_GET, 0, (t_void *)pioctl_req,
+ MNULL);
+ if (ret == MLAN_STATUS_SUCCESS)
+ ret = MLAN_STATUS_PENDING;
+
+ LEAVE();
+ return ret;
+}
+
+/**
+ * @brief Set rate bitmap
+ *
+ * @param pmadapter A pointer to mlan_adapter structure
+ * @param pioctl_req A pointer to ioctl request buffer
+ *
+ * @return MLAN_STATUS_PENDING --success, otherwise fail
+ */
+static mlan_status wlan_rate_ioctl_set_rate_bitmap(pmlan_adapter pmadapter,
+ pmlan_ioctl_req pioctl_req)
+{
+ mlan_ds_rate *ds_rate = MNULL;
+ mlan_status ret = MLAN_STATUS_FAILURE;
+ mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index];
+ t_u16 *bitmap_rates = MNULL;
+
+ ENTER();
+
+ ds_rate = (mlan_ds_rate *)pioctl_req->pbuf;
+ bitmap_rates = ds_rate->param.rate_cfg.bitmap_rates;
+
+ PRINTM(MINFO,
+ "RateBitmap=%04x%04x%04x%04x%04x%04x%04x%04x"
+ "%04x%04x%04x%04x%04x%04x%04x%04x%04x%04x, "
+ "IsRateAuto=%d, DataRate=%d\n",
+ bitmap_rates[17], bitmap_rates[16], bitmap_rates[15],
+ bitmap_rates[14], bitmap_rates[13], bitmap_rates[12],
+ bitmap_rates[11], bitmap_rates[10], bitmap_rates[9],
+ bitmap_rates[8], bitmap_rates[7], bitmap_rates[6],
+ bitmap_rates[5], bitmap_rates[4], bitmap_rates[3],
+ bitmap_rates[2], bitmap_rates[1], bitmap_rates[0],
+ pmpriv->is_data_rate_auto, pmpriv->data_rate);
+
+ /* Send request to firmware */
+ ret = wlan_prepare_cmd(pmpriv, HostCmd_CMD_TX_RATE_CFG,
+ HostCmd_ACT_GEN_SET, 0, (t_void *)pioctl_req,
+ (t_void *)bitmap_rates);
+ if (ret == MLAN_STATUS_SUCCESS)
+ ret = MLAN_STATUS_PENDING;
+
+ LEAVE();
+ return ret;
+}
+
+/**
+ * @brief Get rate value
+ *
+ * @param pmadapter A pointer to mlan_adapter structure
+ * @param pioctl_req A pointer to ioctl request buffer
+ *
+ * @return MLAN_STATUS_SUCCESS/MLAN_STATUS_PENDING --success,
+ * otherwise fail
+ */
+static mlan_status wlan_rate_ioctl_get_rate_value(pmlan_adapter pmadapter,
+ pmlan_ioctl_req pioctl_req)
+{
+ mlan_ds_rate *rate = MNULL;
+ mlan_status ret = MLAN_STATUS_SUCCESS;
+ mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index];
+
+ ENTER();
+
+ rate = (mlan_ds_rate *)pioctl_req->pbuf;
+ rate->param.rate_cfg.is_rate_auto = pmpriv->is_data_rate_auto;
+ pioctl_req->data_read_written =
+ sizeof(mlan_rate_cfg_t) + MLAN_SUB_COMMAND_SIZE;
+
+ /* If not connected, set rate to the lowest in each band */
+ if (pmpriv->media_connected != MTRUE) {
+ if (pmpriv->config_bands & (BAND_B | BAND_G)) {
+ /* Return the lowest supported rate for BG band */
+ rate->param.rate_cfg.rate = SupportedRates_BG[0] & 0x7f;
+ } else if (pmpriv->config_bands & (BAND_A | BAND_B)) {
+ /* Return the lowest supported rate for A band */
+ rate->param.rate_cfg.rate = SupportedRates_BG[0] & 0x7f;
+ } else if (pmpriv->config_bands & BAND_A) {
+ /* Return the lowest supported rate for A band */
+ rate->param.rate_cfg.rate = SupportedRates_A[0] & 0x7f;
+ } else if (pmpriv->config_bands & BAND_G) {
+ /* Return the lowest supported rate for G band */
+ rate->param.rate_cfg.rate = SupportedRates_G[0] & 0x7f;
+ } else if (pmpriv->config_bands & BAND_B) {
+ /* Return the lowest supported rate for B band */
+ rate->param.rate_cfg.rate = SupportedRates_B[0] & 0x7f;
+ } else if (pmpriv->config_bands & BAND_GN) {
+ /* Return the lowest supported rate for N band */
+ rate->param.rate_cfg.rate = SupportedRates_N[0] & 0x7f;
+ } else {
+ PRINTM(MMSG, "Invalid Band 0x%x\n",
+ pmpriv->config_bands);
+ }
+
+ } else {
+ /* Send request to firmware */
+ ret = wlan_prepare_cmd(pmpriv, HostCmd_CMD_802_11_TX_RATE_QUERY,
+ HostCmd_ACT_GEN_GET, 0,
+ (t_void *)pioctl_req, MNULL);
+ if (ret == MLAN_STATUS_SUCCESS)
+ ret = MLAN_STATUS_PENDING;
+ }
+
+ LEAVE();
+ return ret;
+}
+
+/**
+ * @brief Set rate value
+ *
+ * @param pmadapter A pointer to mlan_adapter structure
+ * @param pioctl_req A pointer to ioctl request buffer
+ *
+ * @return MLAN_STATUS_PENDING --success, otherwise fail
+ */
+static mlan_status wlan_rate_ioctl_set_rate_value(pmlan_adapter pmadapter,
+ pmlan_ioctl_req pioctl_req)
+{
+ mlan_ds_rate *ds_rate = MNULL;
+ WLAN_802_11_RATES rates;
+ t_u8 *rate = MNULL;
+ int rate_index = 0;
+ t_u16 bitmap_rates[MAX_BITMAP_RATES_SIZE];
+ t_u32 i = 0;
+ mlan_status ret = MLAN_STATUS_SUCCESS;
+ mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index];
+
+ ENTER();
+
+ ds_rate = (mlan_ds_rate *)pioctl_req->pbuf;
+
+ if (ds_rate->param.rate_cfg.is_rate_auto) {
+ memset(pmadapter, bitmap_rates, 0, sizeof(bitmap_rates));
+ /* Support all HR/DSSS rates */
+ bitmap_rates[0] = 0x000F;
+ /* Support all OFDM rates */
+ bitmap_rates[1] = 0x00FF;
+ /* Rates talbe [0] HR/DSSS,[1] OFDM,[2..9] HT,[10..17] VHT */
+ /* Support all HT-MCSs rate */
+ for (i = 0; i < NELEMENTS(pmpriv->bitmap_rates) - 3 - 8; i++)
+ bitmap_rates[i + 2] = 0xFFFF;
+ bitmap_rates[9] = 0x3FFF;
+ /* Support all VHT-MCSs rate */
+ for (i = 0; i < NELEMENTS(pmpriv->bitmap_rates) - 10; i++)
+ bitmap_rates[i + 10] = 0x03FF; /* 10 Bits valid */
+ } else {
+ memset(pmadapter, rates, 0, sizeof(rates));
+ wlan_get_active_data_rates(pmpriv, pmpriv->bss_mode,
+ (pmpriv->bss_mode ==
+ MLAN_BSS_MODE_INFRA) ?
+ pmpriv->config_bands :
+ pmadapter->adhoc_start_band,
+ rates);
+ rate = rates;
+ for (i = 0; (rate[i] && i < WLAN_SUPPORTED_RATES); i++) {
+ PRINTM(MINFO, "Rate=0x%X Wanted=0x%X\n", rate[i],
+ ds_rate->param.rate_cfg.rate);
+ if ((rate[i] & 0x7f) ==
+ (ds_rate->param.rate_cfg.rate & 0x7f))
+ break;
+ }
+ if ((i < WLAN_SUPPORTED_RATES && !rate[i]) ||
+ (i == WLAN_SUPPORTED_RATES)) {
+ PRINTM(MERROR,
+ "The fixed data rate 0x%X is out "
+ "of range\n",
+ ds_rate->param.rate_cfg.rate);
+ pioctl_req->status_code = MLAN_ERROR_INVALID_PARAMETER;
+ ret = MLAN_STATUS_FAILURE;
+ goto exit;
+ }
+ memset(pmadapter, bitmap_rates, 0, sizeof(bitmap_rates));
+ rate_index = wlan_data_rate_to_index(
+ pmadapter, ds_rate->param.rate_cfg.rate);
+ /* Only allow b/g rates to be set */
+ if (rate_index >= MLAN_RATE_INDEX_HRDSSS0 &&
+ rate_index <= MLAN_RATE_INDEX_HRDSSS3)
+ bitmap_rates[0] = 1 << rate_index;
+ else {
+ rate_index -= 1; /* There is a 0x00 in the table */
+ if (rate_index >= MLAN_RATE_INDEX_OFDM0 &&
+ rate_index <= MLAN_RATE_INDEX_OFDM7)
+ bitmap_rates[1] = 1 << (rate_index -
+ MLAN_RATE_INDEX_OFDM0);
+ }
+ }
+
+ /* Send request to firmware */
+ ret = wlan_prepare_cmd(pmpriv, HostCmd_CMD_TX_RATE_CFG,
+ HostCmd_ACT_GEN_SET, 0, (t_void *)pioctl_req,
+ bitmap_rates);
+ if (ret == MLAN_STATUS_SUCCESS)
+ ret = MLAN_STATUS_PENDING;
+
+exit:
+ LEAVE();
+ return ret;
+}
+
+/**
+ * @brief Get rate index
+ *
+ * @param pmadapter A pointer to mlan_adapter structure
+ * @param pioctl_req A pointer to ioctl request buffer
+ *
+ * @return MLAN_STATUS_PENDING --success, otherwise fail
+ */
+static mlan_status wlan_rate_ioctl_get_rate_index(pmlan_adapter pmadapter,
+ pmlan_ioctl_req pioctl_req)
+{
+ mlan_status ret = MLAN_STATUS_SUCCESS;
+ mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index];
+
+ ENTER();
+
+ /* Send request to firmware */
+ ret = wlan_prepare_cmd(pmpriv, HostCmd_CMD_TX_RATE_CFG,
+ HostCmd_ACT_GEN_GET, 0, (t_void *)pioctl_req,
+ MNULL);
+ if (ret == MLAN_STATUS_SUCCESS)
+ ret = MLAN_STATUS_PENDING;
+
+ LEAVE();
+ return ret;
+}
+
+/**
+ * @brief Set rate index
+ *
+ * @param pmadapter A pointer to mlan_adapter structure
+ * @param pioctl_req A pointer to ioctl request buffer
+ *
+ * @return MLAN_STATUS_PENDING --success, otherwise fail
+ */
+static mlan_status wlan_rate_ioctl_set_rate_index(pmlan_adapter pmadapter,
+ pmlan_ioctl_req pioctl_req)
+{
+ t_u32 rate_index;
+ t_u32 rate_format;
+ t_u32 nss;
+ t_u32 i;
+ mlan_ds_rate *ds_rate = MNULL;
+ mlan_status ret = MLAN_STATUS_FAILURE;
+ mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index];
+ t_u16 bitmap_rates[MAX_BITMAP_RATES_SIZE];
+ int tx_mcs_supp = GET_TXMCSSUPP(pmpriv->usr_dev_mcs_support);
+
+ ENTER();
+
+ ds_rate = (mlan_ds_rate *)pioctl_req->pbuf;
+ rate_format = ds_rate->param.rate_cfg.rate_format;
+ nss = ds_rate->param.rate_cfg.nss;
+ rate_index = ds_rate->param.rate_cfg.rate;
+
+ if (ds_rate->param.rate_cfg.is_rate_auto) {
+ memset(pmadapter, bitmap_rates, 0, sizeof(bitmap_rates));
+ /* Rates talbe [0]: HR/DSSS;[1]: OFDM; [2..9] HT; */
+ /* Support all HR/DSSS rates */
+ bitmap_rates[0] = 0x000F;
+ /* Support all OFDM rates */
+ bitmap_rates[1] = 0x00FF;
+ /* Support all HT-MCSs rate */
+ for (i = 2; i < 9; i++)
+ bitmap_rates[i] = 0xFFFF;
+ bitmap_rates[9] = 0x3FFF;
+ /* [10..17] VHT */
+ /* Support all VHT-MCSs rate for NSS 1 and 2 */
+ for (i = 10; i < 12; i++)
+ bitmap_rates[i] = 0x03FF; /* 10 Bits valid */
+ /* Set to 0 as default value for all other NSSs */
+ for (i = 12; i < 17; i++)
+ bitmap_rates[i] = 0x0;
+ /* [18..25] HE */
+ /* Support all HE-MCSs rate for NSS1 and 2 */
+ for (i = 18; i < 20; i++)
+ bitmap_rates[i] = 0x0FFF;
+ for (i = 20; i < NELEMENTS(bitmap_rates); i++)
+ bitmap_rates[i] = 0x0;
+ } else {
+ PRINTM(MINFO, "Rate index is %d\n", rate_index);
+ if ((rate_format == MLAN_RATE_FORMAT_HT) &&
+ (rate_index > MLAN_RATE_INDEX_MCS7 &&
+ rate_index <= MLAN_RATE_INDEX_MCS15) &&
+ (tx_mcs_supp < 2)) {
+ PRINTM(MERROR,
+ "HW don't support 2x2, rate_index=%d hw_mcs_supp=0x%x\n",
+ rate_index, pmpriv->usr_dev_mcs_support);
+ pioctl_req->status_code = MLAN_ERROR_INVALID_PARAMETER;
+ LEAVE();
+ return MLAN_STATUS_FAILURE;
+ }
+ memset(pmadapter, bitmap_rates, 0, sizeof(bitmap_rates));
+ if (rate_format == MLAN_RATE_FORMAT_LG) {
+ /* Bitmap of HR/DSSS rates */
+ if (rate_index <= MLAN_RATE_INDEX_HRDSSS3) {
+ bitmap_rates[0] = 1 << rate_index;
+ ret = MLAN_STATUS_SUCCESS;
+ /* Bitmap of OFDM rates */
+ } else if ((rate_index >= MLAN_RATE_INDEX_OFDM0) &&
+ (rate_index <= MLAN_RATE_INDEX_OFDM7)) {
+ bitmap_rates[1] = 1 << (rate_index -
+ MLAN_RATE_INDEX_OFDM0);
+ ret = MLAN_STATUS_SUCCESS;
+ }
+ } else if (rate_format == MLAN_RATE_FORMAT_HT) {
+ if (rate_index <= MLAN_RATE_INDEX_MCS32) {
+ bitmap_rates[2 + (rate_index / 16)] =
+ 1 << (rate_index % 16);
+ ret = MLAN_STATUS_SUCCESS;
+ }
+ }
+ if (rate_format == MLAN_RATE_FORMAT_VHT) {
+ if ((rate_index <= MLAN_RATE_INDEX_MCS9) &&
+ (MLAN_RATE_NSS1 <= nss) &&
+ (nss <= MLAN_RATE_NSS2)) {
+ bitmap_rates[10 + nss - MLAN_RATE_NSS1] =
+ (1 << rate_index);
+ ret = MLAN_STATUS_SUCCESS;
+ }
+ }
+ if (rate_format == MLAN_RATE_FORMAT_HE) {
+ if (IS_FW_SUPPORT_11AX(pmadapter)) {
+ if ((rate_index <= MLAN_RATE_INDEX_MCS11) &&
+ (MLAN_RATE_NSS1 <= nss) &&
+ (nss <= MLAN_RATE_NSS2)) {
+ bitmap_rates[18 + nss - MLAN_RATE_NSS1] =
+ (1 << rate_index);
+ ret = MLAN_STATUS_SUCCESS;
+ }
+ } else {
+ PRINTM(MERROR,
+ "Error! Fw doesn't support 11AX\n");
+ LEAVE();
+ return MLAN_STATUS_FAILURE;
+ }
+ }
+
+ if (ret == MLAN_STATUS_FAILURE) {
+ PRINTM(MERROR, "Invalid MCS index=%d. \n", rate_index);
+ pioctl_req->status_code = MLAN_ERROR_INVALID_PARAMETER;
+ LEAVE();
+ return MLAN_STATUS_FAILURE;
+ }
+ }
+
+ PRINTM(MINFO,
+ "RateBitmap=%04x%04x%04x%04x%04x%04x%04x%04x"
+ "%04x%04x%04x%04x%04x%04x%04x%04x%04x%04x, "
+ "IsRateAuto=%d, DataRate=%d\n",
+ bitmap_rates[17], bitmap_rates[16], bitmap_rates[15],
+ bitmap_rates[14], bitmap_rates[13], bitmap_rates[12],
+ bitmap_rates[11], bitmap_rates[10], bitmap_rates[9],
+ bitmap_rates[8], bitmap_rates[7], bitmap_rates[6],
+ bitmap_rates[5], bitmap_rates[4], bitmap_rates[3],
+ bitmap_rates[2], bitmap_rates[1], bitmap_rates[0],
+ pmpriv->is_data_rate_auto, pmpriv->data_rate);
+
+ /* Send request to firmware */
+ ret = wlan_prepare_cmd(pmpriv, HostCmd_CMD_TX_RATE_CFG,
+ HostCmd_ACT_GEN_SET, 0, (t_void *)pioctl_req,
+ (t_void *)bitmap_rates);
+ if (ret == MLAN_STATUS_SUCCESS)
+ ret = MLAN_STATUS_PENDING;
+
+ LEAVE();
+ return ret;
+}
+
+/**
+ * @brief Rate configuration command handler
+ *
+ * @param pmadapter A pointer to mlan_adapter structure
+ * @param pioctl_req A pointer to ioctl request buffer
+ *
+ * @return MLAN_STATUS_SUCCESS/MLAN_STATUS_PENDING --success,
+ * otherwise fail
+ */
+mlan_status wlan_rate_ioctl_cfg(pmlan_adapter pmadapter,
+ pmlan_ioctl_req pioctl_req)
+{
+ mlan_ds_rate *rate = MNULL;
+ mlan_status status = MLAN_STATUS_SUCCESS;
+
+ ENTER();
+
+ rate = (mlan_ds_rate *)pioctl_req->pbuf;
+ if (rate->param.rate_cfg.rate_type == MLAN_RATE_BITMAP) {
+ if (pioctl_req->action == MLAN_ACT_GET)
+ status = wlan_rate_ioctl_get_rate_bitmap(pmadapter,
+ pioctl_req);
+ else
+ status = wlan_rate_ioctl_set_rate_bitmap(pmadapter,
+ pioctl_req);
+ } else if (rate->param.rate_cfg.rate_type == MLAN_RATE_VALUE) {
+ if (pioctl_req->action == MLAN_ACT_GET)
+ status = wlan_rate_ioctl_get_rate_value(pmadapter,
+ pioctl_req);
+ else
+ status = wlan_rate_ioctl_set_rate_value(pmadapter,
+ pioctl_req);
+ } else {
+ if (pioctl_req->action == MLAN_ACT_GET)
+ status = wlan_rate_ioctl_get_rate_index(pmadapter,
+ pioctl_req);
+ else
+ status = wlan_rate_ioctl_set_rate_index(pmadapter,
+ pioctl_req);
+ }
+
+ LEAVE();
+ return status;
+}
+
+/**
+ * @brief Get data rates
+ *
+ * @param pmadapter A pointer to mlan_adapter structure
+ * @param pioctl_req A pointer to ioctl request buffer
+ *
+ * @return MLAN_STATUS_PENDING --success, otherwise fail
+ */
+mlan_status wlan_rate_ioctl_get_data_rate(pmlan_adapter pmadapter,
+ pmlan_ioctl_req pioctl_req)
+{
+ mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index];
+ mlan_status ret = MLAN_STATUS_SUCCESS;
+
+ ENTER();
+
+ if (pioctl_req->action != MLAN_ACT_GET) {
+ ret = MLAN_STATUS_FAILURE;
+ goto exit;
+ }
+
+ /* Send request to firmware */
+ ret = wlan_prepare_cmd(pmpriv, HostCmd_CMD_802_11_TX_RATE_QUERY,
+ HostCmd_ACT_GEN_GET, 0, (t_void *)pioctl_req,
+ MNULL);
+ if (ret == MLAN_STATUS_SUCCESS)
+ ret = MLAN_STATUS_PENDING;
+
+exit:
+ LEAVE();
+ return ret;
+}
+
+/**
+ * @brief Set/Get remain on channel setting
+ *
+ * @param pmadapter A pointer to mlan_adapter structure
+ * @param pioctl_req A pointer to ioctl request buffer
+ *
+ * @return MLAN_STATUS_SUCCESS --success, otherwise fail
+ */
+mlan_status wlan_radio_ioctl_remain_chan_cfg(pmlan_adapter pmadapter,
+ pmlan_ioctl_req pioctl_req)
+{
+ mlan_status ret = MLAN_STATUS_SUCCESS;
+ mlan_ds_radio_cfg *radio_cfg = MNULL;
+ t_u16 cmd_action = 0;
+ mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index];
+
+ ENTER();
+
+ radio_cfg = (mlan_ds_radio_cfg *)pioctl_req->pbuf;
+ if (pioctl_req->action == MLAN_ACT_SET)
+ cmd_action = HostCmd_ACT_GEN_SET;
+ else
+ cmd_action = HostCmd_ACT_GEN_GET;
+
+ /* Send request to firmware */
+ ret = wlan_prepare_cmd(pmpriv, HostCmd_CMD_802_11_REMAIN_ON_CHANNEL,
+ cmd_action, 0, (t_void *)pioctl_req,
+ &radio_cfg->param.remain_chan);
+
+ if (ret == MLAN_STATUS_SUCCESS)
+ ret = MLAN_STATUS_PENDING;
+
+ LEAVE();
+ return ret;
+}
+
+#ifdef WIFI_DIRECT_SUPPORT
+/**
+ * @brief Set/Get wifi_direct_mode
+ *
+ * @param pmadapter A pointer to mlan_adapter structure
+ * @param pioctl_req A pointer to ioctl request buffer
+ *
+ * @return MLAN_STATUS_SUCCESS --success, otherwise fail
+ */
+mlan_status wlan_bss_ioctl_wifi_direct_mode(pmlan_adapter pmadapter,
+ pmlan_ioctl_req pioctl_req)
+{
+ mlan_status ret = MLAN_STATUS_SUCCESS;
+ mlan_ds_bss *bss = MNULL;
+
+ t_u16 cmd_action = 0;
+ mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index];
+
+ ENTER();
+
+ bss = (mlan_ds_bss *)pioctl_req->pbuf;
+
+ if (pioctl_req->action == MLAN_ACT_SET)
+ cmd_action = HostCmd_ACT_GEN_SET;
+ else
+ cmd_action = HostCmd_ACT_GEN_GET;
+
+ /* Send request to firmware */
+ ret = wlan_prepare_cmd(pmpriv, HOST_CMD_WIFI_DIRECT_MODE_CONFIG,
+ cmd_action, 0, (t_void *)pioctl_req,
+ &bss->param.wfd_mode);
+
+ if (ret == MLAN_STATUS_SUCCESS)
+ ret = MLAN_STATUS_PENDING;
+
+ LEAVE();
+ return ret;
+}
+
+/**
+ * @brief Set/Get p2p config
+ *
+ * @param pmadapter A pointer to mlan_adapter structure
+ * @param pioctl_req A pointer to ioctl request buffer
+ *
+ * @return MLAN_STATUS_SUCCESS --success, otherwise fail
+ */
+mlan_status wlan_misc_p2p_config(pmlan_adapter pmadapter,
+ pmlan_ioctl_req pioctl_req)
+{
+ mlan_status ret = MLAN_STATUS_SUCCESS;
+ mlan_ds_misc_cfg *misc_cfg = MNULL;
+ t_u16 cmd_action = 0;
+ mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index];
+
+ ENTER();
+
+ misc_cfg = (mlan_ds_misc_cfg *)pioctl_req->pbuf;
+ if (pioctl_req->action == MLAN_ACT_SET)
+ cmd_action = HostCmd_ACT_GEN_SET;
+ else
+ cmd_action = HostCmd_ACT_GEN_GET;
+
+ /* Send request to firmware */
+ ret = wlan_prepare_cmd(pmpriv, HOST_CMD_P2P_PARAMS_CONFIG, cmd_action,
+ 0, (t_void *)pioctl_req,
+ &misc_cfg->param.p2p_config);
+
+ if (ret == MLAN_STATUS_SUCCESS)
+ ret = MLAN_STATUS_PENDING;
+
+ LEAVE();
+ return ret;
+}
+#endif
+
+/**
+ * @brief Set coalesce config
+ *
+ * @param pmadapter A pointer to mlan_adapter structure
+ * @param pioctl_req A pointer to ioctl request buffer
+ *
+ * @return MLAN_STATUS_SUCCESS --success, otherwise fail
+ */
+mlan_status wlan_misc_ioctl_coalesce_cfg(pmlan_adapter pmadapter,
+ pmlan_ioctl_req pioctl_req)
+{
+ mlan_status ret = MLAN_STATUS_SUCCESS;
+ mlan_ds_misc_cfg *misc_cfg = MNULL;
+ t_u16 cmd_action = 0;
+ mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index];
+
+ ENTER();
+
+ misc_cfg = (mlan_ds_misc_cfg *)pioctl_req->pbuf;
+ if (pioctl_req->action == MLAN_ACT_SET)
+ cmd_action = HostCmd_ACT_GEN_SET;
+ else
+ cmd_action = HostCmd_ACT_GEN_GET;
+
+ /* Send request to firmware */
+ ret = wlan_prepare_cmd(pmpriv, HostCmd_CMD_COALESCE_CFG, cmd_action, 0,
+ (t_void *)pioctl_req,
+ &misc_cfg->param.coalesce_cfg);
+
+ if (ret == MLAN_STATUS_SUCCESS)
+ ret = MLAN_STATUS_PENDING;
+
+ LEAVE();
+ return ret;
+}
+
+/**
+ * @brief Get/Set USB packet aggregation parameters
+ *
+ * @param pmadapter A pointer to mlan_adapter structure
+ * @param pioctl_req A pointer to ioctl request buffer
+ *
+ * @return MLAN_STATUS_PENDING --success, otherwise fail
+ */
+mlan_status wlan_misc_ioctl_aggr_ctrl(pmlan_adapter pmadapter,
+ pmlan_ioctl_req pioctl_req)
+{
+ mlan_status ret = MLAN_STATUS_SUCCESS;
+ mlan_ds_misc_cfg *misc = MNULL;
+ t_u16 cmd_action = 0;
+ mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index];
+
+ ENTER();
+
+ misc = (mlan_ds_misc_cfg *)pioctl_req->pbuf;
+ if (pioctl_req->action == MLAN_ACT_SET)
+ cmd_action = HostCmd_ACT_GEN_SET;
+ else
+ cmd_action = HostCmd_ACT_GEN_GET;
+
+ /* Send request to firmware */
+ ret = wlan_prepare_cmd(pmpriv, HostCmd_CMD_PACKET_AGGR_CTRL, cmd_action,
+ 0, (t_void *)pioctl_req,
+ &misc->param.aggr_params);
+
+ if (ret == MLAN_STATUS_SUCCESS) {
+ ret = MLAN_STATUS_PENDING;
+ }
+
+ LEAVE();
+ return ret;
+}
+
+#ifdef USB
+/**
+ * @brief Get/Set USB packet aggregation parameters
+ *
+ * @param pmadapter A pointer to mlan_adapter structure
+ * @param pioctl_req A pointer to ioctl request buffer
+ *
+ * @return MLAN_STATUS_PENDING --success, otherwise fail
+ */
+mlan_status wlan_misc_ioctl_usb_aggr_ctrl(pmlan_adapter pmadapter,
+ pmlan_ioctl_req pioctl_req)
+{
+ mlan_status ret = MLAN_STATUS_SUCCESS;
+ mlan_ds_misc_cfg *misc = MNULL;
+ t_u16 cmd_action = 0;
+ mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index];
+
+ ENTER();
+
+ if (pmadapter->pcard_usb->fw_usb_aggr == MFALSE) {
+ PRINTM(MERROR, "USB aggregation not supported by FW\n");
+ pioctl_req->status_code = MLAN_ERROR_CMD_INVALID;
+ LEAVE();
+ return MLAN_STATUS_FAILURE;
+ }
+
+ misc = (mlan_ds_misc_cfg *)pioctl_req->pbuf;
+ if (pioctl_req->action == MLAN_ACT_SET)
+ cmd_action = HostCmd_ACT_GEN_SET;
+ else
+ cmd_action = HostCmd_ACT_GEN_GET;
+
+ /* Send request to firmware */
+ ret = wlan_prepare_cmd(pmpriv,
+ HostCmd_CMD_PACKET_AGGR_OVER_HOST_INTERFACE,
+ cmd_action, 0, (t_void *)pioctl_req,
+ &misc->param.usb_aggr_params);
+
+ if (ret == MLAN_STATUS_SUCCESS) {
+ ret = MLAN_STATUS_PENDING;
+ }
+
+ LEAVE();
+ return ret;
+}
+#endif
+
+/**
+ * @brief Get/Set Tx control configuration
+ *
+ * @param pmadapter A pointer to mlan_adapter structure
+ * @param pioctl_req A pointer to ioctl request buffer
+ *
+ * @return MLAN_STATUS_SUCCESS
+ */
+mlan_status wlan_misc_ioctl_txcontrol(pmlan_adapter pmadapter,
+ pmlan_ioctl_req pioctl_req)
+{
+ mlan_status ret = MLAN_STATUS_SUCCESS;
+ mlan_ds_misc_cfg *misc = MNULL;
+ mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index];
+
+ ENTER();
+
+ misc = (mlan_ds_misc_cfg *)pioctl_req->pbuf;
+ if (pioctl_req->action == MLAN_ACT_SET)
+ pmpriv->pkt_tx_ctrl = misc->param.tx_control;
+ else
+ misc->param.tx_control = pmpriv->pkt_tx_ctrl;
+
+ LEAVE();
+ return ret;
+}
+
+#ifdef RX_PACKET_COALESCE
+/**
+ * @brief Get/Set RX packet coalescing configuration
+ *
+ * @param pmadapter A pointer to mlan_adapter structure
+ * @param pioctl_req A pointer to ioctl request buffer
+ *
+ * @return MLAN_STATUS_SUCCESS
+ */
+mlan_status wlan_misc_ioctl_rx_pkt_coalesce_config(pmlan_adapter pmadapter,
+ pmlan_ioctl_req pioctl_req)
+{
+ mlan_status ret = MLAN_STATUS_SUCCESS;
+ mlan_ds_misc_cfg *misc = MNULL;
+ t_u16 cmd_action = 0;
+ mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index];
+
+ ENTER();
+
+ misc = (mlan_ds_misc_cfg *)pioctl_req->pbuf;
+
+ if (pioctl_req->action == MLAN_ACT_SET)
+ cmd_action = HostCmd_ACT_GEN_SET;
+ else
+ cmd_action = HostCmd_ACT_GEN_GET;
+
+ /* Send request to firmware */
+ ret = wlan_prepare_cmd(pmpriv, HostCmd_CMD_RX_PKT_COALESCE_CFG,
+ cmd_action, 0, (t_void *)pioctl_req,
+ &misc->param.rx_coalesce);
+
+ if (ret == MLAN_STATUS_SUCCESS)
+ ret = MLAN_STATUS_PENDING;
+
+ LEAVE();
+ return ret;
+}
+#endif
+
+/**
+ * @brief Is any uAP started or STA connected?
+ *
+ * @param pmadapter A pointer to mlan_adapter structure
+ *
+ * @return MTRUE/MFALSE
+ */
+t_bool wlan_check_interface_active(mlan_adapter *pmadapter)
+{
+ t_bool ret = MFALSE;
+ pmlan_private pmpriv;
+ int i;
+
+ if (pmadapter == MNULL)
+ return MFALSE;
+
+ for (i = 0; i < pmadapter->priv_num; i++) {
+ pmpriv = pmadapter->priv[i];
+ if (pmpriv) {
+#ifdef UAP_SUPPORT
+ if (GET_BSS_ROLE(pmpriv) == MLAN_BSS_ROLE_UAP)
+ ret = pmpriv->uap_bss_started;
+ else
+#endif
+ if (GET_BSS_ROLE(pmpriv) == MLAN_BSS_ROLE_STA)
+ ret = pmpriv->media_connected;
+ }
+ if (ret)
+ return MTRUE;
+ }
+
+ return MFALSE;
+}
+
+/**
+ * @brief Get/Set DFS REPEATER mode
+ *
+ * @param pmadapter A pointer to mlan_adapter structure
+ * @param pioctl_req A pointer to ioctl request buffer
+ *
+ * @return MLAN_STATUS_SUCCESS
+ */
+mlan_status wlan_misc_ioctl_dfs_repeater_cfg(pmlan_adapter pmadapter,
+ pmlan_ioctl_req pioctl_req)
+{
+ mlan_status ret = MLAN_STATUS_SUCCESS;
+ mlan_ds_misc_cfg *misc = MNULL;
+ t_u16 cmd_action = 0;
+ mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index];
+
+ ENTER();
+
+ misc = (mlan_ds_misc_cfg *)pioctl_req->pbuf;
+
+ if (pioctl_req->action == MLAN_ACT_SET) {
+ /* Make sure no interface is active
+ * before setting the dfs repeater mode
+ */
+ if (wlan_check_interface_active(pmadapter)) {
+ PRINTM(MMSG, "DFS-Repeater active priv found,"
+ " skip enabling the mode.\n");
+ ret = MLAN_STATUS_FAILURE;
+ goto done;
+ }
+
+ cmd_action = HostCmd_ACT_GEN_SET;
+ } else {
+ cmd_action = HostCmd_ACT_GEN_GET;
+ }
+
+ /* Send request to firmware */
+ ret = wlan_prepare_cmd(pmpriv, HostCmd_DFS_REPEATER_MODE, cmd_action, 0,
+ (t_void *)pioctl_req, &misc->param.dfs_repeater);
+
+done:
+ if (ret == MLAN_STATUS_SUCCESS)
+ ret = MLAN_STATUS_PENDING;
+
+ LEAVE();
+ return ret;
+}
+
+/**
+ * @brief Set/Get Low Power Mode
+ *
+ * @param pmadapter A pointer to mlan_adapter structure
+ * @param pioctl_req A pointer to ioctl request buffer
+ *
+ * @return MLAN_STATUS_SUCCESS
+ */
+mlan_status wlan_misc_ioctl_low_pwr_mode(pmlan_adapter pmadapter,
+ pmlan_ioctl_req pioctl_req)
+{
+ mlan_status ret = MLAN_STATUS_SUCCESS;
+ mlan_ds_misc_cfg *misc = MNULL;
+ mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index];
+
+ ENTER();
+
+ misc = (mlan_ds_misc_cfg *)pioctl_req->pbuf;
+
+ /* Send request to firmware */
+ ret = wlan_prepare_cmd(pmpriv, HostCMD_CONFIG_LOW_POWER_MODE,
+ HostCmd_ACT_GEN_SET, 0, (t_void *)pioctl_req,
+ &misc->param.low_pwr_mode);
+
+ if (ret == MLAN_STATUS_SUCCESS)
+ ret = MLAN_STATUS_PENDING;
+
+ LEAVE();
+ return ret;
+}
+
+/**
+ * @brief Configure PMIC in Firmware
+ *
+ * @param pmadapter A pointer to mlan_adapter structure
+ * @param pioctl_req A pointer to ioctl request buffer
+ *
+ * @return MLAN_STATUS_SUCCESS
+ */
+mlan_status wlan_misc_ioctl_pmic_configure(pmlan_adapter pmadapter,
+ pmlan_ioctl_req pioctl_req)
+{
+ mlan_status ret = MLAN_STATUS_SUCCESS;
+ mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index];
+
+ ENTER();
+
+ /* Send request to firmware */
+ ret = wlan_prepare_cmd(pmpriv, HOST_CMD_PMIC_CONFIGURE,
+ HostCmd_ACT_GEN_SET, 0, (t_void *)pioctl_req,
+ MNULL);
+
+ if (ret == MLAN_STATUS_SUCCESS)
+ ret = MLAN_STATUS_PENDING;
+
+ LEAVE();
+ return ret;
+}
+
+/* @brief Set/Get CW Mode Level control
+ *
+ * @param pmadapter A pointer to mlan_adapter structure
+ * @param pioctl_req A pointer to ioctl request buffer
+ *
+ * @return MLAN_STATUS_SUCCESS
+ */
+mlan_status wlan_misc_ioctl_cwmode_ctrl(pmlan_adapter pmadapter,
+ pmlan_ioctl_req pioctl_req)
+{
+ mlan_status ret = MLAN_STATUS_SUCCESS;
+ mlan_ds_misc_cfg *misc = MNULL;
+ mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index];
+ t_u16 cmd_action = 0;
+
+ ENTER();
+
+ misc = (mlan_ds_misc_cfg *)pioctl_req->pbuf;
+
+ if (pioctl_req->action == MLAN_ACT_SET)
+ cmd_action = HostCmd_ACT_GEN_SET;
+ else
+ cmd_action = HostCmd_ACT_GEN_GET;
+
+ /* Send request to firmware */
+ ret = wlan_prepare_cmd(pmpriv, HostCmd_CMD_CW_MODE_CTRL, cmd_action, 0,
+ (t_void *)pioctl_req, &misc->param.cwmode);
+
+ if (ret == MLAN_STATUS_SUCCESS)
+ ret = MLAN_STATUS_PENDING;
+
+ LEAVE();
+ return ret;
+}
+
+/**
+ * @brief push value to stack
+ *
+ * @param pmadapter A pointer to mlan_adapter structure
+ * @param s A pointer to mef_stack
+ * @param len Length of value
+ * @param val A pointer to value
+ *
+ * @return MLAN_STATUS_SUCCESS or FAIL
+ */
+inline mlan_status push_n(pmlan_adapter pmadapter, mef_stack *s, t_u8 len,
+ t_u8 *val)
+{
+ if ((s->sp + len) <= MAX_NUM_STACK_BYTES) {
+ memcpy_ext(pmadapter, s->byte + s->sp, val, len,
+ MAX_NUM_STACK_BYTES - s->sp);
+ s->sp += len;
+ return MLAN_STATUS_SUCCESS;
+ } else {
+ PRINTM(MERROR, "Stack is full\n");
+ return MLAN_STATUS_FAILURE;
+ }
+}
+
+/**
+ * @brief push value to stack accoring to operand type
+ *
+ * @param pmadapter A pointer to mlan_adapter structure
+ * @param s A pointer to mef_stack
+ * @param op A pointer to mef_op
+ *
+ * @return MLAN_STATUS_SUCCESS or FAIL
+ */
+inline mlan_status mef_push(pmlan_adapter pmadapter, mef_stack *s, mef_op *op)
+{
+ mlan_status ret = MLAN_STATUS_SUCCESS;
+ t_u8 nbytes;
+ switch (op->operand_type) {
+ case OPERAND_DNUM:
+ ret = push_n(pmadapter, s, 4, op->val);
+ if (ret == MLAN_STATUS_SUCCESS)
+ ret = push_n(pmadapter, s, 1, &op->operand_type);
+ else
+ ret = MLAN_STATUS_FAILURE;
+ break;
+ case OPERAND_BYTE_SEQ:
+ nbytes = op->val[0];
+ if (MLAN_STATUS_SUCCESS ==
+ push_n(pmadapter, s, nbytes, op->val + 1) &&
+ MLAN_STATUS_SUCCESS == push_n(pmadapter, s, 1, op->val) &&
+ MLAN_STATUS_SUCCESS ==
+ push_n(pmadapter, s, 1, &op->operand_type))
+ ret = MLAN_STATUS_SUCCESS;
+ else
+ ret = MLAN_STATUS_FAILURE;
+ break;
+ default:
+ ret = push_n(pmadapter, s, 1, &op->operand_type);
+ break;
+ }
+ return ret;
+}
+
+/**
+ * @brief push dnum filter to stack
+ *
+ * @param pmadapter A pointer to mlan_adapter structure
+ * @param s A pointer to mef_stack
+ * @param filter A pointer to filter item
+ *
+ * @return MLAN_STATUS_SUCCESS or FAIL
+ */
+mlan_status push_filter_dnum_eq(pmlan_adapter pmadapter, mef_stack *s,
+ mef_filter_t *filter)
+{
+ mlan_status ret = MLAN_STATUS_SUCCESS;
+ t_u32 dnum;
+ mef_op op;
+
+ ENTER();
+
+ if (!filter) {
+ ret = MLAN_STATUS_FAILURE;
+ goto done;
+ }
+ if (filter->fill_flag != (FILLING_TYPE | FILLING_PATTERN |
+ FILLING_OFFSET | FILLING_NUM_BYTES)) {
+ PRINTM(MERROR, "Filter item fill error\n");
+ ret = MLAN_STATUS_FAILURE;
+ goto done;
+ }
+
+ /* Format of decimal num:
+ * | 5 bytes | 5 bytes | 5 bytes | 1 byte | |
+ * pattern | offset | num of bytes | type (TYPE_DNUM_EQ) |
+ */
+
+ /* push pattern */
+ memset(pmadapter, &op, 0, sizeof(op));
+ op.operand_type = OPERAND_DNUM;
+ dnum = filter->pattern;
+ memcpy_ext(pmadapter, op.val, &dnum, sizeof(dnum), sizeof(op.val));
+ ret = mef_push(pmadapter, s, &op);
+ if (ret != MLAN_STATUS_SUCCESS)
+ goto done;
+
+ /* push offset */
+ memset(pmadapter, &op, 0, sizeof(op));
+ op.operand_type = OPERAND_DNUM;
+ dnum = filter->offset;
+ memcpy_ext(pmadapter, op.val, &dnum, sizeof(dnum), sizeof(op.val));
+ ret = mef_push(pmadapter, s, &op);
+ if (ret != MLAN_STATUS_SUCCESS)
+ goto done;
+
+ /* push num of bytes */
+ memset(pmadapter, &op, 0, sizeof(op));
+ op.operand_type = OPERAND_DNUM;
+ dnum = filter->num_bytes;
+ memcpy_ext(pmadapter, op.val, &dnum, sizeof(dnum), sizeof(op.val));
+ ret = mef_push(pmadapter, s, &op);
+ if (ret != MLAN_STATUS_SUCCESS)
+ goto done;
+
+ /* push type */
+ memset(pmadapter, &op, 0, sizeof(op));
+ op.operand_type = TYPE_DNUM_EQ;
+ ret = mef_push(pmadapter, s, &op);
+
+done:
+ LEAVE();
+ return ret;
+}
+
+/**
+ * @brief push byte_eq filter to stack
+ *
+ * @param pmadapter A pointer to mlan_adapter structure
+ * @param s A pointer to mef_stack
+ * @param filter A pointer to filter item
+ *
+ * @return MLAN_STATUS_SUCCESS or FAIL
+ */
+mlan_status push_filter_byte_eq(pmlan_adapter pmadapter, mef_stack *s,
+ mef_filter_t *filter)
+{
+ mlan_status ret = MLAN_STATUS_SUCCESS;
+ t_u32 dnum;
+ mef_op op;
+
+ ENTER();
+
+ if (!filter) {
+ ret = MLAN_STATUS_FAILURE;
+ goto done;
+ }
+ if (filter->fill_flag != (FILLING_TYPE | FILLING_REPEAT |
+ FILLING_BYTE_SEQ | FILLING_OFFSET)) {
+ PRINTM(MERROR, "Filter item fill error\n");
+ ret = MLAN_STATUS_FAILURE;
+ goto done;
+ }
+
+ /* Format of decimal num:
+ * | 5 bytes | val | 5 bytes | 1 byte | |
+ * repeat | bytes seq | offset | type (TYPE_BYTE_EQ) |
+ */
+
+ /* push repeat */
+ memset(pmadapter, &op, 0, sizeof(op));
+ op.operand_type = OPERAND_DNUM;
+ dnum = filter->repeat;
+ memcpy_ext(pmadapter, op.val, &dnum, sizeof(dnum), sizeof(op.val));
+ ret = mef_push(pmadapter, s, &op);
+ if (ret != MLAN_STATUS_SUCCESS)
+ goto done;
+
+ /* push bytes seq */
+ memset(pmadapter, &op, 0, sizeof(op));
+ op.operand_type = OPERAND_BYTE_SEQ;
+ op.val[0] = filter->num_byte_seq;
+ memcpy_ext(pmadapter, &op.val[1], filter->byte_seq,
+ filter->num_byte_seq, MAX_NUM_BYTE_SEQ);
+ ret = mef_push(pmadapter, s, &op);
+ if (ret != MLAN_STATUS_SUCCESS)
+ goto done;
+
+ /* push offset */
+ memset(pmadapter, &op, 0, sizeof(op));
+ op.operand_type = OPERAND_DNUM;
+ dnum = filter->offset;
+ memcpy_ext(pmadapter, op.val, &dnum, sizeof(dnum), sizeof(op.val));
+ ret = mef_push(pmadapter, s, &op);
+ if (ret != MLAN_STATUS_SUCCESS)
+ goto done;
+
+ /* push type */
+ memset(pmadapter, &op, 0, sizeof(op));
+ op.operand_type = TYPE_BYTE_EQ;
+ ret = mef_push(pmadapter, s, &op);
+
+done:
+ LEAVE();
+ return ret;
+}
+
+/**
+ * @brief push bite_eq filter to stack
+ *
+ * @param pmadapter A pointer to mlan_adapter structure
+ * @param s A pointer to mef_stack
+ * @param filter A pointer to filter item
+ *
+ * @return MLAN_STATUS_SUCCESS or FAIL
+ */
+mlan_status push_filter_bit_eq(pmlan_adapter pmadapter, mef_stack *s,
+ mef_filter_t *filter)
+{
+ mlan_status ret = MLAN_STATUS_SUCCESS;
+ t_u32 dnum;
+ mef_op op;
+
+ ENTER();
+
+ if (!filter) {
+ ret = MLAN_STATUS_FAILURE;
+ goto done;
+ }
+ if (filter->fill_flag != (FILLING_TYPE | FILLING_REPEAT |
+ FILLING_BYTE_SEQ | FILLING_OFFSET)) {
+ PRINTM(MERROR, "Filter item fill error\n");
+ ret = MLAN_STATUS_FAILURE;
+ goto done;
+ }
+
+ /* Format of decimal num:
+ * | val | 5 bytes | val | 1 byte | |
+ * bytes seq | offset | mask seq | type (TYPE_BIT_EQ) |
+ */
+
+ /* push bytes seq */
+ memset(pmadapter, &op, 0, sizeof(op));
+ op.operand_type = OPERAND_BYTE_SEQ;
+ op.val[0] = filter->num_byte_seq;
+ memcpy_ext(pmadapter, &op.val[1], filter->byte_seq,
+ filter->num_byte_seq, MAX_NUM_BYTE_SEQ);
+ ret = mef_push(pmadapter, s, &op);
+ if (ret != MLAN_STATUS_SUCCESS)
+ goto done;
+
+ /* push offset */
+ memset(pmadapter, &op, 0, sizeof(op));
+ op.operand_type = OPERAND_DNUM;
+ dnum = filter->offset;
+ memcpy_ext(pmadapter, op.val, &dnum, sizeof(dnum), sizeof(op.val));
+ ret = mef_push(pmadapter, s, &op);
+ if (ret != MLAN_STATUS_SUCCESS)
+ goto done;
+
+ /* push mask seq */
+ memset(pmadapter, &op, 0, sizeof(op));
+ op.operand_type = OPERAND_BYTE_SEQ;
+ op.val[0] = filter->num_mask_seq;
+ memcpy_ext(pmadapter, &op.val[1], filter->mask_seq,
+ filter->num_mask_seq, MAX_NUM_BYTE_SEQ);
+ ret = mef_push(pmadapter, s, &op);
+ if (ret != MLAN_STATUS_SUCCESS)
+ goto done;
+
+ /* push type */
+ memset(pmadapter, &op, 0, sizeof(op));
+ op.operand_type = TYPE_BIT_EQ;
+ ret = mef_push(pmadapter, s, &op);
+
+done:
+ LEAVE();
+ return ret;
+}
+
+/**
+ * @brief push filter to stack
+ *
+ * @param pmadapter A pointer to mlan_adapter structure
+ * @param s A pointer to mef_stack
+ * @param filter A pointer to filter item
+ *
+ * @return MLAN_STATUS_SUCCESS or FAIL
+ */
+mlan_status wlan_push_filter(pmlan_adapter pmadapter, mef_stack *s,
+ mef_filter_t *filter)
+{
+ mlan_status ret = MLAN_STATUS_SUCCESS;
+
+ switch (filter->type) {
+ case TYPE_DNUM_EQ:
+ ret = push_filter_dnum_eq(pmadapter, s, filter);
+ break;
+ case TYPE_BYTE_EQ:
+ ret = push_filter_byte_eq(pmadapter, s, filter);
+ break;
+ case TYPE_BIT_EQ:
+ ret = push_filter_bit_eq(pmadapter, s, filter);
+ break;
+ default:
+ PRINTM(MERROR, "Invalid filter type\n");
+ ret = MLAN_STATUS_FAILURE;
+ break;
+ }
+ return ret;
+}
+
+/**
+ * @brief generate mef data
+ *
+ * @param pmadapter A pointer to mlan_adapter structure
+ * @param s A pointer to mef_stack
+ * @param entry A pointer to mef_entry_t
+ *
+ * @return MLAN_STATUS_SUCCESS or FAIL
+ */
+mlan_status wlan_generate_mef_filter_stack(pmlan_adapter pmadapter,
+ mef_stack *s, mef_entry_t *entry)
+{
+ mlan_status ret = MLAN_STATUS_SUCCESS;
+ mef_op op;
+ int i;
+
+ ENTER();
+
+ for (i = 0; i < entry->filter_num; i++) {
+ ret = wlan_push_filter(pmadapter, s, &entry->filter_item[i]);
+ if (ret != MLAN_STATUS_SUCCESS) {
+ PRINTM(MERROR, "push filter to stack error\n");
+ goto done;
+ }
+ if (i != 0) {
+ memset(pmadapter, &op, 0, sizeof(op));
+ op.operand_type = entry->rpn[i];
+ ret = mef_push(pmadapter, s, &op);
+ if (ret != MLAN_STATUS_SUCCESS) {
+ PRINTM(MERROR, "push filter rpn error\n");
+ goto done;
+ }
+ }
+ }
+done:
+ LEAVE();
+ return ret;
+}
+
+/**
+ * @brief Set the mef entries to firmware
+ *
+ * @param pmpriv A pointer to mlan_private structure
+ * @param pmadapter A pointer to mlan_adapter structure
+ * @param pmef A pointer to mef_cfg structure
+ *
+ * @return MLAN_STATUS_SUCCESS or FAIL
+ */
+mlan_status wlan_set_mef_entry(mlan_private *pmpriv, pmlan_adapter pmadapter,
+ mef_cfg *pmef)
+{
+ mlan_status ret = MLAN_STATUS_SUCCESS;
+ mlan_ds_misc_cmd *hostcmd;
+ HostCmd_DS_GEN *hostcmd_hdr;
+ HostCmd_DS_MEF_CFG *mef_hdr;
+ mef_entry_header *entry_hdr;
+ mef_stack *stack;
+ mef_entry_t *pentry;
+ t_u8 *buf;
+ t_u32 i, buf_len;
+ pmlan_callbacks pcb;
+
+ ENTER();
+
+ if (pmef->entry_num > MAX_NUM_ENTRIES) {
+ PRINTM(MERROR, "Too many entries\n");
+ ret = MLAN_STATUS_FAILURE;
+ goto done;
+ }
+ pcb = &pmadapter->callbacks;
+ ret = pcb->moal_malloc(pmadapter->pmoal_handle,
+ sizeof(mlan_ds_misc_cmd), MLAN_MEM_DEF,
+ (t_u8 **)&hostcmd);
+ if (ret != MLAN_STATUS_SUCCESS || hostcmd == MNULL) {
+ PRINTM(MERROR, "Failed to allocate cmd data buffer\n");
+ ret = MLAN_STATUS_FAILURE;
+ goto err_handle;
+ }
+
+ /** Fill the cmd header data*/
+ memset(pmadapter, hostcmd, 0, sizeof(mlan_ds_misc_cmd));
+ buf = hostcmd->cmd;
+ hostcmd_hdr = (HostCmd_DS_GEN *)buf;
+ hostcmd_hdr->command = wlan_cpu_to_le16(HostCmd_CMD_MEF_CFG);
+ buf_len = S_DS_GEN;
+
+ /** Fill HostCmd_DS_MEF_CFG*/
+ mef_hdr = (HostCmd_DS_MEF_CFG *)(buf + buf_len);
+ mef_hdr->criteria = wlan_cpu_to_le32(pmef->criteria);
+ mef_hdr->nentries = wlan_cpu_to_le16(pmef->entry_num);
+ buf_len += sizeof(HostCmd_DS_MEF_CFG);
+
+ /** generate mef entry data*/
+ for (i = 0, pentry = pmef->pentry; i < pmef->entry_num; i++, pentry++) {
+ /** Fill entry header data*/
+ entry_hdr = (mef_entry_header *)(buf + buf_len);
+ entry_hdr->mode = pentry->mode;
+ entry_hdr->action = pentry->action;
+ buf_len += sizeof(mef_entry_header);
+
+ /** Fill Stack data*/
+ stack = (mef_stack *)(buf + buf_len);
+ ret = wlan_generate_mef_filter_stack(pmadapter, stack, pentry);
+ if (ret != MLAN_STATUS_SUCCESS) {
+ PRINTM(MERROR, "Generate mef data error\n");
+ goto err_handle;
+ }
+ buf_len += (stack->sp + sizeof(stack->sp));
+ }
+ hostcmd_hdr->size = wlan_cpu_to_le16(buf_len);
+ hostcmd->len = wlan_cpu_to_le32(buf_len);
+
+ DBG_HEXDUMP(MCMD_D, "MEF DATA", (t_u8 *)hostcmd, buf_len + 4);
+
+ /** Send command to firmware*/
+ ret = wlan_prepare_cmd(pmpriv, 0, 0, 0, (t_void *)MNULL,
+ (t_void *)hostcmd);
+
+err_handle:
+ if (hostcmd)
+ pcb->moal_mfree(pmadapter->pmoal_handle, (t_u8 *)hostcmd);
+done:
+ LEAVE();
+ return ret;
+}
+
+/*
+ * @brief generate Host_CMD_MEF_CFG cmd data to firmware
+ *
+ * @param pmpriv A pointer to mlan_private structure
+ * @param pmadapter A pointer to mlan_adapter structure
+ *
+ * @return MLAN_STATUS_SUCCESS or FAIL
+ */
+mlan_status wlan_process_mef_cfg_cmd(mlan_private *pmpriv,
+ pmlan_adapter pmadapter)
+{
+ mlan_status ret = MLAN_STATUS_SUCCESS;
+ pmlan_callbacks pcb;
+ mef_cfg mef;
+ mef_entry_t *pentry;
+ mef_entry *pmef;
+ t_u16 entry_num = 0;
+
+ ENTER();
+
+ pcb = &pmadapter->callbacks;
+
+ /** check how many entries in adapter*/
+ pmef = &pmadapter->entry_cfg;
+ entry_num += pmef->num_wowlan_entry;
+ entry_num += pmef->num_ipv6_ns_offload;
+ if (!entry_num) {
+ PRINTM(MIOCTL, "No filter entries\n");
+ goto done;
+ }
+
+ ret = pcb->moal_malloc(pmadapter->pmoal_handle,
+ sizeof(mef_entry_t) * entry_num, MLAN_MEM_DEF,
+ (t_u8 **)&mef.pentry);
+ if (ret != MLAN_STATUS_SUCCESS || mef.pentry == MNULL) {
+ PRINTM(MERROR, "Failed to allocate cmd data buffer\n");
+ ret = MLAN_STATUS_FAILURE;
+ goto err_handle;
+ }
+ /** Fill mef_cfg structure*/
+ mef.criteria = pmef->criteria;
+ mef.entry_num = entry_num;
+ memset(pmadapter, mef.pentry, 0, sizeof(mef_entry_t) * entry_num);
+ pentry = mef.pentry;
+ /** Fill mef_entry_t structure*/
+ /** Copy wowlan entry*/
+ if (pmef->num_wowlan_entry) {
+ memcpy_ext(pmadapter, pentry, &pmef->entry[6],
+ sizeof(mef_entry_t), sizeof(mef_entry_t));
+ pentry += pmef->num_wowlan_entry;
+ }
+ /** Copy IPv6 NS message offload entry */
+ if (pmef->num_ipv6_ns_offload)
+ memcpy_ext(pmadapter, pentry, &pmef->entry[7],
+ sizeof(mef_entry_t), sizeof(mef_entry_t));
+
+ /** Set Entries to firmware*/
+ ret = wlan_set_mef_entry(pmpriv, pmadapter, &mef);
+ if (ret != MLAN_STATUS_SUCCESS)
+ PRINTM(MERROR, "Set MEF entries error\n");
+
+err_handle:
+ if (mef.pentry)
+ pcb->moal_mfree(pmadapter->pmoal_handle, (t_u8 *)mef.pentry);
+done:
+ LEAVE();
+ return ret;
+}
+
+/* @brief Get/Set NV-FLT-CONFIG parameters
+ *
+ * @param pmadapter A pointer to mlan_adapter structure
+ * @param pioctl_req A pointer to ioctl request buffer
+ *
+ * @return MLAN_STATUS_SUCCESS
+ */
+mlan_status wlan_misc_ioctl_mef_flt_cfg(pmlan_adapter pmadapter,
+ pmlan_ioctl_req pioctl_req)
+{
+ mlan_status ret = MLAN_STATUS_SUCCESS;
+ mlan_ds_misc_cfg *misc_cfg = MNULL;
+ mlan_ds_misc_mef_flt_cfg *mef_cfg = MNULL;
+ mef_entry *pmef = MNULL;
+
+ ENTER();
+
+ misc_cfg = (mlan_ds_misc_cfg *)pioctl_req->pbuf;
+ mef_cfg = &misc_cfg->param.mef_flt_cfg;
+ pmef = &pmadapter->entry_cfg;
+ switch (pioctl_req->action) {
+ case MLAN_ACT_SET:
+ if (mef_cfg->mef_act_type == MEF_ACT_WOWLAN) {
+ pmef->num_wowlan_entry = 1;
+ pmef->criteria |= mef_cfg->criteria;
+ memcpy_ext(pmadapter, &pmef->entry[6],
+ &mef_cfg->mef_entry, sizeof(mef_entry_t),
+ sizeof(mef_entry_t));
+ }
+ if (mef_cfg->mef_act_type == MEF_ACT_IPV6_NS) {
+ pmef->num_ipv6_ns_offload = 1;
+ pmef->criteria |= mef_cfg->criteria;
+ memcpy_ext(pmadapter, &pmef->entry[7],
+ &mef_cfg->mef_entry, sizeof(mef_entry_t),
+ sizeof(mef_entry_t));
+ }
+ break;
+ case MLAN_ACT_GET:
+ if (mef_cfg->mef_act_type == MEF_ACT_WOWLAN)
+ memcpy_ext(pmadapter, &mef_cfg->mef_entry,
+ &pmef->entry[6], sizeof(mef_entry_t),
+ sizeof(mef_entry_t));
+ break;
+ default:
+ pioctl_req->status_code = MLAN_ERROR_IOCTL_INVALID;
+ ret = MLAN_STATUS_FAILURE;
+ break;
+ }
+
+ LEAVE();
+ return ret;
+}
+
+/**
+ * @brief Set/Get WPA passphrase for esupplicant
+ *
+ * @param pmadapter A pointer to mlan_adapter structure
+ * @param pioctl_req A pointer to ioctl request buffer
+ *
+ * @return MLAN_STATUS_PENDING --success, otherwise fail
+ */
+mlan_status wlan_sec_ioctl_passphrase(pmlan_adapter pmadapter,
+ pmlan_ioctl_req pioctl_req)
+{
+ mlan_status ret = MLAN_STATUS_SUCCESS;
+ mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index];
+ mlan_ds_sec_cfg *sec = MNULL;
+ t_u16 cmd_action = 0;
+#ifdef STA_SUPPORT
+ BSSDescriptor_t *pbss_desc;
+ int i = 0;
+#endif
+ ENTER();
+
+ sec = (mlan_ds_sec_cfg *)pioctl_req->pbuf;
+#ifdef DRV_EMBEDDED_SUPPLICANT
+ if (GET_BSS_ROLE(pmpriv) == MLAN_BSS_ROLE_STA &&
+ !IS_FW_SUPPORT_SUPPLICANT(pmpriv->adapter)) {
+ if (sec->param.passphrase.psk_type == MLAN_PSK_QUERY)
+ SupplicantQueryPassphrase(
+ pmpriv->psapriv,
+ (void *)&sec->param.passphrase);
+ else if (sec->param.passphrase.psk_type == MLAN_PSK_CLEAR)
+ SupplicantClearPMK(pmpriv->psapriv,
+ (void *)&sec->param.passphrase);
+ else
+ SupplicantSetPassphrase(pmpriv->psapriv,
+ (void *)&sec->param.passphrase);
+
+ LEAVE();
+ return ret;
+ }
+#endif
+
+ if (!IS_FW_SUPPORT_SUPPLICANT(pmpriv->adapter)) {
+ LEAVE();
+ return ret;
+ }
+
+ if (pioctl_req->action == MLAN_ACT_SET) {
+ if (sec->param.passphrase.psk_type == MLAN_PSK_CLEAR)
+ cmd_action = HostCmd_ACT_GEN_REMOVE;
+ else
+ cmd_action = HostCmd_ACT_GEN_SET;
+ } else if (pioctl_req->action == MLAN_ACT_CLEAR) {
+ cmd_action = HostCmd_ACT_GEN_REMOVE;
+ } else {
+ if (sec->param.passphrase.psk_type == MLAN_PSK_QUERY) {
+#ifdef STA_SUPPORT
+ if (GET_BSS_ROLE(pmpriv) == MLAN_BSS_ROLE_STA &&
+ sec->param.passphrase.ssid.ssid_len == 0) {
+ i = wlan_find_bssid_in_list(
+ pmpriv,
+ (t_u8 *)&sec->param.passphrase.bssid,
+ MLAN_BSS_MODE_AUTO);
+ if (i >= 0) {
+ pbss_desc = &pmadapter->pscan_table[i];
+ memcpy_ext(pmadapter,
+ &sec->param.passphrase.ssid,
+ &pbss_desc->ssid,
+ sizeof(mlan_802_11_ssid),
+ sizeof(mlan_802_11_ssid));
+ memset(pmadapter,
+ &sec->param.passphrase.bssid, 0,
+ MLAN_MAC_ADDR_LENGTH);
+ PRINTM(MINFO,
+ "PSK_QUERY: found ssid=%s\n",
+ sec->param.passphrase.ssid.ssid);
+ }
+ } else
+#endif
+ memset(pmadapter, &sec->param.passphrase.bssid,
+ 0, MLAN_MAC_ADDR_LENGTH);
+ }
+ cmd_action = HostCmd_ACT_GEN_GET;
+ }
+
+ /* Send request to firmware */
+ ret = wlan_prepare_cmd(pmpriv, HostCmd_CMD_SUPPLICANT_PMK, cmd_action,
+ 0, (t_void *)pioctl_req, (t_void *)sec);
+ if (ret == MLAN_STATUS_SUCCESS)
+ ret = MLAN_STATUS_PENDING;
+
+ LEAVE();
+ return ret;
+}
+
+/**
+ * @brief Set per packet Txctl and Rxinfo configuration
+ *
+ * @param pmadapter A pointer to mlan_adapter structure
+ * @param pioctl_req A pointer to ioctl request buffer
+ *
+ * @return MLAN_STATUS_SUCCESS --success, otherwise fail
+ */
+mlan_status wlan_misc_per_pkt_cfg(pmlan_adapter pmadapter,
+ pmlan_ioctl_req pioctl_req)
+{
+ mlan_status ret = MLAN_STATUS_SUCCESS;
+ mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index];
+ mlan_ds_misc_cfg *misc = MNULL;
+
+ ENTER();
+
+ misc = (mlan_ds_misc_cfg *)pioctl_req->pbuf;
+ pmpriv->rx_pkt_info = MFALSE;
+ if (misc->param.txrx_pkt_ctrl & RX_PKT_INFO)
+ pmpriv->rx_pkt_info = MTRUE;
+
+ LEAVE();
+ return ret;
+}
+
+/**
+ * @brief Set/Get region code
+ *
+ * @param pmadapter A pointer to mlan_adapter structure
+ * @param pioctl_req A pointer to ioctl request buffer
+ *
+ * @return MLAN_STATUS_SUCCESS --success, otherwise fail
+ */
+mlan_status wlan_misc_ioctl_region(pmlan_adapter pmadapter,
+ pmlan_ioctl_req pioctl_req)
+{
+ mlan_status ret = MLAN_STATUS_SUCCESS;
+ mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index];
+ mlan_ds_misc_cfg *misc = MNULL;
+ int i;
+
+ ENTER();
+
+ misc = (mlan_ds_misc_cfg *)pioctl_req->pbuf;
+ if (pioctl_req->action == MLAN_ACT_GET) {
+ misc->param.region_code = pmadapter->region_code;
+ } else {
+ if (pmadapter->otp_region && pmadapter->otp_region->force_reg) {
+ PRINTM(MERROR,
+ "ForceRegionRule is set in the on-chip OTP"
+ " memory\n");
+ LEAVE();
+ return MLAN_STATUS_FAILURE;
+ }
+ for (i = 0; i < MRVDRV_MAX_REGION_CODE; i++) {
+ /* Use the region code to search for the index */
+ if (misc->param.region_code == region_code_index[i]) {
+ pmadapter->region_code =
+ (t_u16)misc->param.region_code;
+ break;
+ }
+ }
+ /* It's unidentified region code */
+ if (i >= MRVDRV_MAX_REGION_CODE) {
+ PRINTM(MERROR, "Region Code not identified\n");
+ pioctl_req->status_code = MLAN_ERROR_INVALID_PARAMETER;
+ LEAVE();
+ return MLAN_STATUS_FAILURE;
+ }
+ pmadapter->cfp_code_bg = misc->param.region_code;
+ pmadapter->cfp_code_a = misc->param.region_code;
+ if (wlan_set_regiontable(pmpriv, (t_u8)pmadapter->region_code,
+ pmadapter->config_bands |
+ pmadapter->adhoc_start_band)) {
+ pioctl_req->status_code = MLAN_ERROR_IOCTL_FAIL;
+ ret = MLAN_STATUS_FAILURE;
+ }
+ }
+ pioctl_req->data_read_written = sizeof(t_u32) + MLAN_SUB_COMMAND_SIZE;
+
+ LEAVE();
+ return ret;
+}
+
+/**
+ * @brief Configure GPIO independent reset
+ *
+ * @param pmadapter A pointer to mlan_adapter structure
+ * @param pioctl_req A pointer to ioctl request buffer
+ *
+ * @return MLAN_STATUS_PENDING --success, otherwise fail
+ */
+mlan_status wlan_misc_ioctl_ind_rst_cfg(pmlan_adapter pmadapter,
+ pmlan_ioctl_req pioctl_req)
+{
+ mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index];
+ mlan_ds_misc_cfg *misc = (mlan_ds_misc_cfg *)pioctl_req->pbuf;
+ mlan_status ret = MLAN_STATUS_SUCCESS;
+ t_u16 cmd_action = 0;
+
+ ENTER();
+
+ if (pioctl_req->action == MLAN_ACT_GET)
+ cmd_action = HostCmd_ACT_GEN_GET;
+ else
+ cmd_action = HostCmd_ACT_GEN_SET;
+
+ /* Send request to firmware */
+ ret = wlan_prepare_cmd(pmpriv, HostCmd_CMD_INDEPENDENT_RESET_CFG,
+ cmd_action, 0, (t_void *)pioctl_req,
+ (t_void *)&misc->param.ind_rst_cfg);
+
+ if (ret == MLAN_STATUS_SUCCESS)
+ ret = MLAN_STATUS_PENDING;
+
+ LEAVE();
+ return ret;
+}
+
+/**
+ * @brief Get timestamp from firmware
+ *
+ * @param pmadapter A pointer to mlan_adapter structure
+ * @param pioctl_req A pointer to ioctl request buffer
+ *
+ * @return MLAN_STATUS_PENDING --success, otherwise fail
+ */
+mlan_status wlan_misc_ioctl_get_tsf(pmlan_adapter pmadapter,
+ pmlan_ioctl_req pioctl_req)
+{
+ mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index];
+ mlan_status ret = MLAN_STATUS_SUCCESS;
+ t_u16 cmd_action = 0;
+
+ ENTER();
+
+ if (pioctl_req->action == MLAN_ACT_GET)
+ cmd_action = HostCmd_ACT_GEN_GET;
+ else {
+ PRINTM(MERROR, "No support set tsf!");
+ return MLAN_STATUS_FAILURE;
+ }
+
+ /* Send request to firmware */
+ ret = wlan_prepare_cmd(pmpriv, HostCmd_CMD_GET_TSF, cmd_action, 0,
+ (t_void *)pioctl_req, MNULL);
+
+ if (ret == MLAN_STATUS_SUCCESS)
+ ret = MLAN_STATUS_PENDING;
+
+ LEAVE();
+ return ret;
+}
+
+/**
+ * @brief Create custom regulatory cfg
+ *
+ * @param pmadapter A pointer to mlan_adapter structure
+ * @param pioctl_req A pointer to ioctl request buffer
+ *
+ * @return MLAN_STATUS_PENDING --success, otherwise fail
+ */
+mlan_status wlan_misc_chan_reg_cfg(pmlan_adapter pmadapter,
+ pmlan_ioctl_req pioctl_req)
+{
+ mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index];
+ mlan_status ret = MLAN_STATUS_SUCCESS;
+ t_u16 cmd_action = 0;
+
+ ENTER();
+
+ if (pioctl_req->action == MLAN_ACT_GET)
+ cmd_action = HostCmd_ACT_GEN_GET;
+ else {
+ PRINTM(MERROR, "No support set channel region cfg!");
+ return MLAN_STATUS_FAILURE;
+ }
+
+ /* Send request to firmware */
+ ret = wlan_prepare_cmd(pmpriv, HostCmd_CMD_CHAN_REGION_CFG, cmd_action,
+ 0, (t_void *)pioctl_req, MNULL);
+
+ if (ret == MLAN_STATUS_SUCCESS)
+ ret = MLAN_STATUS_PENDING;
+
+ LEAVE();
+ return ret;
+}
+
+/**
+ * @brief Check operating class validation
+ *
+ * @param pmadapter A pointer to mlan_adapter structure
+ * @param pioctl_req Pointer to the IOCTL request buffer
+ *
+ * @return MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ */
+mlan_status wlan_misc_ioctl_operclass_validation(pmlan_adapter pmadapter,
+ mlan_ioctl_req *pioctl_req)
+{
+ pmlan_private pmpriv = pmadapter->priv[pioctl_req->bss_index];
+ mlan_ds_misc_cfg *misc = MNULL;
+ t_u8 channel, oper_class;
+ mlan_status ret = MLAN_STATUS_SUCCESS;
+
+ ENTER();
+
+ misc = (mlan_ds_misc_cfg *)pioctl_req->pbuf;
+ channel = misc->param.bw_chan_oper.channel;
+ oper_class = misc->param.bw_chan_oper.oper_class;
+ if (pioctl_req->action == MLAN_ACT_GET) {
+ ret = wlan_check_operclass_validation(pmpriv, channel,
+ oper_class);
+ } else {
+ PRINTM(MERROR, "Unsupported cmd_action\n");
+ LEAVE();
+ return MLAN_STATUS_FAILURE;
+ }
+
+ LEAVE();
+ return ret;
+}
+
+/**
+ * @brief Get Region channel power setting
+ *
+ * @param pmadapter A pointer to mlan_adapter structure
+ * @param pioctl_req A pointer to ioctl request buffer
+ *
+ * @return MLAN_STATUS_PENDING --success, otherwise fail
+ */
+mlan_status wlan_get_rgchnpwr_cfg(pmlan_adapter pmadapter,
+ mlan_ioctl_req *pioctl_req)
+{
+ mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index];
+ mlan_status ret = MLAN_STATUS_SUCCESS;
+ t_u16 cmd_action = 0;
+ mlan_ds_misc_cfg *misc = MNULL;
+
+ ENTER();
+
+ misc = (mlan_ds_misc_cfg *)pioctl_req->pbuf;
+ cmd_action = HostCmd_ACT_GEN_GET;
+
+ /* Send request to firmware */
+ ret = wlan_prepare_cmd(pmpriv, HostCmd_CMD_CHAN_REGION_CFG, cmd_action,
+ 0, (t_void *)pioctl_req, MNULL);
+
+ if (ret == MLAN_STATUS_SUCCESS)
+ ret = MLAN_STATUS_PENDING;
+
+ LEAVE();
+ return ret;
+}
+
+/**
+ * @brief Get CHAN_TPRC setting
+ *
+ * @param pmadapter A pointer to mlan_adapter structure
+ * @param pioctl_req A pointer to ioctl request buffer
+ *
+ * @return MLAN_STATUS_PENDING --success, otherwise fail
+ */
+mlan_status wlan_get_chan_trpc_cfg(pmlan_adapter pmadapter,
+ mlan_ioctl_req *pioctl_req)
+{
+ mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index];
+ mlan_status ret = MLAN_STATUS_SUCCESS;
+ t_u16 cmd_action = 0;
+ mlan_ds_misc_cfg *misc = MNULL;
+
+ ENTER();
+
+ misc = (mlan_ds_misc_cfg *)pioctl_req->pbuf;
+ cmd_action = HostCmd_ACT_GEN_GET;
+
+ /* Send request to firmware */
+ ret = wlan_prepare_cmd(pmpriv, HostCmd_CHANNEL_TRPC_CONFIG, cmd_action,
+ 0, (t_void *)pioctl_req,
+ (t_void *)&misc->param.trpc_cfg);
+
+ if (ret == MLAN_STATUS_SUCCESS)
+ ret = MLAN_STATUS_PENDING;
+
+ LEAVE();
+ return ret;
+}
+
+/**
+ * @brief Get non-global operating class
+ *
+ * @param pmadapter A pointer to mlan_adapter structure
+ * @param pioctl_req Pointer to the IOCTL request buffer
+ *
+ * @return MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ */
+mlan_status wlan_misc_ioctl_oper_class(pmlan_adapter pmadapter,
+ mlan_ioctl_req *pioctl_req)
+{
+ pmlan_private pmpriv = pmadapter->priv[pioctl_req->bss_index];
+ mlan_ds_misc_cfg *misc = MNULL;
+ t_u8 channel, bandwidth, oper_class = 0;
+ mlan_status ret = MLAN_STATUS_SUCCESS;
+
+ ENTER();
+
+ misc = (mlan_ds_misc_cfg *)pioctl_req->pbuf;
+ channel = misc->param.bw_chan_oper.channel;
+ switch (misc->param.bw_chan_oper.bandwidth) {
+ case 20:
+ bandwidth = BW_20MHZ;
+ break;
+ case 40:
+ bandwidth = BW_40MHZ;
+ break;
+ case 80:
+ bandwidth = BW_80MHZ;
+ break;
+ default:
+ bandwidth = BW_20MHZ;
+ break;
+ }
+
+ if (pioctl_req->action == MLAN_ACT_GET) {
+ ret = wlan_get_curr_oper_class(pmpriv, channel, bandwidth,
+ &oper_class);
+ misc->param.bw_chan_oper.oper_class = oper_class;
+ } else {
+ PRINTM(MERROR, "Unsupported cmd_action\n");
+ LEAVE();
+ return MLAN_STATUS_FAILURE;
+ }
+
+ LEAVE();
+ return ret;
+}
+
+/**
+ * @brief config dynamic bandwidth
+ *
+ * @param pmadapter A pointer to mlan_adapter structure
+ * @param pioctl_req Pointer to the IOCTL request buffer
+ *
+ * @return MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ */
+mlan_status wlan_misc_ioctl_fw_dump_event(pmlan_adapter pmadapter,
+ mlan_ioctl_req *pioctl_req)
+{
+ pmlan_private pmpriv = pmadapter->priv[pioctl_req->bss_index];
+ mlan_ds_misc_cfg *misc = MNULL;
+ t_u16 cmd_action = 0;
+ mlan_status ret = MLAN_STATUS_SUCCESS;
+
+ ENTER();
+
+ misc = (mlan_ds_misc_cfg *)pioctl_req->pbuf;
+
+ if (pioctl_req->action == MLAN_ACT_SET)
+ cmd_action = HostCmd_ACT_GEN_SET;
+ else if (pioctl_req->action == MLAN_ACT_GET)
+ cmd_action = HostCmd_ACT_GEN_GET;
+ else {
+ PRINTM(MERROR, "Unsupported cmd_action\n");
+ LEAVE();
+ return MLAN_STATUS_FAILURE;
+ }
+
+ /* Send request to firmware */
+ ret = wlan_prepare_cmd(pmpriv, HostCmd_CMD_FW_DUMP_EVENT, cmd_action, 0,
+ (t_void *)pioctl_req, MNULL);
+
+ if (ret == MLAN_STATUS_SUCCESS)
+ ret = MLAN_STATUS_PENDING;
+
+ LEAVE();
+ return ret;
+}
+
+/**
+ * @brief config boot sleep
+ *
+ * @param pmadapter A pointer to mlan_adapter structure
+ * @param pioctl_req Pointer to the IOCTL request buffer
+ *
+ * @return MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ */
+mlan_status wlan_misc_bootsleep(pmlan_adapter pmadapter,
+ pmlan_ioctl_req pioctl_req)
+{
+ pmlan_private pmpriv = pmadapter->priv[pioctl_req->bss_index];
+ mlan_ds_misc_cfg *misc = MNULL;
+ t_u16 cmd_action = 0;
+ mlan_status ret = MLAN_STATUS_SUCCESS;
+
+ ENTER();
+
+ misc = (mlan_ds_misc_cfg *)pioctl_req->pbuf;
+
+ if (pioctl_req->action == MLAN_ACT_SET)
+ cmd_action = HostCmd_ACT_GEN_SET;
+ else if (pioctl_req->action == MLAN_ACT_GET)
+ cmd_action = HostCmd_ACT_GEN_GET;
+ else {
+ PRINTM(MERROR, "Unsupported cmd_action 0x%x\n",
+ pioctl_req->action);
+ LEAVE();
+ return MLAN_STATUS_FAILURE;
+ }
+
+ /* Send request to firmware */
+ ret = wlan_prepare_cmd(pmpriv, HostCmd_CMD_BOOT_SLEEP, cmd_action, 0,
+ (t_void *)pioctl_req, &misc->param.boot_sleep);
+
+ if (ret == MLAN_STATUS_SUCCESS)
+ ret = MLAN_STATUS_PENDING;
+
+ LEAVE();
+ return ret;
+}
+
+/**
+ * @brief Set/Get Infra/Ad-hoc band configuration
+ *
+ * @param pmadapter A pointer to mlan_adapter structure
+ * @param pioctl_req A pointer to ioctl request buffer
+ *
+ * @return MLAN_STATUS_SUCCESS --success, otherwise fail
+ */
+mlan_status wlan_radio_ioctl_band_cfg(pmlan_adapter pmadapter,
+ pmlan_ioctl_req pioctl_req)
+{
+ t_u32 i, global_band = 0;
+ t_u32 infra_band = 0;
+ t_u32 adhoc_band = 0;
+ t_u32 adhoc_channel = 0;
+ mlan_ds_radio_cfg *radio_cfg = MNULL;
+ mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index];
+
+ ENTER();
+
+ radio_cfg = (mlan_ds_radio_cfg *)pioctl_req->pbuf;
+ if (pioctl_req->action == MLAN_ACT_SET) {
+ infra_band = radio_cfg->param.band_cfg.config_bands;
+ adhoc_band = radio_cfg->param.band_cfg.adhoc_start_band;
+ adhoc_channel = radio_cfg->param.band_cfg.adhoc_channel;
+
+ /* SET Infra band */
+ if ((infra_band | pmadapter->fw_bands) & ~pmadapter->fw_bands) {
+ pioctl_req->status_code = MLAN_ERROR_INVALID_PARAMETER;
+ LEAVE();
+ return MLAN_STATUS_FAILURE;
+ }
+
+ /* SET Ad-hoc Band */
+ if ((adhoc_band | pmadapter->fw_bands) & ~pmadapter->fw_bands) {
+ pioctl_req->status_code = MLAN_ERROR_INVALID_PARAMETER;
+ LEAVE();
+ return MLAN_STATUS_FAILURE;
+ }
+ if (!adhoc_band)
+ adhoc_band = pmadapter->adhoc_start_band;
+
+ for (i = 0; i < pmadapter->priv_num; i++) {
+ if (pmadapter->priv[i] &&
+ pmadapter->priv[i] != pmpriv &&
+ GET_BSS_ROLE(pmadapter->priv[i]) ==
+ MLAN_BSS_ROLE_STA)
+ global_band |=
+ (t_u32)pmadapter->priv[i]->config_bands;
+ }
+ global_band |= infra_band;
+
+ if (wlan_set_regiontable(pmpriv, (t_u8)pmadapter->region_code,
+ global_band | adhoc_band)) {
+ pioctl_req->status_code = MLAN_ERROR_IOCTL_FAIL;
+ LEAVE();
+ return MLAN_STATUS_FAILURE;
+ }
+#ifdef STA_SUPPORT
+ if (wlan_11d_set_universaltable(pmpriv,
+ global_band | adhoc_band)) {
+ pioctl_req->status_code = MLAN_ERROR_IOCTL_FAIL;
+ LEAVE();
+ return MLAN_STATUS_FAILURE;
+ }
+#endif
+ pmpriv->config_bands = infra_band;
+ pmadapter->config_bands = global_band;
+
+ pmadapter->adhoc_start_band = adhoc_band;
+ pmpriv->intf_state_11h.adhoc_auto_sel_chan = MFALSE;
+
+#ifdef STA_SUPPORT
+ /*
+ * If no adhoc_channel is supplied verify if the existing
+ * adhoc channel compiles with new adhoc_band
+ */
+ if (!adhoc_channel) {
+ if (!wlan_find_cfp_by_band_and_channel(
+ pmadapter, pmadapter->adhoc_start_band,
+ pmpriv->adhoc_channel)) {
+ /* Pass back the default channel */
+ radio_cfg->param.band_cfg.adhoc_channel =
+ DEFAULT_AD_HOC_CHANNEL;
+ if ((pmadapter->adhoc_start_band & BAND_A)) {
+ radio_cfg->param.band_cfg.adhoc_channel =
+ DEFAULT_AD_HOC_CHANNEL_A;
+ }
+ }
+ } else {
+ /* Return error if adhoc_band and adhoc_channel
+ * combination is invalid
+ */
+ if (!wlan_find_cfp_by_band_and_channel(
+ pmadapter, pmadapter->adhoc_start_band,
+ (t_u16)adhoc_channel)) {
+ pioctl_req->status_code =
+ MLAN_ERROR_INVALID_PARAMETER;
+ LEAVE();
+ return MLAN_STATUS_FAILURE;
+ }
+ pmpriv->adhoc_channel = (t_u8)adhoc_channel;
+ }
+
+#endif
+
+ } else {
+ /* Infra Bands */
+ radio_cfg->param.band_cfg.config_bands = pmpriv->config_bands;
+ /* Adhoc Band */
+ radio_cfg->param.band_cfg.adhoc_start_band =
+ pmadapter->adhoc_start_band;
+ /* Adhoc Channel */
+ radio_cfg->param.band_cfg.adhoc_channel = pmpriv->adhoc_channel;
+ /* FW support Bands */
+ radio_cfg->param.band_cfg.fw_bands = pmadapter->fw_bands;
+ PRINTM(MINFO, "Global config band = %d\n",
+ pmadapter->config_bands);
+#ifdef STA_SUPPORT
+#endif
+ }
+
+ LEAVE();
+ return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ * @brief Rx Abort Cfg
+ *
+ * @param pmadapter A pointer to mlan_adapter structure
+ * @param pioctl_req A pointer to ioctl request buffer
+ *
+ * @return MLAN_STATUS_PENDING --success, otherwise fail
+ */
+mlan_status wlan_misc_ioctl_rxabortcfg(pmlan_adapter pmadapter,
+ pmlan_ioctl_req pioctl_req)
+{
+ mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index];
+ mlan_ds_misc_cfg *pmisc = (mlan_ds_misc_cfg *)pioctl_req->pbuf;
+ mlan_status ret = MLAN_STATUS_SUCCESS;
+ t_u16 cmd_action = 0;
+
+ ENTER();
+
+ if (pioctl_req->action == MLAN_ACT_SET)
+ cmd_action = HostCmd_ACT_GEN_SET;
+ else
+ cmd_action = HostCmd_ACT_GEN_GET;
+ ret = wlan_prepare_cmd(pmpriv, HostCmd_CMD_RX_ABORT_CFG, cmd_action, 0,
+ (t_void *)pioctl_req,
+ &(pmisc->param.rx_abort_cfg));
+ if (ret == MLAN_STATUS_SUCCESS)
+ ret = MLAN_STATUS_PENDING;
+
+ LEAVE();
+ return ret;
+}
+/**
+ * @brief Rx Abort Cfg ext
+ *
+ * @param pmadapter A pointer to mlan_adapter structure
+ * @param pioctl_req A pointer to ioctl request buffer
+ *
+ * @return MLAN_STATUS_PENDING --success, otherwise fail
+ */
+mlan_status wlan_misc_ioctl_rxabortcfg_ext(pmlan_adapter pmadapter,
+ pmlan_ioctl_req pioctl_req)
+{
+ mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index];
+ mlan_ds_misc_cfg *pmisc = (mlan_ds_misc_cfg *)pioctl_req->pbuf;
+ mlan_status ret = MLAN_STATUS_SUCCESS;
+ t_u16 cmd_action = 0;
+
+ ENTER();
+
+ if (pioctl_req->action == MLAN_ACT_SET)
+ cmd_action = HostCmd_ACT_GEN_SET;
+ else
+ cmd_action = HostCmd_ACT_GEN_GET;
+ ret = wlan_prepare_cmd(pmpriv, HostCmd_CMD_RX_ABORT_CFG_EXT, cmd_action,
+ 0, (t_void *)pioctl_req,
+ &(pmisc->param.rx_abort_cfg_ext));
+ if (ret == MLAN_STATUS_SUCCESS)
+ ret = MLAN_STATUS_PENDING;
+
+ LEAVE();
+ return ret;
+}
+
+/**
+ * @brief Dot11mc unassociated FTM CFG
+ *
+ * @param pmadapter A pointer to mlan_adapter structure
+ * @param pioctl_req A pointer to ioctl request buffer
+ *
+ * @return MLAN_STATUS_PENDING --success, otherwise fail
+ */
+mlan_status wlan_misc_ioctl_dot11mc_unassoc_ftm_cfg(pmlan_adapter pmadapter,
+ pmlan_ioctl_req pioctl_req)
+{
+ mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index];
+ mlan_ds_misc_cfg *pmisc = (mlan_ds_misc_cfg *)pioctl_req->pbuf;
+ mlan_status ret = MLAN_STATUS_SUCCESS;
+ t_u16 cmd_action = 0;
+
+ ENTER();
+
+ if (pioctl_req->action == MLAN_ACT_SET)
+ cmd_action = HostCmd_ACT_GEN_SET;
+ else
+ cmd_action = HostCmd_ACT_GEN_GET;
+ ret = wlan_prepare_cmd(pmpriv, HostCmd_CMD_DOT11MC_UNASSOC_FTM_CFG,
+ cmd_action, 0, (t_void *)pioctl_req,
+ &(pmisc->param.dot11mc_unassoc_ftm_cfg));
+ if (ret == MLAN_STATUS_SUCCESS)
+ ret = MLAN_STATUS_PENDING;
+
+ LEAVE();
+ return ret;
+}
+
+/**
+ * @brief Tx ampdu protection mode
+ *
+ * @param pmadapter A pointer to mlan_adapter structure
+ * @param pioctl_req A pointer to ioctl request buffer
+ *
+ * @return MLAN_STATUS_PENDING --success, otherwise fail
+ */
+mlan_status wlan_misc_ioctl_tx_ampdu_prot_mode(pmlan_adapter pmadapter,
+ pmlan_ioctl_req pioctl_req)
+{
+ mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index];
+ mlan_ds_misc_cfg *pmisc = (mlan_ds_misc_cfg *)pioctl_req->pbuf;
+ mlan_status ret = MLAN_STATUS_SUCCESS;
+ t_u16 cmd_action = 0;
+
+ ENTER();
+
+ if (pioctl_req->action == MLAN_ACT_SET)
+ cmd_action = HostCmd_ACT_GEN_SET;
+ else
+ cmd_action = HostCmd_ACT_GEN_GET;
+ ret = wlan_prepare_cmd(pmpriv, HostCmd_CMD_TX_AMPDU_PROT_MODE,
+ cmd_action, 0, (t_void *)pioctl_req,
+ &(pmisc->param.tx_ampdu_prot_mode));
+ if (ret == MLAN_STATUS_SUCCESS)
+ ret = MLAN_STATUS_PENDING;
+
+ LEAVE();
+ return ret;
+}
+
+/**
+ * @brief Rate adapt config
+ *
+ * @param pmadapter A pointer to mlan_adapter structure
+ * @param pioctl_req A pointer to ioctl request buffer
+ *
+ * @return MLAN_STATUS_PENDING --success, otherwise fail
+ */
+mlan_status wlan_misc_ioctl_rate_adapt_cfg(pmlan_adapter pmadapter,
+ pmlan_ioctl_req pioctl_req)
+{
+ mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index];
+ mlan_ds_misc_cfg *pmisc = (mlan_ds_misc_cfg *)pioctl_req->pbuf;
+ mlan_status ret = MLAN_STATUS_SUCCESS;
+ t_u16 cmd_action = 0;
+
+ ENTER();
+
+ if (pioctl_req->action == MLAN_ACT_SET)
+ cmd_action = HostCmd_ACT_GEN_SET;
+ else
+ cmd_action = HostCmd_ACT_GEN_GET;
+ ret = wlan_prepare_cmd(pmpriv, HostCmd_CMD_RATE_ADAPT_CFG, cmd_action,
+ 0, (t_void *)pioctl_req,
+ &(pmisc->param.rate_adapt_cfg));
+ if (ret == MLAN_STATUS_SUCCESS)
+ ret = MLAN_STATUS_PENDING;
+
+ LEAVE();
+ return ret;
+}
+
+/**
+ * @brief CCK Desense config
+ *
+ * @param pmadapter A pointer to mlan_adapter structure
+ * @param pioctl_req A pointer to ioctl request buffer
+ *
+ * @return MLAN_STATUS_PENDING --success, otherwise fail
+ */
+mlan_status wlan_misc_ioctl_cck_desense_cfg(pmlan_adapter pmadapter,
+ pmlan_ioctl_req pioctl_req)
+{
+ mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index];
+ mlan_ds_misc_cfg *pmisc = (mlan_ds_misc_cfg *)pioctl_req->pbuf;
+ mlan_status ret = MLAN_STATUS_SUCCESS;
+ t_u16 cmd_action = 0;
+
+ ENTER();
+
+ if (pioctl_req->action == MLAN_ACT_SET)
+ cmd_action = HostCmd_ACT_GEN_SET;
+ else
+ cmd_action = HostCmd_ACT_GEN_GET;
+ ret = wlan_prepare_cmd(pmpriv, HostCmd_CMD_CCK_DESENSE_CFG, cmd_action,
+ 0, (t_void *)pioctl_req,
+ &(pmisc->param.cck_desense_cfg));
+ if (ret == MLAN_STATUS_SUCCESS)
+ ret = MLAN_STATUS_PENDING;
+
+ LEAVE();
+ return ret;
+}
+
+/**
+ * @brief config dynamic bandwidth
+ *
+ * @param pmadapter A pointer to mlan_adapter structure
+ * @param pioctl_req Pointer to the IOCTL request buffer
+ *
+ * @return MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ */
+mlan_status wlan_misc_ioctl_dyn_bw(pmlan_adapter pmadapter,
+ mlan_ioctl_req *pioctl_req)
+{
+ pmlan_private pmpriv = pmadapter->priv[pioctl_req->bss_index];
+ mlan_ds_misc_cfg *misc = MNULL;
+ t_u16 cmd_action = 0;
+ mlan_status ret = MLAN_STATUS_SUCCESS;
+
+ ENTER();
+
+ misc = (mlan_ds_misc_cfg *)pioctl_req->pbuf;
+
+ if (pioctl_req->action == MLAN_ACT_SET)
+ cmd_action = HostCmd_ACT_GEN_SET;
+ else if (pioctl_req->action == MLAN_ACT_GET)
+ cmd_action = HostCmd_ACT_GEN_GET;
+ else {
+ PRINTM(MERROR, "Unsupported cmd_action\n");
+ LEAVE();
+ return MLAN_STATUS_FAILURE;
+ }
+
+ /* Send request to firmware */
+ ret = wlan_prepare_cmd(pmpriv, HostCmd_CMD_DYN_BW, cmd_action, 0,
+ (t_void *)pioctl_req, &misc->param.dyn_bw);
+
+ if (ret == MLAN_STATUS_SUCCESS)
+ ret = MLAN_STATUS_PENDING;
+
+ LEAVE();
+ return ret;
+}
+
+/**
+ * @brief Set/Get low power mode configuration parameter
+ *
+ * @param pmadapter A pointer to mlan_adapter structure
+ * @param pioctl_req A pointer to ioctl request buffer
+ *
+ * @return MLAN_STATUS_SUCCESS --success
+ */
+mlan_status wlan_power_ioctl_set_get_lpm(pmlan_adapter pmadapter,
+ pmlan_ioctl_req pioctl_req)
+{
+ mlan_status ret = MLAN_STATUS_SUCCESS;
+ mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index];
+ mlan_ds_power_cfg *pm_cfg = MNULL;
+ t_u16 cmd_action = 0, lpm = 0;
+
+ ENTER();
+
+ pm_cfg = (mlan_ds_power_cfg *)pioctl_req->pbuf;
+ cmd_action = HostCmd_ACT_GEN_GET;
+ if (pioctl_req->action == MLAN_ACT_SET) {
+ cmd_action = HostCmd_ACT_GEN_SET;
+ lpm = pm_cfg->param.lpm;
+ }
+
+ ret = wlan_prepare_cmd(pmpriv, HostCmd_CMD_LOW_POWER_MODE_CFG,
+ cmd_action, 0, (t_void *)pioctl_req, &lpm);
+
+ if (ret == MLAN_STATUS_SUCCESS)
+ ret = MLAN_STATUS_PENDING;
+
+ LEAVE();
+ return ret;
+}
+
+/**
+ * @brief RF Test Mode config
+ *
+ * @param pmadapter A pointer to mlan_adapter structure
+ * @param pioctl_req A pointer to ioctl request buffer
+ *
+ * @return MLAN_STATUS_PENDING --success, otherwise fail
+ */
+mlan_status wlan_misc_ioctl_rf_test_cfg(pmlan_adapter pmadapter,
+ pmlan_ioctl_req pioctl_req)
+{
+ mlan_private *pmpriv = MNULL;
+ mlan_ds_misc_cfg *pmisc = MNULL;
+ mlan_status ret = MLAN_STATUS_FAILURE;
+ t_u16 cmd_action = 0;
+
+ ENTER();
+
+ if (!pioctl_req)
+ goto done;
+
+ pmpriv = pmadapter->priv[pioctl_req->bss_index];
+ pmisc = (mlan_ds_misc_cfg *)pioctl_req->pbuf;
+
+ switch (pmisc->sub_command) {
+ case MLAN_OID_MISC_RF_TEST_GENERIC:
+ if (pioctl_req->action == MLAN_ACT_SET)
+ cmd_action = HostCmd_ACT_GEN_SET;
+ else
+ cmd_action = HostCmd_ACT_GEN_GET;
+ ret = wlan_prepare_cmd(pmpriv, HostCmd_CMD_MFG_COMMAND,
+ cmd_action, 0, (t_void *)pioctl_req,
+ &(pmisc->param.mfg_generic_cfg));
+ break;
+ case MLAN_OID_MISC_RF_TEST_TX_CONT:
+ if (pioctl_req->action == MLAN_ACT_SET)
+ cmd_action = HostCmd_ACT_GEN_SET;
+ else {
+ PRINTM(MERROR, "Unsupported cmd_action\n");
+ ret = MLAN_STATUS_FAILURE;
+ goto done;
+ }
+ ret = wlan_prepare_cmd(pmpriv, HostCmd_CMD_MFG_COMMAND,
+ cmd_action, 0, (t_void *)pioctl_req,
+ &(pmisc->param.mfg_tx_cont));
+ break;
+ case MLAN_OID_MISC_RF_TEST_TX_FRAME:
+ if (pioctl_req->action == MLAN_ACT_SET)
+ cmd_action = HostCmd_ACT_GEN_SET;
+ else {
+ PRINTM(MERROR, "Unsupported cmd_action\n");
+ ret = MLAN_STATUS_FAILURE;
+ goto done;
+ }
+ ret = wlan_prepare_cmd(pmpriv, HostCmd_CMD_MFG_COMMAND,
+ cmd_action, 0, (t_void *)pioctl_req,
+ &(pmisc->param.mfg_tx_frame2));
+ break;
+ }
+ if (ret == MLAN_STATUS_SUCCESS)
+ ret = MLAN_STATUS_PENDING;
+done:
+ LEAVE();
+ return ret;
+}
+
+/**
+ * @brief Range ext mode config
+ *
+ * @param pmadapter A pointer to mlan_adapter structure
+ * @param pioctl_req A pointer to ioctl request buffer
+ *
+ * @return MLAN_STATUS_PENDING --success, otherwise fail
+ */
+mlan_status wlan_misc_ioctl_range_ext(pmlan_adapter pmadapter,
+ pmlan_ioctl_req pioctl_req)
+{
+ mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index];
+ mlan_ds_misc_cfg *pmisc = (mlan_ds_misc_cfg *)pioctl_req->pbuf;
+ mlan_status ret = MLAN_STATUS_SUCCESS;
+ t_u16 cmd_action = 0;
+
+ ENTER();
+
+ if (pioctl_req->action == MLAN_ACT_SET)
+ cmd_action = HostCmd_ACT_GEN_SET;
+ else
+ cmd_action = HostCmd_ACT_GEN_GET;
+ ret = wlan_prepare_cmd(pmpriv, HostCmd_CMD_RANGE_EXT, cmd_action, 0,
+ (t_void *)pioctl_req,
+ &(pmisc->param.range_ext_mode));
+ if (ret == MLAN_STATUS_SUCCESS)
+ ret = MLAN_STATUS_PENDING;
+
+ LEAVE();
+ return ret;
+}
diff --git a/drivers/net/wireless/nxp/mxm_wifiex/wlan_src/mlan/mlan_module.c b/drivers/net/wireless/nxp/mxm_wifiex/wlan_src/mlan/mlan_module.c
new file mode 100644
index 000000000000..4e26b90010bb
--- /dev/null
+++ b/drivers/net/wireless/nxp/mxm_wifiex/wlan_src/mlan/mlan_module.c
@@ -0,0 +1,65 @@
+/** @file mlan_module.c
+ *
+ * @brief This file declares the exported symbols from MLAN.
+ *
+ *
+ * Copyright 2014-2020 NXP
+ *
+ * This software file (the File) is distributed by NXP
+ * under the terms of the GNU General Public License Version 2, June 1991
+ * (the License). You may use, redistribute and/or modify the 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.
+ *
+ */
+
+/******************************************************
+Change log:
+ 12/08/2008: initial version
+******************************************************/
+
+#ifdef LINUX
+#include <linux/module.h>
+#include "mlan_decl.h"
+#include "mlan_ioctl.h"
+
+EXPORT_SYMBOL(mlan_register);
+EXPORT_SYMBOL(mlan_unregister);
+EXPORT_SYMBOL(mlan_init_fw);
+EXPORT_SYMBOL(mlan_set_init_param);
+EXPORT_SYMBOL(mlan_dnld_fw);
+EXPORT_SYMBOL(mlan_shutdown_fw);
+#ifdef USB
+EXPORT_SYMBOL(mlan_write_data_async_complete);
+EXPORT_SYMBOL(mlan_recv);
+#endif
+EXPORT_SYMBOL(mlan_send_packet);
+EXPORT_SYMBOL(mlan_ioctl);
+EXPORT_SYMBOL(mlan_main_process);
+EXPORT_SYMBOL(mlan_rx_process);
+EXPORT_SYMBOL(mlan_select_wmm_queue);
+#if defined(SDIO) || defined(PCIE)
+EXPORT_SYMBOL(mlan_interrupt);
+#if defined(SYSKT)
+EXPORT_SYMBOL(mlan_hs_callback);
+#endif /* SYSKT_MULTI || SYSKT */
+#endif /* SDIO || PCIE */
+
+EXPORT_SYMBOL(mlan_pm_wakeup_card);
+EXPORT_SYMBOL(mlan_is_main_process_running);
+#ifdef PCIE
+EXPORT_SYMBOL(mlan_set_int_mode);
+#endif
+
+MODULE_DESCRIPTION("M-WLAN MLAN Driver");
+MODULE_AUTHOR("NXP");
+MODULE_VERSION(MLAN_RELEASE_VERSION);
+MODULE_LICENSE("GPL");
+#endif /* LINUX */
diff --git a/drivers/net/wireless/nxp/mxm_wifiex/wlan_src/mlan/mlan_pcie.c b/drivers/net/wireless/nxp/mxm_wifiex/wlan_src/mlan/mlan_pcie.c
new file mode 100644
index 000000000000..51e55a90b73b
--- /dev/null
+++ b/drivers/net/wireless/nxp/mxm_wifiex/wlan_src/mlan/mlan_pcie.c
@@ -0,0 +1,4205 @@
+/** @file mlan_pcie.c
+ *
+ * @brief This file contains PCI-E specific code
+ *
+ *
+ * Copyright 2014-2020 NXP
+ *
+ * This software file (the File) is distributed by NXP
+ * under the terms of the GNU General Public License Version 2, June 1991
+ * (the License). You may use, redistribute and/or modify the 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.
+ *
+ */
+
+/********************************************************
+Change log:
+ 02/01/2012: initial version
+********************************************************/
+
+#include "mlan.h"
+#ifdef STA_SUPPORT
+#include "mlan_join.h"
+#endif
+#include "mlan_util.h"
+#include "mlan_fw.h"
+#include "mlan_main.h"
+#include "mlan_init.h"
+#include "mlan_wmm.h"
+#include "mlan_11n.h"
+#include "mlan_pcie.h"
+
+/********************************************************
+ Local Variables
+********************************************************/
+
+/********************************************************
+ Global Variables
+********************************************************/
+
+/********************************************************
+ Local Functions
+********************************************************/
+
+static mlan_status wlan_pcie_delete_evtbd_ring(pmlan_adapter pmadapter);
+static mlan_status wlan_pcie_delete_rxbd_ring(pmlan_adapter pmadapter);
+
+#if defined(PCIE9098) || defined(PCIE9097)
+/**
+ * @brief This function init the adma setting
+ *
+ * @param pmadapter A pointer to mlan_adapter structure
+ * @param adma_type TX/RX data, event, cmd/cmdresp
+ * @param pbase physical address
+ * @param size desc num/dma_size
+ * @param init init flag
+ *
+ * @return MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ */
+static mlan_status wlan_init_adma(mlan_adapter *pmadapter, t_u8 type,
+ t_u64 pbase, t_u16 size, t_u8 init)
+{
+ t_u32 dma_cfg, dma_cfg2, int_mapping;
+ mlan_status ret = MLAN_STATUS_SUCCESS;
+ t_u32 q_addr = 0;
+ t_u8 direction = 0;
+ t_u8 dma_mode = 0;
+ t_u32 msix_data;
+ t_u32 msix_vector;
+ pmlan_callbacks pcb = &pmadapter->callbacks;
+ ENTER();
+ if (init)
+ PRINTM(MCMND, "Init ADMA: type=%d, size=%d init=%d\n", type,
+ size, init);
+ switch (type) {
+ case ADMA_TX_DATA:
+ q_addr = ADMA_CHAN0_Q0;
+ direction = ADMA_HOST_TO_DEVICE;
+ dma_mode = DMA_MODE_DUAL_DESC;
+ msix_vector = ADMA_VECTOR_CHAN0_Q0;
+ break;
+ case ADMA_RX_DATA:
+ q_addr = ADMA_CHAN1_Q0;
+ direction = ADMA_DEVICE_TO_HOST;
+ dma_mode = DMA_MODE_DUAL_DESC;
+ msix_vector = AMDA_VECTOR_CHAN1_Q0;
+ break;
+ case ADMA_EVENT:
+ q_addr = ADMA_CHAN1_Q1;
+ direction = ADMA_DEVICE_TO_HOST;
+ dma_mode = DMA_MODE_DUAL_DESC;
+ msix_vector = AMDA_VECTOR_CHAN1_Q1;
+ break;
+ case ADMA_CMD:
+ q_addr = ADMA_CHAN2_Q0;
+ direction = ADMA_HOST_TO_DEVICE;
+ dma_mode = DMA_MODE_DIRECT;
+ msix_vector = AMDA_VECTOR_CHAN2_Q0;
+ break;
+ case ADMA_CMDRESP:
+ q_addr = ADMA_CHAN2_Q1;
+ direction = ADMA_DEVICE_TO_HOST;
+ dma_mode = DMA_MODE_DIRECT;
+ msix_vector = AMDA_VECTOR_CHAN2_Q1;
+ break;
+ default:
+ PRINTM(MERROR, "unknow adma type\n");
+ ret = MLAN_STATUS_FAILURE;
+ break;
+ }
+ if (ret)
+ goto done;
+ if (init) {
+ if (dma_mode == DMA_MODE_DUAL_DESC) {
+ if (direction == ADMA_HOST_TO_DEVICE)
+ int_mapping = DEST_INT_TO_DEVICE;
+ else
+ int_mapping = DEST_INT_TO_HOST;
+ } else {
+ int_mapping = 0;
+ }
+ /* set INT_MAPPING register */
+ if (pcb->moal_write_reg(pmadapter->pmoal_handle,
+ q_addr + ADMA_INT_MAPPING,
+ (t_u32)int_mapping)) {
+ PRINTM(MERROR,
+ "Failed to write ADMA_INT_MAPPING register.\n");
+ ret = MLAN_STATUS_FAILURE;
+ goto done;
+ }
+
+ /* Read the dma_cfg2 register */
+ if (pcb->moal_read_reg(pmadapter->pmoal_handle,
+ q_addr + ADMA_DMA_CFG2, &dma_cfg2)) {
+ PRINTM(MERROR, "Fail to read DMA CFG2 register\n");
+ ret = MLAN_STATUS_FAILURE;
+ goto done;
+ }
+ dma_cfg2 &= ~(ADMA_SRC_DMA_DONE_INT_BYPASS_EN |
+ ADMA_DST_DMA_DONE_INT_BYPASS_EN |
+ ADMA_MSI_LEGACY_SRC_DMA_DONE_INT_BYPASS_EN |
+ ADMA_MSI_LEGACY_DST_DMA_DONE_INT_BYPASS_EN |
+ ADMA_MSI_LEGACY_ENABLE | ADMA_MSIX_ENABLE |
+ ADMA_MSIX_INT_SRC_DST_SEL);
+
+ if (dma_mode == DMA_MODE_DUAL_DESC) {
+ if (direction == ADMA_HOST_TO_DEVICE) {
+ dma_cfg2 |= ADMA_SRC_DMA_DONE_INT_BYPASS_EN;
+ if (pmadapter->pcard_pcie->pcie_int_mode !=
+ PCIE_INT_MODE_MSIX)
+ dma_cfg2 |=
+ ADMA_MSI_LEGACY_SRC_DMA_DONE_INT_BYPASS_EN;
+ } else {
+ dma_cfg2 |= ADMA_DST_DMA_DONE_INT_BYPASS_EN;
+ if (pmadapter->pcard_pcie->pcie_int_mode !=
+ PCIE_INT_MODE_MSIX)
+ dma_cfg2 |=
+ ADMA_MSI_LEGACY_DST_DMA_DONE_INT_BYPASS_EN;
+ }
+ } else {
+ if (direction == ADMA_HOST_TO_DEVICE)
+ dma_cfg2 |= ADMA_SRC_ADDR_IS_HOST;
+ else
+ dma_cfg2 |= ADMA_DST_ADDR_IS_HOST;
+ }
+
+ if (pmadapter->pcard_pcie->pcie_int_mode ==
+ PCIE_INT_MODE_MSIX) {
+ if (pcb->moal_read_reg(pmadapter->pmoal_handle,
+ q_addr + ADMA_MSIX_DOORBELL_DATA,
+ &msix_data)) {
+ PRINTM(MERROR,
+ "Fail to read DMA MSIX data register\n");
+ ret = MLAN_STATUS_FAILURE;
+ goto done;
+ }
+ msix_data &= ~ADMA_MSIX_VECTOR_MASK;
+ msix_data &= ~ADMA_MSIX_PF_MASK;
+ msix_data |= msix_vector;
+ msix_data |= pmadapter->pcard_pcie->func_num
+ << ADMA_MSIX_PF_BIT;
+ PRINTM(MCMND, "msix_data=0x%x\n", msix_data);
+ if (pcb->moal_write_reg(pmadapter->pmoal_handle,
+ q_addr +
+ ADMA_MSIX_DOORBELL_DATA,
+ (t_u32)msix_data)) {
+ PRINTM(MERROR,
+ "Failed to write DMA DOORBELL_DATA.\n");
+ ret = MLAN_STATUS_FAILURE;
+ goto done;
+ }
+ dma_cfg2 |= ADMA_MSIX_ENABLE;
+ } else
+ dma_cfg2 |= ADMA_MSI_LEGACY_ENABLE;
+ PRINTM(MCMND, "dma_cfg2=0x%x\n", dma_cfg2);
+
+ /* enable INT_BYPASS_EN in the dma_cfg2 register */
+ if (pcb->moal_write_reg(pmadapter->pmoal_handle,
+ q_addr + ADMA_DMA_CFG2,
+ (t_u32)dma_cfg2)) {
+ PRINTM(MERROR, "Failed to write DMA CFG2.\n");
+ ret = MLAN_STATUS_FAILURE;
+ goto done;
+ }
+ }
+ /* Read the TX ring read pointer set by firmware */
+ if (pcb->moal_read_reg(pmadapter->pmoal_handle, q_addr + ADMA_DMA_CFG,
+ &dma_cfg)) {
+ PRINTM(MERROR, "Fail to read DMA CFG register\n");
+ ret = MLAN_STATUS_FAILURE;
+ goto done;
+ }
+ if (direction == ADMA_HOST_TO_DEVICE) {
+ /* Write the lower 32bits of the physical address to
+ * ADMA_SRC_LOW */
+ if (pcb->moal_write_reg(pmadapter->pmoal_handle,
+ q_addr + ADMA_SRC_LOW, (t_u32)pbase)) {
+ PRINTM(MERROR, "Failed to write ADMA_SRC_LOW.\n");
+ ret = MLAN_STATUS_FAILURE;
+ goto done;
+ }
+ /* Write the upper 32bits of the physical address to
+ * ADMA_SRC_HIGH */
+ if (pcb->moal_write_reg(pmadapter->pmoal_handle,
+ q_addr + ADMA_SRC_HIGH,
+ (t_u32)((t_u64)pbase >> 32))) {
+ PRINTM(MERROR, "Failed to write ADMA_SRC_HIGH.\n");
+ ret = MLAN_STATUS_FAILURE;
+ goto done;
+ }
+ if (init) {
+ /** Enable DMA done interrupt */
+ if (pcb->moal_write_reg(
+ pmadapter->pmoal_handle,
+ q_addr + ADMA_SRC_INT_STATUS_MASK,
+ DEF_ADMA_INT_MASK)) {
+ PRINTM(MERROR,
+ "Failed to write ADMA_SRC_INT_STATUS_MASK.\n");
+ ret = MLAN_STATUS_FAILURE;
+ goto done;
+ }
+ if (pcb->moal_write_reg(pmadapter->pmoal_handle,
+ q_addr + ADMA_SRC_INT_MASK,
+ DEF_ADMA_INT_MASK)) {
+ PRINTM(MERROR,
+ "Failed to write ADMA_SRC_INT_MASK.\n");
+ ret = MLAN_STATUS_FAILURE;
+ goto done;
+ }
+ }
+ if (dma_mode == DMA_MODE_DUAL_DESC) {
+ dma_cfg &= ~(DESC_MODE_MASK | DMA_MODE_MASK |
+ SRC_NUM_DESC_MASK | DMA_SIZE_MASK);
+ dma_cfg |= (t_u32)size << SRC_NUM_DESC_BIT;
+ dma_cfg |= DESC_MODE_RING << 2;
+ } else {
+ dma_cfg &= ~(DESC_MODE_MASK | DMA_MODE_MASK |
+ SRC_NUM_DESC_MASK | DST_NUM_DESC_MASK |
+ DMA_SIZE_MASK);
+ dma_cfg |= (t_u32)size << DMA_SIZE_BIT;
+ }
+ } else {
+ /* Write the lower 32bits of the physical address to
+ * ADMA_DST_LOW */
+ if (pcb->moal_write_reg(pmadapter->pmoal_handle,
+ q_addr + ADMA_DST_LOW, (t_u32)pbase)) {
+ PRINTM(MERROR, "Failed to write ADMA_DST_LOW.\n");
+ ret = MLAN_STATUS_FAILURE;
+ goto done;
+ }
+ /* Write the upper 32bits of the physical address to
+ * ADMA_DST_HIGH */
+ if (pcb->moal_write_reg(pmadapter->pmoal_handle,
+ q_addr + ADMA_DST_HIGH,
+ (t_u32)((t_u64)pbase >> 32))) {
+ PRINTM(MERROR, "Failed to write ADMA_DST_HIGH.\n");
+ ret = MLAN_STATUS_FAILURE;
+ goto done;
+ }
+ if (init && (dma_mode == DMA_MODE_DUAL_DESC)) {
+ /** Enable DMA done interrupt */
+ if (pcb->moal_write_reg(
+ pmadapter->pmoal_handle,
+ q_addr + ADMA_DST_INT_STATUS_MASK,
+ DEF_ADMA_INT_MASK)) {
+ PRINTM(MERROR,
+ "Failed to write ADMA_SRC_INT_STATUS_MASK.\n");
+ ret = MLAN_STATUS_FAILURE;
+ goto done;
+ }
+ if (pcb->moal_write_reg(pmadapter->pmoal_handle,
+ q_addr + ADMA_DST_INT_MASK,
+ DEF_ADMA_INT_MASK)) {
+ PRINTM(MERROR,
+ "Failed to write ADMA_SRC_INT_MASK.\n");
+ ret = MLAN_STATUS_FAILURE;
+ goto done;
+ }
+ }
+ if (dma_mode == DMA_MODE_DUAL_DESC) {
+ dma_cfg &= ~(DESC_MODE_MASK | DMA_MODE_MASK |
+ DST_NUM_DESC_MASK | DMA_SIZE_MASK);
+ dma_cfg |= (t_u32)size << DST_NUM_DESC_BIT;
+ dma_cfg |= DESC_MODE_RING << 2;
+ } else {
+ dma_cfg &= ~(DESC_MODE_MASK | DMA_MODE_MASK |
+ SRC_NUM_DESC_MASK | DST_NUM_DESC_MASK);
+ }
+ }
+ dma_cfg |= (t_u32)dma_mode;
+ if (pcb->moal_write_reg(pmadapter->pmoal_handle, q_addr + ADMA_DMA_CFG,
+ dma_cfg)) {
+ PRINTM(MERROR, "Fail to set DMA CFG register\n");
+ LEAVE();
+ return MLAN_STATUS_FAILURE;
+ }
+ if (type == ADMA_CMD && !init) {
+ /* Write 1 to src_wr_ptr to trigger direct dma */
+ if (pcb->moal_write_reg(pmadapter->pmoal_handle,
+ q_addr + ADMA_SRC_RW_PTR, 1)) {
+ PRINTM(MERROR, "Failed to write ADMA_SRC_HIGH.\n");
+ ret = MLAN_STATUS_FAILURE;
+ goto done;
+ }
+ }
+done:
+ LEAVE();
+ return ret;
+}
+#endif
+
+#if defined(PCIE9098) || defined(PCIE9097)
+/**
+ * @brief This function set the host interrupt select mask
+ *
+ * @param pmadapter A pointer to mlan_adapter structure
+ * @param enable 0-disable 1-enable
+ *
+ * @return MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ */
+static mlan_status wlan_pcie_set_host_int_select_mask(mlan_adapter *pmadapter,
+ t_u8 enable)
+{
+ pmlan_callbacks pcb = &pmadapter->callbacks;
+ t_u32 int_sel_mask = 0;
+ t_u32 int_clr_mask = 0;
+ ENTER();
+
+ if (enable) {
+ int_sel_mask = PCIE9098_HOST_INTR_SEL_MASK;
+ int_clr_mask = pmadapter->pcard_pcie->reg->host_intr_mask;
+ }
+
+ /* Simply write the mask to the register */
+ if (pcb->moal_write_reg(pmadapter->pmoal_handle, PCIE9098_HOST_INT_SEL,
+ int_sel_mask)) {
+ PRINTM(MWARN, "Set host interrupt select register failed\n");
+ LEAVE();
+ return MLAN_STATUS_FAILURE;
+ }
+ if (pmadapter->pcard_pcie->pcie_int_mode == PCIE_INT_MODE_MSI) {
+ if (!pmadapter->pcard_pcie->reg->msi_int_wr_clr) {
+ /** enable read to clear interrupt */
+ if (pcb->moal_write_reg(pmadapter->pmoal_handle,
+ pmadapter->pcard_pcie->reg
+ ->reg_host_int_clr_sel,
+ int_clr_mask)) {
+ PRINTM(MWARN,
+ "enable read to clear interrupt failed\n");
+ LEAVE();
+ return MLAN_STATUS_FAILURE;
+ }
+ }
+ }
+ LEAVE();
+ return MLAN_STATUS_SUCCESS;
+}
+#endif
+
+#if defined(PCIE9098) || defined(PCIE9097)
+/**
+ * @brief This function handles command response completion
+ *
+ * @param pmadapter A pointer to mlan_adapter structure
+ * @param pmbuf A pointer to mlan_buffer
+ *
+ * @return MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ */
+static mlan_status wlan_pcie_send_vdll_complete(mlan_adapter *pmadapter)
+{
+ mlan_buffer *pcmdbuf;
+ pmlan_callbacks pcb = &pmadapter->callbacks;
+ ENTER();
+ /*unmap the cmd pmbuf, so the cpu can not access the memory in the
+ * command node*/
+ pcmdbuf = pmadapter->pcard_pcie->vdll_cmd_buf;
+ if (pcmdbuf) {
+ pcb->moal_unmap_memory(pmadapter->pmoal_handle,
+ pcmdbuf->pbuf + pcmdbuf->data_offset,
+ pcmdbuf->buf_pa, pcmdbuf->data_len,
+ PCI_DMA_TODEVICE);
+ pmadapter->pcard_pcie->vdll_cmd_buf = MNULL;
+ }
+ LEAVE();
+ return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ * @brief This function downloads VDLL image to the card.
+ *
+ * @param pmadapter A pointer to mlan_adapter structure
+ * @param pmbuf A pointer to mlan_buffer
+ *
+ * @return MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ */
+static mlan_status wlan_pcie_send_vdll(mlan_adapter *pmadapter,
+ mlan_buffer *pmbuf)
+{
+ mlan_status ret = MLAN_STATUS_PENDING;
+ pmlan_callbacks pcb = &pmadapter->callbacks;
+ t_u16 *tmp;
+ t_u8 *payload;
+
+ ENTER();
+ pmadapter->cmd_sent = MTRUE;
+ payload = pmbuf->pbuf + pmbuf->data_offset;
+
+ tmp = (t_u16 *)&payload[0];
+ *tmp = wlan_cpu_to_le16((t_u16)pmbuf->data_len);
+ tmp = (t_u16 *)&payload[2];
+ *tmp = wlan_cpu_to_le16(MLAN_TYPE_VDLL);
+
+ if (MLAN_STATUS_FAILURE ==
+ pcb->moal_map_memory(
+ pmadapter->pmoal_handle, pmbuf->pbuf + pmbuf->data_offset,
+ &pmbuf->buf_pa, pmbuf->data_len, PCI_DMA_TODEVICE)) {
+ PRINTM(MERROR,
+ "PCIE - Download VDLL block: moal_map_memory failed\n");
+ ret = MLAN_STATUS_FAILURE;
+ goto done;
+ }
+ pmadapter->pcard_pcie->vdll_cmd_buf = pmbuf;
+ /* issue the DMA */
+ /* send the VDLL block down to the firmware */
+ wlan_init_adma(pmadapter, ADMA_CMD, pmbuf->buf_pa, pmbuf->data_len,
+ MFALSE);
+
+ PRINTM(MINFO, "PCIE - Download VDLL Block: successful.\n");
+done:
+ if (ret == MLAN_STATUS_FAILURE)
+ pmadapter->cmd_sent = MFALSE;
+
+ LEAVE();
+ return ret;
+}
+#endif
+
+/**
+ * @brief This function disables the host interrupt
+ *
+ * @param pmadapter A pointer to mlan_adapter structure
+ *
+ * @return MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ */
+static mlan_status wlan_pcie_disable_host_int_mask(mlan_adapter *pmadapter)
+{
+ pmlan_callbacks pcb = &pmadapter->callbacks;
+
+ ENTER();
+ if (pcb->moal_write_reg(pmadapter->pmoal_handle,
+ pmadapter->pcard_pcie->reg->reg_host_int_mask,
+ 0x00000000)) {
+ PRINTM(MWARN, "Disable host interrupt failed\n");
+ LEAVE();
+ return MLAN_STATUS_FAILURE;
+ }
+ LEAVE();
+ return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ * @brief This function enables the host interrupt
+ *
+ * @param pmadapter A pointer to mlan_adapter structure
+ *
+ * @return MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ */
+static mlan_status wlan_pcie_enable_host_int_mask(mlan_adapter *pmadapter)
+{
+ pmlan_callbacks pcb = &pmadapter->callbacks;
+ ENTER();
+ /* Simply write the mask to the register */
+ if (pcb->moal_write_reg(pmadapter->pmoal_handle,
+ pmadapter->pcard_pcie->reg->reg_host_int_mask,
+ pmadapter->pcard_pcie->reg->host_intr_mask)) {
+ PRINTM(MWARN, "Enable host interrupt failed\n");
+ LEAVE();
+ return MLAN_STATUS_FAILURE;
+ }
+ LEAVE();
+ return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ * @brief This function enables the host interrupts.
+ *
+ * @param pmadapter A pointer to mlan_adapter structure
+ * @param enable 0-disable 1-enable
+ *
+ * @return MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ */
+static mlan_status
+wlan_pcie_enable_host_int_status_mask(mlan_adapter *pmadapter, t_u8 enable)
+{
+ pmlan_callbacks pcb = &pmadapter->callbacks;
+ t_u32 host_int_status_mask = 0;
+ ENTER();
+ if (enable)
+ host_int_status_mask =
+ pmadapter->pcard_pcie->reg->host_intr_mask;
+ /* Enable host int status mask */
+ if (pcb->moal_write_reg(
+ pmadapter->pmoal_handle,
+ pmadapter->pcard_pcie->reg->reg_host_int_status_mask,
+ host_int_status_mask)) {
+ PRINTM(MWARN, "Enable host interrupt status mask failed\n");
+ LEAVE();
+ return MLAN_STATUS_FAILURE;
+ }
+ LEAVE();
+ return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ * @brief This function disables the host interrupts.
+ *
+ * @param pmadapter A pointer to mlan_adapter structure
+ *
+ * @return MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ */
+mlan_status wlan_disable_pcie_host_int(mlan_adapter *pmadapter)
+{
+ mlan_status ret;
+
+ ENTER();
+ ret = wlan_pcie_enable_host_int_status_mask(pmadapter, MFALSE);
+ if (ret) {
+ LEAVE();
+ return ret;
+ }
+#if defined(PCIE9098) || defined(PCIE9097)
+ if ((pmadapter->card_type == CARD_TYPE_PCIE9098) ||
+ (pmadapter->card_type == CARD_TYPE_PCIE9097)) {
+ ret = wlan_pcie_set_host_int_select_mask(pmadapter, MFALSE);
+ if (ret) {
+ LEAVE();
+ return ret;
+ }
+ }
+#endif
+ ret = wlan_pcie_disable_host_int_mask(pmadapter);
+ LEAVE();
+ return ret;
+}
+
+/**
+ * @brief This function checks the interrupt status and
+ * handle it accordingly.
+ *
+ * @param pmadapter A pointer to mlan_adapter structure
+ *
+ * @return MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ */
+mlan_status wlan_clear_pending_int_status(mlan_adapter *pmadapter)
+{
+ mlan_status ret = MLAN_STATUS_SUCCESS;
+ t_u32 pcie_ireg = 0;
+ pmlan_callbacks pcb = &pmadapter->callbacks;
+
+ ENTER();
+
+ if (pmadapter->pcard_pcie->pcie_int_mode == PCIE_INT_MODE_MSIX)
+ goto done;
+ if (pcb->moal_read_reg(pmadapter->pmoal_handle,
+ pmadapter->pcard_pcie->reg->reg_host_int_status,
+ &pcie_ireg)) {
+ PRINTM(MERROR, "Read host int status register failed\n");
+ ret = MLAN_STATUS_FAILURE;
+ goto done;
+ }
+ if ((pcie_ireg != 0xFFFFFFFF) && (pcie_ireg)) {
+ PRINTM(MMSG, "pcie_ireg=0x%x\n", pcie_ireg);
+ if (pmadapter->pcard_pcie->reg->msi_int_wr_clr) {
+ if (pcb->moal_write_reg(pmadapter->pmoal_handle,
+ pmadapter->pcard_pcie->reg
+ ->reg_host_int_status,
+ ~pcie_ireg)) {
+ PRINTM(MERROR,
+ "Write host int status register failed\n");
+ ret = MLAN_STATUS_FAILURE;
+ goto done;
+ }
+ }
+ }
+done:
+ LEAVE();
+ return ret;
+}
+
+/**
+ * @brief This function enables the host interrupts.
+ *
+ * @param pmadapter A pointer to mlan_adapter structure
+ *
+ * @return MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ */
+mlan_status wlan_enable_pcie_host_int(mlan_adapter *pmadapter)
+{
+ mlan_status ret;
+
+ ENTER();
+ wlan_clear_pending_int_status(pmadapter);
+ ret = wlan_pcie_enable_host_int_status_mask(pmadapter, MTRUE);
+ if (ret) {
+ LEAVE();
+ return ret;
+ }
+#if defined(PCIE9098) || defined(PCIE9097)
+ if ((pmadapter->card_type == CARD_TYPE_PCIE9098) ||
+ (pmadapter->card_type == CARD_TYPE_PCIE9097)) {
+ ret = wlan_pcie_set_host_int_select_mask(pmadapter, MTRUE);
+ if (ret) {
+ LEAVE();
+ return ret;
+ }
+ }
+#endif
+ ret = wlan_pcie_enable_host_int_mask(pmadapter);
+ LEAVE();
+ return ret;
+}
+
+/**
+ * @brief This function creates buffer descriptor ring for TX
+ *
+ * @param pmadapter A pointer to mlan_adapter structure
+ *
+ * @return MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ */
+static mlan_status wlan_pcie_create_txbd_ring(mlan_adapter *pmadapter)
+{
+ mlan_status ret = MLAN_STATUS_SUCCESS;
+ pmlan_callbacks pcb = &pmadapter->callbacks;
+ t_u32 i;
+#if defined(PCIE8997) || defined(PCIE8897)
+ pmlan_pcie_data_buf ptx_bd_buf;
+#endif
+#if defined(PCIE9098) || defined(PCIE9097)
+ padma_dual_desc_buf padma_bd_buf;
+#endif
+
+ ENTER();
+ /*
+ * driver maintaines the write pointer and firmware maintaines the read
+ * pointer.
+ */
+ pmadapter->pcard_pcie->txbd_wrptr = 0;
+ pmadapter->pcard_pcie->txbd_pending = 0;
+ pmadapter->pcard_pcie->txbd_rdptr = 0;
+
+ /* allocate shared memory for the BD ring and divide the same in to
+ several descriptors */
+#if defined(PCIE8997) || defined(PCIE8897)
+ if (!pmadapter->pcard_pcie->reg->use_adma)
+ pmadapter->pcard_pcie->txbd_ring_size =
+ sizeof(mlan_pcie_data_buf) * MLAN_MAX_TXRX_BD;
+#endif
+
+#if defined(PCIE9098) || defined(PCIE9097)
+ if (pmadapter->pcard_pcie->reg->use_adma)
+ pmadapter->pcard_pcie->txbd_ring_size =
+ sizeof(adma_dual_desc_buf) * MLAN_MAX_TXRX_BD;
+#endif
+ PRINTM(MINFO, "TX ring: allocating %d bytes\n",
+ pmadapter->pcard_pcie->txbd_ring_size);
+
+ ret = pcb->moal_malloc_consistent(
+ pmadapter->pmoal_handle, pmadapter->pcard_pcie->txbd_ring_size,
+ &pmadapter->pcard_pcie->txbd_ring_vbase,
+ &pmadapter->pcard_pcie->txbd_ring_pbase);
+
+ if (ret != MLAN_STATUS_SUCCESS) {
+ PRINTM(MERROR, "%s: No free moal_malloc_consistent\n",
+ __FUNCTION__);
+ LEAVE();
+ return MLAN_STATUS_FAILURE;
+ }
+
+ PRINTM(MINFO,
+ "TX ring: - base: %p, pbase: %#x:%x,"
+ "len: %x\n",
+ pmadapter->pcard_pcie->txbd_ring_vbase,
+ (t_u32)((t_u64)pmadapter->pcard_pcie->txbd_ring_pbase >> 32),
+ (t_u32)pmadapter->pcard_pcie->txbd_ring_pbase,
+ pmadapter->pcard_pcie->txbd_ring_size);
+
+ for (i = 0; i < MLAN_MAX_TXRX_BD; i++) {
+ pmadapter->pcard_pcie->tx_buf_list[i] = MNULL;
+#if defined(PCIE9098) || defined(PCIE9097)
+ if (pmadapter->pcard_pcie->reg->use_adma) {
+ padma_bd_buf =
+ (adma_dual_desc_buf
+ *)(pmadapter->pcard_pcie
+ ->txbd_ring_vbase +
+ (sizeof(adma_dual_desc_buf) * i));
+ pmadapter->pcard_pcie->txbd_ring[i] =
+ (t_void *)padma_bd_buf;
+ padma_bd_buf->paddr = 0;
+ padma_bd_buf->len = 0;
+ padma_bd_buf->flags =
+ ADMA_BD_FLAG_INT_EN | ADMA_BD_FLAG_SRC_HOST |
+ ADMA_BD_FLAG_SOP | ADMA_BD_FLAG_EOP;
+ padma_bd_buf->pkt_size = 0;
+ padma_bd_buf->reserved = 0;
+ }
+#endif
+
+#if defined(PCIE8997) || defined(PCIE8897)
+ if (!pmadapter->pcard_pcie->reg->use_adma) {
+ ptx_bd_buf =
+ (mlan_pcie_data_buf
+ *)(pmadapter->pcard_pcie
+ ->txbd_ring_vbase +
+ (sizeof(mlan_pcie_data_buf) * i));
+ pmadapter->pcard_pcie->txbd_ring[i] =
+ (t_void *)ptx_bd_buf;
+ ptx_bd_buf->paddr = 0;
+ ptx_bd_buf->len = 0;
+ ptx_bd_buf->flags = 0;
+ ptx_bd_buf->frag_len = 0;
+ ptx_bd_buf->offset = 0;
+ }
+#endif
+ }
+ LEAVE();
+ return ret;
+}
+
+/**
+ * @brief This function frees TX buffer descriptor ring
+ *
+ * @param pmadapter A pointer to mlan_adapter structure
+ *
+ * @return MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ */
+static mlan_status wlan_pcie_delete_txbd_ring(mlan_adapter *pmadapter)
+{
+ t_u32 i;
+ pmlan_callbacks pcb = &pmadapter->callbacks;
+ mlan_buffer *pmbuf = MNULL;
+#if defined(PCIE8997) || defined(PCIE8897)
+ mlan_pcie_data_buf *ptx_bd_buf;
+#endif
+#if defined(PCIE9098) || defined(PCIE9097)
+ adma_dual_desc_buf *padma_bd_buf;
+#endif
+
+ ENTER();
+
+ for (i = 0; i < MLAN_MAX_TXRX_BD; i++) {
+ if (pmadapter->pcard_pcie->tx_buf_list[i]) {
+ pmbuf = pmadapter->pcard_pcie->tx_buf_list[i];
+ pcb->moal_unmap_memory(pmadapter->pmoal_handle,
+ pmbuf->pbuf + pmbuf->data_offset,
+ pmbuf->buf_pa,
+ MLAN_RX_DATA_BUF_SIZE,
+ PCI_DMA_TODEVICE);
+ wlan_write_data_complete(pmadapter, pmbuf,
+ MLAN_STATUS_FAILURE);
+ }
+ pmadapter->pcard_pcie->tx_buf_list[i] = MNULL;
+#if defined(PCIE8997) || defined(PCIE8897)
+ if (!pmadapter->pcard_pcie->reg->use_adma) {
+ ptx_bd_buf =
+ (mlan_pcie_data_buf *)
+ pmadapter->pcard_pcie->txbd_ring[i];
+
+ if (ptx_bd_buf) {
+ ptx_bd_buf->paddr = 0;
+ ptx_bd_buf->len = 0;
+ ptx_bd_buf->flags = 0;
+ ptx_bd_buf->frag_len = 0;
+ ptx_bd_buf->offset = 0;
+ }
+ }
+#endif
+
+#if defined(PCIE9098) || defined(PCIE9097)
+ if (pmadapter->pcard_pcie->reg->use_adma) {
+ padma_bd_buf =
+ (adma_dual_desc_buf *)
+ pmadapter->pcard_pcie->txbd_ring[i];
+
+ if (padma_bd_buf) {
+ padma_bd_buf->paddr = 0;
+ padma_bd_buf->len = 0;
+ padma_bd_buf->flags = 0;
+ padma_bd_buf->pkt_size = 0;
+ padma_bd_buf->reserved = 0;
+ }
+ }
+#endif
+ pmadapter->pcard_pcie->txbd_ring[i] = MNULL;
+ }
+
+ if (pmadapter->pcard_pcie->txbd_ring_vbase) {
+ pmadapter->callbacks.moal_mfree_consistent(
+ pmadapter->pmoal_handle,
+ pmadapter->pcard_pcie->txbd_ring_size,
+ pmadapter->pcard_pcie->txbd_ring_vbase,
+ pmadapter->pcard_pcie->txbd_ring_pbase);
+ }
+ pmadapter->pcard_pcie->txbd_pending = 0;
+ pmadapter->pcard_pcie->txbd_ring_size = 0;
+ pmadapter->pcard_pcie->txbd_wrptr = 0;
+ pmadapter->pcard_pcie->txbd_rdptr = 0;
+ pmadapter->pcard_pcie->txbd_ring_vbase = MNULL;
+ pmadapter->pcard_pcie->txbd_ring_pbase = 0;
+
+ LEAVE();
+ return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ * @brief This function creates buffer descriptor ring for RX
+ *
+ * @param pmadapter A pointer to mlan_adapter structure
+ *
+ * @return MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ */
+static mlan_status wlan_pcie_create_rxbd_ring(mlan_adapter *pmadapter)
+{
+ mlan_status ret = MLAN_STATUS_SUCCESS;
+ pmlan_callbacks pcb = &pmadapter->callbacks;
+ mlan_buffer *pmbuf = MNULL;
+ t_u32 i;
+#if defined(PCIE8997) || defined(PCIE8897)
+ mlan_pcie_data_buf *prxbd_buf;
+#endif
+#if defined(PCIE9098) || defined(PCIE9097)
+ adma_dual_desc_buf *padma_bd_buf;
+#endif
+
+ ENTER();
+
+ pmadapter->pcard_pcie->rxbd_rdptr = 0;
+#if defined(PCIE8997) || defined(PCIE8897)
+ /*
+ * driver maintaines the write pointer and firmware maintaines the read
+ * pointer. The read pointer starts at 0 (zero) while the write pointer
+ * starts at zero with rollover bit set
+ */
+ if (!pmadapter->pcard_pcie->reg->use_adma) {
+ pmadapter->pcard_pcie->rxbd_wrptr =
+ pmadapter->pcard_pcie->reg->txrx_rw_ptr_rollover_ind;
+ /* allocate shared memory for the BD ring and divide the same in
+ to several descriptors */
+ pmadapter->pcard_pcie->rxbd_ring_size =
+ sizeof(mlan_pcie_data_buf) * MLAN_MAX_TXRX_BD;
+ }
+#endif
+
+#if defined(PCIE9098) || defined(PCIE9097)
+ /*
+ * driver maintaines the write pointer and firmware maintaines the read
+ * pointer. The read pointer starts at 0 (zero) while the write pointer
+ * starts at MLAN_MAX_TXRX_BD
+ */
+ if (pmadapter->pcard_pcie->reg->use_adma) {
+ pmadapter->pcard_pcie->rxbd_wrptr = MLAN_MAX_TXRX_BD;
+ pmadapter->pcard_pcie->rxbd_ring_size =
+ sizeof(adma_dual_desc_buf) * MLAN_MAX_TXRX_BD;
+ }
+#endif
+
+ PRINTM(MINFO, "RX ring: allocating %d bytes\n",
+ pmadapter->pcard_pcie->rxbd_ring_size);
+
+ ret = pcb->moal_malloc_consistent(
+ pmadapter->pmoal_handle, pmadapter->pcard_pcie->rxbd_ring_size,
+ &pmadapter->pcard_pcie->rxbd_ring_vbase,
+ &pmadapter->pcard_pcie->rxbd_ring_pbase);
+
+ if (ret != MLAN_STATUS_SUCCESS) {
+ PRINTM(MERROR, "%s: No free moal_malloc_consistent\n",
+ __FUNCTION__);
+ LEAVE();
+ return MLAN_STATUS_FAILURE;
+ }
+
+ PRINTM(MINFO,
+ "RX ring: - base: %p, pbase: %#x:%x,"
+ "len: %#x\n",
+ pmadapter->pcard_pcie->rxbd_ring_vbase,
+ (t_u32)((t_u64)pmadapter->pcard_pcie->rxbd_ring_pbase >> 32),
+ (t_u32)pmadapter->pcard_pcie->rxbd_ring_pbase,
+ pmadapter->pcard_pcie->rxbd_ring_size);
+
+ for (i = 0; i < MLAN_MAX_TXRX_BD; i++) {
+ /* Allocate buffer here so that firmware can DMA data on it */
+ pmbuf = wlan_alloc_mlan_buffer(pmadapter, MLAN_RX_DATA_BUF_SIZE,
+ MLAN_RX_HEADER_LEN,
+ MOAL_ALLOC_MLAN_BUFFER);
+ if (!pmbuf) {
+ PRINTM(MERROR,
+ "RX ring create : Unable to allocate mlan_buffer\n");
+ wlan_pcie_delete_rxbd_ring(pmadapter);
+ LEAVE();
+ return MLAN_STATUS_FAILURE;
+ }
+
+ pmadapter->pcard_pcie->rx_buf_list[i] = pmbuf;
+
+ if (MLAN_STATUS_FAILURE ==
+ pcb->moal_map_memory(pmadapter->pmoal_handle,
+ pmbuf->pbuf + pmbuf->data_offset,
+ &pmbuf->buf_pa, MLAN_RX_DATA_BUF_SIZE,
+ PCI_DMA_FROMDEVICE)) {
+ PRINTM(MERROR,
+ "Rx ring create : moal_map_memory failed\n");
+ wlan_pcie_delete_rxbd_ring(pmadapter);
+ LEAVE();
+ return MLAN_STATUS_FAILURE;
+ }
+
+ PRINTM(MINFO,
+ "RX ring: add new mlan_buffer base: %p, "
+ "buf_base: %p, buf_pbase: %#x:%x, "
+ "buf_len: %#x\n",
+ pmbuf, pmbuf->pbuf, (t_u32)((t_u64)pmbuf->buf_pa >> 32),
+ (t_u32)pmbuf->buf_pa, pmbuf->data_len);
+
+#if defined(PCIE8997) || defined(PCIE8897)
+ if (!pmadapter->pcard_pcie->reg->use_adma) {
+ prxbd_buf =
+ (mlan_pcie_data_buf
+ *)(pmadapter->pcard_pcie
+ ->rxbd_ring_vbase +
+ (sizeof(mlan_pcie_data_buf) * i));
+ pmadapter->pcard_pcie->rxbd_ring[i] =
+ (t_void *)prxbd_buf;
+ prxbd_buf->paddr = pmbuf->buf_pa;
+ prxbd_buf->len = (t_u16)pmbuf->data_len;
+ prxbd_buf->flags = MLAN_BD_FLAG_SOP | MLAN_BD_FLAG_EOP;
+ prxbd_buf->offset = 0;
+ prxbd_buf->frag_len = (t_u16)pmbuf->data_len;
+ }
+#endif
+
+#if defined(PCIE9098) || defined(PCIE9097)
+ if (pmadapter->pcard_pcie->reg->use_adma) {
+ padma_bd_buf =
+ (adma_dual_desc_buf
+ *)(pmadapter->pcard_pcie
+ ->rxbd_ring_vbase +
+ (sizeof(adma_dual_desc_buf) * i));
+ pmadapter->pcard_pcie->rxbd_ring[i] =
+ (t_void *)padma_bd_buf;
+ padma_bd_buf->paddr = pmbuf->buf_pa;
+ padma_bd_buf->len =
+ ALIGN_SZ(pmbuf->data_len, ADMA_ALIGN_SIZE);
+ padma_bd_buf->flags =
+ ADMA_BD_FLAG_INT_EN | ADMA_BD_FLAG_DST_HOST;
+ padma_bd_buf->pkt_size = 0;
+ padma_bd_buf->reserved = 0;
+ }
+#endif
+ }
+
+ LEAVE();
+ return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ * @brief This function frees RX buffer descriptor ring
+ *
+ * @param pmadapter A pointer to mlan_adapter structure
+ *
+ * @return MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ */
+static mlan_status wlan_pcie_delete_rxbd_ring(mlan_adapter *pmadapter)
+{
+ t_u32 i;
+ pmlan_callbacks pcb = &pmadapter->callbacks;
+ mlan_buffer *pmbuf = MNULL;
+#if defined(PCIE8997) || defined(PCIE8897)
+ mlan_pcie_data_buf *prxbd_buf;
+#endif
+#if defined(PCIE9098) || defined(PCIE9097)
+ adma_dual_desc_buf *padma_bd_buf;
+#endif
+
+ ENTER();
+ for (i = 0; i < MLAN_MAX_TXRX_BD; i++) {
+ if (pmadapter->pcard_pcie->rx_buf_list[i]) {
+ pmbuf = pmadapter->pcard_pcie->rx_buf_list[i];
+ pcb->moal_unmap_memory(pmadapter->pmoal_handle,
+ pmbuf->pbuf + pmbuf->data_offset,
+ pmbuf->buf_pa,
+ MLAN_RX_DATA_BUF_SIZE,
+ PCI_DMA_FROMDEVICE);
+ wlan_free_mlan_buffer(
+ pmadapter,
+ pmadapter->pcard_pcie->rx_buf_list[i]);
+ }
+ pmadapter->pcard_pcie->rx_buf_list[i] = MNULL;
+#if defined(PCIE8997) || defined(PCIE8897)
+ if (!pmadapter->pcard_pcie->reg->use_adma) {
+ prxbd_buf = (mlan_pcie_data_buf *)
+ pmadapter->pcard_pcie->rxbd_ring[i];
+
+ if (prxbd_buf) {
+ prxbd_buf->paddr = 0;
+ prxbd_buf->offset = 0;
+ prxbd_buf->frag_len = 0;
+ }
+ }
+#endif
+
+#if defined(PCIE9098) || defined(PCIE9097)
+ if (pmadapter->pcard_pcie->reg->use_adma) {
+ padma_bd_buf =
+ (adma_dual_desc_buf *)
+ pmadapter->pcard_pcie->rxbd_ring[i];
+
+ if (padma_bd_buf) {
+ padma_bd_buf->paddr = 0;
+ padma_bd_buf->flags = 0;
+ padma_bd_buf->pkt_size = 0;
+ padma_bd_buf->reserved = 0;
+ padma_bd_buf->len = 0;
+ }
+ }
+#endif
+ pmadapter->pcard_pcie->rxbd_ring[i] = MNULL;
+ }
+
+ if (pmadapter->pcard_pcie->rxbd_ring_vbase)
+ pmadapter->callbacks.moal_mfree_consistent(
+ pmadapter->pmoal_handle,
+ pmadapter->pcard_pcie->rxbd_ring_size,
+ pmadapter->pcard_pcie->rxbd_ring_vbase,
+ pmadapter->pcard_pcie->rxbd_ring_pbase);
+ pmadapter->pcard_pcie->rxbd_ring_size = 0;
+ pmadapter->pcard_pcie->rxbd_rdptr = 0;
+ pmadapter->pcard_pcie->rxbd_wrptr = 0;
+ pmadapter->pcard_pcie->rxbd_ring_vbase = MNULL;
+ pmadapter->pcard_pcie->rxbd_ring_pbase = 0;
+
+ LEAVE();
+ return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ * @brief This function creates buffer descriptor ring for Events
+ *
+ * @param pmadapter A pointer to mlan_adapter structure
+ *
+ * @return MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ */
+static mlan_status wlan_pcie_create_evtbd_ring(mlan_adapter *pmadapter)
+{
+ mlan_status ret = MLAN_STATUS_SUCCESS;
+ pmlan_callbacks pcb = &pmadapter->callbacks;
+ mlan_buffer *pmbuf = MNULL;
+ t_u32 i;
+#if defined(PCIE8997) || defined(PCIE8897)
+ pmlan_pcie_evt_buf pevtbd_buf;
+#endif
+
+#if defined(PCIE9098) || defined(PCIE9097)
+ adma_dual_desc_buf *padma_bd_buf;
+#endif
+
+ ENTER();
+ /*
+ * driver maintaines the write pointer and firmware maintaines the read
+ * pointer. The read pointer starts at 0 (zero) while the write pointer
+ * starts at zero with rollover bit set
+ */
+ pmadapter->pcard_pcie->evtbd_rdptr = 0;
+#if defined(PCIE8997) || defined(PCIE8897)
+ if (!pmadapter->pcard_pcie->reg->use_adma) {
+ pmadapter->pcard_pcie->evtbd_wrptr = EVT_RW_PTR_ROLLOVER_IND;
+ pmadapter->pcard_pcie->evtbd_ring_size =
+ sizeof(mlan_pcie_evt_buf) * MLAN_MAX_EVT_BD;
+ }
+#endif
+
+#if defined(PCIE9098) || defined(PCIE9097)
+ if (pmadapter->pcard_pcie->reg->use_adma) {
+ pmadapter->pcard_pcie->evtbd_wrptr = MLAN_MAX_EVT_BD;
+ pmadapter->pcard_pcie->evtbd_ring_size =
+ sizeof(adma_dual_desc_buf) * MLAN_MAX_EVT_BD;
+ }
+#endif
+ PRINTM(MINFO, "Evt ring: allocating %d bytes\n",
+ pmadapter->pcard_pcie->evtbd_ring_size);
+
+ ret = pcb->moal_malloc_consistent(
+ pmadapter->pmoal_handle, pmadapter->pcard_pcie->evtbd_ring_size,
+ &pmadapter->pcard_pcie->evtbd_ring_vbase,
+ &pmadapter->pcard_pcie->evtbd_ring_pbase);
+
+ if (ret != MLAN_STATUS_SUCCESS) {
+ PRINTM(MERROR, "%s: No free moal_malloc_consistent\n",
+ __FUNCTION__);
+ LEAVE();
+ return MLAN_STATUS_FAILURE;
+ }
+ PRINTM(MINFO,
+ "Evt ring: - base: %p, pbase: %#x:%x,"
+ "len: %#x\n",
+ pmadapter->pcard_pcie->evtbd_ring_vbase,
+ (t_u32)((t_u64)pmadapter->pcard_pcie->evtbd_ring_pbase >> 32),
+ (t_u32)pmadapter->pcard_pcie->evtbd_ring_pbase,
+ pmadapter->pcard_pcie->evtbd_ring_size);
+
+ for (i = 0; i < MLAN_MAX_EVT_BD; i++) {
+ /* Allocate buffer here so that firmware can DMA data on it */
+ pmbuf = wlan_alloc_mlan_buffer(pmadapter, MAX_EVENT_SIZE,
+ MLAN_RX_HEADER_LEN,
+ MOAL_ALLOC_MLAN_BUFFER);
+ if (!pmbuf) {
+ PRINTM(MERROR,
+ "Event ring create : Unable to allocate mlan_buffer\n");
+ wlan_pcie_delete_evtbd_ring(pmadapter);
+ LEAVE();
+ return MLAN_STATUS_FAILURE;
+ }
+
+ pmadapter->pcard_pcie->evt_buf_list[i] = pmbuf;
+
+ if (MLAN_STATUS_FAILURE ==
+ pcb->moal_map_memory(pmadapter->pmoal_handle,
+ pmbuf->pbuf + pmbuf->data_offset,
+ &pmbuf->buf_pa, MAX_EVENT_SIZE,
+ PCI_DMA_FROMDEVICE)) {
+ PRINTM(MERROR,
+ "Event ring create : moal_map_memory failed\n");
+ wlan_pcie_delete_evtbd_ring(pmadapter);
+ LEAVE();
+ return MLAN_STATUS_FAILURE;
+ }
+
+#if defined(PCIE8997) || defined(PCIE8897)
+ if (!pmadapter->pcard_pcie->reg->use_adma) {
+ pevtbd_buf =
+ (mlan_pcie_evt_buf
+ *)(pmadapter->pcard_pcie
+ ->evtbd_ring_vbase +
+ (sizeof(mlan_pcie_evt_buf) * i));
+ pmadapter->pcard_pcie->evtbd_ring[i] =
+ (t_void *)pevtbd_buf;
+ pevtbd_buf->paddr = pmbuf->buf_pa;
+ pevtbd_buf->len = (t_u16)pmbuf->data_len;
+ pevtbd_buf->flags = 0;
+ }
+#endif
+
+#if defined(PCIE9098) || defined(PCIE9097)
+ if (pmadapter->pcard_pcie->reg->use_adma) {
+ padma_bd_buf =
+ (adma_dual_desc_buf
+ *)(pmadapter->pcard_pcie
+ ->evtbd_ring_vbase +
+ (sizeof(adma_dual_desc_buf) * i));
+ pmadapter->pcard_pcie->evtbd_ring[i] =
+ (t_void *)padma_bd_buf;
+ padma_bd_buf->paddr = pmbuf->buf_pa;
+ padma_bd_buf->len =
+ ALIGN_SZ(pmbuf->data_len, ADMA_ALIGN_SIZE);
+ padma_bd_buf->flags =
+ ADMA_BD_FLAG_INT_EN | ADMA_BD_FLAG_DST_HOST;
+ padma_bd_buf->pkt_size = 0;
+ padma_bd_buf->reserved = 0;
+ }
+#endif
+ }
+
+ LEAVE();
+ return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ * @brief This function frees event buffer descriptor ring
+ *
+ * @param pmadapter A pointer to mlan_adapter structure
+ *
+ * @return MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ */
+static mlan_status wlan_pcie_delete_evtbd_ring(mlan_adapter *pmadapter)
+{
+ t_u32 i;
+ pmlan_callbacks pcb = &pmadapter->callbacks;
+ mlan_buffer *pmbuf = MNULL;
+#if defined(PCIE8997) || defined(PCIE8897)
+ mlan_pcie_evt_buf *pevtbd_buf;
+#endif
+#if defined(PCIE9098) || defined(PCIE9097)
+ adma_dual_desc_buf *padma_bd_buf;
+#endif
+
+ ENTER();
+ for (i = 0; i < MLAN_MAX_EVT_BD; i++) {
+ if (pmadapter->pcard_pcie->evt_buf_list[i]) {
+ pmbuf = pmadapter->pcard_pcie->evt_buf_list[i];
+ pcb->moal_unmap_memory(pmadapter->pmoal_handle,
+ pmbuf->pbuf + pmbuf->data_offset,
+ pmbuf->buf_pa, MAX_EVENT_SIZE,
+ PCI_DMA_FROMDEVICE);
+ wlan_free_mlan_buffer(pmadapter, pmbuf);
+ }
+
+ pmadapter->pcard_pcie->evt_buf_list[i] = MNULL;
+#if defined(PCIE8997) || defined(PCIE8897)
+ if (!pmadapter->pcard_pcie->reg->use_adma) {
+ pevtbd_buf =
+ (mlan_pcie_evt_buf *)
+ pmadapter->pcard_pcie->evtbd_ring[i];
+
+ if (pevtbd_buf) {
+ pevtbd_buf->paddr = 0;
+ pevtbd_buf->len = 0;
+ pevtbd_buf->flags = 0;
+ }
+ }
+#endif
+
+#if defined(PCIE9098) || defined(PCIE9097)
+ if (pmadapter->pcard_pcie->reg->use_adma) {
+ padma_bd_buf =
+ (adma_dual_desc_buf *)
+ pmadapter->pcard_pcie->evtbd_ring[i];
+
+ if (padma_bd_buf) {
+ padma_bd_buf->paddr = 0;
+ padma_bd_buf->len = 0;
+ padma_bd_buf->flags = 0;
+ padma_bd_buf->pkt_size = 0;
+ padma_bd_buf->reserved = 0;
+ }
+ }
+#endif
+ pmadapter->pcard_pcie->evtbd_ring[i] = MNULL;
+ }
+
+ if (pmadapter->pcard_pcie->evtbd_ring_vbase)
+ pmadapter->callbacks.moal_mfree_consistent(
+ pmadapter->pmoal_handle,
+ pmadapter->pcard_pcie->evtbd_ring_size,
+ pmadapter->pcard_pcie->evtbd_ring_vbase,
+ pmadapter->pcard_pcie->evtbd_ring_pbase);
+
+ pmadapter->pcard_pcie->evtbd_rdptr = 0;
+ pmadapter->pcard_pcie->evtbd_wrptr = 0;
+ pmadapter->pcard_pcie->evtbd_ring_size = 0;
+ pmadapter->pcard_pcie->evtbd_ring_vbase = MNULL;
+ pmadapter->pcard_pcie->evtbd_ring_pbase = 0;
+
+ LEAVE();
+ return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ * @brief This function allocates buffer for CMD and CMDRSP
+ *
+ * @param pmadapter A pointer to mlan_adapter structure
+ *
+ * @return MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ */
+static mlan_status wlan_pcie_alloc_cmdrsp_buf(mlan_adapter *pmadapter)
+{
+ mlan_buffer *pmbuf = MNULL;
+ pmlan_callbacks pcb = &pmadapter->callbacks;
+ mlan_status ret = MLAN_STATUS_SUCCESS;
+ /** Virtual base address of command response */
+ t_u8 *cmdrsp_vbase;
+ /** Physical base address of command response */
+ t_u64 cmdrsp_pbase = 0;
+
+ ENTER();
+
+ /* Allocate memory for receiving command response data */
+ pmbuf = wlan_alloc_mlan_buffer(pmadapter, 0, 0, MOAL_MALLOC_BUFFER);
+ if (!pmbuf) {
+ PRINTM(MERROR,
+ "Command resp buffer create : Unable to allocate mlan_buffer\n");
+ LEAVE();
+ return MLAN_STATUS_FAILURE;
+ }
+ ret = pcb->moal_malloc_consistent(pmadapter->pmoal_handle,
+ MRVDRV_SIZE_OF_CMD_BUFFER,
+ &cmdrsp_vbase, &cmdrsp_pbase);
+
+ if (ret != MLAN_STATUS_SUCCESS) {
+ PRINTM(MERROR, "%s: No free moal_malloc_consistent\n",
+ __FUNCTION__);
+ /* free pmbuf */
+ wlan_free_mlan_buffer(pmadapter, pmbuf);
+ LEAVE();
+ return MLAN_STATUS_FAILURE;
+ }
+
+ pmbuf->buf_pa = cmdrsp_pbase;
+ pmbuf->pbuf = cmdrsp_vbase;
+ pmbuf->data_offset = 0;
+ pmbuf->data_len = MRVDRV_SIZE_OF_CMD_BUFFER;
+ pmbuf->total_pcie_buf_len = MRVDRV_SIZE_OF_CMD_BUFFER;
+ pmadapter->pcard_pcie->cmdrsp_buf = pmbuf;
+ LEAVE();
+ return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ * @brief This function frees CMD and CMDRSP buffer
+ *
+ * @param pmadapter A pointer to mlan_adapter structure
+ *
+ * @return MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ */
+static mlan_status wlan_pcie_delete_cmdrsp_buf(mlan_adapter *pmadapter)
+{
+ mlan_buffer *pmbuf = MNULL;
+ pmlan_callbacks pcb = &pmadapter->callbacks;
+ t_u8 *cmdrsp_vbase;
+ t_u64 cmdrsp_pbase;
+ ENTER();
+
+ if (!pmadapter) {
+ LEAVE();
+ return MLAN_STATUS_FAILURE;
+ }
+
+ if (pmadapter->pcard_pcie->cmdrsp_buf) {
+ pmbuf = pmadapter->pcard_pcie->cmdrsp_buf;
+ cmdrsp_vbase = pmbuf->pbuf;
+ cmdrsp_pbase = pmbuf->buf_pa;
+ if (cmdrsp_vbase)
+ pmadapter->callbacks.moal_mfree_consistent(
+ pmadapter->pmoal_handle,
+ pmbuf->total_pcie_buf_len, cmdrsp_vbase,
+ cmdrsp_pbase);
+ wlan_free_mlan_buffer(pmadapter, pmbuf);
+ pmadapter->pcard_pcie->cmdrsp_buf = MNULL;
+ }
+ if (pmadapter->pcard_pcie->cmd_buf) {
+ pmbuf = pmadapter->pcard_pcie->cmd_buf;
+ pcb->moal_unmap_memory(pmadapter->pmoal_handle,
+ pmbuf->pbuf + pmbuf->data_offset,
+ pmbuf->buf_pa, MRVDRV_SIZE_OF_CMD_BUFFER,
+ PCI_DMA_TODEVICE);
+ }
+
+ LEAVE();
+ return MLAN_STATUS_SUCCESS;
+}
+
+#if defined(PCIE8997) || defined(PCIE8897)
+#define PCIE_TXBD_EMPTY(wrptr, rdptr, mask, rollover_ind) \
+ (((wrptr & mask) == (rdptr & mask)) && \
+ ((wrptr & rollover_ind) == (rdptr & rollover_ind)))
+
+/**
+ * @brief This function flushes the TX buffer descriptor ring
+ *
+ * @param pmadapter A pointer to mlan_adapter structure
+ *
+ * @return MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ */
+static mlan_status wlan_pcie_flush_txbd_ring(mlan_adapter *pmadapter)
+{
+ mlan_status ret = MLAN_STATUS_SUCCESS;
+ pmlan_callbacks pcb = &pmadapter->callbacks;
+ t_u32 txrx_rw_ptr_mask = pmadapter->pcard_pcie->reg->txrx_rw_ptr_mask;
+ t_u32 txrx_rw_ptr_rollover_ind =
+ pmadapter->pcard_pcie->reg->txrx_rw_ptr_rollover_ind;
+
+ ENTER();
+
+ if (!PCIE_TXBD_EMPTY(pmadapter->pcard_pcie->txbd_wrptr,
+ pmadapter->pcard_pcie->txbd_rdptr,
+ txrx_rw_ptr_mask, txrx_rw_ptr_rollover_ind)) {
+ pmadapter->pcard_pcie->txbd_flush = MTRUE;
+ /* write pointer already set at last send */
+ /* send dnld-rdy intr again, wait for completion */
+ if (pcb->moal_write_reg(
+ pmadapter->pmoal_handle,
+ pmadapter->pcard_pcie->reg->reg_cpu_int_event,
+ CPU_INTR_DNLD_RDY)) {
+ PRINTM(MERROR,
+ "SEND DATA (FLUSH): failed to assert dnld-rdy interrupt.\n");
+ ret = MLAN_STATUS_FAILURE;
+ }
+ }
+
+ LEAVE();
+ return ret;
+}
+#endif
+
+/**
+ * @brief This function check the tx pending buffer
+ *
+ * @param pmadapter A pointer to mlan_adapter structure
+ * @param rdptr tx rdptr
+ *
+ * @return MTRUE/MFALSE;
+ */
+static t_u8 wlan_check_tx_pending_buffer(mlan_adapter *pmadapter, t_u32 rdptr)
+{
+#if defined(PCIE8997) || defined(PCIE8897)
+ t_u32 txrx_rw_ptr_mask = pmadapter->pcard_pcie->reg->txrx_rw_ptr_mask;
+ t_u32 txrx_rw_ptr_rollover_ind =
+ pmadapter->pcard_pcie->reg->txrx_rw_ptr_rollover_ind;
+ if (!pmadapter->pcard_pcie->reg->use_adma) {
+ if (((pmadapter->pcard_pcie->txbd_rdptr & txrx_rw_ptr_mask) !=
+ (rdptr & txrx_rw_ptr_mask)) ||
+ ((pmadapter->pcard_pcie->txbd_rdptr &
+ txrx_rw_ptr_rollover_ind) !=
+ (rdptr & txrx_rw_ptr_rollover_ind)))
+ return MTRUE;
+ else
+ return MFALSE;
+ }
+#endif
+#if defined(PCIE9098) || defined(PCIE9097)
+ if (pmadapter->pcard_pcie->reg->use_adma) {
+ if ((pmadapter->pcard_pcie->txbd_rdptr &
+ ADMA_RW_PTR_WRAP_MASK) != (rdptr & ADMA_RW_PTR_WRAP_MASK))
+ return MTRUE;
+ else
+ return MFALSE;
+ }
+#endif
+ return MFALSE;
+}
+
+/**
+ * @brief This function unmaps and frees downloaded data buffer
+ *
+ * @param pmadapter A pointer to mlan_adapter structure
+ *
+ * @return MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ */
+static mlan_status wlan_pcie_send_data_complete(mlan_adapter *pmadapter)
+{
+ const t_u32 num_tx_buffs = MLAN_MAX_TXRX_BD;
+ mlan_status ret = MLAN_STATUS_SUCCESS;
+ pmlan_callbacks pcb = &pmadapter->callbacks;
+ mlan_buffer *pmbuf;
+ t_u32 wrdoneidx;
+ t_u32 rdptr;
+ t_u32 unmap_count = 0;
+#if defined(PCIE8997) || defined(PCIE8897)
+ t_u32 txrx_rw_ptr_mask = pmadapter->pcard_pcie->reg->txrx_rw_ptr_mask;
+ t_u32 txrx_rw_ptr_rollover_ind =
+ pmadapter->pcard_pcie->reg->txrx_rw_ptr_rollover_ind;
+ mlan_pcie_data_buf *ptx_bd_buf;
+#endif
+#if defined(PCIE9098) || defined(PCIE9097)
+ adma_dual_desc_buf *padma_bd_buf;
+ t_u32 wrptr;
+#endif
+
+ ENTER();
+
+ /* Read the TX ring read pointer set by firmware */
+ if (pcb->moal_read_reg(pmadapter->pmoal_handle,
+ pmadapter->pcard_pcie->reg->reg_txbd_rdptr,
+ &rdptr)) {
+ PRINTM(MERROR,
+ "SEND DATA COMP: failed to read REG_TXBD_RDPTR\n");
+ ret = MLAN_STATUS_FAILURE;
+ goto done;
+ }
+ PRINTM(MINFO, "SEND DATA COMP: rdptr_prev=0x%x, rdptr=0x%x\n",
+ pmadapter->pcard_pcie->txbd_rdptr, rdptr);
+
+#if defined(PCIE8997) || defined(PCIE8897)
+ if (!pmadapter->pcard_pcie->reg->use_adma)
+ rdptr = rdptr >> TXBD_RW_PTR_START;
+#endif
+
+#if defined(PCIE9098) || defined(PCIE9097)
+ if (pmadapter->pcard_pcie->reg->use_adma) {
+ wrptr = rdptr & 0xffff;
+ rdptr = rdptr >> ADMA_RPTR_START;
+ if (wrptr != pmadapter->pcard_pcie->txbd_wrptr)
+ PRINTM(MERROR, "wlan: Unexpected wrptr 0x%x 0x%x\n",
+ wrptr, pmadapter->pcard_pcie->txbd_wrptr);
+ }
+#endif
+
+ /* free from previous txbd_rdptr to current txbd_rdptr */
+ while (wlan_check_tx_pending_buffer(pmadapter, rdptr)) {
+ wrdoneidx =
+ pmadapter->pcard_pcie->txbd_rdptr & (num_tx_buffs - 1);
+ pmbuf = pmadapter->pcard_pcie->tx_buf_list[wrdoneidx];
+ if (pmbuf) {
+ PRINTM(MDAT_D,
+ "SEND DATA COMP: Detach pmbuf %p at tx_ring[%d], pmadapter->txbd_rdptr=0x%x\n",
+ pmbuf, wrdoneidx,
+ pmadapter->pcard_pcie->txbd_rdptr);
+ ret = pcb->moal_unmap_memory(
+ pmadapter->pmoal_handle,
+ pmbuf->pbuf + pmbuf->data_offset, pmbuf->buf_pa,
+ pmbuf->data_len, PCI_DMA_TODEVICE);
+ if (ret == MLAN_STATUS_FAILURE) {
+ PRINTM(MERROR, "%s: moal_unmap_memory failed\n",
+ __FUNCTION__);
+ break;
+ }
+ unmap_count++;
+ pmadapter->pcard_pcie->txbd_pending--;
+#if defined(PCIE8997) || defined(PCIE8897)
+ if (pmadapter->pcard_pcie->txbd_flush)
+ wlan_write_data_complete(pmadapter, pmbuf,
+ MLAN_STATUS_FAILURE);
+ else
+#endif
+ wlan_write_data_complete(pmadapter, pmbuf,
+ MLAN_STATUS_SUCCESS);
+ }
+
+ pmadapter->pcard_pcie->tx_buf_list[wrdoneidx] = MNULL;
+#if defined(PCIE8997) || defined(PCIE8897)
+ if (!pmadapter->pcard_pcie->reg->use_adma) {
+ ptx_bd_buf = (mlan_pcie_data_buf *)pmadapter->pcard_pcie
+ ->txbd_ring[wrdoneidx];
+ ptx_bd_buf->paddr = 0;
+ ptx_bd_buf->len = 0;
+ ptx_bd_buf->flags = 0;
+ ptx_bd_buf->frag_len = 0;
+ ptx_bd_buf->offset = 0;
+ pmadapter->pcard_pcie->txbd_rdptr++;
+ if ((pmadapter->pcard_pcie->txbd_rdptr &
+ txrx_rw_ptr_mask) == num_tx_buffs)
+ pmadapter->pcard_pcie->txbd_rdptr =
+ ((pmadapter->pcard_pcie->txbd_rdptr &
+ txrx_rw_ptr_rollover_ind) ^
+ txrx_rw_ptr_rollover_ind);
+ }
+#endif
+#if defined(PCIE9098) || defined(PCIE9097)
+ if (pmadapter->pcard_pcie->reg->use_adma) {
+ padma_bd_buf =
+ (adma_dual_desc_buf *)pmadapter->pcard_pcie
+ ->txbd_ring[wrdoneidx];
+ padma_bd_buf->paddr = 0;
+ padma_bd_buf->len = 0;
+ padma_bd_buf->flags = 0;
+ padma_bd_buf->pkt_size = 0;
+ padma_bd_buf->reserved = 0;
+ pmadapter->pcard_pcie->txbd_rdptr++;
+ pmadapter->pcard_pcie->txbd_rdptr &=
+ ADMA_RW_PTR_WRAP_MASK;
+ }
+#endif
+ }
+
+ if (unmap_count)
+ pmadapter->data_sent = MFALSE;
+#if defined(PCIE8997) || defined(PCIE8897)
+ if (pmadapter->pcard_pcie->txbd_flush) {
+ if (PCIE_TXBD_EMPTY(pmadapter->pcard_pcie->txbd_wrptr,
+ pmadapter->pcard_pcie->txbd_rdptr,
+ txrx_rw_ptr_mask, txrx_rw_ptr_rollover_ind))
+ pmadapter->pcard_pcie->txbd_flush = MFALSE;
+ else
+ wlan_pcie_flush_txbd_ring(pmadapter);
+ }
+#endif
+done:
+ LEAVE();
+ return ret;
+}
+
+#if defined(PCIE8997) || defined(PCIE8897)
+#define PCIE_TXBD_NOT_FULL(wrptr, rdptr, mask, rollover_ind) \
+ (((wrptr & mask) != (rdptr & mask)) || \
+ ((wrptr & rollover_ind) == (rdptr & rollover_ind)))
+#endif
+
+#if defined(PCIE9098) || defined(PCIE9097)
+#define ADMA_TXBD_IS_FULL(wrptr, rdptr) \
+ (((wrptr & TXRX_RW_PTR_MASK) == (rdptr & TXRX_RW_PTR_MASK)) && \
+ ((wrptr & TXRX_RW_PTR_ROLLOVER_IND) != \
+ (rdptr & TXRX_RW_PTR_ROLLOVER_IND)))
+#endif
+
+static t_u8 wlan_check_txbd_not_full(mlan_adapter *pmadapter)
+{
+#if defined(PCIE8997) || defined(PCIE8897)
+ t_u32 txrx_rw_ptr_mask = pmadapter->pcard_pcie->reg->txrx_rw_ptr_mask;
+ t_u32 txrx_rw_ptr_rollover_ind =
+ pmadapter->pcard_pcie->reg->txrx_rw_ptr_rollover_ind;
+ if (!pmadapter->pcard_pcie->reg->use_adma) {
+ if (PCIE_TXBD_NOT_FULL(pmadapter->pcard_pcie->txbd_wrptr,
+ pmadapter->pcard_pcie->txbd_rdptr,
+ txrx_rw_ptr_mask,
+ txrx_rw_ptr_rollover_ind))
+ return MTRUE;
+ else
+ return MFALSE;
+ }
+#endif
+#if defined(PCIE9098) || defined(PCIE9097)
+ if (pmadapter->pcard_pcie->reg->use_adma) {
+ if (!ADMA_TXBD_IS_FULL(pmadapter->pcard_pcie->txbd_wrptr,
+ pmadapter->pcard_pcie->txbd_rdptr))
+ return MTRUE;
+ else
+ return MFALSE;
+ }
+#endif
+ return MFALSE;
+}
+
+/**
+ * @brief This function downloads data to the card.
+ *
+ * @param pmadapter A pointer to mlan_adapter structure
+ * @param type packet type
+ * @param pmbuf A pointer to mlan_buffer (pmbuf->data_len should include
+ * PCIE header)
+ * @param tx_param A pointer to mlan_tx_param
+ *
+ * @return MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ */
+static mlan_status wlan_pcie_send_data(mlan_adapter *pmadapter, t_u8 type,
+ mlan_buffer *pmbuf,
+ mlan_tx_param *tx_param)
+{
+ t_u32 reg_txbd_wrptr = pmadapter->pcard_pcie->reg->reg_txbd_wrptr;
+#if defined(PCIE8997) || defined(PCIE8897)
+ t_u32 txrx_rw_ptr_mask = pmadapter->pcard_pcie->reg->txrx_rw_ptr_mask;
+ t_u32 txrx_rw_ptr_rollover_ind =
+ pmadapter->pcard_pcie->reg->txrx_rw_ptr_rollover_ind;
+ mlan_pcie_data_buf *ptx_bd_buf = MNULL;
+#endif
+#if defined(PCIE9098) || defined(PCIE9097)
+ adma_dual_desc_buf *padma_bd_buf = MNULL;
+#endif
+ const t_u32 num_tx_buffs = MLAN_MAX_TXRX_BD;
+ mlan_status ret = MLAN_STATUS_PENDING;
+ pmlan_callbacks pcb = &pmadapter->callbacks;
+ t_u32 rxbd_val = 0;
+ t_u32 wrindx;
+ t_u16 *tmp;
+ t_u8 *payload;
+ t_u32 wr_ptr_start = 0;
+
+ ENTER();
+
+ if (!(pmadapter && pmbuf)) {
+ PRINTM(MERROR, "%s() has no buffer", __FUNCTION__);
+ ret = MLAN_STATUS_FAILURE;
+ goto done;
+ }
+ if (!(pmbuf->pbuf && pmbuf->data_len)) {
+ PRINTM(MERROR, "Invalid parameter <%p, %#x>\n", pmbuf->pbuf,
+ pmbuf->data_len);
+ ret = MLAN_STATUS_FAILURE;
+ goto done;
+ }
+
+ PRINTM(MINFO, "SEND DATA: <Rd: %#x, Wr: %#x>\n",
+ pmadapter->pcard_pcie->txbd_rdptr,
+ pmadapter->pcard_pcie->txbd_wrptr);
+
+ if (wlan_check_txbd_not_full(pmadapter)) {
+ pmadapter->data_sent = MTRUE;
+
+ payload = pmbuf->pbuf + pmbuf->data_offset;
+ tmp = (t_u16 *)&payload[0];
+ *tmp = wlan_cpu_to_le16((t_u16)pmbuf->data_len);
+ tmp = (t_u16 *)&payload[2];
+ *tmp = wlan_cpu_to_le16(type);
+
+ /* Map pmbuf, and attach to tx ring */
+ if (MLAN_STATUS_FAILURE ==
+ pcb->moal_map_memory(pmadapter->pmoal_handle,
+ pmbuf->pbuf + pmbuf->data_offset,
+ &pmbuf->buf_pa, pmbuf->data_len,
+ PCI_DMA_TODEVICE)) {
+ PRINTM(MERROR,
+ "SEND DATA: failed to moal_map_memory\n");
+ ret = MLAN_STATUS_FAILURE;
+ goto done;
+ }
+ wrindx = pmadapter->pcard_pcie->txbd_wrptr & (num_tx_buffs - 1);
+ PRINTM(MDAT_D,
+ "SEND DATA: Attach pmbuf %p at tx_ring[%d], txbd_wrptr=0x%x\n",
+ pmbuf, wrindx, pmadapter->pcard_pcie->txbd_wrptr);
+ pmadapter->pcard_pcie->tx_buf_list[wrindx] = pmbuf;
+#if defined(PCIE8997) || defined(PCIE8897)
+ if (!pmadapter->pcard_pcie->reg->use_adma) {
+ wr_ptr_start = TXBD_RW_PTR_START;
+ ptx_bd_buf = (mlan_pcie_data_buf *)pmadapter->pcard_pcie
+ ->txbd_ring[wrindx];
+ ptx_bd_buf->paddr = pmbuf->buf_pa;
+ ptx_bd_buf->len = (t_u16)pmbuf->data_len;
+ ptx_bd_buf->flags = MLAN_BD_FLAG_SOP | MLAN_BD_FLAG_EOP;
+ ptx_bd_buf->frag_len = (t_u16)pmbuf->data_len;
+ ptx_bd_buf->offset = 0;
+ pmadapter->pcard_pcie->last_tx_pkt_size[wrindx] =
+ pmbuf->data_len;
+ pmadapter->pcard_pcie->txbd_wrptr++;
+ if ((pmadapter->pcard_pcie->txbd_wrptr &
+ txrx_rw_ptr_mask) == num_tx_buffs)
+ pmadapter->pcard_pcie->txbd_wrptr =
+ ((pmadapter->pcard_pcie->txbd_wrptr &
+ txrx_rw_ptr_rollover_ind) ^
+ txrx_rw_ptr_rollover_ind);
+ rxbd_val = pmadapter->pcard_pcie->rxbd_wrptr &
+ pmadapter->pcard_pcie->reg
+ ->txrx_rw_ptr_wrap_mask;
+ }
+#endif
+
+#if defined(PCIE9098) || defined(PCIE9097)
+ if (pmadapter->pcard_pcie->reg->use_adma) {
+ wr_ptr_start = ADMA_WPTR_START;
+ padma_bd_buf = (adma_dual_desc_buf *)pmadapter
+ ->pcard_pcie->txbd_ring[wrindx];
+ padma_bd_buf->paddr = pmbuf->buf_pa;
+ padma_bd_buf->len =
+ ALIGN_SZ(pmbuf->data_len, ADMA_ALIGN_SIZE);
+ padma_bd_buf->flags =
+ ADMA_BD_FLAG_SOP | ADMA_BD_FLAG_EOP |
+ ADMA_BD_FLAG_INT_EN | ADMA_BD_FLAG_SRC_HOST;
+ if (padma_bd_buf->len < ADMA_MIN_PKT_SIZE)
+ padma_bd_buf->len = ADMA_MIN_PKT_SIZE;
+ padma_bd_buf->pkt_size = pmbuf->data_len;
+ pmadapter->pcard_pcie->last_tx_pkt_size[wrindx] =
+ pmbuf->data_len;
+ pmadapter->pcard_pcie->txbd_wrptr++;
+ pmadapter->pcard_pcie->txbd_wrptr &=
+ ADMA_RW_PTR_WRAP_MASK;
+ }
+#endif
+ pmadapter->pcard_pcie->txbd_pending++;
+ PRINTM(MINFO, "REG_TXBD_WRPT(0x%x) = 0x%x\n", reg_txbd_wrptr,
+ ((pmadapter->pcard_pcie->txbd_wrptr << wr_ptr_start) |
+ rxbd_val));
+ /* Write the TX ring write pointer in to REG_TXBD_WRPTR */
+ if (pcb->moal_write_reg(pmadapter->pmoal_handle, reg_txbd_wrptr,
+ (pmadapter->pcard_pcie->txbd_wrptr
+ << wr_ptr_start) |
+ rxbd_val)) {
+ PRINTM(MERROR,
+ "SEND DATA: failed to write REG_TXBD_WRPTR\n");
+ ret = MLAN_STATUS_FAILURE;
+ goto done_unmap;
+ }
+ PRINTM(MINFO, "SEND DATA: Updated <Rd: %#x, Wr: %#x>\n",
+ pmadapter->pcard_pcie->txbd_rdptr,
+ pmadapter->pcard_pcie->txbd_wrptr);
+
+ if (wlan_check_txbd_not_full(pmadapter))
+ pmadapter->data_sent = MFALSE;
+
+ PRINTM(MINFO, "Sent packet to firmware successfully\n");
+ } else {
+ PRINTM(MERROR,
+ "TX Ring full, can't send anymore packets to firmware\n");
+ PRINTM(MINFO, "SEND DATA (FULL!): <Rd: %#x, Wr: %#x>\n",
+ pmadapter->pcard_pcie->txbd_rdptr,
+ pmadapter->pcard_pcie->txbd_wrptr);
+ pmadapter->data_sent = MTRUE;
+#if defined(PCIE8997) || defined(PCIE8897)
+ if (!pmadapter->pcard_pcie->reg->use_adma) {
+ /* Send the TX ready interrupt */
+ if (pcb->moal_write_reg(pmadapter->pmoal_handle,
+ pmadapter->pcard_pcie->reg
+ ->reg_cpu_int_event,
+ CPU_INTR_DNLD_RDY))
+ PRINTM(MERROR,
+ "SEND DATA (FULL): failed to assert dnld-rdy interrupt\n");
+ }
+#endif
+ ret = MLAN_STATUS_FAILURE;
+ goto done;
+ }
+
+ LEAVE();
+ return ret;
+
+done_unmap:
+ if (MLAN_STATUS_FAILURE ==
+ pcb->moal_unmap_memory(
+ pmadapter->pmoal_handle, pmbuf->pbuf + pmbuf->data_offset,
+ pmbuf->buf_pa, pmbuf->data_len, PCI_DMA_TODEVICE)) {
+ PRINTM(MERROR, "SEND DATA: failed to moal_unmap_memory\n");
+ ret = MLAN_STATUS_FAILURE;
+ }
+ pmadapter->pcard_pcie->txbd_pending--;
+ pmadapter->pcard_pcie->tx_buf_list[wrindx] = MNULL;
+#if defined(PCIE8997) || defined(PCIE8897)
+ if (!pmadapter->pcard_pcie->reg->use_adma && ptx_bd_buf) {
+ ptx_bd_buf->paddr = 0;
+ ptx_bd_buf->len = 0;
+ ptx_bd_buf->flags = 0;
+ ptx_bd_buf->frag_len = 0;
+ ptx_bd_buf->offset = 0;
+ }
+#endif
+#if defined(PCIE9098) || defined(PCIE9097)
+ if (pmadapter->pcard_pcie->reg->use_adma && padma_bd_buf) {
+ padma_bd_buf->paddr = 0;
+ padma_bd_buf->len = 0;
+ padma_bd_buf->flags = 0;
+ padma_bd_buf->pkt_size = 0;
+ padma_bd_buf->reserved = 0;
+ }
+#endif
+done:
+ LEAVE();
+ return ret;
+}
+
+/**
+ * @brief This function check the rx pending buffer
+ *
+ * @param pmadapter A pointer to mlan_adapter structure
+ * @param rdptr rx rdptr
+ *
+ * @return MTRUE/MFALSE;
+ */
+static t_u8 wlan_check_rx_pending_buffer(mlan_adapter *pmadapter, t_u32 rdptr)
+{
+#if defined(PCIE8997) || defined(PCIE8897)
+ t_u32 txrx_rw_ptr_mask = pmadapter->pcard_pcie->reg->txrx_rw_ptr_mask;
+ t_u32 txrx_rw_ptr_rollover_ind =
+ pmadapter->pcard_pcie->reg->txrx_rw_ptr_rollover_ind;
+ if (!pmadapter->pcard_pcie->reg->use_adma) {
+ if (((rdptr & txrx_rw_ptr_mask) !=
+ (pmadapter->pcard_pcie->rxbd_rdptr & txrx_rw_ptr_mask)) ||
+ ((rdptr & txrx_rw_ptr_rollover_ind) !=
+ (pmadapter->pcard_pcie->rxbd_rdptr &
+ txrx_rw_ptr_rollover_ind)))
+ return MTRUE;
+ else
+ return MFALSE;
+ }
+#endif
+
+#if defined(PCIE9098) || defined(PCIE9097)
+ if (pmadapter->pcard_pcie->reg->use_adma) {
+ if ((pmadapter->pcard_pcie->rxbd_rdptr &
+ ADMA_RW_PTR_WRAP_MASK) != (rdptr & ADMA_RW_PTR_WRAP_MASK))
+ return MTRUE;
+ else
+ return MFALSE;
+ }
+#endif
+ return MFALSE;
+}
+
+/**
+ * @brief This function handles received buffer ring and
+ * dispatches packets to upper
+ *
+ * @param pmadapter A pointer to mlan_adapter structure
+ *
+ * @return MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ */
+static mlan_status wlan_pcie_process_recv_data(mlan_adapter *pmadapter)
+{
+ mlan_status ret = MLAN_STATUS_SUCCESS;
+ pmlan_callbacks pcb = &pmadapter->callbacks;
+ t_u32 rdptr, rd_index;
+ mlan_buffer *pmbuf = MNULL;
+ t_u32 txbd_val = 0;
+ t_u16 rx_len, rx_type;
+ const t_u32 num_rx_buffs = MLAN_MAX_TXRX_BD;
+ t_u32 reg_rxbd_rdptr = pmadapter->pcard_pcie->reg->reg_rxbd_rdptr;
+#if defined(PCIE8997) || defined(PCIE8897)
+ t_u32 txrx_rw_ptr_mask = pmadapter->pcard_pcie->reg->txrx_rw_ptr_mask;
+ t_u32 txrx_rw_ptr_rollover_ind =
+ pmadapter->pcard_pcie->reg->txrx_rw_ptr_rollover_ind;
+ mlan_pcie_data_buf *prxbd_buf;
+#endif
+#if defined(PCIE9098) || defined(PCIE9097)
+ adma_dual_desc_buf *padma_bd_buf;
+#endif
+
+ ENTER();
+
+ /* Read the RX ring Read pointer set by firmware */
+ if (pcb->moal_read_reg(pmadapter->pmoal_handle, reg_rxbd_rdptr,
+ &rdptr)) {
+ PRINTM(MERROR, "RECV DATA: failed to read REG_RXBD_RDPTR\n");
+ ret = MLAN_STATUS_FAILURE;
+ goto done;
+ }
+#if defined(PCIE9098) || defined(PCIE9097)
+ if (pmadapter->pcard_pcie->reg->use_adma)
+ rdptr = rdptr >> ADMA_RPTR_START;
+#endif
+
+ while (wlan_check_rx_pending_buffer(pmadapter, rdptr)) {
+ /* detach pmbuf (with data) from Rx Ring */
+ rd_index =
+ pmadapter->pcard_pcie->rxbd_rdptr & (num_rx_buffs - 1);
+ if (rd_index > MLAN_MAX_TXRX_BD - 1) {
+ PRINTM(MERROR, "RECV DATA: Invalid Rx buffer index.\n");
+ ret = MLAN_STATUS_FAILURE;
+ goto done;
+ }
+ pmbuf = pmadapter->pcard_pcie->rx_buf_list[rd_index];
+
+ if (MLAN_STATUS_FAILURE ==
+ pcb->moal_unmap_memory(pmadapter->pmoal_handle,
+ pmbuf->pbuf + pmbuf->data_offset,
+ pmbuf->buf_pa, MLAN_RX_DATA_BUF_SIZE,
+ PCI_DMA_FROMDEVICE)) {
+ PRINTM(MERROR,
+ "RECV DATA: moal_unmap_memory failed.\n");
+ ret = MLAN_STATUS_FAILURE;
+ goto done;
+ }
+ pmadapter->pcard_pcie->rx_buf_list[rd_index] = MNULL;
+ PRINTM(MDAT_D,
+ "RECV DATA: Detach pmbuf %p at rx_ring[%d], pmadapter->rxbd_rdptr=0x%x\n",
+ pmbuf, rd_index, pmadapter->pcard_pcie->rxbd_rdptr);
+
+ /* Get data length from interface header -
+ first 2 bytes are len, second 2 bytes are type */
+ rx_len = *((t_u16 *)(pmbuf->pbuf + pmbuf->data_offset));
+ rx_len = wlan_le16_to_cpu(rx_len);
+ rx_type = *((t_u16 *)(pmbuf->pbuf + pmbuf->data_offset + 2));
+ rx_type = wlan_le16_to_cpu(rx_type);
+
+ PRINTM(MINFO,
+ "RECV DATA: <Wr: %#x, Rd: %#x>, Len=%d rx_type=%d\n",
+ pmadapter->pcard_pcie->rxbd_wrptr, rdptr, rx_len,
+ rx_type);
+
+ if (rx_len <= MLAN_RX_DATA_BUF_SIZE) {
+ /* send buffer to host (which will free it) */
+ pmbuf->data_len = rx_len - PCIE_INTF_HEADER_LEN;
+ pmbuf->data_offset += PCIE_INTF_HEADER_LEN;
+ // rx_trace 5
+ if (pmadapter->tp_state_on)
+ pmadapter->callbacks.moal_tp_accounting(
+ pmadapter->pmoal_handle, pmbuf,
+ 5 /*RX_DROP_P1*/);
+ if (pmadapter->tp_state_drop_point ==
+ 5 /*RX_DROP_P1*/) {
+ pmadapter->ops.data_complete(pmadapter, pmbuf,
+ ret);
+ } else {
+ PRINTM(MINFO,
+ "RECV DATA: Received packet from FW successfully\n");
+ pmadapter->callbacks.moal_spin_lock(
+ pmadapter->pmoal_handle,
+ pmadapter->rx_data_queue.plock);
+ util_enqueue_list_tail(
+ pmadapter->pmoal_handle,
+ &pmadapter->rx_data_queue,
+ (pmlan_linked_list)pmbuf, MNULL, MNULL);
+ pmadapter->rx_pkts_queued++;
+ pmadapter->callbacks.moal_tp_accounting_rx_param(
+ pmadapter->pmoal_handle, 1,
+ pmadapter->rx_pkts_queued);
+ pmadapter->callbacks.moal_spin_unlock(
+ pmadapter->pmoal_handle,
+ pmadapter->rx_data_queue.plock);
+
+ pmadapter->data_received = MTRUE;
+ }
+ /* Create new buffer and attach it to Rx Ring */
+ pmbuf = wlan_alloc_mlan_buffer(pmadapter,
+ MLAN_RX_DATA_BUF_SIZE,
+ MLAN_RX_HEADER_LEN,
+ MOAL_ALLOC_MLAN_BUFFER);
+ if (!pmbuf) {
+ PRINTM(MERROR,
+ "RECV DATA: Unable to allocate mlan_buffer\n");
+ ret = MLAN_STATUS_FAILURE;
+ goto done;
+ }
+ } else {
+ /* Queue the mlan_buffer again */
+ PRINTM(MERROR, "PCIE: Drop invalid packet, length=%d",
+ rx_len);
+ }
+
+ if (MLAN_STATUS_FAILURE ==
+ pcb->moal_map_memory(pmadapter->pmoal_handle,
+ pmbuf->pbuf + pmbuf->data_offset,
+ &pmbuf->buf_pa, MLAN_RX_DATA_BUF_SIZE,
+ PCI_DMA_FROMDEVICE)) {
+ PRINTM(MERROR, "RECV DATA: moal_map_memory failed\n");
+ ret = MLAN_STATUS_FAILURE;
+ goto done;
+ }
+
+ PRINTM(MDAT_D,
+ "RECV DATA: Attach new pmbuf %p at rx_ring[%d]\n", pmbuf,
+ rd_index);
+ pmadapter->pcard_pcie->rx_buf_list[rd_index] = pmbuf;
+#if defined(PCIE8997) || defined(PCIE8897)
+ if (!pmadapter->pcard_pcie->reg->use_adma) {
+ prxbd_buf = (mlan_pcie_data_buf *)pmadapter->pcard_pcie
+ ->rxbd_ring[rd_index];
+ prxbd_buf->paddr = pmbuf->buf_pa;
+ prxbd_buf->len = (t_u16)pmbuf->data_len;
+ prxbd_buf->flags = MLAN_BD_FLAG_SOP | MLAN_BD_FLAG_EOP;
+ prxbd_buf->offset = 0;
+ prxbd_buf->frag_len = (t_u16)pmbuf->data_len;
+
+ /* update rxbd's rdptrs */
+ if ((++pmadapter->pcard_pcie->rxbd_rdptr &
+ txrx_rw_ptr_mask) == MLAN_MAX_TXRX_BD) {
+ pmadapter->pcard_pcie->rxbd_rdptr =
+ ((pmadapter->pcard_pcie->rxbd_rdptr &
+ txrx_rw_ptr_rollover_ind) ^
+ txrx_rw_ptr_rollover_ind);
+ }
+
+ /* update rxbd's wrptrs */
+ if ((++pmadapter->pcard_pcie->rxbd_wrptr &
+ txrx_rw_ptr_mask) == MLAN_MAX_TXRX_BD) {
+ pmadapter->pcard_pcie->rxbd_wrptr =
+ ((pmadapter->pcard_pcie->rxbd_wrptr &
+ txrx_rw_ptr_rollover_ind) ^
+ txrx_rw_ptr_rollover_ind);
+ }
+ txbd_val = pmadapter->pcard_pcie->txbd_wrptr &
+ pmadapter->pcard_pcie->reg
+ ->txrx_rw_ptr_wrap_mask;
+ txbd_val = txbd_val << TXBD_RW_PTR_START;
+ }
+#endif
+#if defined(PCIE9098) || defined(PCIE9097)
+ if (pmadapter->pcard_pcie->reg->use_adma) {
+ padma_bd_buf =
+ (adma_dual_desc_buf *)pmadapter->pcard_pcie
+ ->rxbd_ring[rd_index];
+ padma_bd_buf->paddr = pmbuf->buf_pa;
+ padma_bd_buf->len =
+ ALIGN_SZ(pmbuf->data_len, ADMA_ALIGN_SIZE);
+ padma_bd_buf->flags =
+ ADMA_BD_FLAG_INT_EN | ADMA_BD_FLAG_DST_HOST;
+ padma_bd_buf->pkt_size = 0;
+ padma_bd_buf->reserved = 0;
+ pmadapter->pcard_pcie->rxbd_rdptr++;
+ pmadapter->pcard_pcie->rxbd_wrptr++;
+ pmadapter->pcard_pcie->rxbd_rdptr &=
+ ADMA_RW_PTR_WRAP_MASK;
+ pmadapter->pcard_pcie->rxbd_wrptr &=
+ ADMA_RW_PTR_WRAP_MASK;
+ }
+#endif
+ PRINTM(MINFO, "RECV DATA: Updated <Wr: %#x, Rd: %#x>\n",
+ pmadapter->pcard_pcie->rxbd_wrptr, rdptr);
+
+ /* Write the RX ring write pointer in to REG_RXBD_WRPTR */
+ if (pcb->moal_write_reg(
+ pmadapter->pmoal_handle,
+ pmadapter->pcard_pcie->reg->reg_rxbd_wrptr,
+ pmadapter->pcard_pcie->rxbd_wrptr | txbd_val)) {
+ PRINTM(MERROR,
+ "RECV DATA: failed to write REG_RXBD_WRPTR\n");
+ ret = MLAN_STATUS_FAILURE;
+ goto done;
+ }
+
+ /* Read the RX ring read pointer set by firmware */
+ if (pcb->moal_read_reg(pmadapter->pmoal_handle, reg_rxbd_rdptr,
+ &rdptr)) {
+ PRINTM(MERROR,
+ "RECV DATA: failed to read REG_RXBD_RDPTR\n");
+ ret = MLAN_STATUS_FAILURE;
+ goto done;
+ }
+#if defined(PCIE9098) || defined(PCIE9097)
+ if (pmadapter->pcard_pcie->reg->use_adma)
+ rdptr = rdptr >> ADMA_RPTR_START;
+#endif
+ }
+
+done:
+ LEAVE();
+ return ret;
+}
+
+/**
+ * @brief This function downloads command to the card.
+ *
+ * @param pmadapter A pointer to mlan_adapter structure
+ * @param pmbuf A pointer to mlan_buffer (pmbuf->data_len should include
+ * PCIE header)
+ *
+ * @return MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ */
+static mlan_status wlan_pcie_send_cmd(mlan_adapter *pmadapter,
+ mlan_buffer *pmbuf)
+{
+ mlan_status ret = MLAN_STATUS_PENDING;
+ pmlan_callbacks pcb = &pmadapter->callbacks;
+ t_u8 *payload = MNULL;
+
+ ENTER();
+ if (!(pmadapter && pmbuf)) {
+ PRINTM(MERROR, "%s() has no buffer", __FUNCTION__);
+ ret = MLAN_STATUS_FAILURE;
+ goto done;
+ }
+ if (!(pmbuf->pbuf && pmbuf->data_len)) {
+ PRINTM(MERROR, "Invalid parameter <%p, %#x>\n", pmbuf->pbuf,
+ pmbuf->data_len);
+ ret = MLAN_STATUS_FAILURE;
+ goto done;
+ }
+
+ /* Make sure a command response buffer is available */
+ if (!pmadapter->pcard_pcie->cmdrsp_buf) {
+ PRINTM(MERROR,
+ "No response buffer available, send command failed\n");
+ ret = MLAN_STATUS_FAILURE;
+ goto done;
+ }
+
+ pmadapter->cmd_sent = MTRUE;
+ payload = pmbuf->pbuf + pmbuf->data_offset;
+ *(t_u16 *)&payload[0] = wlan_cpu_to_le16((t_u16)pmbuf->data_len);
+ *(t_u16 *)&payload[2] = wlan_cpu_to_le16(MLAN_TYPE_CMD);
+
+ if (MLAN_STATUS_FAILURE ==
+ pcb->moal_map_memory(
+ pmadapter->pmoal_handle, pmbuf->pbuf + pmbuf->data_offset,
+ &pmbuf->buf_pa, MLAN_RX_CMD_BUF_SIZE, PCI_DMA_TODEVICE)) {
+ PRINTM(MERROR, "Command buffer : moal_map_memory failed\n");
+ LEAVE();
+ return MLAN_STATUS_FAILURE;
+ }
+ pmadapter->pcard_pcie->cmd_buf = pmbuf;
+
+#if defined(PCIE8997) || defined(PCIE8897)
+ if (!pmadapter->pcard_pcie->reg->use_adma) {
+ /* To send a command, the driver will:
+ 1. Write the 64bit physical address of the data buffer to
+ SCRATCH1 + SCRATCH0
+ 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 (pmadapter->pcard_pcie->cmdrsp_buf) {
+ /* Write the lower 32bits of the cmdrsp buffer physical
+ address */
+ if (pcb->moal_write_reg(pmadapter->pmoal_handle,
+ REG_CMDRSP_ADDR_LO,
+ (t_u32)pmadapter->pcard_pcie
+ ->cmdrsp_buf->buf_pa)) {
+ PRINTM(MERROR,
+ "Failed to write download command to boot code.\n");
+ ret = MLAN_STATUS_FAILURE;
+ goto done;
+ }
+ /* Write the upper 32bits of the cmdrsp buffer physical
+ address */
+ if (pcb->moal_write_reg(
+ pmadapter->pmoal_handle, REG_CMDRSP_ADDR_HI,
+ (t_u32)((t_u64)pmadapter->pcard_pcie
+ ->cmdrsp_buf->buf_pa >>
+ 32))) {
+ PRINTM(MERROR,
+ "Failed to write download command to boot code.\n");
+ ret = MLAN_STATUS_FAILURE;
+ goto done;
+ }
+ }
+
+ /* Write the lower 32bits of the physical address to
+ * REG_CMD_ADDR_LO */
+ if (pcb->moal_write_reg(
+ pmadapter->pmoal_handle, REG_CMD_ADDR_LO,
+ (t_u32)pmadapter->pcard_pcie->cmd_buf->buf_pa)) {
+ PRINTM(MERROR,
+ "Failed to write download command to boot code.\n");
+ ret = MLAN_STATUS_FAILURE;
+ goto done;
+ }
+ /* Write the upper 32bits of the physical address to
+ * REG_CMD_ADDR_HI */
+ if (pcb->moal_write_reg(pmadapter->pmoal_handle,
+ REG_CMD_ADDR_HI,
+ (t_u32)((t_u64)pmadapter->pcard_pcie
+ ->cmd_buf->buf_pa >>
+ 32))) {
+ PRINTM(MERROR,
+ "Failed to write download command to boot code.\n");
+ ret = MLAN_STATUS_FAILURE;
+ goto done;
+ }
+
+ /* Write the command length to REG_CMD_SIZE */
+ if (pcb->moal_write_reg(
+ pmadapter->pmoal_handle, REG_CMD_SIZE,
+ pmadapter->pcard_pcie->cmd_buf->data_len)) {
+ PRINTM(MERROR,
+ "Failed to write command length to REG_CMD_SIZE\n");
+ ret = MLAN_STATUS_FAILURE;
+ goto done;
+ }
+
+ /* Ring the door bell */
+ if (pcb->moal_write_reg(
+ pmadapter->pmoal_handle,
+ pmadapter->pcard_pcie->reg->reg_cpu_int_event,
+ CPU_INTR_DOOR_BELL)) {
+ PRINTM(MERROR,
+ "Failed to assert door-bell interrupt.\n");
+ ret = MLAN_STATUS_FAILURE;
+ goto done;
+ }
+ }
+#endif
+#if defined(PCIE9098) || defined(PCIE9097)
+ if (pmadapter->pcard_pcie->reg->use_adma) {
+ /* To send a command, the driver will:
+ 1. driver prepare the cmdrep buffer for adma
+ 2. driver programs dma_mode field to direct programming mode
+ and programs dma_size field to define DMA data transfer size.
+ 3. driver programs src_base_addr register to define source
+ location of DMA data
+ 4. driver sets src_wptr to 1 to initiate DMA operation
+ */
+ wlan_init_adma(pmadapter, ADMA_CMDRESP,
+ pmadapter->pcard_pcie->cmdrsp_buf->buf_pa,
+ MRVDRV_SIZE_OF_CMD_BUFFER, MFALSE);
+ wlan_init_adma(pmadapter, ADMA_CMD,
+ pmadapter->pcard_pcie->cmd_buf->buf_pa,
+ pmadapter->pcard_pcie->cmd_buf->data_len,
+ MFALSE);
+ }
+#endif
+done:
+ if ((ret == MLAN_STATUS_FAILURE) && pmadapter)
+ pmadapter->cmd_sent = MFALSE;
+
+ LEAVE();
+ return ret;
+}
+
+#if defined(PCIE8997) || defined(PCIE8897)
+#define MLAN_SLEEP_COOKIE_DEF 0xBEEFBEEF
+#define MAX_DELAY_LOOP_COUNT 100
+
+static void mlan_delay_for_sleep_cookie(mlan_adapter *pmadapter,
+ t_u32 max_delay_loop_cnt)
+{
+ t_u8 *buffer;
+ t_u32 sleep_cookie = 0;
+ t_u32 count = 0;
+ pmlan_buffer pmbuf = pmadapter->pcard_pcie->cmdrsp_buf;
+
+ for (count = 0; count < max_delay_loop_cnt; count++) {
+ buffer = pmbuf->pbuf;
+ sleep_cookie = *(t_u32 *)buffer;
+
+ if (sleep_cookie == MLAN_SLEEP_COOKIE_DEF) {
+ PRINTM(MINFO, "sleep cookie FOUND at count = %d!!\n",
+ count);
+ break;
+ }
+ wlan_udelay(pmadapter, 20);
+ }
+
+ if (count >= max_delay_loop_cnt)
+ PRINTM(MERROR, "sleep cookie not found!!\n");
+}
+#endif
+
+/**
+ * @brief This function handles command complete interrupt
+ *
+ * @param pmadapter A pointer to mlan_adapter structure
+ *
+ * @return MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ */
+static mlan_status wlan_pcie_process_cmd_resp(mlan_adapter *pmadapter)
+{
+ mlan_status ret = MLAN_STATUS_SUCCESS;
+ pmlan_callbacks pcb = &pmadapter->callbacks;
+ pmlan_buffer pmbuf = pmadapter->pcard_pcie->cmdrsp_buf;
+ pmlan_buffer cmd_buf = MNULL;
+ t_u16 resp_len = 0;
+
+ ENTER();
+
+ PRINTM(MINFO, "Rx CMD Response\n");
+
+ if (pmbuf == MNULL) {
+ PRINTM(MMSG, "Rx CMD response pmbuf is null\n");
+ LEAVE();
+ return MLAN_STATUS_FAILURE;
+ }
+
+ /* Get data length from interface header -
+ first 2 bytes are len, second 2 bytes are type */
+ resp_len = *((t_u16 *)(pmbuf->pbuf + pmbuf->data_offset));
+
+ pmadapter->upld_len = wlan_le16_to_cpu(resp_len);
+ pmadapter->upld_len -= PCIE_INTF_HEADER_LEN;
+
+ if (!pmadapter->curr_cmd) {
+ if (pmadapter->ps_state == PS_STATE_SLEEP_CFM) {
+ wlan_process_sleep_confirm_resp(
+ pmadapter,
+ pmbuf->pbuf + pmbuf->data_offset +
+ PCIE_INTF_HEADER_LEN,
+ pmadapter->upld_len);
+ /* We are sending sleep confirm done interrupt in the
+ * middle of sleep handshake. There is a corner case
+ * when Tx done interrupt is received from firmware
+ * during sleep handshake due to which host and firmware
+ * power states go out of sync causing Tx data timeout
+ * problem. Hence sleep confirm done interrupt is sent
+ * at the end of sleep handshake to fix the problem
+ *
+ * Host could be reading the interrupt during polling
+ * (while loop) or to address a FW interrupt. In either
+ * case, after clearing the interrupt driver needs to
+ * send a sleep confirm event at the end of processing
+ * command response right here. This marks the end of
+ * the sleep handshake with firmware.
+ */
+ wlan_pcie_enable_host_int_mask(pmadapter);
+ if (pcb->moal_write_reg(pmadapter->pmoal_handle,
+ pmadapter->pcard_pcie->reg
+ ->reg_cpu_int_event,
+ CPU_INTR_SLEEP_CFM_DONE)) {
+ PRINTM(MERROR, "Write register failed\n");
+ LEAVE();
+ return MLAN_STATUS_FAILURE;
+ }
+#if defined(PCIE8997) || defined(PCIE8897)
+ mlan_delay_for_sleep_cookie(pmadapter,
+ MAX_DELAY_LOOP_COUNT);
+#endif
+ cmd_buf = pmadapter->pcard_pcie->cmd_buf;
+ if (cmd_buf) {
+ pcb->moal_unmap_memory(
+ pmadapter->pmoal_handle,
+ cmd_buf->pbuf + cmd_buf->data_offset,
+ cmd_buf->buf_pa, WLAN_UPLD_SIZE,
+ PCI_DMA_TODEVICE);
+ pmadapter->pcard_pcie->cmd_buf = MNULL;
+ }
+ }
+ memcpy_ext(pmadapter, pmadapter->upld_buf,
+ pmbuf->pbuf + pmbuf->data_offset +
+ PCIE_INTF_HEADER_LEN,
+ pmadapter->upld_len, MRVDRV_SIZE_OF_CMD_BUFFER);
+
+ } else {
+ pmadapter->cmd_resp_received = MTRUE;
+ pmbuf->data_len = pmadapter->upld_len;
+ pmbuf->data_offset += PCIE_INTF_HEADER_LEN;
+ pmadapter->curr_cmd->respbuf = pmbuf;
+
+ /* Take the pointer and set it to CMD node and will
+ return in the response complete callback */
+ pmadapter->pcard_pcie->cmdrsp_buf = MNULL;
+#if defined(PCIE8997) || defined(PCIE8897)
+ if (!pmadapter->pcard_pcie->reg->use_adma) {
+ /* Clear the cmd-rsp buffer address in scratch
+ registers. This will prevent firmware from writing to
+ the same response buffer again. */
+ if (pcb->moal_write_reg(pmadapter->pmoal_handle,
+ REG_CMDRSP_ADDR_LO, 0)) {
+ PRINTM(MERROR,
+ "Rx CMD: failed to clear cmd_rsp address.\n");
+ ret = MLAN_STATUS_FAILURE;
+ goto done;
+ }
+ /* Write the upper 32bits of the cmdrsp buffer physical
+ address */
+ if (pcb->moal_write_reg(pmadapter->pmoal_handle,
+ REG_CMDRSP_ADDR_HI, 0)) {
+ PRINTM(MERROR,
+ "Rx CMD: failed to clear cmd_rsp address.\n");
+ ret = MLAN_STATUS_FAILURE;
+ goto done;
+ }
+ }
+#endif
+#if defined(PCIE9098) || defined(PCIE9097)
+ if (pmadapter->pcard_pcie->reg->use_adma) {
+ /* Clear the cmd-rsp buffer address in adma registers.
+ This will prevent firmware from writing to the same
+ response buffer again. */
+ if (wlan_init_adma(pmadapter, ADMA_CMDRESP, 0, 0,
+ MFALSE)) {
+ PRINTM(MERROR,
+ "Rx CMD: failed to clear cmd_rsp address.\n");
+ ret = MLAN_STATUS_FAILURE;
+ goto done;
+ }
+ }
+#endif
+ }
+
+done:
+ LEAVE();
+ return ret;
+}
+
+/**
+ * @brief This function handles command response completion
+ *
+ * @param pmadapter A pointer to mlan_adapter structure
+ * @param pmbuf A pointer to mlan_buffer
+ *
+ * @return MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ */
+mlan_status wlan_pcie_cmdrsp_complete(mlan_adapter *pmadapter,
+ mlan_buffer *pmbuf, mlan_status status)
+{
+ mlan_buffer *pcmdmbuf;
+ pmlan_callbacks pcb = &pmadapter->callbacks;
+
+ ENTER();
+
+ /*return the cmd response pmbuf*/
+ if (pmbuf) {
+ pmbuf->data_len = MRVDRV_SIZE_OF_CMD_BUFFER;
+ pmbuf->data_offset -= PCIE_INTF_HEADER_LEN;
+ pmadapter->pcard_pcie->cmdrsp_buf = pmbuf;
+ }
+
+ /*unmap the cmd pmbuf, so the cpu can not access the memory in the
+ * command node*/
+ pcmdmbuf = pmadapter->pcard_pcie->cmd_buf;
+
+ if (pcmdmbuf) {
+ pcb->moal_unmap_memory(pmadapter->pmoal_handle,
+ pcmdmbuf->pbuf + pcmdmbuf->data_offset,
+ pcmdmbuf->buf_pa, WLAN_UPLD_SIZE,
+ PCI_DMA_TODEVICE);
+ pmadapter->pcard_pcie->cmd_buf = MNULL;
+ }
+
+ LEAVE();
+ return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ * @brief This function check pending evt buffer
+ *
+ * @param pmadapter A pointer to mlan_adapter structure
+ * @param rdptr evt rdptr
+ *
+ * @return MTRUE/MFALSE;
+ */
+static t_u8 wlan_check_evt_buffer(mlan_adapter *pmadapter, t_u32 rdptr)
+{
+#if defined(PCIE8997) || defined(PCIE8897)
+ if (!pmadapter->pcard_pcie->reg->use_adma) {
+ if (((rdptr & EVT_RW_PTR_MASK) !=
+ (pmadapter->pcard_pcie->evtbd_rdptr & EVT_RW_PTR_MASK)) ||
+ ((rdptr & EVT_RW_PTR_ROLLOVER_IND) !=
+ (pmadapter->pcard_pcie->evtbd_rdptr &
+ EVT_RW_PTR_ROLLOVER_IND)))
+ return MTRUE;
+ else
+ return MFALSE;
+ }
+#endif
+#if defined(PCIE9098) || defined(PCIE9097)
+ if (pmadapter->pcard_pcie->reg->use_adma) {
+ if ((pmadapter->pcard_pcie->evtbd_rdptr &
+ ADMA_RW_PTR_WRAP_MASK) != (rdptr & ADMA_RW_PTR_WRAP_MASK))
+ return MTRUE;
+ else
+ return MFALSE;
+ }
+#endif
+ return MFALSE;
+}
+
+/**
+ * @brief This function handles FW event ready interrupt
+ *
+ * @param pmadapter A pointer to mlan_adapter structure
+ *
+ * @return MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ */
+static mlan_status wlan_pcie_process_event_ready(mlan_adapter *pmadapter)
+{
+ t_u32 rd_index =
+ pmadapter->pcard_pcie->evtbd_rdptr & (MLAN_MAX_EVT_BD - 1);
+ t_u32 rdptr, event;
+ pmlan_callbacks pcb = &pmadapter->callbacks;
+#if defined(PCIE8997) || defined(PCIE8897)
+ mlan_pcie_evt_buf *pevtbd_buf;
+#endif
+#if defined(PCIE9098) || defined(PCIE9097)
+ adma_dual_desc_buf *padma_bd_buf;
+#endif
+ ENTER();
+
+ if (pmadapter->event_received) {
+ PRINTM(MINFO, "Event being processed, do not "
+ "process this interrupt just yet\n");
+ LEAVE();
+ return MLAN_STATUS_SUCCESS;
+ }
+
+ if (rd_index >= MLAN_MAX_EVT_BD) {
+ PRINTM(MINFO, "Invalid rd_index...\n");
+ LEAVE();
+ return MLAN_STATUS_FAILURE;
+ }
+
+ /* Read the event ring read pointer set by firmware */
+ if (pcb->moal_read_reg(pmadapter->pmoal_handle,
+ pmadapter->pcard_pcie->reg->reg_evtbd_rdptr,
+ &rdptr)) {
+ PRINTM(MERROR, "EvtRdy: failed to read REG_EVTBD_RDPTR\n");
+ LEAVE();
+ return MLAN_STATUS_FAILURE;
+ }
+#if defined(PCIE9098) || defined(PCIE9097)
+ if (pmadapter->pcard_pcie->reg->use_adma)
+ rdptr = rdptr >> ADMA_RPTR_START;
+#endif
+ PRINTM(MINFO, "EvtRdy: Initial <Wr: 0x%x, Rd: 0x%x>\n",
+ pmadapter->pcard_pcie->evtbd_wrptr, rdptr);
+ if (wlan_check_evt_buffer(pmadapter, rdptr)) {
+ mlan_buffer *pmbuf_evt;
+ t_u16 evt_len;
+
+ PRINTM(MINFO, "EvtRdy: Read Index: %d\n", rd_index);
+ pmbuf_evt = pmadapter->pcard_pcie->evt_buf_list[rd_index];
+
+ /*unmap the pmbuf for CPU Access*/
+ pcb->moal_unmap_memory(pmadapter->pmoal_handle,
+ pmbuf_evt->pbuf + pmbuf_evt->data_offset,
+ pmbuf_evt->buf_pa, MAX_EVENT_SIZE,
+ PCI_DMA_FROMDEVICE);
+
+ /* Take the pointer and set it to event pointer in adapter
+ and will return back after event handling callback */
+#if defined(PCIE8997) || defined(PCIE8897)
+ if (!pmadapter->pcard_pcie->reg->use_adma) {
+ pevtbd_buf = (mlan_pcie_evt_buf *)pmadapter->pcard_pcie
+ ->evtbd_ring[rd_index];
+ pevtbd_buf->paddr = 0;
+ pevtbd_buf->len = 0;
+ pevtbd_buf->flags = 0;
+ }
+#endif
+
+#if defined(PCIE9098) || defined(PCIE9097)
+ if (pmadapter->pcard_pcie->reg->use_adma) {
+ padma_bd_buf =
+ (adma_dual_desc_buf *)pmadapter->pcard_pcie
+ ->evtbd_ring[rd_index];
+ padma_bd_buf->paddr = 0;
+ padma_bd_buf->len = 0;
+ padma_bd_buf->flags = 0;
+ padma_bd_buf->pkt_size = 0;
+ padma_bd_buf->reserved = 0;
+ }
+#endif
+ pmadapter->pcard_pcie->evt_buf_list[rd_index] = MNULL;
+
+ event = *((t_u32 *)&pmbuf_evt->pbuf[pmbuf_evt->data_offset +
+ PCIE_INTF_HEADER_LEN]);
+ pmadapter->event_cause = wlan_le32_to_cpu(event);
+ /* The first 4bytes will be the event transfer header
+ len is 2 bytes followed by type which is 2 bytes */
+ evt_len = *((t_u16 *)&pmbuf_evt->pbuf[pmbuf_evt->data_offset]);
+ evt_len = wlan_le16_to_cpu(evt_len);
+
+ if ((evt_len > 0) && (evt_len > MLAN_EVENT_HEADER_LEN) &&
+ (evt_len - MLAN_EVENT_HEADER_LEN < MAX_EVENT_SIZE))
+ memcpy_ext(pmadapter, pmadapter->event_body,
+ pmbuf_evt->pbuf + pmbuf_evt->data_offset +
+ MLAN_EVENT_HEADER_LEN,
+ evt_len - MLAN_EVENT_HEADER_LEN,
+ sizeof(pmadapter->event_body));
+
+ pmbuf_evt->data_offset += PCIE_INTF_HEADER_LEN;
+ pmbuf_evt->data_len = evt_len - PCIE_INTF_HEADER_LEN;
+ PRINTM(MINFO, "Event length: %d\n", pmbuf_evt->data_len);
+
+ pmadapter->event_received = MTRUE;
+ pmadapter->pmlan_buffer_event = pmbuf_evt;
+ pmadapter->pcard_pcie->evtbd_rdptr++;
+#if defined(PCIE8997) || defined(PCIE8897)
+ if (!pmadapter->pcard_pcie->reg->use_adma) {
+ if ((pmadapter->pcard_pcie->evtbd_rdptr &
+ EVT_RW_PTR_MASK) == MLAN_MAX_EVT_BD) {
+ pmadapter->pcard_pcie->evtbd_rdptr =
+ ((pmadapter->pcard_pcie->evtbd_rdptr &
+ EVT_RW_PTR_ROLLOVER_IND) ^
+ EVT_RW_PTR_ROLLOVER_IND);
+ }
+ }
+#endif
+
+#if defined(PCIE9098) || defined(PCIE9097)
+ if (pmadapter->pcard_pcie->reg->use_adma)
+ pmadapter->pcard_pcie->evtbd_rdptr &=
+ ADMA_RW_PTR_WRAP_MASK;
+#endif
+
+ /* Do not update the event write 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 {
+ PRINTM(MINTR, "------>EVENT DONE\n");
+ if (pcb->moal_write_reg(
+ pmadapter->pmoal_handle,
+ pmadapter->pcard_pcie->reg->reg_cpu_int_event,
+ CPU_INTR_EVENT_DONE)) {
+ PRINTM(MERROR,
+ "Failed to asset event done interrupt\n");
+ return MLAN_STATUS_FAILURE;
+ }
+ }
+ LEAVE();
+ return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ * @brief This function handles event completion
+ *
+ * @param pmadapter A pointer to mlan_adapter structure
+ * @param pmbuf A pointer to mlan_buffer
+ *
+ * @return MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ */
+mlan_status wlan_pcie_event_complete(mlan_adapter *pmadapter,
+ mlan_buffer *pmbuf, mlan_status status)
+{
+ mlan_status ret = MLAN_STATUS_SUCCESS;
+ pmlan_callbacks pcb = &pmadapter->callbacks;
+ t_u32 wrptr =
+ pmadapter->pcard_pcie->evtbd_wrptr & (MLAN_MAX_EVT_BD - 1);
+ t_u32 rdptr;
+#if defined(PCIE8997) || defined(PCIE8897)
+ mlan_pcie_evt_buf *pevtbd_buf;
+#endif
+#if defined(PCIE9098) || defined(PCIE9097)
+ adma_dual_desc_buf *padma_bd_buf;
+#endif
+
+ ENTER();
+ if (!pmbuf) {
+ LEAVE();
+ return MLAN_STATUS_FAILURE;
+ }
+
+ if (wrptr >= MLAN_MAX_EVT_BD) {
+ PRINTM(MERROR, "EvtCom: Invalid wrptr 0x%x\n", wrptr);
+ ret = MLAN_STATUS_FAILURE;
+ goto done;
+ }
+
+ /* Read the event ring read pointer set by firmware */
+ if (pcb->moal_read_reg(pmadapter->pmoal_handle,
+ pmadapter->pcard_pcie->reg->reg_evtbd_rdptr,
+ &rdptr)) {
+ PRINTM(MERROR, "EvtCom: failed to read REG_EVTBD_RDPTR\n");
+ ret = MLAN_STATUS_FAILURE;
+ goto done;
+ }
+#if defined(PCIE9098) || defined(PCIE9097)
+ if (pmadapter->pcard_pcie->reg->use_adma)
+ rdptr = rdptr >> ADMA_RPTR_START;
+#endif
+
+ if (!pmadapter->pcard_pcie->evt_buf_list[wrptr]) {
+ pmbuf->data_len = MAX_EVENT_SIZE;
+ pmbuf->data_offset -= PCIE_INTF_HEADER_LEN;
+
+ if (MLAN_STATUS_FAILURE ==
+ pcb->moal_map_memory(pmadapter->pmoal_handle,
+ pmbuf->pbuf + pmbuf->data_offset,
+ &pmbuf->buf_pa, MAX_EVENT_SIZE,
+ PCI_DMA_FROMDEVICE)) {
+ PRINTM(MERROR, "EvtCom: failed to moal_map_memory\n");
+ LEAVE();
+ return MLAN_STATUS_FAILURE;
+ }
+
+ pmadapter->pcard_pcie->evt_buf_list[wrptr] = pmbuf;
+#if defined(PCIE8997) || defined(PCIE8897)
+ if (!pmadapter->pcard_pcie->reg->use_adma) {
+ pevtbd_buf = (mlan_pcie_evt_buf *)pmadapter->pcard_pcie
+ ->evtbd_ring[wrptr];
+ pevtbd_buf->paddr = pmbuf->buf_pa;
+ pevtbd_buf->len = (t_u16)pmbuf->data_len;
+ pevtbd_buf->flags = 0;
+ }
+#endif
+
+#if defined(PCIE9098) || defined(PCIE9097)
+ if (pmadapter->pcard_pcie->reg->use_adma) {
+ padma_bd_buf = (adma_dual_desc_buf *)pmadapter
+ ->pcard_pcie->evtbd_ring[wrptr];
+ padma_bd_buf->paddr = pmbuf->buf_pa;
+ padma_bd_buf->len =
+ ALIGN_SZ(pmbuf->data_len, ADMA_ALIGN_SIZE);
+ padma_bd_buf->flags = 0;
+ padma_bd_buf->flags =
+ ADMA_BD_FLAG_INT_EN | ADMA_BD_FLAG_DST_HOST;
+ padma_bd_buf->pkt_size = 0;
+ padma_bd_buf->reserved = 0;
+ }
+#endif
+ pmbuf = MNULL;
+ } else {
+ PRINTM(MINFO,
+ "EvtCom: ERROR: Buffer is still valid at "
+ "index %d, <%p, %p>\n",
+ wrptr, pmadapter->pcard_pcie->evt_buf_list[wrptr],
+ pmbuf);
+ }
+
+ pmadapter->pcard_pcie->evtbd_wrptr++;
+
+#if defined(PCIE8997) || defined(PCIE8897)
+ if (!pmadapter->pcard_pcie->reg->use_adma) {
+ if ((pmadapter->pcard_pcie->evtbd_wrptr & EVT_RW_PTR_MASK) ==
+ MLAN_MAX_EVT_BD) {
+ pmadapter->pcard_pcie->evtbd_wrptr =
+ ((pmadapter->pcard_pcie->evtbd_wrptr &
+ EVT_RW_PTR_ROLLOVER_IND) ^
+ EVT_RW_PTR_ROLLOVER_IND);
+ }
+ }
+#endif
+#if defined(PCIE9098) || defined(PCIE9097)
+ if (pmadapter->pcard_pcie->reg->use_adma)
+ pmadapter->pcard_pcie->evtbd_wrptr &= ADMA_RW_PTR_WRAP_MASK;
+#endif
+ PRINTM(MINFO, "EvtCom: Updated <Wr: 0x%x, Rd: 0x%x>\n",
+ pmadapter->pcard_pcie->evtbd_wrptr, rdptr);
+
+ /* Write the event ring write pointer in to REG_EVTBD_WRPTR */
+ if (pcb->moal_write_reg(pmadapter->pmoal_handle,
+ pmadapter->pcard_pcie->reg->reg_evtbd_wrptr,
+ pmadapter->pcard_pcie->evtbd_wrptr)) {
+ PRINTM(MERROR, "EvtCom: failed to write REG_EVTBD_WRPTR\n");
+ ret = MLAN_STATUS_FAILURE;
+ goto done;
+ }
+
+done:
+ /* Free the buffer for failure case */
+ if (ret && pmbuf)
+ wlan_free_mlan_buffer(pmadapter, pmbuf);
+
+ PRINTM(MINFO, "EvtCom: Check Events Again\n");
+ ret = wlan_pcie_process_event_ready(pmadapter);
+
+ LEAVE();
+ return ret;
+}
+
+/**
+ * @brief This function downloads boot command to the card.
+ *
+ * @param pmadapter A pointer to mlan_adapter structure
+ * @param pmbuf A pointer to mlan_buffer
+ *
+ * @return MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ */
+static mlan_status wlan_pcie_send_boot_cmd(mlan_adapter *pmadapter,
+ mlan_buffer *pmbuf)
+{
+ mlan_status ret = MLAN_STATUS_SUCCESS;
+ pmlan_callbacks pcb = &pmadapter->callbacks;
+
+ ENTER();
+
+ if (!pmadapter || !pmbuf) {
+ PRINTM(MERROR, "NULL Pointer\n");
+ LEAVE();
+ return MLAN_STATUS_FAILURE;
+ }
+
+ if (MLAN_STATUS_FAILURE ==
+ pcb->moal_map_memory(
+ pmadapter->pmoal_handle, pmbuf->pbuf + pmbuf->data_offset,
+ &pmbuf->buf_pa, WLAN_UPLD_SIZE, PCI_DMA_TODEVICE)) {
+ PRINTM(MERROR, "BootCmd: failed to moal_map_memory\n");
+ LEAVE();
+ return MLAN_STATUS_FAILURE;
+ }
+
+ if (!(pmbuf->pbuf && pmbuf->data_len && pmbuf->buf_pa)) {
+ PRINTM(MERROR, "%s: Invalid buffer <%p, %#x:%x, len=%d>\n",
+ __func__, pmbuf->pbuf,
+ (t_u32)((t_u64)pmbuf->buf_pa >> 32),
+ (t_u32)pmbuf->buf_pa, pmbuf->data_len);
+ ret = MLAN_STATUS_FAILURE;
+ goto done;
+ }
+
+ /* Write the lower 32bits of the physical address to scratch
+ * register 0 */
+ if (pcb->moal_write_reg(pmadapter->pmoal_handle,
+ pmadapter->pcard_pcie->reg->reg_scratch_0,
+ (t_u32)pmbuf->buf_pa)) {
+ PRINTM(MERROR,
+ "Failed to write download command to boot code\n");
+ ret = MLAN_STATUS_FAILURE;
+ goto done;
+ }
+
+ /* Write the upper 32bits of the physical address to scratch
+ * register 1 */
+ if (pcb->moal_write_reg(pmadapter->pmoal_handle,
+ pmadapter->pcard_pcie->reg->reg_scratch_1,
+ (t_u32)((t_u64)pmbuf->buf_pa >> 32))) {
+ PRINTM(MERROR,
+ "Failed to write download command to boot code\n");
+ ret = MLAN_STATUS_FAILURE;
+ goto done;
+ }
+
+ /* Write the command length to scratch register 2 */
+ if (pcb->moal_write_reg(pmadapter->pmoal_handle,
+ pmadapter->pcard_pcie->reg->reg_scratch_2,
+ pmbuf->data_len)) {
+ PRINTM(MERROR,
+ "Failed to write command length to scratch register 2\n");
+ ret = MLAN_STATUS_FAILURE;
+ goto done;
+ }
+
+ /* Ring the door bell */
+ if (pcb->moal_write_reg(pmadapter->pmoal_handle,
+ pmadapter->pcard_pcie->reg->reg_cpu_int_event,
+ CPU_INTR_DOOR_BELL)) {
+ PRINTM(MERROR, "Failed to assert door-bell interrupt\n");
+ ret = MLAN_STATUS_FAILURE;
+ goto done;
+ }
+
+ LEAVE();
+ return ret;
+
+done:
+ if (MLAN_STATUS_FAILURE ==
+ pcb->moal_unmap_memory(
+ pmadapter->pmoal_handle, pmbuf->pbuf + pmbuf->data_offset,
+ pmbuf->buf_pa, WLAN_UPLD_SIZE, PCI_DMA_TODEVICE))
+ PRINTM(MERROR, "BootCmd: failed to moal_unmap_memory\n");
+ LEAVE();
+ return ret;
+}
+
+/**
+ * @brief This function init rx port in firmware
+ *
+ * @param pmadapter A pointer to mlan_adapter
+ *
+ * @return MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ */
+mlan_status wlan_pcie_init_fw(pmlan_adapter pmadapter)
+{
+ pmlan_callbacks pcb = &pmadapter->callbacks;
+ t_u32 txbd_val = 0;
+ mlan_status ret = MLAN_STATUS_SUCCESS;
+#if defined(PCIE8997) || defined(PCIE8897)
+ if (!pmadapter->pcard_pcie->reg->use_adma) {
+ txbd_val = pmadapter->pcard_pcie->txbd_wrptr &
+ pmadapter->pcard_pcie->reg->txrx_rw_ptr_wrap_mask;
+ txbd_val = txbd_val << TXBD_RW_PTR_START;
+ }
+#endif
+ /* Write the RX ring write pointer in to REG_RXBD_WRPTR */
+ if (pcb->moal_write_reg(pmadapter->pmoal_handle,
+ pmadapter->pcard_pcie->reg->reg_rxbd_wrptr,
+ pmadapter->pcard_pcie->rxbd_wrptr | txbd_val)) {
+ PRINTM(MERROR, "Init FW: failed to write REG_RXBD_WRPTR\n");
+ ret = MLAN_STATUS_FAILURE;
+ goto done;
+ }
+ /* Write the event ring write pointer in to REG_EVTBD_WRPTR */
+ if (pcb->moal_write_reg(pmadapter->pmoal_handle,
+ pmadapter->pcard_pcie->reg->reg_evtbd_wrptr,
+ pmadapter->pcard_pcie->evtbd_wrptr)) {
+ PRINTM(MERROR, "Init FW: failed to write REG_EVTBD_WRPTR\n");
+ ret = MLAN_STATUS_FAILURE;
+ }
+done:
+ return ret;
+}
+
+/**
+ * @brief This function downloads FW blocks to device
+ *
+ * @param pmadapter A pointer to mlan_adapter
+ * @param fw A pointer to firmware image
+ *
+ * @return MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ */
+static mlan_status wlan_pcie_prog_fw_w_helper(mlan_adapter *pmadapter,
+ mlan_fw_image *fw)
+{
+ mlan_status ret = MLAN_STATUS_FAILURE;
+ t_u8 *firmware = fw->pfw_buf;
+ t_u32 firmware_len = fw->fw_len;
+ t_u32 offset = 0;
+ mlan_buffer *pmbuf = MNULL;
+ t_u32 txlen, tx_blocks = 0, tries, len;
+ t_u32 block_retry_cnt = 0;
+ pmlan_callbacks pcb = &pmadapter->callbacks;
+#if defined(PCIE9098)
+ t_u32 rev_id_reg = 0;
+ t_u32 revision_id = 0;
+#endif
+ t_u8 check_fw_status = MFALSE;
+ t_u32 fw_dnld_status = 0;
+ t_u32 fw_dnld_offset = 0;
+ t_u8 mic_retry = 0;
+
+ ENTER();
+ if (!pmadapter) {
+ PRINTM(MERROR, "adapter structure is not valid\n");
+ goto done;
+ }
+
+ if (!firmware || !firmware_len) {
+ PRINTM(MERROR,
+ "No firmware image found! Terminating download\n");
+ goto done;
+ }
+
+ PRINTM(MINFO, "Downloading FW image (%d bytes)\n", firmware_len);
+
+ if (wlan_disable_pcie_host_int(pmadapter)) {
+ PRINTM(MERROR, "prog_fw: Disabling interrupts failed\n");
+ goto done;
+ }
+
+ pmbuf = wlan_alloc_mlan_buffer(pmadapter, WLAN_UPLD_SIZE, 0,
+ MOAL_ALLOC_MLAN_BUFFER);
+ if (!pmbuf) {
+ PRINTM(MERROR, "prog_fw: Unable to allocate mlan_buffer\n");
+ goto done;
+ }
+#if defined(PCIE9098)
+ if (IS_PCIE9098(pmadapter->card_type)) {
+ rev_id_reg = pmadapter->pcard_pcie->reg->reg_rev_id;
+ ret = pcb->moal_read_reg(pmadapter->pmoal_handle, rev_id_reg,
+ &revision_id);
+ if (ret != MLAN_STATUS_SUCCESS) {
+ PRINTM(MERROR,
+ "Failed to read PCIe revision id register\n");
+ goto done;
+ }
+ /* Skyhawk A0, need to check both CRC and MIC error */
+ if (revision_id >= CHIP_9098_REV_A0)
+ check_fw_status = MTRUE;
+ }
+#endif
+ /* For PCIE9097, need check both CRC and MIC error */
+#if defined(PCIE9097)
+ if (IS_PCIE9097(pmadapter->card_type))
+ check_fw_status = MTRUE;
+#endif
+
+ /* Perform firmware data transfer */
+ do {
+ t_u32 ireg_intr = 0;
+ t_u32 read_retry_cnt = 0;
+
+ /* More data? */
+ if (offset >= firmware_len)
+ break;
+
+ for (tries = 0; tries < MAX_POLL_TRIES; tries++) {
+ ret = pcb->moal_read_reg(
+ pmadapter->pmoal_handle,
+ pmadapter->pcard_pcie->reg->reg_scratch_2,
+ &len);
+ if (ret) {
+ PRINTM(MWARN,
+ "Failed reading length from boot code\n");
+ goto done;
+ }
+ if (len || offset)
+ break;
+ wlan_udelay(pmadapter, 10);
+ }
+
+ if (!len) {
+ break;
+ } else if (len > WLAN_UPLD_SIZE) {
+ PRINTM(MERROR,
+ "FW download failure @ %d, invalid length %d\n",
+ offset, len);
+ goto done;
+ }
+
+ txlen = len;
+
+ if (len & MBIT(0)) {
+ if (check_fw_status) {
+ /* Get offset from fw dnld offset Register */
+ ret = pcb->moal_read_reg(
+ pmadapter->pmoal_handle,
+ pmadapter->pcard_pcie->reg
+ ->reg_scratch_6,
+ &fw_dnld_offset);
+ if (ret != MLAN_STATUS_SUCCESS) {
+ PRINTM(MERROR,
+ "FW download failure @ %d, reading fw dnld offset failed\n",
+ offset);
+ goto done;
+ }
+ /* Get CRC MIC error from fw dnld status
+ * Register */
+ ret = pcb->moal_read_reg(
+ pmadapter->pmoal_handle,
+ pmadapter->pcard_pcie->reg
+ ->reg_scratch_7,
+ &fw_dnld_status);
+ if (ret != MLAN_STATUS_SUCCESS) {
+ PRINTM(MERROR,
+ "FW download failure @ %d, reading fw dnld status failed\n",
+ offset);
+ goto done;
+ }
+ PRINTM(MERROR,
+ "FW download error: status=0x%x offset = 0x%x fw offset = 0x%x\n",
+ fw_dnld_status, offset, fw_dnld_offset);
+ }
+ block_retry_cnt++;
+ if (block_retry_cnt > MAX_WRITE_IOMEM_RETRY) {
+ PRINTM(MERROR,
+ "FW download failure @ %d, over max "
+ "retry count\n",
+ offset);
+ goto done;
+ }
+ PRINTM(MERROR,
+ "FW CRC error indicated by the "
+ "helper: len = 0x%04X, txlen = %d\n",
+ len, txlen);
+ len &= ~MBIT(0);
+ /* Setting this to 0 to resend from same offset */
+ txlen = 0;
+ if (fw_dnld_status & (MBIT(6) | MBIT(7))) {
+ offset = 0;
+ mic_retry++;
+ if (mic_retry > MAX_FW_RETRY) {
+ PRINTM(MERROR,
+ "FW download failure @ %d, over max "
+ "mic retry count\n",
+ offset);
+ goto done;
+ }
+ }
+ } else {
+ block_retry_cnt = 0;
+ /* Set blocksize to transfer - checking for last block
+ */
+ if (firmware_len - offset < txlen)
+ txlen = firmware_len - offset;
+
+ PRINTM(MINFO, ".");
+
+ tx_blocks = (txlen + MLAN_PCIE_BLOCK_SIZE_FW_DNLD - 1) /
+ MLAN_PCIE_BLOCK_SIZE_FW_DNLD;
+
+ /* Copy payload to buffer */
+ memmove(pmadapter, pmbuf->pbuf + pmbuf->data_offset,
+ &firmware[offset], txlen);
+ pmbuf->data_len = txlen;
+ }
+
+ /* Send the boot command to device */
+ if (wlan_pcie_send_boot_cmd(pmadapter, pmbuf)) {
+ PRINTM(MERROR,
+ "Failed to send firmware download command\n");
+ goto done;
+ }
+ /* Wait for the command done interrupt */
+ do {
+ if (read_retry_cnt > MAX_READ_REG_RETRY) {
+ PRINTM(MERROR,
+ "prog_fw: Failed to get command done interrupt "
+ "retry count = %d\n",
+ read_retry_cnt);
+ goto done;
+ }
+ if (pcb->moal_read_reg(pmadapter->pmoal_handle,
+ pmadapter->pcard_pcie->reg
+ ->reg_cpu_int_status,
+ &ireg_intr)) {
+ PRINTM(MERROR,
+ "prog_fw: Failed to read "
+ "interrupt status during fw dnld\n");
+ /* buffer was mapped in send_boot_cmd, unmap
+ * first */
+ pcb->moal_unmap_memory(
+ pmadapter->pmoal_handle,
+ pmbuf->pbuf + pmbuf->data_offset,
+ pmbuf->buf_pa, WLAN_UPLD_SIZE,
+ PCI_DMA_TODEVICE);
+ goto done;
+ }
+ read_retry_cnt++;
+ pcb->moal_usleep_range(pmadapter->pmoal_handle, 10, 20);
+ } while ((ireg_intr & CPU_INTR_DOOR_BELL) ==
+ CPU_INTR_DOOR_BELL);
+ /* got interrupt - can unmap buffer now */
+ if (MLAN_STATUS_FAILURE ==
+ pcb->moal_unmap_memory(pmadapter->pmoal_handle,
+ pmbuf->pbuf + pmbuf->data_offset,
+ pmbuf->buf_pa, WLAN_UPLD_SIZE,
+ PCI_DMA_TODEVICE)) {
+ PRINTM(MERROR,
+ "prog_fw: failed to moal_unmap_memory\n");
+ goto done;
+ }
+ offset += txlen;
+ } while (MTRUE);
+
+ PRINTM(MMSG, "FW download over, size %d bytes\n", offset);
+
+ ret = MLAN_STATUS_SUCCESS;
+done:
+ if (pmbuf)
+ wlan_free_mlan_buffer(pmadapter, pmbuf);
+
+ LEAVE();
+ return ret;
+}
+
+/********************************************************
+ Global Functions
+********************************************************/
+/**
+ * @brief This function get pcie device from card type
+ *
+ * @param pmadapter A pointer to mlan_adapter structure
+ * @return MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ */
+mlan_status wlan_get_pcie_device(pmlan_adapter pmadapter)
+{
+ mlan_status ret = MLAN_STATUS_SUCCESS;
+ t_u16 card_type = pmadapter->card_type;
+
+ ENTER();
+
+ ret = pmadapter->callbacks.moal_malloc(pmadapter->pmoal_handle,
+ sizeof(mlan_pcie_card),
+ MLAN_MEM_DEF,
+ (t_u8 **)&pmadapter->pcard_pcie);
+ if (ret != MLAN_STATUS_SUCCESS || !pmadapter->pcard_pcie) {
+ PRINTM(MERROR, "Failed to allocate pcard_pcie\n");
+ LEAVE();
+ return MLAN_STATUS_FAILURE;
+ }
+
+ switch (card_type) {
+#ifdef PCIE8897
+ case CARD_TYPE_PCIE8897:
+ pmadapter->pcard_pcie->reg = &mlan_reg_pcie8897;
+ pmadapter->pcard_info = &mlan_card_info_pcie8897;
+ break;
+#endif
+#ifdef PCIE8997
+ case CARD_TYPE_PCIE8997:
+ pmadapter->pcard_pcie->reg = &mlan_reg_pcie8997;
+ pmadapter->pcard_info = &mlan_card_info_pcie8997;
+ break;
+#endif
+#if defined(PCIE9098) || defined(PCIE9097)
+ case CARD_TYPE_PCIE9097:
+ case CARD_TYPE_PCIE9098:
+ pmadapter->pcard_pcie->reg = &mlan_reg_pcie9098;
+ pmadapter->pcard_info = &mlan_card_info_pcie9098;
+#ifdef PCIE9097
+ if (card_type == CARD_TYPE_PCIE9097 &&
+ pmadapter->card_rev == CHIP_9097_REV_B0)
+ pmadapter->pcard_pcie->reg = &mlan_reg_pcie9097_b0;
+#endif
+ break;
+#endif
+ default:
+ PRINTM(MERROR, "can't get right pcie card type \n");
+ ret = MLAN_STATUS_FAILURE;
+ break;
+ }
+
+ LEAVE();
+ return ret;
+}
+
+/**
+ * @brief PCIE wakeup handler
+ *
+ * @param pmadapter A pointer to mlan_adapter structure
+ *
+ * @return MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ */
+mlan_status wlan_pcie_wakeup(mlan_adapter *pmadapter)
+{
+ mlan_status ret = MLAN_STATUS_SUCCESS;
+ t_u32 data = 0;
+ ENTER();
+ /* Enable interrupts or any chip access will wakeup device */
+ ret = pmadapter->callbacks.moal_read_reg(
+ pmadapter->pmoal_handle, pmadapter->pcard_pcie->reg->reg_ip_rev,
+ &data);
+
+ if (ret == MLAN_STATUS_SUCCESS) {
+ PRINTM(MINFO,
+ "PCIE wakeup: Read PCI register to wakeup device ...\n");
+ } else {
+ PRINTM(MINFO, "PCIE wakeup: Failed to wakeup device ...\n");
+ ret = MLAN_STATUS_FAILURE;
+ }
+ LEAVE();
+ return ret;
+}
+
+/**
+ * @brief This function gets interrupt status.
+ *
+ */
+/**
+ * @param msg_id A message id
+ * @param pmadapter A pointer to mlan_adapter structure
+ * @return MLAN_STATUS_FAILURE -- if the intererupt is not for us
+ */
+mlan_status wlan_pcie_interrupt(t_u16 msg_id, pmlan_adapter pmadapter)
+{
+ t_u32 pcie_ireg;
+ pmlan_callbacks pcb = &pmadapter->callbacks;
+ t_void *pmoal_handle = pmadapter->pmoal_handle;
+ t_void *pint_lock = pmadapter->pint_lock;
+ mlan_status ret = MLAN_STATUS_SUCCESS;
+
+ ENTER();
+
+ if (pmadapter->pcard_pcie->pcie_int_mode == PCIE_INT_MODE_MSI) {
+ pcb->moal_spin_lock(pmoal_handle, pint_lock);
+ pmadapter->ireg = 1;
+ pcb->moal_spin_unlock(pmoal_handle, pint_lock);
+ } else if (pmadapter->pcard_pcie->pcie_int_mode == PCIE_INT_MODE_MSIX) {
+ pcie_ireg = (1 << msg_id) &
+ pmadapter->pcard_pcie->reg->host_intr_mask;
+ if (pcie_ireg) {
+ if (!pmadapter->pps_uapsd_mode &&
+ (pmadapter->ps_state == PS_STATE_SLEEP)) {
+ pmadapter->pm_wakeup_fw_try = MFALSE;
+ pmadapter->ps_state = PS_STATE_AWAKE;
+ pmadapter->pm_wakeup_card_req = MFALSE;
+ }
+ }
+ pcb->moal_spin_lock(pmoal_handle, pint_lock);
+ pmadapter->ireg |= pcie_ireg;
+ pcb->moal_spin_unlock(pmoal_handle, pint_lock);
+
+ PRINTM(MINTR, "ireg: 0x%08x\n", pcie_ireg);
+ } else {
+ wlan_pcie_disable_host_int_mask(pmadapter);
+ if (pcb->moal_read_reg(
+ pmoal_handle,
+ pmadapter->pcard_pcie->reg->reg_host_int_status,
+ &pcie_ireg)) {
+ PRINTM(MWARN, "Read register failed\n");
+ LEAVE();
+ return MLAN_STATUS_FAILURE;
+ }
+
+ if ((pcie_ireg != 0xFFFFFFFF) && (pcie_ireg)) {
+ PRINTM(MINTR, "pcie_ireg=0x%x\n", pcie_ireg);
+ if (!pmadapter->pps_uapsd_mode &&
+ (pmadapter->ps_state == PS_STATE_SLEEP)) {
+ /* Potentially for PCIe we could get other
+ * interrupts like shared. */
+ pmadapter->pm_wakeup_fw_try = MFALSE;
+ pmadapter->ps_state = PS_STATE_AWAKE;
+ pmadapter->pm_wakeup_card_req = MFALSE;
+ }
+ pcb->moal_spin_lock(pmoal_handle, pint_lock);
+ pmadapter->ireg |= pcie_ireg;
+ pcb->moal_spin_unlock(pmoal_handle, pint_lock);
+
+ /* Clear the pending interrupts */
+ if (pcb->moal_write_reg(pmoal_handle,
+ pmadapter->pcard_pcie->reg
+ ->reg_host_int_status,
+ ~pcie_ireg)) {
+ PRINTM(MWARN, "Write register failed\n");
+ LEAVE();
+ return ret;
+ }
+ } else {
+ wlan_pcie_enable_host_int_mask(pmadapter);
+ PRINTM(MINFO, "This is not our interrupt\n");
+ ret = MLAN_STATUS_FAILURE;
+ }
+ }
+
+ LEAVE();
+ return ret;
+}
+
+/**
+ * @brief This function checks the msix interrupt status and
+ * handle it accordingly.
+ *
+ * @param pmadapter A pointer to mlan_adapter structure
+ *
+ * @return MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ */
+mlan_status wlan_process_msix_int(mlan_adapter *pmadapter)
+{
+ mlan_status ret = MLAN_STATUS_SUCCESS;
+ t_u32 pcie_ireg = 0;
+ pmlan_callbacks pcb = &pmadapter->callbacks;
+
+ ENTER();
+
+ pcb->moal_spin_lock(pmadapter->pmoal_handle, pmadapter->pint_lock);
+ pcie_ireg =
+ pmadapter->ireg & pmadapter->pcard_pcie->reg->host_intr_mask;
+ pmadapter->ireg = 0;
+ pcb->moal_spin_unlock(pmadapter->pmoal_handle, pmadapter->pint_lock);
+
+ if (pcie_ireg & pmadapter->pcard_pcie->reg->host_intr_dnld_done) {
+ PRINTM(MINFO, "<--- DATA sent Interrupt --->\n");
+ ret = wlan_pcie_send_data_complete(pmadapter);
+ if (ret)
+ goto done;
+ }
+ if (pcie_ireg & pmadapter->pcard_pcie->reg->host_intr_upld_rdy) {
+ PRINTM(MINFO, "Rx DATA\n");
+ ret = wlan_pcie_process_recv_data(pmadapter);
+ if (ret)
+ goto done;
+ }
+ if (pcie_ireg & pmadapter->pcard_pcie->reg->host_intr_event_rdy) {
+ PRINTM(MINFO, "Rx EVENT\n");
+ ret = wlan_pcie_process_event_ready(pmadapter);
+ if (ret)
+ goto done;
+ }
+ if (pcie_ireg & pmadapter->pcard_pcie->reg->host_intr_cmd_done) {
+ if (pmadapter->cmd_sent) {
+ PRINTM(MINFO, "<--- CMD sent Interrupt --->\n");
+ pmadapter->cmd_sent = MFALSE;
+ }
+ ret = wlan_pcie_process_cmd_resp(pmadapter);
+ if (ret)
+ goto done;
+ }
+#if defined(PCIE9098) || defined(PCIE9097)
+ if (pmadapter->pcard_pcie->reg->host_intr_cmd_dnld &&
+ (pcie_ireg & pmadapter->pcard_pcie->reg->host_intr_cmd_dnld)) {
+ if (pmadapter->cmd_sent)
+ pmadapter->cmd_sent = MFALSE;
+ if (pmadapter->pcard_pcie->vdll_cmd_buf)
+ wlan_pcie_send_vdll_complete(pmadapter);
+ PRINTM(MINFO, "<--- CMD DNLD DONE Interrupt --->\n");
+ }
+#endif
+ PRINTM(MINFO, "cmd_sent=%d data_sent=%d\n", pmadapter->cmd_sent,
+ pmadapter->data_sent);
+
+done:
+ LEAVE();
+ return ret;
+}
+
+/**
+ * @brief This function checks the interrupt status and
+ * handle it accordingly.
+ *
+ * @param pmadapter A pointer to mlan_adapter structure
+ *
+ * @return MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ */
+mlan_status wlan_process_pcie_int_status(mlan_adapter *pmadapter)
+{
+ mlan_status ret = MLAN_STATUS_SUCCESS;
+ t_u32 pcie_ireg = 0;
+ pmlan_callbacks pcb = &pmadapter->callbacks;
+
+ ENTER();
+
+ if (pmadapter->pcard_pcie->pcie_int_mode == PCIE_INT_MODE_MSIX) {
+ wlan_process_msix_int(pmadapter);
+ goto done;
+ }
+ pcb->moal_spin_lock(pmadapter->pmoal_handle, pmadapter->pint_lock);
+ if (pmadapter->pcard_pcie->pcie_int_mode != PCIE_INT_MODE_MSI)
+ pcie_ireg = pmadapter->ireg;
+ pmadapter->ireg = 0;
+ pcb->moal_spin_unlock(pmadapter->pmoal_handle, pmadapter->pint_lock);
+ if (pmadapter->pcard_pcie->pcie_int_mode == PCIE_INT_MODE_MSI) {
+ if (pcb->moal_read_reg(
+ pmadapter->pmoal_handle,
+ pmadapter->pcard_pcie->reg->reg_host_int_status,
+ &pcie_ireg)) {
+ PRINTM(MWARN, "Read register failed\n");
+ ret = MLAN_STATUS_FAILURE;
+ goto done;
+ }
+
+ if ((pcie_ireg != 0xFFFFFFFF) && (pcie_ireg)) {
+ PRINTM(MINTR, "pcie_ireg=0x%x\n", pcie_ireg);
+ if (pmadapter->pcard_pcie->reg->msi_int_wr_clr) {
+ if (pcb->moal_write_reg(
+ pmadapter->pmoal_handle,
+ pmadapter->pcard_pcie->reg
+ ->reg_host_int_status,
+ ~pcie_ireg)) {
+ PRINTM(MWARN,
+ "Write register failed\n");
+ ret = MLAN_STATUS_FAILURE;
+ goto done;
+ }
+ }
+ if (!pmadapter->pps_uapsd_mode &&
+ (pmadapter->ps_state == PS_STATE_SLEEP)) {
+ /* Potentially for PCIe we could get other
+ * interrupts like shared. */
+ pmadapter->pm_wakeup_fw_try = MFALSE;
+ pmadapter->ps_state = PS_STATE_AWAKE;
+ pmadapter->pm_wakeup_card_req = MFALSE;
+ }
+ }
+ }
+ while (pcie_ireg & pmadapter->pcard_pcie->reg->host_intr_mask) {
+ if (pcie_ireg &
+ pmadapter->pcard_pcie->reg->host_intr_dnld_done) {
+ pcie_ireg &=
+ ~pmadapter->pcard_pcie->reg->host_intr_dnld_done;
+ PRINTM(MINFO, "<--- DATA sent Interrupt --->\n");
+ ret = wlan_pcie_send_data_complete(pmadapter);
+ if (ret)
+ goto done;
+ }
+ if (pcie_ireg &
+ pmadapter->pcard_pcie->reg->host_intr_upld_rdy) {
+ pcie_ireg &=
+ ~pmadapter->pcard_pcie->reg->host_intr_upld_rdy;
+ PRINTM(MINFO, "Rx DATA\n");
+ pmadapter->callbacks.moal_tp_accounting_rx_param(
+ pmadapter->pmoal_handle, 0, 0);
+ ret = wlan_pcie_process_recv_data(pmadapter);
+ if (ret)
+ goto done;
+ }
+ if (pcie_ireg &
+ pmadapter->pcard_pcie->reg->host_intr_event_rdy) {
+ pcie_ireg &=
+ ~pmadapter->pcard_pcie->reg->host_intr_event_rdy;
+ PRINTM(MINFO, "Rx EVENT\n");
+ ret = wlan_pcie_process_event_ready(pmadapter);
+ if (ret)
+ goto done;
+ }
+ if (pcie_ireg &
+ pmadapter->pcard_pcie->reg->host_intr_cmd_done) {
+ pcie_ireg &=
+ ~pmadapter->pcard_pcie->reg->host_intr_cmd_done;
+ if (pmadapter->cmd_sent) {
+ PRINTM(MINFO, "<--- CMD sent Interrupt --->\n");
+ pmadapter->cmd_sent = MFALSE;
+ }
+ ret = wlan_pcie_process_cmd_resp(pmadapter);
+ if (ret)
+ goto done;
+ }
+#if defined(PCIE9098) || defined(PCIE9097)
+ if (pmadapter->pcard_pcie->reg->host_intr_cmd_dnld &&
+ (pcie_ireg &
+ pmadapter->pcard_pcie->reg->host_intr_cmd_dnld)) {
+ pcie_ireg &=
+ ~pmadapter->pcard_pcie->reg->host_intr_cmd_dnld;
+ if (pmadapter->cmd_sent)
+ pmadapter->cmd_sent = MFALSE;
+ if (pmadapter->pcard_pcie->vdll_cmd_buf)
+ wlan_pcie_send_vdll_complete(pmadapter);
+ PRINTM(MINFO, "<--- CMD DNLD DONE Interrupt --->\n");
+ }
+#endif
+ if (pmadapter->pcard_pcie->pcie_int_mode == PCIE_INT_MODE_MSI) {
+ pcb->moal_spin_lock(pmadapter->pmoal_handle,
+ pmadapter->pint_lock);
+ pmadapter->ireg = 0;
+ pcb->moal_spin_unlock(pmadapter->pmoal_handle,
+ pmadapter->pint_lock);
+ }
+ if (pcb->moal_read_reg(
+ pmadapter->pmoal_handle,
+ pmadapter->pcard_pcie->reg->reg_host_int_status,
+ &pcie_ireg)) {
+ PRINTM(MWARN, "Read register failed\n");
+ ret = MLAN_STATUS_FAILURE;
+ goto done;
+ }
+
+ if ((pcie_ireg != 0xFFFFFFFF) && (pcie_ireg)) {
+ PRINTM(MINTR, "Poll: pcie_ireg=0x%x\n", pcie_ireg);
+ if ((pmadapter->pcard_pcie->pcie_int_mode ==
+ PCIE_INT_MODE_LEGACY) ||
+ pmadapter->pcard_pcie->reg->msi_int_wr_clr) {
+ if (pcb->moal_write_reg(
+ pmadapter->pmoal_handle,
+ pmadapter->pcard_pcie->reg
+ ->reg_host_int_status,
+ ~pcie_ireg)) {
+ PRINTM(MWARN,
+ "Write register failed\n");
+ return MLAN_STATUS_FAILURE;
+ }
+ }
+ if (pmadapter->pcard_pcie->pcie_int_mode !=
+ PCIE_INT_MODE_MSI) {
+ pcb->moal_spin_lock(pmadapter->pmoal_handle,
+ pmadapter->pint_lock);
+ pcie_ireg |= pmadapter->ireg;
+ pmadapter->ireg = 0;
+ pcb->moal_spin_unlock(pmadapter->pmoal_handle,
+ pmadapter->pint_lock);
+ }
+ /* Don't update the pmadapter->pcie_ireg,
+ * serving the status right now */
+ }
+ }
+ PRINTM(MINFO, "cmd_sent=%d data_sent=%d\n", pmadapter->cmd_sent,
+ pmadapter->data_sent);
+ if (pmadapter->pcard_pcie->pcie_int_mode != PCIE_INT_MODE_MSI) {
+ if (pmadapter->ps_state != PS_STATE_SLEEP ||
+ pmadapter->pcard_info->supp_ps_handshake)
+ wlan_pcie_enable_host_int_mask(pmadapter);
+ }
+done:
+ LEAVE();
+ return ret;
+}
+
+/**
+ * @brief This function sets DRV_READY register
+ *
+ * @param pmadapter A pointer to mlan_adapter structure
+ * @param val Value
+ *
+ * @return MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ *
+ */
+mlan_status wlan_set_drv_ready_reg(mlan_adapter *pmadapter, t_u32 val)
+{
+ pmlan_callbacks pcb = &pmadapter->callbacks;
+
+ ENTER();
+
+ if (pcb->moal_write_reg(pmadapter->pmoal_handle,
+ pmadapter->pcard_pcie->reg->reg_drv_ready,
+ val)) {
+ LEAVE();
+ return MLAN_STATUS_FAILURE;
+ }
+
+ LEAVE();
+ return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ * @brief This function checks if the interface is ready to download
+ * or not while other download interface is present
+ *
+ * @param pmadapter A pointer to mlan_adapter structure
+ * @param val Winner status (0: winner)
+ *
+ * @return MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ *
+ */
+mlan_status wlan_pcie_check_winner_status(mlan_adapter *pmadapter, t_u32 *val)
+{
+ t_u32 winner = 0;
+ pmlan_callbacks pcb = &pmadapter->callbacks;
+
+ ENTER();
+
+ if (MLAN_STATUS_SUCCESS !=
+ pcb->moal_read_reg(pmadapter->pmoal_handle,
+ pmadapter->pcard_pcie->reg->reg_scratch_3,
+ &winner)) {
+ LEAVE();
+ return MLAN_STATUS_FAILURE;
+ }
+ *val = winner;
+
+ LEAVE();
+ return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ * @brief This function checks if the firmware is ready to accept
+ * command or not.
+ *
+ * @param pmadapter A pointer to mlan_adapter structure
+ * @param pollnum Maximum polling number
+ *
+ * @return MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ */
+mlan_status wlan_pcie_check_fw_status(mlan_adapter *pmadapter, t_u32 pollnum)
+{
+ mlan_status ret = MLAN_STATUS_SUCCESS;
+ pmlan_callbacks pcb = &pmadapter->callbacks;
+ t_u32 firmware_stat;
+ t_u32 tries;
+
+ ENTER();
+
+ /* Wait for firmware initialization event */
+ for (tries = 0; tries < pollnum; tries++) {
+ if (pcb->moal_read_reg(pmadapter->pmoal_handle,
+ pmadapter->pcard_pcie->reg->reg_scratch_3,
+ &firmware_stat))
+ ret = MLAN_STATUS_FAILURE;
+ else
+ ret = MLAN_STATUS_SUCCESS;
+ if (ret)
+ continue;
+ if (firmware_stat == PCIE_FIRMWARE_READY) {
+ ret = MLAN_STATUS_SUCCESS;
+ break;
+ } else {
+ wlan_mdelay(pmadapter, 100);
+ ret = MLAN_STATUS_FAILURE;
+ }
+ }
+
+ LEAVE();
+ return ret;
+}
+
+/**
+ * @brief This function init the pcie interface
+ *
+ * @param pmadapter A pointer to mlan_adapter structure
+ *
+ * @return MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ */
+mlan_status wlan_pcie_init(mlan_adapter *pmadapter)
+{
+ ENTER();
+
+ PRINTM(MINFO, "Setting driver ready signature\n");
+ if (wlan_set_drv_ready_reg(pmadapter, PCIE_FIRMWARE_READY)) {
+ PRINTM(MERROR, "Failed to write driver ready signature\n");
+ LEAVE();
+ return MLAN_STATUS_FAILURE;
+ }
+ LEAVE();
+ return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ * @brief This function downloads firmware to card
+ *
+ * @param pmadapter A pointer to mlan_adapter
+ * @param pmfw A pointer to firmware image
+ *
+ * @return MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ */
+mlan_status wlan_pcie_dnld_fw(pmlan_adapter pmadapter, pmlan_fw_image pmfw)
+{
+ mlan_status ret = MLAN_STATUS_SUCCESS;
+ t_u32 poll_num = 1;
+ t_u32 winner = 0;
+
+ ENTER();
+
+ ret = wlan_pcie_init(pmadapter);
+ if (ret == MLAN_STATUS_FAILURE) {
+ PRINTM(MERROR, "WLAN PCIE init failed\n", ret);
+ LEAVE();
+ return ret;
+ }
+ /* Check if firmware is already running */
+ ret = wlan_pcie_check_fw_status(pmadapter, poll_num);
+ if (ret == MLAN_STATUS_SUCCESS) {
+ PRINTM(MMSG, "WLAN FW already running! Skip FW download\n");
+ goto done;
+ }
+ poll_num = MAX_FIRMWARE_POLL_TRIES;
+
+ /* Check if other interface is downloading */
+ ret = wlan_pcie_check_winner_status(pmadapter, &winner);
+ if (ret == MLAN_STATUS_FAILURE) {
+ PRINTM(MFATAL, "WLAN read winner status failed!\n");
+ goto done;
+ }
+ if (winner) {
+ PRINTM(MMSG,
+ "WLAN is not the winner (0x%x). Skip FW download\n",
+ winner);
+ poll_num = MAX_MULTI_INTERFACE_POLL_TRIES;
+ goto poll_fw;
+ }
+
+ /* Download the firmware image via helper */
+ ret = wlan_pcie_prog_fw_w_helper(pmadapter, pmfw);
+ if (ret != MLAN_STATUS_SUCCESS) {
+ PRINTM(MERROR, "prog_fw failed ret=%#x\n", ret);
+ LEAVE();
+ return ret;
+ }
+poll_fw:
+ /* Check if the firmware is downloaded successfully or not */
+ ret = wlan_pcie_check_fw_status(pmadapter, poll_num);
+ if (ret != MLAN_STATUS_SUCCESS) {
+ PRINTM(MFATAL, "FW failed to be active in time!\n");
+ ret = MLAN_STATUS_FAILURE;
+ LEAVE();
+ return ret;
+ }
+done:
+
+ /* re-enable host interrupt for mlan after fw dnld is successful */
+ wlan_enable_pcie_host_int(pmadapter);
+
+ LEAVE();
+ return ret;
+}
+
+/**
+ * @brief 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.
+ *
+ * @param pmpriv A pointer to mlan_private structure
+ * @param type data or command
+ * @param pmbuf A pointer to mlan_buffer (pmbuf->data_len should include
+ * PCIE header)
+ * @param tx_param A pointer to mlan_tx_param (can be MNULL if type is
+ * command)
+ *
+ * @return MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ */
+mlan_status wlan_pcie_host_to_card(pmlan_private pmpriv, t_u8 type,
+ mlan_buffer *pmbuf, mlan_tx_param *tx_param)
+{
+ mlan_status ret = MLAN_STATUS_SUCCESS;
+ pmlan_adapter pmadapter = pmpriv->adapter;
+
+ ENTER();
+
+ if (!pmbuf) {
+ PRINTM(MERROR, "Passed NULL pmbuf to %s\n", __FUNCTION__);
+ return MLAN_STATUS_FAILURE;
+ }
+
+ if (type == MLAN_TYPE_DATA)
+ ret = wlan_pcie_send_data(pmadapter, type, pmbuf, tx_param);
+ else if (type == MLAN_TYPE_CMD)
+ ret = wlan_pcie_send_cmd(pmadapter, pmbuf);
+#if defined(PCIE9098) || defined(PCIE9097)
+ else if (type == MLAN_TYPE_VDLL)
+ ret = wlan_pcie_send_vdll(pmadapter, pmbuf);
+#endif
+ LEAVE();
+ return ret;
+}
+
+/**
+ * @brief This function allocates the PCIE buffer for SSU
+ *
+ * @param pmadapter A pointer to mlan_adapter structure
+ *
+ * @return MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ */
+mlan_status wlan_alloc_ssu_pcie_buf(pmlan_adapter pmadapter)
+{
+ mlan_status ret = MLAN_STATUS_SUCCESS;
+ pmlan_callbacks pcb = &pmadapter->callbacks;
+ mlan_buffer *pmbuf = MNULL;
+ /** Virtual base address of ssu buffer */
+ t_u8 *ssu_vbase;
+ /** Physical base address of ssu buffer */
+ t_u64 ssu_pbase = 0;
+
+ ENTER();
+
+ if (pmadapter->ssu_buf) {
+ PRINTM(MCMND, "ssu buffer already allocated\n");
+ LEAVE();
+ return ret;
+ }
+ /* Allocate buffer here so that firmware can DMA data on it */
+ pmbuf = wlan_alloc_mlan_buffer(pmadapter, 0, 0, MOAL_MALLOC_BUFFER);
+ if (!pmbuf) {
+ PRINTM(MERROR,
+ "SSU buffer create : Unable to allocate mlan_buffer\n");
+ LEAVE();
+ return MLAN_STATUS_FAILURE;
+ }
+ ret = pcb->moal_malloc_consistent(pmadapter->pmoal_handle,
+ MLAN_SSU_BUF_SIZE, &ssu_vbase,
+ &ssu_pbase);
+
+ if (ret != MLAN_STATUS_SUCCESS) {
+ PRINTM(MERROR, "%s: No free moal_malloc_consistent\n",
+ __FUNCTION__);
+ /* free pmbuf */
+ wlan_free_mlan_buffer(pmadapter, pmbuf);
+ LEAVE();
+ return MLAN_STATUS_FAILURE;
+ }
+
+ pmbuf->buf_pa = ssu_pbase;
+ pmbuf->pbuf = ssu_vbase;
+ pmbuf->data_offset = 0;
+ pmbuf->data_len = MLAN_SSU_BUF_SIZE;
+ pmbuf->total_pcie_buf_len = MLAN_SSU_BUF_SIZE;
+
+ PRINTM(MCMND,
+ "SSU buffer: add new mlan_buffer base: %p, "
+ "buf_base: %p, data_offset: %x, buf_pbase: %#x:%x, "
+ "buf_len: %#x\n",
+ pmbuf, pmbuf->pbuf, pmbuf->data_offset,
+ (t_u32)((t_u64)pmbuf->buf_pa >> 32), (t_u32)pmbuf->buf_pa,
+ pmbuf->data_len);
+
+ pmadapter->ssu_buf = pmbuf;
+
+ LEAVE();
+ return ret;
+}
+
+/**
+ * @brief This function frees the allocated ssu buffer.
+ *
+ * @param pmadapter A pointer to mlan_adapter structure
+ *
+ * @return MLAN_STATUS_SUCCESS
+ */
+mlan_status wlan_free_ssu_pcie_buf(pmlan_adapter pmadapter)
+{
+ pmlan_callbacks pcb = &pmadapter->callbacks;
+ mlan_buffer *pmbuf = MNULL;
+ t_u8 *ssu_vbase;
+ t_u64 ssu_pbase;
+
+ ENTER();
+ if (!pmadapter) {
+ LEAVE();
+ return MLAN_STATUS_FAILURE;
+ }
+
+ if (pmadapter->ssu_buf) {
+ pmbuf = pmadapter->ssu_buf;
+ ssu_vbase = pmbuf->pbuf;
+ ssu_pbase = pmbuf->buf_pa;
+ if (ssu_vbase)
+ pcb->moal_mfree_consistent(pmadapter->pmoal_handle,
+ pmbuf->total_pcie_buf_len,
+ ssu_vbase, ssu_pbase);
+ wlan_free_mlan_buffer(pmadapter, pmbuf);
+ }
+ pmadapter->ssu_buf = MNULL;
+
+ LEAVE();
+ return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ * @brief This function allocates the PCIE ring buffers
+ *
+ * The following initializations steps are followed -
+ * - Allocate TXBD ring buffers
+ * - Allocate RXBD ring buffers
+ * - Allocate event BD ring buffers
+ * - Allocate command and command response buffer
+ * - Allocate sleep cookie buffer
+ *
+ * @param pmadapter A pointer to mlan_adapter structure
+ *
+ * @return MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ */
+mlan_status wlan_alloc_pcie_ring_buf(pmlan_adapter pmadapter)
+{
+ mlan_status ret = MLAN_STATUS_SUCCESS;
+
+ ENTER();
+ pmadapter->pcard_pcie->cmdrsp_buf = MNULL;
+ ret = wlan_pcie_create_txbd_ring(pmadapter);
+ if (ret)
+ goto err_cre_txbd;
+ ret = wlan_pcie_create_rxbd_ring(pmadapter);
+ if (ret)
+ goto err_cre_rxbd;
+ ret = wlan_pcie_create_evtbd_ring(pmadapter);
+ if (ret)
+ goto err_cre_evtbd;
+ ret = wlan_pcie_alloc_cmdrsp_buf(pmadapter);
+ if (ret)
+ goto err_alloc_cmdbuf;
+ return ret;
+err_alloc_cmdbuf:
+ wlan_pcie_delete_evtbd_ring(pmadapter);
+err_cre_evtbd:
+ wlan_pcie_delete_rxbd_ring(pmadapter);
+err_cre_rxbd:
+ wlan_pcie_delete_txbd_ring(pmadapter);
+err_cre_txbd:
+
+ LEAVE();
+ return ret;
+}
+
+/**
+ * @brief This function frees the allocated ring buffers.
+ *
+ * The following are freed by this function -
+ * - TXBD ring buffers
+ * - RXBD ring buffers
+ * - Event BD ring buffers
+ * - Command and command response buffer
+ * - Sleep cookie buffer
+ *
+ * @param pmadapter A pointer to mlan_adapter structure
+ *
+ * @return MLAN_STATUS_SUCCESS
+ */
+mlan_status wlan_free_pcie_ring_buf(pmlan_adapter pmadapter)
+{
+ ENTER();
+
+ wlan_pcie_delete_cmdrsp_buf(pmadapter);
+ wlan_pcie_delete_evtbd_ring(pmadapter);
+ wlan_pcie_delete_rxbd_ring(pmadapter);
+ wlan_pcie_delete_txbd_ring(pmadapter);
+ pmadapter->pcard_pcie->cmdrsp_buf = MNULL;
+#ifdef RPTR_MEM_COP
+ if ((pmadapter->card_type == CARD_TYPE_PCIE9098) ||
+ (pmadapter->card_type == CARD_TYPE_PCIE9097))
+ wlan_pcie_free_rdptrs(pmadapter);
+#endif
+
+ LEAVE();
+ return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ * @brief This function cleans up packets in the ring buffers.
+ *
+ * The following are cleaned by this function -
+ * - TXBD ring buffers
+ *
+ * @param pmadapter A pointer to mlan_adapter structure
+ *
+ * @return MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ */
+mlan_status wlan_clean_pcie_ring_buf(pmlan_adapter pmadapter)
+{
+ ENTER();
+#if defined(PCIE8997) || defined(PCIE8897)
+ if (!pmadapter->pcard_pcie->reg->use_adma)
+ wlan_pcie_flush_txbd_ring(pmadapter);
+#endif
+ LEAVE();
+ return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ * @brief This function prepares command to set PCI-Express
+ * host buffer configuration
+ *
+ * @param pmpriv A pointer to mlan_private structure
+ *
+ * @return MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ */
+mlan_status wlan_set_pcie_buf_config(mlan_private *pmpriv)
+{
+ pmlan_adapter pmadapter = MNULL;
+#if defined(PCIE8997) || defined(PCIE8897)
+ HostCmd_DS_PCIE_HOST_BUF_DETAILS host_spec;
+#endif
+ mlan_status ret = MLAN_STATUS_SUCCESS;
+
+ ENTER();
+ if (!pmpriv) {
+ LEAVE();
+ return MLAN_STATUS_FAILURE;
+ }
+ pmadapter = pmpriv->adapter;
+#if defined(PCIE8997) || defined(PCIE8897)
+ if (!pmadapter->pcard_pcie->reg->use_adma) {
+ memset(pmadapter, &host_spec, 0,
+ sizeof(HostCmd_DS_PCIE_HOST_BUF_DETAILS));
+
+ /* Send the ring base addresses and count to firmware */
+ host_spec.txbd_addr_lo =
+ (t_u32)(pmadapter->pcard_pcie->txbd_ring_pbase);
+ host_spec.txbd_addr_hi = (t_u32)(
+ ((t_u64)pmadapter->pcard_pcie->txbd_ring_pbase) >> 32);
+ host_spec.txbd_count = MLAN_MAX_TXRX_BD;
+ host_spec.rxbd_addr_lo =
+ (t_u32)(pmadapter->pcard_pcie->rxbd_ring_pbase);
+ host_spec.rxbd_addr_hi = (t_u32)(
+ ((t_u64)pmadapter->pcard_pcie->rxbd_ring_pbase) >> 32);
+ host_spec.rxbd_count = MLAN_MAX_TXRX_BD;
+ host_spec.evtbd_addr_lo =
+ (t_u32)(pmadapter->pcard_pcie->evtbd_ring_pbase);
+ host_spec.evtbd_addr_hi = (t_u32)(
+ ((t_u64)pmadapter->pcard_pcie->evtbd_ring_pbase) >> 32);
+ host_spec.evtbd_count = MLAN_MAX_EVT_BD;
+
+ ret = wlan_prepare_cmd(pmpriv,
+ HostCmd_CMD_PCIE_HOST_BUF_DETAILS,
+ HostCmd_ACT_GEN_SET, 0, MNULL,
+ &host_spec);
+ if (ret) {
+ PRINTM(MERROR,
+ "PCIE_HOST_BUF_CFG: send command failed\n");
+ ret = MLAN_STATUS_FAILURE;
+ }
+ }
+#endif
+#if defined(PCIE9098) || defined(PCIE9097)
+ if (pmadapter->pcard_pcie->reg->use_adma) {
+ /** config ADMA for Tx Data */
+ wlan_init_adma(pmadapter, ADMA_TX_DATA,
+ pmadapter->pcard_pcie->txbd_ring_pbase,
+ TX_RX_NUM_DESC, MTRUE);
+ /** config ADMA for Rx Data */
+ wlan_init_adma(pmadapter, ADMA_RX_DATA,
+ pmadapter->pcard_pcie->rxbd_ring_pbase,
+ TX_RX_NUM_DESC, MTRUE);
+ /** config ADMA for Rx Event */
+ wlan_init_adma(pmadapter, ADMA_EVENT,
+ pmadapter->pcard_pcie->evtbd_ring_pbase,
+ EVT_NUM_DESC, MTRUE);
+ /** config ADMA for cmd */
+ wlan_init_adma(pmadapter, ADMA_CMD, 0, 0, MTRUE);
+ /** config ADMA for cmdresp */
+ wlan_init_adma(pmadapter, ADMA_CMDRESP,
+ pmadapter->pcard_pcie->cmdrsp_buf->buf_pa, 0,
+ MTRUE);
+ }
+#endif
+ wlan_pcie_init_fw(pmadapter);
+ LEAVE();
+ return ret;
+}
+
+#if defined(PCIE8997) || defined(PCIE8897)
+/**
+ * @brief This function prepares command PCIE host buffer config.
+ *
+ * @param pmpriv A pointer to mlan_private structure
+ * @param cmd A pointer to HostCmd_DS_COMMAND structure
+ * @param cmd_action The action: GET or SET
+ * @param pdata_buf A pointer to data buffer
+ *
+ * @return MLAN_STATUS_SUCCESS
+ */
+mlan_status wlan_cmd_pcie_host_buf_cfg(pmlan_private pmpriv,
+ HostCmd_DS_COMMAND *cmd,
+ t_u16 cmd_action, t_pvoid pdata_buf)
+{
+ HostCmd_DS_PCIE_HOST_BUF_DETAILS *ppcie_hoost_spec =
+ &cmd->params.pcie_host_spec;
+
+ ENTER();
+
+ cmd->command = wlan_cpu_to_le16(HostCmd_CMD_PCIE_HOST_BUF_DETAILS);
+ cmd->size = wlan_cpu_to_le16(
+ (sizeof(HostCmd_DS_PCIE_HOST_BUF_DETAILS)) + S_DS_GEN);
+
+ if (cmd_action == HostCmd_ACT_GEN_SET) {
+ memcpy_ext(pmpriv->adapter, ppcie_hoost_spec, pdata_buf,
+ sizeof(HostCmd_DS_PCIE_HOST_BUF_DETAILS),
+ sizeof(HostCmd_DS_PCIE_HOST_BUF_DETAILS));
+ }
+
+ LEAVE();
+ return MLAN_STATUS_SUCCESS;
+}
+#endif
+
+/**
+ * @brief This function wakes up the card.
+ *
+ * @param pmadapter A pointer to mlan_adapter structure
+ * @param timeout set timeout flag
+ *
+ * @return MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ */
+mlan_status wlan_pm_pcie_wakeup_card(pmlan_adapter pmadapter, t_u8 timeout)
+{
+ mlan_status ret = MLAN_STATUS_SUCCESS;
+ t_u32 age_ts_usec;
+
+ ENTER();
+ PRINTM(MEVENT, "Wakeup device...\n");
+ pmadapter->callbacks.moal_get_system_time(pmadapter->pmoal_handle,
+ &pmadapter->pm_wakeup_in_secs,
+ &age_ts_usec);
+
+ if (timeout) {
+ pmadapter->callbacks.moal_start_timer(
+ pmadapter->pmoal_handle, pmadapter->pwakeup_fw_timer,
+ MFALSE, MRVDRV_TIMER_3S);
+ pmadapter->wakeup_fw_timer_is_set = MTRUE;
+ }
+
+ ret = wlan_pcie_wakeup(pmadapter);
+
+ LEAVE();
+ return ret;
+}
+
+mlan_status wlan_pcie_debug_dump(pmlan_adapter pmadapter)
+{
+ mlan_status ret = MLAN_STATUS_SUCCESS;
+ pmlan_buffer pmbuf = pmadapter->pcard_pcie->cmdrsp_buf;
+ ENTER();
+
+ if (pmbuf == MNULL) {
+ PRINTM(MMSG, "Rx CMD response pmbuf is null\n");
+ LEAVE();
+ return MLAN_STATUS_FAILURE;
+ }
+ PRINTM(MERROR, "Dump Rx CMD Response Buf:\n");
+ DBG_HEXDUMP(MERROR, "CmdResp Buf", pmbuf->pbuf + pmbuf->data_offset,
+ 64);
+
+ LEAVE();
+ return ret;
+}
+
+/**
+ * @brief This function handle data complete
+ *
+ * @param pmadapter A pointer to mlan_adapter structure
+ * @param pmbuf A pointer to the mlan_buffer
+ * @return N/A
+ */
+mlan_status wlan_pcie_data_complete(pmlan_adapter pmadapter, mlan_buffer *pmbuf,
+ mlan_status status)
+{
+ ENTER();
+
+ wlan_free_mlan_buffer(pmadapter, pmbuf);
+
+ LEAVE();
+ return MLAN_STATUS_SUCCESS;
+}
+
+mlan_adapter_operations mlan_pcie_ops = {
+ .dnld_fw = wlan_pcie_dnld_fw,
+ .interrupt = wlan_pcie_interrupt,
+ .process_int_status = wlan_process_pcie_int_status,
+ .host_to_card = wlan_pcie_host_to_card,
+ .wakeup_card = wlan_pm_pcie_wakeup_card,
+ .reset_card = wlan_pcie_wakeup,
+ .event_complete = wlan_pcie_event_complete,
+ .data_complete = wlan_pcie_data_complete,
+ .cmdrsp_complete = wlan_pcie_cmdrsp_complete,
+ .handle_rx_packet = wlan_handle_rx_packet,
+ .debug_dump = wlan_pcie_debug_dump,
+ .intf_header_len = PCIE_INTF_HEADER_LEN,
+};
diff --git a/drivers/net/wireless/nxp/mxm_wifiex/wlan_src/mlan/mlan_pcie.h b/drivers/net/wireless/nxp/mxm_wifiex/wlan_src/mlan/mlan_pcie.h
new file mode 100644
index 000000000000..af404379e81b
--- /dev/null
+++ b/drivers/net/wireless/nxp/mxm_wifiex/wlan_src/mlan/mlan_pcie.h
@@ -0,0 +1,650 @@
+/** @file mlan_pcie.h
+ *
+ * @brief This file contains definitions for PCIE interface.
+ * driver.
+ *
+ *
+ * Copyright 2014-2020 NXP
+ *
+ * This software file (the File) is distributed by NXP
+ * under the terms of the GNU General Public License Version 2, June 1991
+ * (the License). You may use, redistribute and/or modify the 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.
+ *
+ */
+
+/********************************************************
+Change log:
+ 02/01/2012: initial version
+********************************************************/
+
+#ifndef _MLAN_PCIE_H_
+#define _MLAN_PCIE_H_
+/** Tx DATA */
+#define ADMA_TX_DATA 0
+/** Rx DATA */
+#define ADMA_RX_DATA 1
+/** EVENT */
+#define ADMA_EVENT 2
+/** CMD */
+#define ADMA_CMD 3
+/** CMD RESP */
+#define ADMA_CMDRESP 4
+/** ADMA direction */
+#define ADMA_HOST_TO_DEVICE 0
+/** ADMA direction Rx */
+#define ADMA_DEVICE_TO_HOST 1
+/** Direct Program mode */
+#define DMA_MODE_DIRECT 0
+/** Single descriptor mode */
+#define DMA_MODE_SINGLE_DESC 1
+/** dual discriptor mode */
+#define DMA_MODE_DUAL_DESC 2
+/** descriptor mode: ring mode */
+#define DESC_MODE_RING 0
+/** descriptor mode: chain mode */
+#define DESC_MODE_CHAIN 1
+/** DMA size start bit */
+#define DMA_SIZE_BIT 16
+/** DMA size mask */
+#define DMA_SIZE_MASK 0xffff0000
+/** Descriptor mode */
+#define DESC_MODE_MASK 0x0004
+/** DMA MODE MASK */
+#define DMA_MODE_MASK 0x0003
+/** Dest Num Descriptor start bits */
+#define DST_NUM_DESC_BIT 12
+/** Destination Num of Descriptor mask */
+#define DST_NUM_DESC_MASK 0xf000
+/** Src Num Descriptor start bits */
+#define SRC_NUM_DESC_BIT 8
+/** Destination Num of Descriptor mask */
+#define SRC_NUM_DESC_MASK 0x0f00
+/** Virtual Q priority mask */
+#define Q_PRIO_WEIGHT_MASK 0x00f0
+/** DMA cfg register offset*/
+#define ADMA_DMA_CFG 0x0000
+/** source base low */
+#define ADMA_SRC_LOW 0x0004
+/** source base high */
+#define ADMA_SRC_HIGH 0x0008
+/** destination base low */
+#define ADMA_DST_LOW 0x000C
+/** destination base high */
+#define ADMA_DST_HIGH 0x0010
+/** source rd/wr pointer */
+#define ADMA_SRC_RW_PTR 0x0014
+/** destination rd/wr pointer */
+#define ADMA_DST_RW_PTR 0x0018
+/** interrupt direction mapping reg, for each virtual Q, used for
+ * dual-descriptor only, only valid for Q0 */
+#define ADMA_INT_MAPPING 0x001C
+/** destination interrupt to device */
+#define DEST_INT_TO_DEVICE MBIT(0)
+/** destination interrupt to host */
+#define DEST_INT_TO_HOST MBIT(1)
+/** interrupt pending status for each virtual Q, only valid for Q0 */
+#define ADMA_INT_PENDING 0x0020
+/** Default ADMA INT mask, We only enable dma done */
+#define DEF_ADMA_INT_MASK MBIT(0)
+/** source interrupt status mask reg */
+#define ADMA_SRC_INT_STATUS_MASK 0x0024
+/** source interrupt mask reg */
+#define ADMA_SRC_INT_MASK 0x0028
+/** source interrupt status reg */
+#define ADMA_SRC_INT_STATUS 0x002C
+/** destination interrupt status mask reg */
+#define ADMA_DST_INT_STATUS_MASK 0x0030
+/** destination interrupt mask reg */
+#define ADMA_DST_INT_MASK 0x0034
+/** destination interrupt status reg */
+#define ADMA_DST_INT_STATUS 0x0038
+/** DMA cfg2 register */
+#define ADMA_DMA_CFG2 0x003C
+/** ADMA_MSI_LEGACY_DST_DMA_DONE_INT_BYPASS_EN */
+#define ADMA_MSI_LEGACY_DST_DMA_DONE_INT_BYPASS_EN MBIT(22)
+/** ADMA_MSI_LEGACY_SRC_DMA_DONE_INT_BYPASS_EN */
+#define ADMA_MSI_LEGACY_SRC_DMA_DONE_INT_BYPASS_EN MBIT(21)
+/* If this bit is set, MSIX trigger event will be from DST, other wise MSIX
+ * trigger event will be from SRC */
+#define ADMA_MSIX_INT_SRC_DST_SEL MBIT(20)
+/** Enable MSI/Legacy for this Queue */
+#define ADMA_MSI_LEGACY_ENABLE MBIT(19)
+/** Enable MSIX for this queue */
+#define ADMA_MSIX_ENABLE MBIT(18)
+/** ADMA_DST_DMA_DONE_INT_BYPASS_EN */
+#define ADMA_DST_DMA_DONE_INT_BYPASS_EN MBIT(17)
+/** SRC_DMA_DONE_INT_BYPASS_EN */
+#define ADMA_SRC_DMA_DONE_INT_BYPASS_EN MBIT(16)
+/* Destination Read Pointer Memory Copy Enable */
+#define ADMA_DST_RPTR_MEM_COPY_EN MBIT(11)
+/* Source Read Pointer Memory Copy Enable */
+#define ADMA_SRC_RPTR_MEM_COPY_EN MBIT(10)
+/** Destination address is host */
+#define ADMA_DST_ADDR_IS_HOST MBIT(2)
+/** Source address is host */
+#define ADMA_SRC_ADDR_IS_HOST MBIT(1)
+
+/** DMA cfg3 register */
+#define ADMA_DMA_CFG3 0x0040
+/** source rd ptr address low */
+#define ADMA_SRC_RD_PTR_LOW 0x0044
+/** source rd ptr address high */
+#define ADMA_SRC_RD_PTR_HIGH 0x0048
+/** destination rd ptr address low */
+#define ADMA_DST_RD_PTR_LOW 0x004C
+/** destination rd ptr address high */
+#define ADMA_DST_RD_PTR_HIGH 0x0050
+/** source active interrupt mask */
+#define ADMA_SRC_ACTV_INT_MASK 0x0054
+/** destination active interrupt mask */
+#define ADMA_DST_ACTV_INT_MASK 0x0058
+/** Read pointer start from bit 16 */
+#define ADMA_RPTR_START 16
+/** write pointer start from bit 0 */
+#define ADMA_WPTR_START 0
+/** Tx/Rx Read/Write pointer's mask */
+#define TXRX_RW_PTR_MASK (MLAN_MAX_TXRX_BD - 1)
+/** Tx/Rx Read/Write pointer's rollover indicate bit */
+#define TXRX_RW_PTR_ROLLOVER_IND MLAN_MAX_TXRX_BD
+/** Start of packet flag */
+#define ADMA_BD_FLAG_SOP MBIT(0)
+/** End of packet flag */
+#define ADMA_BD_FLAG_EOP MBIT(1)
+/** interrupt enable flag */
+#define ADMA_BD_FLAG_INT_EN MBIT(2)
+/** Source address is host side flag */
+#define ADMA_BD_FLAG_SRC_HOST MBIT(3)
+/** Destination address is host side flag */
+#define ADMA_BD_FLAG_DST_HOST MBIT(4)
+/** ADMA MIN PKT SIZE */
+#define ADMA_MIN_PKT_SIZE 128
+/** ADMA dual descriptor mode requir 8 bytes alignment in buf size */
+#define ADMA_ALIGN_SIZE 8
+/** ADMA RW_PTR wrap mask */
+#define ADMA_RW_PTR_WRAP_MASK 0x00001FFF
+/** ADMA MSIX DOORBEEL DATA */
+#define ADMA_MSIX_DOORBELL_DATA 0x0064
+/** MSIX VECTOR MASK: BIT 0-10 */
+#define ADMA_MSIX_VECTOR_MASK 0x3f
+/** PF mask: BIT 24-28 */
+#define ADMA_MSIX_PF_MASK 0x1f000000
+/** PF start bit */
+#define ADMA_MSIX_PF_BIT 24
+
+#if defined(PCIE9098) || defined(PCIE9097)
+/** PCIE9098 dev_id/vendor id reg */
+#define PCIE9098_DEV_ID_REG 0x0000
+/** PCIE revision ID register */
+#define PCIE9098_REV_ID_REG 0x0008
+/** PCIE IP revision register */
+#define PCIE9098_IP_REV_REG 0x1000
+/** PCIE CPU interrupt events */
+#define PCIE9098_CPU_INT_EVENT 0x1C20
+/** PCIE CPU interrupt status */
+#define PCIE9098_CPU_INT_STATUS 0x1C24
+/** PCIe CPU Interrupt Status Mask */
+#define PCIE9098_CPU_INT2ARM_ISM 0x1C28
+/** PCIE host interrupt status */
+#define PCIE9098_HOST_INT_STATUS 0x1C44
+/** PCIE host interrupt mask */
+#define PCIE9098_HOST_INT_MASK 0x1C48
+/** PCIE host interrupt clear select*/
+#define PCIE9098_HOST_INT_CLR_SEL 0x1C4C
+/** PCIE host interrupt status mask */
+#define PCIE9098_HOST_INT_STATUS_MASK 0x1C50
+/** PCIE host interrupt status */
+#define PCIE9097_B0_HOST_INT_STATUS 0x3C44
+/** PCIE host interrupt mask */
+#define PCIE9097_B0_HOST_INT_MASK 0x3C48
+/** PCIE host interrupt clear select*/
+#define PCIE9097_B0_HOST_INT_CLR_SEL 0x3C4C
+/** PCIE host interrupt status mask */
+#define PCIE9097_B0_HOST_INT_STATUS_MASK 0x3C50
+/** PCIE host interrupt select*/
+#define PCIE9098_HOST_INT_SEL 0x1C58
+/** PCIE data exchange register 0 */
+#define PCIE9098_SCRATCH_0_REG 0x1C60
+/** PCIE data exchange register 1 */
+#define PCIE9098_SCRATCH_1_REG 0x1C64
+/** PCIE data exchange register 2 */
+#define PCIE9098_SCRATCH_2_REG 0x1C68
+/** PCIE data exchange register 3 */
+#define PCIE9098_SCRATCH_3_REG 0x1C6C
+/** PCIE data exchange register 4 */
+#define PCIE9098_SCRATCH_4_REG 0x1C70
+/** PCIE data exchange register 5 */
+#define PCIE9098_SCRATCH_5_REG 0x1C74
+/** PCIE data exchange register 6 */
+#define PCIE9098_SCRATCH_6_REG 0x1C78
+/** PCIE data exchange register 7 */
+#define PCIE9098_SCRATCH_7_REG 0x1C7C
+/** PCIE data exchange register 8 */
+#define PCIE9098_SCRATCH_8_REG 0x1C80
+/** PCIE data exchange register 9 */
+#define PCIE9098_SCRATCH_9_REG 0x1C84
+/** PCIE data exchange register 10 */
+#define PCIE9098_SCRATCH_10_REG 0x1C88
+/** PCIE data exchange register 11 */
+#define PCIE9098_SCRATCH_11_REG 0x1C8C
+/** PCIE data exchange register 12 */
+#define PCIE9098_SCRATCH_12_REG 0x1C90
+/** PCIE data exchange register 13 */
+#define PCIE9098_SCRATCH_13_REG 0x1C94
+/** PCIE data exchange register 14 */
+#define PCIE9098_SCRATCH_14_REG 0x1C98
+/** PCIE data exchange register 15 */
+#define PCIE9098_SCRATCH_15_REG 0x1C9C
+/** ADMA CHAN0_Q0 start address, Tx Data */
+#define ADMA_CHAN0_Q0 0x10000
+/** ADMA CHAN1_Q0 start address, Rx Data */
+#define ADMA_CHAN1_Q0 0x10800
+/** ADMA CHAN1_Q1 start address, Rx Event */
+#define ADMA_CHAN1_Q1 0x10880
+/** ADMA CHAN2_Q0 start address, Tx Command */
+#define ADMA_CHAN2_Q0 0x11000
+/** ADMA CHAN2_Q1 start address, Command Resp */
+#define ADMA_CHAN2_Q1 0x11080
+/** CH0-Q0' src rd/wr ptr */
+#define ADMA_SRC_PTR_CH0_Q0 (ADMA_CHAN0_Q0 + ADMA_SRC_RW_PTR)
+/** CH1-Q1' dest rd/wr ptr */
+#define ADMA_DST_PTR_CH1_Q0 (ADMA_CHAN1_Q0 + ADMA_DST_RW_PTR)
+/** CH1-Q1' dest rd/wr ptr */
+#define ADMA_DST_PTR_CH1_Q1 (ADMA_CHAN1_Q1 + ADMA_DST_RW_PTR)
+/* TX buffer description read pointer */
+#define PCIE9098_TXBD_RDPTR ADMA_SRC_PTR_CH0_Q0
+/* TX buffer description write pointer */
+#define PCIE9098_TXBD_WRPTR ADMA_SRC_PTR_CH0_Q0
+/* RX buffer description read pointer */
+#define PCIE9098_RXBD_RDPTR ADMA_DST_PTR_CH1_Q0
+/* RX buffer description write pointer */
+#define PCIE9098_RXBD_WRPTR ADMA_DST_PTR_CH1_Q0
+/* Event buffer description read pointer */
+#define PCIE9098_EVTBD_RDPTR ADMA_DST_PTR_CH1_Q1
+/* Event buffer description write pointer */
+#define PCIE9098_EVTBD_WRPTR ADMA_DST_PTR_CH1_Q1
+/* Driver ready signature write pointer */
+#define PCIE9098_DRV_READY PCIE9098_SCRATCH_12_REG
+
+/** interrupt bit define for ADMA CHAN0 Q0, For Tx DATA */
+#define ADMA_INT_CHAN0_Q0 MBIT(0)
+/** interrupt bit define for ADMA CHAN1 Q0, For Rx Data */
+#define AMDA_INT_CHAN1_Q0 MBIT(16)
+/** interrupt bit define for ADMA CHAN1 Q1, For Rx Event */
+#define AMDA_INT_CHAN1_Q1 MBIT(17)
+/** interrupt bit define for ADMA CHAN2 Q0, For Tx Command */
+#define AMDA_INT_CHAN2_Q0 MBIT(24)
+/** interrupt bit define for ADMA CHAN2 Q1, For Rx Command Resp */
+#define AMDA_INT_CHAN2_Q1 MBIT(25)
+
+/** interrupt vector number for ADMA CHAN0 Q0, For Tx DATA */
+#define ADMA_VECTOR_CHAN0_Q0 0
+/** interrupt vector number for ADMA CHAN1 Q0, For Rx Data */
+#define AMDA_VECTOR_CHAN1_Q0 16
+/** interrupt vector number for ADMA CHAN1 Q1, For Rx Event */
+#define AMDA_VECTOR_CHAN1_Q1 17
+/** interrupt vector number for ADMA CHAN2 Q0, For Tx Command */
+#define AMDA_VECTOR_CHAN2_Q0 24
+/** interrupt vector number for ADMA CHAN2 Q1, For Rx Command Resp */
+#define AMDA_VECTOR_CHAN2_Q1 25
+
+/** Data sent interrupt for host */
+#define PCIE9098_HOST_INTR_DNLD_DONE ADMA_INT_CHAN0_Q0
+/** Data receive interrupt for host */
+#define PCIE9098_HOST_INTR_UPLD_RDY AMDA_INT_CHAN1_Q0
+/** Command sent interrupt for host */
+#define PCIE9098_HOST_INTR_CMD_DONE AMDA_INT_CHAN2_Q1
+/** Event ready interrupt for host */
+#define PCIE9098_HOST_INTR_EVENT_RDY AMDA_INT_CHAN1_Q1
+/** CMD sent interrupt for host */
+#define PCIE9098_HOST_INTR_CMD_DNLD MBIT(7)
+
+/** Interrupt mask for host */
+#define PCIE9098_HOST_INTR_MASK \
+ (PCIE9098_HOST_INTR_DNLD_DONE | PCIE9098_HOST_INTR_UPLD_RDY | \
+ PCIE9098_HOST_INTR_CMD_DONE | PCIE9098_HOST_INTR_CMD_DNLD | \
+ PCIE9098_HOST_INTR_EVENT_RDY)
+
+/** Interrupt select mask for host */
+#define PCIE9098_HOST_INTR_SEL_MASK \
+ (PCIE9098_HOST_INTR_DNLD_DONE | PCIE9098_HOST_INTR_UPLD_RDY | \
+ PCIE9098_HOST_INTR_CMD_DONE | PCIE9098_HOST_INTR_EVENT_RDY)
+#endif
+
+#if defined(PCIE8997) || defined(PCIE8897)
+/* PCIE INTERNAL REGISTERS */
+/** PCIE data exchange register 0 */
+#define PCIE_SCRATCH_0_REG 0x0C10
+/** PCIE data exchange register 1 */
+#define PCIE_SCRATCH_1_REG 0x0C14
+/** PCIE CPU interrupt events */
+#define PCIE_CPU_INT_EVENT 0x0C18
+/** PCIE CPU interrupt status */
+#define PCIE_CPU_INT_STATUS 0x0C1C
+
+/** PCIe CPU Interrupt Status Mask */
+#define PCIE_CPU_INT2ARM_ISM 0x0C28
+/** PCIE host interrupt status */
+#define PCIE_HOST_INT_STATUS 0x0C30
+/** PCIE host interrupt mask */
+#define PCIE_HOST_INT_MASK 0x0C34
+/** PCIE host interrupt status mask */
+#define PCIE_HOST_INT_STATUS_MASK 0x0C3C
+/** PCIE data exchange register 2 */
+#define PCIE_SCRATCH_2_REG 0x0C40
+/** PCIE data exchange register 3 */
+#define PCIE_SCRATCH_3_REG 0x0C44
+
+#define PCIE_IP_REV_REG 0x0C48
+
+/** PCIE data exchange register 4 */
+#define PCIE_SCRATCH_4_REG 0x0CD0
+/** PCIE data exchange register 5 */
+#define PCIE_SCRATCH_5_REG 0x0CD4
+/** PCIE data exchange register 6 */
+#define PCIE_SCRATCH_6_REG 0x0CD8
+/** PCIE data exchange register 7 */
+#define PCIE_SCRATCH_7_REG 0x0CDC
+/** PCIE data exchange register 8 */
+#define PCIE_SCRATCH_8_REG 0x0CE0
+/** PCIE data exchange register 9 */
+#define PCIE_SCRATCH_9_REG 0x0CE4
+/** PCIE data exchange register 10 */
+#define PCIE_SCRATCH_10_REG 0x0CE8
+/** PCIE data exchange register 11 */
+#define PCIE_SCRATCH_11_REG 0x0CEC
+/** PCIE data exchange register 12 */
+#define PCIE_SCRATCH_12_REG 0x0CF0
+#endif
+
+#ifdef PCIE8997
+/* PCIE read data pointer for queue 0 and 1 */
+#define PCIE8997_RD_DATA_PTR_Q0_Q1 0xC1A4 /* 0x8000C1A4 */
+/* PCIE read data pointer for queue 2 and 3 */
+#define PCIE8997_RD_DATA_PTR_Q2_Q3 0xC1A8 /* 0x8000C1A8 */
+/* PCIE write data pointer for queue 0 and 1 */
+#define PCIE8997_WR_DATA_PTR_Q0_Q1 0xC174 /* 0x8000C174 */
+/* PCIE write data pointer for queue 2 and 3 */
+#define PCIE8997_WR_DATA_PTR_Q2_Q3 0xC178 /* 0x8000C178 */
+#endif
+#ifdef PCIE8897
+/* PCIE read data pointer for queue 0 and 1 */
+#define PCIE8897_RD_DATA_PTR_Q0_Q1 0xC08C /* 0x8000C08C */
+/* PCIE read data pointer for queue 2 and 3 */
+#define PCIE8897_RD_DATA_PTR_Q2_Q3 0xC090 /* 0x8000C090 */
+/* PCIE write data pointer for queue 0 and 1 */
+#define PCIE8897_WR_DATA_PTR_Q0_Q1 0xC05C /* 0x8000C05C */
+/* PCIE write data pointer for queue 2 and 3 */
+#define PCIE8897_WR_DATA_PTR_Q2_Q3 0xC060 /* 0x8000C060 */
+#endif
+
+/** Download ready interrupt for CPU */
+#define CPU_INTR_DNLD_RDY MBIT(0)
+/** Command ready interrupt for CPU */
+#define CPU_INTR_DOOR_BELL MBIT(1)
+/** Confirmation that sleep confirm message has been processed.
+ Device will enter sleep after receiving this interrupt */
+#define CPU_INTR_SLEEP_CFM_DONE MBIT(2)
+/** Reset interrupt for CPU */
+#define CPU_INTR_RESET MBIT(3)
+/** Set Event Done interupt to the FW*/
+#define CPU_INTR_EVENT_DONE MBIT(5)
+
+#if defined(PCIE8997) || defined(PCIE8897)
+/** Data sent interrupt for host */
+#define HOST_INTR_DNLD_DONE MBIT(0)
+/** Data receive interrupt for host */
+#define HOST_INTR_UPLD_RDY MBIT(1)
+/** Command sent interrupt for host */
+#define HOST_INTR_CMD_DONE MBIT(2)
+/** Event ready interrupt for host */
+#define HOST_INTR_EVENT_RDY MBIT(3)
+/** Interrupt mask for host */
+#define HOST_INTR_MASK \
+ (HOST_INTR_DNLD_DONE | HOST_INTR_UPLD_RDY | HOST_INTR_CMD_DONE | \
+ HOST_INTR_EVENT_RDY)
+
+/** Lower 32bits command address holding register */
+#define REG_CMD_ADDR_LO PCIE_SCRATCH_0_REG
+/** Upper 32bits command address holding register */
+#define REG_CMD_ADDR_HI PCIE_SCRATCH_1_REG
+/** Command length holding register */
+#define REG_CMD_SIZE PCIE_SCRATCH_2_REG
+
+/** Lower 32bits command response address holding register */
+#define REG_CMDRSP_ADDR_LO PCIE_SCRATCH_4_REG
+/** Upper 32bits command response address holding register */
+#define REG_CMDRSP_ADDR_HI PCIE_SCRATCH_5_REG
+
+/** TxBD's Read/Write pointer start from bit 16 */
+#define TXBD_RW_PTR_START 16
+/** RxBD's Read/Write pointer start from bit 0 */
+#define RXBD_RW_PTR_STRAT 0
+
+#define MLAN_BD_FLAG_SOP MBIT(0)
+#define MLAN_BD_FLAG_EOP MBIT(1)
+#define MLAN_BD_FLAG_XS_SOP MBIT(2)
+#define MLAN_BD_FLAG_XS_EOP MBIT(3)
+
+/* Event buffer description write pointer */
+#define REG_EVTBD_WRPTR PCIE_SCRATCH_10_REG
+/* Event buffer description read pointer */
+#define REG_EVTBD_RDPTR PCIE_SCRATCH_11_REG
+/* Driver ready signature write pointer */
+#define REG_DRV_READY PCIE_SCRATCH_12_REG
+
+/** Event Read/Write pointer mask */
+#define EVT_RW_PTR_MASK 0x0f
+/** Event Read/Write pointer rollover bit */
+#define EVT_RW_PTR_ROLLOVER_IND MBIT(7)
+#endif
+
+/* Define PCIE block size for firmware download */
+#define MLAN_PCIE_BLOCK_SIZE_FW_DNLD 256
+
+/** Extra added macros **/
+#define MLAN_EVENT_HEADER_LEN 8
+
+/** Max interrupt status register read limit */
+#define MAX_READ_REG_RETRY 10000
+
+#ifdef PCIE8897
+static const struct _mlan_pcie_card_reg mlan_reg_pcie8897 = {
+ .reg_txbd_rdptr = PCIE8897_RD_DATA_PTR_Q0_Q1,
+ .reg_txbd_wrptr = PCIE8897_WR_DATA_PTR_Q0_Q1,
+ .reg_rxbd_rdptr = PCIE8897_RD_DATA_PTR_Q0_Q1,
+ .reg_rxbd_wrptr = PCIE8897_WR_DATA_PTR_Q0_Q1,
+ .reg_evtbd_rdptr = REG_EVTBD_RDPTR,
+ .reg_evtbd_wrptr = REG_EVTBD_WRPTR,
+ .reg_host_int_mask = PCIE_HOST_INT_MASK,
+ .reg_host_int_status_mask = PCIE_HOST_INT_STATUS_MASK,
+ .reg_host_int_status = PCIE_HOST_INT_STATUS,
+ .reg_cpu_int_event = PCIE_CPU_INT_EVENT,
+ .reg_ip_rev = PCIE_IP_REV_REG,
+ .reg_drv_ready = REG_DRV_READY,
+ .reg_cpu_int_status = PCIE_CPU_INT_STATUS,
+ .reg_scratch_0 = PCIE_SCRATCH_0_REG,
+ .reg_scratch_1 = PCIE_SCRATCH_1_REG,
+ .reg_scratch_2 = PCIE_SCRATCH_2_REG,
+ .reg_scratch_3 = PCIE_SCRATCH_3_REG,
+ .host_intr_mask = HOST_INTR_MASK,
+ .host_intr_dnld_done = HOST_INTR_DNLD_DONE,
+ .host_intr_upld_rdy = HOST_INTR_UPLD_RDY,
+ .host_intr_cmd_done = HOST_INTR_CMD_DONE,
+ .host_intr_event_rdy = HOST_INTR_EVENT_RDY,
+ .txrx_rw_ptr_mask = 0x000003FF,
+ .txrx_rw_ptr_wrap_mask = 0x000007FF,
+ .txrx_rw_ptr_rollover_ind = MBIT(10),
+ .use_adma = MFALSE,
+ .msi_int_wr_clr = MTRUE,
+};
+
+static const struct _mlan_card_info mlan_card_info_pcie8897 = {
+ .max_tx_buf_size = MLAN_TX_DATA_BUF_SIZE_4K,
+ .v16_fw_api = 0,
+ .supp_ps_handshake = 0,
+ .default_11n_tx_bf_cap = DEFAULT_11N_TX_BF_CAP_2X2,
+};
+#endif
+
+#ifdef PCIE8997
+static const struct _mlan_pcie_card_reg mlan_reg_pcie8997 = {
+ .reg_txbd_rdptr = PCIE8997_RD_DATA_PTR_Q0_Q1,
+ .reg_txbd_wrptr = PCIE8997_WR_DATA_PTR_Q0_Q1,
+ .reg_rxbd_rdptr = PCIE8997_RD_DATA_PTR_Q0_Q1,
+ .reg_rxbd_wrptr = PCIE8997_WR_DATA_PTR_Q0_Q1,
+ .reg_evtbd_rdptr = REG_EVTBD_RDPTR,
+ .reg_evtbd_wrptr = REG_EVTBD_WRPTR,
+ .reg_host_int_mask = PCIE_HOST_INT_MASK,
+ .reg_host_int_status_mask = PCIE_HOST_INT_STATUS_MASK,
+ .reg_host_int_status = PCIE_HOST_INT_STATUS,
+ .reg_cpu_int_event = PCIE_CPU_INT_EVENT,
+ .reg_ip_rev = PCIE_IP_REV_REG,
+ .reg_drv_ready = REG_DRV_READY,
+ .reg_cpu_int_status = PCIE_CPU_INT_STATUS,
+ .reg_scratch_0 = PCIE_SCRATCH_0_REG,
+ .reg_scratch_1 = PCIE_SCRATCH_1_REG,
+ .reg_scratch_2 = PCIE_SCRATCH_2_REG,
+ .reg_scratch_3 = PCIE_SCRATCH_3_REG,
+ .host_intr_mask = HOST_INTR_MASK,
+ .host_intr_dnld_done = HOST_INTR_DNLD_DONE,
+ .host_intr_upld_rdy = HOST_INTR_UPLD_RDY,
+ .host_intr_cmd_done = HOST_INTR_CMD_DONE,
+ .host_intr_event_rdy = HOST_INTR_EVENT_RDY,
+ .txrx_rw_ptr_mask = 0x00000FFF,
+ .txrx_rw_ptr_wrap_mask = 0x00001FFF,
+ .txrx_rw_ptr_rollover_ind = MBIT(12),
+ .use_adma = MFALSE,
+ .msi_int_wr_clr = MTRUE,
+};
+
+static const struct _mlan_card_info mlan_card_info_pcie8997 = {
+ .max_tx_buf_size = MLAN_TX_DATA_BUF_SIZE_4K,
+ .v16_fw_api = 1,
+ .supp_ps_handshake = 0,
+ .default_11n_tx_bf_cap = DEFAULT_11N_TX_BF_CAP_2X2,
+};
+#endif
+
+#if defined(PCIE9098) || defined(PCIE9097)
+static const struct _mlan_pcie_card_reg mlan_reg_pcie9098 = {
+ .reg_txbd_rdptr = PCIE9098_TXBD_RDPTR,
+ .reg_txbd_wrptr = PCIE9098_TXBD_WRPTR,
+ .reg_rxbd_rdptr = PCIE9098_RXBD_RDPTR,
+ .reg_rxbd_wrptr = PCIE9098_RXBD_WRPTR,
+ .reg_evtbd_rdptr = PCIE9098_EVTBD_RDPTR,
+ .reg_evtbd_wrptr = PCIE9098_EVTBD_WRPTR,
+ .reg_host_int_mask = PCIE9098_HOST_INT_MASK,
+ .reg_host_int_status_mask = PCIE9098_HOST_INT_STATUS_MASK,
+ .reg_host_int_status = PCIE9098_HOST_INT_STATUS,
+ .reg_host_int_clr_sel = PCIE9098_HOST_INT_CLR_SEL,
+ .reg_cpu_int_event = PCIE9098_CPU_INT_EVENT,
+ .reg_ip_rev = PCIE9098_DEV_ID_REG,
+ .reg_drv_ready = PCIE9098_DRV_READY,
+ .reg_cpu_int_status = PCIE9098_CPU_INT_STATUS,
+ .reg_rev_id = PCIE9098_REV_ID_REG,
+ .reg_scratch_0 = PCIE9098_SCRATCH_0_REG,
+ .reg_scratch_1 = PCIE9098_SCRATCH_1_REG,
+ .reg_scratch_2 = PCIE9098_SCRATCH_2_REG,
+ .reg_scratch_3 = PCIE9098_SCRATCH_3_REG,
+ .reg_scratch_6 = PCIE9098_SCRATCH_6_REG,
+ .reg_scratch_7 = PCIE9098_SCRATCH_7_REG,
+ .host_intr_mask = PCIE9098_HOST_INTR_MASK,
+ .host_intr_dnld_done = PCIE9098_HOST_INTR_DNLD_DONE,
+ .host_intr_upld_rdy = PCIE9098_HOST_INTR_UPLD_RDY,
+ .host_intr_cmd_done = PCIE9098_HOST_INTR_CMD_DONE,
+ .host_intr_event_rdy = PCIE9098_HOST_INTR_EVENT_RDY,
+ .host_intr_cmd_dnld = PCIE9098_HOST_INTR_CMD_DNLD,
+ .use_adma = MTRUE,
+ .msi_int_wr_clr = MTRUE,
+};
+
+static const struct _mlan_card_info mlan_card_info_pcie9098 = {
+ .max_tx_buf_size = MLAN_TX_DATA_BUF_SIZE_4K,
+ .v16_fw_api = 1,
+ .v17_fw_api = 1,
+ .supp_ps_handshake = 0,
+ .default_11n_tx_bf_cap = DEFAULT_11N_TX_BF_CAP_2X2,
+};
+#endif
+
+#ifdef PCIE9097
+static const struct _mlan_pcie_card_reg mlan_reg_pcie9097_b0 = {
+ .reg_txbd_rdptr = PCIE9098_TXBD_RDPTR,
+ .reg_txbd_wrptr = PCIE9098_TXBD_WRPTR,
+ .reg_rxbd_rdptr = PCIE9098_RXBD_RDPTR,
+ .reg_rxbd_wrptr = PCIE9098_RXBD_WRPTR,
+ .reg_evtbd_rdptr = PCIE9098_EVTBD_RDPTR,
+ .reg_evtbd_wrptr = PCIE9098_EVTBD_WRPTR,
+ .reg_host_int_mask = PCIE9097_B0_HOST_INT_MASK,
+ .reg_host_int_status_mask = PCIE9097_B0_HOST_INT_STATUS_MASK,
+ .reg_host_int_status = PCIE9097_B0_HOST_INT_STATUS,
+ .reg_host_int_clr_sel = PCIE9097_B0_HOST_INT_CLR_SEL,
+ .reg_cpu_int_event = PCIE9098_CPU_INT_EVENT,
+ .reg_ip_rev = PCIE9098_DEV_ID_REG,
+ .reg_drv_ready = PCIE9098_DRV_READY,
+ .reg_cpu_int_status = PCIE9098_CPU_INT_STATUS,
+ .reg_rev_id = PCIE9098_REV_ID_REG,
+ .reg_scratch_0 = PCIE9098_SCRATCH_0_REG,
+ .reg_scratch_1 = PCIE9098_SCRATCH_1_REG,
+ .reg_scratch_2 = PCIE9098_SCRATCH_2_REG,
+ .reg_scratch_3 = PCIE9098_SCRATCH_3_REG,
+ .reg_scratch_6 = PCIE9098_SCRATCH_6_REG,
+ .reg_scratch_7 = PCIE9098_SCRATCH_7_REG,
+ .host_intr_mask = PCIE9098_HOST_INTR_MASK,
+ .host_intr_dnld_done = PCIE9098_HOST_INTR_DNLD_DONE,
+ .host_intr_upld_rdy = PCIE9098_HOST_INTR_UPLD_RDY,
+ .host_intr_cmd_done = PCIE9098_HOST_INTR_CMD_DONE,
+ .host_intr_event_rdy = PCIE9098_HOST_INTR_EVENT_RDY,
+ .host_intr_cmd_dnld = PCIE9098_HOST_INTR_CMD_DNLD,
+ .use_adma = MTRUE,
+ .msi_int_wr_clr = MTRUE,
+};
+#endif
+/* Get pcie device from card type */
+mlan_status wlan_get_pcie_device(pmlan_adapter pmadapter);
+
+/** Set PCIE host buffer configurations */
+mlan_status wlan_set_pcie_buf_config(mlan_private *pmpriv);
+
+/** Init write pointer */
+mlan_status wlan_pcie_init_fw(pmlan_adapter pmadapter);
+
+#if defined(PCIE8997) || defined(PCIE8897)
+/** Prepare command PCIE host buffer config */
+mlan_status wlan_cmd_pcie_host_buf_cfg(pmlan_private pmpriv,
+ pHostCmd_DS_COMMAND cmd,
+ t_u16 cmd_action, t_pvoid pdata_buf);
+#endif
+
+/** Wakeup PCIE card */
+mlan_status wlan_pcie_wakeup(pmlan_adapter pmadapter);
+
+/** Set DRV_READY register */
+mlan_status wlan_set_drv_ready_reg(mlan_adapter *pmadapter, t_u32 val);
+/** PCIE init */
+mlan_status wlan_pcie_init(mlan_adapter *pmadapter);
+
+/** Read interrupt status */
+mlan_status wlan_process_msix_int(mlan_adapter *pmadapter);
+/** Transfer data to card */
+mlan_status wlan_pcie_host_to_card(pmlan_private pmpriv, t_u8 type,
+ mlan_buffer *mbuf, mlan_tx_param *tx_param);
+/** Ring buffer allocation function */
+mlan_status wlan_alloc_pcie_ring_buf(pmlan_adapter pmadapter);
+/** Ring buffer deallocation function */
+mlan_status wlan_free_pcie_ring_buf(pmlan_adapter pmadapter);
+/** Ring buffer cleanup function, e.g. on deauth */
+mlan_status wlan_clean_pcie_ring_buf(pmlan_adapter pmadapter);
+mlan_status wlan_alloc_ssu_pcie_buf(pmlan_adapter pmadapter);
+mlan_status wlan_free_ssu_pcie_buf(pmlan_adapter pmadapter);
+
+#endif /* _MLAN_PCIE_H_ */
diff --git a/drivers/net/wireless/nxp/mxm_wifiex/wlan_src/mlan/mlan_scan.c b/drivers/net/wireless/nxp/mxm_wifiex/wlan_src/mlan/mlan_scan.c
new file mode 100644
index 000000000000..09484b1a7ece
--- /dev/null
+++ b/drivers/net/wireless/nxp/mxm_wifiex/wlan_src/mlan/mlan_scan.c
@@ -0,0 +1,6468 @@
+/** @file mlan_scan.c
+ *
+ * @brief Functions implementing wlan scan IOCTL and firmware command APIs
+ *
+ * IOCTL handlers as well as command preparation and response routines
+ * for sending scan commands to the firmware.
+ *
+ *
+ * Copyright 2014-2020 NXP
+ *
+ * This software file (the File) is distributed by NXP
+ * under the terms of the GNU General Public License Version 2, June 1991
+ * (the License). You may use, redistribute and/or modify the 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.
+ *
+ */
+
+/******************************************************
+Change log:
+ 10/28/2008: initial version
+******************************************************/
+
+#include "mlan.h"
+#include "mlan_join.h"
+#include "mlan_util.h"
+#include "mlan_fw.h"
+#include "mlan_main.h"
+#include "mlan_11n.h"
+#include "mlan_11ac.h"
+#include "mlan_11ax.h"
+#include "mlan_11h.h"
+#ifdef DRV_EMBEDDED_SUPPLICANT
+#include "authenticator_api.h"
+#endif
+/********************************************************
+ Local Constants
+********************************************************/
+/** minimum scan time for passive to active scan */
+#define MIN_PASSIVE_TO_ACTIVE_SCAN_TIME 150
+
+#define MRVDRV_MAX_CHANNELS_PER_SCAN 40
+/** The maximum number of channels the firmware can scan per command */
+#define MRVDRV_MAX_CHANNELS_PER_SPECIFIC_SCAN 4
+
+/**
+ * Number of channels to scan per firmware scan command issuance.
+ *
+ * Number restricted to prevent hitting the limit on the amount of scan data
+ * returned in a single firmware scan command.
+ */
+#define MRVDRV_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(MrvlIEtypesHeader_t) + \
+ (MRVDRV_MAX_CHANNELS_PER_SPECIFIC_SCAN * sizeof(ChanScanParamSet_t)))
+
+/** Memory needed to store supported rate */
+#define RATE_TLV_MAX_SIZE \
+ (sizeof(MrvlIEtypes_RatesParamSet_t) + HOSTCMD_SUPPORTED_RATES)
+
+/** Memory needed to store a max number/size WildCard
+ * SSID TLV for a firmware scan */
+#define WILDCARD_SSID_TLV_MAX_SIZE \
+ (MRVDRV_MAX_SSID_LIST_LENGTH * \
+ (sizeof(MrvlIEtypes_WildCardSsIdParamSet_t) + \
+ MRVDRV_MAX_SSID_LENGTH))
+
+/** Memory needed to store a max number/size BSSID TLV for a firmware scan */
+#define BSSID_LIST_TLV_MAX_SIZE \
+ (sizeof(MrvlIEtypesHeader_t) + \
+ (MRVDRV_MAX_BSSID_LIST * MLAN_MAC_ADDR_LENGTH))
+
+/** WPS TLV MAX size is MAX IE size plus 2 bytes for
+ * t_u16 MRVL TLV extension */
+#define WPS_TLV_MAX_SIZE (sizeof(IEEEtypes_VendorSpecific_t) + 2)
+/** Maximum memory needed for a wlan_scan_cmd_config
+ * with all TLVs at max */
+#define MAX_SCAN_CFG_ALLOC \
+ (sizeof(wlan_scan_cmd_config) + sizeof(MrvlIEtypes_NumProbes_t) + \
+ sizeof(MrvlIETypes_HTCap_t) + CHAN_TLV_MAX_SIZE + RATE_TLV_MAX_SIZE + \
+ WILDCARD_SSID_TLV_MAX_SIZE + BSSID_LIST_TLV_MAX_SIZE + \
+ WPS_TLV_MAX_SIZE)
+
+/********************************************************
+ Local Variables
+********************************************************/
+
+/**
+ * Interally used to send a configured scan cmd between
+ * driver routines
+ */
+typedef union {
+ /** Scan configuration (variable length) */
+ wlan_scan_cmd_config config;
+ /** Max allocated block */
+ t_u8 config_alloc_buf[MAX_SCAN_CFG_ALLOC];
+} wlan_scan_cmd_config_tlv;
+
+/********************************************************
+ Global Variables
+********************************************************/
+
+/********************************************************
+ Local Functions
+********************************************************/
+/** Cipher suite definition */
+enum cipher_suite {
+ CIPHER_SUITE_WEP40,
+ CIPHER_SUITE_TKIP,
+ CIPHER_SUITE_CCMP,
+ CIPHER_SUITE_WEP104,
+ CIPHER_SUITE_GCMP,
+ CIPHER_SUITE_GCMP_256,
+ CIPHER_SUITE_CCMP_256,
+ CIPHER_SUITE_MAX
+};
+
+static t_u8 wpa_oui[CIPHER_SUITE_MAX][4] = {
+ {0x00, 0x50, 0xf2, 0x01}, /* WEP40 */
+ {0x00, 0x50, 0xf2, 0x02}, /* TKIP */
+ {0x00, 0x50, 0xf2, 0x04}, /* AES */
+ {0x00, 0x50, 0xf2, 0x05}, /* WEP104 */
+};
+
+static t_u8 rsn_oui[CIPHER_SUITE_MAX][4] = {
+ {0x00, 0x0f, 0xac, 0x01}, /* WEP40 */
+ {0x00, 0x0f, 0xac, 0x02}, /* TKIP */
+ {0x00, 0x0f, 0xac, 0x04}, /* AES */
+ {0x00, 0x0f, 0xac, 0x05}, /* WEP104 */
+ {0x00, 0x0f, 0xac, 0x08}, /* GCMP */
+ {0x00, 0x0f, 0xac, 0x09}, /* GCMP-256 */
+ {0x00, 0x0f, 0xac, 0x0a}, /* CCMP-256 */
+};
+
+/**
+ * @brief Convert radio type scan parameter to a band config used in join cmd
+ *
+ * @param radio_type Scan parameter indicating the radio used for a channel
+ * in a scan command.
+ *
+ * @return Band type conversion of scanBand used in join/assoc cmds
+ *
+ */
+t_u8 radio_type_to_band(t_u8 radio_type)
+{
+ t_u8 ret_band;
+
+ switch (radio_type) {
+ case BAND_5GHZ:
+ ret_band = BAND_A;
+ break;
+ case BAND_2GHZ:
+ default:
+ ret_band = BAND_G;
+ break;
+ }
+
+ return ret_band;
+}
+
+/**
+ * @brief This function will update the channel statistics from scan result
+ *
+ * @param pmpriv A pointer to mlan_private structure
+ * @param pchanstats_tlv A pointer to MrvlIEtypes_ChannelStats_t tlv
+ *
+ * @return NA
+ */
+void wlan_update_chan_statistics(mlan_private *pmpriv,
+ MrvlIEtypes_ChannelStats_t *pchanstats_tlv)
+{
+ mlan_adapter *pmadapter = pmpriv->adapter;
+ t_u8 i;
+ chan_statistics_t *pchan_stats =
+ (chan_statistics_t *)((t_u8 *)pchanstats_tlv +
+ sizeof(MrvlIEtypesHeader_t));
+ t_u8 num_chan = wlan_le16_to_cpu(pchanstats_tlv->header.len) /
+ sizeof(chan_statistics_t);
+
+ ENTER();
+
+ for (i = 0; i < num_chan; i++) {
+ if (pmadapter->idx_chan_stats >= pmadapter->num_in_chan_stats) {
+ PRINTM(MERROR,
+ "Over flow: idx_chan_stats=%d, num_in_chan_stats=%d\n",
+ pmadapter->idx_chan_stats,
+ pmadapter->num_in_chan_stats);
+ break;
+ }
+ pchan_stats->total_networks =
+ wlan_le16_to_cpu(pchan_stats->total_networks);
+ pchan_stats->cca_scan_duration =
+ wlan_le16_to_cpu(pchan_stats->cca_scan_duration);
+ pchan_stats->cca_busy_duration =
+ wlan_le16_to_cpu(pchan_stats->cca_busy_duration);
+ PRINTM(MCMND,
+ "chan=%d, noise=%d, total_network=%d scan_duration=%d, busy_duration=%d\n",
+ pchan_stats->chan_num, pchan_stats->noise,
+ pchan_stats->total_networks,
+ pchan_stats->cca_scan_duration,
+ pchan_stats->cca_busy_duration);
+ memcpy_ext(pmadapter,
+ (chan_statistics_t *)&pmadapter
+ ->pchan_stats[pmadapter->idx_chan_stats],
+ pchan_stats, sizeof(chan_statistics_t),
+ sizeof(chan_statistics_t));
+ pmadapter->idx_chan_stats++;
+ pchan_stats++;
+ }
+ LEAVE();
+ return;
+}
+
+/**
+ * @brief This function will parse a given IE for a given OUI
+ *
+ * Parse a given WPA/RSN IE to find if it has a given oui in PTK,
+ * if no OUI found for PTK it returns 0.
+ *
+ * @param pbss_desc A pointer to current BSS descriptor
+ * @return 0 on failure to find OUI, 1 on success.
+ */
+static t_u8 search_oui_in_ie(mlan_adapter *pmadapter, IEBody *ie_body,
+ t_u8 *oui)
+{
+ t_u8 count;
+
+ count = ie_body->PtkCnt[0];
+
+ ENTER();
+ /* 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(pmadapter, ie_body->PtkBody, oui,
+ sizeof(ie_body->PtkBody))) {
+ LEAVE();
+ return MLAN_OUI_PRESENT;
+ }
+
+ --count;
+ if (count) {
+ ie_body = (IEBody *)((t_u8 *)ie_body +
+ sizeof(ie_body->PtkBody));
+ }
+ }
+
+ PRINTM(MINFO, "The OUI %x:%x:%x:%x is not found in PTK\n", oui[0],
+ oui[1], oui[2], oui[3]);
+ LEAVE();
+ return MLAN_OUI_NOT_PRESENT;
+}
+
+/**
+ * @brief This function will pass the correct ie and oui to search_oui_in_ie
+ *
+ * Check the pbss_desc for appropriate IE and then check if RSN IE has AES
+ * OUI in it. If RSN IE does not have AES in PTK then return 0;
+ *
+ * @param pbss_desc A pointer to current BSS descriptor
+ * @return 0 on failure to find AES OUI, 1 on success.
+ */
+static t_u8 is_rsn_oui_present(mlan_adapter *pmadapter,
+ BSSDescriptor_t *pbss_desc, t_u32 cipher_suite)
+{
+ t_u8 *oui = MNULL;
+ IEBody *ie_body = MNULL;
+ t_u8 ret = MLAN_OUI_NOT_PRESENT;
+
+ ENTER();
+ if (pbss_desc->prsn_ie &&
+ (pbss_desc->prsn_ie->ieee_hdr.element_id == RSN_IE) &&
+ (pbss_desc->prsn_ie->ieee_hdr.len > RSN_GTK_OUI_OFFSET)) {
+ ie_body = (IEBody *)(((t_u8 *)pbss_desc->prsn_ie->data) +
+ RSN_GTK_OUI_OFFSET);
+ oui = &rsn_oui[cipher_suite][0];
+ ret = search_oui_in_ie(pmadapter, ie_body, oui);
+ if (ret) {
+ LEAVE();
+ return ret;
+ }
+ }
+ LEAVE();
+ return ret;
+}
+
+/**
+ * @brief This function will pass the correct ie and oui to search_oui_in_ie
+ *
+ * Check the wpa_ie for appropriate IE and then check if RSN IE has AES
+ * OUI in it. If RSN IE does not have AES in PTK then return 0;
+ *
+ * @param pmadapter A pointer to mlan adapter.
+ * @return 0 on failure to find AES OUI, 1 on success.
+ */
+static t_u8 is_rsn_oui_present_in_wpa_ie(mlan_private *pmpriv,
+ t_u32 cipher_suite)
+{
+ mlan_adapter *pmadapter = pmpriv->adapter;
+ t_u8 *oui = MNULL;
+ IEBody *ie_body = MNULL;
+ IEEEtypes_Generic_t *prsn_ie = MNULL;
+ t_u8 ret = MLAN_OUI_NOT_PRESENT;
+
+ ENTER();
+ prsn_ie = (IEEEtypes_Generic_t *)pmpriv->wpa_ie;
+
+ if (prsn_ie && (prsn_ie->ieee_hdr.element_id == RSN_IE) &&
+ (prsn_ie->ieee_hdr.len > RSN_GTK_OUI_OFFSET)) {
+ ie_body = (IEBody *)(prsn_ie->data + RSN_GTK_OUI_OFFSET);
+ oui = &rsn_oui[cipher_suite][0];
+ ret = search_oui_in_ie(pmadapter, ie_body, oui);
+ if (ret) {
+ LEAVE();
+ return ret;
+ }
+ }
+
+ LEAVE();
+ return ret;
+}
+
+/**
+ * @brief This function will pass the correct ie and oui to search_oui_in_ie
+ *
+ * Check the pbss_desc for appropriate IE and then check if WPA IE has AES
+ * OUI in it. If WPA IE does not have AES in PTK then return 0;
+ *
+ * @param pbss_desc A pointer to current BSS descriptor
+ * @return 0 on failure to find AES OUI, 1 on success.
+ */
+static t_u8 is_wpa_oui_present(mlan_adapter *pmadapter,
+ BSSDescriptor_t *pbss_desc, t_u32 cipher_suite)
+{
+ t_u8 *oui = MNULL;
+ IEBody *ie_body = MNULL;
+ t_u8 ret = MLAN_OUI_NOT_PRESENT;
+
+ ENTER();
+ if (((pbss_desc->pwpa_ie) &&
+ ((*(pbss_desc->pwpa_ie)).vend_hdr.element_id == WPA_IE))) {
+ ie_body = (IEBody *)pbss_desc->pwpa_ie->data;
+ oui = &wpa_oui[cipher_suite][0];
+ ret = search_oui_in_ie(pmadapter, ie_body, oui);
+ if (ret) {
+ LEAVE();
+ return ret;
+ }
+ }
+ LEAVE();
+ return ret;
+}
+
+/**
+ * @brief compare config band and a band from the scan result,
+ * which is defined by functiion radio_type_to_band(t_u8 radio_type) above
+ *
+ * @param cfg_band: band configured
+ * scan_band: band from scan result
+ *
+ * @return matched: non-zero. unmatched: 0
+ *
+ */
+static t_u8 wlan_is_band_compatible(t_u8 cfg_band, t_u8 scan_band)
+{
+ t_u8 band;
+ switch (scan_band) {
+ case BAND_A:
+ band = BAND_A | BAND_AN | BAND_AAC;
+ break;
+ case BAND_G:
+ default:
+ band = BAND_B | BAND_G | BAND_GN | BAND_GAC;
+ }
+ return cfg_band & band;
+}
+
+/**
+ * @brief This function finds the best SSID in the Scan List
+ *
+ * Search the scan table for the best SSID that also matches the current
+ * adapter network preference (infrastructure or adhoc)
+ *
+ * @param pmpriv A pointer to mlan_private structure
+ * @return index in BSSID list
+ */
+static t_s32 wlan_find_best_network_in_list(mlan_private *pmpriv)
+{
+ mlan_adapter *pmadapter = pmpriv->adapter;
+ t_u32 mode = pmpriv->bss_mode;
+ t_s32 best_net = -1;
+ t_s32 best_rssi = 0;
+ t_u32 i;
+
+ ENTER();
+
+ PRINTM(MINFO, "Num of BSSIDs = %d\n", pmadapter->num_in_scan_table);
+
+ for (i = 0; i < pmadapter->num_in_scan_table; i++) {
+ switch (mode) {
+ case MLAN_BSS_MODE_INFRA:
+ case MLAN_BSS_MODE_IBSS:
+ if (wlan_is_network_compatible(pmpriv, i, mode) >= 0) {
+ if (SCAN_RSSI(pmadapter->pscan_table[i].rssi) >
+ best_rssi) {
+ best_rssi = SCAN_RSSI(
+ pmadapter->pscan_table[i].rssi);
+ best_net = i;
+ }
+ }
+ break;
+ case MLAN_BSS_MODE_AUTO:
+ default:
+ if (SCAN_RSSI(pmadapter->pscan_table[i].rssi) >
+ best_rssi) {
+ best_rssi = SCAN_RSSI(
+ pmadapter->pscan_table[i].rssi);
+ best_net = i;
+ }
+ break;
+ }
+ }
+
+ LEAVE();
+ return best_net;
+}
+
+/**
+ * @brief Create a channel list for the driver to scan based on region info
+ *
+ * Use the driver region/band information to construct a comprehensive list
+ * of channels to scan. This routine is used for any scan that is not
+ * provided a specific channel list to scan.
+ *
+ * @param pmpriv A pointer to mlan_private structure
+ * @param puser_scan_in MNULL or pointer to scan configuration parameters
+ * @param pscan_chan_list Output parameter: Resulting channel list to scan
+ * @param filtered_scan Flag indicating whether or not a BSSID or SSID
+ * filter is being sent in the command to firmware. Used to increase the number
+ * of channels sent in a scan command and to disable the firmware channel scan
+ * filter.
+ *
+ * @return N/A
+ */
+static t_void wlan_scan_create_channel_list(
+ mlan_private *pmpriv, const wlan_user_scan_cfg *puser_scan_in,
+ ChanScanParamSet_t *pscan_chan_list, t_u8 filtered_scan)
+{
+ mlan_adapter *pmadapter = pmpriv->adapter;
+ region_chan_t *pscan_region;
+ chan_freq_power_t *cfp;
+ t_u32 region_idx;
+ t_u32 chan_idx = 0;
+ t_u32 next_chan;
+ t_u8 scan_type;
+ t_u8 radio_type;
+ t_u8 band;
+ t_u16 scan_dur = 0;
+
+ ENTER();
+
+ for (region_idx = 0; region_idx < NELEMENTS(pmadapter->region_channel);
+ region_idx++) {
+ if (wlan_11d_is_enabled(pmpriv) &&
+ pmpriv->media_connected != MTRUE) {
+ /* Scan all the supported chan for the first scan */
+ if (!pmadapter->universal_channel[region_idx].valid)
+ continue;
+ pscan_region =
+ &pmadapter->universal_channel[region_idx];
+ } else {
+ if (!pmadapter->region_channel[region_idx].valid)
+ continue;
+ pscan_region = &pmadapter->region_channel[region_idx];
+ }
+
+ if (puser_scan_in && !puser_scan_in->chan_list[0].chan_number &&
+ puser_scan_in->chan_list[0].radio_type & BAND_SPECIFIED) {
+ radio_type = puser_scan_in->chan_list[0].radio_type &
+ ~BAND_SPECIFIED;
+ if (!radio_type && (pscan_region->band != BAND_B) &&
+ (pscan_region->band != BAND_G))
+ continue;
+ if (radio_type && (pscan_region->band != BAND_A))
+ continue;
+ }
+ if ((puser_scan_in &&
+ (puser_scan_in->bss_mode == MLAN_SCAN_MODE_IBSS)) ||
+ pmpriv->bss_mode == MLAN_BSS_MODE_IBSS)
+ band = pmadapter->adhoc_start_band;
+ else
+ band = pmpriv->config_bands;
+ if (!wlan_is_band_compatible(band, pscan_region->band))
+ continue;
+ for (next_chan = 0; next_chan < pscan_region->num_cfp;
+ next_chan++) {
+ /* Set the default scan type to the user specified type,
+ * will later be changed to passive on a per channel
+ * basis if restricted by regulatory requirements (11d
+ * or 11h)
+ */
+ scan_type = pmadapter->scan_type;
+ cfp = pscan_region->pcfp + next_chan;
+ if (cfp->dynamic.flags & NXP_CHANNEL_DISABLED)
+ continue;
+
+ if (wlan_is_chan_passive(pmpriv, pscan_region->band,
+ (t_u8)cfp->channel)) {
+ /* do not send probe requests on this channel */
+ scan_type = MLAN_SCAN_TYPE_PASSIVE;
+ }
+ switch (pscan_region->band) {
+ case BAND_A:
+ pscan_chan_list[chan_idx].bandcfg.chanBand =
+ BAND_5GHZ;
+ /* Passive scan on DFS channels */
+ if (wlan_11h_radar_detect_required(
+ pmpriv, (t_u8)cfp->channel) &&
+ scan_type != MLAN_SCAN_TYPE_PASSIVE)
+ scan_type =
+ MLAN_SCAN_TYPE_PASSIVE_TO_ACTIVE;
+ break;
+ case BAND_B:
+ case BAND_G:
+ if (wlan_bg_scan_type_is_passive(
+ pmpriv, (t_u8)cfp->channel)) {
+ scan_type = MLAN_SCAN_TYPE_PASSIVE;
+ }
+ pscan_chan_list[chan_idx].bandcfg.chanBand =
+ BAND_2GHZ;
+ break;
+ default:
+ pscan_chan_list[chan_idx].bandcfg.chanBand =
+ BAND_2GHZ;
+ break;
+ }
+
+ if (puser_scan_in &&
+ puser_scan_in->chan_list[0].scan_time) {
+ scan_dur = (t_u16)puser_scan_in->chan_list[0]
+ .scan_time;
+ } else if (scan_type == MLAN_SCAN_TYPE_PASSIVE ||
+ scan_type ==
+ MLAN_SCAN_TYPE_PASSIVE_TO_ACTIVE) {
+ scan_dur = pmadapter->passive_scan_time;
+ } else if (filtered_scan) {
+ scan_dur = pmadapter->specific_scan_time;
+ } else {
+ scan_dur = pmadapter->active_scan_time;
+ }
+ if (scan_type == MLAN_SCAN_TYPE_PASSIVE_TO_ACTIVE &&
+ pmadapter->passive_to_active_scan ==
+ MLAN_PASS_TO_ACT_SCAN_EN) {
+ scan_dur = MAX(scan_dur,
+ MIN_PASSIVE_TO_ACTIVE_SCAN_TIME);
+ pscan_chan_list[chan_idx]
+ .chan_scan_mode.passive_to_active_scan =
+ MTRUE;
+ }
+ pscan_chan_list[chan_idx].max_scan_time =
+ wlan_cpu_to_le16(scan_dur);
+
+ if (scan_type == MLAN_SCAN_TYPE_PASSIVE ||
+ scan_type == MLAN_SCAN_TYPE_PASSIVE_TO_ACTIVE) {
+ pscan_chan_list[chan_idx]
+ .chan_scan_mode.passive_scan = MTRUE;
+ pscan_chan_list[chan_idx]
+ .chan_scan_mode.hidden_ssid_report =
+ MTRUE;
+ } else {
+ pscan_chan_list[chan_idx]
+ .chan_scan_mode.passive_scan = MFALSE;
+ }
+
+ pscan_chan_list[chan_idx].chan_number =
+ (t_u8)cfp->channel;
+ PRINTM(MINFO,
+ "chan=%d, mode=%d, passive_to_active=%d\n",
+ pscan_chan_list[chan_idx].chan_number,
+ pscan_chan_list[chan_idx]
+ .chan_scan_mode.passive_scan,
+ pscan_chan_list[chan_idx]
+ .chan_scan_mode.passive_to_active_scan);
+ chan_idx++;
+ }
+ }
+
+ LEAVE();
+}
+
+/**
+ * @brief Add WPS IE to probe request frame
+ *
+ * @param pmpriv A pointer to mlan_private structure
+ * @param pptlv_out A pointer to TLV to fill in
+ *
+ * @return N/A
+ */
+static void wlan_add_wps_probe_request_ie(mlan_private *pmpriv,
+ t_u8 **pptlv_out)
+{
+ MrvlIEtypesHeader_t *tlv;
+
+ ENTER();
+
+ if (pmpriv->wps.wps_ie.vend_hdr.len) {
+ tlv = (MrvlIEtypesHeader_t *)*pptlv_out;
+ tlv->type = wlan_cpu_to_le16(VENDOR_SPECIFIC_221);
+ tlv->len = wlan_cpu_to_le16(pmpriv->wps.wps_ie.vend_hdr.len);
+ *pptlv_out += sizeof(MrvlIEtypesHeader_t);
+ memcpy_ext(pmpriv->adapter, *pptlv_out,
+ pmpriv->wps.wps_ie.vend_hdr.oui,
+ pmpriv->wps.wps_ie.vend_hdr.len,
+ pmpriv->wps.wps_ie.vend_hdr.len);
+ *pptlv_out += (pmpriv->wps.wps_ie.vend_hdr.len +
+ sizeof(MrvlIEtypesHeader_t));
+ }
+ LEAVE();
+}
+
+/**
+ * @brief Construct and send multiple scan config commands to the firmware
+ *
+ * Previous routines have created a wlan_scan_cmd_config with any requested
+ * TLVs. This function splits the channel TLV into max_chan_per_scan lists
+ * and sends the portion of the channel TLV along with the other TLVs
+ * to the wlan_cmd routines for execution in the firmware.
+ *
+ * @param pmpriv A pointer to mlan_private structure
+ * @param pioctl_buf A pointer to MLAN IOCTL Request buffer
+ * @param max_chan_per_scan Maximum number channels to be included in each
+ * scan command sent to firmware
+ * @param filtered_scan Flag indicating whether or not a BSSID or SSID
+ * filter is being used for the firmware command
+ * scan command sent to firmware
+ * @param pscan_cfg_out Scan configuration used for this scan.
+ * @param pchan_tlv_out Pointer in the pscan_cfg_out where the channel TLV
+ * should start. This is past any other TLVs that
+ * must be sent down in each firmware command.
+ * @param pscan_chan_list List of channels to scan in max_chan_per_scan
+ * segments
+ *
+ * @return MLAN_STATUS_SUCCESS or error return otherwise
+ */
+static mlan_status
+wlan_scan_channel_list(mlan_private *pmpriv, t_void *pioctl_buf,
+ t_u32 max_chan_per_scan, t_u8 filtered_scan,
+ wlan_scan_cmd_config *pscan_cfg_out,
+ MrvlIEtypes_ChanListParamSet_t *pchan_tlv_out,
+ ChanScanParamSet_t *pscan_chan_list)
+{
+ mlan_status ret = MLAN_STATUS_SUCCESS;
+ mlan_adapter *pmadapter = pmpriv->adapter;
+ ChanScanParamSet_t *ptmp_chan_list;
+ ChanScanParamSet_t *pstart_chan;
+ pmlan_ioctl_req pioctl_req = (mlan_ioctl_req *)pioctl_buf;
+ t_u8 *pchan_tlv_out_temp = MNULL;
+ t_u8 *ptlv_temp = MNULL;
+ t_bool foundJPch14 = MFALSE;
+ t_u16 tlv_buf_len = 0;
+ t_u32 tlv_idx;
+ t_u32 total_scan_time;
+ t_u32 done_early;
+ t_u32 cmd_no;
+ t_u32 first_chan = 1;
+ mlan_callbacks *pcb = (mlan_callbacks *)&pmadapter->callbacks;
+
+ ENTER();
+
+ if (!pscan_cfg_out || !pchan_tlv_out || !pscan_chan_list) {
+ PRINTM(MINFO, "Scan: Null detect: %p, %p, %p\n", pscan_cfg_out,
+ pchan_tlv_out, pscan_chan_list);
+ if (pioctl_req)
+ pioctl_req->status_code = MLAN_ERROR_CMD_SCAN_FAIL;
+ LEAVE();
+ return MLAN_STATUS_FAILURE;
+ }
+ if (!pscan_chan_list->chan_number) {
+ PRINTM(MERROR, "Scan: No channel configured\n");
+ if (pioctl_req)
+ pioctl_req->status_code = MLAN_ERROR_CMD_SCAN_FAIL;
+ LEAVE();
+ return MLAN_STATUS_FAILURE;
+ }
+
+ /* check expiry before preparing scan list - may affect blacklist */
+ wlan_11h_get_csa_closed_channel(pmpriv);
+
+ pchan_tlv_out->header.type = wlan_cpu_to_le16(TLV_TYPE_CHANLIST);
+
+ /* Set the temp channel struct pointer to the start of the desired list
+ */
+ ptmp_chan_list = pscan_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 (ptmp_chan_list->chan_number) {
+ tlv_idx = 0;
+ total_scan_time = 0;
+ pchan_tlv_out->header.len = 0;
+ pstart_chan = ptmp_chan_list;
+ done_early = MFALSE;
+
+ /*
+ * 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 &&
+ ptmp_chan_list->chan_number && !done_early) {
+ if (wlan_is_chan_blacklisted(
+ pmpriv,
+ radio_type_to_band(
+ ptmp_chan_list->bandcfg.chanBand),
+ ptmp_chan_list->chan_number) ||
+ wlan_is_chan_disabled(
+ pmpriv,
+ radio_type_to_band(
+ ptmp_chan_list->bandcfg.chanBand),
+ ptmp_chan_list->chan_number)) {
+ ptmp_chan_list++;
+ continue;
+ }
+
+ if (first_chan) {
+ ptmp_chan_list->chan_scan_mode.first_chan =
+ MTRUE;
+ first_chan = 0;
+ }
+
+ PRINTM(MINFO,
+ "Scan: Chan(%3d), bandcfg(%x), Mode(%d,%d), Dur(%d)\n",
+ ptmp_chan_list->chan_number,
+ ptmp_chan_list->bandcfg,
+ ptmp_chan_list->chan_scan_mode.passive_scan,
+ ptmp_chan_list->chan_scan_mode.disable_chan_filt,
+ wlan_le16_to_cpu(ptmp_chan_list->max_scan_time));
+
+ if (foundJPch14 == MTRUE) {
+ foundJPch14 = MFALSE;
+ /* Restore the TLV buffer */
+ pchan_tlv_out =
+ (MrvlIEtypes_ChanListParamSet_t *)
+ pchan_tlv_out_temp;
+ pchan_tlv_out->header.type =
+ wlan_cpu_to_le16(TLV_TYPE_CHANLIST);
+ pchan_tlv_out->header.len = 0;
+ if (ptlv_temp) {
+ memcpy_ext(pmadapter,
+ pscan_cfg_out->tlv_buf,
+ ptlv_temp, tlv_buf_len,
+ tlv_buf_len);
+ pcb->moal_mfree(pmadapter->pmoal_handle,
+ ptlv_temp);
+ ptlv_temp = MNULL;
+ }
+ }
+
+ /* Special Case: For Japan, Scan on CH14 for 11G rates
+ is not allowed
+ Hence Rates TLV needs to be updated to support only
+ 11B rates */
+ if ((pmadapter->region_code == COUNTRY_CODE_JP_40 ||
+ pmadapter->region_code == COUNTRY_CODE_JP_FF) &&
+ (ptmp_chan_list->chan_number == 14) &&
+ (pmadapter->ext_scan_type != EXT_SCAN_ENHANCE)) {
+ t_u8 *ptlv_pos = pscan_cfg_out->tlv_buf;
+ t_u16 old_ratetlv_len, new_ratetlv_len;
+ MrvlIEtypesHeader_t *header;
+ MrvlIEtypes_RatesParamSet_t *prates_tlv;
+
+ /* Preserve the current TLV buffer */
+ ret = pcb->moal_malloc(
+ pmadapter->pmoal_handle,
+ MAX_SCAN_CFG_ALLOC - CHAN_TLV_MAX_SIZE,
+ MLAN_MEM_DEF, (t_u8 **)&ptlv_temp);
+ if (ret != MLAN_STATUS_SUCCESS || !ptlv_temp) {
+ PRINTM(MERROR,
+ "Memory allocation for pscan_cfg_out failed!\n");
+ if (pioctl_req)
+ pioctl_req->status_code =
+ MLAN_ERROR_NO_MEM;
+ LEAVE();
+ return MLAN_STATUS_FAILURE;
+ }
+ pchan_tlv_out_temp = (t_u8 *)pchan_tlv_out;
+ tlv_buf_len = (t_u32)(pchan_tlv_out_temp -
+ pscan_cfg_out->tlv_buf);
+ memcpy_ext(pmadapter, ptlv_temp, ptlv_pos,
+ tlv_buf_len,
+ MAX_SCAN_CFG_ALLOC -
+ CHAN_TLV_MAX_SIZE);
+
+ /* Search for Rates TLV */
+ while ((!foundJPch14) &&
+ (ptlv_pos < pchan_tlv_out_temp)) {
+ header =
+ (MrvlIEtypesHeader_t *)ptlv_pos;
+ if (header->type ==
+ wlan_cpu_to_le16(TLV_TYPE_RATES))
+ foundJPch14 = MTRUE;
+ else
+ ptlv_pos +=
+ (sizeof(MrvlIEtypesHeader_t) +
+ wlan_le16_to_cpu(
+ header->len));
+ }
+
+ if (foundJPch14) {
+ /* Update the TLV buffer with *new*
+ * Rates TLV and rearrange remaining TLV
+ * buffer*/
+ prates_tlv =
+ (MrvlIEtypes_RatesParamSet_t *)
+ ptlv_pos;
+ old_ratetlv_len =
+ sizeof(MrvlIEtypesHeader_t) +
+ wlan_le16_to_cpu(
+ prates_tlv->header.len);
+
+ prates_tlv->header.len = wlan_copy_rates(
+ prates_tlv->rates, 0,
+ SupportedRates_B,
+ sizeof(SupportedRates_B));
+ new_ratetlv_len =
+ sizeof(MrvlIEtypesHeader_t) +
+ prates_tlv->header.len;
+ prates_tlv->header.len =
+ wlan_cpu_to_le16(
+ prates_tlv->header.len);
+
+ memmove(pmadapter,
+ ptlv_pos + new_ratetlv_len,
+ ptlv_pos + old_ratetlv_len,
+ (t_u32)(pchan_tlv_out_temp -
+ (ptlv_pos +
+ old_ratetlv_len)));
+ pchan_tlv_out =
+ (MrvlIEtypes_ChanListParamSet_t
+ *)(pchan_tlv_out_temp -
+ (old_ratetlv_len -
+ new_ratetlv_len));
+ pchan_tlv_out->header.type =
+ wlan_cpu_to_le16(
+ TLV_TYPE_CHANLIST);
+ pchan_tlv_out->header.len = 0;
+ }
+ }
+
+ /* Copy the current channel TLV to the command being
+ * prepared */
+ memcpy_ext(pmadapter,
+ pchan_tlv_out->chan_scan_param + tlv_idx,
+ ptmp_chan_list,
+ sizeof(pchan_tlv_out->chan_scan_param),
+ sizeof(pchan_tlv_out->chan_scan_param));
+
+ /* Increment the TLV header length by the size appended
+ */
+ pchan_tlv_out->header.len +=
+ sizeof(pchan_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.
+ */
+ pscan_cfg_out->tlv_buf_len = (t_u32)(
+ (t_u8 *)pchan_tlv_out - pscan_cfg_out->tlv_buf);
+
+ /* Add the size of the channel tlv header and the data
+ * length */
+ pscan_cfg_out->tlv_buf_len +=
+ (sizeof(pchan_tlv_out->header) +
+ pchan_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 +=
+ wlan_le16_to_cpu(ptmp_chan_list->max_scan_time);
+
+ done_early = MFALSE;
+
+ /*
+ * 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 &&
+ (ptmp_chan_list->chan_number == 1 ||
+ ptmp_chan_list->chan_number == 6 ||
+ ptmp_chan_list->chan_number == 11)) {
+ done_early = MTRUE;
+ }
+
+ /*
+ * Stop the loop if the *current* channel is 14
+ * and region code is Japan (0x40 or 0xFF)
+ */
+ if ((pmadapter->region_code == COUNTRY_CODE_JP_40 ||
+ pmadapter->region_code == COUNTRY_CODE_JP_FF) &&
+ (ptmp_chan_list->chan_number == 14)) {
+ done_early = MTRUE;
+ }
+
+ /* Increment the tmp pointer to the next channel to be
+ * scanned */
+ ptmp_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 &&
+ (ptmp_chan_list->chan_number == 1 ||
+ ptmp_chan_list->chan_number == 6 ||
+ ptmp_chan_list->chan_number == 11)) {
+ done_early = MTRUE;
+ }
+
+ /*
+ * Stop the loop if the *next* channel is 14
+ * and region code is Japan (0x40 or 0xFF)
+ */
+ if ((pmadapter->region_code == COUNTRY_CODE_JP_40 ||
+ pmadapter->region_code == COUNTRY_CODE_JP_FF) &&
+ (ptmp_chan_list->chan_number == 14)) {
+ done_early = MTRUE;
+ }
+ if (pmadapter->ext_scan && pmadapter->ext_scan_enh &&
+ pmadapter->ext_scan_type == EXT_SCAN_ENHANCE)
+ done_early = MFALSE;
+ }
+
+ /* The total scan time should be less than scan command timeout
+ * value */
+ if (total_scan_time > MRVDRV_MAX_TOTAL_SCAN_TIME) {
+ PRINTM(MMSG,
+ "Total scan time %d ms is over limit (%d ms), scan skipped\n",
+ total_scan_time, MRVDRV_MAX_TOTAL_SCAN_TIME);
+ if (pioctl_req)
+ pioctl_req->status_code =
+ MLAN_ERROR_CMD_SCAN_FAIL;
+ ret = MLAN_STATUS_FAILURE;
+ break;
+ }
+
+ pchan_tlv_out->header.len =
+ wlan_cpu_to_le16(pchan_tlv_out->header.len);
+
+ pmadapter->pscan_channels = pstart_chan;
+
+ /* Send the scan command to the firmware with the specified cfg
+ */
+ if (pmadapter->ext_scan)
+ cmd_no = HostCmd_CMD_802_11_SCAN_EXT;
+ else
+ cmd_no = HostCmd_CMD_802_11_SCAN;
+ ret = wlan_prepare_cmd(pmpriv, cmd_no, HostCmd_ACT_GEN_SET, 0,
+ MNULL, pscan_cfg_out);
+ if (ret)
+ break;
+ }
+
+ LEAVE();
+
+ if (ptlv_temp)
+ pcb->moal_mfree(pmadapter->pmoal_handle, ptlv_temp);
+
+ if (ret)
+ return MLAN_STATUS_FAILURE;
+
+ return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ * @brief Construct a wlan_scan_cmd_config structure to use in scan commands
+ *
+ * Application layer or other functions can invoke wlan_scan_networks
+ * with a scan configuration supplied in a wlan_ioctl_user_scan_cfg struct.
+ * This structure is used as the basis of one or many wlan_scan_cmd_config
+ * commands that are sent to the command processing module and sent to
+ * firmware.
+ *
+ * Create a wlan_scan_cmd_config 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, disable/clear the filter.
+ * If the number of probes is not set, use the adapter default setting
+ * Qualify the channel
+ *
+ * @param pmpriv A pointer to mlan_private structure
+ * @param puser_scan_in MNULL or pointer to scan config parameters
+ * @param pscan_cfg_out Output parameter: Resulting scan configuration
+ * @param ppchan_list_out Output parameter: Pointer to the start of the
+ * channel TLV portion of the output scan config
+ * @param pscan_chan_list Output parameter: Pointer to the resulting
+ * channel list to scan
+ * @param pmax_chan_per_scan Output parameter: Number of channels to scan for
+ * each issuance of the firmware scan command
+ * @param pfiltered_scan Output parameter: Flag indicating whether or not
+ * a BSSID or SSID filter is being sent in the
+ * command to firmware. Used to increase the number
+ * of channels sent in a scan command and to
+ * disable the firmware channel scan filter.
+ * @param pscan_current_only Output parameter: Flag indicating whether or not
+ * we are only scanning our current active channel
+ *
+ * @return MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ */
+static mlan_status wlan_scan_setup_scan_config(
+ mlan_private *pmpriv, wlan_user_scan_cfg *puser_scan_in,
+ wlan_scan_cmd_config *pscan_cfg_out,
+ MrvlIEtypes_ChanListParamSet_t **ppchan_list_out,
+ ChanScanParamSet_t *pscan_chan_list, t_u8 *pmax_chan_per_scan,
+ t_u8 *pfiltered_scan, t_u8 *pscan_current_only)
+{
+ mlan_adapter *pmadapter = pmpriv->adapter;
+ mlan_status ret = MLAN_STATUS_SUCCESS;
+ MrvlIEtypes_NumProbes_t *pnum_probes_tlv;
+ MrvlIEtypes_WildCardSsIdParamSet_t *pwildcard_ssid_tlv;
+ MrvlIEtypes_RatesParamSet_t *prates_tlv;
+ MrvlIEtypes_Bssid_List_t *pbssid_tlv;
+
+ const t_u8 zero_mac[MLAN_MAC_ADDR_LENGTH] = {0, 0, 0, 0, 0, 0};
+ t_u8 *ptlv_pos;
+ t_u32 num_probes;
+ t_u32 ssid_len;
+ t_u32 chan_idx;
+ t_u32 chan_list_idx = 0;
+ t_u32 scan_type;
+ t_u16 scan_dur;
+ t_u8 channel;
+ t_u8 radio_type;
+ t_u32 ssid_idx;
+ t_u8 ssid_filter;
+ WLAN_802_11_RATES rates;
+ t_u32 rates_size;
+ MrvlIETypes_HTCap_t *pht_cap;
+
+ MrvlIETypes_VHTCap_t *pvht_cap;
+ MrvlIEtypes_ScanChanGap_t *pscan_gap_tlv;
+ MrvlIEtypes_BssMode_t *pbss_mode;
+ MrvlIEtypes_Extension_t *phe_cap;
+ t_u16 len = 0;
+
+ ENTER();
+
+ /* 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 *ppchan_list_out. The
+ * difference between the *ppchan_list_out and the tlv_buf start will
+ * be used to calculate the size of anything we add in this routine.
+ */
+ pscan_cfg_out->tlv_buf_len = 0;
+
+ /* Running tlv pointer. Assigned to ppchan_list_out at end of function
+ * so later routines know where channels can be added to the command
+ * buf
+ */
+ ptlv_pos = pscan_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
+ */
+ *pfiltered_scan = MFALSE;
+
+ /* 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.
+ */
+ *pscan_current_only = MFALSE;
+
+ if (puser_scan_in) {
+ ssid_filter = MFALSE;
+
+ /* Set the bss type scan filter, use Adapter setting if unset */
+ pscan_cfg_out->bss_mode =
+ (puser_scan_in->bss_mode ?
+ (t_u8)puser_scan_in->bss_mode :
+ (t_u8)pmadapter->scan_mode);
+
+ /* Set the number of probes to send, use Adapter setting if
+ * unset */
+ num_probes =
+ (puser_scan_in->num_probes ? puser_scan_in->num_probes :
+ pmadapter->scan_probes);
+ /*
+ * Set the BSSID filter to the incoming configuration,
+ * if non-zero. If not set, it will remain disabled
+ * (all zeros).
+ */
+ memcpy_ext(pmadapter, pscan_cfg_out->specific_bssid,
+ puser_scan_in->specific_bssid,
+ sizeof(pscan_cfg_out->specific_bssid),
+ sizeof(pscan_cfg_out->specific_bssid));
+
+ if (pmadapter->ext_scan) {
+ if (puser_scan_in->bssid_num) {
+ pbssid_tlv =
+ (MrvlIEtypes_Bssid_List_t *)ptlv_pos;
+ pbssid_tlv->header.type = TLV_TYPE_BSSID;
+ pbssid_tlv->header.len = wlan_cpu_to_le16(
+ MLAN_MAC_ADDR_LENGTH *
+ puser_scan_in->bssid_num);
+ memcpy_ext(pmadapter, pbssid_tlv->bssid,
+ puser_scan_in->bssid_list,
+ MLAN_MAC_ADDR_LENGTH *
+ puser_scan_in->bssid_num,
+ MLAN_MAC_ADDR_LENGTH *
+ puser_scan_in->bssid_num);
+ ptlv_pos += sizeof(MrvlIEtypesHeader_t) +
+ MLAN_MAC_ADDR_LENGTH *
+ puser_scan_in->bssid_num;
+ DBG_HEXDUMP(
+ MCMD_D, "scan bssid filter", pbssid_tlv,
+ sizeof(MrvlIEtypesHeader_t) +
+ MLAN_MAC_ADDR_LENGTH *
+ puser_scan_in
+ ->bssid_num);
+ } else if (memcmp(pmadapter,
+ pscan_cfg_out->specific_bssid,
+ &zero_mac, sizeof(zero_mac))) {
+ pbssid_tlv =
+ (MrvlIEtypes_Bssid_List_t *)ptlv_pos;
+ pbssid_tlv->header.type = TLV_TYPE_BSSID;
+ pbssid_tlv->header.len =
+ wlan_cpu_to_le16(MLAN_MAC_ADDR_LENGTH);
+ memcpy_ext(pmadapter, pbssid_tlv->bssid,
+ puser_scan_in->specific_bssid,
+ MLAN_MAC_ADDR_LENGTH,
+ MLAN_MAC_ADDR_LENGTH);
+ ptlv_pos += sizeof(MrvlIEtypes_Bssid_List_t);
+ }
+ }
+
+ for (ssid_idx = 0;
+ ((ssid_idx < NELEMENTS(puser_scan_in->ssid_list)) &&
+ (*puser_scan_in->ssid_list[ssid_idx].ssid ||
+ puser_scan_in->ssid_list[ssid_idx].max_len));
+ ssid_idx++) {
+ ssid_len = wlan_strlen(
+ (char *)puser_scan_in->ssid_list[ssid_idx].ssid);
+
+ pwildcard_ssid_tlv =
+ (MrvlIEtypes_WildCardSsIdParamSet_t *)ptlv_pos;
+ pwildcard_ssid_tlv->header.type =
+ wlan_cpu_to_le16(TLV_TYPE_WILDCARDSSID);
+ pwildcard_ssid_tlv->header.len = (t_u16)(
+ ssid_len +
+ sizeof(pwildcard_ssid_tlv->max_ssid_length));
+ pwildcard_ssid_tlv->max_ssid_length =
+ puser_scan_in->ssid_list[ssid_idx].max_len;
+
+ memcpy_ext(pmadapter, pwildcard_ssid_tlv->ssid,
+ puser_scan_in->ssid_list[ssid_idx].ssid,
+ ssid_len, MLAN_MAX_SSID_LENGTH);
+
+ ptlv_pos += (sizeof(pwildcard_ssid_tlv->header) +
+ pwildcard_ssid_tlv->header.len);
+
+ pwildcard_ssid_tlv->header.len = wlan_cpu_to_le16(
+ pwildcard_ssid_tlv->header.len);
+
+ PRINTM(MINFO, "Scan: ssid_list[%d]: %s, %d\n", ssid_idx,
+ pwildcard_ssid_tlv->ssid,
+ pwildcard_ssid_tlv->max_ssid_length);
+
+ if (ssid_len) {
+ ssid_filter = MTRUE;
+ if (!puser_scan_in->ssid_list[ssid_idx].max_len) {
+ PRINTM(MCMND, "user scan: %s\n",
+ pwildcard_ssid_tlv->ssid);
+ puser_scan_in->ssid_filter = MTRUE;
+ }
+ }
+ }
+
+ /*
+ * 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 ((ssid_idx && ssid_filter) ||
+ memcmp(pmadapter, pscan_cfg_out->specific_bssid, &zero_mac,
+ sizeof(zero_mac))) {
+ *pfiltered_scan = MTRUE;
+ }
+
+ } else {
+ pscan_cfg_out->bss_mode = (t_u8)pmadapter->scan_mode;
+ num_probes = pmadapter->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 (*pfiltered_scan)
+ *pmax_chan_per_scan = MRVDRV_MAX_CHANNELS_PER_SPECIFIC_SCAN;
+ else
+ *pmax_chan_per_scan = MRVDRV_CHANNELS_PER_SCAN_CMD;
+
+ if (puser_scan_in) {
+ if (puser_scan_in->scan_chan_gap) {
+ *pmax_chan_per_scan =
+ MRVDRV_MAX_CHANNELS_PER_SPECIFIC_SCAN;
+ PRINTM(MCMND, "Scan: channel gap = 0x%x\n",
+ puser_scan_in->scan_chan_gap);
+ pscan_gap_tlv = (MrvlIEtypes_ScanChanGap_t *)ptlv_pos;
+ pscan_gap_tlv->header.type =
+ wlan_cpu_to_le16(TLV_TYPE_SCAN_CHANNEL_GAP);
+ pscan_gap_tlv->header.len = sizeof(pscan_gap_tlv->gap);
+ pscan_gap_tlv->gap = wlan_cpu_to_le16(
+ (t_u16)puser_scan_in->scan_chan_gap);
+ ptlv_pos += sizeof(pscan_gap_tlv->header) +
+ pscan_gap_tlv->header.len;
+ pscan_gap_tlv->header.len =
+ wlan_cpu_to_le16(pscan_gap_tlv->header.len);
+ }
+ } else if (pmadapter->scan_chan_gap) {
+ *pmax_chan_per_scan = MRVDRV_MAX_CHANNELS_PER_SPECIFIC_SCAN;
+ PRINTM(MCMND, "Scan: channel gap = 0x%x\n",
+ pmadapter->scan_chan_gap);
+ pscan_gap_tlv = (MrvlIEtypes_ScanChanGap_t *)ptlv_pos;
+ pscan_gap_tlv->header.type =
+ wlan_cpu_to_le16(TLV_TYPE_SCAN_CHANNEL_GAP);
+ pscan_gap_tlv->header.len = sizeof(pscan_gap_tlv->gap);
+ pscan_gap_tlv->gap =
+ wlan_cpu_to_le16((t_u16)pmadapter->scan_chan_gap);
+ ptlv_pos += sizeof(pscan_gap_tlv->header) +
+ pscan_gap_tlv->header.len;
+ }
+ if (pmadapter->ext_scan) {
+ pbss_mode = (MrvlIEtypes_BssMode_t *)ptlv_pos;
+ pbss_mode->header.type = wlan_cpu_to_le16(TLV_TYPE_BSS_MODE);
+ pbss_mode->header.len = sizeof(pbss_mode->bss_mode);
+ pbss_mode->bss_mode = pscan_cfg_out->bss_mode;
+ ptlv_pos += sizeof(pbss_mode->header) + pbss_mode->header.len;
+ pbss_mode->header.len = wlan_cpu_to_le16(pbss_mode->header.len);
+ if (pmadapter->ext_scan_enh) {
+ if (puser_scan_in) {
+ if (puser_scan_in->ext_scan_type ==
+ EXT_SCAN_ENHANCE)
+ pmadapter->ext_scan_type =
+ EXT_SCAN_ENHANCE;
+ else
+ pmadapter->ext_scan_type =
+ EXT_SCAN_DEFAULT;
+ } else if (pmadapter->ext_scan == EXT_SCAN_TYPE_ENH)
+ pmadapter->ext_scan_type = EXT_SCAN_ENHANCE;
+ else
+ pmadapter->ext_scan_type = EXT_SCAN_DEFAULT;
+ if (pmadapter->ext_scan_type == EXT_SCAN_ENHANCE)
+ *pmax_chan_per_scan =
+ MRVDRV_MAX_CHANNELS_PER_SCAN;
+ }
+ }
+ /* If the input config or adapter has the number of Probes set, add tlv
+ */
+ if (num_probes) {
+ PRINTM(MINFO, "Scan: num_probes = %d\n", num_probes);
+
+ pnum_probes_tlv = (MrvlIEtypes_NumProbes_t *)ptlv_pos;
+ pnum_probes_tlv->header.type =
+ wlan_cpu_to_le16(TLV_TYPE_NUMPROBES);
+ pnum_probes_tlv->header.len =
+ sizeof(pnum_probes_tlv->num_probes);
+ pnum_probes_tlv->num_probes =
+ wlan_cpu_to_le16((t_u16)num_probes);
+
+ ptlv_pos += sizeof(pnum_probes_tlv->header) +
+ pnum_probes_tlv->header.len;
+
+ pnum_probes_tlv->header.len =
+ wlan_cpu_to_le16(pnum_probes_tlv->header.len);
+ }
+
+ /* Append rates tlv */
+ memset(pmadapter, rates, 0, sizeof(rates));
+
+ rates_size = wlan_get_supported_rates(
+ pmpriv, pmpriv->bss_mode,
+ (pmpriv->bss_mode == MLAN_BSS_MODE_INFRA) ?
+ pmpriv->config_bands :
+ pmadapter->adhoc_start_band,
+ rates);
+
+ prates_tlv = (MrvlIEtypes_RatesParamSet_t *)ptlv_pos;
+ prates_tlv->header.type = wlan_cpu_to_le16(TLV_TYPE_RATES);
+ prates_tlv->header.len = wlan_cpu_to_le16((t_u16)rates_size);
+ memcpy_ext(pmadapter, prates_tlv->rates, rates, rates_size, rates_size);
+ ptlv_pos += sizeof(prates_tlv->header) + rates_size;
+
+ PRINTM(MINFO, "SCAN_CMD: Rates size = %d\n", rates_size);
+
+ if (ISSUPP_11NENABLED(pmpriv->adapter->fw_cap_info) &&
+ (pmpriv->config_bands & BAND_GN ||
+ pmpriv->config_bands & BAND_AN)) {
+ pht_cap = (MrvlIETypes_HTCap_t *)ptlv_pos;
+ memset(pmadapter, pht_cap, 0, sizeof(MrvlIETypes_HTCap_t));
+ pht_cap->header.type = wlan_cpu_to_le16(HT_CAPABILITY);
+ pht_cap->header.len = sizeof(HTCap_t);
+ wlan_fill_ht_cap_tlv(pmpriv, pht_cap, pmpriv->config_bands,
+ MTRUE);
+ HEXDUMP("SCAN: HT_CAPABILITIES IE", (t_u8 *)pht_cap,
+ sizeof(MrvlIETypes_HTCap_t));
+ ptlv_pos += sizeof(MrvlIETypes_HTCap_t);
+ pht_cap->header.len = wlan_cpu_to_le16(pht_cap->header.len);
+ }
+
+ if (ISSUPP_11ACENABLED(pmpriv->adapter->fw_cap_info) &&
+ (pmpriv->config_bands & BAND_AAC)) {
+ pvht_cap = (MrvlIETypes_VHTCap_t *)ptlv_pos;
+ memset(pmadapter, pvht_cap, 0, sizeof(MrvlIETypes_VHTCap_t));
+ pvht_cap->header.type = wlan_cpu_to_le16(VHT_CAPABILITY);
+ pvht_cap->header.len = sizeof(VHT_capa_t);
+ wlan_fill_vht_cap_tlv(pmpriv, pvht_cap, pmpriv->config_bands,
+ MFALSE, MFALSE);
+ HEXDUMP("SCAN: VHT_CAPABILITIES IE", (t_u8 *)pvht_cap,
+ sizeof(MrvlIETypes_VHTCap_t));
+ ptlv_pos += sizeof(MrvlIETypes_VHTCap_t);
+ pvht_cap->header.len = wlan_cpu_to_le16(pvht_cap->header.len);
+ }
+
+ if (IS_FW_SUPPORT_11AX(pmadapter) &&
+ (pmpriv->config_bands & BAND_AAX)) {
+ phe_cap = (MrvlIEtypes_Extension_t *)ptlv_pos;
+ len = wlan_fill_he_cap_tlv(pmpriv, BAND_A, phe_cap, MFALSE);
+ HEXDUMP("SCAN: HE_CAPABILITIES IE", (t_u8 *)phe_cap, len);
+ ptlv_pos += len;
+ }
+
+ if (wlan_is_ext_capa_support(pmpriv))
+ wlan_add_ext_capa_info_ie(pmpriv, MNULL, &ptlv_pos);
+ if (pmpriv->adapter->ecsa_enable) {
+ t_u8 bandwidth = BW_20MHZ;
+ t_u8 oper_class = 1;
+ t_u32 usr_dot_11n_dev_cap;
+ if (pmpriv->media_connected) {
+ if (pmpriv->config_bands & BAND_A)
+ usr_dot_11n_dev_cap =
+ pmpriv->usr_dot_11n_dev_cap_a;
+ else
+ usr_dot_11n_dev_cap =
+ pmpriv->usr_dot_11n_dev_cap_bg;
+ if (usr_dot_11n_dev_cap & MBIT(17)) {
+ bandwidth = BW_40MHZ;
+ if (ISSUPP_11ACENABLED(
+ pmadapter->fw_cap_info) &&
+ (pmpriv->config_bands & BAND_AAC))
+ bandwidth = BW_80MHZ;
+ }
+ wlan_get_curr_oper_class(
+ pmpriv,
+ pmpriv->curr_bss_params.bss_descriptor.channel,
+ bandwidth, &oper_class);
+ }
+ wlan_add_supported_oper_class_ie(pmpriv, &ptlv_pos, oper_class);
+ }
+ wlan_add_wps_probe_request_ie(pmpriv, &ptlv_pos);
+
+ if (puser_scan_in && puser_scan_in->proberesp_only) {
+ MrvlIEtypes_OnlyProberesp_t *proberesp_only =
+ (MrvlIEtypes_OnlyProberesp_t *)ptlv_pos;
+ memset(pmadapter, proberesp_only, 0,
+ sizeof(MrvlIEtypes_OnlyProberesp_t));
+ proberesp_only->header.type =
+ wlan_cpu_to_le16(TLV_TYPE_ONLYPROBERESP);
+ proberesp_only->header.len = wlan_cpu_to_le16(sizeof(t_u8));
+ proberesp_only->proberesp_only = puser_scan_in->proberesp_only;
+ ptlv_pos += sizeof(MrvlIEtypes_OnlyProberesp_t);
+ }
+
+ if (puser_scan_in && memcmp(pmadapter, puser_scan_in->random_mac,
+ zero_mac, MLAN_MAC_ADDR_LENGTH)) {
+ MrvlIEtypes_MacAddr_t *randomMacParam =
+ (MrvlIEtypes_MacAddr_t *)ptlv_pos;
+ memset(pmadapter, randomMacParam, 0,
+ sizeof(MrvlIEtypes_MacAddr_t));
+ randomMacParam->header.type =
+ wlan_cpu_to_le16(TLV_TYPE_RANDOM_MAC);
+ randomMacParam->header.len =
+ wlan_cpu_to_le16(MLAN_MAC_ADDR_LENGTH);
+ memcpy_ext(pmadapter, randomMacParam->mac,
+ puser_scan_in->random_mac, MLAN_MAC_ADDR_LENGTH,
+ MLAN_MAC_ADDR_LENGTH);
+ ptlv_pos += sizeof(MrvlIEtypes_MacAddr_t);
+ }
+ /*
+ * 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.
+ */
+ *ppchan_list_out = (MrvlIEtypes_ChanListParamSet_t *)ptlv_pos;
+
+ if (puser_scan_in && puser_scan_in->chan_list[0].chan_number) {
+ PRINTM(MINFO, "Scan: Using supplied channel list\n");
+
+ for (chan_idx = 0;
+ chan_idx < WLAN_USER_SCAN_CHAN_MAX &&
+ puser_scan_in->chan_list[chan_idx].chan_number;
+ chan_idx++) {
+ radio_type =
+ puser_scan_in->chan_list[chan_idx].radio_type;
+ /*Ignore 5G/2G channels if radio_type do not match
+ * band*/
+ if (!wlan_is_band_compatible(
+ pmpriv->config_bands,
+ radio_type_to_band(radio_type)))
+ continue;
+ (pscan_chan_list + chan_list_idx)->bandcfg.chanBand =
+ radio_type;
+
+ channel =
+ puser_scan_in->chan_list[chan_idx].chan_number;
+ (pscan_chan_list + chan_list_idx)->chan_number =
+ channel;
+
+ scan_type =
+ puser_scan_in->chan_list[chan_idx].scan_type;
+ if (scan_type == MLAN_SCAN_TYPE_UNCHANGED)
+ scan_type = pmadapter->scan_type;
+
+ if (radio_type == BAND_5GHZ) {
+ if (pmadapter->fw_bands & BAND_A)
+ PRINTM(MINFO,
+ "UserScan request for A Band channel %d!!\n",
+ channel);
+ else {
+ PRINTM(MERROR,
+ "Scan in A band is not allowed!!\n");
+ ret = MLAN_STATUS_FAILURE;
+ LEAVE();
+ return ret;
+ }
+ }
+
+ if (wlan_is_chan_passive(pmpriv, radio_type, channel)) {
+ /* do not send probe requests on this channel */
+ scan_type = MLAN_SCAN_TYPE_PASSIVE;
+ }
+ /* Prevent active scanning on a radar controlled channel
+ */
+ if (radio_type == BAND_5GHZ &&
+ scan_type != MLAN_SCAN_TYPE_PASSIVE) {
+ if (pmadapter->active_scan_triggered == MFALSE)
+ if (wlan_11h_radar_detect_required(
+ pmpriv, channel)) {
+ scan_type =
+ MLAN_SCAN_TYPE_PASSIVE_TO_ACTIVE;
+ }
+ }
+ if (radio_type == BAND_2GHZ &&
+ scan_type != MLAN_SCAN_TYPE_PASSIVE) {
+ if (pmadapter->active_scan_triggered == MFALSE)
+ if (wlan_bg_scan_type_is_passive(
+ pmpriv, channel)) {
+ scan_type =
+ MLAN_SCAN_TYPE_PASSIVE;
+ }
+ }
+ if (scan_type == MLAN_SCAN_TYPE_PASSIVE ||
+ scan_type == MLAN_SCAN_TYPE_PASSIVE_TO_ACTIVE) {
+ (pscan_chan_list + chan_list_idx)
+ ->chan_scan_mode.passive_scan = MTRUE;
+ (pscan_chan_list + chan_list_idx)
+ ->chan_scan_mode.hidden_ssid_report =
+ MTRUE;
+ } else {
+ (pscan_chan_list + chan_list_idx)
+ ->chan_scan_mode.passive_scan = MFALSE;
+ }
+
+ if (puser_scan_in->chan_list[chan_idx].scan_time) {
+ scan_dur = (t_u16)puser_scan_in
+ ->chan_list[chan_idx]
+ .scan_time;
+ } else {
+ if (scan_type == MLAN_SCAN_TYPE_PASSIVE ||
+ scan_type ==
+ MLAN_SCAN_TYPE_PASSIVE_TO_ACTIVE) {
+ scan_dur = pmadapter->passive_scan_time;
+ } else if (*pfiltered_scan) {
+ scan_dur =
+ pmadapter->specific_scan_time;
+ } else {
+ scan_dur = pmadapter->active_scan_time;
+ }
+ }
+
+ if (pmadapter->coex_scan &&
+ pmadapter->coex_min_scan_time &&
+ (pmadapter->coex_min_scan_time > scan_dur))
+ scan_dur = pmadapter->coex_min_scan_time;
+ if (scan_type == MLAN_SCAN_TYPE_PASSIVE_TO_ACTIVE &&
+ pmadapter->passive_to_active_scan ==
+ MLAN_PASS_TO_ACT_SCAN_EN) {
+ (pscan_chan_list + chan_list_idx)
+ ->chan_scan_mode.passive_to_active_scan =
+ MTRUE;
+ scan_dur = MAX(MIN_PASSIVE_TO_ACTIVE_SCAN_TIME,
+ scan_dur);
+ }
+ PRINTM(MINFO,
+ "chan=%d, mode=%d, passive_to_active=%d\n",
+ (pscan_chan_list + chan_list_idx)->chan_number,
+ (pscan_chan_list + chan_list_idx)
+ ->chan_scan_mode.passive_scan,
+ (pscan_chan_list + chan_list_idx)
+ ->chan_scan_mode.passive_to_active_scan);
+
+ (pscan_chan_list + chan_list_idx)->min_scan_time =
+ wlan_cpu_to_le16(scan_dur);
+ (pscan_chan_list + chan_list_idx)->max_scan_time =
+ wlan_cpu_to_le16(scan_dur);
+ chan_list_idx++;
+ }
+
+ /* Check if we are only scanning the current channel */
+ if ((chan_idx == 1) &&
+ (puser_scan_in->chan_list[0].chan_number ==
+ pmpriv->curr_bss_params.bss_descriptor.channel)) {
+ *pscan_current_only = MTRUE;
+ PRINTM(MINFO, "Scan: Scanning current channel only\n");
+ }
+
+ } else {
+ PRINTM(MINFO, "Scan: Creating full region channel list\n");
+ wlan_scan_create_channel_list(pmpriv, puser_scan_in,
+ pscan_chan_list, *pfiltered_scan);
+ }
+
+ LEAVE();
+ return ret;
+}
+
+/**
+ * @brief Inspect the scan response buffer for pointers to expected TLVs
+ *
+ * TLVs can be included at the end of the scan response BSS information.
+ * Parse the data in the buffer for pointers to TLVs that can potentially
+ * be passed back in the response
+ *
+ * @param pmadapter Pointer to the mlan_adapter structure
+ * @param ptlv Pointer to the start of the TLV buffer to parse
+ * @param tlv_buf_size Size of the TLV buffer
+ * @param req_tlv_type Request TLV's type
+ * @param pptlv Output parameter: Pointer to the request TLV if
+ * found
+ *
+ * @return N/A
+ */
+static t_void wlan_ret_802_11_scan_get_tlv_ptrs(pmlan_adapter pmadapter,
+ MrvlIEtypes_Data_t *ptlv,
+ t_u32 tlv_buf_size,
+ t_u32 req_tlv_type,
+ MrvlIEtypes_Data_t **pptlv)
+{
+ MrvlIEtypes_Data_t *pcurrent_tlv;
+ t_u32 tlv_buf_left;
+ t_u32 tlv_type;
+ t_u32 tlv_len;
+
+ ENTER();
+
+ pcurrent_tlv = ptlv;
+ tlv_buf_left = tlv_buf_size;
+ *pptlv = MNULL;
+
+ PRINTM(MINFO, "SCAN_RESP: tlv_buf_size = %d\n", tlv_buf_size);
+
+ while (tlv_buf_left >= sizeof(MrvlIEtypesHeader_t)) {
+ tlv_type = wlan_le16_to_cpu(pcurrent_tlv->header.type);
+ tlv_len = wlan_le16_to_cpu(pcurrent_tlv->header.len);
+
+ if (sizeof(ptlv->header) + tlv_len > tlv_buf_left) {
+ PRINTM(MERROR, "SCAN_RESP: TLV buffer corrupt\n");
+ break;
+ }
+
+ if (req_tlv_type == tlv_type) {
+ switch (tlv_type) {
+ case TLV_TYPE_TSFTIMESTAMP:
+ PRINTM(MINFO,
+ "SCAN_RESP: TSF Timestamp TLV, len = %d\n",
+ tlv_len);
+ *pptlv = (MrvlIEtypes_Data_t *)pcurrent_tlv;
+ break;
+ case TLV_TYPE_CHANNELBANDLIST:
+ PRINTM(MINFO,
+ "SCAN_RESP: CHANNEL BAND LIST TLV, len = %d\n",
+ tlv_len);
+ *pptlv = (MrvlIEtypes_Data_t *)pcurrent_tlv;
+ break;
+ case TLV_TYPE_CHANNEL_STATS:
+ PRINTM(MINFO,
+ "SCAN_RESP: CHANNEL STATS TLV, len = %d\n",
+ tlv_len);
+ *pptlv = (MrvlIEtypes_Data_t *)pcurrent_tlv;
+ break;
+ default:
+ PRINTM(MERROR,
+ "SCAN_RESP: Unhandled TLV = %d\n",
+ tlv_type);
+ /* Give up, this seems corrupted */
+ LEAVE();
+ return;
+ }
+ }
+
+ if (*pptlv) {
+ /* HEXDUMP("SCAN_RESP: TLV Buf", (t_u8 *)*pptlv+4,
+ * tlv_len); */
+ break;
+ }
+
+ tlv_buf_left -= (sizeof(ptlv->header) + tlv_len);
+ pcurrent_tlv =
+ (MrvlIEtypes_Data_t *)(pcurrent_tlv->data + tlv_len);
+
+ } /* while */
+
+ LEAVE();
+}
+
+/**
+ * @brief Interpret a BSS scan response returned from the firmware
+ *
+ * Parse the various fixed fields and IEs passed back for a BSS probe
+ * response or beacon from the scan command. Record information as needed
+ * in the scan table BSSDescriptor_t for that entry.
+ *
+ * @param pmadapter A pointer to mlan_adapter structure
+ * @param pbss_entry Output parameter: Pointer to the BSS Entry
+ * @param pbeacon_info Pointer to the Beacon information
+ * @param bytes_left Number of bytes left to parse
+ * @param ext_scan extended scan
+ *
+ * @return MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ */
+static mlan_status wlan_interpret_bss_desc_with_ie(pmlan_adapter pmadapter,
+ BSSDescriptor_t *pbss_entry,
+ t_u8 **pbeacon_info,
+ t_u32 *bytes_left,
+ t_u8 ext_scan)
+{
+ mlan_status ret = MLAN_STATUS_SUCCESS;
+ IEEEtypes_ElementId_e element_id;
+ IEEEtypes_FhParamSet_t *pfh_param_set;
+ IEEEtypes_DsParamSet_t *pds_param_set;
+ IEEEtypes_CfParamSet_t *pcf_param_set;
+ IEEEtypes_IbssParamSet_t *pibss_param_set;
+ IEEEtypes_CapInfo_t *pcap_info;
+ WLAN_802_11_FIXED_IEs fixed_ie;
+ t_u8 *pcurrent_ptr;
+ t_u8 *prate;
+ t_u8 element_len;
+ t_u16 total_ie_len;
+ t_u8 bytes_to_copy;
+ t_u8 rate_size;
+ t_u16 beacon_size;
+ t_u8 found_data_rate_ie;
+ t_u32 bytes_left_for_current_beacon;
+ IEEEtypes_ERPInfo_t *perp_info;
+
+ IEEEtypes_VendorSpecific_t *pvendor_ie;
+ const t_u8 wpa_oui[4] = {0x00, 0x50, 0xf2, 0x01};
+ const t_u8 wmm_oui[4] = {0x00, 0x50, 0xf2, 0x02};
+ const t_u8 osen_oui[] = {0x50, 0x6f, 0x9a, 0x12};
+
+ IEEEtypes_CountryInfoSet_t *pcountry_info;
+ IEEEtypes_Extension_t *pext_tlv;
+
+ ENTER();
+
+ found_data_rate_ie = MFALSE;
+ rate_size = 0;
+ beacon_size = 0;
+
+ if (*bytes_left >= sizeof(beacon_size)) {
+ /* Extract & convert beacon size from the command buffer */
+ memcpy_ext(pmadapter, &beacon_size, *pbeacon_info,
+ sizeof(beacon_size), sizeof(beacon_size));
+ beacon_size = wlan_le16_to_cpu(beacon_size);
+ *bytes_left -= sizeof(beacon_size);
+ *pbeacon_info += sizeof(beacon_size);
+ }
+
+ if (!beacon_size || beacon_size > *bytes_left) {
+ *pbeacon_info += *bytes_left;
+ *bytes_left = 0;
+
+ LEAVE();
+ return MLAN_STATUS_FAILURE;
+ }
+
+ /* Initialize the current working beacon pointer for this BSS iteration
+ */
+ pcurrent_ptr = *pbeacon_info;
+
+ /* Advance the return beacon pointer past the current beacon */
+ *pbeacon_info += beacon_size;
+ *bytes_left -= beacon_size;
+
+ bytes_left_for_current_beacon = beacon_size;
+
+ if (bytes_left_for_current_beacon <
+ (MLAN_MAC_ADDR_LENGTH + sizeof(t_u8) +
+ sizeof(WLAN_802_11_FIXED_IEs))) {
+ PRINTM(MERROR, "InterpretIE: Not enough bytes left\n");
+ LEAVE();
+ return MLAN_STATUS_FAILURE;
+ }
+
+ memcpy_ext(pmadapter, pbss_entry->mac_address, pcurrent_ptr,
+ MLAN_MAC_ADDR_LENGTH, MLAN_MAC_ADDR_LENGTH);
+ PRINTM(MINFO, "InterpretIE: AP MAC Addr-" MACSTR "\n",
+ MAC2STR(pbss_entry->mac_address));
+
+ pcurrent_ptr += MLAN_MAC_ADDR_LENGTH;
+ bytes_left_for_current_beacon -= MLAN_MAC_ADDR_LENGTH;
+
+ /*
+ * Next 4 fields are RSSI (for legacy scan only), time stamp,
+ * beacon interval, and capability information
+ */
+ if (!ext_scan) {
+ /* RSSI is 1 byte long */
+ pbss_entry->rssi = (t_s32)(*pcurrent_ptr);
+ PRINTM(MINFO, "InterpretIE: RSSI=%02X\n", *pcurrent_ptr);
+ pcurrent_ptr += 1;
+ bytes_left_for_current_beacon -= 1;
+ }
+
+ /*
+ * The RSSI is not part of the beacon/probe response. After we have
+ * advanced pcurrent_ptr past the RSSI field, save the remaining
+ * data for use at the application layer
+ */
+ pbss_entry->pbeacon_buf = pcurrent_ptr;
+ pbss_entry->beacon_buf_size = bytes_left_for_current_beacon;
+
+ /* Time stamp is 8 bytes long */
+ memcpy_ext(pmadapter, fixed_ie.time_stamp, pcurrent_ptr, 8,
+ sizeof(fixed_ie.time_stamp));
+ memcpy_ext(pmadapter, pbss_entry->time_stamp, pcurrent_ptr, 8,
+ sizeof(pbss_entry->time_stamp));
+ pcurrent_ptr += 8;
+ bytes_left_for_current_beacon -= 8;
+
+ /* Beacon interval is 2 bytes long */
+ memcpy_ext(pmadapter, &fixed_ie.beacon_interval, pcurrent_ptr, 2,
+ sizeof(fixed_ie.beacon_interval));
+ pbss_entry->beacon_period = wlan_le16_to_cpu(fixed_ie.beacon_interval);
+ pcurrent_ptr += 2;
+ bytes_left_for_current_beacon -= 2;
+
+ /* Capability information is 2 bytes long */
+ memcpy_ext(pmadapter, &fixed_ie.capabilities, pcurrent_ptr, 2,
+ sizeof(fixed_ie.capabilities));
+ PRINTM(MINFO, "InterpretIE: fixed_ie.capabilities=0x%X\n",
+ fixed_ie.capabilities);
+ fixed_ie.capabilities = wlan_le16_to_cpu(fixed_ie.capabilities);
+ pcap_info = (IEEEtypes_CapInfo_t *)&fixed_ie.capabilities;
+ memcpy_ext(pmadapter, &pbss_entry->cap_info, pcap_info,
+ sizeof(IEEEtypes_CapInfo_t), sizeof(IEEEtypes_CapInfo_t));
+ pcurrent_ptr += 2;
+ bytes_left_for_current_beacon -= 2;
+
+ /* Rest of the current buffer are IE's */
+ PRINTM(MINFO, "InterpretIE: IELength for this AP = %d\n",
+ bytes_left_for_current_beacon);
+
+ HEXDUMP("InterpretIE: IE info", (t_u8 *)pcurrent_ptr,
+ bytes_left_for_current_beacon);
+
+ if (pcap_info->privacy) {
+ PRINTM(MINFO, "InterpretIE: AP WEP enabled\n");
+ pbss_entry->privacy = Wlan802_11PrivFilter8021xWEP;
+ } else {
+ pbss_entry->privacy = Wlan802_11PrivFilterAcceptAll;
+ }
+
+ if (pcap_info->ibss == 1)
+ pbss_entry->bss_mode = MLAN_BSS_MODE_IBSS;
+ else
+ pbss_entry->bss_mode = MLAN_BSS_MODE_INFRA;
+
+ if (pcap_info->spectrum_mgmt == 1) {
+ PRINTM(MINFO, "InterpretIE: 11h- Spectrum Management "
+ "capability bit found\n");
+ pbss_entry->wlan_11h_bss_info.sensed_11h = 1;
+ }
+
+ /* Process variable IE */
+ while (bytes_left_for_current_beacon >= 2) {
+ element_id = (IEEEtypes_ElementId_e)(*((t_u8 *)pcurrent_ptr));
+ element_len = *((t_u8 *)pcurrent_ptr + 1);
+ total_ie_len = element_len + sizeof(IEEEtypes_Header_t);
+
+ if (bytes_left_for_current_beacon < total_ie_len) {
+ PRINTM(MERROR, "InterpretIE: Error in processing IE, "
+ "bytes left < IE length\n");
+ bytes_left_for_current_beacon = 0;
+ ret = MLAN_STATUS_FAILURE;
+ continue;
+ }
+
+ switch (element_id) {
+ case SSID:
+ if (element_len > MRVDRV_MAX_SSID_LENGTH) {
+ bytes_left_for_current_beacon = 0;
+ ret = MLAN_STATUS_FAILURE;
+ continue;
+ }
+ if (!pbss_entry->ssid.ssid_len) {
+ pbss_entry->ssid.ssid_len = element_len;
+ memcpy_ext(pmadapter, pbss_entry->ssid.ssid,
+ (pcurrent_ptr + 2), element_len,
+ sizeof(pbss_entry->ssid.ssid));
+ }
+ PRINTM(MINFO, "InterpretIE: ssid: %-32s\n",
+ pbss_entry->ssid.ssid);
+ break;
+
+ case SUPPORTED_RATES:
+ if (element_len > WLAN_SUPPORTED_RATES) {
+ bytes_left_for_current_beacon = 0;
+ ret = MLAN_STATUS_FAILURE;
+ continue;
+ }
+ memcpy_ext(pmadapter, pbss_entry->data_rates,
+ pcurrent_ptr + 2, element_len,
+ sizeof(pbss_entry->data_rates));
+ memcpy_ext(pmadapter, pbss_entry->supported_rates,
+ pcurrent_ptr + 2, element_len,
+ sizeof(pbss_entry->supported_rates));
+ HEXDUMP("InterpretIE: SupportedRates:",
+ pbss_entry->supported_rates, element_len);
+ rate_size = element_len;
+ found_data_rate_ie = MTRUE;
+ break;
+
+ case FH_PARAM_SET:
+ pfh_param_set = (IEEEtypes_FhParamSet_t *)pcurrent_ptr;
+ pbss_entry->network_type_use = Wlan802_11FH;
+ memcpy_ext(pmadapter,
+ &pbss_entry->phy_param_set.fh_param_set,
+ pfh_param_set, total_ie_len,
+ sizeof(IEEEtypes_FhParamSet_t));
+ pbss_entry->phy_param_set.fh_param_set.len = MIN(
+ element_len, (sizeof(IEEEtypes_FhParamSet_t) -
+ sizeof(IEEEtypes_Header_t)));
+ pbss_entry->phy_param_set.fh_param_set.dwell_time =
+ wlan_le16_to_cpu(
+ pbss_entry->phy_param_set.fh_param_set
+ .dwell_time);
+ break;
+
+ case DS_PARAM_SET:
+ pds_param_set = (IEEEtypes_DsParamSet_t *)pcurrent_ptr;
+
+ pbss_entry->network_type_use = Wlan802_11DS;
+ pbss_entry->channel = pds_param_set->current_chan;
+
+ memcpy_ext(pmadapter,
+ &pbss_entry->phy_param_set.ds_param_set,
+ pds_param_set, total_ie_len,
+ sizeof(IEEEtypes_DsParamSet_t));
+ pbss_entry->phy_param_set.ds_param_set.len = MIN(
+ element_len, (sizeof(IEEEtypes_DsParamSet_t) -
+ sizeof(IEEEtypes_Header_t)));
+ break;
+
+ case CF_PARAM_SET:
+ pcf_param_set = (IEEEtypes_CfParamSet_t *)pcurrent_ptr;
+ memcpy_ext(pmadapter,
+ &pbss_entry->ss_param_set.cf_param_set,
+ pcf_param_set, total_ie_len,
+ sizeof(IEEEtypes_CfParamSet_t));
+ pbss_entry->ss_param_set.cf_param_set.len = MIN(
+ element_len, (sizeof(IEEEtypes_CfParamSet_t) -
+ sizeof(IEEEtypes_Header_t)));
+ break;
+
+ case IBSS_PARAM_SET:
+ pibss_param_set =
+ (IEEEtypes_IbssParamSet_t *)pcurrent_ptr;
+ pbss_entry->atim_window =
+ wlan_le16_to_cpu(pibss_param_set->atim_window);
+ memcpy_ext(pmadapter,
+ &pbss_entry->ss_param_set.ibss_param_set,
+ pibss_param_set, total_ie_len,
+ sizeof(IEEEtypes_IbssParamSet_t));
+ pbss_entry->ss_param_set.ibss_param_set.len = MIN(
+ element_len, (sizeof(IEEEtypes_IbssParamSet_t) -
+ sizeof(IEEEtypes_Header_t)));
+ break;
+
+ /* Handle Country Info IE */
+ case COUNTRY_INFO:
+ pcountry_info =
+ (IEEEtypes_CountryInfoSet_t *)pcurrent_ptr;
+
+ if (pcountry_info->len <
+ sizeof(pcountry_info->country_code) ||
+ (unsigned)(pcountry_info->len + 2) >
+ sizeof(IEEEtypes_CountryInfoFullSet_t)) {
+ PRINTM(MERROR,
+ "InterpretIE: 11D- Err "
+ "country_info len =%d min=%d max=%d\n",
+ pcountry_info->len,
+ sizeof(pcountry_info->country_code),
+ sizeof(IEEEtypes_CountryInfoFullSet_t));
+ LEAVE();
+ return MLAN_STATUS_FAILURE;
+ }
+
+ memcpy_ext(pmadapter, &pbss_entry->country_info,
+ pcountry_info, pcountry_info->len + 2,
+ sizeof(pbss_entry->country_info));
+ HEXDUMP("InterpretIE: 11D- country_info:",
+ (t_u8 *)pcountry_info,
+ (t_u32)(pcountry_info->len + 2));
+ break;
+
+ case ERP_INFO:
+ perp_info = (IEEEtypes_ERPInfo_t *)pcurrent_ptr;
+ pbss_entry->erp_flags = perp_info->erp_flags;
+ break;
+
+ case POWER_CONSTRAINT:
+ case POWER_CAPABILITY:
+ case TPC_REPORT:
+ case CHANNEL_SWITCH_ANN:
+ case QUIET:
+ case IBSS_DFS:
+ case SUPPORTED_CHANNELS:
+ case TPC_REQUEST:
+ wlan_11h_process_bss_elem(
+ pmadapter, &pbss_entry->wlan_11h_bss_info,
+ pcurrent_ptr);
+ break;
+ case EXTENDED_SUPPORTED_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) >
+ WLAN_SUPPORTED_RATES) {
+ bytes_to_copy = (WLAN_SUPPORTED_RATES -
+ rate_size);
+ } else {
+ bytes_to_copy = element_len;
+ }
+
+ prate = (t_u8 *)pbss_entry->data_rates;
+ prate += rate_size;
+ memcpy_ext(pmadapter, prate, pcurrent_ptr + 2,
+ bytes_to_copy, bytes_to_copy);
+
+ prate = (t_u8 *)pbss_entry->supported_rates;
+ prate += rate_size;
+ memcpy_ext(pmadapter, prate, pcurrent_ptr + 2,
+ bytes_to_copy, bytes_to_copy);
+ }
+ HEXDUMP("InterpretIE: ExtSupportedRates:",
+ pbss_entry->supported_rates,
+ element_len + rate_size);
+ break;
+
+ case VENDOR_SPECIFIC_221:
+ pvendor_ie = (IEEEtypes_VendorSpecific_t *)pcurrent_ptr;
+
+ if (!memcmp(pmadapter, pvendor_ie->vend_hdr.oui,
+ wpa_oui, sizeof(wpa_oui))) {
+ pbss_entry->pwpa_ie =
+ (IEEEtypes_VendorSpecific_t *)
+ pcurrent_ptr;
+ pbss_entry->wpa_offset = (t_u16)(
+ pcurrent_ptr - pbss_entry->pbeacon_buf);
+ HEXDUMP("InterpretIE: Resp WPA_IE",
+ (t_u8 *)pbss_entry->pwpa_ie,
+ ((*(pbss_entry->pwpa_ie)).vend_hdr.len +
+ sizeof(IEEEtypes_Header_t)));
+ } else if (!memcmp(pmadapter, pvendor_ie->vend_hdr.oui,
+ wmm_oui, sizeof(wmm_oui))) {
+ if (total_ie_len ==
+ sizeof(IEEEtypes_WmmParameter_t) ||
+ total_ie_len ==
+ sizeof(IEEEtypes_WmmInfo_t)) {
+ /*
+ * Only accept and copy the WMM IE if
+ * it matches the size expected for the
+ * WMM Info IE or the WMM Parameter IE.
+ */
+ memcpy_ext(pmadapter,
+ (t_u8 *)&pbss_entry->wmm_ie,
+ pcurrent_ptr, total_ie_len,
+ sizeof(pbss_entry->wmm_ie));
+ HEXDUMP("InterpretIE: Resp WMM_IE",
+ (t_u8 *)&pbss_entry->wmm_ie,
+ total_ie_len);
+ }
+ } else if (!memcmp(pmadapter, pvendor_ie->vend_hdr.oui,
+ osen_oui, sizeof(osen_oui))) {
+ pbss_entry->posen_ie =
+ (IEEEtypes_Generic_t *)pcurrent_ptr;
+ pbss_entry->osen_offset = (t_u16)(
+ pcurrent_ptr - pbss_entry->pbeacon_buf);
+ HEXDUMP("InterpretIE: Resp OSEN_IE",
+ (t_u8 *)pbss_entry->posen_ie,
+ (*(pbss_entry->posen_ie)).ieee_hdr.len +
+ sizeof(IEEEtypes_Header_t));
+ }
+ break;
+ case RSN_IE:
+ pbss_entry->prsn_ie =
+ (IEEEtypes_Generic_t *)pcurrent_ptr;
+ pbss_entry->rsn_offset =
+ (t_u16)(pcurrent_ptr - pbss_entry->pbeacon_buf);
+ HEXDUMP("InterpretIE: Resp RSN_IE",
+ (t_u8 *)pbss_entry->prsn_ie,
+ (*(pbss_entry->prsn_ie)).ieee_hdr.len +
+ sizeof(IEEEtypes_Header_t));
+ break;
+ case WAPI_IE:
+ pbss_entry->pwapi_ie =
+ (IEEEtypes_Generic_t *)pcurrent_ptr;
+ pbss_entry->wapi_offset =
+ (t_u16)(pcurrent_ptr - pbss_entry->pbeacon_buf);
+ HEXDUMP("InterpretIE: Resp WAPI_IE",
+ (t_u8 *)pbss_entry->pwapi_ie,
+ (*(pbss_entry->pwapi_ie)).ieee_hdr.len +
+ sizeof(IEEEtypes_Header_t));
+ break;
+ case HT_CAPABILITY:
+ pbss_entry->pht_cap = (IEEEtypes_HTCap_t *)pcurrent_ptr;
+ pbss_entry->ht_cap_offset =
+ (t_u16)(pcurrent_ptr - pbss_entry->pbeacon_buf);
+ HEXDUMP("InterpretIE: Resp HTCAP_IE",
+ (t_u8 *)pbss_entry->pht_cap,
+ (*(pbss_entry->pht_cap)).ieee_hdr.len +
+ sizeof(IEEEtypes_Header_t));
+ break;
+ case HT_OPERATION:
+ pbss_entry->pht_info =
+ (IEEEtypes_HTInfo_t *)pcurrent_ptr;
+ pbss_entry->ht_info_offset =
+ (t_u16)(pcurrent_ptr - pbss_entry->pbeacon_buf);
+ HEXDUMP("InterpretIE: Resp HTINFO_IE",
+ (t_u8 *)pbss_entry->pht_info,
+ (*(pbss_entry->pht_info)).ieee_hdr.len +
+ sizeof(IEEEtypes_Header_t));
+ break;
+ case BSSCO_2040:
+ pbss_entry->pbss_co_2040 =
+ (IEEEtypes_2040BSSCo_t *)pcurrent_ptr;
+ pbss_entry->bss_co_2040_offset =
+ (t_u16)(pcurrent_ptr - pbss_entry->pbeacon_buf);
+ HEXDUMP("InterpretIE: Resp 2040BSSCOEXISTANCE_IE",
+ (t_u8 *)pbss_entry->pbss_co_2040,
+ (*(pbss_entry->pbss_co_2040)).ieee_hdr.len +
+ sizeof(IEEEtypes_Header_t));
+ break;
+ case EXT_CAPABILITY:
+ pbss_entry->pext_cap =
+ (IEEEtypes_ExtCap_t *)pcurrent_ptr;
+ pbss_entry->ext_cap_offset =
+ (t_u16)(pcurrent_ptr - pbss_entry->pbeacon_buf);
+ HEXDUMP("InterpretIE: Resp EXTCAP_IE",
+ (t_u8 *)pbss_entry->pext_cap,
+ (*(pbss_entry->pext_cap)).ieee_hdr.len +
+ sizeof(IEEEtypes_Header_t));
+ break;
+ case OVERLAPBSSSCANPARAM:
+ pbss_entry->poverlap_bss_scan_param =
+ (IEEEtypes_OverlapBSSScanParam_t *)pcurrent_ptr;
+ pbss_entry->overlap_bss_offset =
+ (t_u16)(pcurrent_ptr - pbss_entry->pbeacon_buf);
+ HEXDUMP("InterpretIE: Resp OBSS_IE",
+ (t_u8 *)pbss_entry->poverlap_bss_scan_param,
+ (*(pbss_entry->poverlap_bss_scan_param))
+ .ieee_hdr.len +
+ sizeof(IEEEtypes_Header_t));
+ break;
+ case VHT_CAPABILITY:
+ pbss_entry->pvht_cap =
+ (IEEEtypes_VHTCap_t *)pcurrent_ptr;
+ pbss_entry->vht_cap_offset =
+ (t_u16)(pcurrent_ptr - pbss_entry->pbeacon_buf);
+ HEXDUMP("InterpretIE: Resp VHTCAP_IE",
+ (t_u8 *)pbss_entry->pvht_cap,
+ (*(pbss_entry->pvht_cap)).ieee_hdr.len +
+ sizeof(IEEEtypes_Header_t));
+ break;
+ case VHT_OPERATION:
+ pbss_entry->pvht_oprat =
+ (IEEEtypes_VHTOprat_t *)pcurrent_ptr;
+ pbss_entry->vht_oprat_offset =
+ (t_u16)(pcurrent_ptr - pbss_entry->pbeacon_buf);
+ HEXDUMP("InterpretIE: Resp VHTOPER_IE",
+ (t_u8 *)pbss_entry->pvht_oprat,
+ (*(pbss_entry->pvht_oprat)).ieee_hdr.len +
+ sizeof(IEEEtypes_Header_t));
+ break;
+ case EXT_BSS_LOAD:
+ pbss_entry->pext_bssload =
+ (IEEEtypes_ExtBSSload_t *)pcurrent_ptr;
+ pbss_entry->ext_bssload_offset =
+ (t_u16)(pcurrent_ptr - pbss_entry->pbeacon_buf);
+ HEXDUMP("InterpretIE: Resp EXTBSSLOAD_IE",
+ (t_u8 *)pbss_entry->pext_bssload,
+ (*(pbss_entry->pext_bssload)).ieee_hdr.len +
+ sizeof(IEEEtypes_Header_t));
+ break;
+ case VHT_TX_POWER_ENV:
+ pbss_entry->pvht_txpower =
+ (IEEEtypes_VHTtxpower_t *)pcurrent_ptr;
+ pbss_entry->vht_txpower_offset =
+ (t_u16)(pcurrent_ptr - pbss_entry->pbeacon_buf);
+ HEXDUMP("InterpretIE: Resp TXPOW_IE",
+ (t_u8 *)pbss_entry->pvht_txpower,
+ (*(pbss_entry->pvht_txpower)).ieee_hdr.len +
+ sizeof(IEEEtypes_Header_t));
+ break;
+ case EXT_POWER_CONSTR:
+ pbss_entry->pext_pwer =
+ (IEEEtypes_ExtPwerCons_t *)pcurrent_ptr;
+ pbss_entry->ext_pwer_offset =
+ (t_u16)(pcurrent_ptr - pbss_entry->pbeacon_buf);
+ HEXDUMP("InterpretIE: Resp EXTPOW_IE",
+ (t_u8 *)pbss_entry->pext_pwer,
+ (*(pbss_entry->pext_pwer)).ieee_hdr.len +
+ sizeof(IEEEtypes_Header_t));
+ break;
+ case QUIET_CHAN:
+ pbss_entry->pquiet_chan =
+ (IEEEtypes_QuietChan_t *)pcurrent_ptr;
+ pbss_entry->quiet_chan_offset =
+ (t_u16)(pcurrent_ptr - pbss_entry->pbeacon_buf);
+ HEXDUMP("InterpretIE: Resp QUIETCHAN_IE",
+ (t_u8 *)pbss_entry->pquiet_chan,
+ (*(pbss_entry->pquiet_chan)).ieee_hdr.len +
+ sizeof(IEEEtypes_Header_t));
+ break;
+ case BW_CHANNEL_SWITCH:
+ /* RANDYTODO */
+ break;
+ case AID_INFO:
+ break;
+ case OPER_MODE_NTF:
+ pbss_entry->poper_mode =
+ (IEEEtypes_OperModeNtf_t *)pcurrent_ptr;
+ pbss_entry->oper_mode_offset =
+ (t_u16)(pcurrent_ptr - pbss_entry->pbeacon_buf);
+ HEXDUMP("InterpretIE: Resp OPERMODENTF_IE",
+ (t_u8 *)pbss_entry->poper_mode,
+ (*(pbss_entry->poper_mode)).ieee_hdr.len +
+ sizeof(IEEEtypes_Header_t));
+ break;
+ case EXTENSION:
+ pext_tlv = (IEEEtypes_Extension_t *)pcurrent_ptr;
+ switch (pext_tlv->ext_id) {
+ case HE_CAPABILITY:
+ pbss_entry->phe_cap =
+ (IEEEtypes_HECap_t *)pcurrent_ptr;
+ pbss_entry->he_cap_offset = (t_u16)(
+ pcurrent_ptr - pbss_entry->pbeacon_buf);
+ break;
+ case HE_OPERATION:
+ pbss_entry->phe_oprat = pext_tlv;
+ pbss_entry->he_oprat_offset = (t_u16)(
+ pcurrent_ptr - pbss_entry->pbeacon_buf);
+ break;
+ default:
+ break;
+ }
+ break;
+ case MOBILITY_DOMAIN:
+ PRINTM(MCMND, "Mobility Domain IE received in Scan\n");
+ pbss_entry->pmd_ie =
+ (IEEEtypes_MobilityDomain_t *)pcurrent_ptr;
+ pbss_entry->md_offset =
+ (t_u16)(pcurrent_ptr - pbss_entry->pbeacon_buf);
+ HEXDUMP("InterpretIE: Resp Mobility Domain IE",
+ (t_u8 *)pbss_entry->pmd_ie,
+ (*(pbss_entry->pmd_ie)).ieee_hdr.len +
+ sizeof(IEEEtypes_Header_t));
+ break;
+ default:
+ break;
+ }
+
+ pcurrent_ptr += element_len + 2;
+
+ /* Need to account for IE ID and IE Len */
+ bytes_left_for_current_beacon -= (element_len + 2);
+
+ } /* while (bytes_left_for_current_beacon > 2) */
+
+ LEAVE();
+ return ret;
+}
+
+/**
+ * @brief Adjust ie's position in BSSDescriptor_t
+ *
+ * @param pmpriv A pointer to mlan_private structure
+ * @param pbss_entry A pointer to BSSDescriptor_t structure
+ *
+ * @return N/A
+ */
+static t_void wlan_adjust_ie_in_bss_entry(mlan_private *pmpriv,
+ BSSDescriptor_t *pbss_entry)
+{
+ ENTER();
+ if (pbss_entry->pbeacon_buf) {
+ if (pbss_entry->pwpa_ie) {
+ pbss_entry->pwpa_ie =
+ (IEEEtypes_VendorSpecific_t
+ *)(pbss_entry->pbeacon_buf +
+ pbss_entry->wpa_offset);
+ }
+ if (pbss_entry->prsn_ie) {
+ pbss_entry->prsn_ie =
+ (IEEEtypes_Generic_t *)(pbss_entry->pbeacon_buf +
+ pbss_entry->rsn_offset);
+ }
+ if (pbss_entry->pwapi_ie) {
+ pbss_entry->pwapi_ie =
+ (IEEEtypes_Generic_t *)(pbss_entry->pbeacon_buf +
+ pbss_entry->wapi_offset);
+ }
+
+ if (pbss_entry->posen_ie) {
+ pbss_entry->posen_ie =
+ (IEEEtypes_Generic_t *)(pbss_entry->pbeacon_buf +
+ pbss_entry->osen_offset);
+ }
+ if (pbss_entry->pmd_ie) {
+ pbss_entry->pmd_ie =
+ (IEEEtypes_MobilityDomain_t
+ *)(pbss_entry->pbeacon_buf +
+ pbss_entry->md_offset);
+ }
+ if (pbss_entry->pht_cap) {
+ pbss_entry->pht_cap =
+ (IEEEtypes_HTCap_t *)(pbss_entry->pbeacon_buf +
+ pbss_entry->ht_cap_offset);
+ }
+ if (pbss_entry->pht_info) {
+ pbss_entry->pht_info =
+ (IEEEtypes_HTInfo_t
+ *)(pbss_entry->pbeacon_buf +
+ pbss_entry->ht_info_offset);
+ }
+ if (pbss_entry->pbss_co_2040) {
+ pbss_entry->pbss_co_2040 =
+ (IEEEtypes_2040BSSCo_t
+ *)(pbss_entry->pbeacon_buf +
+ pbss_entry->bss_co_2040_offset);
+ }
+ if (pbss_entry->pext_cap) {
+ pbss_entry->pext_cap =
+ (IEEEtypes_ExtCap_t
+ *)(pbss_entry->pbeacon_buf +
+ pbss_entry->ext_cap_offset);
+ }
+ if (pbss_entry->poverlap_bss_scan_param) {
+ pbss_entry->poverlap_bss_scan_param =
+ (IEEEtypes_OverlapBSSScanParam_t
+ *)(pbss_entry->pbeacon_buf +
+ pbss_entry->overlap_bss_offset);
+ }
+ if (pbss_entry->pvht_cap) {
+ pbss_entry->pvht_cap =
+ (IEEEtypes_VHTCap_t
+ *)(pbss_entry->pbeacon_buf +
+ pbss_entry->vht_cap_offset);
+ }
+ if (pbss_entry->pvht_oprat) {
+ pbss_entry->pvht_oprat =
+ (IEEEtypes_VHTOprat_t
+ *)(pbss_entry->pbeacon_buf +
+ pbss_entry->vht_oprat_offset);
+ }
+ if (pbss_entry->pvht_txpower) {
+ pbss_entry->pvht_txpower =
+ (IEEEtypes_VHTtxpower_t
+ *)(pbss_entry->pbeacon_buf +
+ pbss_entry->vht_txpower_offset);
+ }
+ if (pbss_entry->pext_pwer) {
+ pbss_entry->pext_pwer =
+ (IEEEtypes_ExtPwerCons_t
+ *)(pbss_entry->pbeacon_buf +
+ pbss_entry->ext_pwer_offset);
+ }
+ if (pbss_entry->pext_bssload) {
+ pbss_entry->pext_bssload =
+ (IEEEtypes_ExtBSSload_t
+ *)(pbss_entry->pbeacon_buf +
+ pbss_entry->ext_bssload_offset);
+ }
+ if (pbss_entry->pquiet_chan) {
+ pbss_entry->pquiet_chan =
+ (IEEEtypes_QuietChan_t
+ *)(pbss_entry->pbeacon_buf +
+ pbss_entry->quiet_chan_offset);
+ }
+ if (pbss_entry->poper_mode) {
+ pbss_entry->poper_mode =
+ (IEEEtypes_OperModeNtf_t
+ *)(pbss_entry->pbeacon_buf +
+ pbss_entry->oper_mode_offset);
+ }
+ if (pbss_entry->phe_cap) {
+ pbss_entry->phe_cap =
+ (IEEEtypes_HECap_t *)(pbss_entry->pbeacon_buf +
+ pbss_entry->he_cap_offset);
+ }
+
+ if (pbss_entry->phe_oprat) {
+ pbss_entry->phe_oprat =
+ (IEEEtypes_Extension_t
+ *)(pbss_entry->pbeacon_buf +
+ pbss_entry->he_oprat_offset);
+ }
+ } else {
+ pbss_entry->pwpa_ie = MNULL;
+ pbss_entry->wpa_offset = 0;
+ pbss_entry->prsn_ie = MNULL;
+ pbss_entry->rsn_offset = 0;
+ pbss_entry->pwapi_ie = MNULL;
+ pbss_entry->wapi_offset = 0;
+
+ pbss_entry->posen_ie = MNULL;
+ pbss_entry->osen_offset = 0;
+ pbss_entry->pmd_ie = MNULL;
+ pbss_entry->md_offset = 0;
+ pbss_entry->pht_cap = MNULL;
+ pbss_entry->ht_cap_offset = 0;
+ pbss_entry->pht_info = MNULL;
+ pbss_entry->ht_info_offset = 0;
+ pbss_entry->pbss_co_2040 = MNULL;
+ pbss_entry->bss_co_2040_offset = 0;
+ pbss_entry->pext_cap = MNULL;
+ pbss_entry->ext_cap_offset = 0;
+ pbss_entry->poverlap_bss_scan_param = MNULL;
+ pbss_entry->overlap_bss_offset = 0;
+ }
+ LEAVE();
+ return;
+}
+
+/**
+ * @brief Store a beacon or probe response for a BSS returned in the scan
+ *
+ * Store a new scan response or an update for a previous scan response. New
+ * entries need to verify that they do not exceed the total amount of
+ * memory allocated for the table.
+
+ * Replacement entries need to take into consideration the amount of space
+ * currently allocated for the beacon/probe response and adjust the entry
+ * as needed.
+ *
+ * A small amount of extra pad (SCAN_BEACON_ENTRY_PAD) is generally reserved
+ * for an entry in case it is a beacon since a probe response for the
+ * network will by larger per the standard. This helps to reduce the
+ * amount of memory copying to fit a new probe response into an entry
+ * already occupied by a network's previously stored beacon.
+ *
+ * @param pmpriv A pointer to mlan_private structure
+ * @param beacon_idx Index in the scan table to store this entry; may be
+ * replacing an older duplicate entry for this BSS
+ * @param num_of_ent Number of entries currently in the table
+ * @param pnew_beacon Pointer to the new beacon/probe response to save
+ *
+ * @return N/A
+ */
+static t_void wlan_ret_802_11_scan_store_beacon(mlan_private *pmpriv,
+ t_u32 beacon_idx,
+ t_u32 num_of_ent,
+ BSSDescriptor_t *pnew_beacon)
+{
+ mlan_adapter *pmadapter = pmpriv->adapter;
+ t_u8 *pbcn_store;
+ t_u32 new_bcn_size;
+ t_u32 old_bcn_size;
+ t_u32 bcn_space;
+ t_u32 adj_idx;
+ mlan_status ret = MLAN_STATUS_SUCCESS;
+ t_u8 *tmp_buf;
+ t_u16 bcn_size = 0;
+ t_u32 bcn_offset = 0;
+
+ ENTER();
+
+ if (pmadapter->pscan_table[beacon_idx].pbeacon_buf) {
+ new_bcn_size = pnew_beacon->beacon_buf_size;
+ old_bcn_size =
+ pmadapter->pscan_table[beacon_idx].beacon_buf_size;
+ bcn_space =
+ pmadapter->pscan_table[beacon_idx].beacon_buf_size_max;
+ pbcn_store = pmadapter->pscan_table[beacon_idx].pbeacon_buf;
+
+ /* Set the max to be the same as current entry unless changed
+ * below */
+ pnew_beacon->beacon_buf_size_max = bcn_space;
+
+ if (new_bcn_size == old_bcn_size) {
+ /*
+ * Beacon is the same size as the previous entry.
+ * Replace the previous contents with the scan result
+ */
+ memcpy_ext(pmadapter, pbcn_store,
+ pnew_beacon->pbeacon_buf,
+ pnew_beacon->beacon_buf_size,
+ pnew_beacon->beacon_buf_size);
+
+ } else if (new_bcn_size <= bcn_space) {
+ /*
+ * New beacon size will fit in the amount of space
+ * we have previously allocated for it
+ */
+
+ /* Copy the new beacon buffer entry over the old one */
+ memcpy_ext(pmadapter, pbcn_store,
+ pnew_beacon->pbeacon_buf, new_bcn_size,
+ new_bcn_size);
+
+ /*
+ * If the old beacon size was less than the
+ * maximum we had allotted for the entry, and
+ * the new entry is even smaller, reset the
+ * max size to the old beacon entry and compress
+ * the storage space (leaving a new pad space of
+ * (old_bcn_size - new_bcn_size).
+ */
+ if (old_bcn_size < bcn_space &&
+ new_bcn_size <= old_bcn_size) {
+ /*
+ * Old Beacon size is smaller than the
+ * allotted storage size. Shrink the
+ * allotted storage space.
+ */
+ PRINTM(MINFO,
+ "AppControl: Smaller Duplicate Beacon (%d), "
+ "old = %d, new = %d, space = %d, left = %d\n",
+ beacon_idx, old_bcn_size, new_bcn_size,
+ bcn_space,
+ (pmadapter->bcn_buf_size -
+ (pmadapter->pbcn_buf_end -
+ pmadapter->bcn_buf)));
+
+ /*
+ * memmove (since the memory overlaps) the data
+ * after the beacon we just stored to the end
+ * of the current beacon. This cleans up any
+ * unused space the old larger beacon was using
+ * in the buffer
+ */
+ memmove(pmadapter,
+ (void *)((t_ptr)pbcn_store +
+ (t_ptr)old_bcn_size),
+ (void *)((t_ptr)pbcn_store +
+ (t_ptr)bcn_space),
+ (t_u32)((t_ptr)pmadapter->pbcn_buf_end -
+ ((t_ptr)pbcn_store +
+ (t_ptr)bcn_space)));
+
+ /*
+ * Decrement the end pointer by the difference
+ * between the old larger size and the new
+ * smaller size since we are using less space
+ * due to the new beacon being smaller
+ */
+ pmadapter->pbcn_buf_end -=
+ (bcn_space - old_bcn_size);
+
+ /*
+ * Set the maximum storage size to the old
+ * beacon size
+ */
+ pnew_beacon->beacon_buf_size_max = old_bcn_size;
+
+ /* Adjust beacon buffer pointers that are past
+ * the current */
+ for (adj_idx = 0; adj_idx < num_of_ent;
+ adj_idx++) {
+ if (pmadapter->pscan_table[adj_idx]
+ .pbeacon_buf > pbcn_store) {
+ pmadapter->pscan_table[adj_idx]
+ .pbeacon_buf -=
+ (bcn_space -
+ old_bcn_size);
+ wlan_adjust_ie_in_bss_entry(
+ pmpriv,
+ &pmadapter->pscan_table
+ [adj_idx]);
+ }
+ }
+ }
+ } else if (pmadapter->pbcn_buf_end +
+ (new_bcn_size - bcn_space) <
+ (pmadapter->bcn_buf + pmadapter->bcn_buf_size)) {
+ /*
+ * Beacon is larger than space previously allocated
+ * (bcn_space) and there is enough space left in the
+ * beaconBuffer to store the additional data
+ */
+ PRINTM(MINFO,
+ "AppControl: Larger Duplicate Beacon (%d), "
+ "old = %d, new = %d, space = %d, left = %d\n",
+ beacon_idx, old_bcn_size, new_bcn_size,
+ bcn_space,
+ (pmadapter->bcn_buf_size -
+ (pmadapter->pbcn_buf_end - pmadapter->bcn_buf)));
+
+ /*
+ * memmove (since the memory overlaps) the data
+ * after the beacon we just stored to the end of
+ * the current beacon. This moves the data for
+ * the beacons after this further in memory to
+ * make space for the new larger beacon we are
+ * about to copy in.
+ */
+ memmove(pmadapter,
+ (void *)((t_ptr)pbcn_store +
+ (t_ptr)new_bcn_size),
+ (void *)((t_ptr)pbcn_store + (t_ptr)bcn_space),
+ (t_u32)((t_ptr)pmadapter->pbcn_buf_end -
+ ((t_ptr)pbcn_store + (t_ptr)bcn_space)));
+
+ /* Copy the new beacon buffer entry over the old one */
+ memcpy_ext(pmadapter, pbcn_store,
+ pnew_beacon->pbeacon_buf, new_bcn_size,
+ new_bcn_size);
+
+ /*
+ * Move the beacon end pointer by the amount of new
+ * beacon data we are adding
+ */
+ pmadapter->pbcn_buf_end += (new_bcn_size - bcn_space);
+
+ /*
+ * This entry is bigger than the allotted max space
+ * previously reserved. Increase the max space to
+ * be equal to the new beacon size
+ */
+ pnew_beacon->beacon_buf_size_max = new_bcn_size;
+
+ /* Adjust beacon buffer pointers that are past the
+ * current */
+ for (adj_idx = 0; adj_idx < num_of_ent; adj_idx++) {
+ if (pmadapter->pscan_table[adj_idx].pbeacon_buf >
+ pbcn_store) {
+ pmadapter->pscan_table[adj_idx]
+ .pbeacon_buf +=
+ (new_bcn_size - bcn_space);
+ wlan_adjust_ie_in_bss_entry(
+ pmpriv,
+ &pmadapter->pscan_table[adj_idx]);
+ }
+ }
+ } else {
+ /*
+ * Beacon is larger than the previously allocated
+ * space, but there is not enough free space to
+ * store the additional data
+ */
+ PRINTM(MERROR,
+ "AppControl: Failed: Larger Duplicate Beacon (%d),"
+ " old = %d, new = %d, space = %d, left = %d\n",
+ beacon_idx, old_bcn_size, new_bcn_size,
+ bcn_space,
+ (pmadapter->bcn_buf_size -
+ (pmadapter->pbcn_buf_end - pmadapter->bcn_buf)));
+
+ /* Storage failure, keep old beacon intact */
+ pnew_beacon->beacon_buf_size = old_bcn_size;
+ if (pnew_beacon->pwpa_ie)
+ pnew_beacon->wpa_offset =
+ pmadapter->pscan_table[beacon_idx]
+ .wpa_offset;
+ if (pnew_beacon->prsn_ie)
+ pnew_beacon->rsn_offset =
+ pmadapter->pscan_table[beacon_idx]
+ .rsn_offset;
+ if (pnew_beacon->pwapi_ie)
+ pnew_beacon->wapi_offset =
+ pmadapter->pscan_table[beacon_idx]
+ .wapi_offset;
+
+ if (pnew_beacon->posen_ie)
+ pnew_beacon->osen_offset =
+ pmadapter->pscan_table[beacon_idx]
+ .osen_offset;
+ if (pnew_beacon->pmd_ie)
+ pnew_beacon->md_offset =
+ pmadapter->pscan_table[beacon_idx]
+ .md_offset;
+ if (pnew_beacon->pht_cap)
+ pnew_beacon->ht_cap_offset =
+ pmadapter->pscan_table[beacon_idx]
+ .ht_cap_offset;
+ if (pnew_beacon->pht_info)
+ pnew_beacon->ht_info_offset =
+ pmadapter->pscan_table[beacon_idx]
+ .ht_info_offset;
+ if (pnew_beacon->pbss_co_2040)
+ pnew_beacon->bss_co_2040_offset =
+ pmadapter->pscan_table[beacon_idx]
+ .bss_co_2040_offset;
+ if (pnew_beacon->pext_cap)
+ pnew_beacon->ext_cap_offset =
+ pmadapter->pscan_table[beacon_idx]
+ .ext_cap_offset;
+ if (pnew_beacon->poverlap_bss_scan_param)
+ pnew_beacon->overlap_bss_offset =
+ pmadapter->pscan_table[beacon_idx]
+ .overlap_bss_offset;
+ if (pnew_beacon->pvht_cap)
+ pnew_beacon->vht_cap_offset =
+ pmadapter->pscan_table[beacon_idx]
+ .vht_cap_offset;
+ if (pnew_beacon->pvht_oprat)
+ pnew_beacon->vht_oprat_offset =
+ pmadapter->pscan_table[beacon_idx]
+ .vht_oprat_offset;
+ if (pnew_beacon->pvht_txpower)
+ pnew_beacon->vht_txpower_offset =
+ pmadapter->pscan_table[beacon_idx]
+ .vht_txpower_offset;
+ if (pnew_beacon->pext_pwer)
+ pnew_beacon->ext_pwer_offset =
+ pmadapter->pscan_table[beacon_idx]
+ .ext_pwer_offset;
+ if (pnew_beacon->pext_bssload)
+ pnew_beacon->ext_bssload_offset =
+ pmadapter->pscan_table[beacon_idx]
+ .ext_bssload_offset;
+ if (pnew_beacon->pquiet_chan)
+ pnew_beacon->quiet_chan_offset =
+ pmadapter->pscan_table[beacon_idx]
+ .quiet_chan_offset;
+ if (pnew_beacon->poper_mode)
+ pnew_beacon->oper_mode_offset =
+ pmadapter->pscan_table[beacon_idx]
+ .oper_mode_offset;
+ if (pnew_beacon->phe_cap)
+ pnew_beacon->he_cap_offset =
+ pmadapter->pscan_table[beacon_idx]
+ .he_cap_offset;
+ if (pnew_beacon->phe_oprat)
+ pnew_beacon->he_oprat_offset =
+ pmadapter->pscan_table[beacon_idx]
+ .he_oprat_offset;
+ }
+ /* Point the new entry to its permanent storage space */
+ pnew_beacon->pbeacon_buf = pbcn_store;
+ wlan_adjust_ie_in_bss_entry(pmpriv, pnew_beacon);
+ } else {
+ if ((pmadapter->pbcn_buf_end + pnew_beacon->beacon_buf_size +
+ SCAN_BEACON_ENTRY_PAD >
+ (pmadapter->bcn_buf + pmadapter->bcn_buf_size)) &&
+ (pmadapter->bcn_buf_size < MAX_SCAN_BEACON_BUFFER)) {
+ /* no space for this entry, realloc bcn buffer */
+ ret = pmadapter->callbacks.moal_malloc(
+ pmadapter->pmoal_handle,
+ pmadapter->bcn_buf_size +
+ DEFAULT_SCAN_BEACON_BUFFER,
+ MLAN_MEM_DEF, (t_u8 **)&tmp_buf);
+
+ if ((ret == MLAN_STATUS_SUCCESS) && (tmp_buf)) {
+ PRINTM(MCMND,
+ "Realloc Beacon buffer, old size=%d, new_size=%d\n",
+ pmadapter->bcn_buf_size,
+ pmadapter->bcn_buf_size +
+ DEFAULT_SCAN_BEACON_BUFFER);
+ bcn_size = pmadapter->pbcn_buf_end -
+ pmadapter->bcn_buf;
+ memcpy_ext(pmadapter, tmp_buf,
+ pmadapter->bcn_buf, bcn_size,
+ bcn_size);
+ /* Adjust beacon buffer pointers that are past
+ * the current */
+ for (adj_idx = 0; adj_idx < num_of_ent;
+ adj_idx++) {
+ bcn_offset =
+ pmadapter->pscan_table[adj_idx]
+ .pbeacon_buf -
+ pmadapter->bcn_buf;
+ pmadapter->pscan_table[adj_idx]
+ .pbeacon_buf =
+ tmp_buf + bcn_offset;
+ wlan_adjust_ie_in_bss_entry(
+ pmpriv,
+ &pmadapter->pscan_table[adj_idx]);
+ }
+ pmadapter->pbcn_buf_end = tmp_buf + bcn_size;
+ pmadapter->callbacks.moal_mfree(
+ pmadapter->pmoal_handle,
+ (t_u8 *)pmadapter->bcn_buf);
+ pmadapter->bcn_buf = tmp_buf;
+ pmadapter->bcn_buf_size +=
+ DEFAULT_SCAN_BEACON_BUFFER;
+ }
+ }
+ /*
+ * No existing beacon data exists for this entry, check to see
+ * if we can fit it in the remaining space
+ */
+ if (pmadapter->pbcn_buf_end + pnew_beacon->beacon_buf_size +
+ SCAN_BEACON_ENTRY_PAD <
+ (pmadapter->bcn_buf + pmadapter->bcn_buf_size)) {
+ /*
+ * Copy the beacon buffer data from the local entry
+ * to the adapter dev struct buffer space used to
+ * store the raw beacon data for each entry in the
+ * scan table
+ */
+ memcpy_ext(pmadapter, pmadapter->pbcn_buf_end,
+ pnew_beacon->pbeacon_buf,
+ pnew_beacon->beacon_buf_size,
+ pnew_beacon->beacon_buf_size);
+
+ /*
+ * Update the beacon ptr to point to the table
+ * save area
+ */
+ pnew_beacon->pbeacon_buf = pmadapter->pbcn_buf_end;
+ pnew_beacon->beacon_buf_size_max =
+ (pnew_beacon->beacon_buf_size +
+ SCAN_BEACON_ENTRY_PAD);
+ wlan_adjust_ie_in_bss_entry(pmpriv, pnew_beacon);
+
+ /* Increment the end pointer by the size reserved */
+ pmadapter->pbcn_buf_end +=
+ pnew_beacon->beacon_buf_size_max;
+
+ PRINTM(MINFO,
+ "AppControl: Beacon[%02d] sz=%03d,"
+ " used = %04d, left = %04d\n",
+ beacon_idx, pnew_beacon->beacon_buf_size,
+ (pmadapter->pbcn_buf_end - pmadapter->bcn_buf),
+ (pmadapter->bcn_buf_size -
+ (pmadapter->pbcn_buf_end - pmadapter->bcn_buf)));
+ } else {
+ /*
+ * No space for new beacon
+ */
+ PRINTM(MCMND,
+ "AppControl: No space beacon (%d): " MACSTR
+ "; sz=%03d, left=%03d\n",
+ beacon_idx, MAC2STR(pnew_beacon->mac_address),
+ pnew_beacon->beacon_buf_size,
+ (pmadapter->bcn_buf_size -
+ (pmadapter->pbcn_buf_end - pmadapter->bcn_buf)));
+
+ /*
+ * Storage failure; clear storage records
+ * for this bcn
+ */
+ pnew_beacon->pbeacon_buf = MNULL;
+ pnew_beacon->beacon_buf_size = 0;
+ pnew_beacon->beacon_buf_size_max = 0;
+ wlan_adjust_ie_in_bss_entry(pmpriv, pnew_beacon);
+ }
+ }
+
+ LEAVE();
+}
+
+/**
+ * @brief update beacon buffer of the current bss descriptor
+ *
+ * @param pmpriv A pointer to mlan_private structure
+ *
+ * @return MLAN_STATUS_SUCCESS, otherwise failure
+ */
+static mlan_status wlan_update_curr_bcn(mlan_private *pmpriv)
+{
+ BSSDescriptor_t *pcurr_bss = &pmpriv->curr_bss_params.bss_descriptor;
+ mlan_status ret = MLAN_STATUS_SUCCESS;
+
+ ENTER();
+
+ if (pmpriv->pcurr_bcn_buf && pmpriv->curr_bcn_size) {
+ pcurr_bss->pbeacon_buf = pmpriv->pcurr_bcn_buf;
+ pcurr_bss->beacon_buf_size = pmpriv->curr_bcn_size;
+ pcurr_bss->beacon_buf_size_max = pmpriv->curr_bcn_size;
+
+ /* adjust the pointers in the current bss descriptor */
+ if (pcurr_bss->pwpa_ie) {
+ pcurr_bss->pwpa_ie =
+ (IEEEtypes_VendorSpecific_t
+ *)(pcurr_bss->pbeacon_buf +
+ pcurr_bss->wpa_offset);
+ }
+ if (pcurr_bss->prsn_ie) {
+ pcurr_bss->prsn_ie =
+ (IEEEtypes_Generic_t *)(pcurr_bss->pbeacon_buf +
+ pcurr_bss->rsn_offset);
+ }
+ if (pcurr_bss->pmd_ie) {
+ pcurr_bss->pmd_ie = (IEEEtypes_MobilityDomain_t
+ *)(pcurr_bss->pbeacon_buf +
+ pcurr_bss->md_offset);
+ }
+ if (pcurr_bss->pht_cap) {
+ pcurr_bss->pht_cap =
+ (IEEEtypes_HTCap_t *)(pcurr_bss->pbeacon_buf +
+ pcurr_bss->ht_cap_offset);
+ }
+
+ if (pcurr_bss->pht_info) {
+ pcurr_bss->pht_info =
+ (IEEEtypes_HTInfo_t
+ *)(pcurr_bss->pbeacon_buf +
+ pcurr_bss->ht_info_offset);
+ }
+
+ if (pcurr_bss->pbss_co_2040) {
+ pcurr_bss->pbss_co_2040 =
+ (IEEEtypes_2040BSSCo_t
+ *)(pcurr_bss->pbeacon_buf +
+ pcurr_bss->bss_co_2040_offset);
+ }
+
+ if (pcurr_bss->pext_cap) {
+ pcurr_bss->pext_cap =
+ (IEEEtypes_ExtCap_t
+ *)(pcurr_bss->pbeacon_buf +
+ pcurr_bss->ext_cap_offset);
+ }
+
+ if (pcurr_bss->poverlap_bss_scan_param) {
+ pcurr_bss->poverlap_bss_scan_param =
+ (IEEEtypes_OverlapBSSScanParam_t
+ *)(pcurr_bss->pbeacon_buf +
+ pcurr_bss->overlap_bss_offset);
+ }
+
+ if (pcurr_bss->pvht_cap) {
+ pcurr_bss->pvht_cap =
+ (IEEEtypes_VHTCap_t
+ *)(pcurr_bss->pbeacon_buf +
+ pcurr_bss->vht_cap_offset);
+ }
+
+ if (pcurr_bss->pvht_oprat) {
+ pcurr_bss->pvht_oprat =
+ (IEEEtypes_VHTOprat_t
+ *)(pcurr_bss->pbeacon_buf +
+ pcurr_bss->vht_oprat_offset);
+ }
+
+ if (pcurr_bss->pvht_txpower) {
+ pcurr_bss->pvht_txpower =
+ (IEEEtypes_VHTtxpower_t
+ *)(pcurr_bss->pbeacon_buf +
+ pcurr_bss->vht_txpower_offset);
+ }
+
+ if (pcurr_bss->pext_pwer) {
+ pcurr_bss->pext_pwer =
+ (IEEEtypes_ExtPwerCons_t
+ *)(pcurr_bss->pbeacon_buf +
+ pcurr_bss->ext_pwer_offset);
+ }
+
+ if (pcurr_bss->pext_bssload) {
+ pcurr_bss->pext_bssload =
+ (IEEEtypes_ExtBSSload_t
+ *)(pcurr_bss->pbeacon_buf +
+ pcurr_bss->ext_bssload_offset);
+ }
+
+ if (pcurr_bss->pquiet_chan) {
+ pcurr_bss->pquiet_chan =
+ (IEEEtypes_QuietChan_t
+ *)(pcurr_bss->pbeacon_buf +
+ pcurr_bss->quiet_chan_offset);
+ }
+
+ if (pcurr_bss->poper_mode) {
+ pcurr_bss->poper_mode =
+ (IEEEtypes_OperModeNtf_t
+ *)(pcurr_bss->pbeacon_buf +
+ pcurr_bss->oper_mode_offset);
+ }
+ if (pcurr_bss->phe_cap) {
+ pcurr_bss->phe_cap =
+ (IEEEtypes_HECap_t *)(pcurr_bss->pbeacon_buf +
+ pcurr_bss->he_cap_offset);
+ }
+
+ if (pcurr_bss->phe_oprat) {
+ pcurr_bss->phe_oprat =
+ (IEEEtypes_Extension_t
+ *)(pcurr_bss->pbeacon_buf +
+ pcurr_bss->he_oprat_offset);
+ }
+
+ PRINTM(MINFO, "current beacon restored %d\n",
+ pmpriv->curr_bcn_size);
+ } else {
+ PRINTM(MERROR, "curr_bcn_buf not saved\n");
+ ret = MLAN_STATUS_FAILURE;
+ }
+
+ LEAVE();
+ return ret;
+}
+
+/**
+ * @brief get the chan load from chan stats.
+ *
+ * @param pmadapter A pointer to mlan_adapter structure
+ * @param channel channel *
+ *
+ * @return channel load
+ */
+static t_u16 wlan_get_chan_load(mlan_adapter *pmadapter, t_u8 channel)
+{
+ t_u16 chan_load = 0;
+ int i;
+ for (i = 0; i < pmadapter->num_in_chan_stats; i++) {
+ if ((pmadapter->pchan_stats[i].chan_num == channel) &&
+ pmadapter->pchan_stats[i].cca_scan_duration) {
+ chan_load =
+ (pmadapter->pchan_stats[i].cca_busy_duration *
+ 100) /
+ pmadapter->pchan_stats[i].cca_scan_duration;
+ break;
+ }
+ }
+ return chan_load;
+}
+
+/**
+ * @brief get the chan min/max rssi
+ *
+ * @param pmadapter A pointer to mlan_adapter structure
+ * @param channel channel *
+ * @param min_flag flag to get min rssi
+ * @return rssi
+ */
+static t_u8 wlan_get_chan_rssi(mlan_adapter *pmadapter, t_u8 channel,
+ t_u8 min_flag)
+{
+ t_u8 rssi = 0;
+ int i;
+ for (i = 0; i < pmadapter->num_in_scan_table; i++) {
+ if (pmadapter->pscan_table[i].channel == channel) {
+ if (rssi == 0)
+ rssi = (t_s32)pmadapter->pscan_table[i].rssi;
+ else {
+ if (min_flag)
+ rssi = MIN(
+ rssi,
+ pmadapter->pscan_table[i].rssi);
+ else
+ rssi = MAX(
+ rssi,
+ pmadapter->pscan_table[i].rssi);
+ }
+ }
+ }
+ return rssi;
+}
+
+/**
+ * @brief update the min/max rssi for channel statistics.
+ *
+ * @param pmadapter A pointer to mlan_adapter structure
+ * @return N/A
+ */
+static t_void wlan_update_chan_rssi(mlan_adapter *pmadapter)
+{
+ int i;
+ t_s8 min_rssi = 0;
+ t_s8 max_rssi = 0;
+ t_s8 rss = 0;
+ for (i = 0; i < pmadapter->num_in_chan_stats; i++) {
+ if (pmadapter->pchan_stats[i].chan_num &&
+ pmadapter->pchan_stats[i].cca_scan_duration) {
+ min_rssi = -wlan_get_chan_rssi(
+ pmadapter, pmadapter->pchan_stats[i].chan_num,
+ MFALSE);
+ max_rssi = -wlan_get_chan_rssi(
+ pmadapter, pmadapter->pchan_stats[i].chan_num,
+ MTRUE);
+ rss = min_rssi - pmadapter->pchan_stats[i].noise;
+ // rss should always > 0, FW need fix the wrong
+ // rssi/noise in scantable
+ if (rss > 0)
+ pmadapter->pchan_stats[i].min_rss = rss;
+ else
+ pmadapter->pchan_stats[i].min_rss = 0;
+
+ rss = max_rssi - pmadapter->pchan_stats[i].noise;
+ if (rss > 0)
+ pmadapter->pchan_stats[i].max_rss = rss;
+ else
+ pmadapter->pchan_stats[i].max_rss = 0;
+ PRINTM(MCMND,
+ "chan=%d, min_rssi=%d, max_rssi=%d noise=%d min_rss=%d, max_rss=%d\n",
+ pmadapter->pchan_stats[i].chan_num, min_rssi,
+ max_rssi, pmadapter->pchan_stats[i].noise,
+ pmadapter->pchan_stats[i].min_rss,
+ pmadapter->pchan_stats[i].max_rss);
+ }
+ }
+ return;
+}
+
+/**
+ * @brief Post process the scan table after a new scan command has completed
+ *
+ * Inspect each entry of the scan table and try to find an entry that
+ * matches our current associated/joined network from the scan. If
+ * one is found, update the stored copy of the BSSDescriptor for our
+ * current network.
+ *
+ * Debug dump the current scan table contents if compiled accordingly.
+ *
+ * @param pmpriv A pointer to mlan_private structure
+ *
+ * @return N/A
+ */
+static t_void wlan_scan_process_results(mlan_private *pmpriv)
+{
+ mlan_adapter *pmadapter = pmpriv->adapter;
+ t_s32 j;
+ t_u32 i;
+ mlan_status ret = MLAN_STATUS_SUCCESS;
+ BSSDescriptor_t *bss_new_entry = MNULL;
+ pmlan_callbacks pcb = &pmadapter->callbacks;
+
+ ENTER();
+
+ if (pmpriv->media_connected == MTRUE) {
+ j = wlan_find_bssid_in_list(
+ pmpriv,
+ pmpriv->curr_bss_params.bss_descriptor.mac_address,
+ pmpriv->bss_mode);
+
+ if (j >= 0) {
+ memcpy_ext(pmadapter, &pmadapter->pscan_table[j].ssid,
+ &pmpriv->curr_bss_params.bss_descriptor.ssid,
+ sizeof(mlan_802_11_ssid),
+ sizeof(mlan_802_11_ssid));
+ pmadapter->callbacks.moal_spin_lock(
+ pmadapter->pmoal_handle,
+ pmpriv->curr_bcn_buf_lock);
+ pmpriv->curr_bss_params.bss_descriptor.pwpa_ie = MNULL;
+ pmpriv->curr_bss_params.bss_descriptor.wpa_offset = 0;
+ pmpriv->curr_bss_params.bss_descriptor.prsn_ie = MNULL;
+ pmpriv->curr_bss_params.bss_descriptor.rsn_offset = 0;
+ pmpriv->curr_bss_params.bss_descriptor.pwapi_ie = MNULL;
+ pmpriv->curr_bss_params.bss_descriptor.wapi_offset = 0;
+
+ pmpriv->curr_bss_params.bss_descriptor.posen_ie = MNULL;
+ pmpriv->curr_bss_params.bss_descriptor.osen_offset = 0;
+ pmpriv->curr_bss_params.bss_descriptor.pmd_ie = MNULL;
+ pmpriv->curr_bss_params.bss_descriptor.md_offset = 0;
+ pmpriv->curr_bss_params.bss_descriptor.pht_cap = MNULL;
+ pmpriv->curr_bss_params.bss_descriptor.ht_cap_offset =
+ 0;
+ pmpriv->curr_bss_params.bss_descriptor.pht_info = MNULL;
+ pmpriv->curr_bss_params.bss_descriptor.ht_info_offset =
+ 0;
+ pmpriv->curr_bss_params.bss_descriptor.pbss_co_2040 =
+ MNULL;
+ pmpriv->curr_bss_params.bss_descriptor
+ .bss_co_2040_offset = 0;
+ pmpriv->curr_bss_params.bss_descriptor.pext_cap = MNULL;
+ pmpriv->curr_bss_params.bss_descriptor.ext_cap_offset =
+ 0;
+ pmpriv->curr_bss_params.bss_descriptor
+ .poverlap_bss_scan_param = MNULL;
+ pmpriv->curr_bss_params.bss_descriptor
+ .overlap_bss_offset = 0;
+ pmpriv->curr_bss_params.bss_descriptor.pvht_cap = MNULL;
+ pmpriv->curr_bss_params.bss_descriptor.vht_cap_offset =
+ 0;
+ pmpriv->curr_bss_params.bss_descriptor.pvht_oprat =
+ MNULL;
+ pmpriv->curr_bss_params.bss_descriptor.vht_oprat_offset =
+ 0;
+ pmpriv->curr_bss_params.bss_descriptor.pvht_txpower =
+ MNULL;
+ pmpriv->curr_bss_params.bss_descriptor
+ .vht_txpower_offset = 0;
+ pmpriv->curr_bss_params.bss_descriptor.pext_pwer =
+ MNULL;
+ pmpriv->curr_bss_params.bss_descriptor.ext_pwer_offset =
+ 0;
+ pmpriv->curr_bss_params.bss_descriptor.pext_bssload =
+ MNULL;
+ pmpriv->curr_bss_params.bss_descriptor
+ .ext_bssload_offset = 0;
+ pmpriv->curr_bss_params.bss_descriptor.pquiet_chan =
+ MNULL;
+ pmpriv->curr_bss_params.bss_descriptor
+ .quiet_chan_offset = 0;
+ pmpriv->curr_bss_params.bss_descriptor.poper_mode =
+ MNULL;
+ pmpriv->curr_bss_params.bss_descriptor.oper_mode_offset =
+ 0;
+ pmpriv->curr_bss_params.bss_descriptor.phe_cap = MNULL;
+ pmpriv->curr_bss_params.bss_descriptor.he_cap_offset =
+ 0;
+ pmpriv->curr_bss_params.bss_descriptor.phe_oprat =
+ MNULL;
+ pmpriv->curr_bss_params.bss_descriptor.he_oprat_offset =
+ 0;
+ pmpriv->curr_bss_params.bss_descriptor.pbeacon_buf =
+ MNULL;
+ pmpriv->curr_bss_params.bss_descriptor.beacon_buf_size =
+ 0;
+ pmpriv->curr_bss_params.bss_descriptor
+ .beacon_buf_size_max = 0;
+
+ PRINTM(MINFO,
+ "Found current ssid/bssid in list @ index #%d\n",
+ j);
+ /* Make a copy of current BSSID descriptor */
+ memcpy_ext(
+ pmadapter,
+ &pmpriv->curr_bss_params.bss_descriptor,
+ &pmadapter->pscan_table[j],
+ sizeof(pmpriv->curr_bss_params.bss_descriptor),
+ sizeof(pmpriv->curr_bss_params.bss_descriptor));
+
+ pmadapter->callbacks.moal_spin_unlock(
+ pmadapter->pmoal_handle,
+ pmpriv->curr_bcn_buf_lock);
+ wlan_save_curr_bcn(pmpriv);
+ } else {
+ // Apend to the end of scan table
+ if (pmpriv->pcurr_bcn_buf && pmpriv->curr_bcn_size) {
+ ret = pcb->moal_malloc(pmadapter->pmoal_handle,
+ sizeof(BSSDescriptor_t),
+ MLAN_MEM_DEF,
+ (t_u8 **)&bss_new_entry);
+ if (ret == MLAN_STATUS_SUCCESS &&
+ bss_new_entry) {
+ memcpy_ext(
+ pmadapter, bss_new_entry,
+ &pmpriv->curr_bss_params
+ .bss_descriptor,
+ sizeof(pmpriv->curr_bss_params
+ .bss_descriptor),
+ sizeof(BSSDescriptor_t));
+ if (pmadapter->num_in_scan_table <
+ MRVDRV_MAX_BSSID_LIST)
+ pmadapter->num_in_scan_table++;
+ pmadapter
+ ->pscan_table
+ [pmadapter->num_in_scan_table -
+ 1]
+ .pbeacon_buf = MNULL;
+ wlan_ret_802_11_scan_store_beacon(
+ pmpriv,
+ pmadapter->num_in_scan_table -
+ 1,
+ pmadapter->num_in_scan_table,
+ bss_new_entry);
+ if (bss_new_entry->pbeacon_buf == MNULL)
+ pmadapter->num_in_scan_table--;
+ else
+ memcpy_ext(
+ pmadapter,
+ &pmadapter->pscan_table
+ [pmadapter->num_in_scan_table -
+ 1],
+ bss_new_entry,
+ sizeof(BSSDescriptor_t),
+ sizeof(BSSDescriptor_t));
+ pcb->moal_mfree(pmadapter->pmoal_handle,
+ (t_u8 *)bss_new_entry);
+ }
+ }
+ }
+ }
+
+ for (i = 0; i < pmadapter->num_in_scan_table; i++) {
+ PRINTM(MINFO,
+ "Scan:(%02d) " MACSTR ", "
+ "RSSI[%03d], SSID[%s]\n",
+ i, MAC2STR(pmadapter->pscan_table[i].mac_address),
+ (t_s32)pmadapter->pscan_table[i].rssi,
+ pmadapter->pscan_table[i].ssid.ssid);
+ pmadapter->pscan_table[i].chan_load = wlan_get_chan_load(
+ pmadapter, pmadapter->pscan_table[i].channel);
+ }
+ wlan_update_chan_rssi(pmadapter);
+
+ /*
+ * Prepares domain info from scan table and downloads the
+ * domain info command to the FW.
+ */
+ wlan_11d_prepare_dnld_domain_info_cmd(pmpriv);
+ PRINTM(MMSG, "wlan: SCAN COMPLETED: scanned AP count=%d\n",
+ pmadapter->num_in_scan_table);
+ LEAVE();
+}
+
+/**
+ * @brief Delete a specific indexed entry from the scan table.
+ *
+ * Delete the scan table entry indexed by table_idx. Compact the remaining
+ * entries and adjust any buffering of beacon/probe response data
+ * if needed.
+ *
+ * @param pmpriv A pointer to mlan_private structure
+ * @param table_idx Scan table entry index to delete from the table
+ *
+ * @return N/A
+ *
+ * @pre table_idx must be an index to a valid entry
+ */
+static t_void wlan_scan_delete_table_entry(mlan_private *pmpriv,
+ t_s32 table_idx)
+{
+ mlan_adapter *pmadapter = pmpriv->adapter;
+ t_u32 del_idx;
+ t_u32 beacon_buf_adj;
+ t_u8 *pbeacon_buf;
+
+ ENTER();
+
+ /*
+ * Shift the saved beacon buffer data for the scan table back over the
+ * entry being removed. Update the end of buffer pointer. Save the
+ * deleted buffer allocation size for pointer adjustments for entries
+ * compacted after the deleted index.
+ */
+ beacon_buf_adj = pmadapter->pscan_table[table_idx].beacon_buf_size_max;
+
+ PRINTM(MINFO,
+ "Scan: Delete Entry %d, beacon buffer removal = %d bytes\n",
+ table_idx, beacon_buf_adj);
+
+ /* Check if the table entry had storage allocated for its beacon */
+ if (beacon_buf_adj) {
+ pbeacon_buf = pmadapter->pscan_table[table_idx].pbeacon_buf;
+
+ /*
+ * Remove the entry's buffer space, decrement the table
+ * end pointer by the amount we are removing
+ */
+ pmadapter->pbcn_buf_end -= beacon_buf_adj;
+
+ PRINTM(MINFO,
+ "Scan: Delete Entry %d, compact data: %p <- %p (sz = %d)\n",
+ table_idx, pbeacon_buf, pbeacon_buf + beacon_buf_adj,
+ pmadapter->pbcn_buf_end - pbeacon_buf);
+
+ /*
+ * Compact data storage. Copy all data after the deleted
+ * entry's end address (pbeacon_buf + beacon_buf_adj) back to
+ * the original start address (pbeacon_buf).
+ *
+ * Scan table entries affected by the move will have their entry
+ * pointer adjusted below.
+ *
+ * Use memmove since the dest/src memory regions overlap.
+ */
+ memmove(pmadapter, pbeacon_buf,
+ (void *)((t_ptr)pbeacon_buf + (t_ptr)beacon_buf_adj),
+ (t_u32)((t_ptr)pmadapter->pbcn_buf_end -
+ (t_ptr)pbeacon_buf));
+ }
+
+ PRINTM(MINFO, "Scan: Delete Entry %d, num_in_scan_table = %d\n",
+ table_idx, pmadapter->num_in_scan_table);
+
+ /*
+ * Shift all of the entries after the table_idx back by one, compacting
+ * the table and removing the requested entry
+ */
+ for (del_idx = table_idx; (del_idx + 1) < pmadapter->num_in_scan_table;
+ del_idx++) {
+ /* Copy the next entry over this one */
+ memcpy_ext(pmadapter, pmadapter->pscan_table + del_idx,
+ pmadapter->pscan_table + del_idx + 1,
+ sizeof(BSSDescriptor_t), sizeof(BSSDescriptor_t));
+
+ /*
+ * Adjust this entry's pointer to its beacon buffer based on the
+ * removed/compacted entry from the deleted index. Don't
+ * decrement if the buffer pointer is MNULL (no data stored for
+ * this entry).
+ */
+ if (pmadapter->pscan_table[del_idx].pbeacon_buf) {
+ pmadapter->pscan_table[del_idx].pbeacon_buf -=
+ beacon_buf_adj;
+ if (pmadapter->pscan_table[del_idx].pwpa_ie) {
+ pmadapter->pscan_table[del_idx].pwpa_ie =
+ (IEEEtypes_VendorSpecific_t
+ *)(pmadapter
+ ->pscan_table[del_idx]
+ .pbeacon_buf +
+ pmadapter
+ ->pscan_table[del_idx]
+ .wpa_offset);
+ }
+ if (pmadapter->pscan_table[del_idx].prsn_ie) {
+ pmadapter->pscan_table[del_idx].prsn_ie =
+ (IEEEtypes_Generic_t
+ *)(pmadapter
+ ->pscan_table[del_idx]
+ .pbeacon_buf +
+ pmadapter
+ ->pscan_table[del_idx]
+ .rsn_offset);
+ }
+ if (pmadapter->pscan_table[del_idx].pwapi_ie) {
+ pmadapter->pscan_table[del_idx].pwapi_ie =
+ (IEEEtypes_Generic_t
+ *)(pmadapter
+ ->pscan_table[del_idx]
+ .pbeacon_buf +
+ pmadapter
+ ->pscan_table[del_idx]
+ .wapi_offset);
+ }
+
+ if (pmadapter->pscan_table[del_idx].posen_ie) {
+ pmadapter->pscan_table[del_idx].posen_ie =
+ (IEEEtypes_Generic_t
+ *)(pmadapter
+ ->pscan_table[del_idx]
+ .pbeacon_buf +
+ pmadapter
+ ->pscan_table[del_idx]
+ .osen_offset);
+ }
+ if (pmadapter->pscan_table[del_idx].pmd_ie) {
+ pmadapter->pscan_table[del_idx].pmd_ie =
+ (IEEEtypes_MobilityDomain_t
+ *)(pmadapter
+ ->pscan_table[del_idx]
+ .pbeacon_buf +
+ pmadapter
+ ->pscan_table[del_idx]
+ .md_offset);
+ }
+ if (pmadapter->pscan_table[del_idx].pht_cap) {
+ pmadapter->pscan_table[del_idx].pht_cap =
+ (IEEEtypes_HTCap_t
+ *)(pmadapter
+ ->pscan_table[del_idx]
+ .pbeacon_buf +
+ pmadapter
+ ->pscan_table[del_idx]
+ .ht_cap_offset);
+ }
+
+ if (pmadapter->pscan_table[del_idx].pht_info) {
+ pmadapter->pscan_table[del_idx].pht_info =
+ (IEEEtypes_HTInfo_t
+ *)(pmadapter
+ ->pscan_table[del_idx]
+ .pbeacon_buf +
+ pmadapter
+ ->pscan_table[del_idx]
+ .ht_info_offset);
+ }
+ if (pmadapter->pscan_table[del_idx].pbss_co_2040) {
+ pmadapter->pscan_table[del_idx].pbss_co_2040 =
+ (IEEEtypes_2040BSSCo_t
+ *)(pmadapter
+ ->pscan_table[del_idx]
+ .pbeacon_buf +
+ pmadapter
+ ->pscan_table[del_idx]
+ .bss_co_2040_offset);
+ }
+ if (pmadapter->pscan_table[del_idx].pext_cap) {
+ pmadapter->pscan_table[del_idx].pext_cap =
+ (IEEEtypes_ExtCap_t
+ *)(pmadapter
+ ->pscan_table[del_idx]
+ .pbeacon_buf +
+ pmadapter
+ ->pscan_table[del_idx]
+ .ext_cap_offset);
+ }
+ if (pmadapter->pscan_table[del_idx]
+ .poverlap_bss_scan_param) {
+ pmadapter->pscan_table[del_idx]
+ .poverlap_bss_scan_param =
+ (IEEEtypes_OverlapBSSScanParam_t
+ *)(pmadapter
+ ->pscan_table[del_idx]
+ .pbeacon_buf +
+ pmadapter
+ ->pscan_table[del_idx]
+ .overlap_bss_offset);
+ }
+
+ if (pmadapter->pscan_table[del_idx].pvht_cap) {
+ pmadapter->pscan_table[del_idx].pvht_cap =
+ (IEEEtypes_VHTCap_t
+ *)(pmadapter
+ ->pscan_table[del_idx]
+ .pbeacon_buf +
+ pmadapter
+ ->pscan_table[del_idx]
+ .vht_cap_offset);
+ }
+
+ if (pmadapter->pscan_table[del_idx].pvht_oprat) {
+ pmadapter->pscan_table[del_idx].pvht_oprat =
+ (IEEEtypes_VHTOprat_t
+ *)(pmadapter
+ ->pscan_table[del_idx]
+ .pbeacon_buf +
+ pmadapter
+ ->pscan_table[del_idx]
+ .vht_oprat_offset);
+ }
+ if (pmadapter->pscan_table[del_idx].pvht_txpower) {
+ pmadapter->pscan_table[del_idx].pvht_txpower =
+ (IEEEtypes_VHTtxpower_t
+ *)(pmadapter
+ ->pscan_table[del_idx]
+ .pbeacon_buf +
+ pmadapter
+ ->pscan_table[del_idx]
+ .vht_txpower_offset);
+ }
+ if (pmadapter->pscan_table[del_idx].pext_pwer) {
+ pmadapter->pscan_table[del_idx].pext_pwer =
+ (IEEEtypes_ExtPwerCons_t
+ *)(pmadapter
+ ->pscan_table[del_idx]
+ .pbeacon_buf +
+ pmadapter
+ ->pscan_table[del_idx]
+ .ext_pwer_offset);
+ }
+ if (pmadapter->pscan_table[del_idx].pext_bssload) {
+ pmadapter->pscan_table[del_idx].pext_bssload =
+ (IEEEtypes_ExtBSSload_t
+ *)(pmadapter
+ ->pscan_table[del_idx]
+ .pbeacon_buf +
+ pmadapter
+ ->pscan_table[del_idx]
+ .ext_bssload_offset);
+ }
+ if (pmadapter->pscan_table[del_idx].pquiet_chan) {
+ pmadapter->pscan_table[del_idx].pquiet_chan =
+ (IEEEtypes_QuietChan_t
+ *)(pmadapter
+ ->pscan_table[del_idx]
+ .pbeacon_buf +
+ pmadapter
+ ->pscan_table[del_idx]
+ .quiet_chan_offset);
+ }
+ if (pmadapter->pscan_table[del_idx].poper_mode) {
+ pmadapter->pscan_table[del_idx].poper_mode =
+ (IEEEtypes_OperModeNtf_t
+ *)(pmadapter
+ ->pscan_table[del_idx]
+ .pbeacon_buf +
+ pmadapter
+ ->pscan_table[del_idx]
+ .oper_mode_offset);
+ }
+ if (pmadapter->pscan_table[del_idx].phe_cap) {
+ pmadapter->pscan_table[del_idx].phe_cap =
+ (IEEEtypes_HECap_t
+ *)(pmadapter
+ ->pscan_table[del_idx]
+ .pbeacon_buf +
+ pmadapter
+ ->pscan_table[del_idx]
+ .he_cap_offset);
+ }
+ if (pmadapter->pscan_table[del_idx].phe_oprat) {
+ pmadapter->pscan_table[del_idx].phe_oprat =
+ (IEEEtypes_Extension_t
+ *)(pmadapter
+ ->pscan_table[del_idx]
+ .pbeacon_buf +
+ pmadapter
+ ->pscan_table[del_idx]
+ .he_oprat_offset);
+ }
+ }
+ }
+
+ /* The last entry is invalid now that it has been deleted or moved back
+ */
+ memset(pmadapter,
+ pmadapter->pscan_table + pmadapter->num_in_scan_table - 1, 0x00,
+ sizeof(BSSDescriptor_t));
+
+ pmadapter->num_in_scan_table--;
+
+ LEAVE();
+}
+
+/**
+ * @brief Delete all occurrences of a given SSID from the scan table
+ *
+ * Iterate through the scan table and delete all entries that match a given
+ * SSID. Compact the remaining scan table entries.
+ *
+ * @param pmpriv A pointer to mlan_private structure
+ * @param pdel_ssid Pointer to an SSID to be used in deleting all
+ * matching SSIDs from the scan table
+ *
+ * @return MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ */
+static mlan_status
+wlan_scan_delete_ssid_table_entry(mlan_private *pmpriv,
+ mlan_802_11_ssid *pdel_ssid)
+{
+ mlan_status ret = MLAN_STATUS_FAILURE;
+ t_s32 table_idx;
+
+ ENTER();
+
+ PRINTM(MINFO, "Scan: Delete Ssid Entry: %-32s\n", pdel_ssid->ssid);
+
+ /*
+ * If the requested SSID is found in the table, delete it. Then keep
+ * searching the table for multiple entries for the SSID until no
+ * more are found
+ */
+ while ((table_idx = wlan_find_ssid_in_list(pmpriv, pdel_ssid, MNULL,
+ MLAN_BSS_MODE_AUTO)) >= 0) {
+ PRINTM(MINFO, "Scan: Delete SSID Entry: Found Idx = %d\n",
+ table_idx);
+ ret = MLAN_STATUS_SUCCESS;
+ wlan_scan_delete_table_entry(pmpriv, table_idx);
+ }
+
+ LEAVE();
+ return ret;
+}
+
+/********************************************************
+ Global Functions
+********************************************************/
+
+/**
+ * @brief Check if a scanned network 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
+ *
+ * @param pmpriv A pointer to mlan_private
+ * @param index Index in scan table to check against current driver settings
+ * @param mode Network mode: Infrastructure or IBSS
+ *
+ * @return Index in ScanTable, or negative value if error
+ */
+t_s32 wlan_is_network_compatible(mlan_private *pmpriv, t_u32 index, t_u32 mode)
+{
+ mlan_adapter *pmadapter = pmpriv->adapter;
+ BSSDescriptor_t *pbss_desc;
+
+ ENTER();
+
+ pbss_desc = &pmadapter->pscan_table[index];
+ /* Don't check for compatibility if roaming */
+ if ((pmpriv->media_connected == MTRUE) &&
+ (pmpriv->bss_mode == MLAN_BSS_MODE_INFRA) &&
+ (pbss_desc->bss_mode == MLAN_BSS_MODE_INFRA)) {
+ LEAVE();
+ return index;
+ }
+
+ pbss_desc->disable_11n = MFALSE;
+
+ /* if the HE CAP IE exists, HT CAP IE should exist too */
+ /* 2.4G AX AP, don't have VHT CAP */
+ if (pbss_desc->phe_cap && !pbss_desc->pht_cap) {
+ PRINTM(MINFO,
+ "Disable 11n if VHT CAP/HT CAP IE is not found from the 11AX AP\n");
+ pbss_desc->disable_11n = MTRUE;
+ }
+
+ /* if the VHT CAP IE exists, the HT CAP IE should exist too */
+ if (pbss_desc->pvht_cap && !pbss_desc->pht_cap) {
+ PRINTM(MINFO,
+ "Disable 11n if HT CAP IE is not found from the 11AC AP\n");
+ pbss_desc->disable_11n = MTRUE;
+ }
+
+ if (pbss_desc->wlan_11h_bss_info.chan_switch_ann.element_id ==
+ CHANNEL_SWITCH_ANN) {
+ PRINTM(MINFO,
+ "Don't connect to AP with CHANNEL_SWITCH_ANN IE.\n");
+ LEAVE();
+ return -1;
+ }
+
+ if (pmpriv->wps.session_enable == MTRUE) {
+ PRINTM(MINFO, "Return success directly in WPS period\n");
+ LEAVE();
+ return index;
+ }
+
+ if (pmpriv->sec_info.osen_enabled && pbss_desc->posen_ie &&
+ ((*(pbss_desc->posen_ie)).ieee_hdr.element_id ==
+ VENDOR_SPECIFIC_221)) {
+ /* Hotspot 2.0 OSEN AKM */
+ PRINTM(MMSG,
+ "Return success directly in Hotspot OSEN: index=%d "
+ "encryption_mode=%#x\n",
+ index, pmpriv->sec_info.encryption_mode);
+ LEAVE();
+ return index;
+ }
+
+ if ((pbss_desc->bss_mode == mode) &&
+ (pmpriv->sec_info.ewpa_enabled == MTRUE
+#ifdef DRV_EMBEDDED_SUPPLICANT
+ || supplicantIsEnabled(pmpriv->psapriv)
+#endif
+ )) {
+ if (((pbss_desc->pwpa_ie) &&
+ ((*(pbss_desc->pwpa_ie)).vend_hdr.element_id == WPA_IE)) ||
+ ((pbss_desc->prsn_ie) &&
+ ((*(pbss_desc->prsn_ie)).ieee_hdr.element_id == RSN_IE))) {
+ if (((pmpriv->adapter->config_bands & BAND_GN ||
+ pmpriv->adapter->config_bands & BAND_AN) &&
+ pbss_desc->pht_cap) &&
+ (pmpriv->bss_mode == MLAN_BSS_MODE_INFRA) &&
+ !is_wpa_oui_present(pmpriv->adapter, pbss_desc,
+ CIPHER_SUITE_CCMP) &&
+ !is_rsn_oui_present(pmpriv->adapter, pbss_desc,
+ CIPHER_SUITE_CCMP) &&
+ !is_rsn_oui_present(pmpriv->adapter, pbss_desc,
+ CIPHER_SUITE_GCMP) &&
+ !is_rsn_oui_present(pmpriv->adapter, pbss_desc,
+ CIPHER_SUITE_GCMP_256) &&
+ !is_rsn_oui_present(pmpriv->adapter, pbss_desc,
+ CIPHER_SUITE_CCMP_256)) {
+ if (is_wpa_oui_present(pmpriv->adapter,
+ pbss_desc,
+ CIPHER_SUITE_TKIP) ||
+ is_rsn_oui_present(pmpriv->adapter,
+ pbss_desc,
+ CIPHER_SUITE_TKIP)) {
+ PRINTM(MINFO,
+ "Disable 11n if AES is not supported by AP\n");
+ pbss_desc->disable_11n = MTRUE;
+ } else {
+ LEAVE();
+ return -1;
+ }
+ }
+ LEAVE();
+ return index;
+ } else {
+ PRINTM(MINFO,
+ "ewpa_enabled: Ignore none WPA/WPA2 AP\n");
+ LEAVE();
+ return -1;
+ }
+ }
+
+ if (pmpriv->sec_info.wapi_enabled &&
+ (pbss_desc->pwapi_ie &&
+ ((*(pbss_desc->pwapi_ie)).ieee_hdr.element_id == WAPI_IE))) {
+ PRINTM(MINFO, "Return success for WAPI AP\n");
+ LEAVE();
+ return index;
+ }
+
+ if (pbss_desc->bss_mode == mode) {
+ if (pmpriv->sec_info.wep_status == Wlan802_11WEPDisabled &&
+ !pmpriv->sec_info.wpa_enabled &&
+ !pmpriv->sec_info.wpa2_enabled &&
+ ((!pbss_desc->pwpa_ie) ||
+ ((*(pbss_desc->pwpa_ie)).vend_hdr.element_id != WPA_IE)) &&
+ ((!pbss_desc->prsn_ie) ||
+ ((*(pbss_desc->prsn_ie)).ieee_hdr.element_id != RSN_IE)) &&
+ pmpriv->sec_info.encryption_mode ==
+ MLAN_ENCRYPTION_MODE_NONE &&
+ !pbss_desc->privacy) {
+ /* No security */
+ LEAVE();
+ return index;
+ } else if (pmpriv->sec_info.wep_status ==
+ Wlan802_11WEPEnabled &&
+ !pmpriv->sec_info.wpa_enabled &&
+ !pmpriv->sec_info.wpa2_enabled &&
+ pbss_desc->privacy) {
+ /* Static WEP enabled */
+ PRINTM(MINFO, "Disable 11n in WEP mode\n");
+ pbss_desc->disable_11n = MTRUE;
+ /* Reject the following cases: */
+ /*
+ * case 1: RSN IE w/o WEP OUI and WPA IE w/o WEP OUI
+ * case 2: RSN IE w/o WEP OUI and No WPA IE
+ * case 3: WPA IE w/o WEP OUI and No RSN IE
+ */
+ if (((pbss_desc->prsn_ie) &&
+ ((*(pbss_desc->prsn_ie)).ieee_hdr.element_id ==
+ RSN_IE)) ||
+ ((pbss_desc->pwpa_ie) &&
+ ((*(pbss_desc->pwpa_ie)).vend_hdr.element_id ==
+ WPA_IE))) {
+ if (!is_rsn_oui_present(pmpriv->adapter,
+ pbss_desc,
+ CIPHER_SUITE_WEP40) &&
+ !is_rsn_oui_present(pmpriv->adapter,
+ pbss_desc,
+ CIPHER_SUITE_WEP104) &&
+ !is_wpa_oui_present(pmpriv->adapter,
+ pbss_desc,
+ CIPHER_SUITE_WEP40) &&
+ !is_wpa_oui_present(pmpriv->adapter,
+ pbss_desc,
+ CIPHER_SUITE_WEP104))
+ index = -1;
+ }
+
+ LEAVE();
+ return index;
+ } else if (pmpriv->sec_info.wep_status ==
+ Wlan802_11WEPDisabled &&
+ pmpriv->sec_info.wpa_enabled &&
+ !pmpriv->sec_info.wpa2_enabled &&
+ ((pbss_desc->pwpa_ie) &&
+ ((*(pbss_desc->pwpa_ie)).vend_hdr.element_id ==
+ WPA_IE))
+ /*
+ * Privacy bit may NOT be set in some APs like
+ * LinkSys WRT54G && pbss_desc->privacy
+ */
+ ) {
+ PRINTM(MINFO,
+ "wlan_is_network_compatible() WPA: index=%d wpa_ie=%#x "
+ "rsn_ie=%#x WEP=%s WPA=%s WPA2=%s EncMode=%#x "
+ "privacy=%#x\n",
+ index,
+ (pbss_desc->pwpa_ie) ?
+ (*(pbss_desc->pwpa_ie))
+ .vend_hdr.element_id :
+ 0,
+ (pbss_desc->prsn_ie) ?
+ (*(pbss_desc->prsn_ie))
+ .ieee_hdr.element_id :
+ 0,
+ (pmpriv->sec_info.wep_status ==
+ Wlan802_11WEPEnabled) ?
+ "e" :
+ "d",
+ (pmpriv->sec_info.wpa_enabled) ? "e" : "d",
+ (pmpriv->sec_info.wpa2_enabled) ? "e" : "d",
+ pmpriv->sec_info.encryption_mode,
+ pbss_desc->privacy);
+ if (((pmpriv->adapter->config_bands & BAND_GN ||
+ pmpriv->adapter->config_bands & BAND_AN) &&
+ pbss_desc->pht_cap) &&
+ (pmpriv->bss_mode == MLAN_BSS_MODE_INFRA) &&
+ !is_wpa_oui_present(pmpriv->adapter, pbss_desc,
+ CIPHER_SUITE_CCMP)) {
+ if (is_wpa_oui_present(pmpriv->adapter,
+ pbss_desc,
+ CIPHER_SUITE_TKIP)) {
+ PRINTM(MINFO,
+ "Disable 11n if AES is not supported by AP\n");
+ pbss_desc->disable_11n = MTRUE;
+ } else {
+ LEAVE();
+ return -1;
+ }
+ }
+ LEAVE();
+ return index;
+ } else if (pmpriv->sec_info.wep_status ==
+ Wlan802_11WEPDisabled &&
+ !pmpriv->sec_info.wpa_enabled &&
+ pmpriv->sec_info.wpa2_enabled &&
+ ((pbss_desc->prsn_ie) &&
+ ((*(pbss_desc->prsn_ie)).ieee_hdr.element_id ==
+ RSN_IE))
+ /*
+ * Privacy bit may NOT be set in some APs like
+ * LinkSys WRT54G && pbss_desc->privacy
+ */
+ ) {
+ /* WPA2 enabled */
+ PRINTM(MINFO,
+ "wlan_is_network_compatible() WPA2: index=%d wpa_ie=%#x "
+ "rsn_ie=%#x WEP=%s WPA=%s WPA2=%s EncMode=%#x "
+ "privacy=%#x\n",
+ index,
+ (pbss_desc->pwpa_ie) ?
+ (*(pbss_desc->pwpa_ie))
+ .vend_hdr.element_id :
+ 0,
+ (pbss_desc->prsn_ie) ?
+ (*(pbss_desc->prsn_ie))
+ .ieee_hdr.element_id :
+ 0,
+ (pmpriv->sec_info.wep_status ==
+ Wlan802_11WEPEnabled) ?
+ "e" :
+ "d",
+ (pmpriv->sec_info.wpa_enabled) ? "e" : "d",
+ (pmpriv->sec_info.wpa2_enabled) ? "e" : "d",
+ pmpriv->sec_info.encryption_mode,
+ pbss_desc->privacy);
+ if (((pmpriv->adapter->config_bands & BAND_GN ||
+ pmpriv->adapter->config_bands & BAND_AN) &&
+ pbss_desc->pht_cap) &&
+ (pmpriv->bss_mode == MLAN_BSS_MODE_INFRA) &&
+ !is_rsn_oui_present(pmpriv->adapter, pbss_desc,
+ CIPHER_SUITE_CCMP) &&
+ !is_rsn_oui_present(pmpriv->adapter, pbss_desc,
+ CIPHER_SUITE_GCMP) &&
+ !is_rsn_oui_present(pmpriv->adapter, pbss_desc,
+ CIPHER_SUITE_GCMP_256) &&
+ !is_rsn_oui_present(pmpriv->adapter, pbss_desc,
+ CIPHER_SUITE_CCMP_256)) {
+ if (is_rsn_oui_present(pmpriv->adapter,
+ pbss_desc,
+ CIPHER_SUITE_TKIP)) {
+ PRINTM(MINFO,
+ "Disable 11n if AES is not supported by AP\n");
+ pbss_desc->disable_11n = MTRUE;
+ } else if (is_rsn_oui_present_in_wpa_ie(
+ pmpriv, CIPHER_SUITE_CCMP) ||
+ is_rsn_oui_present_in_wpa_ie(
+ pmpriv, CIPHER_SUITE_GCMP) ||
+ is_rsn_oui_present_in_wpa_ie(
+ pmpriv,
+ CIPHER_SUITE_GCMP_256) ||
+ is_rsn_oui_present_in_wpa_ie(
+ pmpriv,
+ CIPHER_SUITE_CCMP_256)) {
+ LEAVE();
+ return index;
+ } else {
+ LEAVE();
+ return -1;
+ }
+ }
+ LEAVE();
+ return index;
+ } else if (pmpriv->sec_info.wep_status ==
+ Wlan802_11WEPDisabled &&
+ !pmpriv->sec_info.wpa_enabled &&
+ !pmpriv->sec_info.wpa2_enabled &&
+ ((!pbss_desc->pwpa_ie) ||
+ ((*(pbss_desc->pwpa_ie)).vend_hdr.element_id !=
+ WPA_IE)) &&
+ ((!pbss_desc->prsn_ie) ||
+ ((*(pbss_desc->prsn_ie)).ieee_hdr.element_id !=
+ RSN_IE)) &&
+ pmpriv->sec_info.encryption_mode !=
+ MLAN_ENCRYPTION_MODE_NONE &&
+ pbss_desc->privacy) {
+ /* Dynamic WEP enabled */
+ pbss_desc->disable_11n = MTRUE;
+ PRINTM(MINFO,
+ "wlan_is_network_compatible() dynamic WEP: index=%d "
+ "wpa_ie=%#x rsn_ie=%#x EncMode=%#x privacy=%#x\n",
+ index,
+ (pbss_desc->pwpa_ie) ?
+ (*(pbss_desc->pwpa_ie))
+ .vend_hdr.element_id :
+ 0,
+ (pbss_desc->prsn_ie) ?
+ (*(pbss_desc->prsn_ie))
+ .ieee_hdr.element_id :
+ 0,
+ pmpriv->sec_info.encryption_mode,
+ pbss_desc->privacy);
+ LEAVE();
+ return index;
+ }
+ /* Security doesn't match */
+ PRINTM(MINFO,
+ "wlan_is_network_compatible() FAILED: index=%d wpa_ie=%#x "
+ "rsn_ie=%#x WEP=%s WPA=%s WPA2=%s EncMode=%#x privacy=%#x\n",
+ index,
+ (pbss_desc->pwpa_ie) ?
+ (*(pbss_desc->pwpa_ie)).vend_hdr.element_id :
+ 0,
+ (pbss_desc->prsn_ie) ?
+ (*(pbss_desc->prsn_ie)).ieee_hdr.element_id :
+ 0,
+ (pmpriv->sec_info.wep_status == Wlan802_11WEPEnabled) ?
+ "e" :
+ "d",
+ (pmpriv->sec_info.wpa_enabled) ? "e" : "d",
+ (pmpriv->sec_info.wpa2_enabled) ? "e" : "d",
+ pmpriv->sec_info.encryption_mode, pbss_desc->privacy);
+ LEAVE();
+ return -1;
+ }
+ /* Mode doesn't match */
+ LEAVE();
+ return -1;
+}
+
+/**
+ * @brief Internal function used to flush the scan list
+ *
+ * @param pmadapter A pointer to mlan_adapter structure
+ *
+ * @return MLAN_STATUS_SUCCESS
+ */
+mlan_status wlan_flush_scan_table(pmlan_adapter pmadapter)
+{
+ t_u8 i = 0;
+ ENTER();
+
+ PRINTM(MINFO, "Flushing scan table\n");
+
+ memset(pmadapter, pmadapter->pscan_table, 0,
+ (sizeof(BSSDescriptor_t) * MRVDRV_MAX_BSSID_LIST));
+ pmadapter->num_in_scan_table = 0;
+
+ memset(pmadapter, pmadapter->bcn_buf, 0, pmadapter->bcn_buf_size);
+ pmadapter->pbcn_buf_end = pmadapter->bcn_buf;
+
+ for (i = 0; i < pmadapter->num_in_chan_stats; i++)
+ pmadapter->pchan_stats[i].cca_scan_duration = 0;
+ pmadapter->idx_chan_stats = 0;
+
+ LEAVE();
+ return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ * @brief Internal function used to start a scan based on an input config
+ *
+ * Use 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
+ *
+ * @param pmpriv A pointer to mlan_private structure
+ * @param pioctl_buf A pointer to MLAN IOCTL Request buffer
+ * @param puser_scan_in Pointer to the input configuration for the requested
+ * scan.
+ *
+ * @return MLAN_STATUS_SUCCESS or < 0 if error
+ */
+mlan_status wlan_scan_networks(mlan_private *pmpriv, t_void *pioctl_buf,
+ wlan_user_scan_cfg *puser_scan_in)
+{
+ mlan_status ret = MLAN_STATUS_SUCCESS;
+ mlan_adapter *pmadapter = pmpriv->adapter;
+ mlan_callbacks *pcb = (mlan_callbacks *)&pmadapter->callbacks;
+ cmd_ctrl_node *pcmd_node = MNULL;
+ pmlan_ioctl_req pioctl_req = (mlan_ioctl_req *)pioctl_buf;
+
+ wlan_scan_cmd_config_tlv *pscan_cfg_out = MNULL;
+ MrvlIEtypes_ChanListParamSet_t *pchan_list_out;
+ t_u32 buf_size;
+ ChanScanParamSet_t *pscan_chan_list;
+
+ t_u8 keep_previous_scan;
+ t_u8 filtered_scan;
+ t_u8 scan_current_chan_only;
+ t_u8 max_chan_per_scan;
+ t_u8 i;
+
+ ENTER();
+
+ ret = pcb->moal_malloc(pmadapter->pmoal_handle,
+ sizeof(wlan_scan_cmd_config_tlv), MLAN_MEM_DEF,
+ (t_u8 **)&pscan_cfg_out);
+ if (ret != MLAN_STATUS_SUCCESS || !pscan_cfg_out) {
+ PRINTM(MERROR, "Memory allocation for pscan_cfg_out failed!\n");
+ if (pioctl_req)
+ pioctl_req->status_code = MLAN_ERROR_NO_MEM;
+ LEAVE();
+ return MLAN_STATUS_FAILURE;
+ }
+
+ buf_size = sizeof(ChanScanParamSet_t) * WLAN_USER_SCAN_CHAN_MAX;
+ ret = pcb->moal_malloc(pmadapter->pmoal_handle, buf_size, MLAN_MEM_DEF,
+ (t_u8 **)&pscan_chan_list);
+ if (ret != MLAN_STATUS_SUCCESS || !pscan_chan_list) {
+ PRINTM(MERROR, "Failed to allocate scan_chan_list\n");
+ if (pscan_cfg_out)
+ pcb->moal_mfree(pmadapter->pmoal_handle,
+ (t_u8 *)pscan_cfg_out);
+ if (pioctl_req)
+ pioctl_req->status_code = MLAN_ERROR_NO_MEM;
+ LEAVE();
+ return MLAN_STATUS_FAILURE;
+ }
+
+ memset(pmadapter, pscan_chan_list, 0x00, buf_size);
+ memset(pmadapter, pscan_cfg_out, 0x00,
+ sizeof(wlan_scan_cmd_config_tlv));
+
+ keep_previous_scan = MFALSE;
+
+ ret = wlan_scan_setup_scan_config(pmpriv, puser_scan_in,
+ &pscan_cfg_out->config,
+ &pchan_list_out, pscan_chan_list,
+ &max_chan_per_scan, &filtered_scan,
+ &scan_current_chan_only);
+ if (ret != MLAN_STATUS_SUCCESS) {
+ PRINTM(MERROR, "Failed to setup scan config\n");
+ if (pscan_cfg_out)
+ pcb->moal_mfree(pmadapter->pmoal_handle,
+ (t_u8 *)pscan_cfg_out);
+ if (pscan_chan_list)
+ pcb->moal_mfree(pmadapter->pmoal_handle,
+ (t_u8 *)pscan_chan_list);
+ if (pioctl_req)
+ pioctl_req->status_code = MLAN_ERROR_INVALID_PARAMETER;
+ LEAVE();
+ return MLAN_STATUS_FAILURE;
+ }
+
+ if (puser_scan_in)
+ keep_previous_scan = puser_scan_in->keep_previous_scan;
+
+ if (keep_previous_scan == MFALSE) {
+ memset(pmadapter, pmadapter->pscan_table, 0x00,
+ sizeof(BSSDescriptor_t) * MRVDRV_MAX_BSSID_LIST);
+ pmadapter->num_in_scan_table = 0;
+ pmadapter->pbcn_buf_end = pmadapter->bcn_buf;
+ }
+ for (i = 0; i < pmadapter->num_in_chan_stats; i++)
+ pmadapter->pchan_stats[i].cca_scan_duration = 0;
+ pmadapter->idx_chan_stats = 0;
+
+ ret = wlan_scan_channel_list(pmpriv, pioctl_buf, max_chan_per_scan,
+ filtered_scan, &pscan_cfg_out->config,
+ pchan_list_out, pscan_chan_list);
+
+ /* Get scan command from scan_pending_q and put to cmd_pending_q */
+ if (ret == MLAN_STATUS_SUCCESS) {
+ if (pmadapter->ext_scan && pmadapter->ext_scan_enh &&
+ pmadapter->ext_scan_type == EXT_SCAN_ENHANCE) {
+ wlan_request_cmd_lock(pmadapter);
+ pmadapter->pscan_ioctl_req = pioctl_req;
+ pmadapter->scan_processing = MTRUE;
+ wlan_release_cmd_lock(pmadapter);
+ } else {
+ wlan_request_cmd_lock(pmadapter);
+ if (util_peek_list(pmadapter->pmoal_handle,
+ &pmadapter->scan_pending_q, MNULL,
+ MNULL)) {
+ pcmd_node = (cmd_ctrl_node *)util_dequeue_list(
+ pmadapter->pmoal_handle,
+ &pmadapter->scan_pending_q, MNULL,
+ MNULL);
+ pmadapter->pscan_ioctl_req = pioctl_req;
+ pmadapter->scan_processing = MTRUE;
+ wlan_insert_cmd_to_pending_q(pmadapter,
+ pcmd_node, MTRUE);
+ }
+ wlan_release_cmd_lock(pmadapter);
+ }
+ }
+ if (pscan_cfg_out)
+ pcb->moal_mfree(pmadapter->pmoal_handle, (t_u8 *)pscan_cfg_out);
+
+ if (pscan_chan_list)
+ pcb->moal_mfree(pmadapter->pmoal_handle,
+ (t_u8 *)pscan_chan_list);
+
+ LEAVE();
+ return ret;
+}
+
+/**
+ * @brief Prepare a scan command to be sent to the firmware
+ *
+ * Use the wlan_scan_cmd_config sent to the command processing module in
+ * the wlan_prepare_cmd to configure a HostCmd_DS_802_11_SCAN command
+ * struct 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.
+ *
+ * @param pmpriv A pointer to mlan_private structure
+ * @param pcmd A pointer to HostCmd_DS_COMMAND structure to be sent to
+ * firmware with the HostCmd_DS_801_11_SCAN structure
+ * @param pdata_buf Void pointer cast of a wlan_scan_cmd_config struct used
+ * to set the fields/TLVs for the command sent to firmware
+ *
+ * @return MLAN_STATUS_SUCCESS
+ */
+mlan_status wlan_cmd_802_11_scan(mlan_private *pmpriv, HostCmd_DS_COMMAND *pcmd,
+ t_void *pdata_buf)
+{
+ HostCmd_DS_802_11_SCAN *pscan_cmd = &pcmd->params.scan;
+ wlan_scan_cmd_config *pscan_cfg;
+
+ ENTER();
+
+ pscan_cfg = (wlan_scan_cmd_config *)pdata_buf;
+
+ /* Set fixed field variables in scan command */
+ pscan_cmd->bss_mode = pscan_cfg->bss_mode;
+ memcpy_ext(pmpriv->adapter, pscan_cmd->bssid, pscan_cfg->specific_bssid,
+ sizeof(pscan_cmd->bssid), sizeof(pscan_cmd->bssid));
+ memcpy_ext(pmpriv->adapter, pscan_cmd->tlv_buffer, pscan_cfg->tlv_buf,
+ pscan_cfg->tlv_buf_len, pscan_cfg->tlv_buf_len);
+
+ pcmd->command = wlan_cpu_to_le16(HostCmd_CMD_802_11_SCAN);
+
+ /* Size is equal to the sizeof(fixed portions) + the TLV len + header */
+ pcmd->size = (t_u16)wlan_cpu_to_le16(
+ (t_u16)(sizeof(pscan_cmd->bss_mode) + sizeof(pscan_cmd->bssid) +
+ pscan_cfg->tlv_buf_len + S_DS_GEN));
+
+ LEAVE();
+ return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ * @brief Check if any hidden SSID found in passive scan channels
+ * and do specific SSID active scan for those channels
+ *
+ * @param pmpriv A pointer to mlan_private structure
+ * @param pioctl_buf A pointer to mlan_ioctl_req structure
+ *
+ * @return MTRUE/MFALSE
+ */
+
+t_bool wlan_active_scan_req_for_passive_chan(mlan_private *pmpriv,
+ mlan_ioctl_req *pioctl_buf)
+{
+ t_bool ret = MFALSE;
+ mlan_adapter *pmadapter = pmpriv->adapter;
+ t_bool scan_reqd = MFALSE;
+ t_bool chan_listed = MFALSE;
+ t_u8 id = 0;
+ t_u32 bss_idx, i;
+ t_u8 null_ssid[MLAN_MAX_SSID_LENGTH] = {0};
+ mlan_callbacks *pcb = (mlan_callbacks *)&pmpriv->adapter->callbacks;
+ wlan_user_scan_cfg *user_scan_cfg;
+ mlan_ds_scan *pscan = (mlan_ds_scan *)pioctl_buf->pbuf;
+ mlan_scan_req *pscan_req = MNULL;
+ wlan_user_scan_cfg *puser_scan_in = MNULL;
+
+ ENTER();
+
+ if (pscan->sub_command == MLAN_OID_SCAN_USER_CONFIG) {
+ puser_scan_in = (wlan_user_scan_cfg *)
+ pscan->param.user_scan.scan_cfg_buf;
+ if (!puser_scan_in->ssid_filter)
+ goto done;
+ }
+
+ if (pmadapter->active_scan_triggered) {
+ pmadapter->active_scan_triggered = MFALSE;
+ goto done;
+ }
+
+ if ((pcb->moal_malloc(pmadapter->pmoal_handle,
+ sizeof(wlan_user_scan_cfg), MLAN_MEM_DEF,
+ (t_u8 **)&user_scan_cfg) !=
+ MLAN_STATUS_SUCCESS) ||
+ !user_scan_cfg) {
+ PRINTM(MERROR, "Memory allocation for user_scan_cfg failed\n");
+ goto done;
+ }
+ memset(pmadapter, user_scan_cfg, 0, sizeof(wlan_user_scan_cfg));
+ for (bss_idx = 0; bss_idx < pmadapter->num_in_scan_table; bss_idx++) {
+ scan_reqd = MFALSE;
+ if (!memcmp(pmadapter,
+ pmadapter->pscan_table[bss_idx].ssid.ssid,
+ null_ssid,
+ pmadapter->pscan_table[bss_idx].ssid.ssid_len)) {
+ if (puser_scan_in &&
+ puser_scan_in->chan_list[0].chan_number) {
+ for (i = 0;
+ i < WLAN_USER_SCAN_CHAN_MAX &&
+ puser_scan_in->chan_list[i].chan_number;
+ i++) {
+ if (puser_scan_in->chan_list[i]
+ .chan_number ==
+ pmadapter->pscan_table[bss_idx]
+ .channel) {
+ if (puser_scan_in->chan_list[i]
+ .scan_type ==
+ MLAN_SCAN_TYPE_PASSIVE)
+ scan_reqd = MTRUE;
+ break;
+ }
+ }
+ } else if (pmadapter->scan_type ==
+ MLAN_SCAN_TYPE_PASSIVE) {
+ scan_reqd = MTRUE;
+ } else {
+ if ((pmadapter->pscan_table[bss_idx].bss_band &
+ BAND_A) &&
+ wlan_11h_radar_detect_required(
+ pmpriv,
+ pmadapter->pscan_table[bss_idx]
+ .channel))
+ scan_reqd = MTRUE;
+ if (pmadapter->pscan_table[bss_idx].bss_band &
+ (BAND_B | BAND_G) &&
+ wlan_bg_scan_type_is_passive(
+ pmpriv,
+ pmadapter->pscan_table[bss_idx]
+ .channel))
+ scan_reqd = MTRUE;
+ }
+
+ if (scan_reqd) {
+ chan_listed = MFALSE;
+ for (i = 0; i < id; i++) {
+ if ((user_scan_cfg->chan_list[i]
+ .chan_number ==
+ pmadapter->pscan_table[bss_idx]
+ .channel) &&
+ (user_scan_cfg->chan_list[i]
+ .radio_type &
+ pmadapter->pscan_table[bss_idx]
+ .bss_band)) {
+ chan_listed = MTRUE;
+ break;
+ }
+ }
+ if (chan_listed == MTRUE)
+ continue;
+ user_scan_cfg->chan_list[id].chan_number =
+ pmadapter->pscan_table[bss_idx].channel;
+ if (pmadapter->pscan_table[bss_idx].bss_band &
+ (BAND_B | BAND_G))
+ user_scan_cfg->chan_list[id].radio_type =
+ BAND_2GHZ;
+ if (pmadapter->pscan_table[bss_idx].bss_band &
+ BAND_A)
+ user_scan_cfg->chan_list[id].radio_type =
+ BAND_5GHZ;
+ user_scan_cfg->chan_list[id].scan_type =
+ MLAN_SCAN_TYPE_ACTIVE;
+ id++;
+ }
+ }
+ }
+ if (id) {
+ pmadapter->active_scan_triggered = MTRUE;
+ if (pscan->sub_command == MLAN_OID_SCAN_USER_CONFIG) {
+ memcpy_ext(pmpriv->adapter, user_scan_cfg->ssid_list,
+ puser_scan_in->ssid_list,
+ sizeof(user_scan_cfg->ssid_list),
+ sizeof(user_scan_cfg->ssid_list));
+ } else {
+ pscan_req = &pscan->param.scan_req;
+ memcpy_ext(pmpriv->adapter,
+ user_scan_cfg->ssid_list[0].ssid,
+ pscan_req->scan_ssid.ssid,
+ pscan_req->scan_ssid.ssid_len,
+ MLAN_MAX_SSID_LENGTH);
+ }
+ user_scan_cfg->keep_previous_scan = MTRUE;
+ if (MLAN_STATUS_SUCCESS !=
+ wlan_scan_networks(pmpriv, pioctl_buf, user_scan_cfg)) {
+ goto done;
+ }
+ ret = MTRUE;
+ }
+ if (user_scan_cfg)
+ pcb->moal_mfree(pmadapter->pmoal_handle, (t_u8 *)user_scan_cfg);
+
+done:
+ LEAVE();
+ return ret;
+}
+
+/**
+ * @brief 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) |
+ * .-------------------------------------------------------------.
+ *
+ * @param pmpriv A pointer to mlan_private structure
+ * @param resp A pointer to HostCmd_DS_COMMAND
+ * @param pioctl_buf A pointer to mlan_ioctl_req structure
+ *
+ * @return MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ */
+mlan_status wlan_ret_802_11_scan(mlan_private *pmpriv, HostCmd_DS_COMMAND *resp,
+ t_void *pioctl_buf)
+{
+ mlan_status ret = MLAN_STATUS_SUCCESS;
+ mlan_adapter *pmadapter = pmpriv->adapter;
+ mlan_callbacks *pcb = MNULL;
+ cmd_ctrl_node *pcmd_node = MNULL;
+ HostCmd_DS_802_11_SCAN_RSP *pscan_rsp = MNULL;
+ BSSDescriptor_t *bss_new_entry = MNULL;
+ MrvlIEtypes_Data_t *ptlv;
+ MrvlIEtypes_TsfTimestamp_t *ptsf_tlv = MNULL;
+ MrvlIEtypes_ChannelStats_t *pchanstats_tlv = MNULL;
+ t_u8 *pbss_info;
+ t_u32 scan_resp_size;
+ t_u32 bytes_left;
+ t_u32 num_in_table;
+ t_u32 bss_idx;
+ t_u32 idx;
+ t_u32 tlv_buf_size;
+ t_u64 tsf_val;
+ chan_freq_power_t *cfp;
+ MrvlIEtypes_ChanBandListParamSet_t *pchan_band_tlv = MNULL;
+ ChanBandParamSet_t *pchan_band;
+ t_u8 band;
+ t_u8 is_bgscan_resp;
+ t_u32 age_ts_usec;
+ t_u8 null_ssid[MLAN_MAX_SSID_LENGTH] = {0};
+ t_u32 status_code = 0;
+ pmlan_ioctl_req pscan_ioctl_req = MNULL;
+
+ ENTER();
+ pcb = (pmlan_callbacks)&pmadapter->callbacks;
+
+ is_bgscan_resp = (resp->command == HostCmd_CMD_802_11_BG_SCAN_QUERY);
+ if (is_bgscan_resp)
+ pscan_rsp = &resp->params.bg_scan_query_resp.scan_resp;
+ else
+ pscan_rsp = &resp->params.scan_resp;
+
+ if (pscan_rsp->number_of_sets > MRVDRV_MAX_BSSID_LIST) {
+ PRINTM(MERROR,
+ "SCAN_RESP: Invalid number of AP returned (%d)!!\n",
+ pscan_rsp->number_of_sets);
+ status_code = MLAN_ERROR_CMD_SCAN_FAIL;
+ ret = MLAN_STATUS_FAILURE;
+ goto done;
+ }
+
+ bytes_left = wlan_le16_to_cpu(pscan_rsp->bss_descript_size);
+ PRINTM(MINFO, "SCAN_RESP: bss_descript_size %d\n", bytes_left);
+
+ scan_resp_size = resp->size;
+
+ PRINTM(MINFO, "SCAN_RESP: returned %d APs before parsing\n",
+ pscan_rsp->number_of_sets);
+
+ num_in_table = pmadapter->num_in_scan_table;
+ pbss_info = pscan_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(pscan_rsp->bss_descript_size) +
+ sizeof(pscan_rsp->number_of_sets) + S_DS_GEN);
+ if (is_bgscan_resp)
+ tlv_buf_size -= sizeof(
+ resp->params.bg_scan_query_resp.report_condition);
+
+ ptlv = (MrvlIEtypes_Data_t *)(pscan_rsp->bss_desc_and_tlv_buffer +
+ bytes_left);
+
+ /*
+ * Search the TLV buffer space in the scan response
+ * for any valid TLVs
+ */
+ wlan_ret_802_11_scan_get_tlv_ptrs(pmadapter, ptlv, tlv_buf_size,
+ TLV_TYPE_TSFTIMESTAMP,
+ (MrvlIEtypes_Data_t **)&ptsf_tlv);
+
+ /*
+ * Search the TLV buffer space in the scan response
+ * for any valid TLVs
+ */
+ wlan_ret_802_11_scan_get_tlv_ptrs(
+ pmadapter, ptlv, tlv_buf_size, TLV_TYPE_CHANNELBANDLIST,
+ (MrvlIEtypes_Data_t **)&pchan_band_tlv);
+ wlan_ret_802_11_scan_get_tlv_ptrs(
+ pmadapter, ptlv, tlv_buf_size, TLV_TYPE_CHANNEL_STATS,
+ (MrvlIEtypes_Data_t **)&pchanstats_tlv);
+
+ if (pchanstats_tlv)
+ wlan_update_chan_statistics(pmpriv, pchanstats_tlv);
+
+ /*
+ * Process each scan response returned (pscan_rsp->number_of_sets).
+ * Save the information in the bss_new_entry and then insert into
+ * the driver scan table either as an update to an existing entry
+ * or as an addition at the end of the table
+ */
+ ret = pcb->moal_malloc(pmadapter->pmoal_handle, sizeof(BSSDescriptor_t),
+ MLAN_MEM_DEF, (t_u8 **)&bss_new_entry);
+
+ if (ret != MLAN_STATUS_SUCCESS || !bss_new_entry) {
+ PRINTM(MERROR, "Memory allocation for bss_new_entry failed!\n");
+ status_code = MLAN_ERROR_NO_MEM;
+ ret = MLAN_STATUS_FAILURE;
+ goto done;
+ }
+
+ for (idx = 0; idx < pscan_rsp->number_of_sets && bytes_left; idx++) {
+ /* Zero out the bss_new_entry we are about to store info in */
+ memset(pmadapter, bss_new_entry, 0x00, sizeof(BSSDescriptor_t));
+
+ /* Process the data fields and IEs returned for this BSS */
+ if (wlan_interpret_bss_desc_with_ie(
+ pmadapter, bss_new_entry, &pbss_info, &bytes_left,
+ MFALSE) == MLAN_STATUS_SUCCESS) {
+ PRINTM(MINFO, "SCAN_RESP: BSSID = " MACSTR "\n",
+ MAC2STR(bss_new_entry->mac_address));
+
+ band = BAND_G;
+ if (pchan_band_tlv) {
+ pchan_band =
+ &pchan_band_tlv->chan_band_param[idx];
+ band = radio_type_to_band(
+ pchan_band->bandcfg.chanBand);
+ if (!bss_new_entry->channel)
+ bss_new_entry->channel =
+ pchan_band->chan_number;
+ }
+ /*
+ * Save the band designation for this entry
+ * for use in join
+ */
+ bss_new_entry->bss_band = band;
+
+ cfp = wlan_find_cfp_by_band_and_channel(
+ pmadapter, (t_u8)bss_new_entry->bss_band,
+ (t_u16)bss_new_entry->channel);
+ if (cfp)
+ bss_new_entry->freq = cfp->freq;
+ else
+ bss_new_entry->freq = 0;
+
+ /* Skip entry if on blacklisted channel */
+ if (cfp && cfp->dynamic.blacklist) {
+ PRINTM(MINFO,
+ "SCAN_RESP: dropping entry on blacklist channel.\n");
+ continue;
+ }
+
+ /*
+ * Search the scan table for the same bssid
+ */
+ for (bss_idx = 0; bss_idx < num_in_table; bss_idx++) {
+ if (!memcmp(pmadapter,
+ bss_new_entry->mac_address,
+ pmadapter->pscan_table[bss_idx]
+ .mac_address,
+ sizeof(bss_new_entry->mac_address))) {
+ /*
+ * If the SSID matches as well, it is a
+ * duplicate of this entry. Keep the
+ * bss_idx set to this entry so we
+ * replace the old contents in the table
+ */
+ if ((bss_new_entry->ssid.ssid_len ==
+ pmadapter->pscan_table[bss_idx]
+ .ssid.ssid_len) &&
+ (!memcmp(
+ pmadapter,
+ bss_new_entry->ssid.ssid,
+ pmadapter
+ ->pscan_table[bss_idx]
+ .ssid.ssid,
+ bss_new_entry->ssid
+ .ssid_len))) {
+ PRINTM(MINFO,
+ "SCAN_RESP: Duplicate of index: %d\n",
+ bss_idx);
+
+ break;
+ }
+ /*
+ * If the SSID is NULL for same BSSID
+ * keep the bss_idx set to this entry
+ * so we replace the old contents in
+ * the table
+ */
+ if (!memcmp(pmadapter,
+ pmadapter
+ ->pscan_table[bss_idx]
+ .ssid.ssid,
+ null_ssid,
+ pmadapter
+ ->pscan_table[bss_idx]
+ .ssid.ssid_len)) {
+ PRINTM(MINFO,
+ "SCAN_RESP: Duplicate of index: %d\n",
+ bss_idx);
+ break;
+ }
+ }
+ }
+ /*
+ * If the bss_idx is equal to the number of entries
+ * in the table, the new entry was not a duplicate;
+ * append it to the scan table
+ */
+ if (bss_idx == num_in_table) {
+ /*
+ * Range check the bss_idx, keep it limited
+ * to the last entry
+ */
+ if (bss_idx == MRVDRV_MAX_BSSID_LIST)
+ bss_idx--;
+ else
+ num_in_table++;
+ } else {
+ if ((bss_new_entry->channel !=
+ pmadapter->pscan_table[bss_idx].channel) &&
+ (bss_new_entry->rssi >
+ pmadapter->pscan_table[bss_idx].rssi)) {
+ PRINTM(MCMND,
+ "skip update the duplicate entry with low rssi\n");
+ continue;
+ }
+ }
+ /*
+ * Save the beacon/probe response returned for later
+ * application retrieval. Duplicate beacon/probe
+ * responses are updated if possible
+ */
+ wlan_ret_802_11_scan_store_beacon(
+ pmpriv, bss_idx, num_in_table, bss_new_entry);
+ if (bss_new_entry->pbeacon_buf == MNULL) {
+ PRINTM(MCMND,
+ "No space for beacon, drop this entry\n");
+ num_in_table--;
+ continue;
+ }
+ /*
+ * If the TSF TLV was appended to the scan results, save
+ * this entry's TSF value in the networkTSF field. The
+ * networkTSF is the firmware's TSF value at the time
+ * the beacon or probe response was received.
+ */
+ if (ptsf_tlv) {
+ memcpy_ext(
+ pmpriv->adapter, &tsf_val,
+ &ptsf_tlv->tsf_data[idx * TSF_DATA_SIZE],
+ sizeof(tsf_val), sizeof(tsf_val));
+ tsf_val = wlan_le64_to_cpu(tsf_val);
+ memcpy_ext(pmpriv->adapter,
+ &bss_new_entry->network_tsf,
+ &tsf_val,
+ sizeof(bss_new_entry->network_tsf),
+ sizeof(bss_new_entry->network_tsf));
+ }
+
+ /* Copy the locally created bss_new_entry to the scan
+ * table */
+ memcpy_ext(pmadapter, &pmadapter->pscan_table[bss_idx],
+ bss_new_entry,
+ sizeof(pmadapter->pscan_table[bss_idx]),
+ sizeof(pmadapter->pscan_table[bss_idx]));
+
+ } else {
+ /* Error parsing/interpreting the scan response, skipped
+ */
+ PRINTM(MERROR,
+ "SCAN_RESP: wlan_interpret_bss_desc_with_ie returned error\n");
+ }
+ }
+
+ PRINTM(MINFO, "SCAN_RESP: Scanned %2d APs, %d valid, %d total\n",
+ pscan_rsp->number_of_sets,
+ num_in_table - pmadapter->num_in_scan_table, num_in_table);
+
+ /* Update the total number of BSSIDs in the scan table */
+ pmadapter->num_in_scan_table = num_in_table;
+ /* Update the age_in_second */
+ pmadapter->callbacks.moal_get_system_time(
+ pmadapter->pmoal_handle, &pmadapter->age_in_secs, &age_ts_usec);
+ if (is_bgscan_resp)
+ goto done;
+ wlan_request_cmd_lock(pmadapter);
+ if (!util_peek_list(pmadapter->pmoal_handle, &pmadapter->scan_pending_q,
+ MNULL, MNULL)) {
+ wlan_release_cmd_lock(pmadapter);
+ if (pmadapter->pscan_ioctl_req) {
+ if (((mlan_ds_scan *)pmadapter->pscan_ioctl_req->pbuf)
+ ->sub_command ==
+ MLAN_OID_SCAN_SPECIFIC_SSID ||
+ ((mlan_ds_scan *)pmadapter->pscan_ioctl_req->pbuf)
+ ->sub_command ==
+ MLAN_OID_SCAN_USER_CONFIG) {
+ if (wlan_active_scan_req_for_passive_chan(
+ pmpriv,
+ pmadapter->pscan_ioctl_req)) {
+ goto done;
+ }
+ }
+ }
+ /*
+ * Process the resulting scan table:
+ * - Remove any bad ssids
+ * - Update our current BSS information from scan data
+ */
+ wlan_scan_process_results(pmpriv);
+
+ wlan_request_cmd_lock(pmadapter);
+ pmadapter->scan_processing = MFALSE;
+ pscan_ioctl_req = pmadapter->pscan_ioctl_req;
+ pmadapter->pscan_ioctl_req = MNULL;
+ /* Need to indicate IOCTL complete */
+ if (pscan_ioctl_req) {
+ pscan_ioctl_req->status_code = MLAN_ERROR_NO_ERROR;
+ /* Indicate ioctl complete */
+ pcb->moal_ioctl_complete(
+ pmadapter->pmoal_handle,
+ (pmlan_ioctl_req)pscan_ioctl_req,
+ MLAN_STATUS_SUCCESS);
+ }
+ wlan_release_cmd_lock(pmadapter);
+ pmadapter->bgscan_reported = MFALSE;
+ wlan_recv_event(pmpriv, MLAN_EVENT_ID_DRV_SCAN_REPORT, MNULL);
+ } else {
+ /* If firmware not ready, do not issue any more scan commands */
+ if (pmadapter->hw_status != WlanHardwareStatusReady) {
+ wlan_release_cmd_lock(pmadapter);
+ status_code = MLAN_ERROR_FW_NOT_READY;
+ ret = MLAN_STATUS_FAILURE;
+ goto done;
+ } else {
+ /* Get scan command from scan_pending_q and put to
+ * cmd_pending_q */
+ pcmd_node = (cmd_ctrl_node *)util_dequeue_list(
+ pmadapter->pmoal_handle,
+ &pmadapter->scan_pending_q, MNULL, MNULL);
+ wlan_insert_cmd_to_pending_q(pmadapter, pcmd_node,
+ MTRUE);
+ wlan_release_cmd_lock(pmadapter);
+ }
+ }
+
+done:
+ if (bss_new_entry)
+ pcb->moal_mfree(pmadapter->pmoal_handle, (t_u8 *)bss_new_entry);
+ if (ret) {
+ /* Flush all pending scan commands */
+ wlan_flush_scan_queue(pmadapter);
+ wlan_request_cmd_lock(pmadapter);
+ pmadapter->scan_processing = MFALSE;
+ pscan_ioctl_req = pmadapter->pscan_ioctl_req;
+ pmadapter->pscan_ioctl_req = MNULL;
+ if (pscan_ioctl_req) {
+ pscan_ioctl_req->status_code = status_code;
+ /* Indicate ioctl complete */
+ pcb->moal_ioctl_complete(pmadapter->pmoal_handle,
+ pscan_ioctl_req,
+ MLAN_STATUS_FAILURE);
+ }
+ wlan_release_cmd_lock(pmadapter);
+ }
+ LEAVE();
+ return ret;
+}
+
+/**
+ * @brief Prepare an extended scan command to be sent to the firmware
+ *
+ * Use the wlan_scan_cmd_config sent to the command processing module in
+ * the wlan_prepare_cmd to configure a HostCmd_DS_802_11_SCAN_EXT command
+ * struct to send to firmware.
+ *
+ * @param pmpriv A pointer to mlan_private structure
+ * @param pcmd A pointer to HostCmd_DS_COMMAND structure to be sent to
+ * firmware with the HostCmd_DS_802_11_SCAN_EXT structure
+ * @param pdata_buf Void pointer cast of a wlan_scan_cmd_config struct used
+ * to set the fields/TLVs for the command sent to firmware
+ *
+ * @return MLAN_STATUS_SUCCESS
+ */
+mlan_status wlan_cmd_802_11_scan_ext(mlan_private *pmpriv,
+ HostCmd_DS_COMMAND *pcmd,
+ t_void *pdata_buf)
+{
+ HostCmd_DS_802_11_SCAN_EXT *pext_scan_cmd = &pcmd->params.ext_scan;
+ wlan_scan_cmd_config *pscan_cfg = MNULL;
+
+ ENTER();
+
+ pcmd->command = wlan_cpu_to_le16(HostCmd_CMD_802_11_SCAN_EXT);
+
+ if (pmpriv->adapter->ext_scan_enh == MTRUE) {
+ if (pdata_buf) {
+ if (pmpriv->adapter->ext_scan_type == EXT_SCAN_ENHANCE)
+ pext_scan_cmd->ext_scan_type = EXT_SCAN_ENHANCE;
+ else
+ pext_scan_cmd->ext_scan_type = EXT_SCAN_DEFAULT;
+ } else {
+ pcmd->size = wlan_cpu_to_le16((t_u16)(
+ sizeof(pext_scan_cmd->ext_scan_type) +
+ (t_u16)(sizeof(pext_scan_cmd->reserved)) +
+ S_DS_GEN));
+ pext_scan_cmd->ext_scan_type = EXT_SCAN_CANCEL;
+ LEAVE();
+ return MLAN_STATUS_SUCCESS;
+ }
+ }
+ pscan_cfg = (wlan_scan_cmd_config *)pdata_buf;
+
+ memcpy_ext(pmpriv->adapter, pext_scan_cmd->tlv_buffer,
+ pscan_cfg->tlv_buf, pscan_cfg->tlv_buf_len,
+ pscan_cfg->tlv_buf_len);
+
+ /* Size is equal to the sizeof(fixed portions) + the TLV len + header */
+ pcmd->size = wlan_cpu_to_le16(
+ (t_u16)(sizeof(pext_scan_cmd->ext_scan_type) +
+ (t_u16)sizeof(pext_scan_cmd->reserved) +
+ pscan_cfg->tlv_buf_len + S_DS_GEN));
+
+ LEAVE();
+ return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ * @brief This function handles the command response of extended scan
+ *
+ * @param pmpriv A pointer to mlan_private structure
+ * @param resp A pointer to HostCmd_DS_COMMAND
+ * @param pioctl_buf A pointer to mlan_ioctl_req structure
+ *
+ * @return MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ */
+mlan_status wlan_ret_802_11_scan_ext(mlan_private *pmpriv,
+ HostCmd_DS_COMMAND *resp,
+ t_void *pioctl_buf)
+{
+ HostCmd_DS_802_11_SCAN_EXT *pext_scan_cmd = &(resp->params.ext_scan);
+ MrvlIEtypesHeader_t *tlv = MNULL;
+ MrvlIEtypes_ChannelStats_t *tlv_chanstats = MNULL;
+ t_u16 tlv_buf_left = 0;
+ t_u16 tlv_type = 0;
+ t_u16 tlv_len = 0;
+ t_u32 ext_scan_type;
+ mlan_callbacks *pcb = (mlan_callbacks *)&pmpriv->adapter->callbacks;
+ pmlan_ioctl_req pioctl_req = (pmlan_ioctl_req)pioctl_buf;
+ mlan_adapter *pmadapter = pmpriv->adapter;
+ ENTER();
+
+ PRINTM(MINFO, "EXT scan returns successfully\n");
+ ext_scan_type = pext_scan_cmd->ext_scan_type;
+ if (ext_scan_type == EXT_SCAN_CANCEL) {
+ PRINTM(MCMND, "Cancel scan command completed!\n");
+ wlan_request_cmd_lock(pmadapter);
+ pmadapter->scan_processing = MFALSE;
+ pmadapter->ext_scan_type = EXT_SCAN_DEFAULT;
+ wlan_release_cmd_lock(pmadapter);
+ /* Need to indicate IOCTL complete */
+ if (pioctl_req != MNULL) {
+ pioctl_req->status_code = MLAN_STATUS_SUCCESS;
+ /* Indicate ioctl complete */
+ pcb->moal_ioctl_complete(pmadapter->pmoal_handle,
+ (pmlan_ioctl_req)pioctl_req,
+ MLAN_STATUS_SUCCESS);
+ }
+ LEAVE();
+ return MLAN_STATUS_SUCCESS;
+ } else if (ext_scan_type == EXT_SCAN_ENHANCE) {
+ /* Setup the timer after scan command response */
+ pcb->moal_start_timer(pmpriv->adapter->pmoal_handle,
+ pmpriv->adapter->pmlan_cmd_timer, MFALSE,
+ MRVDRV_TIMER_10S * 2);
+ pmpriv->adapter->cmd_timer_is_set = MTRUE;
+ LEAVE();
+ return MLAN_STATUS_SUCCESS;
+ }
+ tlv = (MrvlIEtypesHeader_t *)pext_scan_cmd->tlv_buffer;
+ tlv_buf_left = resp->size -
+ (sizeof(HostCmd_DS_802_11_SCAN_EXT) - 1 + S_DS_GEN);
+ while (tlv_buf_left >= sizeof(MrvlIEtypesHeader_t)) {
+ tlv_type = wlan_le16_to_cpu(tlv->type);
+ tlv_len = wlan_le16_to_cpu(tlv->len);
+ if (tlv_buf_left < (tlv_len + sizeof(MrvlIEtypesHeader_t))) {
+ PRINTM(MERROR, "Error processing scan gap TLV\n");
+ break;
+ }
+ switch (tlv_type) {
+ case TLV_TYPE_CHANNEL_STATS:
+ tlv_chanstats = (MrvlIEtypes_ChannelStats_t *)tlv;
+ wlan_update_chan_statistics(pmpriv, tlv_chanstats);
+ break;
+ default:
+ break;
+ }
+ tlv_buf_left -= tlv_len + sizeof(MrvlIEtypesHeader_t);
+ tlv = (MrvlIEtypesHeader_t *)((t_u8 *)tlv + tlv_len +
+ sizeof(MrvlIEtypesHeader_t));
+ }
+ LEAVE();
+ return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ * @brief This function add a new entry to scan_table
+ *
+ * @param pmpriv A pointer to mlan_private structure
+ * @param bss_new_entry A pointer to the bss_new_entry
+ * @param num_in_tbl number of scan entry in scan_table
+ *
+ * @return N/A
+ */
+t_void wlan_add_new_entry_to_scan_table(mlan_private *pmpriv,
+ BSSDescriptor_t *bss_new_entry,
+ t_u32 *num_in_tbl)
+{
+ mlan_adapter *pmadapter = pmpriv->adapter;
+ t_u32 bss_idx;
+ t_u32 num_in_table = *num_in_tbl;
+ t_u8 null_ssid[MLAN_MAX_SSID_LENGTH] = {0};
+
+ /*
+ * Search the scan table for the same bssid
+ */
+ for (bss_idx = 0; bss_idx < num_in_table; bss_idx++) {
+ if (!memcmp(pmadapter, bss_new_entry->mac_address,
+ pmadapter->pscan_table[bss_idx].mac_address,
+ sizeof(bss_new_entry->mac_address))) {
+ /*
+ * If the SSID matches as well, it is a
+ * duplicate of this entry. Keep the
+ * bss_idx set to this entry so we
+ * replace the old contents in the table
+ */
+ if ((bss_new_entry->ssid.ssid_len ==
+ pmadapter->pscan_table[bss_idx].ssid.ssid_len) &&
+ (!memcmp(pmadapter, bss_new_entry->ssid.ssid,
+ pmadapter->pscan_table[bss_idx].ssid.ssid,
+ bss_new_entry->ssid.ssid_len))) {
+ PRINTM(MINFO,
+ "EXT_SCAN: Duplicate of index: %d\n",
+ bss_idx);
+ break;
+ }
+ /*
+ * If the SSID is NULL for same BSSID
+ * keep the bss_idx set to this entry
+ * so we replace the old contents in
+ * the table
+ */
+ if (!memcmp(pmadapter,
+ pmadapter->pscan_table[bss_idx].ssid.ssid,
+ null_ssid,
+ pmadapter->pscan_table[bss_idx]
+ .ssid.ssid_len)) {
+ PRINTM(MINFO,
+ "EXT_SCAN: Duplicate of index: %d\n",
+ bss_idx);
+ break;
+ }
+ }
+ }
+ /* If the bss_idx is equal to the number of entries
+ * in the table, the new entry was not a duplicate;
+ * append it to the scan table
+ */
+ if (bss_idx == num_in_table) {
+ /* Range check the bss_idx, keep it limited to the last entry */
+ if (bss_idx == MRVDRV_MAX_BSSID_LIST)
+ bss_idx--;
+ else
+ num_in_table++;
+ } else {
+ if ((bss_new_entry->channel !=
+ pmadapter->pscan_table[bss_idx].channel) &&
+ (bss_new_entry->rssi >
+ pmadapter->pscan_table[bss_idx].rssi)) {
+ PRINTM(MCMND,
+ "skip update the duplicate entry with low rssi\n");
+ return;
+ }
+ }
+ /*
+ * Save the beacon/probe response returned for later
+ * application retrieval. Duplicate beacon/probe
+ * responses are updated if possible
+ */
+ wlan_ret_802_11_scan_store_beacon(pmpriv, bss_idx, num_in_table,
+ bss_new_entry);
+ if (bss_new_entry->pbeacon_buf == MNULL) {
+ PRINTM(MCMND, "No space for beacon, drop this entry\n");
+ num_in_table--;
+ goto done;
+ } else {
+ /* Copy the locally created bss_new_entry to the scan table */
+ memcpy_ext(pmadapter, &pmadapter->pscan_table[bss_idx],
+ bss_new_entry,
+ sizeof(pmadapter->pscan_table[bss_idx]),
+ sizeof(pmadapter->pscan_table[bss_idx]));
+ }
+done:
+ *num_in_tbl = num_in_table;
+ return;
+}
+
+/**
+ * @brief This function parse and store the extended scan results
+ *
+ * @param pmpriv A pointer to mlan_private structure
+ * @param number_of_sets Number of BSS
+ * @param pscan_resp A pointer to scan response buffer
+ * @param scan_resp_size Size of scan response buffer
+ *
+ * @return MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ */
+static mlan_status wlan_parse_ext_scan_result(mlan_private *pmpriv,
+ t_u8 number_of_sets,
+ t_u8 *pscan_resp,
+ t_u16 scan_resp_size)
+{
+ mlan_status ret = MLAN_STATUS_SUCCESS;
+ mlan_adapter *pmadapter = pmpriv->adapter;
+ mlan_callbacks *pcb = MNULL;
+ BSSDescriptor_t *bss_new_entry = MNULL;
+ t_u8 *pbss_info;
+ t_u32 bytes_left;
+ t_u32 bytes_left_for_tlv;
+ t_u32 num_in_table;
+ t_u32 idx;
+ t_u64 tsf_val;
+ chan_freq_power_t *cfp;
+ t_u16 tlv_type, tlv_len;
+ MrvlIEtypes_Data_t *ptlv = MNULL;
+ MrvlIEtypes_Bss_Scan_Rsp_t *pscan_rsp_tlv = MNULL;
+ MrvlIEtypes_Bss_Scan_Info_t *pscan_info_tlv = MNULL;
+ t_u8 band;
+ t_u32 age_ts_usec;
+
+ ENTER();
+ pcb = (pmlan_callbacks)&pmadapter->callbacks;
+
+ if (number_of_sets > MRVDRV_MAX_BSSID_LIST) {
+ PRINTM(MERROR,
+ "EXT_SCAN: Invalid number of AP returned (%d)!!\n",
+ number_of_sets);
+ ret = MLAN_STATUS_FAILURE;
+ goto done;
+ }
+
+ bytes_left = scan_resp_size;
+ PRINTM(MINFO, "EXT_SCAN: bss_descript_size %d\n", scan_resp_size);
+ PRINTM(MINFO, "EXT_SCAN: returned %d APs before parsing\n",
+ number_of_sets);
+
+ num_in_table = pmadapter->num_in_scan_table;
+ ptlv = (MrvlIEtypes_Data_t *)pscan_resp;
+
+ /*
+ * Process each scan response returned number_of_sets. Save
+ * the information in the bss_new_entry and then insert into the
+ * driver scan table either as an update to an existing entry
+ * or as an addition at the end of the table
+ */
+ ret = pcb->moal_malloc(pmadapter->pmoal_handle, sizeof(BSSDescriptor_t),
+ MLAN_MEM_DEF, (t_u8 **)&bss_new_entry);
+
+ if (ret != MLAN_STATUS_SUCCESS || !bss_new_entry) {
+ PRINTM(MERROR, "Memory allocation for bss_new_entry failed!\n");
+ ret = MLAN_STATUS_FAILURE;
+ goto done;
+ }
+
+ for (idx = 0;
+ idx < number_of_sets && bytes_left > sizeof(MrvlIEtypesHeader_t);
+ idx++) {
+ tlv_type = wlan_le16_to_cpu(ptlv->header.type);
+ tlv_len = wlan_le16_to_cpu(ptlv->header.len);
+ if (bytes_left < sizeof(MrvlIEtypesHeader_t) + tlv_len) {
+ PRINTM(MERROR,
+ "EXT_SCAN: Error bytes left < TLV length\n");
+ break;
+ }
+ pscan_rsp_tlv = MNULL;
+ pscan_info_tlv = MNULL;
+ bytes_left_for_tlv = bytes_left;
+ /*
+ * BSS response TLV with beacon or probe response buffer
+ * at the initial position of each descriptor
+ */
+ if (tlv_type == TLV_TYPE_BSS_SCAN_RSP) {
+ pbss_info = (t_u8 *)ptlv;
+ pscan_rsp_tlv = (MrvlIEtypes_Bss_Scan_Rsp_t *)ptlv;
+ ptlv = (MrvlIEtypes_Data_t *)(ptlv->data + tlv_len);
+ bytes_left_for_tlv -=
+ (tlv_len + sizeof(MrvlIEtypesHeader_t));
+ } else
+ break;
+
+ /* Process variable TLV */
+ while (bytes_left_for_tlv >= sizeof(MrvlIEtypesHeader_t) &&
+ wlan_le16_to_cpu(ptlv->header.type) !=
+ TLV_TYPE_BSS_SCAN_RSP) {
+ tlv_type = wlan_le16_to_cpu(ptlv->header.type);
+ tlv_len = wlan_le16_to_cpu(ptlv->header.len);
+ if (bytes_left_for_tlv <
+ sizeof(MrvlIEtypesHeader_t) + tlv_len) {
+ PRINTM(MERROR,
+ "EXT_SCAN: Error in processing TLV, "
+ "bytes left < TLV length\n");
+ pscan_rsp_tlv = MNULL;
+ bytes_left_for_tlv = 0;
+ continue;
+ }
+ switch (tlv_type) {
+ case TLV_TYPE_BSS_SCAN_INFO:
+ pscan_info_tlv =
+ (MrvlIEtypes_Bss_Scan_Info_t *)ptlv;
+ if (tlv_len !=
+ sizeof(MrvlIEtypes_Bss_Scan_Info_t) -
+ sizeof(MrvlIEtypesHeader_t)) {
+ bytes_left_for_tlv = 0;
+ continue;
+ }
+ break;
+ default:
+ break;
+ }
+ ptlv = (MrvlIEtypes_Data_t *)(ptlv->data + tlv_len);
+ bytes_left -= (tlv_len + sizeof(MrvlIEtypesHeader_t));
+ bytes_left_for_tlv -=
+ (tlv_len + sizeof(MrvlIEtypesHeader_t));
+ }
+ /* No BSS response TLV */
+ if (pscan_rsp_tlv == MNULL)
+ 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
+ */
+ pbss_info += sizeof(t_u16);
+ bytes_left -= sizeof(t_u16);
+
+ /* Zero out the bss_new_entry we are about to store info in */
+ memset(pmadapter, bss_new_entry, 0x00, sizeof(BSSDescriptor_t));
+
+ /* Process the data fields and IEs returned for this BSS */
+ if (wlan_interpret_bss_desc_with_ie(
+ pmadapter, bss_new_entry, &pbss_info, &bytes_left,
+ MTRUE) == MLAN_STATUS_SUCCESS) {
+ PRINTM(MINFO, "EXT_SCAN: BSSID = " MACSTR "\n",
+ MAC2STR(bss_new_entry->mac_address));
+
+ band = BAND_G;
+ /*
+ * If the BSS info TLV was appended to the scan results,
+ * save this entry's TSF value in the networkTSF field.
+ * The networkTSF is the firmware's TSF value at the
+ * time the beacon or probe response was received.
+ */
+ if (pscan_info_tlv) {
+ /* RSSI is 2 byte long */
+ bss_new_entry->rssi = -(t_s32)(
+ wlan_le16_to_cpu(pscan_info_tlv->rssi));
+ PRINTM(MINFO, "EXT_SCAN: RSSI=%d\n",
+ bss_new_entry->rssi);
+ memcpy_ext(pmpriv->adapter, &tsf_val,
+ &pscan_info_tlv->tsf,
+ sizeof(tsf_val), sizeof(tsf_val));
+ tsf_val = wlan_le64_to_cpu(tsf_val);
+ memcpy_ext(pmpriv->adapter,
+ &bss_new_entry->network_tsf,
+ &tsf_val,
+ sizeof(bss_new_entry->network_tsf),
+ sizeof(bss_new_entry->network_tsf));
+ band = radio_type_to_band(
+ pscan_info_tlv->bandcfg.chanBand);
+ if (!bss_new_entry->channel)
+ bss_new_entry->channel =
+ pscan_info_tlv->channel;
+ }
+ /* Save the band designation for this entry for use in
+ * join */
+ bss_new_entry->bss_band = band;
+
+ cfp = wlan_find_cfp_by_band_and_channel(
+ pmadapter, (t_u8)bss_new_entry->bss_band,
+ (t_u16)bss_new_entry->channel);
+ if (cfp)
+ bss_new_entry->freq = cfp->freq;
+ else
+ bss_new_entry->freq = 0;
+
+ /* Skip entry if on blacklisted channel */
+ if (cfp && cfp->dynamic.blacklist) {
+ PRINTM(MINFO,
+ "EXT_SCAN: dropping entry on blacklist channel.\n");
+ continue;
+ }
+ wlan_add_new_entry_to_scan_table(pmpriv, bss_new_entry,
+ &num_in_table);
+
+ } else {
+ /* Error parsing/interpreting the scan response, skipped
+ */
+ PRINTM(MERROR,
+ "EXT_SCAN: wlan_interpret_bss_desc_with_ie returned error\n");
+ }
+ }
+
+ PRINTM(MCMND, "EXT_SCAN: Scanned %2d APs, %d valid, %d total\n",
+ number_of_sets, num_in_table - pmadapter->num_in_scan_table,
+ num_in_table);
+
+ /* Update the total number of BSSIDs in the scan table */
+ pmadapter->num_in_scan_table = num_in_table;
+ /* Update the age_in_second */
+ pmadapter->callbacks.moal_get_system_time(
+ pmadapter->pmoal_handle, &pmadapter->age_in_secs, &age_ts_usec);
+
+done:
+ if (bss_new_entry)
+ pcb->moal_mfree(pmadapter->pmoal_handle, (t_u8 *)bss_new_entry);
+
+ LEAVE();
+ return ret;
+}
+
+/**
+ * @brief This function handles the event extended scan report
+ *
+ * @param pmpriv A pointer to mlan_private structure
+ * @param pmbuf A pointer to mlan_buffer
+ *
+ * @return MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ */
+mlan_status wlan_handle_event_ext_scan_report(mlan_private *pmpriv,
+ mlan_buffer *pmbuf)
+{
+ mlan_adapter *pmadapter = pmpriv->adapter;
+ mlan_callbacks *pcb = &pmadapter->callbacks;
+ mlan_ioctl_req *pioctl_req = MNULL;
+ cmd_ctrl_node *pcmd_node = MNULL;
+ mlan_status ret = MLAN_STATUS_SUCCESS;
+
+ mlan_event_scan_result *pevent_scan =
+ (pmlan_event_scan_result)(pmbuf->pbuf + pmbuf->data_offset);
+ t_u8 *ptlv = (pmbuf->pbuf + pmbuf->data_offset +
+ sizeof(mlan_event_scan_result));
+ t_u16 tlv_buf_left = wlan_le16_to_cpu(pevent_scan->buf_size);
+
+ DBG_HEXDUMP(MCMD_D, "EVENT EXT_SCAN", pmbuf->pbuf + pmbuf->data_offset,
+ pmbuf->data_len);
+ wlan_parse_ext_scan_result(pmpriv, pevent_scan->num_of_set, ptlv,
+ tlv_buf_left);
+ if (!pevent_scan->more_event &&
+ (pmadapter->ext_scan_type != EXT_SCAN_ENHANCE)) {
+ wlan_request_cmd_lock(pmadapter);
+ if (!util_peek_list(pmadapter->pmoal_handle,
+ &pmadapter->scan_pending_q, MNULL, MNULL)) {
+ wlan_release_cmd_lock(pmadapter);
+ if (pmadapter->pscan_ioctl_req) {
+ if (((mlan_ds_scan *)
+ pmadapter->pscan_ioctl_req->pbuf)
+ ->sub_command ==
+ MLAN_OID_SCAN_SPECIFIC_SSID ||
+ ((mlan_ds_scan *)
+ pmadapter->pscan_ioctl_req->pbuf)
+ ->sub_command ==
+ MLAN_OID_SCAN_USER_CONFIG) {
+ if (wlan_active_scan_req_for_passive_chan(
+ pmpriv,
+ pmadapter->pscan_ioctl_req)) {
+ LEAVE();
+ return ret;
+ }
+ }
+ }
+ /*
+ * Process the resulting scan table:
+ * - Remove any bad ssids
+ * - Update our current BSS information from scan data
+ */
+ wlan_scan_process_results(pmpriv);
+ wlan_request_cmd_lock(pmadapter);
+ pmadapter->scan_processing = MFALSE;
+ pioctl_req = pmadapter->pscan_ioctl_req;
+ pmadapter->pscan_ioctl_req = MNULL;
+ /* Need to indicate IOCTL complete */
+ if (pioctl_req != MNULL) {
+ pioctl_req->status_code = MLAN_ERROR_NO_ERROR;
+ /* Indicate ioctl complete */
+ pcb->moal_ioctl_complete(
+ pmadapter->pmoal_handle,
+ (pmlan_ioctl_req)pioctl_req,
+ MLAN_STATUS_SUCCESS);
+ }
+ wlan_release_cmd_lock(pmadapter);
+
+ pmadapter->bgscan_reported = MFALSE;
+ wlan_recv_event(pmpriv, MLAN_EVENT_ID_DRV_SCAN_REPORT,
+ MNULL);
+ } else {
+ /* If firmware not ready, do not issue any more scan
+ * commands */
+ if (pmadapter->hw_status != WlanHardwareStatusReady) {
+ wlan_release_cmd_lock(pmadapter);
+ /* Flush all pending scan commands */
+ wlan_flush_scan_queue(pmadapter);
+ wlan_request_cmd_lock(pmadapter);
+ pmadapter->scan_processing = MFALSE;
+ pioctl_req = pmadapter->pscan_ioctl_req;
+ pmadapter->pscan_ioctl_req = MNULL;
+ /* Indicate IOCTL complete */
+ if (pioctl_req != MNULL) {
+ pioctl_req->status_code =
+ MLAN_ERROR_FW_NOT_READY;
+
+ /* Indicate ioctl complete */
+ pcb->moal_ioctl_complete(
+ pmadapter->pmoal_handle,
+ (pmlan_ioctl_req)pioctl_req,
+ MLAN_STATUS_FAILURE);
+ }
+ wlan_release_cmd_lock(pmadapter);
+ } else {
+ /* Get scan command from scan_pending_q and put
+ * to cmd_pending_q */
+ pcmd_node = (cmd_ctrl_node *)util_dequeue_list(
+ pmadapter->pmoal_handle,
+ &pmadapter->scan_pending_q, MNULL,
+ MNULL);
+ wlan_insert_cmd_to_pending_q(pmadapter,
+ pcmd_node, MTRUE);
+ wlan_release_cmd_lock(pmadapter);
+ }
+ }
+ }
+ LEAVE();
+ return ret;
+}
+
+/**
+ * @brief This function handles the event extended scan status
+ *
+ * @param pmpriv A pointer to mlan_private structure
+ * @param pmbuf A pointer to mlan_buffer
+ *
+ * @return MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ */
+mlan_status wlan_handle_event_ext_scan_status(mlan_private *pmpriv,
+ mlan_buffer *pmbuf)
+{
+ mlan_adapter *pmadapter = pmpriv->adapter;
+ mlan_status ret = MLAN_STATUS_SUCCESS;
+ mlan_event_scan_status *scan_event;
+ mlan_ioctl_req *pioctl_req;
+ mlan_callbacks *pcb = (mlan_callbacks *)&pmadapter->callbacks;
+ t_u16 tlv_buf_left, tlv_len, tlv_type;
+ MrvlIEtypesHeader_t *tlv;
+ MrvlIEtypes_ChannelStats_t *tlv_chan_stats;
+ t_u8 status;
+
+ ENTER();
+
+ if (pmbuf->data_len < sizeof(mlan_event_scan_status)) {
+ PRINTM(MERROR, "Wrong ext scan status event data length\n");
+ ret = MLAN_STATUS_FAILURE;
+ goto done;
+ }
+
+ scan_event =
+ (pmlan_event_scan_status)(pmbuf->pbuf + pmbuf->data_offset);
+ DBG_HEXDUMP(MCMD_D, "EVENT: Ext_Scan_Status", scan_event,
+ pmbuf->data_len);
+ status = scan_event->scan_status;
+ PRINTM(MEVENT, "ext_scan_status: status %d (scan %s), buf_len %d\n",
+ status, status ? "cancelled" : "success", scan_event->buf_len);
+
+ tlv = (MrvlIEtypesHeader_t *)scan_event->event_buf;
+ tlv_buf_left = pmbuf->data_len - sizeof(mlan_event_scan_status);
+ while (tlv_buf_left >= sizeof(MrvlIEtypesHeader_t)) {
+ tlv_type = wlan_le16_to_cpu(tlv->type);
+ tlv_len = wlan_le16_to_cpu(tlv->len);
+ if (tlv_buf_left < (tlv_len + sizeof(MrvlIEtypesHeader_t))) {
+ PRINTM(MERROR,
+ "Error process scan gap tlv: length %d type 0x%x\n",
+ tlv_len, tlv_type);
+ ret = MLAN_STATUS_FAILURE;
+ goto done;
+ }
+ switch (tlv_type) {
+ case TLV_TYPE_CHANNEL_STATS:
+ tlv_chan_stats = (MrvlIEtypes_ChannelStats_t *)tlv;
+ wlan_update_chan_statistics(pmpriv, tlv_chan_stats);
+ break;
+ default:
+ break;
+ }
+ tlv_buf_left -= tlv_len + sizeof(MrvlIEtypesHeader_t);
+ tlv = (MrvlIEtypesHeader_t *)((t_u8 *)tlv + tlv_len +
+ sizeof(MrvlIEtypesHeader_t));
+ }
+
+done:
+ /* Now we got response from FW, cancel the command timer */
+ if (!pmadapter->curr_cmd && pmadapter->cmd_timer_is_set) {
+ /* Cancel command timeout timer */
+ pcb->moal_stop_timer(pmadapter->pmoal_handle,
+ pmadapter->pmlan_cmd_timer);
+ /* Cancel command timeout timer */
+ pmadapter->cmd_timer_is_set = MFALSE;
+ }
+ if (pmadapter->pscan_ioctl_req) {
+ if (((mlan_ds_scan *)pmadapter->pscan_ioctl_req->pbuf)
+ ->sub_command ==
+ MLAN_OID_SCAN_SPECIFIC_SSID ||
+ ((mlan_ds_scan *)pmadapter->pscan_ioctl_req->pbuf)
+ ->sub_command ==
+ MLAN_OID_SCAN_USER_CONFIG) {
+ if (wlan_active_scan_req_for_passive_chan(
+ pmpriv, pmadapter->pscan_ioctl_req)) {
+ LEAVE();
+ return ret;
+ }
+ }
+ }
+ /*
+ * Process the resulting scan table:
+ * - Remove any bad ssids
+ * - Update our current BSS information from scan data
+ */
+ wlan_scan_process_results(pmpriv);
+ /** Complete scan ioctl */
+ wlan_request_cmd_lock(pmadapter);
+ pmadapter->scan_processing = MFALSE;
+ pmadapter->ext_scan_type = EXT_SCAN_DEFAULT;
+ pioctl_req = pmadapter->pscan_ioctl_req;
+ pmadapter->pscan_ioctl_req = MNULL;
+ /* Need to indicate IOCTL complete */
+ if (pioctl_req != MNULL) {
+ pioctl_req->status_code = MLAN_ERROR_NO_ERROR;
+ /* Indicate ioctl complete */
+ pcb->moal_ioctl_complete(pmadapter->pmoal_handle, pioctl_req,
+ MLAN_STATUS_SUCCESS);
+ }
+ wlan_release_cmd_lock(pmadapter);
+ pmadapter->bgscan_reported = MFALSE;
+ wlan_recv_event(pmpriv, MLAN_EVENT_ID_DRV_SCAN_REPORT, MNULL);
+ LEAVE();
+ return ret;
+}
+
+/**
+ * @brief This function prepares command of bg_scan_query.
+ *
+ * @param pmpriv A pointer to mlan_private structure
+ * @param pcmd A pointer to HostCmd_DS_COMMAND structure
+ * @param pdata_buf Void pointer cast of a wlan_scan_cmd_config struct used
+ * to set the fields/TLVs for the command sent to firmware
+ *
+ * @return MLAN_STATUS_SUCCESS
+ */
+mlan_status wlan_cmd_802_11_bg_scan_query(mlan_private *pmpriv,
+ HostCmd_DS_COMMAND *pcmd,
+ t_void *pdata_buf)
+{
+ HostCmd_DS_802_11_BG_SCAN_QUERY *bg_query = &pcmd->params.bg_scan_query;
+
+ ENTER();
+
+ pcmd->command = wlan_cpu_to_le16(HostCmd_CMD_802_11_BG_SCAN_QUERY);
+ pcmd->size = wlan_cpu_to_le16(sizeof(HostCmd_DS_802_11_BG_SCAN_QUERY) +
+ S_DS_GEN);
+
+ bg_query->flush = MTRUE;
+
+ LEAVE();
+ return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ * @brief Create a channel list for the driver to scan based on region info
+ *
+ * Use the driver region/band information to construct a comprehensive list
+ * of channels to scan. This routine is used for any scan that is not
+ * provided a specific channel list to scan.
+ *
+ * @param pmpriv A pointer to mlan_private structure
+ * @param pbg_scan_in pointer to scan configuration parameters
+ * @param tlv_chan_list A pointer to structure
+ * MrvlIEtypes_ChanListParamSet_t
+ *
+ * @return channel number
+ */
+static t_u8
+wlan_bgscan_create_channel_list(mlan_private *pmpriv,
+ const wlan_bgscan_cfg *pbg_scan_in,
+ MrvlIEtypes_ChanListParamSet_t *tlv_chan_list)
+{
+ mlan_adapter *pmadapter = pmpriv->adapter;
+ region_chan_t *pscan_region;
+ chan_freq_power_t *cfp;
+ t_u32 region_idx;
+ t_u32 chan_idx = 0;
+ t_u32 next_chan;
+ t_u8 scan_type;
+ t_u8 radio_type;
+ t_u8 band;
+
+ ENTER();
+
+ for (region_idx = 0; region_idx < NELEMENTS(pmadapter->region_channel);
+ region_idx++) {
+ if (wlan_11d_is_enabled(pmpriv) &&
+ pmpriv->media_connected != MTRUE) {
+ /* Scan all the supported chan for the first scan */
+ if (!pmadapter->universal_channel[region_idx].valid)
+ continue;
+ pscan_region =
+ &pmadapter->universal_channel[region_idx];
+ } else {
+ if (!pmadapter->region_channel[region_idx].valid)
+ continue;
+ pscan_region = &pmadapter->region_channel[region_idx];
+ }
+
+ if (pbg_scan_in && !pbg_scan_in->chan_list[0].chan_number &&
+ pbg_scan_in->chan_list[0].radio_type & BAND_SPECIFIED) {
+ radio_type = pbg_scan_in->chan_list[0].radio_type &
+ ~BAND_SPECIFIED;
+ if (!radio_type && (pscan_region->band != BAND_B) &&
+ (pscan_region->band != BAND_G))
+ continue;
+ if (radio_type && (pscan_region->band != BAND_A))
+ continue;
+ }
+ if ((pbg_scan_in &&
+ (pbg_scan_in->bss_type == MLAN_SCAN_MODE_IBSS)) ||
+ pmpriv->bss_mode == MLAN_BSS_MODE_IBSS)
+ band = pmadapter->adhoc_start_band;
+ else
+ band = pmpriv->config_bands;
+ if (!wlan_is_band_compatible(band, pscan_region->band))
+ continue;
+ for (next_chan = 0; next_chan < pscan_region->num_cfp;
+ next_chan++, chan_idx++) {
+ if (chan_idx >= WLAN_BG_SCAN_CHAN_MAX)
+ break;
+ /*
+ * Set the default scan type to ACTIVE SCAN type, will
+ * later be changed to passive on a per channel basis
+ * if restricted by regulatory requirements (11d or 11h)
+ */
+ scan_type = MLAN_SCAN_TYPE_ACTIVE;
+ cfp = pscan_region->pcfp + next_chan;
+
+ switch (pscan_region->band) {
+ case BAND_A:
+ tlv_chan_list->chan_scan_param[chan_idx]
+ .bandcfg.chanBand = BAND_5GHZ;
+ /* Passive scan on DFS channels */
+ if (wlan_11h_radar_detect_required(
+ pmpriv, (t_u8)cfp->channel))
+ scan_type = MLAN_SCAN_TYPE_PASSIVE;
+ break;
+ case BAND_B:
+ case BAND_G:
+ if (wlan_bg_scan_type_is_passive(
+ pmpriv, (t_u8)cfp->channel))
+ scan_type = MLAN_SCAN_TYPE_PASSIVE;
+ tlv_chan_list->chan_scan_param[chan_idx]
+ .bandcfg.chanBand = BAND_2GHZ;
+ break;
+ default:
+ tlv_chan_list->chan_scan_param[chan_idx]
+ .bandcfg.chanBand = BAND_2GHZ;
+ break;
+ }
+
+ if (pbg_scan_in &&
+ pbg_scan_in->chan_list[0].scan_time) {
+ tlv_chan_list->chan_scan_param[chan_idx]
+ .max_scan_time = wlan_cpu_to_le16(
+ (t_u16)pbg_scan_in->chan_list[0]
+ .scan_time);
+ tlv_chan_list->chan_scan_param[chan_idx]
+ .min_scan_time = wlan_cpu_to_le16(
+ (t_u16)pbg_scan_in->chan_list[0]
+ .scan_time);
+ } else if (scan_type == MLAN_SCAN_TYPE_PASSIVE) {
+ tlv_chan_list->chan_scan_param[chan_idx]
+ .max_scan_time = wlan_cpu_to_le16(
+ pmadapter->passive_scan_time);
+ tlv_chan_list->chan_scan_param[chan_idx]
+ .min_scan_time = wlan_cpu_to_le16(
+ pmadapter->passive_scan_time);
+ } else {
+ tlv_chan_list->chan_scan_param[chan_idx]
+ .max_scan_time = wlan_cpu_to_le16(
+ pmadapter->specific_scan_time);
+ tlv_chan_list->chan_scan_param[chan_idx]
+ .min_scan_time = wlan_cpu_to_le16(
+ pmadapter->specific_scan_time);
+ }
+
+ if (scan_type == MLAN_SCAN_TYPE_PASSIVE) {
+ tlv_chan_list->chan_scan_param[chan_idx]
+ .chan_scan_mode.passive_scan = MTRUE;
+ } else {
+ tlv_chan_list->chan_scan_param[chan_idx]
+ .chan_scan_mode.passive_scan = MFALSE;
+ }
+
+ tlv_chan_list->chan_scan_param[chan_idx].chan_number =
+ (t_u8)cfp->channel;
+ }
+ }
+
+ LEAVE();
+ return chan_idx;
+}
+
+/**
+ * @brief This function prepares command of bg_scan_config
+ *
+ * @param pmpriv A pointer to mlan_private structure
+ * @param pcmd A pointer to HostCmd_DS_COMMAND structure
+ * @param pdata_buf Void pointer cast of a wlan_scan_cmd_config struct used
+ * to set the fields/TLVs for the command sent to firmware
+ *
+ * @return MLAN_STATUS_SUCCESS
+ */
+mlan_status wlan_cmd_bgscan_config(mlan_private *pmpriv,
+ HostCmd_DS_COMMAND *pcmd, t_void *pdata_buf)
+{
+ mlan_adapter *pmadapter = pmpriv->adapter;
+ HostCmd_DS_802_11_BG_SCAN_CONFIG *bg_scan =
+ &pcmd->params.bg_scan_config;
+ wlan_bgscan_cfg *bg_scan_in = (wlan_bgscan_cfg *)pdata_buf;
+ t_u16 cmd_size = 0;
+ MrvlIEtypes_NumProbes_t *pnum_probes_tlv = MNULL;
+ MrvlIEtypes_BeaconLowRssiThreshold_t *rssi_tlv = MNULL;
+ MrvlIEtypes_BeaconLowSnrThreshold_t *snr_tlv = MNULL;
+ MrvlIEtypes_WildCardSsIdParamSet_t *pwildcard_ssid_tlv = MNULL;
+ MrvlIEtypes_ChanListParamSet_t *tlv_chan_list = MNULL;
+ MrvlIEtypes_StartLater_t *tlv_start_later = MNULL;
+ MrvlIEtypes_RepeatCount_t *tlv_repeat = MNULL;
+ MrvlIEtypes_EESParamSet_t *tlv_ees_cfg = MNULL;
+ MrvlIEtype_EESNetworkCfg_t *tlv_ees_net_cfg = MNULL;
+ MrvlIEtypes_Cipher_t *tlv_ees_cipher = MNULL;
+ MrvlIEtypes_SsIdParamSet_t *tlv_ssid = MNULL;
+ MrvlIETypes_HTCap_t *pht_cap = MNULL;
+ MrvlIETypes_VHTCap_t *pvht_cap = MNULL;
+ MrvlIEtypes_Extension_t *phe_cap = MNULL;
+ t_u16 len = 0;
+
+ t_u8 index;
+ t_u8 *tlv = MNULL;
+ t_u16 num_probes = 0;
+ t_u32 ssid_idx;
+ t_u32 ssid_len = 0;
+ t_u32 chan_idx;
+ t_u32 chan_num;
+ t_u8 radio_type;
+ t_u16 scan_dur;
+ t_u8 scan_type;
+ t_u8 band;
+ const t_u8 zero_mac[6] = {0, 0, 0, 0, 0, 0};
+
+ ENTER();
+
+ pcmd->command = wlan_cpu_to_le16(HostCmd_CMD_802_11_BG_SCAN_CONFIG);
+ bg_scan->action = wlan_cpu_to_le16(bg_scan_in->action);
+ bg_scan->enable = bg_scan_in->enable;
+ bg_scan->bss_type = bg_scan_in->bss_type;
+ cmd_size = sizeof(HostCmd_DS_802_11_BG_SCAN_CONFIG) + S_DS_GEN;
+ if (bg_scan_in->scan_interval)
+ bg_scan->scan_interval =
+ wlan_cpu_to_le32(bg_scan_in->scan_interval);
+ else
+ bg_scan->scan_interval =
+ wlan_cpu_to_le32(DEFAULT_BGSCAN_INTERVAL);
+ bg_scan->report_condition =
+ wlan_cpu_to_le32(bg_scan_in->report_condition);
+
+ if ((bg_scan_in->action == BG_SCAN_ACT_GET) ||
+ (bg_scan_in->action == BG_SCAN_ACT_GET_PPS_UAPSD) ||
+ (!bg_scan->enable))
+ goto done;
+
+ tlv = (t_u8 *)bg_scan + sizeof(HostCmd_DS_802_11_BG_SCAN_CONFIG);
+ num_probes = (bg_scan_in->num_probes ? bg_scan_in->num_probes :
+ pmadapter->scan_probes);
+ if (num_probes) {
+ pnum_probes_tlv = (MrvlIEtypes_NumProbes_t *)tlv;
+ pnum_probes_tlv->header.type =
+ wlan_cpu_to_le16(TLV_TYPE_NUMPROBES);
+ pnum_probes_tlv->header.len =
+ wlan_cpu_to_le16(sizeof(pnum_probes_tlv->num_probes));
+ pnum_probes_tlv->num_probes =
+ wlan_cpu_to_le16((t_u16)num_probes);
+ tlv += sizeof(MrvlIEtypes_NumProbes_t);
+ cmd_size += sizeof(MrvlIEtypes_NumProbes_t);
+ }
+ if (bg_scan_in->rssi_threshold) {
+ rssi_tlv = (MrvlIEtypes_BeaconLowRssiThreshold_t *)tlv;
+ rssi_tlv->header.type = wlan_cpu_to_le16(TLV_TYPE_RSSI_LOW);
+ rssi_tlv->header.len = wlan_cpu_to_le16(
+ sizeof(MrvlIEtypes_BeaconLowRssiThreshold_t) -
+ sizeof(MrvlIEtypesHeader_t));
+ rssi_tlv->value = bg_scan_in->rssi_threshold;
+ rssi_tlv->frequency = 0;
+ tlv += sizeof(MrvlIEtypes_BeaconLowRssiThreshold_t);
+ cmd_size += sizeof(MrvlIEtypes_BeaconLowRssiThreshold_t);
+ }
+ if (bg_scan_in->snr_threshold) {
+ snr_tlv = (MrvlIEtypes_BeaconLowSnrThreshold_t *)tlv;
+ snr_tlv->header.type = wlan_cpu_to_le16(TLV_TYPE_SNR_LOW);
+ snr_tlv->header.len = wlan_cpu_to_le16(
+ sizeof(MrvlIEtypes_BeaconLowSnrThreshold_t) -
+ sizeof(MrvlIEtypesHeader_t));
+ snr_tlv->value = bg_scan_in->snr_threshold;
+ snr_tlv->frequency = 0;
+ tlv += sizeof(MrvlIEtypes_BeaconLowRssiThreshold_t);
+ cmd_size += sizeof(MrvlIEtypes_BeaconLowRssiThreshold_t);
+ }
+ if (bg_scan_in->repeat_count) {
+ tlv_repeat = (MrvlIEtypes_RepeatCount_t *)tlv;
+ tlv_repeat->header.type =
+ wlan_cpu_to_le16(TLV_TYPE_REPEAT_COUNT);
+ tlv_repeat->header.len =
+ wlan_cpu_to_le16(sizeof(MrvlIEtypes_RepeatCount_t) -
+ sizeof(MrvlIEtypesHeader_t));
+ tlv_repeat->repeat_count =
+ wlan_cpu_to_le16(bg_scan_in->repeat_count);
+ tlv += sizeof(MrvlIEtypes_RepeatCount_t);
+ cmd_size += sizeof(MrvlIEtypes_RepeatCount_t);
+ }
+ for (ssid_idx = 0; ((ssid_idx < NELEMENTS(bg_scan_in->ssid_list)) &&
+ (*bg_scan_in->ssid_list[ssid_idx].ssid ||
+ bg_scan_in->ssid_list[ssid_idx].max_len));
+ ssid_idx++) {
+ ssid_len = wlan_strlen(
+ (char *)bg_scan_in->ssid_list[ssid_idx].ssid);
+ pwildcard_ssid_tlv = (MrvlIEtypes_WildCardSsIdParamSet_t *)tlv;
+ pwildcard_ssid_tlv->header.type =
+ wlan_cpu_to_le16(TLV_TYPE_WILDCARDSSID);
+ pwildcard_ssid_tlv->header.len = (t_u16)(
+ ssid_len + sizeof(pwildcard_ssid_tlv->max_ssid_length));
+ pwildcard_ssid_tlv->max_ssid_length =
+ bg_scan_in->ssid_list[ssid_idx].max_len;
+ memcpy_ext(pmadapter, pwildcard_ssid_tlv->ssid,
+ bg_scan_in->ssid_list[ssid_idx].ssid, ssid_len,
+ MLAN_MAX_SSID_LENGTH);
+ tlv += sizeof(pwildcard_ssid_tlv->header) +
+ pwildcard_ssid_tlv->header.len;
+ cmd_size += sizeof(pwildcard_ssid_tlv->header) +
+ pwildcard_ssid_tlv->header.len;
+ pwildcard_ssid_tlv->header.len =
+ wlan_cpu_to_le16(pwildcard_ssid_tlv->header.len);
+ PRINTM(MINFO, "Scan: ssid_list[%d]: %s, %d\n", ssid_idx,
+ pwildcard_ssid_tlv->ssid,
+ pwildcard_ssid_tlv->max_ssid_length);
+ }
+ if (bg_scan_in->chan_list[0].chan_number) {
+ tlv_chan_list = (MrvlIEtypes_ChanListParamSet_t *)tlv;
+ PRINTM(MINFO, "Scan: Using supplied channel list\n");
+ chan_num = 0;
+ for (chan_idx = 0; chan_idx < WLAN_BG_SCAN_CHAN_MAX &&
+ bg_scan_in->chan_list[chan_idx].chan_number;
+ chan_idx++) {
+ radio_type = bg_scan_in->chan_list[chan_idx].radio_type;
+ if (bg_scan_in->bss_type == MLAN_SCAN_MODE_IBSS ||
+ pmpriv->bss_mode == MLAN_BSS_MODE_IBSS)
+ band = pmadapter->adhoc_start_band;
+ else
+ band = pmpriv->config_bands;
+ if (!wlan_is_band_compatible(
+ band, radio_type_to_band(radio_type)))
+ continue;
+ scan_type = bg_scan_in->chan_list[chan_idx].scan_type;
+ /* Prevent active scanning on a radar controlled channel
+ */
+ if (radio_type == BAND_5GHZ) {
+ if (wlan_11h_radar_detect_required(
+ pmpriv,
+ bg_scan_in->chan_list[chan_idx]
+ .chan_number)) {
+ scan_type = MLAN_SCAN_TYPE_PASSIVE;
+ }
+ }
+ if (radio_type == BAND_2GHZ) {
+ if (wlan_bg_scan_type_is_passive(
+ pmpriv,
+ bg_scan_in->chan_list[chan_idx]
+ .chan_number)) {
+ scan_type = MLAN_SCAN_TYPE_PASSIVE;
+ }
+ }
+ tlv_chan_list->chan_scan_param[chan_num].chan_number =
+ bg_scan_in->chan_list[chan_idx].chan_number;
+ tlv_chan_list->chan_scan_param[chan_num]
+ .bandcfg.chanBand =
+ bg_scan_in->chan_list[chan_idx].radio_type;
+
+ if (scan_type == MLAN_SCAN_TYPE_PASSIVE) {
+ tlv_chan_list->chan_scan_param[chan_num]
+ .chan_scan_mode.passive_scan = MTRUE;
+ } else {
+ tlv_chan_list->chan_scan_param[chan_num]
+ .chan_scan_mode.passive_scan = MFALSE;
+ }
+ if (bg_scan_in->chan_list[chan_idx].scan_time) {
+ scan_dur =
+ (t_u16)bg_scan_in->chan_list[chan_idx]
+ .scan_time;
+ } else {
+ if (scan_type == MLAN_SCAN_TYPE_PASSIVE) {
+ scan_dur = pmadapter->passive_scan_time;
+ } else {
+ scan_dur =
+ pmadapter->specific_scan_time;
+ }
+ }
+ tlv_chan_list->chan_scan_param[chan_num].min_scan_time =
+ wlan_cpu_to_le16(scan_dur);
+ tlv_chan_list->chan_scan_param[chan_num].max_scan_time =
+ wlan_cpu_to_le16(scan_dur);
+ chan_num++;
+ }
+ tlv_chan_list->header.type =
+ wlan_cpu_to_le16(TLV_TYPE_CHANLIST);
+ tlv_chan_list->header.len =
+ wlan_cpu_to_le16(sizeof(ChanScanParamSet_t) * chan_num);
+ tlv += sizeof(MrvlIEtypesHeader_t) +
+ sizeof(ChanScanParamSet_t) * chan_num;
+ cmd_size += sizeof(MrvlIEtypesHeader_t) +
+ sizeof(ChanScanParamSet_t) * chan_num;
+ } else {
+ tlv_chan_list = (MrvlIEtypes_ChanListParamSet_t *)tlv;
+ chan_num = wlan_bgscan_create_channel_list(pmpriv, bg_scan_in,
+ tlv_chan_list);
+ tlv_chan_list->header.type =
+ wlan_cpu_to_le16(TLV_TYPE_CHANLIST);
+ tlv_chan_list->header.len =
+ wlan_cpu_to_le16(sizeof(ChanScanParamSet_t) * chan_num);
+ tlv += sizeof(MrvlIEtypesHeader_t) +
+ sizeof(ChanScanParamSet_t) * chan_num;
+ cmd_size += sizeof(MrvlIEtypesHeader_t) +
+ sizeof(ChanScanParamSet_t) * chan_num;
+ }
+ if (bg_scan_in->chan_per_scan) {
+ bg_scan->chan_per_scan = bg_scan_in->chan_per_scan;
+ } else {
+ if (bg_scan_in->report_condition & BG_SCAN_WAIT_ALL_CHAN_DONE)
+ bg_scan->chan_per_scan = chan_num;
+ else
+ bg_scan->chan_per_scan =
+ MRVDRV_MAX_CHANNELS_PER_SPECIFIC_SCAN;
+ }
+ if (ISSUPP_11NENABLED(pmpriv->adapter->fw_cap_info) &&
+ (pmpriv->config_bands & BAND_GN ||
+ pmpriv->config_bands & BAND_AN)) {
+ pht_cap = (MrvlIETypes_HTCap_t *)tlv;
+ memset(pmadapter, pht_cap, 0, sizeof(MrvlIETypes_HTCap_t));
+ pht_cap->header.type = wlan_cpu_to_le16(HT_CAPABILITY);
+ pht_cap->header.len = sizeof(HTCap_t);
+ wlan_fill_ht_cap_tlv(pmpriv, pht_cap, pmpriv->config_bands,
+ MTRUE);
+ DBG_HEXDUMP(MCMD_D, "BGSCAN: HT_CAPABILITIES IE",
+ (t_u8 *)pht_cap, sizeof(MrvlIETypes_HTCap_t));
+ tlv += sizeof(MrvlIETypes_HTCap_t);
+ cmd_size += sizeof(MrvlIETypes_HTCap_t);
+ pht_cap->header.len = wlan_cpu_to_le16(pht_cap->header.len);
+ }
+ if (ISSUPP_11ACENABLED(pmpriv->adapter->fw_cap_info) &&
+ (pmpriv->config_bands & BAND_AAC)) {
+ pvht_cap = (MrvlIETypes_VHTCap_t *)tlv;
+ memset(pmadapter, pvht_cap, 0, sizeof(MrvlIETypes_VHTCap_t));
+ pvht_cap->header.type = wlan_cpu_to_le16(VHT_CAPABILITY);
+ pvht_cap->header.len = sizeof(VHT_capa_t);
+ wlan_fill_vht_cap_tlv(pmpriv, pvht_cap, pmpriv->config_bands,
+ MFALSE, MFALSE);
+ DBG_HEXDUMP(MCMD_D, "BGSCAN: VHT_CAPABILITIES IE",
+ (t_u8 *)pvht_cap, sizeof(MrvlIETypes_VHTCap_t));
+ tlv += sizeof(MrvlIETypes_VHTCap_t);
+ cmd_size += sizeof(MrvlIETypes_VHTCap_t);
+ pvht_cap->header.len = wlan_cpu_to_le16(pvht_cap->header.len);
+ }
+
+ if (IS_FW_SUPPORT_11AX(pmadapter) &&
+ (pmpriv->config_bands & BAND_AAX)) {
+ phe_cap = (MrvlIEtypes_Extension_t *)tlv;
+ len = wlan_fill_he_cap_tlv(pmpriv, BAND_A, phe_cap, MFALSE);
+ DBG_HEXDUMP(MCMD_D, "BGSCAN: HE_CAPABILITIES IE",
+ (t_u8 *)phe_cap, len);
+ tlv += len;
+ cmd_size += len;
+ }
+ if (wlan_is_ext_capa_support(pmpriv)) {
+ wlan_add_ext_capa_info_ie(pmpriv, MNULL, &tlv);
+ cmd_size += sizeof(MrvlIETypes_ExtCap_t);
+ }
+ if (pmpriv->adapter->ecsa_enable) {
+ t_u8 bandwidth = BW_20MHZ;
+ t_u8 oper_class = 1;
+ t_u32 usr_dot_11n_dev_cap;
+ if (pmpriv->media_connected) {
+ if (pmpriv->config_bands & BAND_A)
+ usr_dot_11n_dev_cap =
+ pmpriv->usr_dot_11n_dev_cap_a;
+ else
+ usr_dot_11n_dev_cap =
+ pmpriv->usr_dot_11n_dev_cap_bg;
+ if (usr_dot_11n_dev_cap & MBIT(17)) {
+ bandwidth = BW_40MHZ;
+ if (ISSUPP_11ACENABLED(
+ pmadapter->fw_cap_info) &&
+ (pmpriv->config_bands & BAND_AAC))
+ bandwidth = BW_80MHZ;
+ }
+ wlan_get_curr_oper_class(
+ pmpriv,
+ pmpriv->curr_bss_params.bss_descriptor.channel,
+ bandwidth, &oper_class);
+ }
+ len = wlan_add_supported_oper_class_ie(pmpriv, &tlv,
+ oper_class);
+ cmd_size += len;
+ }
+
+ tlv_start_later = (MrvlIEtypes_StartLater_t *)tlv;
+ tlv_start_later->header.type =
+ wlan_cpu_to_le16(TLV_TYPE_STARTBGSCANLATER);
+ tlv_start_later->header.len = wlan_cpu_to_le16(
+ sizeof(MrvlIEtypes_StartLater_t) - sizeof(MrvlIEtypesHeader_t));
+ tlv_start_later->value = wlan_cpu_to_le16(bg_scan_in->start_later);
+ tlv += sizeof(MrvlIEtypes_StartLater_t);
+ cmd_size += sizeof(MrvlIEtypes_StartLater_t);
+
+ if (bg_scan_in->config_ees) {
+ /* Fill EES configuration */
+ tlv_ees_cfg = (MrvlIEtypes_EESParamSet_t *)tlv;
+ tlv_ees_cfg->header.type = wlan_cpu_to_le16(TLV_TYPE_EES_CFG);
+ tlv_ees_cfg->header.len =
+ wlan_cpu_to_le16(sizeof(MrvlIEtypes_EESParamSet_t) -
+ sizeof(MrvlIEtypesHeader_t));
+ tlv_ees_cfg->ees_mode = wlan_cpu_to_le16(bg_scan_in->ees_mode);
+ tlv_ees_cfg->report_cond =
+ wlan_cpu_to_le16(bg_scan_in->report_cond);
+ tlv_ees_cfg->high_period =
+ wlan_cpu_to_le16(bg_scan_in->high_period);
+ tlv_ees_cfg->high_period_count =
+ wlan_cpu_to_le16(bg_scan_in->high_period_count);
+ tlv_ees_cfg->mid_period =
+ wlan_cpu_to_le16(bg_scan_in->mid_period);
+ tlv_ees_cfg->mid_period_count =
+ wlan_cpu_to_le16(bg_scan_in->mid_period_count);
+ tlv_ees_cfg->low_period =
+ wlan_cpu_to_le16(bg_scan_in->low_period);
+ tlv_ees_cfg->low_period_count =
+ wlan_cpu_to_le16(bg_scan_in->low_period_count);
+ tlv += sizeof(MrvlIEtypes_EESParamSet_t);
+ cmd_size += sizeof(MrvlIEtypes_EESParamSet_t);
+
+ if (bg_scan_in->network_count) {
+ /* Fill EES network configuration */
+ tlv_ees_net_cfg = (MrvlIEtype_EESNetworkCfg_t *)tlv;
+ tlv_ees_net_cfg->header.type =
+ wlan_cpu_to_le16(TLV_TYPE_EES_NET_CFG);
+ tlv_ees_net_cfg->header.len = wlan_cpu_to_le16(
+ sizeof(MrvlIEtype_EESNetworkCfg_t) -
+ sizeof(MrvlIEtypesHeader_t));
+ tlv_ees_net_cfg->network_count =
+ bg_scan_in->network_count;
+ tlv_ees_net_cfg->max_conn_count =
+ bg_scan_in->max_conn_count;
+ tlv_ees_net_cfg->black_list_exp =
+ bg_scan_in->black_list_exp;
+ tlv += sizeof(MrvlIEtype_EESNetworkCfg_t);
+ cmd_size += sizeof(MrvlIEtype_EESNetworkCfg_t);
+ for (index = 0; index < bg_scan_in->network_count;
+ index++) {
+ if (wlan_strlen((char *)bg_scan_in
+ ->ees_ssid_cfg[index]
+ .ssid)) {
+ /* Fill SSID settings */
+ tlv_ssid =
+ (MrvlIEtypes_SsIdParamSet_t *)
+ tlv;
+ tlv_ssid->header.type =
+ wlan_cpu_to_le16(TLV_TYPE_SSID);
+ tlv_ssid->header.len = wlan_cpu_to_le16(
+ (t_u16)bg_scan_in
+ ->ees_ssid_cfg[index]
+ .max_len);
+ memcpy_ext(
+ pmadapter, tlv_ssid->ssid,
+ bg_scan_in->ees_ssid_cfg[index]
+ .ssid,
+ bg_scan_in->ees_ssid_cfg[index]
+ .max_len,
+ MLAN_MAX_SSID_LENGTH);
+ tlv += sizeof(MrvlIEtypesHeader_t) +
+ tlv_ssid->header.len;
+ cmd_size +=
+ sizeof(MrvlIEtypesHeader_t) +
+ tlv_ssid->header.len;
+ } else {
+ /* Fill Wildcard SSID settings */
+ pwildcard_ssid_tlv =
+ (MrvlIEtypes_WildCardSsIdParamSet_t
+ *)tlv;
+ pwildcard_ssid_tlv->header.type =
+ wlan_cpu_to_le16(
+ TLV_TYPE_WILDCARDSSID);
+ pwildcard_ssid_tlv->header
+ .len = wlan_cpu_to_le16(
+ sizeof(MrvlIEtypes_WildCardSsIdParamSet_t) -
+ sizeof(MrvlIEtypesHeader_t));
+ pwildcard_ssid_tlv->max_ssid_length =
+ MLAN_MAX_SSID_LENGTH;
+ tlv += sizeof(MrvlIEtypesHeader_t) +
+ sizeof(pwildcard_ssid_tlv
+ ->max_ssid_length);
+ cmd_size +=
+ sizeof(MrvlIEtypesHeader_t) +
+ sizeof(pwildcard_ssid_tlv
+ ->max_ssid_length);
+ }
+ /* Fill Cipher settings */
+ tlv_ees_cipher = (MrvlIEtypes_Cipher_t *)tlv;
+ tlv_ees_cipher->header.type =
+ wlan_cpu_to_le16(TLV_TYPE_CIPHER);
+ tlv_ees_cipher->header.len = wlan_cpu_to_le16(
+ sizeof(MrvlIEtypes_Cipher_t) -
+ sizeof(MrvlIEtypesHeader_t));
+ tlv_ees_cipher->pair_cipher =
+ bg_scan_in->ees_ssid_cfg[index]
+ .pair_cipher;
+ tlv_ees_cipher->group_cipher =
+ bg_scan_in->ees_ssid_cfg[index]
+ .group_cipher;
+ tlv += sizeof(MrvlIEtypes_Cipher_t);
+ cmd_size += sizeof(MrvlIEtypes_Cipher_t);
+ }
+ }
+ }
+
+ if (memcmp(pmadapter, bg_scan_in->random_mac, zero_mac,
+ MLAN_MAC_ADDR_LENGTH)) {
+ MrvlIEtypes_MacAddr_t *randomMacParam =
+ (MrvlIEtypes_MacAddr_t *)tlv;
+ memset(pmadapter, randomMacParam, 0,
+ sizeof(MrvlIEtypes_MacAddr_t));
+ randomMacParam->header.type =
+ wlan_cpu_to_le16(TLV_TYPE_RANDOM_MAC);
+ randomMacParam->header.len =
+ wlan_cpu_to_le16(MLAN_MAC_ADDR_LENGTH);
+ memcpy_ext(pmadapter, randomMacParam->mac,
+ bg_scan_in->random_mac, MLAN_MAC_ADDR_LENGTH,
+ MLAN_MAC_ADDR_LENGTH);
+ tlv += sizeof(MrvlIEtypes_MacAddr_t);
+ cmd_size += sizeof(MrvlIEtypes_MacAddr_t);
+ }
+done:
+ pcmd->size = wlan_cpu_to_le16(cmd_size);
+ LEAVE();
+ return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ * @brief This function handles the command response of extended scan
+ *
+ * @param pmpriv A pointer to mlan_private structure
+ * @param resp A pointer to HostCmd_DS_COMMAND
+ * @param pioctl_buf A pointer to mlan_ioctl_req structure
+ *
+ * @return MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ */
+mlan_status wlan_ret_bgscan_config(mlan_private *pmpriv,
+ HostCmd_DS_COMMAND *resp,
+ mlan_ioctl_req *pioctl_buf)
+{
+ mlan_ds_scan *pscan = MNULL;
+ HostCmd_DS_802_11_BG_SCAN_CONFIG *bg_scan =
+ &resp->params.bg_scan_config;
+ wlan_bgscan_cfg *bg_scan_out = MNULL;
+
+ ENTER();
+ if (pioctl_buf) {
+ pscan = (mlan_ds_scan *)pioctl_buf->pbuf;
+ bg_scan_out =
+ (wlan_bgscan_cfg *)pscan->param.user_scan.scan_cfg_buf;
+ bg_scan_out->action = wlan_le16_to_cpu(bg_scan->action);
+ if ((bg_scan_out->action == BG_SCAN_ACT_GET) ||
+ (bg_scan_out->action == BG_SCAN_ACT_GET_PPS_UAPSD)) {
+ bg_scan_out->enable = bg_scan->enable;
+ bg_scan_out->bss_type = bg_scan->bss_type;
+ bg_scan_out->chan_per_scan = bg_scan->chan_per_scan;
+ bg_scan_out->scan_interval =
+ wlan_le32_to_cpu(bg_scan->scan_interval);
+ bg_scan_out->report_condition =
+ wlan_le32_to_cpu(bg_scan->report_condition);
+ pioctl_buf->data_read_written =
+ sizeof(mlan_ds_scan) + MLAN_SUB_COMMAND_SIZE;
+ }
+ }
+ LEAVE();
+ return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ * @brief This function handles the command response of bgscan_query
+ * @param pmpriv A pointer to mlan_private structure
+ * @param resp A pointer to HostCmd_DS_COMMAND
+ * @param pioctl_buf A pointer to mlan_ioctl_req structure
+ *
+ * @return MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ */
+mlan_status wlan_ret_802_11_bgscan_query(mlan_private *pmpriv,
+ HostCmd_DS_COMMAND *resp,
+ mlan_ioctl_req *pioctl_buf)
+{
+ mlan_ds_scan *pscan = MNULL;
+ mlan_adapter *pmadapter = pmpriv->adapter;
+ ENTER();
+ wlan_ret_802_11_scan(pmpriv, resp, MNULL);
+ if (pioctl_buf) {
+ pscan = (mlan_ds_scan *)pioctl_buf->pbuf;
+ pscan->param.scan_resp.pscan_table =
+ (t_u8 *)pmadapter->pscan_table;
+ pscan->param.scan_resp.num_in_scan_table =
+ pmadapter->num_in_scan_table;
+ pscan->param.scan_resp.age_in_secs = pmadapter->age_in_secs;
+ pscan->param.scan_resp.pchan_stats =
+ (t_u8 *)pmadapter->pchan_stats;
+ pscan->param.scan_resp.num_in_chan_stats =
+ pmadapter->num_in_chan_stats;
+
+ pioctl_buf->data_read_written =
+ sizeof(mlan_scan_resp) + MLAN_SUB_COMMAND_SIZE;
+ }
+ LEAVE();
+ return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ * @brief This function finds ssid in ssid list.
+ *
+ * @param pmpriv A pointer to mlan_private structure
+ * @param ssid SSID to find in the list
+ * @param bssid BSSID to qualify the SSID selection (if provided)
+ * @param mode Network mode: Infrastructure or IBSS
+ *
+ * @return index in BSSID list or < 0 if error
+ */
+t_s32 wlan_find_ssid_in_list(mlan_private *pmpriv, mlan_802_11_ssid *ssid,
+ t_u8 *bssid, t_u32 mode)
+{
+ mlan_adapter *pmadapter = pmpriv->adapter;
+ t_s32 net = -1, j;
+ t_u8 best_rssi = 0;
+ t_u32 i;
+
+ ENTER();
+ PRINTM(MINFO, "Num of entries in scan table = %d\n",
+ pmadapter->num_in_scan_table);
+
+ /*
+ * Loop through the table until the maximum is reached or until a match
+ * is found based on the bssid field comparison
+ */
+ for (i = 0;
+ i < pmadapter->num_in_scan_table && (!bssid || (bssid && net < 0));
+ i++) {
+ if (!wlan_ssid_cmp(pmadapter, &pmadapter->pscan_table[i].ssid,
+ ssid) &&
+ (!bssid ||
+ !memcmp(pmadapter, pmadapter->pscan_table[i].mac_address,
+ bssid, MLAN_MAC_ADDR_LENGTH))) {
+ if ((mode == MLAN_BSS_MODE_INFRA) &&
+ !wlan_is_band_compatible(
+ pmpriv->config_bands,
+ pmadapter->pscan_table[i].bss_band))
+ continue;
+
+ switch (mode) {
+ case MLAN_BSS_MODE_INFRA:
+ case MLAN_BSS_MODE_IBSS:
+ j = wlan_is_network_compatible(pmpriv, i, mode);
+
+ if (j >= 0) {
+ if (SCAN_RSSI(pmadapter->pscan_table[i]
+ .rssi) >
+ best_rssi) {
+ best_rssi = SCAN_RSSI(
+ pmadapter
+ ->pscan_table[i]
+ .rssi);
+ net = i;
+ }
+ } else {
+ if (net == -1)
+ net = j;
+ }
+ break;
+ case MLAN_BSS_MODE_AUTO:
+ default:
+ /*
+ * Do not check compatibility if the mode
+ * requested is Auto/Unknown. Allows generic
+ * find to work without verifying against the
+ * Adapter security settings
+ */
+ if (SCAN_RSSI(pmadapter->pscan_table[i].rssi) >
+ best_rssi) {
+ best_rssi = SCAN_RSSI(
+ pmadapter->pscan_table[i].rssi);
+ net = i;
+ }
+ break;
+ }
+ }
+ }
+
+ LEAVE();
+ return net;
+}
+
+/**
+ * @brief This function finds a specific compatible BSSID in the scan list
+ *
+ * @param pmpriv A pointer to mlan_private structure
+ * @param bssid BSSID to find in the scan list
+ * @param mode Network mode: Infrastructure or IBSS
+ *
+ * @return index in BSSID list or < 0 if error
+ */
+t_s32 wlan_find_bssid_in_list(mlan_private *pmpriv, t_u8 *bssid, t_u32 mode)
+{
+ mlan_adapter *pmadapter = pmpriv->adapter;
+ t_s32 net = -1;
+ t_u32 i;
+
+ ENTER();
+
+ if (!bssid) {
+ LEAVE();
+ return -1;
+ }
+
+ PRINTM(MINFO, "FindBSSID: Num of BSSIDs = %d\n",
+ pmadapter->num_in_scan_table);
+
+ /*
+ * Look through the scan table for a compatible match. The ret return
+ * variable will be equal to the index in the scan table (greater
+ * than zero) if the network is compatible. The loop will continue
+ * past a matched bssid that is not compatible in case there is an
+ * AP with multiple SSIDs assigned to the same BSSID
+ */
+ for (i = 0; net < 0 && i < pmadapter->num_in_scan_table; i++) {
+ if (!memcmp(pmadapter, pmadapter->pscan_table[i].mac_address,
+ bssid, MLAN_MAC_ADDR_LENGTH)) {
+ if ((mode == MLAN_BSS_MODE_INFRA) &&
+ !wlan_is_band_compatible(
+ pmpriv->config_bands,
+ pmadapter->pscan_table[i].bss_band))
+ continue;
+ switch (mode) {
+ case MLAN_BSS_MODE_INFRA:
+ case MLAN_BSS_MODE_IBSS:
+ net = wlan_is_network_compatible(pmpriv, i,
+ mode);
+ break;
+ default:
+ net = i;
+ break;
+ }
+ }
+ }
+
+ LEAVE();
+ return net;
+}
+
+/**
+ * @brief Compare two SSIDs
+ *
+ * @param pmadapter A pointer to mlan_adapter structure
+ * @param ssid1 A pointer to ssid to compare
+ * @param ssid2 A pointer to ssid to compare
+ *
+ * @return 0--ssid is same, otherwise is different
+ */
+t_s32 wlan_ssid_cmp(pmlan_adapter pmadapter, mlan_802_11_ssid *ssid1,
+ mlan_802_11_ssid *ssid2)
+{
+ ENTER();
+
+ if (!ssid1 || !ssid2) {
+ LEAVE();
+ return -1;
+ }
+
+ if (ssid1->ssid_len != ssid2->ssid_len) {
+ LEAVE();
+ return -1;
+ }
+
+ LEAVE();
+ return memcmp(pmadapter, ssid1->ssid, ssid2->ssid, ssid1->ssid_len);
+}
+
+/**
+ * @brief Find the AP with specific ssid in the scan list
+ *
+ * @param pmpriv A pointer to mlan_private structure
+ * @param preq_ssid_bssid A pointer to AP's ssid returned
+ *
+ * @return MLAN_STATUS_SUCCESS--success, otherwise--fail
+ */
+mlan_status wlan_find_best_network(mlan_private *pmpriv,
+ mlan_ssid_bssid *preq_ssid_bssid)
+{
+ mlan_adapter *pmadapter = pmpriv->adapter;
+ mlan_status ret = MLAN_STATUS_SUCCESS;
+ BSSDescriptor_t *preq_bss;
+ t_s32 i;
+
+ ENTER();
+
+ memset(pmadapter, preq_ssid_bssid, 0, sizeof(mlan_ssid_bssid));
+
+ i = wlan_find_best_network_in_list(pmpriv);
+
+ if (i >= 0) {
+ preq_bss = &pmadapter->pscan_table[i];
+ memcpy_ext(pmadapter, &preq_ssid_bssid->ssid, &preq_bss->ssid,
+ sizeof(mlan_802_11_ssid),
+ sizeof(preq_ssid_bssid->ssid));
+ memcpy_ext(pmadapter, (t_u8 *)&preq_ssid_bssid->bssid,
+ (t_u8 *)&preq_bss->mac_address, MLAN_MAC_ADDR_LENGTH,
+ MLAN_MAC_ADDR_LENGTH);
+
+ /* Make sure we are in the right mode */
+ if (pmpriv->bss_mode == MLAN_BSS_MODE_AUTO)
+ pmpriv->bss_mode = preq_bss->bss_mode;
+ preq_ssid_bssid->channel = (t_u16)preq_bss->channel;
+ if (preq_bss->pmd_ie &&
+ wlan_ft_akm_is_used(pmpriv, (t_u8 *)preq_bss->prsn_ie)) {
+ preq_ssid_bssid->ft_md = preq_bss->pmd_ie->mdid;
+ preq_ssid_bssid->ft_cap = preq_bss->pmd_ie->ft_cap;
+ }
+ preq_ssid_bssid->bss_band = preq_bss->bss_band;
+ preq_ssid_bssid->idx = i + 1;
+ }
+
+ if (!preq_ssid_bssid->ssid.ssid_len) {
+ ret = MLAN_STATUS_FAILURE;
+ goto done;
+ }
+
+ PRINTM(MINFO,
+ "Best network found = [%s], "
+ "[" MACSTR "]\n",
+ preq_ssid_bssid->ssid.ssid, MAC2STR(preq_ssid_bssid->bssid));
+
+done:
+ LEAVE();
+ return ret;
+}
+
+/**
+ * @brief Send a scan command for all available channels filtered on a spec
+ *
+ * @param pmpriv A pointer to mlan_private structure
+ * @param pioctl_buf A pointer to MLAN IOCTL Request buffer
+ * @param preq_ssid A pointer to AP's ssid returned
+ *
+ * @return MLAN_STATUS_SUCCESS--success, otherwise--fail
+ */
+mlan_status wlan_scan_specific_ssid(mlan_private *pmpriv, t_void *pioctl_buf,
+ mlan_802_11_ssid *preq_ssid)
+{
+ mlan_status ret = MLAN_STATUS_SUCCESS;
+ mlan_callbacks *pcb = (mlan_callbacks *)&pmpriv->adapter->callbacks;
+ wlan_user_scan_cfg *pscan_cfg;
+ pmlan_ioctl_req pioctl_req = (mlan_ioctl_req *)pioctl_buf;
+
+ ENTER();
+
+ if (!preq_ssid) {
+ if (pioctl_req)
+ pioctl_req->status_code = MLAN_ERROR_CMD_SCAN_FAIL;
+ ret = MLAN_STATUS_FAILURE;
+ goto done;
+ }
+ wlan_scan_delete_ssid_table_entry(pmpriv, preq_ssid);
+
+ ret = pcb->moal_malloc(pmpriv->adapter->pmoal_handle,
+ sizeof(wlan_user_scan_cfg), MLAN_MEM_DEF,
+ (t_u8 **)&pscan_cfg);
+
+ if (ret != MLAN_STATUS_SUCCESS || !pscan_cfg) {
+ PRINTM(MERROR, "Memory allocation for pscan_cfg failed!\n");
+ if (pioctl_req)
+ pioctl_req->status_code = MLAN_ERROR_NO_MEM;
+ ret = MLAN_STATUS_FAILURE;
+ goto done;
+ }
+
+ memset(pmpriv->adapter, pscan_cfg, 0x00, sizeof(wlan_user_scan_cfg));
+
+ memcpy_ext(pmpriv->adapter, pscan_cfg->ssid_list[0].ssid,
+ preq_ssid->ssid, preq_ssid->ssid_len, MLAN_MAX_SSID_LENGTH);
+ pscan_cfg->keep_previous_scan = MFALSE;
+
+ ret = wlan_scan_networks(pmpriv, pioctl_buf, pscan_cfg);
+
+ if (pscan_cfg)
+ pcb->moal_mfree(pmpriv->adapter->pmoal_handle,
+ (t_u8 *)pscan_cfg);
+
+done:
+ LEAVE();
+ return ret;
+}
+
+/**
+ * @brief Save a beacon buffer of the current bss descriptor
+ * Save the current beacon buffer to restore in the following cases that
+ * makes the bcn_buf 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.
+ *
+ * @param pmpriv A pointer to mlan_private structure
+ *
+ * @return N/A
+ */
+t_void wlan_save_curr_bcn(mlan_private *pmpriv)
+{
+ mlan_adapter *pmadapter = pmpriv->adapter;
+ mlan_callbacks *pcb = (pmlan_callbacks)&pmadapter->callbacks;
+ BSSDescriptor_t *pcurr_bss = &pmpriv->curr_bss_params.bss_descriptor;
+ mlan_status ret = MLAN_STATUS_SUCCESS;
+
+ ENTER();
+ pcb->moal_spin_lock(pmadapter->pmoal_handle, pmpriv->curr_bcn_buf_lock);
+ /* save the beacon buffer if it is not saved or updated */
+ if ((pmpriv->pcurr_bcn_buf == MNULL) ||
+ (pmpriv->curr_bcn_size != pcurr_bss->beacon_buf_size) ||
+ (memcmp(pmpriv->adapter, pmpriv->pcurr_bcn_buf,
+ pcurr_bss->pbeacon_buf, pcurr_bss->beacon_buf_size))) {
+ if (pmpriv->pcurr_bcn_buf) {
+ pcb->moal_mfree(pmadapter->pmoal_handle,
+ pmpriv->pcurr_bcn_buf);
+ pmpriv->pcurr_bcn_buf = MNULL;
+ }
+ pmpriv->curr_bcn_size = pcurr_bss->beacon_buf_size;
+
+ if (pmpriv->curr_bcn_size) {
+ ret = pcb->moal_malloc(pmadapter->pmoal_handle,
+ pcurr_bss->beacon_buf_size,
+ MLAN_MEM_DEF,
+ &pmpriv->pcurr_bcn_buf);
+
+ if ((ret == MLAN_STATUS_SUCCESS) &&
+ pmpriv->pcurr_bcn_buf) {
+ memcpy_ext(pmpriv->adapter,
+ pmpriv->pcurr_bcn_buf,
+ pcurr_bss->pbeacon_buf,
+ pcurr_bss->beacon_buf_size,
+ pcurr_bss->beacon_buf_size);
+ PRINTM(MINFO, "current beacon saved %d\n",
+ pmpriv->curr_bcn_size);
+ } else {
+ PRINTM(MERROR,
+ "Fail to allocate curr_bcn_buf\n");
+ }
+ }
+ }
+ wlan_update_curr_bcn(pmpriv);
+ pcb->moal_spin_unlock(pmadapter->pmoal_handle,
+ pmpriv->curr_bcn_buf_lock);
+
+ LEAVE();
+}
+
+/**
+ * @brief Free a beacon buffer of the current bss descriptor
+ *
+ * @param pmpriv A pointer to mlan_private structure
+ *
+ * @return N/A
+ */
+t_void wlan_free_curr_bcn(mlan_private *pmpriv)
+{
+ mlan_adapter *pmadapter = pmpriv->adapter;
+ mlan_callbacks *pcb = (pmlan_callbacks)&pmadapter->callbacks;
+
+ ENTER();
+ if (pmpriv->pcurr_bcn_buf) {
+ pcb->moal_mfree(pmadapter->pmoal_handle, pmpriv->pcurr_bcn_buf);
+ pmpriv->pcurr_bcn_buf = MNULL;
+ }
+ LEAVE();
+}
diff --git a/drivers/net/wireless/nxp/mxm_wifiex/wlan_src/mlan/mlan_sdio.c b/drivers/net/wireless/nxp/mxm_wifiex/wlan_src/mlan/mlan_sdio.c
new file mode 100644
index 000000000000..b88c4fdb3ad8
--- /dev/null
+++ b/drivers/net/wireless/nxp/mxm_wifiex/wlan_src/mlan/mlan_sdio.c
@@ -0,0 +1,3013 @@
+/** @file mlan_sdio.c
+ *
+ * @brief This file contains SDIO specific code
+ *
+ *
+ * Copyright 2014-2020 NXP
+ *
+ * This software file (the File) is distributed by NXP
+ * under the terms of the GNU General Public License Version 2, June 1991
+ * (the License). You may use, redistribute and/or modify the 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.
+ *
+ */
+
+/********************************************************
+Change log:
+ 10/27/2008: initial version
+********************************************************/
+
+#include "mlan.h"
+#ifdef STA_SUPPORT
+#include "mlan_join.h"
+#endif
+#include "mlan_util.h"
+#include "mlan_fw.h"
+#include "mlan_main.h"
+#include "mlan_init.h"
+#include "mlan_wmm.h"
+#include "mlan_11n.h"
+#include "mlan_sdio.h"
+
+/********************************************************
+ Local Variables
+********************************************************/
+
+/********************************************************
+ Global Variables
+********************************************************/
+
+/********************************************************
+ Local Functions
+********************************************************/
+
+/**
+ * @brief This function initialize the SDIO port
+ *
+ * @param pmadapter A pointer to mlan_adapter structure
+ * @return MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ */
+static mlan_status wlan_sdio_init_ioport(mlan_adapter *pmadapter)
+{
+ t_u32 reg;
+ pmlan_callbacks pcb = &pmadapter->callbacks;
+ t_u8 host_int_rsr_reg = pmadapter->pcard_sd->reg->host_int_rsr_reg;
+ t_u8 host_int_rsr_mask = pmadapter->pcard_sd->reg->sdio_int_mask;
+ t_u8 card_misc_cfg_reg = pmadapter->pcard_sd->reg->card_misc_cfg_reg;
+ t_u8 card_config_2_1_reg =
+ pmadapter->pcard_sd->reg->card_config_2_1_reg;
+ t_u8 cmd_config_0 = pmadapter->pcard_sd->reg->cmd_config_0;
+ t_u8 cmd_config_1 = pmadapter->pcard_sd->reg->cmd_config_1;
+
+ ENTER();
+
+ pmadapter->pcard_sd->ioport = MEM_PORT;
+ PRINTM(MINFO, "SDIO FUNC1 IO port: 0x%x\n",
+ pmadapter->pcard_sd->ioport);
+
+ /* enable sdio cmd53 new mode */
+ if (MLAN_STATUS_SUCCESS == pcb->moal_read_reg(pmadapter->pmoal_handle,
+ card_config_2_1_reg,
+ &reg)) {
+ pcb->moal_write_reg(pmadapter->pmoal_handle,
+ card_config_2_1_reg, reg | CMD53_NEW_MODE);
+ } else {
+ LEAVE();
+ return MLAN_STATUS_FAILURE;
+ }
+
+ /* configure cmd port */
+ /* enable reading rx length from the register */
+ if (MLAN_STATUS_SUCCESS ==
+ pcb->moal_read_reg(pmadapter->pmoal_handle, cmd_config_0, &reg)) {
+ pcb->moal_write_reg(pmadapter->pmoal_handle, cmd_config_0,
+ reg | CMD_PORT_RD_LEN_EN);
+ } else {
+ LEAVE();
+ return MLAN_STATUS_FAILURE;
+ }
+ /* enable Dnld/Upld ready auto reset for cmd port
+ * after cmd53 is completed */
+ if (MLAN_STATUS_SUCCESS ==
+ pcb->moal_read_reg(pmadapter->pmoal_handle, cmd_config_1, &reg)) {
+ pcb->moal_write_reg(pmadapter->pmoal_handle, cmd_config_1,
+ reg | CMD_PORT_AUTO_EN);
+ } else {
+ LEAVE();
+ return MLAN_STATUS_FAILURE;
+ }
+
+#if defined(SD8977) || defined(SD8978)
+ if (IS_SD8977(pmadapter->card_type) ||
+ IS_SD8978(pmadapter->card_type)) {
+ if ((pmadapter->init_para.int_mode == INT_MODE_GPIO) &&
+ (pmadapter->init_para.gpio_pin == GPIO_INT_NEW_MODE)) {
+ PRINTM(MMSG, "Enable GPIO-1 int mode\n");
+ pcb->moal_write_reg(pmadapter->pmoal_handle,
+ SCRATCH_REG_32,
+ ENABLE_GPIO_1_INT_MODE);
+ }
+ }
+#endif
+ /* Set Host interrupt reset to read to clear */
+ if (MLAN_STATUS_SUCCESS == pcb->moal_read_reg(pmadapter->pmoal_handle,
+ host_int_rsr_reg, &reg)) {
+ pcb->moal_write_reg(pmadapter->pmoal_handle, host_int_rsr_reg,
+ reg | host_int_rsr_mask);
+ } else {
+ LEAVE();
+ return MLAN_STATUS_FAILURE;
+ }
+
+ /* Dnld/Upld ready set to auto reset */
+ if (MLAN_STATUS_SUCCESS == pcb->moal_read_reg(pmadapter->pmoal_handle,
+ card_misc_cfg_reg,
+ &reg)) {
+ pcb->moal_write_reg(pmadapter->pmoal_handle, card_misc_cfg_reg,
+ reg | AUTO_RE_ENABLE_INT);
+ } else {
+ LEAVE();
+ return MLAN_STATUS_FAILURE;
+ }
+ LEAVE();
+ return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ * @brief This function sends data to the card.
+ *
+ * @param pmadapter A pointer to mlan_adapter structure
+ * @param pmbuf A pointer to mlan_buffer (pmbuf->data_len should include
+ * SDIO header)
+ * @param port Port
+ * @return MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ */
+static mlan_status wlan_write_data_sync(mlan_adapter *pmadapter,
+ mlan_buffer *pmbuf, t_u32 port)
+{
+ t_u32 i = 0;
+ pmlan_callbacks pcb = &pmadapter->callbacks;
+ mlan_status ret = MLAN_STATUS_SUCCESS;
+
+ ENTER();
+
+ do {
+ ret = pcb->moal_write_data_sync(pmadapter->pmoal_handle, pmbuf,
+ port, 0);
+ if (ret != MLAN_STATUS_SUCCESS) {
+ i++;
+ PRINTM(MERROR,
+ "host_to_card, write iomem (%d) failed: %d\n", i,
+ ret);
+ if (MLAN_STATUS_SUCCESS !=
+ pcb->moal_write_reg(pmadapter->pmoal_handle,
+ HOST_TO_CARD_EVENT_REG,
+ HOST_TERM_CMD53)) {
+ PRINTM(MERROR, "write CFG reg failed\n");
+ }
+ ret = MLAN_STATUS_FAILURE;
+ if (i > MAX_WRITE_IOMEM_RETRY) {
+ pmbuf->status_code = MLAN_ERROR_DATA_TX_FAIL;
+ goto exit;
+ }
+ }
+ } while (ret == MLAN_STATUS_FAILURE);
+exit:
+ LEAVE();
+ return ret;
+}
+
+/**
+ * @brief This function gets available SDIO port for reading cmd/data
+ *
+ * @param pmadapter A pointer to mlan_adapter structure
+ * @param pport A pointer to port number
+ * @return MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ */
+static mlan_status wlan_get_rd_port(mlan_adapter *pmadapter, t_u8 *pport)
+{
+ t_u32 rd_bitmap = pmadapter->pcard_sd->mp_rd_bitmap;
+ const mlan_sdio_card_reg *reg = pmadapter->pcard_sd->reg;
+ t_u8 max_ports = MAX_PORT;
+
+ ENTER();
+
+ PRINTM(MIF_D, "wlan_get_rd_port: mp_rd_bitmap=0x%08x\n", rd_bitmap);
+
+ if (!(rd_bitmap & reg->data_port_mask)) {
+ LEAVE();
+ return MLAN_STATUS_FAILURE;
+ }
+
+ if (pmadapter->pcard_sd->mp_rd_bitmap &
+ (1 << pmadapter->pcard_sd->curr_rd_port)) {
+ pmadapter->pcard_sd->mp_rd_bitmap &=
+ (t_u32)(~(1 << pmadapter->pcard_sd->curr_rd_port));
+ *pport = pmadapter->pcard_sd->curr_rd_port;
+
+ /* hw rx wraps round only after port (MAX_PORT-1) */
+ if (++pmadapter->pcard_sd->curr_rd_port == max_ports)
+ pmadapter->pcard_sd->curr_rd_port = reg->start_rd_port;
+ } else {
+ LEAVE();
+ return MLAN_STATUS_FAILURE;
+ }
+
+ PRINTM(MIF_D, "port=%d mp_rd_bitmap=0x%08x -> 0x%08x\n", *pport,
+ rd_bitmap, pmadapter->pcard_sd->mp_rd_bitmap);
+
+ LEAVE();
+ return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ * @brief This function gets available SDIO port for writing data
+ *
+ * @param pmadapter A pointer to mlan_adapter structure
+ * @param pport A pointer to port number
+ * @return MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ */
+static mlan_status wlan_get_wr_port_data(mlan_adapter *pmadapter, t_u8 *pport)
+{
+ t_u32 wr_bitmap = pmadapter->pcard_sd->mp_wr_bitmap;
+ const mlan_sdio_card_reg *reg = pmadapter->pcard_sd->reg;
+
+ ENTER();
+
+ PRINTM(MIF_D, "wlan_get_wr_port_data: mp_wr_bitmap=0x%08x\n",
+ wr_bitmap);
+
+ if (!(wr_bitmap & pmadapter->pcard_sd->mp_data_port_mask)) {
+ pmadapter->data_sent = MTRUE;
+ LEAVE();
+ return MLAN_STATUS_RESOURCE;
+ }
+
+ if (pmadapter->pcard_sd->mp_wr_bitmap &
+ (1 << pmadapter->pcard_sd->curr_wr_port)) {
+ pmadapter->pcard_sd->mp_wr_bitmap &=
+ (t_u32)(~(1 << pmadapter->pcard_sd->curr_wr_port));
+ *pport = pmadapter->pcard_sd->curr_wr_port;
+ if (++pmadapter->pcard_sd->curr_wr_port ==
+ pmadapter->pcard_sd->mp_end_port)
+ pmadapter->pcard_sd->curr_wr_port = reg->start_wr_port;
+ } else {
+ pmadapter->data_sent = MTRUE;
+ LEAVE();
+ return MLAN_STATUS_RESOURCE;
+ }
+
+ PRINTM(MIF_D, "port=%d mp_wr_bitmap=0x%08x -> 0x%08x\n", *pport,
+ wr_bitmap, pmadapter->pcard_sd->mp_wr_bitmap);
+ LEAVE();
+ return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ * @brief This function polls the card status register.
+ *
+ * @param pmadapter A pointer to mlan_adapter structure
+ * @param bits the bit mask
+ * @return MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ */
+static mlan_status wlan_sdio_poll_card_status(mlan_adapter *pmadapter,
+ t_u8 bits)
+{
+ pmlan_callbacks pcb = &pmadapter->callbacks;
+ t_u32 tries;
+ t_u32 cs = 0;
+
+ ENTER();
+
+ for (tries = 0; tries < MAX_POLL_TRIES; tries++) {
+ if (pcb->moal_read_reg(pmadapter->pmoal_handle,
+ pmadapter->pcard_sd->reg->poll_reg,
+ &cs) != MLAN_STATUS_SUCCESS)
+ break;
+ else if ((cs & bits) == bits) {
+ LEAVE();
+ return MLAN_STATUS_SUCCESS;
+ }
+ wlan_udelay(pmadapter, 10);
+ }
+
+ PRINTM(MERROR,
+ "wlan_sdio_poll_card_status failed, tries = %d, cs = 0x%x\n",
+ tries, cs);
+ LEAVE();
+ return MLAN_STATUS_FAILURE;
+}
+
+/**
+ * @brief This function reads firmware status registers
+ *
+ * @param pmadapter A pointer to mlan_adapter structure
+ * @param dat A pointer to keep returned data
+ * @return MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ */
+static mlan_status wlan_sdio_read_fw_status(mlan_adapter *pmadapter, t_u16 *dat)
+{
+ pmlan_callbacks pcb = &pmadapter->callbacks;
+ t_u32 fws0 = 0, fws1 = 0;
+
+ ENTER();
+ if (MLAN_STATUS_SUCCESS !=
+ pcb->moal_read_reg(pmadapter->pmoal_handle,
+ pmadapter->pcard_sd->reg->status_reg_0, &fws0)) {
+ LEAVE();
+ return MLAN_STATUS_FAILURE;
+ }
+
+ if (MLAN_STATUS_SUCCESS !=
+ pcb->moal_read_reg(pmadapter->pmoal_handle,
+ pmadapter->pcard_sd->reg->status_reg_1, &fws1)) {
+ LEAVE();
+ return MLAN_STATUS_FAILURE;
+ }
+
+ *dat = (t_u16)((fws1 << 8) | fws0);
+ LEAVE();
+ return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ * @brief This function reads firmware dnld offset registers
+ *
+ * @param pmadapter A pointer to mlan_adapter structure
+ * @param dat A pointer to keep returned data
+ * @return MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ */
+static mlan_status wlan_sdio_read_fw_dnld_offset(mlan_adapter *pmadapter,
+ t_u32 *dat)
+{
+ pmlan_callbacks pcb = &pmadapter->callbacks;
+ const mlan_sdio_card_reg *reg = pmadapter->pcard_sd->reg;
+ mlan_status ret = MLAN_STATUS_SUCCESS;
+ t_u32 fw_dnld_offset_0 = 0;
+ t_u32 fw_dnld_offset_1 = 0;
+ t_u32 fw_dnld_offset_2 = 0;
+ t_u32 fw_dnld_offset_3 = 0;
+
+ ENTER();
+
+ ret = pcb->moal_read_reg(pmadapter->pmoal_handle,
+ reg->fw_dnld_offset_0_reg, &fw_dnld_offset_0);
+ if (ret != MLAN_STATUS_SUCCESS) {
+ PRINTM(MERROR,
+ "Dev fw_dnld_offset_0 reg read failed: reg(0x%04X)=0x%x. Terminating download\n",
+ reg->fw_dnld_offset_0_reg, fw_dnld_offset_0);
+ ret = MLAN_STATUS_FAILURE;
+ goto done;
+ }
+ ret = pcb->moal_read_reg(pmadapter->pmoal_handle,
+ reg->fw_dnld_offset_1_reg, &fw_dnld_offset_1);
+ if (ret != MLAN_STATUS_SUCCESS) {
+ PRINTM(MERROR,
+ "Dev fw_dnld_offset_1 reg read failed: reg(0x%04X)=0x%x. Terminating download\n",
+ reg->fw_dnld_offset_1_reg, fw_dnld_offset_1);
+ ret = MLAN_STATUS_FAILURE;
+ goto done;
+ }
+ ret = pcb->moal_read_reg(pmadapter->pmoal_handle,
+ reg->fw_dnld_offset_2_reg, &fw_dnld_offset_2);
+ if (ret != MLAN_STATUS_SUCCESS) {
+ PRINTM(MERROR,
+ "Dev fw_dnld_offset_2 reg read failed: reg(0x%04X)=0x%x. Terminating download\n",
+ reg->fw_dnld_offset_2_reg, fw_dnld_offset_2);
+ ret = MLAN_STATUS_FAILURE;
+ goto done;
+ }
+ ret = pcb->moal_read_reg(pmadapter->pmoal_handle,
+ reg->fw_dnld_offset_3_reg, &fw_dnld_offset_3);
+ if (ret != MLAN_STATUS_SUCCESS) {
+ PRINTM(MERROR,
+ "Dev fw_dnld_offset_3 reg read failed: reg(0x%04X)=0x%x. Terminating download\n",
+ reg->fw_dnld_offset_3_reg, fw_dnld_offset_3);
+ ret = MLAN_STATUS_FAILURE;
+ goto done;
+ }
+
+ *dat = (t_u32)(((fw_dnld_offset_3 & 0xff) << 24) |
+ ((fw_dnld_offset_2 & 0xff) << 16) |
+ ((fw_dnld_offset_1 & 0xff) << 8) |
+ (fw_dnld_offset_0 & 0xff));
+
+done:
+ LEAVE();
+ return ret;
+}
+
+/**
+ * @brief This function reads firmware dnld status registers
+ *
+ * @param pmadapter A pointer to mlan_adapter structure
+ * @param dat A pointer to keep returned data
+ * @return MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ */
+static mlan_status wlan_sdio_read_fw_dnld_status(mlan_adapter *pmadapter,
+ t_u16 *dat)
+{
+ pmlan_callbacks pcb = &pmadapter->callbacks;
+ const mlan_sdio_card_reg *reg = pmadapter->pcard_sd->reg;
+ mlan_status ret = MLAN_STATUS_SUCCESS;
+ t_u32 fw_dnld_status_0 = 0;
+ t_u32 fw_dnld_status_1 = 0;
+
+ ENTER();
+
+ ret = pcb->moal_read_reg(pmadapter->pmoal_handle,
+ reg->fw_dnld_status_0_reg, &fw_dnld_status_0);
+ if (ret != MLAN_STATUS_SUCCESS) {
+ PRINTM(MERROR,
+ "Dev fw_dnld_status_0 reg read failed: reg(0x%04X)=0x%x. Terminating download\n",
+ reg->fw_dnld_status_0_reg, fw_dnld_status_0);
+ ret = MLAN_STATUS_FAILURE;
+ goto done;
+ }
+ ret = pcb->moal_read_reg(pmadapter->pmoal_handle,
+ reg->fw_dnld_status_1_reg, &fw_dnld_status_1);
+ if (ret != MLAN_STATUS_SUCCESS) {
+ PRINTM(MERROR,
+ "Dev fw_dnld_status_1 reg read failed: reg(0x%04X)=0x%x. Terminating download\n",
+ reg->fw_dnld_status_1_reg, fw_dnld_status_1);
+ ret = MLAN_STATUS_FAILURE;
+ goto done;
+ }
+
+ *dat = (t_u16)(((fw_dnld_status_1 & 0xff) << 8) |
+ (fw_dnld_status_0 & 0xff));
+
+done:
+ LEAVE();
+ return ret;
+}
+
+/** @brief This function disables the host interrupts mask.
+ *
+ * @param pmadapter A pointer to mlan_adapter structure
+ * @param mask the interrupt mask
+ * @return MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ */
+static mlan_status wlan_sdio_disable_host_int_mask(pmlan_adapter pmadapter,
+ t_u8 mask)
+{
+ t_u32 host_int_mask = 0;
+ pmlan_callbacks pcb = &pmadapter->callbacks;
+
+ ENTER();
+
+ /* Read back the host_int_mask register */
+ if (MLAN_STATUS_SUCCESS !=
+ pcb->moal_read_reg(pmadapter->pmoal_handle,
+ pmadapter->pcard_sd->reg->host_int_mask_reg,
+ &host_int_mask)) {
+ LEAVE();
+ return MLAN_STATUS_FAILURE;
+ }
+
+ /* Update with the mask and write back to the register */
+ host_int_mask &= ~mask;
+
+ if (MLAN_STATUS_SUCCESS !=
+ pcb->moal_write_reg(pmadapter->pmoal_handle,
+ pmadapter->pcard_sd->reg->host_int_mask_reg,
+ host_int_mask)) {
+ PRINTM(MWARN, "Disable host interrupt failed\n");
+ LEAVE();
+ return MLAN_STATUS_FAILURE;
+ }
+
+ LEAVE();
+ return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ * @brief This function enables the host interrupts mask
+ *
+ * @param pmadapter A pointer to mlan_adapter structure
+ * @param mask the interrupt mask
+ * @return MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ */
+static mlan_status wlan_sdio_enable_host_int_mask(pmlan_adapter pmadapter,
+ t_u8 mask)
+{
+ pmlan_callbacks pcb = &pmadapter->callbacks;
+
+ ENTER();
+
+ /* Simply write the mask to the register */
+ if (MLAN_STATUS_SUCCESS !=
+ pcb->moal_write_reg(pmadapter->pmoal_handle,
+ pmadapter->pcard_sd->reg->host_int_mask_reg,
+ mask)) {
+ PRINTM(MWARN, "Enable host interrupt failed\n");
+ LEAVE();
+ return MLAN_STATUS_FAILURE;
+ }
+
+ LEAVE();
+ return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ * @brief This function reads data from the card.
+ *
+ * @param pmadapter A pointer to mlan_adapter structure
+ * @param type A pointer to keep type as data or command
+ * @param nb A pointer to keep the data/cmd length returned in buffer
+ * @param pmbuf A pointer to the SDIO data/cmd buffer
+ * @param npayload the length of data/cmd buffer
+ * @param ioport the SDIO ioport
+ * @return MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ */
+static mlan_status wlan_sdio_card_to_host(mlan_adapter *pmadapter, t_u32 *type,
+ t_u32 *nb, pmlan_buffer pmbuf,
+ t_u32 npayload, t_u32 ioport)
+{
+ mlan_status ret = MLAN_STATUS_SUCCESS;
+ pmlan_callbacks pcb = &pmadapter->callbacks;
+ t_u32 i = 0;
+
+ ENTER();
+
+ if (!pmbuf) {
+ PRINTM(MWARN, "pmbuf is NULL!\n");
+ ret = MLAN_STATUS_FAILURE;
+ goto exit;
+ }
+ do {
+ ret = pcb->moal_read_data_sync(pmadapter->pmoal_handle, pmbuf,
+ ioport, 0);
+
+ if (ret != MLAN_STATUS_SUCCESS) {
+ PRINTM(MERROR,
+ "wlan: cmd53 read failed: %d ioport=0x%x retry=%d\n",
+ ret, ioport, i);
+ i++;
+ if (MLAN_STATUS_SUCCESS !=
+ pcb->moal_write_reg(pmadapter->pmoal_handle,
+ HOST_TO_CARD_EVENT_REG,
+ HOST_TERM_CMD53)) {
+ PRINTM(MERROR, "Set Term cmd53 failed\n");
+ }
+ if (i > MAX_WRITE_IOMEM_RETRY) {
+ pmbuf->status_code = MLAN_ERROR_DATA_RX_FAIL;
+ ret = MLAN_STATUS_FAILURE;
+ goto exit;
+ }
+ }
+ } while (ret == MLAN_STATUS_FAILURE);
+ *nb = wlan_le16_to_cpu(*(t_u16 *)(pmbuf->pbuf + pmbuf->data_offset));
+ if (*nb > npayload) {
+ PRINTM(MERROR, "invalid packet, *nb=%d, npayload=%d\n", *nb,
+ npayload);
+ pmbuf->status_code = MLAN_ERROR_PKT_SIZE_INVALID;
+ ret = MLAN_STATUS_FAILURE;
+ goto exit;
+ }
+
+ DBG_HEXDUMP(MIF_D, "SDIO Blk Rd", pmbuf->pbuf + pmbuf->data_offset,
+ MIN(*nb, MAX_DATA_DUMP_LEN));
+
+ *type = wlan_le16_to_cpu(
+ *(t_u16 *)(pmbuf->pbuf + pmbuf->data_offset + 2));
+
+exit:
+ LEAVE();
+ return ret;
+}
+
+/**
+ * @brief This function downloads FW blocks to device
+ *
+ * @param pmadapter A pointer to mlan_adapter
+ * @param firmware A pointer to firmware image
+ * @param firmwarelen firmware len
+ *
+ * @return MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ */
+static mlan_status wlan_sdio_prog_fw_w_helper(pmlan_adapter pmadapter, t_u8 *fw,
+ t_u32 fw_len)
+{
+ mlan_status ret = MLAN_STATUS_SUCCESS;
+ pmlan_callbacks pcb = &pmadapter->callbacks;
+ t_u8 *firmware = fw;
+ t_u32 firmwarelen = fw_len;
+ t_u32 offset = 0;
+ t_u32 base0, base1;
+ t_void *tmpfwbuf = MNULL;
+ t_u32 tmpfwbufsz;
+ t_u8 *fwbuf;
+ mlan_buffer mbuf;
+ t_u16 len = 0;
+ t_u32 txlen = 0, tx_blocks = 0, tries = 0;
+ t_u32 i = 0;
+ const mlan_sdio_card_reg *reg = pmadapter->pcard_sd->reg;
+ t_u32 read_base_0_reg = reg->base_0_reg;
+ t_u32 read_base_1_reg = reg->base_1_reg;
+#if defined(SD9098)
+ t_u32 rev_id_reg = 0;
+ t_u32 revision_id = 0;
+#endif
+ t_u8 check_fw_status = MFALSE;
+ t_u16 fw_dnld_status = 0;
+ t_u32 fw_dnld_offset = 0;
+ t_u8 mic_retry = 0;
+
+ ENTER();
+
+ if (!firmware && !pcb->moal_get_fw_data) {
+ PRINTM(MMSG, "No firmware image found! Terminating download\n");
+ LEAVE();
+ return MLAN_STATUS_FAILURE;
+ }
+
+ PRINTM(MINFO, "WLAN: Downloading FW image (%d bytes)\n", firmwarelen);
+
+ tmpfwbufsz = ALIGN_SZ(WLAN_UPLD_SIZE, DMA_ALIGNMENT);
+ ret = pcb->moal_malloc(pmadapter->pmoal_handle, tmpfwbufsz,
+ MLAN_MEM_DEF | MLAN_MEM_DMA, (t_u8 **)&tmpfwbuf);
+ if ((ret != MLAN_STATUS_SUCCESS) || !tmpfwbuf) {
+ PRINTM(MERROR,
+ "Unable to allocate buffer for firmware. Terminating download\n");
+ ret = MLAN_STATUS_FAILURE;
+ goto done;
+ }
+ memset(pmadapter, tmpfwbuf, 0, tmpfwbufsz);
+ /* Ensure 8-byte aligned firmware buffer */
+ fwbuf = (t_u8 *)ALIGN_ADDR(tmpfwbuf, DMA_ALIGNMENT);
+#if defined(SD9098)
+ if (IS_SD9098(pmadapter->card_type)) {
+ rev_id_reg = pmadapter->pcard_sd->reg->card_revision_reg;
+ ret = pcb->moal_read_reg(pmadapter->pmoal_handle, rev_id_reg,
+ &revision_id);
+ if (ret != MLAN_STATUS_SUCCESS) {
+ PRINTM(MERROR,
+ "Card Revision register read failed:"
+ "card_revision_reg=0x%x\n",
+ rev_id_reg);
+ goto done;
+ }
+ /* Skyhawk A0, need to check both CRC and MIC error */
+ if (revision_id >= CHIP_9098_REV_A0)
+ check_fw_status = MTRUE;
+ }
+#endif
+#if defined(SD9097)
+ if (IS_SD9097(pmadapter->card_type))
+ check_fw_status = MTRUE;
+#endif
+ /* Perform firmware data transfer */
+ do {
+ /* The host polls for the DN_LD_CARD_RDY and CARD_IO_READY bits
+ */
+ ret = wlan_sdio_poll_card_status(
+ pmadapter, CARD_IO_READY | DN_LD_CARD_RDY);
+ if (ret != MLAN_STATUS_SUCCESS) {
+ PRINTM(MFATAL,
+ "WLAN: FW download with helper poll status timeout @ %d\n",
+ offset);
+ goto done;
+ }
+
+ /* More data */
+ if (firmwarelen && offset >= firmwarelen)
+ break;
+
+ for (tries = 0; tries < MAX_POLL_TRIES; tries++) {
+ ret = pcb->moal_read_reg(pmadapter->pmoal_handle,
+ read_base_0_reg, &base0);
+ if (ret != MLAN_STATUS_SUCCESS) {
+ PRINTM(MERROR,
+ "Dev BASE0 register read failed:"
+ " base0=0x%04X(%d). Terminating download\n",
+ base0, base0);
+ goto done;
+ }
+ ret = pcb->moal_read_reg(pmadapter->pmoal_handle,
+ read_base_1_reg, &base1);
+ if (ret != MLAN_STATUS_SUCCESS) {
+ PRINTM(MERROR,
+ "Dev BASE1 register read failed:"
+ " base1=0x%04X(%d). Terminating download\n",
+ base1, base1);
+ goto done;
+ }
+ len = (t_u16)(((base1 & 0xff) << 8) | (base0 & 0xff));
+
+ if (len)
+ break;
+ wlan_udelay(pmadapter, 10);
+ }
+
+ if (!len)
+ break;
+ else if (len > WLAN_UPLD_SIZE) {
+ PRINTM(MFATAL,
+ "WLAN: FW download failure @ %d, invalid length %d\n",
+ offset, len);
+ ret = MLAN_STATUS_FAILURE;
+ goto done;
+ }
+
+ /* Ignore CRC check before download the 1st packet */
+ if (offset == 0 && (len & MBIT(0)))
+ len &= ~MBIT(0);
+
+ txlen = len;
+
+ if (len & MBIT(0)) {
+ /* New fw download process, check CRC and MIC error */
+ if (check_fw_status) {
+ /* Get offset from fw dnld offset Register */
+ ret = wlan_sdio_read_fw_dnld_offset(
+ pmadapter, &fw_dnld_offset);
+ if (ret != MLAN_STATUS_SUCCESS) {
+ PRINTM(MFATAL,
+ "WLAN: FW download with helper read fw dnld offset failed @ %d\n",
+ offset);
+ goto done;
+ }
+ /* Get CRC MIC error from fw dnld status
+ * Register */
+ ret = wlan_sdio_read_fw_dnld_status(
+ pmadapter, &fw_dnld_status);
+ if (ret != MLAN_STATUS_SUCCESS) {
+ PRINTM(MFATAL,
+ "WLAN: FW download with helper read fw dnld status failed @ %d\n",
+ offset);
+ goto done;
+ }
+ PRINTM(MERROR,
+ "WLAN: FW download error: status=0x%x offset = 0x%x fw offset = 0x%x\n",
+ fw_dnld_status, offset, fw_dnld_offset);
+ }
+ i++;
+ if (i > MAX_WRITE_IOMEM_RETRY) {
+ PRINTM(MFATAL,
+ "WLAN: FW download failure @ %d, over max retry count\n",
+ offset);
+ ret = MLAN_STATUS_FAILURE;
+ goto done;
+ }
+
+ PRINTM(MERROR,
+ "WLAN: FW CRC error indicated by the helper:"
+ " len = 0x%04X, txlen = %d\n",
+ len, txlen);
+ len &= ~MBIT(0);
+ if (fw_dnld_status & (MBIT(6) | MBIT(7))) {
+ offset = 0;
+ mic_retry++;
+ if (mic_retry > MAX_FW_RETRY) {
+ PRINTM(MFATAL,
+ "WLAN: FW download failure @ %d, over max mic retry count\n",
+ offset);
+ ret = MLAN_STATUS_FAILURE;
+ goto done;
+ }
+ }
+ PRINTM(MERROR, "WLAN: retry: %d, offset %d\n", i,
+ offset);
+ DBG_HEXDUMP(MERROR, "WLAN: FW block:", fwbuf, len);
+ /* Setting this to 0 to resend from same offset */
+ txlen = 0;
+ } else {
+ i = 0;
+
+ /* Set blocksize to transfer - checking
+ * for last block */
+ if (firmwarelen && firmwarelen - offset < txlen)
+ txlen = firmwarelen - offset;
+ PRINTM(MINFO, ".");
+
+ tx_blocks = (txlen + MLAN_SDIO_BLOCK_SIZE_FW_DNLD - 1) /
+ MLAN_SDIO_BLOCK_SIZE_FW_DNLD;
+
+ /* Copy payload to buffer */
+ if (firmware)
+ memmove(pmadapter, fwbuf, &firmware[offset],
+ txlen);
+ else
+ pcb->moal_get_fw_data(pmadapter->pmoal_handle,
+ offset, txlen, fwbuf);
+ }
+
+ /* Send data */
+ memset(pmadapter, &mbuf, 0, sizeof(mlan_buffer));
+ mbuf.pbuf = (t_u8 *)fwbuf;
+ mbuf.data_len = tx_blocks * MLAN_SDIO_BLOCK_SIZE_FW_DNLD;
+
+ ret = pcb->moal_write_data_sync(pmadapter->pmoal_handle, &mbuf,
+ pmadapter->pcard_sd->ioport, 0);
+ if (ret != MLAN_STATUS_SUCCESS) {
+ PRINTM(MERROR,
+ "WLAN: FW download, write iomem (%d) failed @ %d\n",
+ i, offset);
+ if (pcb->moal_write_reg(pmadapter->pmoal_handle,
+ HOST_TO_CARD_EVENT_REG,
+ HOST_TERM_CMD53) !=
+ MLAN_STATUS_SUCCESS) {
+ PRINTM(MERROR, "write CFG reg failed\n");
+ }
+ ret = MLAN_STATUS_FAILURE;
+ goto done;
+ }
+
+ offset += txlen;
+ } while (MTRUE);
+
+ PRINTM(MMSG, "Wlan: FW download over, firmwarelen=%d downloaded %d\n",
+ firmwarelen, offset);
+
+ ret = MLAN_STATUS_SUCCESS;
+done:
+ if (tmpfwbuf)
+ pcb->moal_mfree(pmadapter->pmoal_handle, (t_u8 *)tmpfwbuf);
+
+ LEAVE();
+ return ret;
+}
+
+/**
+ * @brief This function disables the host interrupts.
+ *
+ * @param pmadapter A pointer to mlan_adapter structure
+ * @return MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ */
+static mlan_status wlan_disable_sdio_host_int(pmlan_adapter pmadapter)
+{
+ mlan_status ret;
+
+ ENTER();
+ ret = wlan_sdio_disable_host_int_mask(pmadapter, HIM_DISABLE);
+ LEAVE();
+ return ret;
+}
+
+/**
+ * @brief This function decodes the rx packet &
+ * calls corresponding handlers according to the packet type
+ *
+ * @param pmadapter A pointer to mlan_adapter structure
+ * @param pmbuf A pointer to the SDIO data/cmd buffer
+ * @param upld_typ Type of rx packet
+ * @param lock_flag flag for spin_lock.
+ * @return MLAN_STATUS_SUCCESS
+ */
+static mlan_status wlan_decode_rx_packet(mlan_adapter *pmadapter,
+ mlan_buffer *pmbuf, t_u32 upld_typ,
+ t_u8 lock_flag)
+{
+ t_u8 *cmd_buf;
+ t_u32 event;
+
+ ENTER();
+
+ switch (upld_typ) {
+ case MLAN_TYPE_SPA_DATA:
+ PRINTM(MINFO, "--- Rx: SPA Data packet ---\n");
+ pmbuf->data_len = pmadapter->upld_len;
+ if (pmadapter->rx_work_flag) {
+ pmbuf->buf_type = MLAN_BUF_TYPE_SPA_DATA;
+ if (lock_flag)
+ pmadapter->callbacks.moal_spin_lock(
+ pmadapter->pmoal_handle,
+ pmadapter->rx_data_queue.plock);
+ util_enqueue_list_tail(pmadapter->pmoal_handle,
+ &pmadapter->rx_data_queue,
+ (pmlan_linked_list)pmbuf, MNULL,
+ MNULL);
+ pmadapter->rx_pkts_queued++;
+ if (lock_flag)
+ pmadapter->callbacks.moal_spin_unlock(
+ pmadapter->pmoal_handle,
+ pmadapter->rx_data_queue.plock);
+ } else {
+ wlan_decode_spa_buffer(pmadapter,
+ pmbuf->pbuf + pmbuf->data_offset,
+ pmbuf->data_len);
+ wlan_free_mlan_buffer(pmadapter, pmbuf);
+ }
+ pmadapter->data_received = MTRUE;
+ break;
+ case MLAN_TYPE_DATA:
+ PRINTM(MINFO, "--- Rx: Data packet ---\n");
+ if (pmadapter->upld_len > pmbuf->data_len) {
+ PRINTM(MERROR,
+ "SDIO: Drop packet upld_len=%d data_len=%d \n",
+ pmadapter->upld_len, pmbuf->data_len);
+ wlan_free_mlan_buffer(pmadapter, pmbuf);
+ break;
+ }
+ pmbuf->data_len = (pmadapter->upld_len - SDIO_INTF_HEADER_LEN);
+ pmbuf->data_offset += SDIO_INTF_HEADER_LEN;
+ if (pmadapter->rx_work_flag) {
+ if (lock_flag)
+ pmadapter->callbacks.moal_spin_lock(
+ pmadapter->pmoal_handle,
+ pmadapter->rx_data_queue.plock);
+ util_enqueue_list_tail(pmadapter->pmoal_handle,
+ &pmadapter->rx_data_queue,
+ (pmlan_linked_list)pmbuf, MNULL,
+ MNULL);
+ pmadapter->rx_pkts_queued++;
+ if (lock_flag)
+ pmadapter->callbacks.moal_spin_unlock(
+ pmadapter->pmoal_handle,
+ pmadapter->rx_data_queue.plock);
+ } else {
+ wlan_handle_rx_packet(pmadapter, pmbuf);
+ }
+ pmadapter->data_received = MTRUE;
+ break;
+
+ case MLAN_TYPE_CMD:
+ PRINTM(MINFO, "--- Rx: Cmd Response ---\n");
+ /* take care of curr_cmd = NULL case */
+ if (!pmadapter->curr_cmd) {
+ cmd_buf = pmadapter->upld_buf;
+ if (pmadapter->ps_state == PS_STATE_SLEEP_CFM) {
+ wlan_process_sleep_confirm_resp(
+ pmadapter,
+ pmbuf->pbuf + pmbuf->data_offset +
+ SDIO_INTF_HEADER_LEN,
+ pmadapter->upld_len -
+ SDIO_INTF_HEADER_LEN);
+ }
+ pmadapter->upld_len -= SDIO_INTF_HEADER_LEN;
+ memcpy_ext(pmadapter, cmd_buf,
+ pmbuf->pbuf + pmbuf->data_offset +
+ SDIO_INTF_HEADER_LEN,
+ pmadapter->upld_len - SDIO_INTF_HEADER_LEN,
+ MRVDRV_SIZE_OF_CMD_BUFFER);
+ wlan_free_mlan_buffer(pmadapter, pmbuf);
+ } else {
+ pmadapter->cmd_resp_received = MTRUE;
+ pmadapter->upld_len -= SDIO_INTF_HEADER_LEN;
+ pmbuf->data_len = pmadapter->upld_len;
+ pmbuf->data_offset += SDIO_INTF_HEADER_LEN;
+ pmadapter->curr_cmd->respbuf = pmbuf;
+ if (pmadapter->upld_len >= MRVDRV_SIZE_OF_CMD_BUFFER) {
+ PRINTM(MMSG, "Invalid CmdResp len=%d\n",
+ pmadapter->upld_len);
+ DBG_HEXDUMP(MERROR, "Invalid CmdResp",
+ pmbuf->pbuf + pmbuf->data_offset,
+ MAX_DATA_DUMP_LEN);
+ }
+ }
+ break;
+
+ case MLAN_TYPE_EVENT:
+ PRINTM(MINFO, "--- Rx: Event ---\n");
+ event = *(t_u32 *)&pmbuf->pbuf[pmbuf->data_offset +
+ SDIO_INTF_HEADER_LEN];
+ pmadapter->event_cause = wlan_le32_to_cpu(event);
+ if ((pmadapter->upld_len > MLAN_EVENT_HEADER_LEN) &&
+ ((pmadapter->upld_len - MLAN_EVENT_HEADER_LEN) <
+ MAX_EVENT_SIZE)) {
+ memcpy_ext(pmadapter, pmadapter->event_body,
+ pmbuf->pbuf + pmbuf->data_offset +
+ MLAN_EVENT_HEADER_LEN,
+ pmadapter->upld_len - MLAN_EVENT_HEADER_LEN,
+ MAX_EVENT_SIZE);
+ }
+
+ /* event cause has been saved to adapter->event_cause */
+ pmadapter->event_received = MTRUE;
+ pmbuf->data_len = pmadapter->upld_len;
+ pmadapter->pmlan_buffer_event = pmbuf;
+
+ /* remove SDIO header */
+ pmbuf->data_offset += SDIO_INTF_HEADER_LEN;
+ pmbuf->data_len -= SDIO_INTF_HEADER_LEN;
+ break;
+
+ default:
+ PRINTM(MERROR, "SDIO unknown upload type = 0x%x\n", upld_typ);
+ wlan_free_mlan_buffer(pmadapter, pmbuf);
+ break;
+ }
+
+ LEAVE();
+ return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ * @brief This function receives single packet
+ *
+ * @param pmadapter A pointer to mlan_adapter structure
+ * @return MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ */
+mlan_status wlan_receive_single_packet(mlan_adapter *pmadapter)
+{
+ mlan_buffer *pmbuf;
+ t_u8 port;
+ t_u16 rx_len;
+ t_u32 pkt_type = 0;
+ mlan_status ret = MLAN_STATUS_SUCCESS;
+
+ ENTER();
+ pmbuf = pmadapter->pcard_sd->mpa_rx.mbuf_arr[0];
+ port = pmadapter->pcard_sd->mpa_rx.start_port;
+ rx_len = pmadapter->pcard_sd->mpa_rx.len_arr[0];
+ if (MLAN_STATUS_SUCCESS !=
+ wlan_sdio_card_to_host(pmadapter, &pkt_type,
+ (t_u32 *)&pmadapter->upld_len, pmbuf, rx_len,
+ pmadapter->pcard_sd->ioport + port)) {
+ ret = MLAN_STATUS_FAILURE;
+ goto done;
+ }
+ if (pkt_type != MLAN_TYPE_DATA && pkt_type != MLAN_TYPE_SPA_DATA) {
+ PRINTM(MERROR,
+ "receive a wrong pkt from DATA PORT: type=%d, len=%dd\n",
+ pkt_type, pmbuf->data_len);
+ pmbuf->status_code = MLAN_ERROR_DATA_RX_FAIL;
+ ret = MLAN_STATUS_FAILURE;
+ goto done;
+ }
+ pmadapter->pcard_sd->mpa_rx_count[0]++;
+ wlan_decode_rx_packet(pmadapter, pmbuf, pkt_type, MTRUE);
+done:
+ if (ret != MLAN_STATUS_SUCCESS)
+ wlan_free_mlan_buffer(pmadapter, pmbuf);
+ MP_RX_AGGR_BUF_RESET(pmadapter);
+ LEAVE();
+ return ret;
+}
+
+/**
+ * @brief This function receives data from the card in aggregate mode.
+ *
+ * @param pmadapter A pointer to mlan_adapter structure
+ * @return MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ */
+mlan_status wlan_receive_mp_aggr_buf(mlan_adapter *pmadapter)
+{
+ mlan_status ret = MLAN_STATUS_SUCCESS;
+ pmlan_callbacks pcb = &pmadapter->callbacks;
+ mlan_buffer mbuf_aggr;
+ mlan_buffer *mbuf_deaggr;
+ t_u32 pind = 0;
+ t_u32 pkt_len, pkt_type = 0;
+ t_u8 *curr_ptr;
+ t_u32 cmd53_port = 0;
+ t_u32 i = 0;
+ t_u32 port_count = 0;
+
+ /* do aggr RX now */
+ PRINTM(MINFO, "do_rx_aggr: num of packets: %d\n",
+ pmadapter->pcard_sd->mpa_rx.pkt_cnt);
+
+ memset(pmadapter, &mbuf_aggr, 0, sizeof(mlan_buffer));
+
+ if (pmadapter->pcard_sd->mpa_rx.pkt_cnt == 1)
+ return wlan_receive_single_packet(pmadapter);
+ if (!pmadapter->pcard_sd->mpa_rx.buf) {
+ mbuf_aggr.data_len = pmadapter->pcard_sd->mpa_rx.buf_len;
+ mbuf_aggr.pnext = mbuf_aggr.pprev = &mbuf_aggr;
+ mbuf_aggr.use_count = 0;
+ for (pind = 0; pind < pmadapter->pcard_sd->mpa_rx.pkt_cnt;
+ pind++) {
+ pmadapter->pcard_sd->mpa_rx.mbuf_arr[pind]->data_len =
+ pmadapter->pcard_sd->mpa_rx.len_arr[pind];
+ wlan_link_buf_to_aggr(
+ &mbuf_aggr,
+ pmadapter->pcard_sd->mpa_rx.mbuf_arr[pind]);
+ }
+ } else {
+ mbuf_aggr.pbuf = (t_u8 *)pmadapter->pcard_sd->mpa_rx.buf;
+ mbuf_aggr.data_len = pmadapter->pcard_sd->mpa_rx.buf_len;
+ }
+
+ port_count = bitcount(pmadapter->pcard_sd->mpa_rx.ports) - 1;
+ /* port_count = pmadapter->mpa_rx.pkt_cnt - 1; */
+ cmd53_port = (pmadapter->pcard_sd->ioport | SDIO_MPA_ADDR_BASE |
+ (port_count << 8)) +
+ pmadapter->pcard_sd->mpa_rx.start_port;
+ do {
+ ret = pcb->moal_read_data_sync(pmadapter->pmoal_handle,
+ &mbuf_aggr, cmd53_port, 0);
+ if (ret != MLAN_STATUS_SUCCESS) {
+ PRINTM(MERROR,
+ "wlan: sdio mp cmd53 read failed: %d ioport=0x%x retry=%d\n",
+ ret, cmd53_port, i);
+ i++;
+ if (MLAN_STATUS_SUCCESS !=
+ pcb->moal_write_reg(pmadapter->pmoal_handle,
+ HOST_TO_CARD_EVENT_REG,
+ HOST_TERM_CMD53)) {
+ PRINTM(MERROR, "Set Term cmd53 failed\n");
+ }
+ if (i > MAX_WRITE_IOMEM_RETRY) {
+ ret = MLAN_STATUS_FAILURE;
+ goto done;
+ }
+ }
+ } while (ret == MLAN_STATUS_FAILURE);
+ if (pmadapter->rx_work_flag)
+ pmadapter->callbacks.moal_spin_lock(
+ pmadapter->pmoal_handle,
+ pmadapter->rx_data_queue.plock);
+ if (!pmadapter->pcard_sd->mpa_rx.buf &&
+ pmadapter->pcard_sd->mpa_rx.pkt_cnt > 1) {
+ for (pind = 0; pind < pmadapter->pcard_sd->mpa_rx.pkt_cnt;
+ pind++) {
+ mbuf_deaggr =
+ pmadapter->pcard_sd->mpa_rx.mbuf_arr[pind];
+ pkt_len = wlan_le16_to_cpu(
+ *(t_u16 *)(mbuf_deaggr->pbuf +
+ mbuf_deaggr->data_offset));
+ pkt_type = wlan_le16_to_cpu(
+ *(t_u16 *)(mbuf_deaggr->pbuf +
+ mbuf_deaggr->data_offset + 2));
+ pmadapter->upld_len = pkt_len;
+ wlan_decode_rx_packet(pmadapter, mbuf_deaggr, pkt_type,
+ MFALSE);
+ }
+ } else {
+ DBG_HEXDUMP(MIF_D, "SDIO MP-A Blk Rd",
+ pmadapter->pcard_sd->mpa_rx.buf,
+ MIN(pmadapter->pcard_sd->mpa_rx.buf_len,
+ MAX_DATA_DUMP_LEN));
+
+ curr_ptr = pmadapter->pcard_sd->mpa_rx.buf;
+
+ for (pind = 0; pind < pmadapter->pcard_sd->mpa_rx.pkt_cnt;
+ pind++) {
+ /* get curr PKT len & type */
+ pkt_len = wlan_le16_to_cpu(*(t_u16 *)&curr_ptr[0]);
+ pkt_type = wlan_le16_to_cpu(*(t_u16 *)&curr_ptr[2]);
+
+ PRINTM(MINFO, "RX: [%d] pktlen: %d pkt_type: 0x%x\n",
+ pind, pkt_len, pkt_type);
+
+ /* copy pkt to deaggr buf */
+ mbuf_deaggr =
+ pmadapter->pcard_sd->mpa_rx.mbuf_arr[pind];
+ if ((pkt_type == MLAN_TYPE_DATA ||
+ pkt_type == MLAN_TYPE_SPA_DATA) &&
+ (pkt_len <=
+ pmadapter->pcard_sd->mpa_rx.len_arr[pind])) {
+ memcpy_ext(pmadapter,
+ mbuf_deaggr->pbuf +
+ mbuf_deaggr->data_offset,
+ curr_ptr, pkt_len, pkt_len);
+ pmadapter->upld_len = pkt_len;
+ /* Process de-aggr packet */
+ wlan_decode_rx_packet(pmadapter, mbuf_deaggr,
+ pkt_type, MFALSE);
+ } else {
+ PRINTM(MERROR,
+ "Wrong aggr packet: type=%d, len=%d, max_len=%d\n",
+ pkt_type, pkt_len,
+ pmadapter->pcard_sd->mpa_rx
+ .len_arr[pind]);
+ wlan_free_mlan_buffer(pmadapter, mbuf_deaggr);
+ }
+ curr_ptr += pmadapter->pcard_sd->mpa_rx.len_arr[pind];
+ }
+ }
+ if (pmadapter->rx_work_flag)
+ pmadapter->callbacks.moal_spin_unlock(
+ pmadapter->pmoal_handle,
+ pmadapter->rx_data_queue.plock);
+ pmadapter->pcard_sd
+ ->mpa_rx_count[pmadapter->pcard_sd->mpa_rx.pkt_cnt - 1]++;
+ MP_RX_AGGR_BUF_RESET(pmadapter);
+done:
+ return ret;
+}
+
+/**
+ * @brief This function receives data from the card in aggregate mode.
+ *
+ * @param pmadapter A pointer to mlan_adapter structure
+ * @param pmbuf A pointer to the SDIO data/cmd buffer
+ * @param port Current port on which packet needs to be rxed
+ * @param rx_len Length of received packet
+ * @return MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ */
+static mlan_status wlan_sdio_card_to_host_mp_aggr(mlan_adapter *pmadapter,
+ mlan_buffer *pmbuf, t_u8 port,
+ t_u16 rx_len)
+{
+ mlan_status ret = MLAN_STATUS_SUCCESS;
+ t_s32 f_do_rx_aggr = 0;
+ t_s32 f_do_rx_cur = 0;
+ t_s32 f_aggr_cur = 0;
+ t_s32 f_post_aggr_cur = 0;
+ t_u32 pind = 0;
+ t_u32 pkt_type = 0;
+ const mlan_sdio_card_reg *reg = pmadapter->pcard_sd->reg;
+
+ ENTER();
+
+ if (!pmadapter->pcard_sd->mpa_rx.enabled) {
+ PRINTM(MINFO,
+ "card_2_host_mp_aggr: rx aggregation disabled !\n");
+
+ f_do_rx_cur = 1;
+ goto rx_curr_single;
+ }
+
+ if (pmadapter->pcard_sd->mp_rd_bitmap & reg->data_port_mask) {
+ /* Some more data RX pending */
+ PRINTM(MINFO, "card_2_host_mp_aggr: Not last packet\n");
+
+ if (MP_RX_AGGR_IN_PROGRESS(pmadapter)) {
+ if (MP_RX_AGGR_BUF_HAS_ROOM(pmadapter, 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 */
+ PRINTM(MINFO, "card_2_host_mp_aggr: Last packet\n");
+
+ if (MP_RX_AGGR_IN_PROGRESS(pmadapter)) {
+ f_do_rx_aggr = 1;
+ if (MP_RX_AGGR_BUF_HAS_ROOM(pmadapter, 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) {
+ PRINTM(MINFO, "Current packet aggregation.\n");
+ /* Curr pkt can be aggregated */
+ MP_RX_AGGR_SETUP(pmadapter, pmbuf, port, rx_len);
+
+ if (MP_RX_AGGR_PKT_LIMIT_REACHED(pmadapter) ||
+ MP_RX_AGGR_PORT_LIMIT_REACHED(pmadapter)) {
+ PRINTM(MINFO,
+ "card_2_host_mp_aggr: Aggregation Packet limit reached\n");
+ /* No more pkts allowed in Aggr buf, rx it */
+ f_do_rx_aggr = 1;
+ }
+ }
+
+ if (f_do_rx_aggr) {
+ /* do aggr RX now */
+ if (MLAN_STATUS_SUCCESS !=
+ wlan_receive_mp_aggr_buf(pmadapter)) {
+ ret = MLAN_STATUS_FAILURE;
+ goto done;
+ }
+ }
+rx_curr_single:
+ if (f_do_rx_cur) {
+ PRINTM(MINFO, "RX: f_do_rx_cur: port: %d rx_len: %d\n", port,
+ rx_len);
+
+ if (MLAN_STATUS_SUCCESS !=
+ wlan_sdio_card_to_host(
+ pmadapter, &pkt_type, (t_u32 *)&pmadapter->upld_len,
+ pmbuf, rx_len,
+ pmadapter->pcard_sd->ioport + port)) {
+ ret = MLAN_STATUS_FAILURE;
+ goto done;
+ }
+ if (pkt_type != MLAN_TYPE_DATA &&
+ pkt_type != MLAN_TYPE_SPA_DATA) {
+ PRINTM(MERROR,
+ "receive a wrong pkt from DATA PORT: type=%d, len=%dd\n",
+ pkt_type, pmbuf->data_len);
+ pmbuf->status_code = MLAN_ERROR_DATA_RX_FAIL;
+ ret = MLAN_STATUS_FAILURE;
+ goto done;
+ }
+
+ pmadapter->pcard_sd->mpa_rx_count[0]++;
+
+ wlan_decode_rx_packet(pmadapter, pmbuf, pkt_type, MTRUE);
+ }
+ if (f_post_aggr_cur) {
+ PRINTM(MINFO, "Current packet aggregation.\n");
+ /* Curr pkt can be aggregated */
+ MP_RX_AGGR_SETUP(pmadapter, pmbuf, port, rx_len);
+ }
+done:
+ if (ret == MLAN_STATUS_FAILURE) {
+ if (MP_RX_AGGR_IN_PROGRESS(pmadapter)) {
+ /* MP-A transfer failed - cleanup */
+ for (pind = 0;
+ pind < pmadapter->pcard_sd->mpa_rx.pkt_cnt;
+ pind++) {
+ wlan_free_mlan_buffer(
+ pmadapter, pmadapter->pcard_sd->mpa_rx
+ .mbuf_arr[pind]);
+ }
+ MP_RX_AGGR_BUF_RESET(pmadapter);
+ }
+
+ if (f_do_rx_cur) {
+ /* Single Transfer pending */
+ /* Free curr buff also */
+ wlan_free_mlan_buffer(pmadapter, pmbuf);
+ }
+ }
+
+ LEAVE();
+ return ret;
+}
+
+/**
+ * @brief This function sends aggr buf
+ *
+ * @param pmadapter A pointer to mlan_adapter structure
+ * @return MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ */
+mlan_status wlan_send_mp_aggr_buf(mlan_adapter *pmadapter)
+{
+ mlan_status ret = MLAN_STATUS_SUCCESS;
+ t_u32 cmd53_port = 0;
+ t_u32 port_count = 0;
+ mlan_buffer mbuf_aggr;
+ t_u8 i = 0;
+ t_u8 mp_aggr_pkt_limit = SDIO_MP_AGGR_DEF_PKT_LIMIT;
+
+ ENTER();
+
+ if (!pmadapter->pcard_sd->mpa_tx.pkt_cnt) {
+ LEAVE();
+ return ret;
+ }
+ PRINTM(MINFO,
+ "host_2_card_mp_aggr: Send aggregation buffer."
+ "%d %d\n",
+ pmadapter->pcard_sd->mpa_tx.start_port,
+ pmadapter->pcard_sd->mpa_tx.ports);
+
+ memset(pmadapter, &mbuf_aggr, 0, sizeof(mlan_buffer));
+
+ if (!pmadapter->pcard_sd->mpa_tx.buf &&
+ pmadapter->pcard_sd->mpa_tx.pkt_cnt > 1) {
+ mbuf_aggr.data_len = pmadapter->pcard_sd->mpa_tx.buf_len;
+ mbuf_aggr.pnext = mbuf_aggr.pprev = &mbuf_aggr;
+ mbuf_aggr.use_count = 0;
+ for (i = 0; i < pmadapter->pcard_sd->mpa_tx.pkt_cnt; i++)
+ wlan_link_buf_to_aggr(
+ &mbuf_aggr,
+ pmadapter->pcard_sd->mpa_tx.mbuf_arr[i]);
+ } else {
+ mbuf_aggr.pbuf = (t_u8 *)pmadapter->pcard_sd->mpa_tx.buf;
+ mbuf_aggr.data_len = pmadapter->pcard_sd->mpa_tx.buf_len;
+ }
+
+ port_count = bitcount(pmadapter->pcard_sd->mpa_tx.ports) - 1;
+ cmd53_port = (pmadapter->pcard_sd->ioport | SDIO_MPA_ADDR_BASE |
+ (port_count << 8)) +
+ pmadapter->pcard_sd->mpa_tx.start_port;
+
+ if (pmadapter->pcard_sd->mpa_tx.pkt_cnt == 1)
+ cmd53_port = pmadapter->pcard_sd->ioport +
+ pmadapter->pcard_sd->mpa_tx.start_port;
+ /** only one packet */
+ if (!pmadapter->pcard_sd->mpa_tx.buf &&
+ pmadapter->pcard_sd->mpa_tx.pkt_cnt == 1)
+ ret = wlan_write_data_sync(
+ pmadapter, pmadapter->pcard_sd->mpa_tx.mbuf_arr[0],
+ cmd53_port);
+ else
+ ret = wlan_write_data_sync(pmadapter, &mbuf_aggr, cmd53_port);
+ if (!pmadapter->pcard_sd->mpa_tx.buf) {
+ /** free mlan buffer */
+ for (i = 0; i < pmadapter->pcard_sd->mpa_tx.pkt_cnt; i++) {
+ wlan_write_data_complete(
+ pmadapter,
+ pmadapter->pcard_sd->mpa_tx.mbuf_arr[i],
+ MLAN_STATUS_SUCCESS);
+ }
+ }
+ if (!(pmadapter->pcard_sd->mp_wr_bitmap &
+ (1 << pmadapter->pcard_sd->curr_wr_port)) &&
+ (pmadapter->pcard_sd->mpa_tx.pkt_cnt < mp_aggr_pkt_limit))
+ pmadapter->pcard_sd->mpa_sent_no_ports++;
+ pmadapter->pcard_sd
+ ->mpa_tx_count[pmadapter->pcard_sd->mpa_tx.pkt_cnt - 1]++;
+ pmadapter->pcard_sd
+ ->last_mp_wr_bitmap[pmadapter->pcard_sd->last_mp_index] =
+ pmadapter->pcard_sd->mp_wr_bitmap;
+ pmadapter->pcard_sd
+ ->last_mp_wr_ports[pmadapter->pcard_sd->last_mp_index] =
+ cmd53_port;
+ pmadapter->pcard_sd->last_mp_wr_len[pmadapter->pcard_sd->last_mp_index] =
+ pmadapter->pcard_sd->mpa_tx.buf_len;
+ pmadapter->pcard_sd
+ ->last_curr_wr_port[pmadapter->pcard_sd->last_mp_index] =
+ pmadapter->pcard_sd->curr_wr_port;
+ memcpy_ext(
+ pmadapter,
+ (t_u8 *)&pmadapter->pcard_sd
+ ->last_mp_wr_info[pmadapter->pcard_sd->last_mp_index *
+ mp_aggr_pkt_limit],
+ (t_u8 *)pmadapter->pcard_sd->mpa_tx.mp_wr_info,
+ mp_aggr_pkt_limit * sizeof(t_u16),
+ mp_aggr_pkt_limit * sizeof(t_u16));
+ pmadapter->pcard_sd->last_mp_index++;
+ if (pmadapter->pcard_sd->last_mp_index >= SDIO_MP_DBG_NUM)
+ pmadapter->pcard_sd->last_mp_index = 0;
+ MP_TX_AGGR_BUF_RESET(pmadapter);
+ LEAVE();
+ return ret;
+}
+
+/**
+ * @brief This function sends data to the card in SDIO aggregated mode.
+ *
+ * @param pmadapter A pointer to mlan_adapter structure
+ * @param mbuf A pointer to the SDIO data/cmd buffer
+ * @param port current port for aggregation
+ * @param next_pkt_len Length of next packet used for multiport aggregation
+ * @return MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ */
+static mlan_status wlan_host_to_card_mp_aggr(mlan_adapter *pmadapter,
+ mlan_buffer *mbuf, t_u8 port,
+ t_u32 next_pkt_len)
+{
+ mlan_status ret = MLAN_STATUS_SUCCESS;
+ t_s32 f_send_aggr_buf = 0;
+ t_s32 f_send_cur_buf = 0;
+ t_s32 f_precopy_cur_buf = 0;
+ t_s32 f_postcopy_cur_buf = 0;
+ t_u8 aggr_sg = 0;
+ t_u8 mp_aggr_pkt_limit = SDIO_MP_AGGR_DEF_PKT_LIMIT;
+
+ ENTER();
+
+ PRINTM(MIF_D, "host_2_card_mp_aggr: next_pkt_len: %d curr_port:%d\n",
+ next_pkt_len, port);
+
+ if (!pmadapter->pcard_sd->mpa_tx.enabled) {
+ PRINTM(MINFO,
+ "host_2_card_mp_aggr: tx aggregation disabled !\n");
+ f_send_cur_buf = 1;
+ goto tx_curr_single;
+ }
+
+ if (next_pkt_len) {
+ /* More pkt in TX queue */
+ PRINTM(MINFO, "host_2_card_mp_aggr: More packets in Queue.\n");
+
+ if (MP_TX_AGGR_IN_PROGRESS(pmadapter)) {
+ if (MP_TX_AGGR_BUF_HAS_ROOM(pmadapter, mbuf,
+ mbuf->data_len)) {
+ f_precopy_cur_buf = 1;
+
+ if (!(pmadapter->pcard_sd->mp_wr_bitmap &
+ (1
+ << pmadapter->pcard_sd->curr_wr_port)) ||
+ !MP_TX_AGGR_BUF_HAS_ROOM(
+ pmadapter, mbuf,
+ mbuf->data_len + next_pkt_len)) {
+ f_send_aggr_buf = 1;
+ }
+ } else {
+ /* No room in Aggr buf, send it */
+ f_send_aggr_buf = 1;
+
+ if (!(pmadapter->pcard_sd->mp_wr_bitmap &
+ (1
+ << pmadapter->pcard_sd->curr_wr_port))) {
+ f_send_cur_buf = 1;
+ } else {
+ f_postcopy_cur_buf = 1;
+ }
+ }
+ } else {
+ if (MP_TX_AGGR_BUF_HAS_ROOM(pmadapter, mbuf,
+ mbuf->data_len) &&
+ (pmadapter->pcard_sd->mp_wr_bitmap &
+ (1 << pmadapter->pcard_sd->curr_wr_port)))
+ f_precopy_cur_buf = 1;
+ else
+ f_send_cur_buf = 1;
+ }
+ } else {
+ /* Last pkt in TX queue */
+ PRINTM(MINFO,
+ "host_2_card_mp_aggr: Last packet in Tx Queue.\n");
+
+ if (MP_TX_AGGR_IN_PROGRESS(pmadapter)) {
+ /* some packs in Aggr buf already */
+ f_send_aggr_buf = 1;
+
+ if (MP_TX_AGGR_BUF_HAS_ROOM(pmadapter, mbuf,
+ mbuf->data_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;
+ }
+ pmadapter->pcard_sd->mpa_sent_last_pkt++;
+ }
+
+ if (f_precopy_cur_buf) {
+ PRINTM(MINFO, "host_2_card_mp_aggr: Precopy current buffer\n");
+ if (pmadapter->pcard_sd->mpa_buf)
+ memcpy_ext(
+ pmadapter,
+ pmadapter->pcard_sd->mpa_buf +
+ (pmadapter->pcard_sd->last_mp_index *
+ mp_aggr_pkt_limit +
+ pmadapter->pcard_sd->mpa_tx.pkt_cnt) *
+ MLAN_SDIO_BLOCK_SIZE,
+ mbuf->pbuf + mbuf->data_offset,
+ MLAN_SDIO_BLOCK_SIZE, MLAN_SDIO_BLOCK_SIZE);
+ if (!pmadapter->pcard_sd->mpa_tx.buf) {
+ MP_TX_AGGR_BUF_PUT_SG(pmadapter, mbuf, port);
+ aggr_sg = MTRUE;
+ } else {
+ MP_TX_AGGR_BUF_PUT(pmadapter, mbuf, port);
+ }
+ if (MP_TX_AGGR_PKT_LIMIT_REACHED(pmadapter)) {
+ PRINTM(MIF_D,
+ "host_2_card_mp_aggr: Aggregation Pkt limit reached\n");
+ /* No more pkts allowed in Aggr buf, send it */
+ f_send_aggr_buf = 1;
+ }
+ }
+
+ if (f_send_aggr_buf)
+ ret = wlan_send_mp_aggr_buf(pmadapter);
+
+tx_curr_single:
+ if (f_send_cur_buf) {
+ PRINTM(MINFO, "host_2_card_mp_aggr: writing to port #%d\n",
+ port);
+ ret = wlan_write_data_sync(pmadapter, mbuf,
+ pmadapter->pcard_sd->ioport + port);
+ if (!(pmadapter->pcard_sd->mp_wr_bitmap &
+ (1 << pmadapter->pcard_sd->curr_wr_port)))
+ pmadapter->pcard_sd->mpa_sent_no_ports++;
+ pmadapter->pcard_sd
+ ->last_mp_wr_bitmap[pmadapter->pcard_sd->last_mp_index] =
+ pmadapter->pcard_sd->mp_wr_bitmap;
+ pmadapter->pcard_sd
+ ->last_mp_wr_ports[pmadapter->pcard_sd->last_mp_index] =
+ pmadapter->pcard_sd->ioport + port;
+ pmadapter->pcard_sd
+ ->last_mp_wr_len[pmadapter->pcard_sd->last_mp_index] =
+ mbuf->data_len;
+ memset(pmadapter,
+ (t_u8 *)&pmadapter->pcard_sd->last_mp_wr_info
+ [pmadapter->pcard_sd->last_mp_index *
+ mp_aggr_pkt_limit],
+ 0, sizeof(t_u16) * mp_aggr_pkt_limit);
+ pmadapter->pcard_sd
+ ->last_mp_wr_info[pmadapter->pcard_sd->last_mp_index *
+ mp_aggr_pkt_limit] =
+ *(t_u16 *)(mbuf->pbuf + mbuf->data_offset);
+ pmadapter->pcard_sd
+ ->last_curr_wr_port[pmadapter->pcard_sd->last_mp_index] =
+ pmadapter->pcard_sd->curr_wr_port;
+ if (pmadapter->pcard_sd->mpa_buf)
+ memcpy_ext(pmadapter,
+ pmadapter->pcard_sd->mpa_buf +
+ (pmadapter->pcard_sd->last_mp_index *
+ mp_aggr_pkt_limit *
+ MLAN_SDIO_BLOCK_SIZE),
+ mbuf->pbuf + mbuf->data_offset,
+ MLAN_SDIO_BLOCK_SIZE, MLAN_SDIO_BLOCK_SIZE);
+ pmadapter->pcard_sd->last_mp_index++;
+ if (pmadapter->pcard_sd->last_mp_index >= SDIO_MP_DBG_NUM)
+ pmadapter->pcard_sd->last_mp_index = 0;
+ pmadapter->pcard_sd->mpa_tx_count[0]++;
+ }
+ if (f_postcopy_cur_buf) {
+ PRINTM(MINFO, "host_2_card_mp_aggr: Postcopy current buffer\n");
+ if (pmadapter->pcard_sd->mpa_buf)
+ memcpy_ext(
+ pmadapter,
+ pmadapter->pcard_sd->mpa_buf +
+ (pmadapter->pcard_sd->last_mp_index *
+ mp_aggr_pkt_limit +
+ pmadapter->pcard_sd->mpa_tx.pkt_cnt) *
+ MLAN_SDIO_BLOCK_SIZE,
+ mbuf->pbuf + mbuf->data_offset,
+ MLAN_SDIO_BLOCK_SIZE, MLAN_SDIO_BLOCK_SIZE);
+ if (!pmadapter->pcard_sd->mpa_tx.buf) {
+ MP_TX_AGGR_BUF_PUT_SG(pmadapter, mbuf, port);
+ aggr_sg = MTRUE;
+ } else {
+ MP_TX_AGGR_BUF_PUT(pmadapter, mbuf, port);
+ }
+ }
+ /* Always return PENDING in SG mode */
+ if (aggr_sg)
+ ret = MLAN_STATUS_PENDING;
+
+ LEAVE();
+ return ret;
+}
+
+/********************************************************
+ Global functions
+********************************************************/
+
+/**
+ * @brief This function checks if the interface is ready to download
+ * or not while other download interface is present
+ *
+ * @param pmadapter A pointer to mlan_adapter structure
+ * @param val Winner status (0: winner)
+ * @return MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ *
+ */
+mlan_status wlan_sdio_check_winner_status(mlan_adapter *pmadapter, t_u32 *val)
+{
+ t_u32 winner = 0;
+ pmlan_callbacks pcb;
+ t_u8 card_winner_check_reg = pmadapter->pcard_sd->reg->winner_check_reg;
+
+ ENTER();
+
+ pcb = &pmadapter->callbacks;
+
+ if (MLAN_STATUS_SUCCESS != pcb->moal_read_reg(pmadapter->pmoal_handle,
+ card_winner_check_reg,
+ &winner)) {
+ LEAVE();
+ return MLAN_STATUS_FAILURE;
+ }
+ *val = winner;
+
+ LEAVE();
+ return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ * @brief This function checks if the firmware is ready to accept
+ * command or not.
+ *
+ * @param pmadapter A pointer to mlan_adapter structure
+ * @param pollnum Maximum polling number
+ * @return MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ */
+mlan_status wlan_sdio_check_fw_status(mlan_adapter *pmadapter, t_u32 pollnum)
+{
+ mlan_status ret = MLAN_STATUS_SUCCESS;
+ t_u16 firmwarestat = 0;
+ t_u32 tries;
+
+ ENTER();
+
+ /* Wait for firmware initialization event */
+ for (tries = 0; tries < pollnum; tries++) {
+ ret = wlan_sdio_read_fw_status(pmadapter, &firmwarestat);
+ if (MLAN_STATUS_SUCCESS != ret)
+ continue;
+ if (firmwarestat == SDIO_FIRMWARE_READY) {
+ ret = MLAN_STATUS_SUCCESS;
+ break;
+ } else {
+ wlan_mdelay(pmadapter, 100);
+ ret = MLAN_STATUS_FAILURE;
+ }
+ }
+
+ if (ret != MLAN_STATUS_SUCCESS) {
+ if (pollnum > 1)
+ PRINTM(MERROR,
+ "Fail to poll firmware status: firmwarestat=0x%x\n",
+ firmwarestat);
+ goto done;
+ }
+
+done:
+ LEAVE();
+ return ret;
+}
+
+/**
+ * @brief This function enables the host interrupts.
+ *
+ * @param pmadapter A pointer to mlan_adapter structure
+ * @return MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ */
+mlan_status wlan_enable_sdio_host_int(pmlan_adapter pmadapter)
+{
+ mlan_status ret;
+ t_u8 mask = pmadapter->pcard_sd->reg->host_int_enable;
+
+ ENTER();
+ ret = wlan_sdio_enable_host_int_mask(pmadapter, mask);
+ LEAVE();
+ return ret;
+}
+
+/**
+ * @brief This function downloads firmware to card
+ *
+ * @param pmadapter A pointer to mlan_adapter
+ * @param pmfw A pointer to firmware image
+ *
+ * @return MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ */
+mlan_status wlan_sdio_dnld_fw(pmlan_adapter pmadapter, pmlan_fw_image pmfw)
+{
+ mlan_status ret = MLAN_STATUS_SUCCESS;
+ t_u32 poll_num = 1;
+ t_u32 winner = 0;
+
+ ENTER();
+
+ /*when using GPIO wakeup, don't run the below code.
+ *if using GPIO wakeup, host will do handshake with FW
+ *to check if FW wake up and pull up SDIO line, then reload driver.
+ *So when using GPIO wakeup, don't need driver to do check wakeup status
+ *again. when using SDIO interface wakeup, run the below code; if using
+ *SDIO interface wakeup, driver need to do check wakeup status with FW.
+ */
+
+ /* Card specific probing */
+ ret = wlan_sdio_probe(pmadapter);
+ if (ret == MLAN_STATUS_FAILURE) {
+ PRINTM(MERROR, "WLAN SDIO probe failed\n", ret);
+ LEAVE();
+ return ret;
+ }
+
+ /* Check if firmware is already running */
+ ret = wlan_sdio_check_fw_status(pmadapter, poll_num);
+ if (ret == MLAN_STATUS_SUCCESS) {
+#if defined(SDIO)
+ if (pmfw->fw_reload == FW_RELOAD_SDIO_INBAND_RESET) {
+ PRINTM(MMSG, "Try reset fw in mlan\n");
+ ret = wlan_reset_fw(pmadapter);
+ if (ret == MLAN_STATUS_FAILURE) {
+ PRINTM(MERROR, "FW reset failure!");
+ LEAVE();
+ return ret;
+ }
+ } else {
+#endif
+ PRINTM(MMSG,
+ "WLAN FW already running! Skip FW download\n");
+#if defined(SDIO)
+ pmadapter->ops.wakeup_card(pmadapter, MFALSE);
+#endif
+ goto done;
+#if defined(SDIO)
+ }
+#endif
+ }
+ poll_num = MAX_FIRMWARE_POLL_TRIES;
+
+ /* Check if other interface is downloading */
+ ret = wlan_sdio_check_winner_status(pmadapter, &winner);
+ if (ret == MLAN_STATUS_FAILURE) {
+ PRINTM(MFATAL, "WLAN read winner status failed!\n");
+ goto done;
+ }
+ if (winner) {
+ PRINTM(MMSG,
+ "WLAN is not the winner (0x%x). Skip FW download\n",
+ winner);
+ poll_num = MAX_MULTI_INTERFACE_POLL_TRIES;
+ goto poll_fw;
+ }
+
+ /* Download the firmware image via helper */
+ ret = wlan_sdio_prog_fw_w_helper(pmadapter, pmfw->pfw_buf,
+ pmfw->fw_len);
+ if (ret != MLAN_STATUS_SUCCESS) {
+ PRINTM(MERROR, "wlan_dnld_fw fail ret=0x%x\n", ret);
+ LEAVE();
+ return ret;
+ }
+
+poll_fw:
+ /* Check if the firmware is downloaded successfully or not */
+ ret = wlan_sdio_check_fw_status(pmadapter, poll_num);
+ if (ret != MLAN_STATUS_SUCCESS) {
+ PRINTM(MFATAL, "FW failed to be active in time!\n");
+ ret = MLAN_STATUS_FAILURE;
+ LEAVE();
+ return ret;
+ }
+done:
+
+ /* re-enable host interrupt for mlan after fw dnld is successful */
+ wlan_enable_sdio_host_int(pmadapter);
+
+ LEAVE();
+ return ret;
+}
+
+/**
+ * @brief This function probes the driver
+ *
+ * @param pmadapter A pointer to mlan_adapter structure
+ * @return MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ */
+mlan_status wlan_sdio_probe(pmlan_adapter pmadapter)
+{
+ mlan_status ret = MLAN_STATUS_SUCCESS;
+ t_u32 sdio_ireg = 0;
+ pmlan_callbacks pcb = &pmadapter->callbacks;
+
+ ENTER();
+ /*
+ * 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.
+ */
+ pcb->moal_read_reg(pmadapter->pmoal_handle,
+ pmadapter->pcard_sd->reg->host_int_status_reg,
+ &sdio_ireg);
+
+ /* Disable host interrupt mask register for SDIO */
+ ret = wlan_disable_sdio_host_int(pmadapter);
+ if (ret != MLAN_STATUS_SUCCESS) {
+ LEAVE();
+ return MLAN_STATUS_FAILURE;
+ }
+ /* Get SDIO ioport */
+ ret = wlan_sdio_init_ioport(pmadapter);
+ LEAVE();
+ return ret;
+}
+
+/**
+ * @brief This function get sdio device from card type
+ *
+ * @param pmadapter A pointer to mlan_adapter structure
+ * @return MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ */
+mlan_status wlan_get_sdio_device(pmlan_adapter pmadapter)
+{
+ mlan_status ret = MLAN_STATUS_SUCCESS;
+ t_u16 card_type = pmadapter->card_type;
+
+ ENTER();
+
+ ret = pmadapter->callbacks.moal_malloc(pmadapter->pmoal_handle,
+ sizeof(mlan_sdio_card),
+ MLAN_MEM_DEF,
+ (t_u8 **)&pmadapter->pcard_sd);
+ if (ret != MLAN_STATUS_SUCCESS || !pmadapter->pcard_sd) {
+ PRINTM(MERROR, "Failed to allocate pcard_sd\n");
+ LEAVE();
+ return MLAN_STATUS_FAILURE;
+ }
+
+ switch (card_type) {
+#ifdef SD8887
+ case CARD_TYPE_SD8887:
+ pmadapter->pcard_sd->reg = &mlan_reg_sd8887;
+ pmadapter->pcard_info = &mlan_card_info_sd8887;
+ break;
+#endif
+#ifdef SD8897
+ case CARD_TYPE_SD8897:
+ pmadapter->pcard_sd->reg = &mlan_reg_sd8897;
+ pmadapter->pcard_info = &mlan_card_info_sd8897;
+ break;
+#endif
+#if defined(SD8977) || defined(SD8978)
+ case CARD_TYPE_SD8977:
+ case CARD_TYPE_SD8978:
+ pmadapter->pcard_sd->reg = &mlan_reg_sd8977_sd8997;
+ pmadapter->pcard_info = &mlan_card_info_sd8977;
+ break;
+#endif
+#ifdef SD8997
+ case CARD_TYPE_SD8997:
+ pmadapter->pcard_sd->reg = &mlan_reg_sd8977_sd8997;
+ pmadapter->pcard_info = &mlan_card_info_sd8997;
+ break;
+#endif
+#ifdef SD8987
+ case CARD_TYPE_SD8987:
+ pmadapter->pcard_sd->reg = &mlan_reg_sd8977_sd8997;
+ pmadapter->pcard_info = &mlan_card_info_sd8987;
+ break;
+#endif
+#ifdef SD9098
+ case CARD_TYPE_SD9098:
+ pmadapter->pcard_sd->reg = &mlan_reg_sd8977_sd8997;
+ pmadapter->pcard_info = &mlan_card_info_sd9098;
+ break;
+#endif
+#ifdef SD9097
+ case CARD_TYPE_SD9097:
+ pmadapter->pcard_sd->reg = &mlan_reg_sd8977_sd8997;
+ pmadapter->pcard_info = &mlan_card_info_sd9097;
+ break;
+#endif
+ default:
+ PRINTM(MERROR, "can't get right card type \n");
+ ret = MLAN_STATUS_FAILURE;
+ break;
+ }
+
+ LEAVE();
+ return ret;
+}
+
+/**
+ * @brief This function gets interrupt status.
+ *
+ * @param pmadapter A pointer to mlan_adapter structure
+ * @return MLAN_STATUS_SUCCESS
+ */
+mlan_status wlan_sdio_interrupt(t_u16 msg_id, pmlan_adapter pmadapter)
+{
+ pmlan_callbacks pcb = &pmadapter->callbacks;
+ mlan_buffer mbuf;
+ t_u32 sdio_ireg = 0;
+ t_u8 offset = 0;
+ t_u8 max_mp_regs = pmadapter->pcard_sd->reg->max_mp_regs;
+ t_u8 host_int_status_reg =
+ pmadapter->pcard_sd->reg->host_int_status_reg;
+
+ ENTER();
+
+ while (max_mp_regs) {
+ memset(pmadapter, &mbuf, 0, sizeof(mlan_buffer));
+ mbuf.pbuf = pmadapter->pcard_sd->mp_regs + offset;
+ mbuf.data_len = MIN(max_mp_regs, MLAN_SDIO_BLOCK_SIZE);
+
+ if (MLAN_STATUS_SUCCESS !=
+ pcb->moal_read_data_sync(pmadapter->pmoal_handle, &mbuf,
+ (REG_PORT + offset) |
+ MLAN_SDIO_BYTE_MODE_MASK,
+ 0)) {
+ PRINTM(MERROR,
+ "moal_read_data_sync: read registers failed\n");
+ pmadapter->dbg.num_int_read_failure++;
+ goto done;
+ }
+ offset += mbuf.data_len;
+ max_mp_regs -= mbuf.data_len;
+ }
+
+ DBG_HEXDUMP(MIF_D, "SDIO MP Registers", pmadapter->pcard_sd->mp_regs,
+ max_mp_regs);
+ sdio_ireg = pmadapter->pcard_sd->mp_regs[host_int_status_reg];
+ pmadapter->dbg.last_int_status = pmadapter->ireg | sdio_ireg;
+ if (sdio_ireg) {
+ /*
+ * DN_LD_HOST_INT_STATUS and/or UP_LD_HOST_INT_STATUS
+ * DN_LD_CMD_PORT_HOST_INT_STATUS and/or
+ * UP_LD_CMD_PORT_HOST_INT_STATUS
+ * Clear the interrupt status register
+ */
+ PRINTM(MINTR, "wlan_interrupt: sdio_ireg = 0x%x\n", sdio_ireg);
+ pmadapter->pcard_sd->num_of_irq++;
+ pcb->moal_spin_lock(pmadapter->pmoal_handle,
+ pmadapter->pint_lock);
+ pmadapter->ireg |= sdio_ireg;
+ pcb->moal_spin_unlock(pmadapter->pmoal_handle,
+ pmadapter->pint_lock);
+ if (!pmadapter->pps_uapsd_mode &&
+ pmadapter->ps_state == PS_STATE_SLEEP) {
+ pmadapter->pm_wakeup_fw_try = MFALSE;
+ pmadapter->ps_state = PS_STATE_AWAKE;
+ pmadapter->pm_wakeup_card_req = MFALSE;
+ }
+ } else {
+ PRINTM(MMSG, "wlan_interrupt: sdio_ireg = 0x%x\n", sdio_ireg);
+ }
+done:
+ LEAVE();
+ return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ * @brief This function try to read the packet when fail to alloc rx buffer
+ *
+ * @param pmadapter A pointer to mlan_adapter structure
+ * @param port Current port on which packet needs to be rxed
+ * @param rx_len Length of received packet
+ * @return MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ */
+static mlan_status wlan_sdio_card_to_host_recovery(mlan_adapter *pmadapter,
+ t_u8 port, t_u16 rx_len)
+{
+ mlan_buffer mbuf;
+ t_u32 pkt_type = 0;
+ mlan_status ret = MLAN_STATUS_FAILURE;
+ ENTER();
+
+ if (MP_RX_AGGR_IN_PROGRESS(pmadapter)) {
+ PRINTM(MDATA, "Recovery:do Rx Aggr\n");
+ /* do aggr RX now */
+ wlan_receive_mp_aggr_buf(pmadapter);
+ }
+ memset(pmadapter, &mbuf, 0, sizeof(mlan_buffer));
+ mbuf.pbuf = pmadapter->pcard_sd->rx_buf;
+ mbuf.data_len = rx_len;
+
+ PRINTM(MDATA, "Recovery: Try read port=%d rx_len=%d\n", port, rx_len);
+ if (MLAN_STATUS_SUCCESS !=
+ wlan_sdio_card_to_host(pmadapter, &pkt_type,
+ (t_u32 *)&pmadapter->upld_len, &mbuf, rx_len,
+ pmadapter->pcard_sd->ioport + port)) {
+ PRINTM(MERROR, "Recovery: Fail to do cmd53\n");
+ }
+ if (pkt_type != MLAN_TYPE_DATA && pkt_type != MLAN_TYPE_SPA_DATA) {
+ PRINTM(MERROR,
+ "Recovery: Receive a wrong pkt: type=%d, len=%d\n",
+ pkt_type, pmadapter->upld_len);
+ goto done;
+ }
+ if (pkt_type == MLAN_TYPE_DATA) {
+ // TODO fill the hole in Rx reorder table
+ PRINTM(MDATA, "Recovery: Drop Data packet\n");
+ pmadapter->dbg.num_pkt_dropped++;
+ } else if (pkt_type == MLAN_TYPE_SPA_DATA) {
+ PRINTM(MDATA, "Recovery: SPA Data packet len=%d\n",
+ pmadapter->upld_len);
+ wlan_decode_spa_buffer(pmadapter, pmadapter->pcard_sd->rx_buf,
+ pmadapter->upld_len);
+ pmadapter->data_received = MTRUE;
+ }
+ PRINTM(MMSG, "wlan: Success handle rx port=%d, rx_len=%d \n", port,
+ rx_len);
+ ret = MLAN_STATUS_SUCCESS;
+done:
+ LEAVE();
+ return ret;
+}
+
+/**
+ * @brief This function checks the interrupt status and handle it accordingly.
+ *
+ * @param pmadapter A pointer to mlan_adapter structure
+ * @return MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ */
+mlan_status wlan_process_sdio_int_status(mlan_adapter *pmadapter)
+{
+ mlan_status ret = MLAN_STATUS_SUCCESS;
+ pmlan_callbacks pcb = &pmadapter->callbacks;
+ t_u8 sdio_ireg;
+ mlan_buffer *pmbuf = MNULL;
+
+ t_u8 port = 0;
+ t_u32 len_reg_l, len_reg_u;
+ t_u32 rx_blocks;
+ t_u8 bit_count = 0;
+ t_u32 ps_state = pmadapter->ps_state;
+ t_u16 rx_len;
+ t_u32 upld_typ = 0;
+ t_u32 cr = 0;
+ const mlan_sdio_card_reg *reg = pmadapter->pcard_sd->reg;
+ t_u8 rd_len_p0_l = reg->rd_len_p0_l;
+ t_u8 rd_len_p0_u = reg->rd_len_p0_u;
+ t_u8 cmd_rd_len_0 = reg->cmd_rd_len_0;
+ t_u8 cmd_rd_len_1 = reg->cmd_rd_len_1;
+
+ ENTER();
+
+ pcb->moal_spin_lock(pmadapter->pmoal_handle, pmadapter->pint_lock);
+ sdio_ireg = (t_u8)pmadapter->ireg;
+ pmadapter->ireg = 0;
+ pcb->moal_spin_unlock(pmadapter->pmoal_handle, pmadapter->pint_lock);
+
+ if (!sdio_ireg)
+ goto done;
+
+ /* check the command port */
+ if (sdio_ireg & DN_LD_CMD_PORT_HOST_INT_STATUS) {
+ if (pmadapter->cmd_sent)
+ pmadapter->cmd_sent = MFALSE;
+
+ PRINTM(MINFO, "cmd_sent=%d\n", pmadapter->cmd_sent);
+ }
+
+ if (sdio_ireg & UP_LD_CMD_PORT_HOST_INT_STATUS) {
+ /* read the len of control packet */
+ rx_len = ((t_u16)pmadapter->pcard_sd->mp_regs[cmd_rd_len_1])
+ << 8;
+ rx_len |= (t_u16)pmadapter->pcard_sd->mp_regs[cmd_rd_len_0];
+ PRINTM(MINFO, "RX: cmd port rx_len=%u\n", rx_len);
+ rx_blocks = (rx_len + MLAN_SDIO_BLOCK_SIZE - 1) /
+ MLAN_SDIO_BLOCK_SIZE;
+ if (rx_len <= SDIO_INTF_HEADER_LEN ||
+ (rx_blocks * MLAN_SDIO_BLOCK_SIZE) > ALLOC_BUF_SIZE) {
+ PRINTM(MERROR, "invalid rx_len=%d\n", rx_len);
+ ret = MLAN_STATUS_FAILURE;
+ goto done;
+ }
+ rx_len = (t_u16)(rx_blocks * MLAN_SDIO_BLOCK_SIZE);
+ pmbuf = wlan_alloc_mlan_buffer(pmadapter, rx_len, 0,
+ MOAL_MALLOC_BUFFER);
+ if (pmbuf == MNULL) {
+ PRINTM(MERROR, "Failed to allocate 'mlan_buffer'\n");
+ ret = MLAN_STATUS_FAILURE;
+ goto done;
+ }
+ PRINTM(MINFO, "cmd rx buffer rx_len = %d\n", rx_len);
+
+ /* Transfer data from card */
+ if (MLAN_STATUS_SUCCESS !=
+ wlan_sdio_card_to_host(
+ pmadapter, &upld_typ, (t_u32 *)&pmadapter->upld_len,
+ pmbuf, rx_len,
+ pmadapter->pcard_sd->ioport | CMD_PORT_SLCT)) {
+ pmadapter->dbg.num_cmdevt_card_to_host_failure++;
+ PRINTM(MERROR,
+ "Card-to-host cmd failed: int status=0x%x\n",
+ sdio_ireg);
+ wlan_free_mlan_buffer(pmadapter, pmbuf);
+ ret = MLAN_STATUS_FAILURE;
+ goto term_cmd53;
+ }
+
+ if ((upld_typ != MLAN_TYPE_CMD) &&
+ (upld_typ != MLAN_TYPE_EVENT))
+ PRINTM(MERROR,
+ "receive a wrong packet from CMD PORT. type =0x%x\n",
+ upld_typ);
+
+ wlan_decode_rx_packet(pmadapter, pmbuf, upld_typ, MFALSE);
+
+ /* We might receive data/sleep_cfm at the same time */
+ /* reset data_receive flag to avoid ps_state change */
+ if ((ps_state == PS_STATE_SLEEP_CFM) &&
+ (pmadapter->ps_state == PS_STATE_SLEEP))
+ pmadapter->data_received = MFALSE;
+ }
+
+ if (sdio_ireg & DN_LD_HOST_INT_STATUS) {
+ if (pmadapter->pcard_sd->mp_wr_bitmap &
+ pmadapter->pcard_sd->mp_data_port_mask)
+ pmadapter->pcard_sd->mp_invalid_update++;
+ pmadapter->pcard_sd->mp_wr_bitmap =
+ (t_u32)pmadapter->pcard_sd->mp_regs[reg->wr_bitmap_l];
+ pmadapter->pcard_sd->mp_wr_bitmap |=
+ ((t_u32)pmadapter->pcard_sd->mp_regs[reg->wr_bitmap_u])
+ << 8;
+ pmadapter->pcard_sd->mp_wr_bitmap |=
+ ((t_u32)pmadapter->pcard_sd->mp_regs[reg->wr_bitmap_1l])
+ << 16;
+ pmadapter->pcard_sd->mp_wr_bitmap |=
+ ((t_u32)pmadapter->pcard_sd->mp_regs[reg->wr_bitmap_1u])
+ << 24;
+ bit_count = bitcount(pmadapter->pcard_sd->mp_wr_bitmap &
+ pmadapter->pcard_sd->mp_data_port_mask);
+ if (bit_count) {
+ pmadapter->pcard_sd->mp_update[bit_count - 1]++;
+ if (pmadapter->pcard_sd->mp_update[bit_count - 1] ==
+ 0xffffffff)
+ memset(pmadapter,
+ pmadapter->pcard_sd->mp_update, 0,
+ sizeof(pmadapter->pcard_sd->mp_update));
+ }
+
+ pmadapter->pcard_sd->last_recv_wr_bitmap =
+ pmadapter->pcard_sd->mp_wr_bitmap;
+ PRINTM(MINTR, "DNLD: wr_bitmap=0x%08x\n",
+ pmadapter->pcard_sd->mp_wr_bitmap);
+ if (pmadapter->data_sent &&
+ (pmadapter->pcard_sd->mp_wr_bitmap &
+ (1 << pmadapter->pcard_sd->curr_wr_port))) {
+ PRINTM(MINFO, " <--- Tx DONE Interrupt --->\n");
+ pmadapter->data_sent = MFALSE;
+ }
+ }
+
+ if (sdio_ireg & UP_LD_HOST_INT_STATUS) {
+ pmadapter->pcard_sd->mp_rd_bitmap =
+ (t_u32)pmadapter->pcard_sd->mp_regs[reg->rd_bitmap_l];
+ pmadapter->pcard_sd->mp_rd_bitmap |=
+ ((t_u32)pmadapter->pcard_sd->mp_regs[reg->rd_bitmap_u])
+ << 8;
+ pmadapter->pcard_sd->mp_rd_bitmap |=
+ ((t_u32)pmadapter->pcard_sd->mp_regs[reg->rd_bitmap_1l])
+ << 16;
+ pmadapter->pcard_sd->mp_rd_bitmap |=
+ ((t_u32)pmadapter->pcard_sd->mp_regs[reg->rd_bitmap_1u])
+ << 24;
+ PRINTM(MINTR, "UPLD: rd_bitmap=0x%08x\n",
+ pmadapter->pcard_sd->mp_rd_bitmap);
+
+ while (MTRUE) {
+ ret = wlan_get_rd_port(pmadapter, &port);
+ if (ret != MLAN_STATUS_SUCCESS) {
+ PRINTM(MINFO,
+ "no more rd_port to be handled\n");
+ break;
+ }
+ len_reg_l = rd_len_p0_l + (port << 1);
+ len_reg_u = rd_len_p0_u + (port << 1);
+ rx_len =
+ ((t_u16)pmadapter->pcard_sd->mp_regs[len_reg_u])
+ << 8;
+ rx_len |=
+ (t_u16)pmadapter->pcard_sd->mp_regs[len_reg_l];
+ PRINTM(MINFO, "RX: port=%d rx_len=%u\n", port, rx_len);
+ rx_blocks = (rx_len + MLAN_SDIO_BLOCK_SIZE - 1) /
+ MLAN_SDIO_BLOCK_SIZE;
+ if (rx_len <= SDIO_INTF_HEADER_LEN ||
+ (rx_blocks * MLAN_SDIO_BLOCK_SIZE) >
+ pmadapter->pcard_sd->mpa_rx.buf_size) {
+ PRINTM(MERROR, "invalid rx_len=%d\n", rx_len);
+ ret = MLAN_STATUS_FAILURE;
+ goto done;
+ }
+ rx_len = (t_u16)(rx_blocks * MLAN_SDIO_BLOCK_SIZE);
+ if (rx_len > MRVDRV_ETH_RX_PACKET_BUFFER_SIZE)
+ pmbuf = wlan_alloc_mlan_buffer(
+ pmadapter, rx_len, 0,
+ MOAL_MALLOC_BUFFER);
+ else
+ pmbuf = wlan_alloc_mlan_buffer(
+ pmadapter, rx_len, MLAN_RX_HEADER_LEN,
+ MOAL_ALLOC_MLAN_BUFFER);
+ if (pmbuf == MNULL) {
+ PRINTM(MERROR,
+ "Failed to allocate 'mlan_buffer'\n");
+ pmadapter->dbg.num_alloc_buffer_failure++;
+ if (MLAN_STATUS_SUCCESS ==
+ wlan_sdio_card_to_host_recovery(
+ pmadapter, port, rx_len))
+ continue;
+ ret = MLAN_STATUS_FAILURE;
+ goto done;
+ }
+ PRINTM(MINFO, "rx_len = %d\n", rx_len);
+ if (MLAN_STATUS_SUCCESS !=
+ wlan_sdio_card_to_host_mp_aggr(pmadapter, pmbuf,
+ port, rx_len)) {
+ pmadapter->dbg.num_rx_card_to_host_failure++;
+
+ PRINTM(MERROR,
+ "Card to host failed: int status=0x%x\n",
+ sdio_ireg);
+ ret = MLAN_STATUS_FAILURE;
+ goto term_cmd53;
+ }
+ }
+ /* We might receive data/sleep_cfm at the same time */
+ /* reset data_receive flag to avoid ps_state change */
+ if ((ps_state == PS_STATE_SLEEP_CFM) &&
+ (pmadapter->ps_state == PS_STATE_SLEEP))
+ pmadapter->data_received = MFALSE;
+ }
+
+ ret = MLAN_STATUS_SUCCESS;
+ goto done;
+
+term_cmd53:
+ /* terminate cmd53 */
+ if (MLAN_STATUS_SUCCESS != pcb->moal_read_reg(pmadapter->pmoal_handle,
+ HOST_TO_CARD_EVENT_REG,
+ &cr))
+ PRINTM(MERROR, "read CFG reg failed\n");
+ PRINTM(MINFO, "Config Reg val = %d\n", cr);
+ if (MLAN_STATUS_SUCCESS != pcb->moal_write_reg(pmadapter->pmoal_handle,
+ HOST_TO_CARD_EVENT_REG,
+ (cr | HOST_TERM_CMD53)))
+ PRINTM(MERROR, "write CFG reg failed\n");
+ PRINTM(MINFO, "write success\n");
+ if (MLAN_STATUS_SUCCESS != pcb->moal_read_reg(pmadapter->pmoal_handle,
+ HOST_TO_CARD_EVENT_REG,
+ &cr))
+ PRINTM(MERROR, "read CFG reg failed\n");
+ PRINTM(MINFO, "Config reg val =%x\n", cr);
+
+done:
+ LEAVE();
+ return ret;
+}
+
+/**
+ * @brief This function sends data to the card.
+ *
+ * @param pmadapter A pointer to mlan_adapter structure
+ * @param type data or command
+ * @param pmbuf A pointer to mlan_buffer (pmbuf->data_len should include
+ * SDIO header)
+ * @param tx_param A pointer to mlan_tx_param
+ * @return MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ */
+mlan_status wlan_sdio_host_to_card(mlan_adapter *pmadapter, t_u8 type,
+ mlan_buffer *pmbuf, mlan_tx_param *tx_param)
+{
+ mlan_status ret = MLAN_STATUS_SUCCESS;
+ t_u32 buf_block_len;
+ t_u32 blksz;
+ t_u8 port = 0;
+ t_u32 cmd53_port = 0;
+ t_u8 *payload = pmbuf->pbuf + pmbuf->data_offset;
+
+ ENTER();
+
+ /* Allocate buffer and copy payload */
+ blksz = MLAN_SDIO_BLOCK_SIZE;
+ buf_block_len = (pmbuf->data_len + blksz - 1) / blksz;
+ *(t_u16 *)&payload[0] = wlan_cpu_to_le16((t_u16)pmbuf->data_len);
+ *(t_u16 *)&payload[2] = wlan_cpu_to_le16(type);
+
+ /*
+ * This is SDIO specific header
+ * t_u16 length,
+ * t_u16 type (MLAN_TYPE_DATA = 0,
+ * MLAN_TYPE_CMD = 1, MLAN_TYPE_EVENT = 3)
+ */
+ if (type == MLAN_TYPE_DATA) {
+ ret = wlan_get_wr_port_data(pmadapter, &port);
+ if (ret != MLAN_STATUS_SUCCESS) {
+ PRINTM(MERROR,
+ "no wr_port available: wr_bitmap=0x%08x curr_wr_port=%d\n",
+ pmadapter->pcard_sd->mp_wr_bitmap,
+ pmadapter->pcard_sd->curr_wr_port);
+ goto exit;
+ }
+ /* Transfer data to card */
+ pmbuf->data_len = buf_block_len * blksz;
+
+ if (tx_param)
+ ret = wlan_host_to_card_mp_aggr(pmadapter, pmbuf, port,
+ tx_param->next_pkt_len);
+ else
+ ret = wlan_host_to_card_mp_aggr(pmadapter, pmbuf, port,
+ 0);
+ } else {
+ /*Type must be MLAN_TYPE_CMD*/
+ pmadapter->cmd_sent = MTRUE;
+ if (pmbuf->data_len <= SDIO_INTF_HEADER_LEN ||
+ pmbuf->data_len > WLAN_UPLD_SIZE)
+ PRINTM(MWARN,
+ "wlan_sdio_host_to_card(): Error: payload=%p, nb=%d\n",
+ payload, pmbuf->data_len);
+ /* Transfer data to card */
+ pmbuf->data_len = buf_block_len * blksz;
+ cmd53_port = (pmadapter->pcard_sd->ioport) | CMD_PORT_SLCT;
+ ret = wlan_write_data_sync(pmadapter, pmbuf, cmd53_port);
+ }
+
+ if (ret == MLAN_STATUS_FAILURE) {
+ PRINTM(MERROR, "Error: host_to_card failed: 0x%X\n", ret);
+ if (type == MLAN_TYPE_CMD)
+ pmadapter->cmd_sent = MFALSE;
+ if (type == MLAN_TYPE_DATA)
+ pmadapter->data_sent = MFALSE;
+ } else {
+ if (type == MLAN_TYPE_DATA) {
+ if (!(pmadapter->pcard_sd->mp_wr_bitmap &
+ (1 << pmadapter->pcard_sd->curr_wr_port)))
+ pmadapter->data_sent = MTRUE;
+ else
+ pmadapter->data_sent = MFALSE;
+ }
+ DBG_HEXDUMP(MIF_D, "SDIO Blk Wr",
+ pmbuf->pbuf + pmbuf->data_offset,
+ MIN(pmbuf->data_len, MAX_DATA_DUMP_LEN));
+ }
+exit:
+ LEAVE();
+ return ret;
+}
+
+#if (defined(SD9098) || defined(SD9097))
+/**
+ * @brief This function sends vdll data to the card.
+ *
+ * @param pmadapter A pointer to mlan_adapter structure
+ * @param pmbuf A pointer to mlan_buffer (pmbuf->data_len should include
+ * SDIO header)
+ * @return MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ */
+mlan_status wlan_sdio_send_vdll(mlan_adapter *pmadapter, mlan_buffer *pmbuf)
+{
+ mlan_status ret = MLAN_STATUS_SUCCESS;
+ t_u32 buf_block_len;
+ t_u32 blksz;
+ t_u8 *payload = pmbuf->pbuf + pmbuf->data_offset;
+ t_u32 cmd53_port = 0;
+ ENTER();
+ blksz = MLAN_SDIO_BLOCK_SIZE;
+ buf_block_len = (pmbuf->data_len + blksz - 1) / blksz;
+
+ *(t_u16 *)&payload[0] = wlan_cpu_to_le16((t_u16)pmbuf->data_len);
+ *(t_u16 *)&payload[2] = wlan_cpu_to_le16(MLAN_TYPE_VDLL);
+
+ pmbuf->data_len = buf_block_len * blksz;
+
+ if (pmbuf->data_len > MRVDRV_SIZE_OF_CMD_BUFFER) {
+ PRINTM(MERROR, "VDLL block is too big: %d\n", pmbuf->data_len);
+ return MLAN_STATUS_FAILURE;
+ }
+ cmd53_port = (pmadapter->pcard_sd->ioport) | CMD_PORT_SLCT;
+ pmadapter->cmd_sent = MTRUE;
+ ret = wlan_write_data_sync(pmadapter, pmbuf, cmd53_port);
+ if (ret == MLAN_STATUS_FAILURE)
+ PRINTM(MERROR, "Send Vdll: host_to_card failed: 0x%X\n", ret);
+ else
+ DBG_HEXDUMP(MIF_D, "SDIO Blk Wr",
+ pmbuf->pbuf + pmbuf->data_offset,
+ MIN(pmbuf->data_len, MAX_DATA_DUMP_LEN));
+ LEAVE();
+ return ret;
+}
+#endif
+
+/**
+ * @brief This function sends data to the card.
+ *
+ * @param pmpriv A pointer to mlan_private structure
+ * @param type data or command
+ * @param pmbuf A pointer to mlan_buffer (pmbuf->data_len should include
+ * SDIO header)
+ * @param tx_param A pointer to mlan_tx_param
+ * @return MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ */
+mlan_status wlan_sdio_host_to_card_ext(pmlan_private pmpriv, t_u8 type,
+ mlan_buffer *pmbuf,
+ mlan_tx_param *tx_param)
+{
+ mlan_status ret = MLAN_STATUS_SUCCESS;
+ mlan_adapter *pmadapter = pmpriv->adapter;
+
+#if (defined(SD9098) || defined(SD9097))
+ if (type == MLAN_TYPE_VDLL)
+ return wlan_sdio_send_vdll(pmadapter, pmbuf);
+#endif
+ ret = wlan_sdio_host_to_card(pmadapter, type, pmbuf, tx_param);
+
+ if (type == MLAN_TYPE_DATA && ret == MLAN_STATUS_FAILURE)
+ pmadapter->data_sent = MFALSE;
+
+ LEAVE();
+ return ret;
+}
+
+/**
+ * @brief Deaggregate single port aggregation packet
+ *
+ * @param pmadapter A pointer to mlan_adapter structure
+ * @param buf A pointer to aggregated data packet
+ * @param len
+ *
+ * @return N/A
+ */
+void wlan_decode_spa_buffer(mlan_adapter *pmadapter, t_u8 *buf, t_u32 len)
+{
+ int total_pkt_len;
+ t_u8 block_num = 0;
+ t_u16 block_size = 0;
+ t_u8 *data;
+ t_u32 pkt_len, pkt_type = 0;
+ mlan_buffer *mbuf_deaggr = MNULL;
+
+ ENTER();
+
+ data = (t_u8 *)buf;
+ total_pkt_len = len;
+ if (total_pkt_len < pmadapter->pcard_sd->sdio_rx_block_size) {
+ PRINTM(MERROR, "Invalid sp aggr packet size=%d\n",
+ total_pkt_len);
+ goto done;
+ }
+ while (total_pkt_len >=
+ (OFFSET_OF_SDIO_HEADER + SDIO_INTF_HEADER_LEN)) {
+ block_num = *(data + OFFSET_OF_BLOCK_NUMBER);
+ block_size =
+ pmadapter->pcard_sd->sdio_rx_block_size * block_num;
+ if (block_size > total_pkt_len) {
+ PRINTM(MERROR,
+ "Error in pkt, block_num=%d, pkt_len=%d\n",
+ block_num, total_pkt_len);
+ break;
+ }
+ pkt_len = wlan_le16_to_cpu(
+ *(t_u16 *)(data + OFFSET_OF_SDIO_HEADER));
+ pkt_type = wlan_le16_to_cpu(
+ *(t_u16 *)(data + OFFSET_OF_SDIO_HEADER + 2));
+ if ((pkt_len + OFFSET_OF_SDIO_HEADER) > block_size) {
+ PRINTM(MERROR,
+ "Error in pkt, pkt_len=%d, block_size=%d\n",
+ pkt_len, block_size);
+ break;
+ }
+ mbuf_deaggr = wlan_alloc_mlan_buffer(
+ pmadapter, pkt_len - SDIO_INTF_HEADER_LEN,
+ MLAN_RX_HEADER_LEN, MOAL_ALLOC_MLAN_BUFFER);
+ if (mbuf_deaggr == MNULL) {
+ PRINTM(MERROR, "Error allocating daggr mlan_buffer\n");
+ break;
+ }
+ memcpy_ext(pmadapter,
+ mbuf_deaggr->pbuf + mbuf_deaggr->data_offset,
+ data + OFFSET_OF_SDIO_HEADER + SDIO_INTF_HEADER_LEN,
+ pkt_len - SDIO_INTF_HEADER_LEN,
+ pkt_len - SDIO_INTF_HEADER_LEN);
+ mbuf_deaggr->data_len = pkt_len - SDIO_INTF_HEADER_LEN;
+ wlan_handle_rx_packet(pmadapter, mbuf_deaggr);
+ data += block_size;
+ total_pkt_len -= block_size;
+ if (total_pkt_len < pmadapter->pcard_sd->sdio_rx_block_size)
+ break;
+ }
+done:
+ LEAVE();
+ return;
+}
+
+/**
+ * @brief This function deaggr rx pkt
+ *
+ * @param pmadapter A pointer to mlan_adapter structure
+ * @param pmbuf A pointer to the SDIO mpa data
+ * @return N/A
+ */
+t_void wlan_sdio_deaggr_rx_pkt(pmlan_adapter pmadapter, mlan_buffer *pmbuf)
+{
+ if (pmbuf->buf_type == MLAN_BUF_TYPE_SPA_DATA) {
+ wlan_decode_spa_buffer(pmadapter,
+ pmbuf->pbuf + pmbuf->data_offset,
+ pmbuf->data_len);
+ wlan_free_mlan_buffer(pmadapter, pmbuf);
+ } else
+ wlan_handle_rx_packet(pmadapter, pmbuf);
+}
+
+/**
+ * @brief This function allocates buffer for the SDIO aggregation buffer
+ * related members of adapter structure
+ *
+ * @param pmadapter A pointer to mlan_adapter structure
+ * @param mpa_tx_buf_size Tx buffer size to allocate
+ * @param mpa_rx_buf_size Rx buffer size to allocate
+ *
+ * @return MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ */
+mlan_status wlan_alloc_sdio_mpa_buffers(mlan_adapter *pmadapter,
+ t_u32 mpa_tx_buf_size,
+ t_u32 mpa_rx_buf_size)
+{
+ mlan_status ret = MLAN_STATUS_SUCCESS;
+ pmlan_callbacks pcb = &pmadapter->callbacks;
+ t_u8 mp_aggr_pkt_limit = SDIO_MP_AGGR_DEF_PKT_LIMIT;
+
+ ENTER();
+
+ if ((pmadapter->pcard_sd->max_segs < mp_aggr_pkt_limit) ||
+ (pmadapter->pcard_sd->max_seg_size <
+ pmadapter->pcard_sd->max_sp_tx_size)) {
+ ret = pcb->moal_malloc(
+ pmadapter->pmoal_handle,
+ mpa_tx_buf_size + DMA_ALIGNMENT,
+ MLAN_MEM_DEF | MLAN_MEM_DMA,
+ (t_u8 **)&pmadapter->pcard_sd->mpa_tx.head_ptr);
+ if (ret != MLAN_STATUS_SUCCESS ||
+ !pmadapter->pcard_sd->mpa_tx.head_ptr) {
+ PRINTM(MERROR,
+ "Could not allocate buffer for SDIO MP TX aggr\n");
+ ret = MLAN_STATUS_FAILURE;
+ goto error;
+ }
+ pmadapter->pcard_sd->mpa_tx.buf = (t_u8 *)ALIGN_ADDR(
+ pmadapter->pcard_sd->mpa_tx.head_ptr, DMA_ALIGNMENT);
+ } else {
+ PRINTM(MMSG, "wlan: Enable TX SG mode\n");
+ pmadapter->pcard_sd->mpa_tx.head_ptr = MNULL;
+ pmadapter->pcard_sd->mpa_tx.buf = MNULL;
+ }
+ pmadapter->pcard_sd->mpa_tx.buf_size = mpa_tx_buf_size;
+
+ if ((pmadapter->pcard_sd->max_segs < mp_aggr_pkt_limit) ||
+ (pmadapter->pcard_sd->max_seg_size <
+ pmadapter->pcard_sd->max_sp_rx_size)) {
+ ret = pcb->moal_malloc(
+ pmadapter->pmoal_handle,
+ mpa_rx_buf_size + DMA_ALIGNMENT,
+ MLAN_MEM_DEF | MLAN_MEM_DMA,
+ (t_u8 **)&pmadapter->pcard_sd->mpa_rx.head_ptr);
+ if (ret != MLAN_STATUS_SUCCESS ||
+ !pmadapter->pcard_sd->mpa_rx.head_ptr) {
+ PRINTM(MERROR,
+ "Could not allocate buffer for SDIO MP RX aggr\n");
+ ret = MLAN_STATUS_FAILURE;
+ goto error;
+ }
+ pmadapter->pcard_sd->mpa_rx.buf = (t_u8 *)ALIGN_ADDR(
+ pmadapter->pcard_sd->mpa_rx.head_ptr, DMA_ALIGNMENT);
+ } else {
+ PRINTM(MMSG, "wlan: Enable RX SG mode\n");
+ pmadapter->pcard_sd->mpa_rx.head_ptr = MNULL;
+ pmadapter->pcard_sd->mpa_rx.buf = MNULL;
+ }
+ pmadapter->pcard_sd->mpa_rx.buf_size = mpa_rx_buf_size;
+error:
+ if (ret != MLAN_STATUS_SUCCESS)
+ wlan_free_sdio_mpa_buffers(pmadapter);
+
+ LEAVE();
+ return ret;
+}
+
+/**
+ * @brief This function frees buffers for the SDIO aggregation
+ *
+ * @param pmadapter A pointer to mlan_adapter structure
+ *
+ * @return MLAN_STATUS_SUCCESS
+ */
+mlan_status wlan_free_sdio_mpa_buffers(mlan_adapter *pmadapter)
+{
+ pmlan_callbacks pcb = &pmadapter->callbacks;
+
+ ENTER();
+
+ if (pmadapter->pcard_sd->mpa_tx.buf) {
+ pcb->moal_mfree(pmadapter->pmoal_handle,
+ (t_u8 *)pmadapter->pcard_sd->mpa_tx.head_ptr);
+ pmadapter->pcard_sd->mpa_tx.head_ptr = MNULL;
+ pmadapter->pcard_sd->mpa_tx.buf = MNULL;
+ pmadapter->pcard_sd->mpa_tx.buf_size = 0;
+ }
+
+ if (pmadapter->pcard_sd->mpa_rx.buf) {
+ pcb->moal_mfree(pmadapter->pmoal_handle,
+ (t_u8 *)pmadapter->pcard_sd->mpa_rx.head_ptr);
+ pmadapter->pcard_sd->mpa_rx.head_ptr = MNULL;
+ pmadapter->pcard_sd->mpa_rx.buf = MNULL;
+ pmadapter->pcard_sd->mpa_rx.buf_size = 0;
+ }
+
+ LEAVE();
+ return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ * @brief This function re-allocate rx mpa buffer
+ *
+ * @param pmadapter A pointer to mlan_adapter structure
+ *
+ * @return MLAN_STATUS_SUCCESS
+ */
+mlan_status wlan_re_alloc_sdio_rx_mpa_buffer(mlan_adapter *pmadapter)
+{
+ mlan_status ret = MLAN_STATUS_SUCCESS;
+ pmlan_callbacks pcb = &pmadapter->callbacks;
+ t_u8 mp_aggr_pkt_limit = SDIO_MP_AGGR_DEF_PKT_LIMIT;
+ t_u32 mpa_rx_buf_size = SDIO_MP_AGGR_BUF_SIZE_MAX;
+
+ if (pmadapter->pcard_sd->mpa_rx.buf) {
+ pcb->moal_mfree(pmadapter->pmoal_handle,
+ (t_u8 *)pmadapter->pcard_sd->mpa_rx.head_ptr);
+ pmadapter->pcard_sd->mpa_rx.head_ptr = MNULL;
+ pmadapter->pcard_sd->mpa_rx.buf = MNULL;
+ pmadapter->pcard_sd->mpa_rx.buf_size = 0;
+ }
+ if (pmadapter->pcard_sd->sdio_rx_aggr_enable) {
+ mpa_rx_buf_size = MAX(mpa_rx_buf_size, SDIO_CMD53_MAX_SIZE);
+ /** reallocate rx buffer for recover when single port rx
+ * aggregation enabled */
+ if (pmadapter->pcard_sd->rx_buffer) {
+ pcb->moal_mfree(pmadapter->pmoal_handle,
+ (t_u8 *)pmadapter->pcard_sd->rx_buffer);
+ pmadapter->pcard_sd->rx_buffer = MNULL;
+ pmadapter->pcard_sd->rx_buf = MNULL;
+ }
+ ret = pmadapter->callbacks.moal_malloc(
+ pmadapter->pmoal_handle,
+ SDIO_CMD53_MAX_SIZE + DMA_ALIGNMENT,
+ MLAN_MEM_DEF | MLAN_MEM_DMA,
+ (t_u8 **)&pmadapter->pcard_sd->rx_buffer);
+
+ if (ret != MLAN_STATUS_SUCCESS ||
+ !pmadapter->pcard_sd->rx_buffer) {
+ PRINTM(MERROR, "Failed to allocate receive buffer\n");
+ ret = MLAN_STATUS_FAILURE;
+ goto error;
+ }
+ pmadapter->pcard_sd->rx_buf = (t_u8 *)ALIGN_ADDR(
+ pmadapter->pcard_sd->rx_buffer, DMA_ALIGNMENT);
+ }
+ if ((pmadapter->pcard_sd->max_segs < mp_aggr_pkt_limit) ||
+ (pmadapter->pcard_sd->max_seg_size <
+ pmadapter->pcard_sd->max_sp_rx_size)) {
+ ret = pcb->moal_malloc(
+ pmadapter->pmoal_handle,
+ mpa_rx_buf_size + DMA_ALIGNMENT,
+ MLAN_MEM_DEF | MLAN_MEM_DMA,
+ (t_u8 **)&pmadapter->pcard_sd->mpa_rx.head_ptr);
+ if (ret != MLAN_STATUS_SUCCESS ||
+ !pmadapter->pcard_sd->mpa_rx.head_ptr) {
+ PRINTM(MERROR,
+ "Could not allocate buffer for SDIO MP RX aggr\n");
+ ret = MLAN_STATUS_FAILURE;
+ goto error;
+ }
+ pmadapter->pcard_sd->mpa_rx.buf = (t_u8 *)ALIGN_ADDR(
+ pmadapter->pcard_sd->mpa_rx.head_ptr, DMA_ALIGNMENT);
+ } else {
+ PRINTM(MMSG, "wlan: Enable RX SG mode\n");
+ pmadapter->pcard_sd->mpa_rx.head_ptr = MNULL;
+ pmadapter->pcard_sd->mpa_rx.buf = MNULL;
+ }
+ pmadapter->pcard_sd->mpa_rx.buf_size = mpa_rx_buf_size;
+ PRINTM(MMSG, "mpa_rx_buf_size=%d\n", mpa_rx_buf_size);
+error:
+ return ret;
+}
+
+/**
+ * @brief This function wakes up the card.
+ *
+ * @param pmadapter A pointer to mlan_adapter structure
+ * @param timeout set timeout flag
+ *
+ * @return MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ */
+mlan_status wlan_pm_sdio_wakeup_card(pmlan_adapter pmadapter, t_u8 timeout)
+{
+ mlan_status ret = MLAN_STATUS_SUCCESS;
+ t_u32 age_ts_usec;
+ pmlan_callbacks pcb = &pmadapter->callbacks;
+
+ ENTER();
+ PRINTM(MEVENT, "Wakeup device...\n");
+ pmadapter->callbacks.moal_get_system_time(pmadapter->pmoal_handle,
+ &pmadapter->pm_wakeup_in_secs,
+ &age_ts_usec);
+
+ if (timeout) {
+ pmadapter->callbacks.moal_start_timer(
+ pmadapter->pmoal_handle, pmadapter->pwakeup_fw_timer,
+ MFALSE, MRVDRV_TIMER_3S);
+ pmadapter->wakeup_fw_timer_is_set = MTRUE;
+ }
+
+ ret = pcb->moal_write_reg(pmadapter->pmoal_handle,
+ HOST_TO_CARD_EVENT_REG, HOST_POWER_UP);
+
+ LEAVE();
+ return ret;
+}
+
+/**
+ * @brief This function resets the PM setting of the card.
+ *
+ * @param pmadapter A pointer to mlan_adapter structure
+ *
+ * @return MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ */
+mlan_status wlan_pm_sdio_reset_card(pmlan_adapter pmadapter)
+{
+ mlan_status ret = MLAN_STATUS_SUCCESS;
+ pmlan_callbacks pcb = &pmadapter->callbacks;
+
+ ENTER();
+
+ ret = pcb->moal_write_reg(pmadapter->pmoal_handle,
+ HOST_TO_CARD_EVENT_REG, 0);
+
+ LEAVE();
+ return ret;
+}
+
+/**
+ * @brief This function issues commands to initialize firmware
+ *
+ * @param priv A pointer to mlan_private structure
+ *
+ * @return MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ */
+mlan_status wlan_set_sdio_gpio_int(pmlan_private priv)
+{
+ mlan_status ret = MLAN_STATUS_SUCCESS;
+ pmlan_adapter pmadapter = MNULL;
+ HostCmd_DS_SDIO_GPIO_INT_CONFIG sdio_int_cfg;
+
+ if (!priv) {
+ LEAVE();
+ return MLAN_STATUS_FAILURE;
+ }
+ pmadapter = priv->adapter;
+
+ ENTER();
+
+ if (pmadapter->pcard_sd->int_mode == INT_MODE_GPIO) {
+ if (pmadapter->pcard_sd->gpio_pin != GPIO_INT_NEW_MODE) {
+ PRINTM(MINFO,
+ "SDIO_GPIO_INT_CONFIG: interrupt mode is GPIO\n");
+ sdio_int_cfg.action = HostCmd_ACT_GEN_SET;
+ sdio_int_cfg.gpio_pin = pmadapter->pcard_sd->gpio_pin;
+ sdio_int_cfg.gpio_int_edge = INT_FALLING_EDGE;
+ sdio_int_cfg.gpio_pulse_width = DELAY_1_US;
+ ret = wlan_prepare_cmd(priv,
+ HostCmd_CMD_SDIO_GPIO_INT_CONFIG,
+ HostCmd_ACT_GEN_SET, 0, MNULL,
+ &sdio_int_cfg);
+
+ if (ret) {
+ PRINTM(MERROR,
+ "SDIO_GPIO_INT_CONFIG: send command fail\n");
+ ret = MLAN_STATUS_FAILURE;
+ }
+ }
+ } else {
+ PRINTM(MINFO, "SDIO_GPIO_INT_CONFIG: interrupt mode is SDIO\n");
+ }
+
+ LEAVE();
+ return ret;
+}
+
+/**
+ * @brief This function prepares command of SDIO GPIO interrupt
+ *
+ * @param pmpriv A pointer to mlan_private structure
+ * @param cmd A pointer to HostCmd_DS_COMMAND structure
+ * @param cmd_action The action: GET or SET
+ * @param pdata_buf A pointer to data buffer
+ * @return MLAN_STATUS_SUCCESS
+ */
+mlan_status wlan_cmd_sdio_gpio_int(pmlan_private pmpriv,
+ HostCmd_DS_COMMAND *cmd, t_u16 cmd_action,
+ t_void *pdata_buf)
+{
+ HostCmd_DS_SDIO_GPIO_INT_CONFIG *psdio_gpio_int =
+ &cmd->params.sdio_gpio_int;
+
+ ENTER();
+
+ cmd->command = wlan_cpu_to_le16(HostCmd_CMD_SDIO_GPIO_INT_CONFIG);
+ cmd->size = wlan_cpu_to_le16((sizeof(HostCmd_DS_SDIO_GPIO_INT_CONFIG)) +
+ S_DS_GEN);
+
+ memset(pmpriv->adapter, psdio_gpio_int, 0,
+ sizeof(HostCmd_DS_SDIO_GPIO_INT_CONFIG));
+ if (cmd_action == HostCmd_ACT_GEN_SET) {
+ memcpy_ext(pmpriv->adapter, psdio_gpio_int, pdata_buf,
+ sizeof(HostCmd_DS_SDIO_GPIO_INT_CONFIG),
+ sizeof(HostCmd_DS_SDIO_GPIO_INT_CONFIG));
+ psdio_gpio_int->action =
+ wlan_cpu_to_le16(psdio_gpio_int->action);
+ psdio_gpio_int->gpio_pin =
+ wlan_cpu_to_le16(psdio_gpio_int->gpio_pin);
+ psdio_gpio_int->gpio_int_edge =
+ wlan_cpu_to_le16(psdio_gpio_int->gpio_int_edge);
+ psdio_gpio_int->gpio_pulse_width =
+ wlan_cpu_to_le16(psdio_gpio_int->gpio_pulse_width);
+ }
+
+ LEAVE();
+ return MLAN_STATUS_SUCCESS;
+}
+
+mlan_status wlan_reset_fw(pmlan_adapter pmadapter)
+{
+ t_u32 tries = 0;
+ t_u32 value = 1;
+ t_u32 reset_reg = pmadapter->pcard_sd->reg->fw_reset_reg;
+ t_u8 reset_val = pmadapter->pcard_sd->reg->fw_reset_val;
+ pmlan_callbacks pcb = &pmadapter->callbacks;
+ mlan_status ret = MLAN_STATUS_SUCCESS;
+
+ ENTER();
+ wlan_pm_sdio_wakeup_card(pmadapter, MFALSE);
+
+ /** wait SOC fully wake up */
+ for (tries = 0; tries < MAX_POLL_TRIES; ++tries) {
+ if (MLAN_STATUS_SUCCESS ==
+ pcb->moal_write_reg(pmadapter->pmoal_handle, reset_reg,
+ 0xba)) {
+ pcb->moal_read_reg(pmadapter->pmoal_handle, reset_reg,
+ &value);
+ if (value == 0xba) {
+ PRINTM(MMSG, "FW wake up\n");
+ break;
+ }
+ }
+ pcb->moal_udelay(pmadapter->pmoal_handle, 1000);
+ }
+ /* Write register to notify FW */
+ if (MLAN_STATUS_FAILURE == pcb->moal_write_reg(pmadapter->pmoal_handle,
+ reset_reg, reset_val)) {
+ PRINTM(MERROR, "Failed to write register.\n");
+ ret = MLAN_STATUS_FAILURE;
+ goto done;
+ }
+#if defined(SD8997) || defined(SD8977) || defined(SD8987) || \
+ defined(SD9098) || defined(SD9097) || defined(SD8978)
+ if (MFALSE
+#ifdef SD8997
+ || IS_SD8997(pmadapter->card_type)
+#endif
+#ifdef SD8977
+ || IS_SD8977(pmadapter->card_type)
+#endif
+#ifdef SD8978
+ || IS_SD8978(pmadapter->card_type)
+#endif
+#ifdef SD8987
+ || IS_SD8987(pmadapter->card_type)
+#endif
+#ifdef SD9098
+ || IS_SD9098(pmadapter->card_type)
+#endif
+#ifdef SD9097
+ || IS_SD9097(pmadapter->card_type)
+#endif
+ ) {
+ pcb->moal_read_reg(pmadapter->pmoal_handle,
+ HOST_TO_CARD_EVENT_REG, &value);
+ pcb->moal_write_reg(pmadapter->pmoal_handle,
+ HOST_TO_CARD_EVENT_REG,
+ value | HOST_POWER_UP);
+ }
+#endif
+ /* Poll register around 100 ms */
+ for (tries = 0; tries < MAX_POLL_TRIES; ++tries) {
+ pcb->moal_read_reg(pmadapter->pmoal_handle, reset_reg, &value);
+ if (value == 0)
+ /* FW is ready */
+ break;
+ pcb->moal_udelay(pmadapter->pmoal_handle, 1000);
+ }
+
+ if (value) {
+ PRINTM(MERROR, "Failed to poll FW reset register %X=0x%x\n",
+ reset_reg, value);
+ ret = MLAN_STATUS_FAILURE;
+ goto done;
+ }
+ PRINTM(MMSG, "FW Reset success\n");
+ ret = wlan_sdio_probe(pmadapter);
+done:
+ LEAVE();
+ return ret;
+}
+
+/**
+ * @brief This function handle event/data/cmd complete
+ *
+ * @param pmadapter A pointer to mlan_adapter structure
+ * @param pmbuf A pointer to the mlan_buffer
+ * @return N/A
+ */
+mlan_status wlan_sdio_data_evt_complete(pmlan_adapter pmadapter,
+ mlan_buffer *pmbuf, mlan_status status)
+{
+ ENTER();
+
+ wlan_free_mlan_buffer(pmadapter, pmbuf);
+
+ LEAVE();
+ return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ * @brief This function handle receive packet
+ *
+ * @param pmadapter A pointer to mlan_adapter structure
+ * @param pmbuf A pointer to the mlan_buffer
+ * @return
+ */
+mlan_status wlan_sdio_handle_rx_packet(mlan_adapter *pmadapter,
+ pmlan_buffer pmbuf)
+{
+ ENTER();
+
+ wlan_sdio_deaggr_rx_pkt(pmadapter, pmbuf);
+
+ LEAVE();
+ return MLAN_STATUS_SUCCESS;
+}
+
+mlan_adapter_operations mlan_sdio_ops = {
+ .dnld_fw = wlan_sdio_dnld_fw,
+ .interrupt = wlan_sdio_interrupt,
+ .process_int_status = wlan_process_sdio_int_status,
+ .host_to_card = wlan_sdio_host_to_card_ext,
+ .wakeup_card = wlan_pm_sdio_wakeup_card,
+ .reset_card = wlan_pm_sdio_reset_card,
+ .event_complete = wlan_sdio_data_evt_complete,
+ .data_complete = wlan_sdio_data_evt_complete,
+ .cmdrsp_complete = wlan_sdio_data_evt_complete,
+ .handle_rx_packet = wlan_sdio_handle_rx_packet,
+
+ .intf_header_len = SDIO_INTF_HEADER_LEN,
+};
diff --git a/drivers/net/wireless/nxp/mxm_wifiex/wlan_src/mlan/mlan_sdio.h b/drivers/net/wireless/nxp/mxm_wifiex/wlan_src/mlan/mlan_sdio.h
new file mode 100644
index 000000000000..6f653365a63a
--- /dev/null
+++ b/drivers/net/wireless/nxp/mxm_wifiex/wlan_src/mlan/mlan_sdio.h
@@ -0,0 +1,550 @@
+/** @file mlan_sdio.h
+ *
+ * @brief This file contains definitions for SDIO interface.
+ * driver.
+ *
+ *
+ * Copyright 2014-2020 NXP
+ *
+ * This software file (the File) is distributed by NXP
+ * under the terms of the GNU General Public License Version 2, June 1991
+ * (the License). You may use, redistribute and/or modify the 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.
+ *
+ */
+/****************************************************
+Change log:
+****************************************************/
+
+#ifndef _MLAN_SDIO_H
+#define _MLAN_SDIO_H
+
+/** Block mode */
+#ifndef BLOCK_MODE
+#define BLOCK_MODE 1
+#endif
+
+/** Fixed address mode */
+#ifndef FIXED_ADDRESS
+#define FIXED_ADDRESS 0
+#endif
+
+/* Host Control Registers */
+/** Host Control Registers : Host to Card Event */
+#define HOST_TO_CARD_EVENT_REG 0x00
+/** Host Control Registers : Host terminates Command 53 */
+#define HOST_TERM_CMD53 (0x1U << 2)
+/** Host Control Registers : Host without Command 53 finish host */
+#define HOST_WO_CMD53_FINISH_HOST (0x1U << 2)
+/** Host Control Registers : Host power up */
+#define HOST_POWER_UP (0x1U << 1)
+/** Host Control Registers : Host power down */
+#define HOST_POWER_DOWN (0x1U << 0)
+
+/** Host Control Registers : Upload host interrupt RSR */
+#define UP_LD_HOST_INT_RSR (0x1U)
+#define HOST_INT_RSR_MASK 0xFF
+
+/** Host Control Registers : Upload command port host interrupt status */
+#define UP_LD_CMD_PORT_HOST_INT_STATUS (0x40U)
+/** Host Control Registers : Download command port host interrupt status */
+#define DN_LD_CMD_PORT_HOST_INT_STATUS (0x80U)
+
+/** 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 : Cmd port upload interrupt mask */
+#define CMD_PORT_UPLD_INT_MASK (0x1U << 6)
+/** Host Control Registers : Cmd port download interrupt mask */
+#define CMD_PORT_DNLD_INT_MASK (0x1U << 7)
+/** Enable Host interrupt mask */
+#define HIM_ENABLE \
+ (UP_LD_HOST_INT_MASK | DN_LD_HOST_INT_MASK | CMD_PORT_UPLD_INT_MASK | \
+ CMD_PORT_DNLD_INT_MASK)
+/** Disable Host interrupt mask */
+#define HIM_DISABLE 0xff
+
+/** 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 : Download CRC error */
+#define DN_LD_CRC_ERR (0x1U << 2)
+/** Host Control Registers : Upload restart */
+#define UP_LD_RESTART (0x1U << 1)
+/** Host Control Registers : Download restart */
+#define DN_LD_RESTART (0x1U << 0)
+
+/** Card Control Registers : Command port upload ready */
+#define UP_LD_CP_RDY (0x1U << 6)
+/** Card Control Registers : Command port download ready */
+#define DN_LD_CP_RDY (0x1U << 7)
+/** Card Control Registers : Card I/O ready */
+#define CARD_IO_READY (0x1U << 3)
+/** Card Control Registers : CIS card ready */
+#define CIS_CARD_RDY (0x1U << 2)
+/** Card Control Registers : Upload card ready */
+#define UP_LD_CARD_RDY (0x1U << 1)
+/** Card Control Registers : Download card ready */
+#define DN_LD_CARD_RDY (0x1U << 0)
+
+/** Card Control Registers : Host power interrupt mask */
+#define HOST_POWER_INT_MASK (0x1U << 3)
+/** Card Control Registers : Abort card interrupt mask */
+#define ABORT_CARD_INT_MASK (0x1U << 2)
+/** Card Control Registers : Upload card interrupt mask */
+#define UP_LD_CARD_INT_MASK (0x1U << 1)
+/** Card Control Registers : Download card interrupt mask */
+#define DN_LD_CARD_INT_MASK (0x1U << 0)
+
+/** Card Control Registers : Power up interrupt */
+#define POWER_UP_INT (0x1U << 4)
+/** Card Control Registers : Power down interrupt */
+#define POWER_DOWN_INT (0x1U << 3)
+
+/** Card Control Registers : Power up RSR */
+#define POWER_UP_RSR (0x1U << 4)
+/** Card Control Registers : Power down RSR */
+#define POWER_DOWN_RSR (0x1U << 3)
+
+/** Card Control Registers : SD test BUS 0 */
+#define SD_TESTBUS0 (0x1U)
+/** Card Control Registers : SD test BUS 1 */
+#define SD_TESTBUS1 (0x1U)
+/** Card Control Registers : SD test BUS 2 */
+#define SD_TESTBUS2 (0x1U)
+/** Card Control Registers : SD test BUS 3 */
+#define SD_TESTBUS3 (0x1U)
+
+/** Port for registers */
+#define REG_PORT 0
+/** Port for memory */
+#define MEM_PORT 0x10000
+
+/** Card Control Registers : cmd53 new mode */
+#define CMD53_NEW_MODE (0x1U << 0)
+/** Card Control Registers : cmd53 tx len format 1 (0x10) */
+#define CMD53_TX_LEN_FORMAT_1 (0x1U << 4)
+/** Card Control Registers : cmd53 tx len format 2 (0x20)*/
+#define CMD53_TX_LEN_FORMAT_2 (0x1U << 5)
+/** Card Control Registers : cmd53 rx len format 1 (0x40) */
+#define CMD53_RX_LEN_FORMAT_1 (0x1U << 6)
+/** Card Control Registers : cmd53 rx len format 2 (0x80)*/
+#define CMD53_RX_LEN_FORMAT_2 (0x1U << 7)
+
+#define CMD_PORT_RD_LEN_EN (0x1U << 2)
+/* Card Control Registers : cmd port auto enable */
+#define CMD_PORT_AUTO_EN (0x1U << 0)
+
+/* Command port */
+#define CMD_PORT_SLCT 0x8000
+
+/** Misc. Config Register : Auto Re-enable interrupts */
+#define AUTO_RE_ENABLE_INT MBIT(4)
+
+/** Enable GPIO-1 as a duplicated signal of interrupt as appear of SDIO_DAT1*/
+#define ENABLE_GPIO_1_INT_MODE 0x88
+/** Scratch reg 3 2 : Configure GPIO-1 INT*/
+#define SCRATCH_REG_32 0xEE
+
+/** Event header Len*/
+#define MLAN_EVENT_HEADER_LEN 8
+
+/** SDIO byte mode size */
+#define MAX_BYTE_MODE_SIZE 512
+
+/** The base address for packet with multiple ports aggregation */
+#define SDIO_MPA_ADDR_BASE 0x1000
+
+/** SDIO Tx aggregation in progress ? */
+#define MP_TX_AGGR_IN_PROGRESS(a) (a->pcard_sd->mpa_tx.pkt_cnt > 0)
+
+/** SDIO Tx aggregation buffer room for next packet ? */
+#define MP_TX_AGGR_BUF_HAS_ROOM(a, mbuf, len) \
+ (((a->pcard_sd->mpa_tx.buf_len) + len) <= \
+ (a->pcard_sd->mpa_tx.buf_size))
+
+/** Copy current packet (SDIO Tx aggregation buffer) to SDIO buffer */
+#define MP_TX_AGGR_BUF_PUT(a, mbuf, port) \
+ do { \
+ pmadapter->callbacks.moal_memmove( \
+ a->pmoal_handle, \
+ &a->pcard_sd->mpa_tx.buf[a->pcard_sd->mpa_tx.buf_len], \
+ mbuf->pbuf + mbuf->data_offset, mbuf->data_len); \
+ a->pcard_sd->mpa_tx.buf_len += mbuf->data_len; \
+ a->pcard_sd->mpa_tx.mp_wr_info[a->pcard_sd->mpa_tx.pkt_cnt] = \
+ *(t_u16 *)(mbuf->pbuf + mbuf->data_offset); \
+ if (!a->pcard_sd->mpa_tx.pkt_cnt) { \
+ a->pcard_sd->mpa_tx.start_port = port; \
+ } \
+ a->pcard_sd->mpa_tx.ports |= (1 << port); \
+ a->pcard_sd->mpa_tx.pkt_cnt++; \
+ } while (0)
+
+#define MP_TX_AGGR_BUF_PUT_SG(a, mbuf, port) \
+ do { \
+ a->pcard_sd->mpa_tx.buf_len += mbuf->data_len; \
+ a->pcard_sd->mpa_tx.mp_wr_info[a->pcard_sd->mpa_tx.pkt_cnt] = \
+ *(t_u16 *)(mbuf->pbuf + mbuf->data_offset); \
+ a->pcard_sd->mpa_tx.mbuf_arr[a->pcard_sd->mpa_tx.pkt_cnt] = \
+ mbuf; \
+ if (!a->pcard_sd->mpa_tx.pkt_cnt) { \
+ a->pcard_sd->mpa_tx.start_port = port; \
+ } \
+ a->pcard_sd->mpa_tx.ports |= (1 << port); \
+ a->pcard_sd->mpa_tx.pkt_cnt++; \
+ } while (0)
+/** SDIO Tx aggregation limit ? */
+#define MP_TX_AGGR_PKT_LIMIT_REACHED(a) \
+ ((a->pcard_sd->mpa_tx.pkt_cnt) == (a->pcard_sd->mpa_tx.pkt_aggr_limit))
+
+/** Reset SDIO Tx aggregation buffer parameters */
+#define MP_TX_AGGR_BUF_RESET(a) \
+ do { \
+ memset(a, a->pcard_sd->mpa_tx.mp_wr_info, 0, \
+ sizeof(a->pcard_sd->mpa_tx.mp_wr_info)); \
+ a->pcard_sd->mpa_tx.pkt_cnt = 0; \
+ a->pcard_sd->mpa_tx.buf_len = 0; \
+ a->pcard_sd->mpa_tx.ports = 0; \
+ a->pcard_sd->mpa_tx.start_port = 0; \
+ } while (0)
+
+/** SDIO Rx aggregation limit ? */
+#define MP_RX_AGGR_PKT_LIMIT_REACHED(a) \
+ (a->pcard_sd->mpa_rx.pkt_cnt == a->pcard_sd->mpa_rx.pkt_aggr_limit)
+
+/** SDIO Rx aggregation port limit ? */
+/** this is for test only, because port 0 is reserved for control port */
+/* #define MP_RX_AGGR_PORT_LIMIT_REACHED(a) (a->curr_rd_port == 1) */
+
+/* receive packets aggregated up to a half of mp_end_port */
+/* note: hw rx wraps round only after port (MAX_PORT-1) */
+#define MP_RX_AGGR_PORT_LIMIT_REACHED(a) \
+ (((a->pcard_sd->curr_rd_port < a->pcard_sd->mpa_rx.start_port) && \
+ (((MAX_PORT - a->pcard_sd->mpa_rx.start_port) + \
+ a->pcard_sd->curr_rd_port) >= (a->pcard_sd->mp_end_port >> 1))) || \
+ ((a->pcard_sd->curr_rd_port - a->pcard_sd->mpa_rx.start_port) >= \
+ (a->pcard_sd->mp_end_port >> 1)))
+
+/** SDIO Rx aggregation in progress ? */
+#define MP_RX_AGGR_IN_PROGRESS(a) (a->pcard_sd->mpa_rx.pkt_cnt > 0)
+
+/** SDIO Rx aggregation buffer room for next packet ? */
+#define MP_RX_AGGR_BUF_HAS_ROOM(a, rx_len) \
+ ((a->pcard_sd->mpa_rx.buf_len + rx_len) <= a->pcard_sd->mpa_rx.buf_size)
+
+/** Prepare to copy current packet from card to SDIO Rx aggregation buffer */
+#define MP_RX_AGGR_SETUP(a, mbuf, port, rx_len) \
+ do { \
+ a->pcard_sd->mpa_rx.buf_len += rx_len; \
+ if (!a->pcard_sd->mpa_rx.pkt_cnt) { \
+ a->pcard_sd->mpa_rx.start_port = port; \
+ } \
+ a->pcard_sd->mpa_rx.ports |= (1 << port); \
+ a->pcard_sd->mpa_rx.mbuf_arr[a->pcard_sd->mpa_rx.pkt_cnt] = \
+ mbuf; \
+ a->pcard_sd->mpa_rx.len_arr[a->pcard_sd->mpa_rx.pkt_cnt] = \
+ rx_len; \
+ a->pcard_sd->mpa_rx.pkt_cnt++; \
+ } while (0)
+
+/** Reset SDIO Rx aggregation buffer parameters */
+#define MP_RX_AGGR_BUF_RESET(a) \
+ do { \
+ a->pcard_sd->mpa_rx.pkt_cnt = 0; \
+ a->pcard_sd->mpa_rx.buf_len = 0; \
+ a->pcard_sd->mpa_rx.ports = 0; \
+ a->pcard_sd->mpa_rx.start_port = 0; \
+ } while (0)
+
+/** aggr buf size 32k */
+#define SDIO_MP_AGGR_BUF_SIZE_32K (32768)
+/** max aggr buf size 64k-256 */
+#define SDIO_MP_AGGR_BUF_SIZE_MAX (65280)
+
+#ifdef SD8887
+static const struct _mlan_sdio_card_reg mlan_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_status = DN_LD_HOST_INT_STATUS | UP_LD_HOST_INT_STATUS |
+ DN_LD_CMD_PORT_HOST_INT_STATUS |
+ UP_LD_CMD_PORT_HOST_INT_STATUS,
+ .status_reg_0 = 0x90,
+ .status_reg_1 = 0x91,
+ .sdio_int_mask = 0xff,
+ .data_port_mask = 0xffffffff,
+ .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_config_2_1_reg = 0xD9,
+ .cmd_config_0 = 0xC4,
+ .cmd_config_1 = 0xC5,
+ .cmd_config_2 = 0xC6,
+ .cmd_config_3 = 0xC7,
+ .cmd_rd_len_0 = 0xC0,
+ .cmd_rd_len_1 = 0xC1,
+ .cmd_rd_len_2 = 0xC2,
+ .cmd_rd_len_3 = 0xC3,
+ .io_port_0_reg = 0xE4,
+ .io_port_1_reg = 0xE5,
+ .io_port_2_reg = 0xE6,
+ .host_int_rsr_reg = 0x04,
+ .host_int_mask_reg = 0x08,
+ .host_int_status_reg = 0x0C,
+ .host_restart_reg = 0x58,
+ .card_to_host_event_reg = 0x5C,
+ .host_interrupt_mask_reg = 0x60,
+ .card_interrupt_status_reg = 0x64,
+ .card_interrupt_rsr_reg = 0x68,
+ .card_revision_reg = 0xC8,
+ .card_ocr_0_reg = 0xD4,
+ .card_ocr_1_reg = 0xD5,
+ .card_ocr_3_reg = 0xD6,
+ .card_config_reg = 0xD7,
+ .card_misc_cfg_reg = 0xD8,
+ .debug_0_reg = 0xDC,
+ .debug_1_reg = 0xDD,
+ .debug_2_reg = 0xDE,
+ .debug_3_reg = 0xDF,
+ .fw_reset_reg = 0x0B6,
+ .fw_reset_val = 1,
+ .winner_check_reg = 0x90,
+};
+
+static const struct _mlan_card_info mlan_card_info_sd8887 = {
+ .max_tx_buf_size = MLAN_TX_DATA_BUF_SIZE_2K,
+ .v16_fw_api = 0,
+ .supp_ps_handshake = 0,
+ .default_11n_tx_bf_cap = DEFAULT_11N_TX_BF_CAP_1X1,
+};
+#endif
+
+#ifdef SD8897
+static const struct _mlan_sdio_card_reg mlan_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_status = DN_LD_HOST_INT_STATUS | UP_LD_HOST_INT_STATUS |
+ DN_LD_CMD_PORT_HOST_INT_STATUS |
+ UP_LD_CMD_PORT_HOST_INT_STATUS,
+ .status_reg_0 = 0xC0,
+ .status_reg_1 = 0xC1,
+ .sdio_int_mask = 0xff,
+ .data_port_mask = 0xffffffff,
+ .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_config_2_1_reg = 0xCD,
+ .cmd_config_0 = 0xB8,
+ .cmd_config_1 = 0xB9,
+ .cmd_config_2 = 0xBA,
+ .cmd_config_3 = 0xBB,
+ .cmd_rd_len_0 = 0xB4,
+ .cmd_rd_len_1 = 0xB5,
+ .cmd_rd_len_2 = 0xB6,
+ .cmd_rd_len_3 = 0xB7,
+ .io_port_0_reg = 0xD8,
+ .io_port_1_reg = 0xD9,
+ .io_port_2_reg = 0xDA,
+ .host_int_rsr_reg = 0x01,
+ .host_int_mask_reg = 0x02,
+ .host_int_status_reg = 0x03,
+ .host_restart_reg = 0x4C,
+ .card_to_host_event_reg = 0x50,
+ .host_interrupt_mask_reg = 0x54,
+ .card_interrupt_status_reg = 0x58,
+ .card_interrupt_rsr_reg = 0x5C,
+ .card_revision_reg = 0xBC,
+ .card_ocr_0_reg = 0xC8,
+ .card_ocr_1_reg = 0xC9,
+ .card_ocr_3_reg = 0xCA,
+ .card_config_reg = 0xCB,
+ .card_misc_cfg_reg = 0xCC,
+ .debug_0_reg = 0xD0,
+ .debug_1_reg = 0xD1,
+ .debug_2_reg = 0xD2,
+ .debug_3_reg = 0xD3,
+ .fw_reset_reg = 0x0E8,
+ .fw_reset_val = 1,
+ .winner_check_reg = 0xC0,
+};
+
+static const struct _mlan_card_info mlan_card_info_sd8897 = {
+ .max_tx_buf_size = MLAN_TX_DATA_BUF_SIZE_4K,
+ .v16_fw_api = 0,
+ .supp_ps_handshake = 0,
+ .default_11n_tx_bf_cap = DEFAULT_11N_TX_BF_CAP_2X2,
+};
+#endif
+
+#if defined(SD8977) || defined(SD8997) || defined(SD8987) || \
+ defined(SD9098) || defined(SD9097) || defined(SD8978)
+static const struct _mlan_sdio_card_reg mlan_reg_sd8977_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_status = DN_LD_HOST_INT_STATUS | UP_LD_HOST_INT_STATUS |
+ DN_LD_CMD_PORT_HOST_INT_STATUS |
+ UP_LD_CMD_PORT_HOST_INT_STATUS,
+ .status_reg_0 = 0xe8,
+ .status_reg_1 = 0xe9,
+ .sdio_int_mask = 0xff,
+ .data_port_mask = 0xffffffff,
+ .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_config_2_1_reg = 0xD9,
+ .cmd_config_0 = 0xC4,
+ .cmd_config_1 = 0xC5,
+ .cmd_config_2 = 0xC6,
+ .cmd_config_3 = 0xC7,
+ .cmd_rd_len_0 = 0xC0,
+ .cmd_rd_len_1 = 0xC1,
+ .cmd_rd_len_2 = 0xC2,
+ .cmd_rd_len_3 = 0xC3,
+ .io_port_0_reg = 0xE4,
+ .io_port_1_reg = 0xE5,
+ .io_port_2_reg = 0xE6,
+ .host_int_rsr_reg = 0x04,
+ .host_int_mask_reg = 0x08,
+ .host_int_status_reg = 0x0C,
+ .host_restart_reg = 0x58,
+ .card_to_host_event_reg = 0x5C,
+ .host_interrupt_mask_reg = 0x60,
+ .card_interrupt_status_reg = 0x64,
+ .card_interrupt_rsr_reg = 0x68,
+ .card_revision_reg = 0xC8,
+ .card_ocr_0_reg = 0xD4,
+ .card_ocr_1_reg = 0xD5,
+ .card_ocr_3_reg = 0xD6,
+ .card_config_reg = 0xD7,
+ .card_misc_cfg_reg = 0xD8,
+ .debug_0_reg = 0xDC,
+ .debug_1_reg = 0xDD,
+ .debug_2_reg = 0xDE,
+ .debug_3_reg = 0xDF,
+ .fw_reset_reg = 0x0EE,
+ .fw_reset_val = 0x99,
+ .fw_dnld_offset_0_reg = 0xEC,
+ .fw_dnld_offset_1_reg = 0xED,
+ .fw_dnld_offset_2_reg = 0xEE,
+ .fw_dnld_offset_3_reg = 0xEF,
+ .fw_dnld_status_0_reg = 0xE8,
+ .fw_dnld_status_1_reg = 0xE9,
+ .winner_check_reg = 0xFC,
+};
+
+#ifdef SD8997
+static const struct _mlan_card_info mlan_card_info_sd8997 = {
+ .max_tx_buf_size = MLAN_TX_DATA_BUF_SIZE_4K,
+ .v16_fw_api = 1,
+ .supp_ps_handshake = 0,
+ .default_11n_tx_bf_cap = DEFAULT_11N_TX_BF_CAP_2X2,
+};
+#endif
+
+#ifdef SD9097
+static const struct _mlan_card_info mlan_card_info_sd9097 = {
+ .max_tx_buf_size = MLAN_TX_DATA_BUF_SIZE_4K,
+ .v16_fw_api = 1,
+ .v17_fw_api = 1,
+ .supp_ps_handshake = 0,
+ .default_11n_tx_bf_cap = DEFAULT_11N_TX_BF_CAP_2X2,
+};
+#endif
+#ifdef SD9098
+static const struct _mlan_card_info mlan_card_info_sd9098 = {
+ .max_tx_buf_size = MLAN_TX_DATA_BUF_SIZE_4K,
+ .v16_fw_api = 1,
+ .v17_fw_api = 1,
+ .supp_ps_handshake = 0,
+ .default_11n_tx_bf_cap = DEFAULT_11N_TX_BF_CAP_2X2,
+};
+#endif
+
+#if defined(SD8977) || defined(SD8978)
+static const struct _mlan_card_info mlan_card_info_sd8977 = {
+ .max_tx_buf_size = MLAN_TX_DATA_BUF_SIZE_2K,
+ .v16_fw_api = 1,
+ .supp_ps_handshake = 0,
+ .default_11n_tx_bf_cap = DEFAULT_11N_TX_BF_CAP_1X1,
+};
+#endif
+
+#ifdef SD8987
+static const struct _mlan_card_info mlan_card_info_sd8987 = {
+ .max_tx_buf_size = MLAN_TX_DATA_BUF_SIZE_2K,
+ .v16_fw_api = 1,
+ .supp_ps_handshake = 0,
+ .default_11n_tx_bf_cap = DEFAULT_11N_TX_BF_CAP_1X1,
+};
+#endif
+#endif
+
+/** Probe and initialization function */
+mlan_status wlan_sdio_probe(pmlan_adapter pmadapter);
+mlan_status wlan_get_sdio_device(pmlan_adapter pmadapter);
+
+mlan_status wlan_send_mp_aggr_buf(mlan_adapter *pmadapter);
+
+mlan_status wlan_re_alloc_sdio_rx_mpa_buffer(mlan_adapter *pmadapter);
+
+void wlan_decode_spa_buffer(mlan_adapter *pmadapter, t_u8 *buf, t_u32 len);
+t_void wlan_sdio_deaggr_rx_pkt(pmlan_adapter pmadapter, mlan_buffer *pmbuf);
+/** Transfer data to card */
+mlan_status wlan_sdio_host_to_card(mlan_adapter *pmadapter, t_u8 type,
+ mlan_buffer *mbuf, mlan_tx_param *tx_param);
+mlan_status wlan_set_sdio_gpio_int(pmlan_private priv);
+mlan_status wlan_cmd_sdio_gpio_int(pmlan_private pmpriv,
+ HostCmd_DS_COMMAND *cmd, t_u16 cmd_action,
+ t_void *pdata_buf);
+mlan_status wlan_reset_fw(pmlan_adapter pmadapter);
+
+#endif /* _MLAN_SDIO_H */
diff --git a/drivers/net/wireless/nxp/mxm_wifiex/wlan_src/mlan/mlan_shim.c b/drivers/net/wireless/nxp/mxm_wifiex/wlan_src/mlan/mlan_shim.c
new file mode 100644
index 000000000000..c5fc7f5085c7
--- /dev/null
+++ b/drivers/net/wireless/nxp/mxm_wifiex/wlan_src/mlan/mlan_shim.c
@@ -0,0 +1,1700 @@
+/** @file mlan_shim.c
+ *
+ * @brief This file contains APIs to MOAL module.
+ *
+ *
+ * Copyright 2014-2020 NXP
+ *
+ * This software file (the File) is distributed by NXP
+ * under the terms of the GNU General Public License Version 2, June 1991
+ * (the License). You may use, redistribute and/or modify the 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.
+ *
+ */
+
+/********************************************************
+Change log:
+ 10/13/2008: initial version
+********************************************************/
+
+#include "mlan.h"
+#ifdef STA_SUPPORT
+#include "mlan_join.h"
+#endif
+#include "mlan_util.h"
+#include "mlan_fw.h"
+#include "mlan_main.h"
+#include "mlan_wmm.h"
+#ifdef SDIO
+#include "mlan_sdio.h"
+#endif /* SDIO */
+#ifdef PCIE
+#include "mlan_pcie.h"
+#endif /* PCIE */
+#ifdef UAP_SUPPORT
+#include "mlan_uap.h"
+#endif
+#include "mlan_11h.h"
+#include "mlan_11n_rxreorder.h"
+#ifdef DRV_EMBEDDED_AUTHENTICATOR
+#include "authenticator_api.h"
+#endif
+
+/********************************************************
+ Local Variables
+********************************************************/
+
+/********************************************************
+ Global Variables
+********************************************************/
+#ifdef STA_SUPPORT
+mlan_operations mlan_sta_ops = {
+ /* init cmd handler */
+ wlan_ops_sta_init_cmd,
+ /* ioctl handler */
+ wlan_ops_sta_ioctl,
+ /* cmd handler */
+ wlan_ops_sta_prepare_cmd,
+ /* cmdresp handler */
+ wlan_ops_sta_process_cmdresp,
+ /* rx handler */
+ wlan_ops_sta_process_rx_packet,
+ /* Event handler */
+ wlan_ops_sta_process_event,
+ /* txpd handler */
+ wlan_ops_sta_process_txpd,
+ /* BSS role: STA */
+ MLAN_BSS_ROLE_STA,
+};
+#endif
+#ifdef UAP_SUPPORT
+mlan_operations mlan_uap_ops = {
+ /* init cmd handler */
+ wlan_ops_uap_init_cmd,
+ /* ioctl handler */
+ wlan_ops_uap_ioctl,
+ /* cmd handler */
+ wlan_ops_uap_prepare_cmd,
+ /* cmdresp handler */
+ wlan_ops_uap_process_cmdresp,
+ /* rx handler */
+ wlan_ops_uap_process_rx_packet,
+ /* Event handler */
+ wlan_ops_uap_process_event,
+ /* txpd handler */
+ wlan_ops_uap_process_txpd,
+ /* BSS role: uAP */
+ MLAN_BSS_ROLE_UAP,
+};
+#endif
+
+/** mlan function table */
+mlan_operations *mlan_ops[] = {
+#ifdef STA_SUPPORT
+ &mlan_sta_ops,
+#endif
+#ifdef UAP_SUPPORT
+ &mlan_uap_ops,
+#endif
+ MNULL,
+};
+
+/** Global moal_assert callback */
+t_void (*assert_callback)(t_pvoid pmoal_handle, t_u32 cond) = MNULL;
+#ifdef DEBUG_LEVEL1
+#ifdef DEBUG_LEVEL2
+#define DEFAULT_DEBUG_MASK (0xffffffff)
+#else
+#define DEFAULT_DEBUG_MASK (MMSG | MFATAL | MERROR)
+#endif
+
+/** Global moal_print callback */
+t_void (*print_callback)(t_pvoid pmoal_handle, t_u32 level, char *pformat,
+ IN...) = MNULL;
+
+/** Global moal_get_system_time callback */
+mlan_status (*get_sys_time_callback)(t_pvoid pmoal_handle, t_pu32 psec,
+ t_pu32 pusec) = MNULL;
+
+/** Global driver debug mit masks */
+t_u32 mlan_drvdbg = DEFAULT_DEBUG_MASK;
+#endif
+
+#ifdef USB
+extern mlan_status wlan_get_usb_device(pmlan_adapter pmadapter);
+#endif
+/********************************************************
+ Local Functions
+*******************************************************/
+/**
+ * @brief This function process pending ioctl
+ *
+ * @param pmadapter A pointer to mlan_adapter structure
+ *
+ */
+void wlan_process_pending_ioctl(mlan_adapter *pmadapter)
+{
+ pmlan_ioctl_req pioctl_buf;
+ mlan_status status = MLAN_STATUS_SUCCESS;
+ pmlan_callbacks pcb;
+#if defined(STA_SUPPORT) && defined(UAP_SUPPORT)
+ pmlan_ds_bss bss = MNULL;
+#endif
+#ifdef STA_SUPPORT
+ pmlan_ds_misc_cfg misc = MNULL;
+#endif
+ ENTER();
+
+ pcb = &pmadapter->callbacks;
+
+ while ((pioctl_buf = (pmlan_ioctl_req)util_dequeue_list(
+ pmadapter->pmoal_handle, &pmadapter->ioctl_pending_q,
+ pcb->moal_spin_lock, pcb->moal_spin_unlock))) {
+ switch (pioctl_buf->req_id) {
+#if defined(STA_SUPPORT) && defined(UAP_SUPPORT)
+ case MLAN_IOCTL_BSS:
+ bss = (mlan_ds_bss *)pioctl_buf->pbuf;
+ if (bss->sub_command == MLAN_OID_BSS_ROLE) {
+ PRINTM(MCMND, "Role switch ioctl: %d\n",
+ bss->param.bss_role);
+ status = wlan_bss_ioctl_bss_role(pmadapter,
+ pioctl_buf);
+ }
+ break;
+#endif
+#ifdef STA_SUPPORT
+ case MLAN_IOCTL_MISC_CFG:
+ misc = (mlan_ds_misc_cfg *)pioctl_buf->pbuf;
+ if (misc->sub_command == MLAN_OID_MISC_WARM_RESET) {
+ PRINTM(MCMND, "Warm Reset ioctl\n");
+ status = wlan_misc_ioctl_warm_reset(pmadapter,
+ pioctl_buf);
+ }
+ break;
+#endif
+ default:
+ break;
+ }
+ if (status != MLAN_STATUS_PENDING)
+ pcb->moal_ioctl_complete(pmadapter->pmoal_handle,
+ pioctl_buf, status);
+ }
+ LEAVE();
+}
+/********************************************************
+ Global Functions
+********************************************************/
+#ifdef USB
+extern mlan_adapter_operations mlan_usb_ops;
+#endif
+#ifdef PCIE
+extern mlan_adapter_operations mlan_pcie_ops;
+#endif
+#ifdef SDIO
+extern mlan_adapter_operations mlan_sdio_ops;
+#endif
+
+/**
+ * @brief This function registers MOAL to MLAN module.
+ *
+ * @param pmdevice A pointer to a mlan_device structure
+ * allocated in MOAL
+ * @param ppmlan_adapter A pointer to a t_void pointer to store
+ * mlan_adapter structure pointer as the context
+ *
+ * @return MLAN_STATUS_SUCCESS
+ * The registration succeeded.
+ * MLAN_STATUS_FAILURE
+ * The registration failed.
+ *
+ * mlan_status mlan_register(
+ * pmlan_device pmdevice,
+ * t_void **ppmlan_adapter
+ * );
+ *
+ * Comments
+ * MOAL constructs mlan_device data structure to pass moal_handle and
+ * mlan_callback table to MLAN. MLAN returns mlan_adapter pointer to
+ * the ppmlan_adapter buffer provided by MOAL.
+ * Headers:
+ * declared in mlan_decl.h
+ * See Also
+ * mlan_unregister
+ */
+mlan_status mlan_register(pmlan_device pmdevice, t_void **ppmlan_adapter)
+{
+ mlan_status ret = MLAN_STATUS_SUCCESS;
+ pmlan_adapter pmadapter = MNULL;
+ pmlan_callbacks pcb = MNULL;
+ t_u8 i = 0;
+ t_u32 j = 0;
+
+ if (!pmdevice || !ppmlan_adapter) {
+ return MLAN_STATUS_FAILURE;
+ }
+ MASSERT(ppmlan_adapter);
+ MASSERT(pmdevice->callbacks.moal_print);
+#ifdef DEBUG_LEVEL1
+ print_callback = pmdevice->callbacks.moal_print;
+ get_sys_time_callback = pmdevice->callbacks.moal_get_system_time;
+#endif
+ assert_callback = pmdevice->callbacks.moal_assert;
+
+ ENTER();
+
+ MASSERT(pmdevice->callbacks.moal_malloc);
+ MASSERT(pmdevice->callbacks.moal_mfree);
+ MASSERT(pmdevice->callbacks.moal_memset);
+ MASSERT(pmdevice->callbacks.moal_memmove);
+ MASSERT(pmdevice->callbacks.moal_udelay);
+ MASSERT(pmdevice->callbacks.moal_usleep_range);
+
+ if (!pmdevice->callbacks.moal_malloc ||
+ !pmdevice->callbacks.moal_mfree ||
+ !pmdevice->callbacks.moal_memset ||
+ !pmdevice->callbacks.moal_udelay ||
+ !pmdevice->callbacks.moal_usleep_range ||
+ !pmdevice->callbacks.moal_memmove) {
+ LEAVE();
+ return MLAN_STATUS_FAILURE;
+ }
+
+ /* Allocate memory for adapter structure */
+ if (pmdevice->callbacks.moal_vmalloc && pmdevice->callbacks.moal_vfree)
+ ret = pmdevice->callbacks.moal_vmalloc(pmdevice->pmoal_handle,
+ sizeof(mlan_adapter),
+ (t_u8 **)&pmadapter);
+ else
+ ret = pmdevice->callbacks.moal_malloc(pmdevice->pmoal_handle,
+ sizeof(mlan_adapter),
+ MLAN_MEM_DEF,
+ (t_u8 **)&pmadapter);
+ if ((ret != MLAN_STATUS_SUCCESS) || !pmadapter) {
+ ret = MLAN_STATUS_FAILURE;
+ goto exit_register;
+ }
+
+ pmdevice->callbacks.moal_memset(pmdevice->pmoal_handle, pmadapter, 0,
+ sizeof(mlan_adapter));
+
+ pcb = &pmadapter->callbacks;
+
+ /* Save callback functions */
+ pmdevice->callbacks.moal_memmove(pmadapter->pmoal_handle, pcb,
+ &pmdevice->callbacks,
+ sizeof(mlan_callbacks));
+
+ /* Assertion for all callback functions */
+ MASSERT(pcb->moal_get_hw_spec_complete);
+ MASSERT(pcb->moal_init_fw_complete);
+ MASSERT(pcb->moal_shutdown_fw_complete);
+ MASSERT(pcb->moal_send_packet_complete);
+ MASSERT(pcb->moal_recv_packet);
+ MASSERT(pcb->moal_recv_event);
+ MASSERT(pcb->moal_ioctl_complete);
+
+#if defined(SDIO) || defined(PCIE)
+ if (!IS_USB(pmadapter->card_type)) {
+ MASSERT(pcb->moal_write_reg);
+ MASSERT(pcb->moal_read_reg);
+ MASSERT(pcb->moal_alloc_mlan_buffer);
+ MASSERT(pcb->moal_free_mlan_buffer);
+ }
+#endif
+ MASSERT(pcb->moal_get_vdll_data);
+ MASSERT(pcb->moal_write_data_sync);
+ MASSERT(pcb->moal_read_data_sync);
+ MASSERT(pcb->moal_mfree);
+ MASSERT(pcb->moal_memcpy);
+ MASSERT(pcb->moal_memcpy_ext);
+ MASSERT(pcb->moal_memcmp);
+ MASSERT(pcb->moal_get_system_time);
+ MASSERT(pcb->moal_init_timer);
+ MASSERT(pcb->moal_free_timer);
+ MASSERT(pcb->moal_get_boot_ktime);
+ MASSERT(pcb->moal_start_timer);
+ MASSERT(pcb->moal_stop_timer);
+ MASSERT(pcb->moal_init_lock);
+ MASSERT(pcb->moal_free_lock);
+ MASSERT(pcb->moal_spin_lock);
+ MASSERT(pcb->moal_spin_unlock);
+ MASSERT(pcb->moal_hist_data_add);
+ /* Save pmoal_handle */
+ pmadapter->pmoal_handle = pmdevice->pmoal_handle;
+
+ pmadapter->feature_control = pmdevice->feature_control;
+
+ pmadapter->card_type = pmdevice->card_type;
+ pmadapter->card_rev = pmdevice->card_rev;
+ pmadapter->init_para.uap_max_sta = pmdevice->uap_max_sta;
+
+#ifdef SDIO
+ if (IS_SD(pmadapter->card_type)) {
+ PRINTM(MMSG,
+ "Attach mlan adapter operations.card_type is 0x%x.\n",
+ pmdevice->card_type);
+ memcpy_ext(pmadapter, &pmadapter->ops, &mlan_sdio_ops,
+ sizeof(mlan_adapter_operations),
+ sizeof(mlan_adapter_operations));
+ ret = wlan_get_sdio_device(pmadapter);
+ if (MLAN_STATUS_SUCCESS != ret) {
+ ret = MLAN_STATUS_FAILURE;
+ goto error;
+ }
+ if ((pmdevice->int_mode == INT_MODE_GPIO) &&
+ (pmdevice->gpio_pin == 0)) {
+ PRINTM(MERROR,
+ "SDIO_GPIO_INT_CONFIG: Invalid GPIO Pin\n");
+ ret = MLAN_STATUS_FAILURE;
+ goto error;
+ }
+ pmadapter->init_para.int_mode = pmdevice->int_mode;
+ pmadapter->init_para.gpio_pin = pmdevice->gpio_pin;
+ /* card specific probing has been deferred until now .. */
+ ret = wlan_sdio_probe(pmadapter);
+ if (MLAN_STATUS_SUCCESS != ret) {
+ ret = MLAN_STATUS_FAILURE;
+ goto error;
+ }
+ pmadapter->pcard_sd->max_segs = pmdevice->max_segs;
+ pmadapter->pcard_sd->max_seg_size = pmdevice->max_seg_size;
+
+ pmadapter->init_para.mpa_tx_cfg = pmdevice->mpa_tx_cfg;
+ pmadapter->init_para.mpa_rx_cfg = pmdevice->mpa_rx_cfg;
+ pmadapter->pcard_sd->sdio_rx_aggr_enable =
+ pmdevice->sdio_rx_aggr_enable;
+ }
+#endif
+
+#ifdef PCIE
+ if (IS_PCIE(pmadapter->card_type)) {
+ MASSERT(pcb->moal_malloc_consistent);
+ MASSERT(pcb->moal_mfree_consistent);
+ MASSERT(pcb->moal_map_memory);
+ MASSERT(pcb->moal_unmap_memory);
+ PRINTM(MMSG,
+ "Attach mlan adapter operations.card_type is 0x%x.\n",
+ pmdevice->card_type);
+ memcpy_ext(pmadapter, &pmadapter->ops, &mlan_pcie_ops,
+ sizeof(mlan_adapter_operations),
+ sizeof(mlan_adapter_operations));
+ ret = wlan_get_pcie_device(pmadapter);
+ if (MLAN_STATUS_SUCCESS != ret) {
+ ret = MLAN_STATUS_FAILURE;
+ goto error;
+ }
+ }
+#endif
+
+#ifdef USB
+ if (IS_USB(pmadapter->card_type)) {
+ MASSERT(pcb->moal_write_data_async);
+ MASSERT(pcb->moal_recv_complete);
+ PRINTM(MMSG,
+ "Attach mlan adapter operations.card_type is 0x%x.\n",
+ pmdevice->card_type);
+ memcpy_ext(pmadapter, &pmadapter->ops, &mlan_usb_ops,
+ sizeof(mlan_adapter_operations),
+ sizeof(mlan_adapter_operations));
+ ret = wlan_get_usb_device(pmadapter);
+ if (MLAN_STATUS_SUCCESS != ret) {
+ ret = MLAN_STATUS_FAILURE;
+ goto error;
+ }
+ }
+#endif
+
+#ifdef DEBUG_LEVEL1
+ mlan_drvdbg = pmdevice->drvdbg;
+#endif
+
+#ifdef MFG_CMD_SUPPORT
+ pmadapter->init_para.mfg_mode = pmdevice->mfg_mode;
+#endif
+ pmadapter->init_para.auto_ds = pmdevice->auto_ds;
+ pmadapter->init_para.ps_mode = pmdevice->ps_mode;
+ if (pmdevice->max_tx_buf == MLAN_TX_DATA_BUF_SIZE_2K ||
+ pmdevice->max_tx_buf == MLAN_TX_DATA_BUF_SIZE_4K ||
+ pmdevice->max_tx_buf == MLAN_TX_DATA_BUF_SIZE_12K ||
+ pmdevice->max_tx_buf == MLAN_TX_DATA_BUF_SIZE_8K)
+ pmadapter->init_para.max_tx_buf = pmdevice->max_tx_buf;
+#ifdef STA_SUPPORT
+ pmadapter->init_para.cfg_11d = pmdevice->cfg_11d;
+#else
+ pmadapter->init_para.cfg_11d = 0;
+#endif
+ if (IS_DFS_SUPPORT(pmadapter->feature_control))
+ pmadapter->init_para.dfs_master_radar_det_en =
+ DFS_MASTER_RADAR_DETECT_EN;
+ pmadapter->init_para.dfs_slave_radar_det_en = DFS_SLAVE_RADAR_DETECT_EN;
+ pmadapter->init_para.dev_cap_mask = pmdevice->dev_cap_mask;
+ pmadapter->init_para.indrstcfg = pmdevice->indrstcfg;
+ pmadapter->rx_work_flag = pmdevice->rx_work;
+ pmadapter->init_para.passive_to_active_scan =
+ pmdevice->passive_to_active_scan;
+ pmadapter->fixed_beacon_buffer = pmdevice->fixed_beacon_buffer;
+
+ pmadapter->multiple_dtim = pmdevice->multi_dtim;
+ pmadapter->inact_tmo = pmdevice->inact_tmo;
+ pmadapter->init_para.fw_region = pmdevice->fw_region;
+ pmadapter->hs_wake_interval = pmdevice->hs_wake_interval;
+ if (pmdevice->indication_gpio != 0xff) {
+ pmadapter->ind_gpio = pmdevice->indication_gpio & 0x0f;
+ pmadapter->level = (pmdevice->indication_gpio & 0xf0) >> 4;
+ if (pmadapter->level != 0 && pmadapter->level != 1) {
+ PRINTM(MERROR,
+ "Indication GPIO level is wrong and will use default value 0.\n");
+ pmadapter->level = 0;
+ }
+ }
+ pmadapter->hs_mimo_switch = pmdevice->hs_mimo_switch;
+#ifdef USB
+ if (IS_USB(pmadapter->card_type)) {
+ pmadapter->tx_cmd_ep = pmdevice->tx_cmd_ep;
+ pmadapter->rx_cmd_ep = pmdevice->rx_cmd_ep;
+ pmadapter->tx_data_ep = pmdevice->tx_data_ep;
+ pmadapter->rx_data_ep = pmdevice->rx_data_ep;
+ }
+#endif
+ pmadapter->init_para.dfs53cfg = pmdevice->dfs53cfg;
+ pmadapter->priv_num = 0;
+ pmadapter->priv[0] = MNULL;
+
+ if (pcb->moal_vmalloc && pcb->moal_vfree)
+ ret = pcb->moal_vmalloc(pmadapter->pmoal_handle,
+ sizeof(mlan_private),
+ (t_u8 **)&pmadapter->priv[0]);
+ else
+ ret = pcb->moal_malloc(pmadapter->pmoal_handle,
+ sizeof(mlan_private), MLAN_MEM_DEF,
+ (t_u8 **)&pmadapter->priv[0]);
+ if (ret != MLAN_STATUS_SUCCESS || !pmadapter->priv[0]) {
+ ret = MLAN_STATUS_FAILURE;
+ goto error;
+ }
+
+ pmadapter->priv_num++;
+ memset(pmadapter, pmadapter->priv[0], 0, sizeof(mlan_private));
+
+ pmadapter->priv[0]->adapter = pmadapter;
+ pmadapter->priv[0]->bss_type = (t_u8)pmdevice->bss_attr[0].bss_type;
+ pmadapter->priv[0]->frame_type = (t_u8)pmdevice->bss_attr[0].frame_type;
+ pmadapter->priv[0]->bss_priority =
+ (t_u8)pmdevice->bss_attr[0].bss_priority;
+ if (pmdevice->bss_attr[0].bss_type == MLAN_BSS_TYPE_STA)
+ pmadapter->priv[0]->bss_role = MLAN_BSS_ROLE_STA;
+ else if (pmdevice->bss_attr[0].bss_type == MLAN_BSS_TYPE_UAP)
+ pmadapter->priv[0]->bss_role = MLAN_BSS_ROLE_UAP;
+#ifdef WIFI_DIRECT_SUPPORT
+ else if (pmdevice->bss_attr[0].bss_type == MLAN_BSS_TYPE_WIFIDIRECT) {
+ pmadapter->priv[0]->bss_role = MLAN_BSS_ROLE_STA;
+ if (pmdevice->bss_attr[0].bss_virtual)
+ pmadapter->priv[0]->bss_virtual = MTRUE;
+ }
+#endif
+ /* Save bss_index and bss_num */
+ pmadapter->priv[0]->bss_index = 0;
+ pmadapter->priv[0]->bss_num = (t_u8)pmdevice->bss_attr[0].bss_num;
+
+ /* init function table */
+ for (j = 0; mlan_ops[j]; j++) {
+ if (mlan_ops[j]->bss_role == GET_BSS_ROLE(pmadapter->priv[0])) {
+ memcpy_ext(pmadapter, &pmadapter->priv[0]->ops,
+ mlan_ops[j], sizeof(mlan_operations),
+ sizeof(mlan_operations));
+ break;
+ }
+ }
+ /** back up bss_attr table */
+ memcpy_ext(pmadapter, pmadapter->bss_attr, pmdevice->bss_attr,
+ sizeof(pmadapter->bss_attr), sizeof(pmadapter->bss_attr));
+
+ /* Initialize lock variables */
+ if (wlan_init_lock_list(pmadapter) != MLAN_STATUS_SUCCESS) {
+ ret = MLAN_STATUS_FAILURE;
+ goto error;
+ }
+
+ /** init lock varible for first priv */
+ if (wlan_init_priv_lock_list(pmadapter, 0) != MLAN_STATUS_SUCCESS) {
+ ret = MLAN_STATUS_FAILURE;
+ goto error;
+ }
+
+ /* Allocate memory for member of adapter structure */
+ if (wlan_allocate_adapter(pmadapter)) {
+ ret = MLAN_STATUS_FAILURE;
+ goto error;
+ }
+
+ /* Initialize timers */
+ if (wlan_init_timer(pmadapter) != MLAN_STATUS_SUCCESS) {
+ ret = MLAN_STATUS_FAILURE;
+ goto error;
+ }
+ /* Return pointer of mlan_adapter to MOAL */
+ *ppmlan_adapter = pmadapter;
+
+ goto exit_register;
+
+error:
+ PRINTM(MINFO, "Leave mlan_register with error\n");
+ /* Free adapter structure */
+ wlan_free_adapter(pmadapter);
+
+ for (i = 0; i < MLAN_MAX_BSS_NUM; i++) {
+ if (pmadapter->priv[i]) {
+ if (pcb->moal_vmalloc && pcb->moal_vfree)
+ pcb->moal_vfree(pmadapter->pmoal_handle,
+ (t_u8 *)pmadapter->priv[i]);
+ else if (pcb->moal_mfree)
+ pcb->moal_mfree(pmadapter->pmoal_handle,
+ (t_u8 *)pmadapter->priv[i]);
+ }
+ }
+ if (pcb->moal_vmalloc && pcb->moal_vfree)
+ pcb->moal_vfree(pmadapter->pmoal_handle, (t_u8 *)pmadapter);
+ else if (pcb->moal_mfree)
+ pcb->moal_mfree(pmadapter->pmoal_handle, (t_u8 *)pmadapter);
+
+exit_register:
+ LEAVE();
+ return ret;
+}
+
+/**
+ * @brief This function unregisters MOAL from MLAN module.
+ *
+ * @param pmlan_adapter A pointer to a mlan_device structure
+ * allocated in MOAL
+ *
+ * @return MLAN_STATUS_SUCCESS
+ * The deregistration succeeded.
+ */
+mlan_status mlan_unregister(t_void *pmlan_adapter)
+{
+ mlan_status ret = MLAN_STATUS_SUCCESS;
+ mlan_adapter *pmadapter = (mlan_adapter *)pmlan_adapter;
+ pmlan_callbacks pcb;
+ t_s32 i = 0;
+
+ MASSERT(pmlan_adapter);
+
+ ENTER();
+
+ pcb = &pmadapter->callbacks;
+
+ /* Free adapter structure */
+ wlan_free_adapter(pmadapter);
+
+ /* Free private structures */
+ for (i = 0; i < pmadapter->priv_num; i++) {
+ if (pmadapter->priv[i]) {
+ if (pcb->moal_vmalloc && pcb->moal_vfree)
+ pcb->moal_vfree(pmadapter->pmoal_handle,
+ (t_u8 *)pmadapter->priv[i]);
+ else if (pcb->moal_mfree)
+ pcb->moal_mfree(pmadapter->pmoal_handle,
+ (t_u8 *)pmadapter->priv[i]);
+ }
+ }
+
+ /* Free mlan_adapter */
+ if (pcb->moal_vmalloc && pcb->moal_vfree)
+ pcb->moal_vfree(pmadapter->pmoal_handle, (t_u8 *)pmadapter);
+ else if (pcb->moal_mfree)
+ pcb->moal_mfree(pmadapter->pmoal_handle, (t_u8 *)pmadapter);
+
+ LEAVE();
+ return ret;
+}
+
+/**
+ * @brief This function downloads the firmware
+ *
+ * @param pmlan_adapter A pointer to a t_void pointer to store
+ * mlan_adapter structure pointer
+ * @param pmfw A pointer to firmware image
+ *
+ * @return MLAN_STATUS_SUCCESS
+ * The firmware download succeeded.
+ * MLAN_STATUS_FAILURE
+ * The firmware download failed.
+ */
+mlan_status mlan_dnld_fw(t_void *pmlan_adapter, pmlan_fw_image pmfw)
+{
+ mlan_status ret = MLAN_STATUS_FAILURE;
+ mlan_adapter *pmadapter = (mlan_adapter *)pmlan_adapter;
+
+ ENTER();
+ MASSERT(pmlan_adapter);
+
+ /* Download helper/firmware */
+ if (pmfw) {
+ ret = pmadapter->ops.dnld_fw(pmadapter, pmfw);
+ if (ret != MLAN_STATUS_SUCCESS) {
+ PRINTM(MERROR, "wlan_dnld_fw fail ret=0x%x\n", ret);
+ LEAVE();
+ return ret;
+ }
+ }
+
+ LEAVE();
+ return ret;
+}
+
+/**
+ * @brief This function pass init param to MLAN
+ *
+ * @param pmlan_adapter A pointer to a t_void pointer to store
+ * mlan_adapter structure pointer
+ * @param pparam A pointer to mlan_init_param structure
+ *
+ * @return MLAN_STATUS_SUCCESS
+ *
+ */
+mlan_status mlan_set_init_param(t_void *pmlan_adapter, pmlan_init_param pparam)
+{
+ mlan_status ret = MLAN_STATUS_SUCCESS;
+ mlan_adapter *pmadapter = (mlan_adapter *)pmlan_adapter;
+
+ ENTER();
+ MASSERT(pmlan_adapter);
+
+ /** Save DPD data in MLAN */
+ if ((pparam->pdpd_data_buf) || (pparam->dpd_data_len > 0)) {
+ pmadapter->pdpd_data = pparam->pdpd_data_buf;
+ pmadapter->dpd_data_len = pparam->dpd_data_len;
+ }
+ if (pparam->ptxpwr_data_buf && (pparam->txpwr_data_len > 0)) {
+ pmadapter->ptxpwr_data = pparam->ptxpwr_data_buf;
+ pmadapter->txpwr_data_len = pparam->txpwr_data_len;
+ }
+ /** Save cal data in MLAN */
+ if ((pparam->pcal_data_buf) && (pparam->cal_data_len > 0)) {
+ pmadapter->pcal_data = pparam->pcal_data_buf;
+ pmadapter->cal_data_len = pparam->cal_data_len;
+ }
+
+ LEAVE();
+ return ret;
+}
+
+/**
+ * @brief This function initializes the firmware
+ *
+ * @param pmlan_adapter A pointer to a t_void pointer to store
+ * mlan_adapter structure pointer
+ *
+ * @return MLAN_STATUS_SUCCESS
+ * The firmware initialization succeeded.
+ * MLAN_STATUS_PENDING
+ * The firmware initialization is pending.
+ * MLAN_STATUS_FAILURE
+ * The firmware initialization failed.
+ */
+mlan_status mlan_init_fw(t_void *pmlan_adapter)
+{
+ mlan_status ret = MLAN_STATUS_SUCCESS;
+ mlan_adapter *pmadapter = (mlan_adapter *)pmlan_adapter;
+
+ ENTER();
+ MASSERT(pmlan_adapter);
+
+ pmadapter->hw_status = WlanHardwareStatusGetHwSpec;
+
+ /* Initialize firmware, may return PENDING */
+ ret = wlan_init_fw(pmadapter);
+ PRINTM(MINFO, "wlan_init_fw returned ret=0x%x\n", ret);
+
+ LEAVE();
+ return ret;
+}
+
+/**
+ * @brief Shutdown firmware
+ *
+ * @param pmlan_adapter A pointer to mlan_adapter structure
+ *
+ * @return MLAN_STATUS_SUCCESS
+ * The firmware shutdown call succeeded.
+ * MLAN_STATUS_PENDING
+ * The firmware shutdown call is pending.
+ * MLAN_STATUS_FAILURE
+ * The firmware shutdown call failed.
+ */
+mlan_status mlan_shutdown_fw(t_void *pmlan_adapter)
+{
+ mlan_status ret = MLAN_STATUS_PENDING;
+ mlan_adapter *pmadapter = (mlan_adapter *)pmlan_adapter;
+ pmlan_buffer pmbuf;
+ pmlan_ioctl_req pioctl_buf;
+ pmlan_callbacks pcb;
+ t_s32 i = 0;
+
+ ENTER();
+
+ MASSERT(pmlan_adapter);
+ /* MLAN already shutdown */
+ if (pmadapter->hw_status == WlanHardwareStatusNotReady) {
+ LEAVE();
+ return MLAN_STATUS_SUCCESS;
+ }
+
+ pmadapter->hw_status = WlanHardwareStatusClosing;
+ /* Wait for mlan_process to complete */
+ if (pmadapter->mlan_processing) {
+ PRINTM(MWARN, "MLAN main processing is still running\n");
+ LEAVE();
+ return ret;
+ }
+
+ /* Shut down MLAN */
+ PRINTM(MINFO, "Shutdown MLAN...\n");
+
+ /* Cancel all pending commands and complete ioctls */
+ wlan_cancel_all_pending_cmd(pmadapter, MTRUE);
+
+ /* Clean up priv structures */
+ for (i = 0; i < pmadapter->priv_num; i++) {
+ if (pmadapter->priv[i])
+ wlan_free_priv(pmadapter->priv[i]);
+ }
+
+ pcb = &pmadapter->callbacks;
+ /** cancel pending ioctl */
+ while ((pioctl_buf = (pmlan_ioctl_req)util_dequeue_list(
+ pmadapter->pmoal_handle, &pmadapter->ioctl_pending_q,
+ pcb->moal_spin_lock, pcb->moal_spin_unlock))) {
+ pioctl_buf->status_code = MLAN_ERROR_CMD_CANCEL;
+ pcb->moal_ioctl_complete(pmadapter->pmoal_handle, pioctl_buf,
+ MLAN_STATUS_FAILURE);
+ }
+
+ while ((pmbuf = (pmlan_buffer)util_dequeue_list(
+ pmadapter->pmoal_handle, &pmadapter->rx_data_queue,
+ pcb->moal_spin_lock, pcb->moal_spin_unlock))) {
+#ifdef USB
+ if (IS_USB(pmadapter->card_type))
+ pcb->moal_recv_complete(pmadapter->pmoal_handle, pmbuf,
+ pmadapter->rx_data_ep,
+ MLAN_STATUS_FAILURE);
+#endif
+#if defined(SDIO) || defined(PCIE)
+ if (!IS_USB(pmadapter->card_type))
+ wlan_free_mlan_buffer(pmadapter, pmbuf);
+#endif
+ }
+ pmadapter->rx_pkts_queued = 0;
+#ifdef PCIE
+ if (IS_PCIE(pmadapter->card_type) &&
+ wlan_set_drv_ready_reg(pmadapter, 0)) {
+ PRINTM(MERROR, "Failed to write driver not-ready signature\n");
+ }
+#endif
+
+ /* Notify completion */
+ ret = wlan_shutdown_fw_complete(pmadapter);
+
+ LEAVE();
+ return ret;
+}
+
+/**
+ * @brief queue main work
+ *
+ * @param pmadapter A pointer to mlan_adapter structure
+ *
+ * @return N/A
+ */
+static t_void mlan_queue_main_work(mlan_adapter *pmadapter)
+{
+ pmlan_callbacks pcb = &pmadapter->callbacks;
+ ENTER();
+ pcb->moal_spin_lock(pmadapter->pmoal_handle,
+ pmadapter->pmain_proc_lock);
+
+ /* Check if already processing */
+ if (pmadapter->mlan_processing) {
+ pmadapter->more_task_flag = MTRUE;
+ pcb->moal_spin_unlock(pmadapter->pmoal_handle,
+ pmadapter->pmain_proc_lock);
+ } else {
+ pcb->moal_spin_unlock(pmadapter->pmoal_handle,
+ pmadapter->pmain_proc_lock);
+ wlan_recv_event(wlan_get_priv(pmadapter, MLAN_BSS_ROLE_ANY),
+ MLAN_EVENT_ID_DRV_DEFER_HANDLING, MNULL);
+ }
+ LEAVE();
+ return;
+}
+
+/**
+ * @brief queue rx_work
+ *
+ * @param pmadapter A pointer to mlan_adapter structure
+ *
+ * @return N/A
+ */
+static t_void mlan_queue_rx_work(mlan_adapter *pmadapter)
+{
+ pmlan_callbacks pcb = &pmadapter->callbacks;
+ ENTER();
+
+ pcb->moal_spin_lock(pmadapter->pmoal_handle, pmadapter->prx_proc_lock);
+
+ /* Check if already processing */
+ if (pmadapter->mlan_rx_processing) {
+ pmadapter->more_rx_task_flag = MTRUE;
+ pcb->moal_spin_unlock(pmadapter->pmoal_handle,
+ pmadapter->prx_proc_lock);
+ } else {
+ pcb->moal_spin_unlock(pmadapter->pmoal_handle,
+ pmadapter->prx_proc_lock);
+ wlan_recv_event(wlan_get_priv(pmadapter, MLAN_BSS_ROLE_ANY),
+ MLAN_EVENT_ID_DRV_DEFER_RX_WORK, MNULL);
+ }
+ LEAVE();
+ return;
+}
+
+/**
+ * @brief block main process
+ *
+ * @param pmadapter A pointer to mlan_adapter structure
+ * @param block MTRUE/MFALSE
+ *
+ * @return N/A
+ */
+void mlan_block_main_process(mlan_adapter *pmadapter, t_u8 block)
+{
+ pmlan_callbacks pcb = &pmadapter->callbacks;
+ pcb->moal_spin_lock(pmadapter->pmoal_handle,
+ pmadapter->pmain_proc_lock);
+ if (!block) {
+ pmadapter->main_lock_flag = MFALSE;
+ pcb->moal_spin_unlock(pmadapter->pmoal_handle,
+ pmadapter->pmain_proc_lock);
+ } else {
+ pmadapter->main_lock_flag = MTRUE;
+ if (pmadapter->mlan_processing) {
+ pcb->moal_spin_unlock(pmadapter->pmoal_handle,
+ pmadapter->pmain_proc_lock);
+ PRINTM(MEVENT, "wlan: wait main work done...\n");
+ wlan_recv_event(
+ wlan_get_priv(pmadapter, MLAN_BSS_ROLE_ANY),
+ MLAN_EVENT_ID_DRV_FLUSH_MAIN_WORK, MNULL);
+ } else {
+ pcb->moal_spin_unlock(pmadapter->pmoal_handle,
+ pmadapter->pmain_proc_lock);
+ }
+ }
+}
+
+/**
+ * @brief block rx process
+ *
+ * @param pmadapter A pointer to mlan_adapter structure
+ * @param block MTRUE/MFALSE;
+ *
+ * @return N/A
+ */
+void mlan_block_rx_process(mlan_adapter *pmadapter, t_u8 block)
+{
+ pmlan_callbacks pcb = &pmadapter->callbacks;
+ pcb->moal_spin_lock(pmadapter->pmoal_handle, pmadapter->prx_proc_lock);
+ if (!block) {
+ pmadapter->rx_lock_flag = MFALSE;
+ pcb->moal_spin_unlock(pmadapter->pmoal_handle,
+ pmadapter->prx_proc_lock);
+ } else {
+ pmadapter->rx_lock_flag = MTRUE;
+ if (pmadapter->mlan_rx_processing) {
+ pcb->moal_spin_unlock(pmadapter->pmoal_handle,
+ pmadapter->prx_proc_lock);
+ PRINTM(MEVENT, "wlan: wait rx work done...\n");
+ wlan_recv_event(wlan_get_priv(pmadapter,
+ MLAN_BSS_ROLE_ANY),
+ MLAN_EVENT_ID_DRV_FLUSH_RX_WORK, MNULL);
+ } else {
+ pcb->moal_spin_unlock(pmadapter->pmoal_handle,
+ pmadapter->prx_proc_lock);
+ }
+ }
+}
+
+/**
+ * @brief The receive process
+ *
+ * @param pmlan_adapter A pointer to mlan_adapter structure
+ * @param rx_pkts A pointer to save receive pkts number
+ *
+ * @return MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ */
+mlan_status mlan_rx_process(t_void *pmlan_adapter, t_u8 *rx_pkts)
+{
+ mlan_status ret = MLAN_STATUS_SUCCESS;
+ mlan_adapter *pmadapter = (mlan_adapter *)pmlan_adapter;
+ pmlan_callbacks pcb;
+ pmlan_buffer pmbuf;
+ t_u8 limit = 0;
+ t_u8 rx_num = 0;
+
+ ENTER();
+
+ MASSERT(pmlan_adapter);
+ pcb = &pmadapter->callbacks;
+ pcb->moal_spin_lock(pmadapter->pmoal_handle, pmadapter->prx_proc_lock);
+ if (pmadapter->mlan_rx_processing || pmadapter->rx_lock_flag) {
+ pmadapter->more_rx_task_flag = MTRUE;
+ pcb->moal_spin_unlock(pmadapter->pmoal_handle,
+ pmadapter->prx_proc_lock);
+ goto exit_rx_proc;
+ } else {
+ pmadapter->mlan_rx_processing = MTRUE;
+ pcb->moal_spin_unlock(pmadapter->pmoal_handle,
+ pmadapter->prx_proc_lock);
+ }
+ if (rx_pkts)
+ limit = *rx_pkts;
+
+rx_process_start:
+ /* Check for Rx data */
+ while (MTRUE) {
+#ifdef DRV_EMBEDDED_AUTHENTICATOR
+ if (pmadapter->authenticator_priv) {
+ if (IsAuthenticatorEnabled(
+ pmadapter->authenticator_priv->psapriv)) {
+ AuthenticatorKeyMgmtInit(
+ pmadapter->authenticator_priv->psapriv,
+ pmadapter->authenticator_priv
+ ->curr_addr);
+ pmadapter->authenticator_priv = MNULL;
+ }
+ }
+#endif
+ if (pmadapter->flush_data) {
+ pmadapter->flush_data = MFALSE;
+ wlan_flush_rxreorder_tbl(pmadapter);
+ }
+ pmadapter->callbacks.moal_spin_lock(
+ pmadapter->pmoal_handle,
+ pmadapter->rx_data_queue.plock);
+ pmbuf = (pmlan_buffer)util_dequeue_list(
+ pmadapter->pmoal_handle, &pmadapter->rx_data_queue,
+ MNULL, MNULL);
+ if (!pmbuf) {
+ pmadapter->callbacks.moal_spin_unlock(
+ pmadapter->pmoal_handle,
+ pmadapter->rx_data_queue.plock);
+ break;
+ }
+ pmadapter->rx_pkts_queued--;
+ rx_num++;
+ pmadapter->callbacks.moal_spin_unlock(
+ pmadapter->pmoal_handle,
+ pmadapter->rx_data_queue.plock);
+
+ // rx_trace 6
+ if (pmadapter->tp_state_on)
+ pmadapter->callbacks.moal_tp_accounting(
+ pmadapter->pmoal_handle, pmbuf,
+ 6 /*RX_DROP_P2*/);
+ if (pmadapter->tp_state_drop_point == 6 /*RX_DROP_P2*/) {
+ pmadapter->ops.data_complete(pmadapter, pmbuf, ret);
+ goto rx_process_start;
+ }
+
+ if (pmadapter->delay_task_flag &&
+ (pmadapter->rx_pkts_queued < LOW_RX_PENDING)) {
+ PRINTM(MEVENT, "Run\n");
+ pmadapter->delay_task_flag = MFALSE;
+ mlan_queue_main_work(pmadapter);
+ }
+ pmadapter->ops.handle_rx_packet(pmadapter, pmbuf);
+ if (limit && rx_num >= limit)
+ break;
+ }
+ if (rx_pkts)
+ *rx_pkts = rx_num;
+ pcb->moal_spin_lock(pmadapter->pmoal_handle, pmadapter->prx_proc_lock);
+ if (pmadapter->more_rx_task_flag) {
+ pmadapter->more_rx_task_flag = MFALSE;
+ pcb->moal_spin_unlock(pmadapter->pmoal_handle,
+ pmadapter->prx_proc_lock);
+ goto rx_process_start;
+ }
+ pmadapter->mlan_rx_processing = MFALSE;
+ pcb->moal_spin_unlock(pmadapter->pmoal_handle,
+ pmadapter->prx_proc_lock);
+exit_rx_proc:
+ LEAVE();
+ return ret;
+}
+
+/**
+ * @brief The main process
+ *
+ * @param pmlan_adapter A pointer to mlan_adapter structure
+ *
+ * @return MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ */
+mlan_status mlan_main_process(t_void *pmlan_adapter)
+{
+ mlan_status ret = MLAN_STATUS_SUCCESS;
+ mlan_adapter *pmadapter = (mlan_adapter *)pmlan_adapter;
+ pmlan_callbacks pcb;
+
+ ENTER();
+
+ MASSERT(pmlan_adapter);
+
+ pcb = &pmadapter->callbacks;
+
+ pcb->moal_spin_lock(pmadapter->pmoal_handle,
+ pmadapter->pmain_proc_lock);
+
+ /* Check if already processing */
+ if (pmadapter->mlan_processing || pmadapter->main_lock_flag) {
+ pmadapter->more_task_flag = MTRUE;
+ pcb->moal_spin_unlock(pmadapter->pmoal_handle,
+ pmadapter->pmain_proc_lock);
+ goto exit_main_proc;
+ } else {
+ pmadapter->mlan_processing = MTRUE;
+ pmadapter->main_process_cnt++;
+ pcb->moal_spin_unlock(pmadapter->pmoal_handle,
+ pmadapter->pmain_proc_lock);
+ }
+process_start:
+ do {
+ /* Is MLAN shutting down or not ready? */
+ if ((pmadapter->hw_status == WlanHardwareStatusClosing) ||
+ (pmadapter->hw_status == WlanHardwareStatusNotReady))
+ break;
+ if (pmadapter->pending_ioctl) {
+ wlan_process_pending_ioctl(pmadapter);
+ pmadapter->pending_ioctl = MFALSE;
+ }
+ if (pmadapter->pending_disconnect_priv) {
+ PRINTM(MEVENT, "Reset connect state\n");
+ wlan_reset_connect_state(
+ pmadapter->pending_disconnect_priv, MTRUE);
+ pmadapter->pending_disconnect_priv = MNULL;
+ }
+#if defined(SDIO) || defined(PCIE)
+ if (!IS_USB(pmadapter->card_type)) {
+ if (pmadapter->rx_pkts_queued > HIGH_RX_PENDING) {
+ pcb->moal_tp_accounting_rx_param(
+ pmadapter->pmoal_handle, 2, 0);
+ PRINTM(MEVENT, "Pause\n");
+ pmadapter->delay_task_flag = MTRUE;
+ mlan_queue_rx_work(pmadapter);
+ break;
+ }
+ /* Handle pending interrupts if any */
+ if (pmadapter->ireg) {
+ if (pmadapter->hs_activated == MTRUE)
+ wlan_process_hs_config(pmadapter);
+ pmadapter->ops.process_int_status(pmadapter);
+ if (pmadapter->data_received)
+ mlan_queue_rx_work(pmadapter);
+ }
+ }
+#endif
+
+ /* Need to wake up the card ? */
+ if ((pmadapter->ps_state == PS_STATE_SLEEP) &&
+ (pmadapter->pm_wakeup_card_req &&
+ !pmadapter->pm_wakeup_fw_try) &&
+ (wlan_is_cmd_pending(pmadapter) ||
+ !wlan_bypass_tx_list_empty(pmadapter) ||
+ !wlan_wmm_lists_empty(pmadapter))) {
+ pmadapter->ops.wakeup_card(pmadapter, MTRUE);
+ pmadapter->pm_wakeup_fw_try = MTRUE;
+ continue;
+ }
+ if (IS_CARD_RX_RCVD(pmadapter) ||
+ (!pmadapter->cmd_sent &&
+ pmadapter->vdll_ctrl.pending_block)) {
+ pmadapter->data_received = MFALSE;
+ if (pmadapter->hs_activated == MTRUE) {
+ pmadapter->is_hs_configured = MFALSE;
+ wlan_host_sleep_activated_event(
+ wlan_get_priv(pmadapter,
+ MLAN_BSS_ROLE_ANY),
+ MFALSE);
+ }
+ pmadapter->pm_wakeup_fw_try = MFALSE;
+ if (pmadapter->ps_state == PS_STATE_SLEEP)
+ pmadapter->ps_state = PS_STATE_AWAKE;
+ if (pmadapter->wakeup_fw_timer_is_set) {
+ pcb->moal_stop_timer(
+ pmadapter->pmoal_handle,
+ pmadapter->pwakeup_fw_timer);
+ pmadapter->wakeup_fw_timer_is_set = MFALSE;
+ }
+ } else {
+ /* We have tried to wakeup the card already */
+ if (pmadapter->pm_wakeup_fw_try)
+ break;
+ /* Check if we need to confirm Sleep Request received
+ * previously */
+ if (pmadapter->ps_state == PS_STATE_PRE_SLEEP)
+ if (!pmadapter->cmd_sent &&
+ !pmadapter->curr_cmd &&
+ !pmadapter->vdll_ctrl.pending_block)
+ wlan_check_ps_cond(pmadapter);
+ if (pmadapter->ps_state != PS_STATE_AWAKE ||
+ (pmadapter->tx_lock_flag == MTRUE))
+ break;
+
+ if (pmadapter->data_sent ||
+ (wlan_bypass_tx_list_empty(pmadapter) &&
+ wlan_wmm_lists_empty(pmadapter)) ||
+ wlan_11h_radar_detected_tx_blocked(pmadapter)) {
+ if (pmadapter->cmd_sent ||
+ pmadapter->curr_cmd ||
+ !wlan_is_cmd_pending(pmadapter)) {
+ break;
+ }
+ }
+ }
+
+ /* Check for Cmd Resp */
+ if (pmadapter->cmd_resp_received) {
+ pmadapter->cmd_resp_received = MFALSE;
+ wlan_process_cmdresp(pmadapter);
+
+ /* call moal back when init_fw is done */
+ if (pmadapter->hw_status ==
+ WlanHardwareStatusInitdone) {
+ pmadapter->hw_status = WlanHardwareStatusReady;
+ wlan_init_fw_complete(pmadapter);
+ } else if (pmadapter->hw_status ==
+ WlanHardwareStatusGetHwSpecdone) {
+ pmadapter->hw_status =
+ WlanHardwareStatusInitializing;
+ wlan_get_hw_spec_complete(pmadapter);
+ }
+ }
+
+ /* Check for event */
+ if (pmadapter->event_received) {
+ pmadapter->event_received = MFALSE;
+ wlan_process_event(pmadapter);
+ }
+
+ /* Check if we need to confirm Sleep Request received previously
+ */
+ if (pmadapter->ps_state == PS_STATE_PRE_SLEEP)
+ if (!pmadapter->cmd_sent && !pmadapter->curr_cmd &&
+ !pmadapter->vdll_ctrl.pending_block)
+ wlan_check_ps_cond(pmadapter);
+
+ /*
+ * The ps_state may have been changed during processing of
+ * Sleep Request event.
+ */
+ if ((pmadapter->ps_state == PS_STATE_SLEEP) ||
+ (pmadapter->ps_state == PS_STATE_PRE_SLEEP) ||
+ (pmadapter->ps_state == PS_STATE_SLEEP_CFM) ||
+ (pmadapter->tx_lock_flag == MTRUE)) {
+ continue;
+ }
+
+ /* in a case of race condition, download the VDLL block here */
+ if (!pmadapter->cmd_sent &&
+ pmadapter->vdll_ctrl.pending_block) {
+ wlan_download_vdll_block(
+ pmadapter, pmadapter->vdll_ctrl.pending_block,
+ pmadapter->vdll_ctrl.pending_block_len);
+ pmadapter->vdll_ctrl.pending_block = MNULL;
+ }
+ if (!pmadapter->cmd_sent && !pmadapter->curr_cmd) {
+ if (wlan_exec_next_cmd(pmadapter) ==
+ MLAN_STATUS_FAILURE) {
+ ret = MLAN_STATUS_FAILURE;
+ break;
+ }
+ }
+
+ if (!pmadapter->data_sent &&
+ !wlan_11h_radar_detected_tx_blocked(pmadapter) &&
+ !wlan_bypass_tx_list_empty(pmadapter)) {
+ PRINTM(MINFO, "mlan_send_pkt(): deq(bybass_txq)\n");
+ wlan_process_bypass_tx(pmadapter);
+ if (pmadapter->hs_activated == MTRUE) {
+ pmadapter->is_hs_configured = MFALSE;
+ wlan_host_sleep_activated_event(
+ wlan_get_priv(pmadapter,
+ MLAN_BSS_ROLE_ANY),
+ MFALSE);
+ }
+ }
+
+ if (!pmadapter->data_sent && !wlan_wmm_lists_empty(pmadapter) &&
+ !wlan_11h_radar_detected_tx_blocked(pmadapter)) {
+ wlan_wmm_process_tx(pmadapter);
+ if (pmadapter->hs_activated == MTRUE) {
+ pmadapter->is_hs_configured = MFALSE;
+ wlan_host_sleep_activated_event(
+ wlan_get_priv(pmadapter,
+ MLAN_BSS_ROLE_ANY),
+ MFALSE);
+ }
+ }
+
+#ifdef STA_SUPPORT
+ if (pmadapter->delay_null_pkt && !pmadapter->cmd_sent &&
+ !pmadapter->curr_cmd && !wlan_is_cmd_pending(pmadapter) &&
+ wlan_bypass_tx_list_empty(pmadapter) &&
+ wlan_wmm_lists_empty(pmadapter)) {
+ if (wlan_send_null_packet(
+ wlan_get_priv(pmadapter, MLAN_BSS_ROLE_STA),
+ MRVDRV_TxPD_POWER_MGMT_NULL_PACKET |
+ MRVDRV_TxPD_POWER_MGMT_LAST_PACKET) ==
+ MLAN_STATUS_SUCCESS) {
+ pmadapter->delay_null_pkt = MFALSE;
+ }
+ break;
+ }
+#endif
+
+ } while (MTRUE);
+
+ pcb->moal_spin_lock(pmadapter->pmoal_handle,
+ pmadapter->pmain_proc_lock);
+ if (pmadapter->more_task_flag == MTRUE) {
+ pmadapter->more_task_flag = MFALSE;
+ pcb->moal_spin_unlock(pmadapter->pmoal_handle,
+ pmadapter->pmain_proc_lock);
+ goto process_start;
+ }
+ pmadapter->mlan_processing = MFALSE;
+ pcb->moal_spin_unlock(pmadapter->pmoal_handle,
+ pmadapter->pmain_proc_lock);
+
+exit_main_proc:
+ if (pmadapter->hw_status == WlanHardwareStatusClosing)
+ mlan_shutdown_fw(pmadapter);
+ LEAVE();
+ return ret;
+}
+
+/**
+ * @brief Function to send packet
+ *
+ * @param pmlan_adapter A pointer to mlan_adapter structure
+ * @param pmbuf A pointer to mlan_buffer structure
+ *
+ * @return MLAN_STATUS_PENDING
+ */
+mlan_status mlan_send_packet(t_void *pmlan_adapter, pmlan_buffer pmbuf)
+{
+ mlan_status ret = MLAN_STATUS_PENDING;
+ mlan_adapter *pmadapter = (mlan_adapter *)pmlan_adapter;
+ mlan_private *pmpriv;
+ t_u16 eth_type = 0;
+
+ ENTER();
+ MASSERT(pmlan_adapter && pmbuf);
+
+ if (!pmlan_adapter || !pmbuf) {
+ return MLAN_STATUS_FAILURE;
+ }
+
+ MASSERT(pmbuf->bss_index < pmadapter->priv_num);
+ pmbuf->flags |= MLAN_BUF_FLAG_MOAL_TX_BUF;
+ pmpriv = pmadapter->priv[pmbuf->bss_index];
+
+ eth_type =
+ mlan_ntohs(*(t_u16 *)&pmbuf->pbuf[pmbuf->data_offset +
+ MLAN_ETHER_PKT_TYPE_OFFSET]);
+ if (((pmadapter->priv[pmbuf->bss_index]->port_ctrl_mode == MTRUE) &&
+ ((eth_type == MLAN_ETHER_PKT_TYPE_EAPOL) ||
+ (eth_type == MLAN_ETHER_PKT_TYPE_ARP) ||
+ (eth_type == MLAN_ETHER_PKT_TYPE_WAPI))) ||
+ (pmbuf->buf_type == MLAN_BUF_TYPE_RAW_DATA)
+
+ ) {
+ if (eth_type == MLAN_ETHER_PKT_TYPE_EAPOL) {
+ PRINTM_NETINTF(MMSG, pmpriv);
+ PRINTM(MMSG, "wlan: Send EAPOL pkt to " MACSTR "\n",
+ MAC2STR(pmbuf->pbuf + pmbuf->data_offset));
+ }
+ if (pmadapter->tp_state_on)
+ pmadapter->callbacks.moal_tp_accounting(
+ pmadapter->pmoal_handle, pmbuf->pdesc, 2);
+ if (pmadapter->tp_state_drop_point == 2)
+ return 0;
+ else
+ wlan_add_buf_bypass_txqueue(pmadapter, pmbuf);
+ } else {
+ if (pmadapter->tp_state_on)
+ pmadapter->callbacks.moal_tp_accounting(
+ pmadapter->pmoal_handle, pmbuf->pdesc, 2);
+ if (pmadapter->tp_state_drop_point == 2)
+ return 0;
+ else
+ /* Transmit the packet*/
+ wlan_wmm_add_buf_txqueue(pmadapter, pmbuf);
+ }
+
+ LEAVE();
+ return ret;
+}
+
+/**
+ * @brief MLAN ioctl handler
+ *
+ * @param adapter A pointer to mlan_adapter structure
+ * @param pioctl_req A pointer to ioctl request buffer
+ *
+ * @return MLAN_STATUS_SUCCESS/MLAN_STATUS_PENDING --success,
+ * otherwise fail
+ */
+mlan_status mlan_ioctl(t_void *adapter, pmlan_ioctl_req pioctl_req)
+{
+ mlan_status ret = MLAN_STATUS_SUCCESS;
+ pmlan_adapter pmadapter = (pmlan_adapter)adapter;
+ pmlan_private pmpriv = MNULL;
+
+ ENTER();
+
+ if (pioctl_req == MNULL) {
+ PRINTM(MMSG, "Cancel all pending cmd!\n");
+ wlan_cancel_all_pending_cmd(pmadapter, MFALSE);
+ goto exit;
+ }
+ if (pioctl_req->action == MLAN_ACT_CANCEL) {
+ wlan_cancel_pending_ioctl(pmadapter, pioctl_req);
+ ret = MLAN_STATUS_SUCCESS;
+ goto exit;
+ }
+ pmpriv = pmadapter->priv[pioctl_req->bss_index];
+ ret = pmpriv->ops.ioctl(adapter, pioctl_req);
+exit:
+ LEAVE();
+ return ret;
+}
+
+#ifdef USB
+/**
+ * @brief Packet send completion callback
+ *
+ * @param pmlan_adapter A pointer to mlan_adapter structure
+ * @param pmbuf A pointer to mlan_buffer structure
+ * @param port Data port
+ * @param status Callback status
+ *
+ * @return MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ */
+mlan_status mlan_write_data_async_complete(t_void *pmlan_adapter,
+ pmlan_buffer pmbuf, t_u32 port,
+ mlan_status status)
+{
+ mlan_status ret = MLAN_STATUS_SUCCESS;
+ mlan_adapter *pmadapter = (mlan_adapter *)pmlan_adapter;
+
+ ENTER();
+
+ if (port == pmadapter->tx_cmd_ep) {
+ pmadapter->cmd_sent = MFALSE;
+ PRINTM(MCMND, "mlan_write_data_async_complete: CMD\n");
+ /* pmbuf was allocated by MLAN */
+ wlan_free_mlan_buffer(pmadapter, pmbuf);
+ } else {
+ pmadapter->data_sent = MFALSE;
+ ret = wlan_write_data_complete(pmadapter, pmbuf, status);
+ }
+
+ LEAVE();
+ return ret;
+}
+
+/**
+ * @brief Packet receive handler
+ *
+ * @param pmlan_adapter A pointer to mlan_adapter structure
+ * @param pmbuf A pointer to mlan_buffer structure
+ * @param port Data port
+ *
+ * @return MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE or
+ * MLAN_STATUS_PENDING
+ */
+mlan_status mlan_recv(t_void *pmlan_adapter, pmlan_buffer pmbuf, t_u32 port)
+{
+ mlan_status ret = MLAN_STATUS_PENDING;
+ mlan_adapter *pmadapter = (mlan_adapter *)pmlan_adapter;
+ t_u8 *pbuf;
+ t_u32 len, recv_type;
+ t_u32 event_cause;
+#ifdef DEBUG_LEVEL1
+ t_u32 sec, usec;
+#endif
+ t_u32 max_rx_data_size = MLAN_RX_DATA_BUF_SIZE;
+
+ ENTER();
+
+ MASSERT(pmlan_adapter && pmbuf);
+
+ if (pmadapter->hs_activated == MTRUE)
+ wlan_process_hs_config(pmadapter);
+ pbuf = pmbuf->pbuf + pmbuf->data_offset;
+ len = pmbuf->data_len;
+
+ MASSERT(len >= MLAN_TYPE_LEN);
+ recv_type = *(t_u32 *)pbuf;
+ recv_type = wlan_le32_to_cpu(recv_type);
+ pbuf += MLAN_TYPE_LEN;
+ len -= MLAN_TYPE_LEN;
+
+ if (port == pmadapter->rx_cmd_ep) {
+ switch (recv_type) {
+ case MLAN_USB_TYPE_CMD:
+ PRINTM_GET_SYS_TIME(MCMND, &sec, &usec);
+ PRINTM(MCMND, "mlan_recv: CMD (%lu.%06lu)\n", sec,
+ usec);
+ if (len > MRVDRV_SIZE_OF_CMD_BUFFER) {
+ pmbuf->status_code = MLAN_ERROR_CMD_RESP_FAIL;
+ ret = MLAN_STATUS_FAILURE;
+ PRINTM(MERROR, "mlan_recv: CMD too large\n");
+ } else if (!pmadapter->curr_cmd) {
+ if (pmadapter->ps_state == PS_STATE_SLEEP_CFM) {
+ pmbuf->data_offset += MLAN_TYPE_LEN;
+ pmbuf->data_len -= MLAN_TYPE_LEN;
+ wlan_process_sleep_confirm_resp(
+ pmadapter,
+ pmbuf->pbuf +
+ pmbuf->data_offset,
+ pmbuf->data_len);
+ pmbuf->flags |=
+ MLAN_BUF_FLAG_SLEEPCFM_RESP;
+ ret = MLAN_STATUS_SUCCESS;
+
+ } else {
+ pmbuf->status_code =
+ MLAN_ERROR_CMD_RESP_FAIL;
+ ret = MLAN_STATUS_FAILURE;
+ }
+ PRINTM(MINFO, "mlan_recv: no curr_cmd\n");
+ } else {
+ pmadapter->upld_len = len;
+ pmbuf->data_offset += MLAN_TYPE_LEN;
+ pmbuf->data_len -= MLAN_TYPE_LEN;
+ pmadapter->curr_cmd->respbuf = pmbuf;
+ pmadapter->cmd_resp_received = MTRUE;
+ }
+ break;
+ case MLAN_USB_TYPE_EVENT:
+ MASSERT(len >= sizeof(t_u32));
+ memmove(pmadapter, &event_cause, pbuf, sizeof(t_u32));
+ pmadapter->event_cause = wlan_le32_to_cpu(event_cause);
+ PRINTM_GET_SYS_TIME(MEVENT, &sec, &usec);
+ PRINTM(MEVENT, "mlan_recv: EVENT 0x%x (%lu.%06lu)\n",
+ pmadapter->event_cause, sec, usec);
+ pbuf += sizeof(t_u32);
+ len -= sizeof(t_u32);
+ if ((len > 0) && (len < MAX_EVENT_SIZE))
+ memmove(pmadapter, pmadapter->event_body, pbuf,
+ len);
+ pmadapter->event_received = MTRUE;
+ pmadapter->pmlan_buffer_event = pmbuf;
+ /* remove 4 byte recv_type */
+ pmbuf->data_offset += MLAN_TYPE_LEN;
+ pmbuf->data_len -= MLAN_TYPE_LEN;
+ /* MOAL to call mlan_main_process for processing */
+ break;
+ default:
+ pmbuf->status_code = MLAN_ERROR_PKT_INVALID;
+ ret = MLAN_STATUS_FAILURE;
+ PRINTM(MERROR, "mlan_recv: unknown recv_type 0x%x\n",
+ recv_type);
+ break;
+ }
+ } else if (port == pmadapter->rx_data_ep) {
+ PRINTM_GET_SYS_TIME(MDATA, &sec, &usec);
+ PRINTM(MDATA, "mlan_recv: DATA (%lu.%06lu)\n", sec, usec);
+#if defined(USB)
+ if (pmadapter->pcard_usb->usb_rx_deaggr.aggr_ctrl.enable) {
+ max_rx_data_size = pmadapter->pcard_usb->usb_rx_deaggr
+ .aggr_ctrl.aggr_max;
+ if (pmadapter->pcard_usb->usb_rx_deaggr.aggr_ctrl
+ .aggr_mode == MLAN_USB_AGGR_MODE_NUM) {
+ max_rx_data_size *=
+ MAX(MLAN_USB_MAX_PKT_SIZE,
+ pmadapter->pcard_usb->usb_rx_deaggr
+ .aggr_ctrl.aggr_align);
+ max_rx_data_size = MAX(max_rx_data_size,
+ MLAN_RX_DATA_BUF_SIZE);
+ }
+ }
+#endif
+ if (len > max_rx_data_size) {
+ pmbuf->status_code = MLAN_ERROR_PKT_SIZE_INVALID;
+ ret = MLAN_STATUS_FAILURE;
+ PRINTM(MERROR, "mlan_recv: DATA too large\n");
+ } else {
+ pmadapter->upld_len = len;
+ pmadapter->callbacks.moal_get_system_time(
+ pmadapter->pmoal_handle, &pmbuf->in_ts_sec,
+ &pmbuf->in_ts_usec);
+ pmadapter->callbacks.moal_spin_lock(
+ pmadapter->pmoal_handle,
+ pmadapter->rx_data_queue.plock);
+ util_enqueue_list_tail(pmadapter->pmoal_handle,
+ &pmadapter->rx_data_queue,
+ (pmlan_linked_list)pmbuf, MNULL,
+ MNULL);
+ pmadapter->rx_pkts_queued++;
+ pmadapter->callbacks.moal_spin_unlock(
+ pmadapter->pmoal_handle,
+ pmadapter->rx_data_queue.plock);
+ pmadapter->data_received = MTRUE;
+ mlan_queue_rx_work(pmadapter);
+ }
+ } else {
+ pmbuf->status_code = MLAN_ERROR_PKT_INVALID;
+ ret = MLAN_STATUS_FAILURE;
+ PRINTM(MERROR, "mlan_recv: unknown port number 0x%x\n", port);
+ }
+
+ LEAVE();
+ return ret;
+}
+#endif /* USB */
+
+/**
+ * @brief Packet receive completion callback handler
+ *
+ * @param pmlan_adapter A pointer to mlan_adapter structure
+ * @param pmbuf A pointer to mlan_buffer structure
+ * @param status Callback status
+ *
+ * @return MLAN_STATUS_SUCCESS
+ */
+mlan_status mlan_recv_packet_complete(t_void *pmlan_adapter, pmlan_buffer pmbuf,
+ mlan_status status)
+{
+ mlan_adapter *pmadapter = (mlan_adapter *)pmlan_adapter;
+
+ ENTER();
+ wlan_recv_packet_complete(pmadapter, pmbuf, status);
+ LEAVE();
+ return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ * @brief select wmm queue
+ *
+ * @param pmlan_adapter A pointer to mlan_adapter structure
+ * @param bss_num BSS number
+ * @param tid TID
+ *
+ * @return wmm queue priority (0 - 3)
+ */
+t_u8 mlan_select_wmm_queue(t_void *pmlan_adapter, t_u8 bss_num, t_u8 tid)
+{
+ mlan_adapter *pmadapter = (mlan_adapter *)pmlan_adapter;
+ pmlan_private pmpriv = pmadapter->priv[bss_num];
+ t_u8 ret;
+ ENTER();
+ ret = wlan_wmm_select_queue(pmpriv, tid);
+ LEAVE();
+ return ret;
+}
+
+#if defined(SDIO) || defined(PCIE)
+/**
+ * @brief This function gets interrupt status.
+ * @param msg_id only used for PCIE
+ */
+/**
+ * @param msg_id A message id
+ * @param adapter A pointer to mlan_adapter structure
+ * @return MLAN_STATUS_FAILURE -- if the intererupt is not for us
+ */
+mlan_status mlan_interrupt(t_u16 msg_id, t_void *adapter)
+{
+ mlan_adapter *pmadapter = (mlan_adapter *)adapter;
+ mlan_status ret;
+
+ ENTER();
+ ret = pmadapter->ops.interrupt(msg_id, pmadapter);
+ LEAVE();
+ return ret;
+}
+#endif
+
+/**
+ * @brief This function wakeup firmware.
+ *
+ * @param adapter A pointer to mlan_adapter structure
+ * @param keep_wakeup keep wake up flag
+ * @return N/A
+ */
+t_void mlan_pm_wakeup_card(t_void *adapter, t_u8 keep_wakeup)
+{
+ mlan_adapter *pmadapter = (mlan_adapter *)adapter;
+
+ ENTER();
+ if (keep_wakeup)
+ pmadapter->ops.wakeup_card(pmadapter, MFALSE);
+ pmadapter->keep_wakeup = keep_wakeup;
+
+ LEAVE();
+}
+
+/**
+ * @brief This function check main_process status.
+ *
+ * @param adapter A pointer to mlan_adapter structure
+ * @return MTRUE/MFALSE
+ */
+t_u8 mlan_is_main_process_running(t_void *adapter)
+{
+ mlan_adapter *pmadapter = (mlan_adapter *)adapter;
+ pmlan_callbacks pcb = &pmadapter->callbacks;
+ t_u8 ret = MFALSE;
+ ENTER();
+ pcb->moal_spin_lock(pmadapter->pmoal_handle,
+ pmadapter->pmain_proc_lock);
+
+ /* Check if already processing */
+ if (pmadapter->mlan_processing) {
+ pmadapter->more_task_flag = MTRUE;
+ ret = MTRUE;
+ }
+ pcb->moal_spin_unlock(pmadapter->pmoal_handle,
+ pmadapter->pmain_proc_lock);
+ LEAVE();
+ return ret;
+}
+
+#ifdef PCIE
+/**
+ * @brief This function sets the PCIE interrupt mode.
+ *
+ * @param adapter A pointer to mlan_adapter structure
+ * @param int_mode PCIE interrupt type active
+ * @param func_num PCIE function num
+ * @return N/A
+ */
+t_void mlan_set_int_mode(t_void *adapter, t_u32 int_mode, t_u8 func_num)
+{
+ mlan_adapter *pmadapter = (mlan_adapter *)adapter;
+ ENTER();
+ pmadapter->pcard_pcie->pcie_int_mode = int_mode;
+ pmadapter->pcard_pcie->func_num = func_num;
+ LEAVE();
+}
+#endif
diff --git a/drivers/net/wireless/nxp/mxm_wifiex/wlan_src/mlan/mlan_sta_cmd.c b/drivers/net/wireless/nxp/mxm_wifiex/wlan_src/mlan/mlan_sta_cmd.c
new file mode 100644
index 000000000000..314e8fb7f3e4
--- /dev/null
+++ b/drivers/net/wireless/nxp/mxm_wifiex/wlan_src/mlan/mlan_sta_cmd.c
@@ -0,0 +1,2950 @@
+/** @file mlan_sta_cmd.c
+ *
+ * @brief This file contains the handling of command.
+ * it prepares command and sends it to firmware when
+ * it is ready.
+ *
+ *
+ * Copyright 2014-2020 NXP
+ *
+ * This software file (the File) is distributed by NXP
+ * under the terms of the GNU General Public License Version 2, June 1991
+ * (the License). You may use, redistribute and/or modify the 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.
+ *
+ */
+
+/******************************************************
+ * Change log:
+ * 10/21/2008: initial version
+ ******************************************************/
+
+#include "mlan.h"
+#include "mlan_join.h"
+#include "mlan_util.h"
+#include "mlan_fw.h"
+#include "mlan_main.h"
+#include "mlan_wmm.h"
+#include "mlan_11n.h"
+#include "mlan_11ac.h"
+#include "mlan_11ax.h"
+#include "mlan_11h.h"
+#ifdef SDIO
+#include "mlan_sdio.h"
+#endif /* SDIO */
+#include "mlan_meas.h"
+#ifdef PCIE
+#include "mlan_pcie.h"
+#endif /* PCIE */
+
+/********************************************************
+ * Local Variables
+ ********************************************************/
+
+/********************************************************
+ * Global Variables
+ ********************************************************/
+
+/********************************************************
+ * Local Functions
+ ********************************************************/
+
+/**
+ * @brief This function prepares command of RSSI info.
+ *
+ * @param pmpriv A pointer to mlan_private structure
+ * @param pcmd A pointer to HostCmd_DS_COMMAND structure
+ * @param cmd_action Command action
+ *
+ * @return MLAN_STATUS_SUCCESS
+ */
+static mlan_status wlan_cmd_802_11_rssi_info(pmlan_private pmpriv,
+ HostCmd_DS_COMMAND *pcmd,
+ t_u16 cmd_action)
+{
+ ENTER();
+
+ pcmd->command = wlan_cpu_to_le16(HostCmd_CMD_RSSI_INFO);
+ pcmd->size = wlan_cpu_to_le16(sizeof(HostCmd_DS_802_11_RSSI_INFO) +
+ S_DS_GEN);
+ pcmd->params.rssi_info.action = wlan_cpu_to_le16(cmd_action);
+ pcmd->params.rssi_info.ndata =
+ wlan_cpu_to_le16(pmpriv->data_avg_factor);
+ pcmd->params.rssi_info.nbcn = wlan_cpu_to_le16(pmpriv->bcn_avg_factor);
+
+ /* Reset SNR/NF/RSSI values in private structure */
+ pmpriv->data_rssi_last = 0;
+ pmpriv->data_nf_last = 0;
+ pmpriv->data_rssi_avg = 0;
+ pmpriv->data_nf_avg = 0;
+ pmpriv->bcn_rssi_last = 0;
+ pmpriv->bcn_nf_last = 0;
+ pmpriv->bcn_rssi_avg = 0;
+ pmpriv->bcn_nf_avg = 0;
+
+ LEAVE();
+ return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ * @brief This function prepares command of RSSI info.
+ *
+ * @param pmpriv A pointer to mlan_private structure
+ * @param pcmd A pointer to HostCmd_DS_COMMAND structure
+ * @param cmd_action Command action
+ *
+ * @return MLAN_STATUS_SUCCESS
+ */
+static mlan_status wlan_cmd_802_11_rssi_info_ext(pmlan_private pmpriv,
+ HostCmd_DS_COMMAND *pcmd,
+ t_u16 cmd_action,
+ t_void *pdata_buf)
+{
+ HostCmd_DS_802_11_RSSI_INFO_EXT *rssi_info_ext_cmd =
+ &pcmd->params.rssi_info_ext;
+ mlan_ds_get_info *info = (mlan_ds_get_info *)pdata_buf;
+ MrvlIEtypes_RSSI_EXT_t *signal_info_tlv = MNULL;
+ t_u8 *pos = MNULL;
+
+ ENTER();
+
+ pcmd->command = wlan_cpu_to_le16(HostCmd_CMD_RSSI_INFO_EXT);
+ pcmd->size = sizeof(HostCmd_DS_802_11_RSSI_INFO_EXT) + S_DS_GEN;
+ rssi_info_ext_cmd->action = wlan_cpu_to_le16(cmd_action);
+ rssi_info_ext_cmd->ndata = 0;
+ rssi_info_ext_cmd->nbcn = 0;
+
+ if (info->param.path_id) {
+ pos = (t_u8 *)rssi_info_ext_cmd->tlv_buf;
+ signal_info_tlv = (MrvlIEtypes_RSSI_EXT_t *)pos;
+ signal_info_tlv->header.len =
+ wlan_cpu_to_le16(sizeof(MrvlIEtypes_RSSI_EXT_t) -
+ sizeof(MrvlIEtypesHeader_t));
+ signal_info_tlv->header.type =
+ wlan_cpu_to_le16(TLV_TYPE_RSSI_INFO);
+ signal_info_tlv->path_id =
+ wlan_cpu_to_le16(info->param.path_id);
+ pcmd->size += sizeof(MrvlIEtypes_RSSI_EXT_t);
+ }
+ pcmd->size = wlan_cpu_to_le16(pcmd->size);
+ LEAVE();
+ return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ * @brief This function prepares command of snmp_mib.
+ *
+ * @param pmpriv A pointer to mlan_private structure
+ * @param cmd A pointer to HostCmd_DS_COMMAND structure
+ * @param cmd_action The action: GET or SET
+ * @param cmd_oid OID: ENABLE or DISABLE
+ * @param pdata_buf A pointer to command information buffer
+ *
+ * @return MLAN_STATUS_SUCCESS
+ */
+static mlan_status wlan_cmd_802_11_snmp_mib(pmlan_private pmpriv,
+ HostCmd_DS_COMMAND *cmd,
+ t_u16 cmd_action, t_u32 cmd_oid,
+ t_void *pdata_buf)
+{
+ HostCmd_DS_802_11_SNMP_MIB *psnmp_mib = &cmd->params.smib;
+ t_u32 ul_temp;
+
+ ENTER();
+ PRINTM(MINFO, "SNMP_CMD: cmd_oid = 0x%x\n", cmd_oid);
+ cmd->command = wlan_cpu_to_le16(HostCmd_CMD_802_11_SNMP_MIB);
+ cmd->size = sizeof(HostCmd_DS_802_11_SNMP_MIB) - 1 + S_DS_GEN;
+
+ if (cmd_action == HostCmd_ACT_GEN_GET) {
+ psnmp_mib->query_type = wlan_cpu_to_le16(HostCmd_ACT_GEN_GET);
+ psnmp_mib->buf_size = wlan_cpu_to_le16(MAX_SNMP_BUF_SIZE);
+ cmd->size += MAX_SNMP_BUF_SIZE;
+ }
+
+ switch (cmd_oid) {
+ case DtimPeriod_i:
+ psnmp_mib->oid = wlan_cpu_to_le16((t_u16)DtimPeriod_i);
+ if (cmd_action == HostCmd_ACT_GEN_SET) {
+ psnmp_mib->query_type =
+ wlan_cpu_to_le16(HostCmd_ACT_GEN_SET);
+ psnmp_mib->buf_size = wlan_cpu_to_le16(sizeof(t_u8));
+ ul_temp = *((t_u32 *)pdata_buf);
+ psnmp_mib->value[0] = (t_u8)ul_temp;
+ cmd->size += sizeof(t_u8);
+ }
+ break;
+ case FragThresh_i:
+ psnmp_mib->oid = wlan_cpu_to_le16((t_u16)FragThresh_i);
+ if (cmd_action == HostCmd_ACT_GEN_SET) {
+ psnmp_mib->query_type =
+ wlan_cpu_to_le16(HostCmd_ACT_GEN_SET);
+ psnmp_mib->buf_size = wlan_cpu_to_le16(sizeof(t_u16));
+ ul_temp = *((t_u32 *)pdata_buf);
+ *((t_u16 *)(psnmp_mib->value)) =
+ wlan_cpu_to_le16((t_u16)ul_temp);
+ cmd->size += sizeof(t_u16);
+ }
+ break;
+ case RtsThresh_i:
+ psnmp_mib->oid = wlan_cpu_to_le16((t_u16)RtsThresh_i);
+ if (cmd_action == HostCmd_ACT_GEN_SET) {
+ psnmp_mib->query_type =
+ wlan_cpu_to_le16(HostCmd_ACT_GEN_SET);
+ psnmp_mib->buf_size = wlan_cpu_to_le16(sizeof(t_u16));
+ ul_temp = *((t_u32 *)pdata_buf);
+ *(t_u16 *)(psnmp_mib->value) =
+ wlan_cpu_to_le16((t_u16)ul_temp);
+ cmd->size += sizeof(t_u16);
+ }
+ break;
+
+ case ShortRetryLim_i:
+ psnmp_mib->oid = wlan_cpu_to_le16((t_u16)ShortRetryLim_i);
+ if (cmd_action == HostCmd_ACT_GEN_SET) {
+ psnmp_mib->query_type =
+ wlan_cpu_to_le16(HostCmd_ACT_GEN_SET);
+ psnmp_mib->buf_size = wlan_cpu_to_le16(sizeof(t_u16));
+ ul_temp = (*(t_u32 *)pdata_buf);
+ *((t_u16 *)(psnmp_mib->value)) =
+ wlan_cpu_to_le16((t_u16)ul_temp);
+ cmd->size += sizeof(t_u16);
+ }
+ break;
+ case Dot11D_i:
+ psnmp_mib->oid = wlan_cpu_to_le16((t_u16)Dot11D_i);
+ if (cmd_action == HostCmd_ACT_GEN_SET) {
+ psnmp_mib->query_type =
+ wlan_cpu_to_le16(HostCmd_ACT_GEN_SET);
+ psnmp_mib->buf_size = wlan_cpu_to_le16(sizeof(t_u16));
+ ul_temp = *(t_u32 *)pdata_buf;
+ *((t_u16 *)(psnmp_mib->value)) =
+ wlan_cpu_to_le16((t_u16)ul_temp);
+ cmd->size += sizeof(t_u16);
+ }
+ break;
+ case Dot11H_i:
+ psnmp_mib->oid = wlan_cpu_to_le16((t_u16)Dot11H_i);
+ if (cmd_action == HostCmd_ACT_GEN_SET) {
+ psnmp_mib->query_type =
+ wlan_cpu_to_le16(HostCmd_ACT_GEN_SET);
+ psnmp_mib->buf_size = wlan_cpu_to_le16(sizeof(t_u16));
+ ul_temp = *(t_u32 *)pdata_buf;
+ *((t_u16 *)(psnmp_mib->value)) =
+ wlan_cpu_to_le16((t_u16)ul_temp);
+ cmd->size += sizeof(t_u16);
+ }
+ break;
+ case WwsMode_i:
+ psnmp_mib->oid = wlan_cpu_to_le16((t_u16)WwsMode_i);
+ if (cmd_action == HostCmd_ACT_GEN_SET) {
+ psnmp_mib->query_type =
+ wlan_cpu_to_le16(HostCmd_ACT_GEN_SET);
+ psnmp_mib->buf_size = wlan_cpu_to_le16(sizeof(t_u16));
+ ul_temp = *((t_u32 *)pdata_buf);
+ *((t_u16 *)(psnmp_mib->value)) =
+ wlan_cpu_to_le16((t_u16)ul_temp);
+ cmd->size += sizeof(t_u16);
+ }
+ break;
+ case Thermal_i:
+ psnmp_mib->oid = wlan_cpu_to_le16((t_u16)Thermal_i);
+ break;
+ case NullPktPeriod_i:
+ /** keep alive null data pkt interval in full power mode */
+ psnmp_mib->oid = wlan_cpu_to_le16((t_u16)NullPktPeriod_i);
+ if (cmd_action == HostCmd_ACT_GEN_SET) {
+ psnmp_mib->query_type =
+ wlan_cpu_to_le16(HostCmd_ACT_GEN_SET);
+ psnmp_mib->buf_size = wlan_cpu_to_le16(sizeof(t_u32));
+ ul_temp = *((t_u32 *)pdata_buf);
+ ul_temp = wlan_cpu_to_le32(ul_temp);
+ memcpy_ext(pmpriv->adapter, psnmp_mib->value, &ul_temp,
+ sizeof(t_u32), sizeof(t_u32));
+ cmd->size += sizeof(t_u32);
+ }
+ break;
+ case ECSAEnable_i:
+ psnmp_mib->oid = wlan_cpu_to_le16((t_u16)ECSAEnable_i);
+ if (cmd_action == HostCmd_ACT_GEN_SET) {
+ psnmp_mib->query_type =
+ wlan_cpu_to_le16(HostCmd_ACT_GEN_SET);
+ psnmp_mib->buf_size = wlan_cpu_to_le16(sizeof(t_u8));
+ psnmp_mib->value[0] = *((t_u8 *)pdata_buf);
+ cmd->size += sizeof(t_u8);
+ }
+ break;
+ case SignalextEnable_i:
+ psnmp_mib->oid = wlan_cpu_to_le16((t_u16)SignalextEnable_i);
+ if (cmd_action == HostCmd_ACT_GEN_SET) {
+ psnmp_mib->query_type =
+ wlan_cpu_to_le16(HostCmd_ACT_GEN_SET);
+ psnmp_mib->buf_size = wlan_cpu_to_le16(sizeof(t_u8));
+ psnmp_mib->value[0] = *(t_u8 *)pdata_buf;
+ cmd->size += sizeof(t_u8);
+ }
+ break;
+ default:
+ break;
+ }
+ cmd->size = wlan_cpu_to_le16(cmd->size);
+ PRINTM(MINFO,
+ "SNMP_CMD: Action=0x%x, OID=0x%x, OIDSize=0x%x, Value=0x%x\n",
+ cmd_action, cmd_oid, wlan_le16_to_cpu(psnmp_mib->buf_size),
+ wlan_le16_to_cpu(*(t_u16 *)psnmp_mib->value));
+ LEAVE();
+ return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ * @brief This function prepares command of get_log.
+ *
+ * @param pmpriv A pointer to mlan_private structure
+ * @param cmd A pointer to HostCmd_DS_COMMAND structure
+ *
+ * @return MLAN_STATUS_SUCCESS
+ */
+static mlan_status wlan_cmd_802_11_get_log(pmlan_private pmpriv,
+ HostCmd_DS_COMMAND *cmd)
+{
+ ENTER();
+ cmd->command = wlan_cpu_to_le16(HostCmd_CMD_802_11_GET_LOG);
+ cmd->size =
+ wlan_cpu_to_le16(sizeof(HostCmd_DS_802_11_GET_LOG) + S_DS_GEN);
+ LEAVE();
+ return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ * @brief This function prepares command of MFG Continuous Tx cmd.
+ *
+ * @param pmpriv A pointer to mlan_private structure
+ * @param cmd A pointer to HostCmd_DS_COMMAND structure
+ * @param action The action: GET or SET
+ * @param pdata_buf A pointer to data buffer
+ *
+ * @return MLAN_STATUS_SUCCESS
+ */
+static mlan_status wlan_cmd_mfg_tx_cont(pmlan_private pmpriv,
+ HostCmd_DS_COMMAND *cmd, t_u16 action,
+ t_void *pdata_buf)
+{
+ struct mfg_cmd_tx_cont *mcmd =
+ (struct mfg_cmd_tx_cont *)&cmd->params.mfg_tx_cont;
+ struct mfg_cmd_tx_cont *cfg = (struct mfg_cmd_tx_cont *)pdata_buf;
+
+ ENTER();
+ cmd->command = wlan_cpu_to_le16(HostCmd_CMD_MFG_COMMAND);
+ cmd->size = wlan_cpu_to_le16(sizeof(struct mfg_cmd_tx_cont) + S_DS_GEN);
+
+ mcmd->mfg_cmd = wlan_cpu_to_le32(cfg->mfg_cmd);
+ mcmd->action = wlan_cpu_to_le16(action);
+ if (action == HostCmd_ACT_GEN_SET) {
+ mcmd->enable_tx = wlan_cpu_to_le32(cfg->enable_tx);
+ mcmd->cw_mode = wlan_cpu_to_le32(cfg->cw_mode);
+ mcmd->payload_pattern = wlan_cpu_to_le32(cfg->payload_pattern);
+ mcmd->cs_mode = wlan_cpu_to_le32(cfg->cs_mode);
+ mcmd->act_sub_ch = wlan_cpu_to_le32(cfg->act_sub_ch);
+ mcmd->tx_rate = wlan_cpu_to_le32(cfg->tx_rate);
+ }
+
+ LEAVE();
+ return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ * @brief This function prepares command of MFG Tx frame.
+ *
+ * @param pmpriv A pointer to mlan_private structure
+ * @param cmd A pointer to HostCmd_DS_COMMAND structure
+ * @param action The action: GET or SET
+ * @param pdata_buf A pointer to data buffer
+ *
+ * @return MLAN_STATUS_SUCCESS
+ */
+static mlan_status wlan_cmd_mfg_tx_frame(pmlan_private pmpriv,
+ HostCmd_DS_COMMAND *cmd, t_u16 action,
+ t_void *pdata_buf)
+{
+ struct mfg_cmd_tx_frame2 *mcmd =
+ (struct mfg_cmd_tx_frame2 *)&cmd->params.mfg_tx_frame2;
+ struct mfg_cmd_tx_frame2 *cfg = (struct mfg_cmd_tx_frame2 *)pdata_buf;
+
+ ENTER();
+ cmd->command = wlan_cpu_to_le16(HostCmd_CMD_MFG_COMMAND);
+ cmd->size =
+ wlan_cpu_to_le16(sizeof(struct mfg_cmd_tx_frame2) + S_DS_GEN);
+
+ mcmd->mfg_cmd = wlan_cpu_to_le32(cfg->mfg_cmd);
+ mcmd->action = wlan_cpu_to_le16(action);
+ if (action == HostCmd_ACT_GEN_SET) {
+ mcmd->enable = wlan_cpu_to_le32(cfg->enable);
+ mcmd->data_rate = wlan_cpu_to_le32(cfg->data_rate);
+ mcmd->frame_pattern = wlan_cpu_to_le32(cfg->frame_pattern);
+ mcmd->frame_length = wlan_cpu_to_le32(cfg->frame_length);
+ mcmd->adjust_burst_sifs =
+ wlan_cpu_to_le16(cfg->adjust_burst_sifs);
+ mcmd->burst_sifs_in_us =
+ wlan_cpu_to_le32(cfg->burst_sifs_in_us);
+ mcmd->short_preamble = wlan_cpu_to_le32(cfg->short_preamble);
+ mcmd->act_sub_ch = wlan_cpu_to_le32(cfg->act_sub_ch);
+ mcmd->short_gi = wlan_cpu_to_le32(cfg->short_gi);
+ mcmd->tx_bf = wlan_cpu_to_le32(cfg->tx_bf);
+ mcmd->gf_mode = wlan_cpu_to_le32(cfg->gf_mode);
+ mcmd->stbc = wlan_cpu_to_le32(cfg->stbc);
+ memcpy_ext(pmpriv->adapter, mcmd->bssid, cfg->bssid,
+ MLAN_MAC_ADDR_LENGTH, sizeof(mcmd->bssid));
+ }
+
+ LEAVE();
+ return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ * @brief This function prepares command of MFG cmd.
+ *
+ * @param pmpriv A pointer to mlan_private structure
+ * @param cmd A pointer to HostCmd_DS_COMMAND structure
+ * @param action The action: GET or SET
+ * @param pdata_buf A pointer to data buffer
+ *
+ * @return MLAN_STATUS_SUCCESS
+ */
+mlan_status wlan_cmd_mfg(pmlan_private pmpriv, HostCmd_DS_COMMAND *cmd,
+ t_u16 action, t_void *pdata_buf)
+{
+ struct mfg_cmd_generic_cfg *mcmd =
+ (struct mfg_cmd_generic_cfg *)&cmd->params.mfg_generic_cfg;
+ struct mfg_cmd_generic_cfg *cfg =
+ (struct mfg_cmd_generic_cfg *)pdata_buf;
+ mlan_status ret = MLAN_STATUS_SUCCESS;
+
+ ENTER();
+
+ if (!mcmd || !cfg) {
+ ret = MLAN_STATUS_FAILURE;
+ goto cmd_mfg_done;
+ }
+ switch (cfg->mfg_cmd) {
+ case MFG_CMD_TX_CONT:
+ ret = wlan_cmd_mfg_tx_cont(pmpriv, cmd, action, pdata_buf);
+ goto cmd_mfg_done;
+ case MFG_CMD_TX_FRAME:
+ ret = wlan_cmd_mfg_tx_frame(pmpriv, cmd, action, pdata_buf);
+ goto cmd_mfg_done;
+ case MFG_CMD_SET_TEST_MODE:
+ case MFG_CMD_UNSET_TEST_MODE:
+ case MFG_CMD_TX_ANT:
+ case MFG_CMD_RX_ANT:
+ case MFG_CMD_RF_CHAN:
+ case MFG_CMD_CLR_RX_ERR:
+ case MFG_CMD_RF_BAND_AG:
+ case MFG_CMD_RF_CHANNELBW:
+ case MFG_CMD_RFPWR:
+ break;
+ default:
+ ret = MLAN_STATUS_FAILURE;
+ goto cmd_mfg_done;
+ }
+ cmd->command = wlan_cpu_to_le16(HostCmd_CMD_MFG_COMMAND);
+ cmd->size =
+ wlan_cpu_to_le16(sizeof(struct mfg_cmd_generic_cfg) + S_DS_GEN);
+
+ mcmd->mfg_cmd = wlan_cpu_to_le32(cfg->mfg_cmd);
+ mcmd->action = wlan_cpu_to_le16(action);
+ if (action == HostCmd_ACT_GEN_SET) {
+ mcmd->data1 = wlan_cpu_to_le32(cfg->data1);
+ mcmd->data2 = wlan_cpu_to_le32(cfg->data2);
+ mcmd->data3 = wlan_cpu_to_le32(cfg->data3);
+ }
+cmd_mfg_done:
+ LEAVE();
+ return ret;
+}
+
+/**
+ * @brief This function prepares command of tx_power_cfg.
+ *
+ * @param pmpriv A pointer to mlan_private structure
+ * @param cmd A pointer to HostCmd_DS_COMMAND structure
+ * @param cmd_action The action: GET or SET
+ * @param pdata_buf A pointer to data buffer
+ *
+ * @return MLAN_STATUS_SUCCESS
+ */
+static mlan_status wlan_cmd_tx_power_cfg(pmlan_private pmpriv,
+ HostCmd_DS_COMMAND *cmd,
+ t_u16 cmd_action, t_void *pdata_buf)
+{
+ MrvlTypes_Power_Group_t *ppg_tlv = MNULL;
+ HostCmd_DS_TXPWR_CFG *ptxp = MNULL;
+ HostCmd_DS_TXPWR_CFG *ptxp_cfg = &cmd->params.txp_cfg;
+
+ ENTER();
+
+ cmd->command = wlan_cpu_to_le16(HostCmd_CMD_TXPWR_CFG);
+ cmd->size = wlan_cpu_to_le16(S_DS_GEN + sizeof(HostCmd_DS_TXPWR_CFG));
+ switch (cmd_action) {
+ case HostCmd_ACT_GEN_SET:
+ ptxp = (HostCmd_DS_TXPWR_CFG *)pdata_buf;
+ if (ptxp->mode) {
+ ppg_tlv = (MrvlTypes_Power_Group_t
+ *)((t_u8 *)pdata_buf +
+ sizeof(HostCmd_DS_TXPWR_CFG));
+ memmove(pmpriv->adapter, ptxp_cfg, pdata_buf,
+ sizeof(HostCmd_DS_TXPWR_CFG) +
+ sizeof(MrvlTypes_Power_Group_t) +
+ ppg_tlv->length);
+
+ ppg_tlv = (MrvlTypes_Power_Group_t
+ *)((t_u8 *)ptxp_cfg +
+ sizeof(HostCmd_DS_TXPWR_CFG));
+ cmd->size += wlan_cpu_to_le16(
+ sizeof(MrvlTypes_Power_Group_t) +
+ ppg_tlv->length);
+ ppg_tlv->type = wlan_cpu_to_le16(ppg_tlv->type);
+ ppg_tlv->length = wlan_cpu_to_le16(ppg_tlv->length);
+ } else {
+ memmove(pmpriv->adapter, ptxp_cfg, pdata_buf,
+ sizeof(HostCmd_DS_TXPWR_CFG));
+ }
+ ptxp_cfg->action = wlan_cpu_to_le16(cmd_action);
+ ptxp_cfg->cfg_index = wlan_cpu_to_le16(ptxp_cfg->cfg_index);
+ ptxp_cfg->mode = wlan_cpu_to_le32(ptxp_cfg->mode);
+ break;
+ case HostCmd_ACT_GEN_GET:
+ ptxp_cfg->action = wlan_cpu_to_le16(cmd_action);
+ break;
+ }
+
+ LEAVE();
+ return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ * @brief This function prepares command of rf_tx_power.
+ *
+ * @param pmpriv A pointer to wlan_private structure
+ * @param cmd A pointer to HostCmd_DS_COMMAND structure
+ * @param cmd_action the action: GET or SET
+ * @param pdata_buf A pointer to data buffer
+ * @return MLAN_STATUS_SUCCESS
+ */
+static mlan_status wlan_cmd_802_11_rf_tx_power(pmlan_private pmpriv,
+ HostCmd_DS_COMMAND *cmd,
+ t_u16 cmd_action,
+ t_void *pdata_buf)
+{
+ HostCmd_DS_802_11_RF_TX_POWER *prtp = &cmd->params.txp;
+
+ ENTER();
+
+ cmd->size = wlan_cpu_to_le16((sizeof(HostCmd_DS_802_11_RF_TX_POWER)) +
+ S_DS_GEN);
+ cmd->command = wlan_cpu_to_le16(HostCmd_CMD_802_11_RF_TX_POWER);
+ prtp->action = cmd_action;
+
+ PRINTM(MINFO, "RF_TX_POWER_CMD: Size:%d Cmd:0x%x Act:%d\n", cmd->size,
+ cmd->command, prtp->action);
+
+ switch (cmd_action) {
+ case HostCmd_ACT_GEN_GET:
+ prtp->action = wlan_cpu_to_le16(HostCmd_ACT_GEN_GET);
+ prtp->current_level = 0;
+ break;
+
+ case HostCmd_ACT_GEN_SET:
+ prtp->action = wlan_cpu_to_le16(HostCmd_ACT_GEN_SET);
+ prtp->current_level = wlan_cpu_to_le16(*((t_s16 *)pdata_buf));
+ break;
+ }
+ LEAVE();
+ return MLAN_STATUS_SUCCESS;
+}
+
+#ifdef WIFI_DIRECT_SUPPORT
+/**
+ * @brief Check if any p2p interface is conencted
+ *
+ * @param pmadapter A pointer to mlan_adapter structure
+ *
+ * @return MTRUE/MFALSE;
+ */
+static t_u8 wlan_is_p2p_connected(pmlan_adapter pmadapter)
+{
+ int j;
+ pmlan_private priv;
+
+ ENTER();
+ for (j = 0; j < pmadapter->priv_num; ++j) {
+ priv = pmadapter->priv[j];
+ if (priv) {
+ if (priv->bss_type == MLAN_BSS_TYPE_WIFIDIRECT) {
+ if ((priv->bss_role == MLAN_BSS_ROLE_STA) &&
+ (priv->media_connected == MTRUE)) {
+ LEAVE();
+ return MTRUE;
+ }
+ if ((priv->bss_role == MLAN_BSS_ROLE_UAP) &&
+ (priv->uap_bss_started == MTRUE)) {
+ LEAVE();
+ return MTRUE;
+ }
+ }
+ }
+ }
+ LEAVE();
+ return MFALSE;
+}
+#endif
+
+/**
+ * @brief This function prepares command of hs_cfg.
+ *
+ * @param pmpriv A pointer to mlan_private structure
+ * @param cmd A pointer to HostCmd_DS_COMMAND structure
+ * @param cmd_action The action: GET or SET
+ * @param pdata_buf A pointer to data buffer
+ *
+ * @return MLAN_STATUS_SUCCESS
+ */
+static mlan_status wlan_cmd_802_11_hs_cfg(pmlan_private pmpriv,
+ HostCmd_DS_COMMAND *cmd,
+ t_u16 cmd_action,
+ hs_config_param *pdata_buf)
+{
+ pmlan_adapter pmadapter = pmpriv->adapter;
+ HostCmd_DS_802_11_HS_CFG_ENH *phs_cfg = &cmd->params.opt_hs_cfg;
+ t_u16 hs_activate = MFALSE;
+ t_u8 *tlv = (t_u8 *)phs_cfg + sizeof(HostCmd_DS_802_11_HS_CFG_ENH);
+ MrvlIEtypes_HsWakeHoldoff_t *holdoff_tlv = MNULL;
+ MrvlIEtypes_PsParamsInHs_t *psparam_tlv = MNULL;
+ MrvlIEtypes_WakeupSourceGPIO_t *gpio_tlv = MNULL;
+ MrvlIEtypes_MgmtFrameFilter_t *mgmt_filter_tlv = MNULL;
+ MrvlIEtypes_WakeupExtend_t *ext_tlv = MNULL;
+ MrvlIEtypes_HS_Antmode_t *antmode_tlv = MNULL;
+
+ ENTER();
+
+ if (pdata_buf == MNULL) {
+ /* New Activate command */
+ hs_activate = MTRUE;
+ }
+ cmd->command = wlan_cpu_to_le16(HostCmd_CMD_802_11_HS_CFG_ENH);
+
+ cmd->size = S_DS_GEN + sizeof(HostCmd_DS_802_11_HS_CFG_ENH);
+
+ if (hs_activate) {
+ cmd->size = wlan_cpu_to_le16(cmd->size);
+ phs_cfg->action = wlan_cpu_to_le16(HS_ACTIVATE);
+ phs_cfg->params.hs_activate.resp_ctrl =
+ wlan_cpu_to_le16(RESP_NEEDED);
+ } else {
+ phs_cfg->action = wlan_cpu_to_le16(HS_CONFIGURE);
+#ifdef WIFI_DIRECT_SUPPORT
+ if (wlan_is_p2p_connected(pmadapter))
+ phs_cfg->params.hs_config.conditions = wlan_cpu_to_le32(
+ pdata_buf->conditions |
+ HOST_SLEEP_COND_MULTICAST_DATA);
+ else
+#endif
+ phs_cfg->params.hs_config.conditions =
+ wlan_cpu_to_le32(pdata_buf->conditions);
+ phs_cfg->params.hs_config.gpio = pdata_buf->gpio;
+ phs_cfg->params.hs_config.gap = pdata_buf->gap;
+ if (pmadapter->min_wake_holdoff) {
+ cmd->size += sizeof(MrvlIEtypes_HsWakeHoldoff_t);
+ holdoff_tlv = (MrvlIEtypes_HsWakeHoldoff_t *)tlv;
+ holdoff_tlv->header.type =
+ wlan_cpu_to_le16(TLV_TYPE_HS_WAKE_HOLDOFF);
+ holdoff_tlv->header.len = wlan_cpu_to_le16(
+ sizeof(MrvlIEtypes_HsWakeHoldoff_t) -
+ sizeof(MrvlIEtypesHeader_t));
+ holdoff_tlv->min_wake_holdoff =
+ wlan_cpu_to_le16(pmadapter->min_wake_holdoff);
+ tlv += sizeof(MrvlIEtypes_HsWakeHoldoff_t);
+ PRINTM(MCMND, "min_wake_holdoff=%d\n",
+ pmadapter->min_wake_holdoff);
+ }
+ if (pmadapter->hs_wake_interval && pmpriv->media_connected &&
+ (pmpriv->bss_type == MLAN_BSS_TYPE_STA)) {
+ cmd->size += sizeof(MrvlIEtypes_PsParamsInHs_t);
+ psparam_tlv = (MrvlIEtypes_PsParamsInHs_t *)tlv;
+ psparam_tlv->header.type =
+ wlan_cpu_to_le16(TLV_TYPE_PS_PARAMS_IN_HS);
+ psparam_tlv->header.len = wlan_cpu_to_le16(
+ sizeof(MrvlIEtypes_PsParamsInHs_t) -
+ sizeof(MrvlIEtypesHeader_t));
+ psparam_tlv->hs_wake_interval =
+ wlan_cpu_to_le32(pmadapter->hs_wake_interval);
+ psparam_tlv->hs_inactivity_timeout = wlan_cpu_to_le32(
+ pmadapter->hs_inactivity_timeout);
+ tlv += sizeof(MrvlIEtypes_PsParamsInHs_t);
+ PRINTM(MCMND, "hs_wake_interval=%d\n",
+ pmadapter->hs_wake_interval);
+ PRINTM(MCMND, "hs_inactivity_timeout=%d\n",
+ pmadapter->hs_inactivity_timeout);
+ }
+ if (pmadapter->param_type_ind == 1) {
+ cmd->size += sizeof(MrvlIEtypes_WakeupSourceGPIO_t);
+ gpio_tlv = (MrvlIEtypes_WakeupSourceGPIO_t *)tlv;
+ gpio_tlv->header.type = wlan_cpu_to_le16(
+ TLV_TYPE_HS_WAKEUP_SOURCE_GPIO);
+ gpio_tlv->header.len = wlan_cpu_to_le16(
+ sizeof(MrvlIEtypes_WakeupSourceGPIO_t) -
+ sizeof(MrvlIEtypesHeader_t));
+ gpio_tlv->ind_gpio = (t_u8)pmadapter->ind_gpio;
+ gpio_tlv->level = (t_u8)pmadapter->level;
+ tlv += sizeof(MrvlIEtypes_WakeupSourceGPIO_t);
+ }
+ if (pmadapter->param_type_ext == 2) {
+ cmd->size += sizeof(MrvlIEtypes_WakeupExtend_t);
+ ext_tlv = (MrvlIEtypes_WakeupExtend_t *)tlv;
+ ext_tlv->header.type =
+ wlan_cpu_to_le16(TLV_TYPE_WAKEUP_EXTEND);
+ ext_tlv->header.len = wlan_cpu_to_le16(
+ sizeof(MrvlIEtypes_WakeupExtend_t) -
+ sizeof(MrvlIEtypesHeader_t));
+ ext_tlv->event_force_ignore =
+ wlan_cpu_to_le32(pmadapter->event_force_ignore);
+ ext_tlv->event_use_ext_gap =
+ wlan_cpu_to_le32(pmadapter->event_use_ext_gap);
+ ext_tlv->ext_gap = pmadapter->ext_gap;
+ ext_tlv->gpio_wave = pmadapter->gpio_wave;
+ tlv += sizeof(MrvlIEtypes_WakeupExtend_t);
+ }
+ if (pmadapter->mgmt_filter[0].type) {
+ int i = 0;
+ mgmt_frame_filter mgmt_filter[MAX_MGMT_FRAME_FILTER];
+
+ memset(pmadapter, mgmt_filter, 0,
+ MAX_MGMT_FRAME_FILTER *
+ sizeof(mgmt_frame_filter));
+ mgmt_filter_tlv = (MrvlIEtypes_MgmtFrameFilter_t *)tlv;
+ mgmt_filter_tlv->header.type =
+ wlan_cpu_to_le16(TLV_TYPE_MGMT_FRAME_WAKEUP);
+ tlv += sizeof(MrvlIEtypesHeader_t);
+ while (i < MAX_MGMT_FRAME_FILTER &&
+ pmadapter->mgmt_filter[i].type) {
+ mgmt_filter[i].action =
+ (t_u8)pmadapter->mgmt_filter[i].action;
+ mgmt_filter[i].type =
+ (t_u8)pmadapter->mgmt_filter[i].type;
+ mgmt_filter[i].frame_mask = wlan_cpu_to_le32(
+ pmadapter->mgmt_filter[i].frame_mask);
+ i++;
+ }
+ memcpy_ext(pmadapter, (t_u8 *)mgmt_filter_tlv->filter,
+ (t_u8 *)mgmt_filter,
+ i * sizeof(mgmt_frame_filter),
+ sizeof(mgmt_filter_tlv->filter));
+ tlv += i * sizeof(mgmt_frame_filter);
+ mgmt_filter_tlv->header.len =
+ wlan_cpu_to_le16(i * sizeof(mgmt_frame_filter));
+ cmd->size += i * sizeof(mgmt_frame_filter) +
+ sizeof(MrvlIEtypesHeader_t);
+ }
+ if (pmadapter->hs_mimo_switch) {
+ cmd->size += sizeof(MrvlIEtypes_HS_Antmode_t);
+ antmode_tlv = (MrvlIEtypes_HS_Antmode_t *)tlv;
+ antmode_tlv->header.type =
+ wlan_cpu_to_le16(TLV_TYPE_HS_ANTMODE);
+ antmode_tlv->header.len = wlan_cpu_to_le16(
+ sizeof(MrvlIEtypes_HS_Antmode_t) -
+ sizeof(MrvlIEtypesHeader_t));
+ antmode_tlv->txpath_antmode = ANTMODE_FW_DECISION;
+ antmode_tlv->rxpath_antmode = ANTMODE_FW_DECISION;
+ tlv += sizeof(MrvlIEtypes_HS_Antmode_t);
+ PRINTM(MCMND, "hs_mimo_switch=%d\n",
+ pmadapter->hs_mimo_switch);
+ PRINTM(MCMND, "txpath_antmode=%d, rxpath_antmode=%d\n",
+ antmode_tlv->txpath_antmode,
+ antmode_tlv->rxpath_antmode);
+ }
+ cmd->size = wlan_cpu_to_le16(cmd->size);
+ PRINTM(MCMND, "HS_CFG_CMD: condition:0x%x gpio:0x%x\n",
+ phs_cfg->params.hs_config.conditions,
+ phs_cfg->params.hs_config.gpio);
+ PRINTM(MCMND, "HS_CFG_CMD: gap:0x%x holdoff=%d\n",
+ phs_cfg->params.hs_config.gap,
+ pmadapter->min_wake_holdoff);
+ PRINTM(MCMND,
+ "HS_CFG_CMD: wake_interval=%d inactivity_timeout=%d\n",
+ pmadapter->hs_wake_interval,
+ pmadapter->hs_inactivity_timeout);
+ }
+
+ LEAVE();
+ return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ * @brief This function prepares command of sleep_period.
+ *
+ * @param pmpriv A pointer to mlan_private structure
+ * @param cmd A pointer to HostCmd_DS_COMMAND structure
+ * @param cmd_action The action: GET or SET
+ * @param pdata_buf A pointer to data buffer
+ *
+ * @return MLAN_STATUS_SUCCESS
+ */
+static mlan_status wlan_cmd_802_11_sleep_period(pmlan_private pmpriv,
+ HostCmd_DS_COMMAND *cmd,
+ t_u16 cmd_action,
+ t_u16 *pdata_buf)
+{
+ HostCmd_DS_802_11_SLEEP_PERIOD *pcmd_sleep_pd = &cmd->params.sleep_pd;
+
+ ENTER();
+
+ cmd->command = wlan_cpu_to_le16(HostCmd_CMD_802_11_SLEEP_PERIOD);
+ cmd->size = wlan_cpu_to_le16(sizeof(HostCmd_DS_802_11_SLEEP_PERIOD) +
+ S_DS_GEN);
+ if (cmd_action == HostCmd_ACT_GEN_SET)
+ pcmd_sleep_pd->sleep_pd = wlan_cpu_to_le16(*(t_u16 *)pdata_buf);
+
+ pcmd_sleep_pd->action = wlan_cpu_to_le16(cmd_action);
+
+ LEAVE();
+ return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ * @brief This function prepares command of sleep_params.
+ *
+ * @param pmpriv A pointer to mlan_private structure
+ * @param cmd A pointer to HostCmd_DS_COMMAND structure
+ * @param cmd_action The action: GET or SET
+ * @param pdata_buf A pointer to data buffer
+ *
+ * @return MLAN_STATUS_SUCCESS
+ */
+static mlan_status wlan_cmd_802_11_sleep_params(pmlan_private pmpriv,
+ HostCmd_DS_COMMAND *cmd,
+ t_u16 cmd_action,
+ t_u16 *pdata_buf)
+{
+ HostCmd_DS_802_11_SLEEP_PARAMS *pcmd_sp = &cmd->params.sleep_param;
+ mlan_ds_sleep_params *psp = (mlan_ds_sleep_params *)pdata_buf;
+
+ ENTER();
+
+ cmd->command = wlan_cpu_to_le16(HostCmd_CMD_802_11_SLEEP_PARAMS);
+ cmd->size = wlan_cpu_to_le16(sizeof(HostCmd_DS_802_11_SLEEP_PARAMS) +
+ S_DS_GEN);
+ if (cmd_action == HostCmd_ACT_GEN_SET) {
+ pcmd_sp->reserved = (t_u16)psp->reserved;
+ pcmd_sp->error = (t_u16)psp->error;
+ pcmd_sp->offset = (t_u16)psp->offset;
+ pcmd_sp->stable_time = (t_u16)psp->stable_time;
+ pcmd_sp->cal_control = (t_u8)psp->cal_control;
+ pcmd_sp->external_sleep_clk = (t_u8)psp->ext_sleep_clk;
+
+ pcmd_sp->reserved = wlan_cpu_to_le16(pcmd_sp->reserved);
+ pcmd_sp->error = wlan_cpu_to_le16(pcmd_sp->error);
+ pcmd_sp->offset = wlan_cpu_to_le16(pcmd_sp->offset);
+ pcmd_sp->stable_time = wlan_cpu_to_le16(pcmd_sp->stable_time);
+ }
+ pcmd_sp->action = wlan_cpu_to_le16(cmd_action);
+
+ LEAVE();
+ return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ * @brief This function prepares command of mac_multicast_adr.
+ *
+ * @param pmpriv A pointer to mlan_private structure
+ * @param cmd A pointer to HostCmd_DS_COMMAND structure
+ * @param cmd_action The action: GET or SET
+ * @param pdata_buf A pointer to data buffer
+ *
+ * @return MLAN_STATUS_SUCCESS
+ */
+static mlan_status wlan_cmd_mac_multicast_adr(pmlan_private pmpriv,
+ HostCmd_DS_COMMAND *cmd,
+ t_u16 cmd_action,
+ t_void *pdata_buf)
+{
+ mlan_multicast_list *pmcast_list = (mlan_multicast_list *)pdata_buf;
+ HostCmd_DS_MAC_MULTICAST_ADR *pmc_addr = &cmd->params.mc_addr;
+
+ ENTER();
+ cmd->size = wlan_cpu_to_le16(sizeof(HostCmd_DS_MAC_MULTICAST_ADR) +
+ S_DS_GEN);
+ cmd->command = wlan_cpu_to_le16(HostCmd_CMD_MAC_MULTICAST_ADR);
+
+ pmc_addr->action = wlan_cpu_to_le16(cmd_action);
+ pmc_addr->num_of_adrs =
+ wlan_cpu_to_le16((t_u16)pmcast_list->num_multicast_addr);
+ memcpy_ext(pmpriv->adapter, pmc_addr->mac_list, pmcast_list->mac_list,
+ pmcast_list->num_multicast_addr * MLAN_MAC_ADDR_LENGTH,
+ sizeof(pmc_addr->mac_list));
+
+ LEAVE();
+ return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ * @brief This function prepares command of deauthenticate/disassociate.
+ *
+ * @param pmpriv A pointer to mlan_private structure
+ * @param cmd_no Command number
+ * @param cmd A pointer to HostCmd_DS_COMMAND structure
+ * @param pdata_buf A pointer to data buffer
+ *
+ * @return MLAN_STATUS_SUCCESS
+ */
+static mlan_status wlan_cmd_802_11_deauthenticate(pmlan_private pmpriv,
+ t_u16 cmd_no,
+ HostCmd_DS_COMMAND *cmd,
+ t_void *pdata_buf)
+{
+ HostCmd_DS_802_11_DEAUTHENTICATE *pdeauth = &cmd->params.deauth;
+
+ ENTER();
+
+ cmd->command = wlan_cpu_to_le16(cmd_no);
+ cmd->size = wlan_cpu_to_le16(sizeof(HostCmd_DS_802_11_DEAUTHENTICATE) +
+ S_DS_GEN);
+
+ /* Set AP MAC address */
+ memcpy_ext(pmpriv->adapter, pdeauth, (t_u8 *)pdata_buf,
+ sizeof(*pdeauth), sizeof(*pdeauth));
+ if (cmd_no == HostCmd_CMD_802_11_DEAUTHENTICATE)
+ PRINTM(MCMND, "Deauth: " MACSTR "\n",
+ MAC2STR(pdeauth->mac_addr));
+ else
+ PRINTM(MCMND, "Disassociate: " MACSTR "\n",
+ MAC2STR(pdeauth->mac_addr));
+
+ if (pmpriv->adapter->state_11h.recvd_chanswann_event) {
+/** Reason code 36 = Requested from peer station as it is leaving the BSS */
+#define REASON_CODE_PEER_STA_LEAVING 36
+ pdeauth->reason_code =
+ wlan_cpu_to_le16(REASON_CODE_PEER_STA_LEAVING);
+ } else {
+ pdeauth->reason_code = wlan_cpu_to_le16(pdeauth->reason_code);
+ }
+
+ LEAVE();
+ return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ * @brief This function prepares command of ad_hoc_stop.
+ *
+ * @param pmpriv A pointer to mlan_private structure
+ * @param cmd A pointer to HostCmd_DS_COMMAND structure
+ *
+ * @return MLAN_STATUS_SUCCESS
+ */
+static mlan_status wlan_cmd_802_11_ad_hoc_stop(pmlan_private pmpriv,
+ HostCmd_DS_COMMAND *cmd)
+{
+ ENTER();
+
+ cmd->command = wlan_cpu_to_le16(HostCmd_CMD_802_11_AD_HOC_STOP);
+ cmd->size = wlan_cpu_to_le16(S_DS_GEN);
+
+ if (wlan_11h_is_active(pmpriv))
+ wlan_11h_activate(pmpriv, MNULL, MFALSE);
+
+ LEAVE();
+ return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ * @brief This function prepares command of key_material.
+ *
+ * @param pmpriv A pointer to mlan_private structure
+ * @param cmd A pointer to HostCmd_DS_COMMAND structure
+ * @param cmd_action The action: GET or SET
+ * @param cmd_oid OID: ENABLE or DISABLE
+ * @param pdata_buf A pointer to data buffer
+ *
+ * @return MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ */
+static mlan_status wlan_cmd_802_11_key_material(pmlan_private pmpriv,
+ HostCmd_DS_COMMAND *cmd,
+ t_u16 cmd_action, t_u32 cmd_oid,
+ t_void *pdata_buf)
+{
+ HostCmd_DS_802_11_KEY_MATERIAL *pkey_material =
+ &cmd->params.key_material;
+ mlan_ds_encrypt_key *pkey = (mlan_ds_encrypt_key *)pdata_buf;
+ mlan_status ret = MLAN_STATUS_SUCCESS;
+
+ ENTER();
+ if (!pkey) {
+ ret = MLAN_STATUS_FAILURE;
+ goto done;
+ }
+ cmd->command = wlan_cpu_to_le16(HostCmd_CMD_802_11_KEY_MATERIAL);
+ pkey_material->action = wlan_cpu_to_le16(cmd_action);
+ if (cmd_action == HostCmd_ACT_GEN_GET) {
+ PRINTM(MCMND, "GET Key\n");
+ pkey_material->key_param_set.key_idx =
+ pkey->key_index & KEY_INDEX_MASK;
+ pkey_material->key_param_set.type =
+ wlan_cpu_to_le16(TLV_TYPE_KEY_PARAM_V2);
+ pkey_material->key_param_set.length =
+ wlan_cpu_to_le16(KEY_PARAMS_FIXED_LEN);
+ memcpy_ext(pmpriv->adapter,
+ pkey_material->key_param_set.mac_addr,
+ pkey->mac_addr, MLAN_MAC_ADDR_LENGTH,
+ MLAN_MAC_ADDR_LENGTH);
+ if (pkey->key_flags & KEY_FLAG_GROUP_KEY)
+ pkey_material->key_param_set.key_info |=
+ KEY_INFO_MCAST_KEY;
+ else
+ pkey_material->key_param_set.key_info |=
+ KEY_INFO_UCAST_KEY;
+ if (pkey->key_flags & KEY_FLAG_AES_MCAST_IGTK)
+ pkey_material->key_param_set.key_info =
+ KEY_INFO_CMAC_AES_KEY;
+ pkey_material->key_param_set.key_info =
+ wlan_cpu_to_le16(pkey_material->key_param_set.key_info);
+ cmd->size = wlan_cpu_to_le16(sizeof(MrvlIEtypesHeader_t) +
+ S_DS_GEN + KEY_PARAMS_FIXED_LEN +
+ sizeof(pkey_material->action));
+ goto done;
+ }
+ memset(pmpriv->adapter, &pkey_material->key_param_set, 0,
+ sizeof(MrvlIEtype_KeyParamSetV2_t));
+ if (pkey->key_flags & KEY_FLAG_REMOVE_KEY) {
+ pkey_material->action =
+ wlan_cpu_to_le16(HostCmd_ACT_GEN_REMOVE);
+ pkey_material->key_param_set.type =
+ wlan_cpu_to_le16(TLV_TYPE_KEY_PARAM_V2);
+ pkey_material->key_param_set.length =
+ wlan_cpu_to_le16(KEY_PARAMS_FIXED_LEN);
+ pkey_material->key_param_set.key_idx =
+ pkey->key_index & KEY_INDEX_MASK;
+ pkey_material->key_param_set.key_info = wlan_cpu_to_le16(
+ KEY_INFO_MCAST_KEY | KEY_INFO_UCAST_KEY);
+ memcpy_ext(pmpriv->adapter,
+ pkey_material->key_param_set.mac_addr,
+ pkey->mac_addr, MLAN_MAC_ADDR_LENGTH,
+ MLAN_MAC_ADDR_LENGTH);
+ cmd->size = wlan_cpu_to_le16(sizeof(MrvlIEtypesHeader_t) +
+ S_DS_GEN + KEY_PARAMS_FIXED_LEN +
+ sizeof(pkey_material->action));
+ PRINTM(MCMND, "Remove Key\n");
+ goto done;
+ }
+ pkey_material->action = wlan_cpu_to_le16(HostCmd_ACT_GEN_SET);
+ pkey_material->key_param_set.key_idx = pkey->key_index & KEY_INDEX_MASK;
+ pkey_material->key_param_set.type =
+ wlan_cpu_to_le16(TLV_TYPE_KEY_PARAM_V2);
+ pkey_material->key_param_set.key_info = KEY_INFO_ENABLE_KEY;
+ memcpy_ext(pmpriv->adapter, pkey_material->key_param_set.mac_addr,
+ pkey->mac_addr, MLAN_MAC_ADDR_LENGTH, MLAN_MAC_ADDR_LENGTH);
+ if (pkey->key_len <= MAX_WEP_KEY_SIZE) {
+ pkey_material->key_param_set.length = wlan_cpu_to_le16(
+ KEY_PARAMS_FIXED_LEN + sizeof(wep_param_t));
+ pkey_material->key_param_set.key_type = KEY_TYPE_ID_WEP;
+ if (pkey->is_current_wep_key) {
+ pkey_material->key_param_set.key_info |=
+ KEY_INFO_MCAST_KEY | KEY_INFO_UCAST_KEY;
+ if (pkey_material->key_param_set.key_idx ==
+ (pmpriv->wep_key_curr_index & KEY_INDEX_MASK))
+ pkey_material->key_param_set.key_info |=
+ KEY_INFO_DEFAULT_KEY;
+ } else {
+ if (pkey->key_flags & KEY_FLAG_GROUP_KEY)
+ pkey_material->key_param_set.key_info |=
+ KEY_INFO_MCAST_KEY;
+ else
+ pkey_material->key_param_set.key_info |=
+ KEY_INFO_UCAST_KEY;
+ }
+ pkey_material->key_param_set.key_info =
+ wlan_cpu_to_le16(pkey_material->key_param_set.key_info);
+ pkey_material->key_param_set.key_params.wep.key_len =
+ wlan_cpu_to_le16(pkey->key_len);
+ memcpy_ext(pmpriv->adapter,
+ pkey_material->key_param_set.key_params.wep.key,
+ pkey->key_material, pkey->key_len, MAX_WEP_KEY_SIZE);
+ cmd->size = wlan_cpu_to_le16(sizeof(MrvlIEtypesHeader_t) +
+ S_DS_GEN + KEY_PARAMS_FIXED_LEN +
+ sizeof(wep_param_t) +
+ sizeof(pkey_material->action));
+ PRINTM(MCMND, "Set WEP Key\n");
+ goto done;
+ }
+ if (pkey->key_flags & KEY_FLAG_GROUP_KEY)
+ pkey_material->key_param_set.key_info |= KEY_INFO_MCAST_KEY;
+ else
+ pkey_material->key_param_set.key_info |= KEY_INFO_UCAST_KEY;
+ if (pkey->key_flags & KEY_FLAG_SET_TX_KEY)
+ pkey_material->key_param_set.key_info |=
+ KEY_INFO_TX_KEY | KEY_INFO_RX_KEY;
+ else
+ pkey_material->key_param_set.key_info |= KEY_INFO_RX_KEY;
+ if (pkey->is_wapi_key) {
+ pkey_material->key_param_set.key_type = KEY_TYPE_ID_WAPI;
+ memcpy_ext(pmpriv->adapter,
+ pkey_material->key_param_set.key_params.wapi.pn,
+ pkey->pn, PN_SIZE, PN_SIZE);
+ pkey_material->key_param_set.key_params.wapi.key_len =
+ wlan_cpu_to_le16(pkey->key_len);
+ memcpy_ext(pmpriv->adapter,
+ pkey_material->key_param_set.key_params.wapi.key,
+ pkey->key_material, pkey->key_len, WAPI_KEY_SIZE);
+ if (!pmpriv->sec_info.wapi_key_on)
+ pkey_material->key_param_set.key_info |=
+ KEY_INFO_DEFAULT_KEY;
+ if (pkey->key_flags & KEY_FLAG_GROUP_KEY)
+ pmpriv->sec_info.wapi_key_on = MTRUE;
+ pkey_material->key_param_set.key_info =
+ wlan_cpu_to_le16(pkey_material->key_param_set.key_info);
+ pkey_material->key_param_set.length = wlan_cpu_to_le16(
+ KEY_PARAMS_FIXED_LEN + sizeof(wapi_param));
+ cmd->size = wlan_cpu_to_le16(sizeof(MrvlIEtypesHeader_t) +
+ S_DS_GEN + KEY_PARAMS_FIXED_LEN +
+ sizeof(wapi_param) +
+ sizeof(pkey_material->action));
+ PRINTM(MCMND, "Set WAPI Key\n");
+ goto done;
+ }
+ if (pmpriv->bss_mode == MLAN_BSS_MODE_INFRA) {
+ /* Enable default key for WPA/WPA2 */
+ if (!pmpriv->wpa_is_gtk_set)
+ pkey_material->key_param_set.key_info |=
+ KEY_INFO_DEFAULT_KEY;
+ } else {
+ pkey_material->key_param_set.key_info |= KEY_INFO_DEFAULT_KEY;
+ /* Enable unicast bit for WPA-NONE/ADHOC_AES */
+ if ((!pmpriv->sec_info.wpa2_enabled) &&
+ (pkey->key_flags & KEY_FLAG_SET_TX_KEY))
+ pkey_material->key_param_set.key_info |=
+ KEY_INFO_UCAST_KEY;
+ }
+ pkey_material->key_param_set.key_info =
+ wlan_cpu_to_le16(pkey_material->key_param_set.key_info);
+ if (pkey->key_flags & KEY_FLAG_GCMP ||
+ pkey->key_flags & KEY_FLAG_GCMP_256) {
+ if (pkey->key_flags &
+ (KEY_FLAG_RX_SEQ_VALID | KEY_FLAG_TX_SEQ_VALID)) {
+ memcpy_ext(
+ pmpriv->adapter,
+ pkey_material->key_param_set.key_params.gcmp.pn,
+ pkey->pn, SEQ_MAX_SIZE, WPA_PN_SIZE);
+ }
+ if (pkey->key_flags & KEY_FLAG_GCMP)
+ pkey_material->key_param_set.key_type =
+ KEY_TYPE_ID_GCMP;
+ else
+ pkey_material->key_param_set.key_type =
+ KEY_TYPE_ID_GCMP_256;
+ pkey_material->key_param_set.key_params.gcmp.key_len =
+ wlan_cpu_to_le16(pkey->key_len);
+ memcpy_ext(pmpriv->adapter,
+ pkey_material->key_param_set.key_params.gcmp.key,
+ pkey->key_material, pkey->key_len, WPA_GCMP_KEY_LEN);
+ pkey_material->key_param_set.length = wlan_cpu_to_le16(
+ KEY_PARAMS_FIXED_LEN + sizeof(gcmp_param));
+ cmd->size = wlan_cpu_to_le16(sizeof(MrvlIEtypesHeader_t) +
+ S_DS_GEN + KEY_PARAMS_FIXED_LEN +
+ sizeof(gcmp_param) +
+ sizeof(pkey_material->action));
+
+ goto done;
+ }
+ if (pkey->key_flags & KEY_FLAG_CCMP_256) {
+ if (pkey->key_flags &
+ (KEY_FLAG_RX_SEQ_VALID | KEY_FLAG_TX_SEQ_VALID)) {
+ memcpy_ext(pmpriv->adapter,
+ pkey_material->key_param_set.key_params
+ .ccmp256.pn,
+ pkey->pn, SEQ_MAX_SIZE, WPA_PN_SIZE);
+ }
+ pkey_material->key_param_set.key_type = KEY_TYPE_ID_CCMP_256;
+ pkey_material->key_param_set.key_params.ccmp256.key_len =
+ wlan_cpu_to_le16(pkey->key_len);
+ memcpy_ext(pmpriv->adapter,
+ pkey_material->key_param_set.key_params.ccmp256.key,
+ pkey->key_material, pkey->key_len,
+ WPA_CCMP_256_KEY_LEN);
+ pkey_material->key_param_set.length = wlan_cpu_to_le16(
+ KEY_PARAMS_FIXED_LEN + sizeof(ccmp_256_param));
+ cmd->size = wlan_cpu_to_le16(sizeof(MrvlIEtypesHeader_t) +
+ S_DS_GEN + KEY_PARAMS_FIXED_LEN +
+ sizeof(ccmp_256_param) +
+ sizeof(pkey_material->action));
+
+ goto done;
+ }
+ if (pkey->key_len == WPA_AES_KEY_LEN &&
+ !(pkey->key_flags & KEY_FLAG_AES_MCAST_IGTK)) {
+ if (pkey->key_flags &
+ (KEY_FLAG_RX_SEQ_VALID | KEY_FLAG_TX_SEQ_VALID))
+ memcpy_ext(
+ pmpriv->adapter,
+ pkey_material->key_param_set.key_params.aes.pn,
+ pkey->pn, SEQ_MAX_SIZE, WPA_PN_SIZE);
+ pkey_material->key_param_set.key_type = KEY_TYPE_ID_AES;
+ pkey_material->key_param_set.key_params.aes.key_len =
+ wlan_cpu_to_le16(pkey->key_len);
+ memcpy_ext(pmpriv->adapter,
+ pkey_material->key_param_set.key_params.aes.key,
+ pkey->key_material, pkey->key_len, WPA_AES_KEY_LEN);
+ pkey_material->key_param_set.length = wlan_cpu_to_le16(
+ KEY_PARAMS_FIXED_LEN + sizeof(aes_param));
+ cmd->size = wlan_cpu_to_le16(sizeof(MrvlIEtypesHeader_t) +
+ S_DS_GEN + KEY_PARAMS_FIXED_LEN +
+ sizeof(aes_param) +
+ sizeof(pkey_material->action));
+ PRINTM(MCMND, "Set AES Key\n");
+ goto done;
+ }
+ if (pkey->key_len == WPA_IGTK_KEY_LEN &&
+ (pkey->key_flags & KEY_FLAG_AES_MCAST_IGTK)) {
+ if (pkey->key_flags &
+ (KEY_FLAG_RX_SEQ_VALID | KEY_FLAG_TX_SEQ_VALID))
+ memcpy_ext(pmpriv->adapter,
+ pkey_material->key_param_set.key_params
+ .cmac_aes.ipn,
+ pkey->pn, SEQ_MAX_SIZE, IGTK_PN_SIZE);
+ pkey_material->key_param_set.key_info &=
+ ~(wlan_cpu_to_le16(KEY_INFO_MCAST_KEY));
+ pkey_material->key_param_set.key_info |=
+ wlan_cpu_to_le16(KEY_INFO_AES_MCAST_IGTK);
+ pkey_material->key_param_set.key_type = KEY_TYPE_ID_AES_CMAC;
+ pkey_material->key_param_set.key_params.cmac_aes.key_len =
+ wlan_cpu_to_le16(pkey->key_len);
+ memcpy_ext(pmpriv->adapter,
+ pkey_material->key_param_set.key_params.cmac_aes.key,
+ pkey->key_material, pkey->key_len, CMAC_AES_KEY_LEN);
+ pkey_material->key_param_set.length = wlan_cpu_to_le16(
+ KEY_PARAMS_FIXED_LEN + sizeof(cmac_aes_param));
+ cmd->size = wlan_cpu_to_le16(sizeof(MrvlIEtypesHeader_t) +
+ S_DS_GEN + KEY_PARAMS_FIXED_LEN +
+ sizeof(cmac_aes_param) +
+ sizeof(pkey_material->action));
+ PRINTM(MCMND, "Set CMAC AES Key\n");
+ goto done;
+ }
+ if (pkey->key_len == WPA_TKIP_KEY_LEN) {
+ if (pkey->key_flags &
+ (KEY_FLAG_RX_SEQ_VALID | KEY_FLAG_TX_SEQ_VALID))
+ memcpy_ext(
+ pmpriv->adapter,
+ pkey_material->key_param_set.key_params.tkip.pn,
+ pkey->pn, SEQ_MAX_SIZE, WPA_PN_SIZE);
+ pkey_material->key_param_set.key_type = KEY_TYPE_ID_TKIP;
+ pkey_material->key_param_set.key_params.tkip.key_len =
+ wlan_cpu_to_le16(pkey->key_len);
+ memcpy_ext(pmpriv->adapter,
+ pkey_material->key_param_set.key_params.tkip.key,
+ pkey->key_material, pkey->key_len, WPA_TKIP_KEY_LEN);
+ pkey_material->key_param_set.length = wlan_cpu_to_le16(
+ KEY_PARAMS_FIXED_LEN + sizeof(tkip_param));
+ cmd->size = wlan_cpu_to_le16(sizeof(MrvlIEtypesHeader_t) +
+ S_DS_GEN + KEY_PARAMS_FIXED_LEN +
+ sizeof(tkip_param) +
+ sizeof(pkey_material->action));
+ PRINTM(MCMND, "Set TKIP Key\n");
+ }
+done:
+ LEAVE();
+ return ret;
+}
+
+/**
+ * @brief This function prepares command of gtk rekey offload
+ *
+ * @param pmpriv A pointer to mlan_private structure
+ * @param cmd A pointer to HostCmd_DS_COMMAND structure
+ * @param cmd_action The action: GET or SET
+ * @param cmd_oid OID: ENABLE or DISABLE
+ * @param pdata_buf A pointer to data buffer
+ *
+ * @return MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ */
+static mlan_status wlan_cmd_gtk_rekey_offload(pmlan_private pmpriv,
+ HostCmd_DS_COMMAND *cmd,
+ t_u16 cmd_action, t_u32 cmd_oid,
+ t_void *pdata_buf)
+{
+ HostCmd_DS_GTK_REKEY_PARAMS *rekey = &cmd->params.gtk_rekey;
+ mlan_ds_misc_gtk_rekey_data *data =
+ (mlan_ds_misc_gtk_rekey_data *)pdata_buf;
+ t_u64 rekey_ctr;
+
+ ENTER();
+ cmd->command = wlan_cpu_to_le16(HostCmd_CMD_GTK_REKEY_OFFLOAD_CFG);
+ cmd->size = wlan_cpu_to_le16(sizeof(*rekey) + S_DS_GEN);
+
+ rekey->action = wlan_cpu_to_le16(cmd_action);
+ if (cmd_action == HostCmd_ACT_GEN_SET) {
+ memcpy_ext(pmpriv->adapter, rekey->kek, data->kek, MLAN_KEK_LEN,
+ MLAN_KEK_LEN);
+ memcpy_ext(pmpriv->adapter, rekey->kck, data->kck, MLAN_KCK_LEN,
+ MLAN_KCK_LEN);
+ rekey_ctr = wlan_le64_to_cpu(
+ swap_byte_64(*(t_u64 *)data->replay_ctr));
+ rekey->replay_ctr_low = wlan_cpu_to_le32((t_u32)rekey_ctr);
+ rekey->replay_ctr_high =
+ wlan_cpu_to_le32((t_u64)rekey_ctr >> 32);
+ }
+
+ LEAVE();
+ return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ * @brief This function send eapol pkt to FW
+ *
+ * @param pmpriv A pointer to mlan_private structure
+ * @param cmd A pointer to HostCmd_DS_COMMAND structure
+ * @param cmd_action the action: GET or SET
+ * @param pdata_buf A pointer to data buffer
+ *
+ * @return MLAN_STATUS_SUCCESS
+ */
+static mlan_status wlan_cmd_eapol_pkt(pmlan_private pmpriv,
+ HostCmd_DS_COMMAND *cmd, t_u16 cmd_action,
+ t_void *pdata_buf)
+{
+ HostCmd_DS_EAPOL_PKT *eapol_pkt = &cmd->params.eapol_pkt;
+ mlan_buffer *pmbuf = (mlan_buffer *)pdata_buf;
+
+ ENTER();
+ eapol_pkt->action = wlan_cpu_to_le16(HostCmd_ACT_GEN_SET);
+ cmd->size = sizeof(HostCmd_DS_EAPOL_PKT) + S_DS_GEN;
+ cmd->command = wlan_cpu_to_le16(cmd->command);
+
+ eapol_pkt->tlv_eapol.header.type = wlan_cpu_to_le16(TLV_TYPE_EAPOL_PKT);
+ eapol_pkt->tlv_eapol.header.len = wlan_cpu_to_le16(pmbuf->data_len);
+ memcpy_ext(pmpriv->adapter, eapol_pkt->tlv_eapol.pkt_buf,
+ pmbuf->pbuf + pmbuf->data_offset, pmbuf->data_len,
+ pmbuf->data_len);
+ cmd->size += pmbuf->data_len;
+ cmd->size = wlan_cpu_to_le16(cmd->size);
+
+ LEAVE();
+ return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ * @brief Handle the supplicant profile command
+ *
+ * @param pmpriv A pointer to mlan_private structure
+ * @param cmd A pointer to HostCmd_DS_COMMAND structure
+ * @param cmd_action The action: GET or SET
+ *
+ * @return MLAN_STATUS_SUCCESS
+ */
+static mlan_status wlan_cmd_802_11_supplicant_profile(pmlan_private pmpriv,
+ HostCmd_DS_COMMAND *cmd,
+ t_u16 cmd_action,
+ t_void *pdata_buf)
+{
+ HostCmd_DS_802_11_SUPPLICANT_PROFILE *sup_profile =
+ (HostCmd_DS_802_11_SUPPLICANT_PROFILE *)&(
+ cmd->params.esupplicant_profile);
+ MrvlIEtypes_EncrProto_t *encr_proto_tlv = MNULL;
+ MrvlIEtypes_Cipher_t *pcipher_tlv = MNULL;
+ t_u8 *ptlv_buffer = (t_u8 *)sup_profile->tlv_buf;
+ mlan_ds_esupp_mode *esupp = MNULL;
+
+ ENTER();
+
+ cmd->size = wlan_cpu_to_le16(
+ sizeof(HostCmd_DS_802_11_SUPPLICANT_PROFILE) + S_DS_GEN - 1);
+ cmd->command = wlan_cpu_to_le16(HostCmd_CMD_SUPPLICANT_PROFILE);
+ sup_profile->action = wlan_cpu_to_le16(cmd_action);
+ if ((cmd_action == HostCmd_ACT_GEN_SET) && pdata_buf) {
+ esupp = (mlan_ds_esupp_mode *)pdata_buf;
+ if (esupp->rsn_mode) {
+ encr_proto_tlv = (MrvlIEtypes_EncrProto_t *)ptlv_buffer;
+ encr_proto_tlv->header.type =
+ wlan_cpu_to_le16(TLV_TYPE_ENCRYPTION_PROTO);
+ encr_proto_tlv->header.len =
+ (t_u16)sizeof(encr_proto_tlv->rsn_mode);
+ encr_proto_tlv->rsn_mode =
+ wlan_cpu_to_le16(esupp->rsn_mode);
+ ptlv_buffer += (encr_proto_tlv->header.len +
+ sizeof(MrvlIEtypesHeader_t));
+ cmd->size += (encr_proto_tlv->header.len +
+ sizeof(MrvlIEtypesHeader_t));
+ encr_proto_tlv->header.len =
+ wlan_cpu_to_le16(encr_proto_tlv->header.len);
+ }
+ if (esupp->act_paircipher || esupp->act_groupcipher) {
+ pcipher_tlv = (MrvlIEtypes_Cipher_t *)ptlv_buffer;
+ pcipher_tlv->header.type =
+ wlan_cpu_to_le16(TLV_TYPE_CIPHER);
+ pcipher_tlv->header.len =
+ (t_u16)(sizeof(pcipher_tlv->pair_cipher) +
+ sizeof(pcipher_tlv->group_cipher));
+ if (esupp->act_paircipher) {
+ pcipher_tlv->pair_cipher =
+ esupp->act_paircipher & 0xff;
+ }
+ if (esupp->act_groupcipher) {
+ pcipher_tlv->group_cipher =
+ esupp->act_groupcipher & 0xff;
+ }
+ ptlv_buffer += (pcipher_tlv->header.len +
+ sizeof(MrvlIEtypesHeader_t));
+ cmd->size += (pcipher_tlv->header.len +
+ sizeof(MrvlIEtypesHeader_t));
+ pcipher_tlv->header.len =
+ wlan_cpu_to_le16(pcipher_tlv->header.len);
+ }
+ }
+ cmd->size = wlan_cpu_to_le16(cmd->size);
+ LEAVE();
+ return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ * @brief This function prepares command of rf_channel.
+ *
+ * @param pmpriv A pointer to mlan_private structure
+ * @param cmd A pointer to HostCmd_DS_COMMAND structure
+ * @param cmd_action The action: GET or SET
+ * @param pdata_buf A pointer to data buffer
+ *
+ * @return MLAN_STATUS_SUCCESS
+ */
+static mlan_status wlan_cmd_802_11_rf_channel(pmlan_private pmpriv,
+ HostCmd_DS_COMMAND *cmd,
+ t_u16 cmd_action,
+ t_void *pdata_buf)
+{
+ HostCmd_DS_802_11_RF_CHANNEL *prf_chan = &cmd->params.rf_channel;
+
+ ENTER();
+
+ cmd->command = wlan_cpu_to_le16(HostCmd_CMD_802_11_RF_CHANNEL);
+ cmd->size = wlan_cpu_to_le16(sizeof(HostCmd_DS_802_11_RF_CHANNEL) +
+ S_DS_GEN);
+
+ if (cmd_action == HostCmd_ACT_GEN_SET) {
+ if ((pmpriv->adapter->adhoc_start_band & BAND_A))
+ prf_chan->rf_type.bandcfg.chanBand = BAND_5GHZ;
+ prf_chan->rf_type.bandcfg.chanWidth =
+ pmpriv->adapter->chan_bandwidth;
+ prf_chan->current_channel =
+ wlan_cpu_to_le16(*((t_u16 *)pdata_buf));
+ }
+ prf_chan->action = wlan_cpu_to_le16(cmd_action);
+ LEAVE();
+ return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ * @brief This function prepares command of ibss_coalescing_status.
+ *
+ * @param pmpriv A pointer to mlan_private structure
+ * @param cmd A pointer to HostCmd_DS_COMMAND structure
+ * @param cmd_action The action: GET or SET
+ * @param pdata_buf A pointer to data buffer or MNULL
+ *
+ * @return MLAN_STATUS_SUCCESS
+ */
+static mlan_status wlan_cmd_ibss_coalescing_status(pmlan_private pmpriv,
+ HostCmd_DS_COMMAND *cmd,
+ t_u16 cmd_action,
+ t_void *pdata_buf)
+{
+ HostCmd_DS_802_11_IBSS_STATUS *pibss_coal =
+ &(cmd->params.ibss_coalescing);
+ t_u16 enable = 0;
+
+ ENTER();
+
+ cmd->command =
+ wlan_cpu_to_le16(HostCmd_CMD_802_11_IBSS_COALESCING_STATUS);
+ cmd->size = wlan_cpu_to_le16(sizeof(HostCmd_DS_802_11_IBSS_STATUS) +
+ S_DS_GEN);
+ cmd->result = 0;
+ pibss_coal->action = wlan_cpu_to_le16(cmd_action);
+
+ switch (cmd_action) {
+ case HostCmd_ACT_GEN_SET:
+ if (pdata_buf != MNULL)
+ enable = *(t_u16 *)pdata_buf;
+ pibss_coal->enable = wlan_cpu_to_le16(enable);
+ break;
+
+ /* In other case.. Nothing to do */
+ case HostCmd_ACT_GEN_GET:
+ default:
+ break;
+ }
+
+ LEAVE();
+ return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ * @brief This function prepares command of mgmt IE list.
+ *
+ * @param pmpriv A pointer to mlan_private structure
+ * @param cmd A pointer to HostCmd_DS_COMMAND structure
+ * @param cmd_action The action: GET or SET
+ * @param pdata_buf A pointer to data buffer
+ *
+ * @return MLAN_STATUS_SUCCESS
+ */
+static mlan_status wlan_cmd_mgmt_ie_list(pmlan_private pmpriv,
+ HostCmd_DS_COMMAND *cmd,
+ t_u16 cmd_action, t_void *pdata_buf)
+{
+ t_u16 req_len = 0, travel_len = 0;
+ custom_ie *cptr = MNULL;
+ mlan_ds_misc_custom_ie *cust_ie = MNULL;
+ HostCmd_DS_MGMT_IE_LIST_CFG *pmgmt_ie_list =
+ &(cmd->params.mgmt_ie_list);
+
+ ENTER();
+
+ cmd->command = wlan_cpu_to_le16(HostCmd_CMD_MGMT_IE_LIST);
+ cmd->size = sizeof(HostCmd_DS_MGMT_IE_LIST_CFG) + S_DS_GEN;
+ cmd->result = 0;
+ pmgmt_ie_list->action = wlan_cpu_to_le16(cmd_action);
+
+ cust_ie = (mlan_ds_misc_custom_ie *)pdata_buf;
+ pmgmt_ie_list->ds_mgmt_ie.type = wlan_cpu_to_le16(cust_ie->type);
+ pmgmt_ie_list->ds_mgmt_ie.len = wlan_cpu_to_le16(cust_ie->len);
+
+ req_len = cust_ie->len;
+ travel_len = 0;
+ /* conversion for index, mask, len */
+ if (req_len == sizeof(t_u16))
+ cust_ie->ie_data_list[0].ie_index =
+ wlan_cpu_to_le16(cust_ie->ie_data_list[0].ie_index);
+
+ while (req_len > sizeof(t_u16)) {
+ cptr = (custom_ie *)(((t_u8 *)cust_ie->ie_data_list) +
+ travel_len);
+ travel_len += cptr->ie_length + sizeof(custom_ie) - MAX_IE_SIZE;
+ req_len -= cptr->ie_length + sizeof(custom_ie) - MAX_IE_SIZE;
+ cptr->ie_index = wlan_cpu_to_le16(cptr->ie_index);
+ cptr->mgmt_subtype_mask =
+ wlan_cpu_to_le16(cptr->mgmt_subtype_mask);
+ cptr->ie_length = wlan_cpu_to_le16(cptr->ie_length);
+ }
+ if (cust_ie->len)
+ memcpy_ext(pmpriv->adapter,
+ pmgmt_ie_list->ds_mgmt_ie.ie_data_list,
+ cust_ie->ie_data_list, cust_ie->len,
+ sizeof(pmgmt_ie_list->ds_mgmt_ie.ie_data_list));
+
+ cmd->size -= (MAX_MGMT_IE_INDEX_TO_FW * sizeof(custom_ie)) +
+ sizeof(tlvbuf_max_mgmt_ie);
+ cmd->size += cust_ie->len;
+ cmd->size = wlan_cpu_to_le16(cmd->size);
+
+ LEAVE();
+ return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ * @brief This function prepares system clock cfg command
+ *
+ * @param pmpriv A pointer to mlan_private structure
+ * @param cmd A pointer to HostCmd_DS_COMMAND structure
+ * @param cmd_action The action: GET or SET
+ * @param pdata_buf A pointer to data buffer
+ * @return MLAN_STATUS_SUCCESS
+ */
+static mlan_status wlan_cmd_sysclock_cfg(pmlan_private pmpriv,
+ HostCmd_DS_COMMAND *cmd,
+ t_u16 cmd_action, t_void *pdata_buf)
+{
+ HostCmd_DS_ECL_SYSTEM_CLOCK_CONFIG *cfg = &cmd->params.sys_clock_cfg;
+ mlan_ds_misc_sys_clock *clk_cfg = (mlan_ds_misc_sys_clock *)pdata_buf;
+ int i = 0;
+
+ ENTER();
+
+ cmd->command = wlan_cpu_to_le16(HostCmd_CMD_ECL_SYSTEM_CLOCK_CONFIG);
+ cmd->size = wlan_cpu_to_le16(
+ sizeof(HostCmd_DS_ECL_SYSTEM_CLOCK_CONFIG) + S_DS_GEN);
+
+ cfg->action = wlan_cpu_to_le16(cmd_action);
+ cfg->cur_sys_clk = wlan_cpu_to_le16(clk_cfg->cur_sys_clk);
+ cfg->sys_clk_type = wlan_cpu_to_le16(clk_cfg->sys_clk_type);
+ cfg->sys_clk_len =
+ wlan_cpu_to_le16(clk_cfg->sys_clk_num) * sizeof(t_u16);
+ for (i = 0; i < clk_cfg->sys_clk_num; i++)
+ cfg->sys_clk[i] = wlan_cpu_to_le16(clk_cfg->sys_clk[i]);
+
+ LEAVE();
+ return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ * @brief This function prepares command of subscribe event.
+ *
+ * @param pmpriv A pointer to mlan_private structure
+ * @param cmd A pointer to HostCmd_DS_COMMAND structure
+ * @param cmd_action the action: GET or SET
+ * @param pdata_buf A pointer to data buffer
+ * @return MLAN_STATUS_SUCCESS
+ */
+static mlan_status wlan_cmd_subscribe_event(pmlan_private pmpriv,
+ HostCmd_DS_COMMAND *cmd,
+ t_u16 cmd_action, t_void *pdata_buf)
+{
+ mlan_ds_subscribe_evt *sub_evt = (mlan_ds_subscribe_evt *)pdata_buf;
+ HostCmd_DS_SUBSCRIBE_EVENT *evt =
+ (HostCmd_DS_SUBSCRIBE_EVENT *)&cmd->params.subscribe_event;
+ t_u16 cmd_size = 0;
+ t_u8 *tlv = MNULL;
+ MrvlIEtypes_BeaconLowRssiThreshold_t *rssi_low = MNULL;
+ MrvlIEtypes_BeaconLowSnrThreshold_t *snr_low = MNULL;
+ MrvlIEtypes_FailureCount_t *fail_count = MNULL;
+ MrvlIEtypes_BeaconsMissed_t *beacon_missed = MNULL;
+ MrvlIEtypes_BeaconHighRssiThreshold_t *rssi_high = MNULL;
+ MrvlIEtypes_BeaconHighSnrThreshold_t *snr_high = MNULL;
+ MrvlIEtypes_DataLowRssiThreshold_t *data_rssi_low = MNULL;
+ MrvlIEtypes_DataLowSnrThreshold_t *data_snr_low = MNULL;
+ MrvlIEtypes_DataHighRssiThreshold_t *data_rssi_high = MNULL;
+ MrvlIEtypes_DataHighSnrThreshold_t *data_snr_high = MNULL;
+ MrvlIEtypes_LinkQualityThreshold_t *link_quality = MNULL;
+ MrvlIETypes_PreBeaconMissed_t *pre_bcn_missed = MNULL;
+
+ ENTER();
+
+ cmd->command = wlan_cpu_to_le16(HostCmd_CMD_802_11_SUBSCRIBE_EVENT);
+ evt->action = wlan_cpu_to_le16(cmd_action);
+ cmd_size = sizeof(HostCmd_DS_SUBSCRIBE_EVENT) + S_DS_GEN;
+ if (cmd_action == HostCmd_ACT_GEN_GET)
+ goto done;
+ evt->action = wlan_cpu_to_le16(sub_evt->evt_action);
+ evt->event_bitmap = wlan_cpu_to_le16(sub_evt->evt_bitmap);
+ tlv = (t_u8 *)cmd + cmd_size;
+ if (sub_evt->evt_bitmap & SUBSCRIBE_EVT_RSSI_LOW) {
+ rssi_low = (MrvlIEtypes_BeaconLowRssiThreshold_t *)tlv;
+ rssi_low->header.type = wlan_cpu_to_le16(TLV_TYPE_RSSI_LOW);
+ rssi_low->header.len = wlan_cpu_to_le16(
+ sizeof(MrvlIEtypes_BeaconLowRssiThreshold_t) -
+ sizeof(MrvlIEtypesHeader_t));
+ rssi_low->value = sub_evt->low_rssi;
+ rssi_low->frequency = sub_evt->low_rssi_freq;
+ tlv += sizeof(MrvlIEtypes_BeaconLowRssiThreshold_t);
+ cmd_size += sizeof(MrvlIEtypes_BeaconLowRssiThreshold_t);
+ }
+ if (sub_evt->evt_bitmap & SUBSCRIBE_EVT_SNR_LOW) {
+ snr_low = (MrvlIEtypes_BeaconLowSnrThreshold_t *)tlv;
+ snr_low->header.type = wlan_cpu_to_le16(TLV_TYPE_SNR_LOW);
+ snr_low->header.len = wlan_cpu_to_le16(
+ sizeof(MrvlIEtypes_BeaconLowSnrThreshold_t) -
+ sizeof(MrvlIEtypesHeader_t));
+ snr_low->value = sub_evt->low_snr;
+ snr_low->frequency = sub_evt->low_snr_freq;
+ tlv += sizeof(MrvlIEtypes_BeaconLowSnrThreshold_t);
+ cmd_size += sizeof(MrvlIEtypes_BeaconLowSnrThreshold_t);
+ }
+ if (sub_evt->evt_bitmap & SUBSCRIBE_EVT_MAX_FAIL) {
+ fail_count = (MrvlIEtypes_FailureCount_t *)tlv;
+ fail_count->header.type = wlan_cpu_to_le16(TLV_TYPE_FAILCOUNT);
+ fail_count->header.len =
+ wlan_cpu_to_le16(sizeof(MrvlIEtypes_FailureCount_t) -
+ sizeof(MrvlIEtypesHeader_t));
+ fail_count->value = sub_evt->failure_count;
+ fail_count->frequency = sub_evt->failure_count_freq;
+ tlv += sizeof(MrvlIEtypes_FailureCount_t);
+ cmd_size += sizeof(MrvlIEtypes_FailureCount_t);
+ }
+ if (sub_evt->evt_bitmap & SUBSCRIBE_EVT_BEACON_MISSED) {
+ beacon_missed = (MrvlIEtypes_BeaconsMissed_t *)tlv;
+ beacon_missed->header.type = wlan_cpu_to_le16(TLV_TYPE_BCNMISS);
+ beacon_missed->header.len =
+ wlan_cpu_to_le16(sizeof(MrvlIEtypes_BeaconsMissed_t) -
+ sizeof(MrvlIEtypesHeader_t));
+ beacon_missed->value = sub_evt->beacon_miss;
+ beacon_missed->frequency = sub_evt->beacon_miss_freq;
+ tlv += sizeof(MrvlIEtypes_BeaconsMissed_t);
+ cmd_size += sizeof(MrvlIEtypes_BeaconsMissed_t);
+ }
+ if (sub_evt->evt_bitmap & SUBSCRIBE_EVT_RSSI_HIGH) {
+ rssi_high = (MrvlIEtypes_BeaconHighRssiThreshold_t *)tlv;
+ rssi_high->header.type = wlan_cpu_to_le16(TLV_TYPE_RSSI_HIGH);
+ rssi_high->header.len = wlan_cpu_to_le16(
+ sizeof(MrvlIEtypes_BeaconHighRssiThreshold_t) -
+ sizeof(MrvlIEtypesHeader_t));
+ rssi_high->value = sub_evt->high_rssi;
+ rssi_high->frequency = sub_evt->high_rssi_freq;
+ tlv += sizeof(MrvlIEtypes_BeaconHighRssiThreshold_t);
+ cmd_size += sizeof(MrvlIEtypes_BeaconHighRssiThreshold_t);
+ }
+ if (sub_evt->evt_bitmap & SUBSCRIBE_EVT_SNR_HIGH) {
+ snr_high = (MrvlIEtypes_BeaconHighSnrThreshold_t *)tlv;
+ snr_high->header.type = wlan_cpu_to_le16(TLV_TYPE_SNR_HIGH);
+ snr_high->header.len = wlan_cpu_to_le16(
+ sizeof(MrvlIEtypes_BeaconHighSnrThreshold_t) -
+ sizeof(MrvlIEtypesHeader_t));
+ snr_high->value = sub_evt->high_snr;
+ snr_high->frequency = sub_evt->high_snr_freq;
+ tlv += sizeof(MrvlIEtypes_BeaconHighSnrThreshold_t);
+ cmd_size += sizeof(MrvlIEtypes_BeaconHighSnrThreshold_t);
+ }
+ if (sub_evt->evt_bitmap & SUBSCRIBE_EVT_DATA_RSSI_LOW) {
+ data_rssi_low = (MrvlIEtypes_DataLowRssiThreshold_t *)tlv;
+ data_rssi_low->header.type =
+ wlan_cpu_to_le16(TLV_TYPE_RSSI_LOW_DATA);
+ data_rssi_low->header.len = wlan_cpu_to_le16(
+ sizeof(MrvlIEtypes_DataLowRssiThreshold_t) -
+ sizeof(MrvlIEtypesHeader_t));
+ data_rssi_low->value = sub_evt->data_low_rssi;
+ data_rssi_low->frequency = sub_evt->data_low_rssi_freq;
+ tlv += sizeof(MrvlIEtypes_DataLowRssiThreshold_t);
+ cmd_size += sizeof(MrvlIEtypes_DataLowRssiThreshold_t);
+ }
+ if (sub_evt->evt_bitmap & SUBSCRIBE_EVT_DATA_SNR_LOW) {
+ data_snr_low = (MrvlIEtypes_DataLowSnrThreshold_t *)tlv;
+ data_snr_low->header.type =
+ wlan_cpu_to_le16(TLV_TYPE_SNR_LOW_DATA);
+ data_snr_low->header.len = wlan_cpu_to_le16(
+ sizeof(MrvlIEtypes_DataLowSnrThreshold_t) -
+ sizeof(MrvlIEtypesHeader_t));
+ data_snr_low->value = sub_evt->data_low_snr;
+ data_snr_low->frequency = sub_evt->data_low_snr_freq;
+ tlv += sizeof(MrvlIEtypes_DataLowSnrThreshold_t);
+ cmd_size += sizeof(MrvlIEtypes_DataLowSnrThreshold_t);
+ }
+ if (sub_evt->evt_bitmap & SUBSCRIBE_EVT_DATA_RSSI_HIGH) {
+ data_rssi_high = (MrvlIEtypes_DataHighRssiThreshold_t *)tlv;
+ data_rssi_high->header.type =
+ wlan_cpu_to_le16(TLV_TYPE_RSSI_HIGH_DATA);
+ data_rssi_high->header.len = wlan_cpu_to_le16(
+ sizeof(MrvlIEtypes_DataHighRssiThreshold_t) -
+ sizeof(MrvlIEtypesHeader_t));
+ data_rssi_high->value = sub_evt->data_high_rssi;
+ data_rssi_high->frequency = sub_evt->data_high_rssi_freq;
+ tlv += sizeof(MrvlIEtypes_DataHighRssiThreshold_t);
+ cmd_size += sizeof(MrvlIEtypes_DataHighRssiThreshold_t);
+ }
+ if (sub_evt->evt_bitmap & SUBSCRIBE_EVT_DATA_SNR_HIGH) {
+ data_snr_high = (MrvlIEtypes_DataHighSnrThreshold_t *)tlv;
+ data_snr_high->header.type =
+ wlan_cpu_to_le16(TLV_TYPE_SNR_HIGH_DATA);
+ data_snr_high->header.len = wlan_cpu_to_le16(
+ sizeof(MrvlIEtypes_DataHighSnrThreshold_t) -
+ sizeof(MrvlIEtypesHeader_t));
+ data_snr_high->value = sub_evt->data_high_snr;
+ data_snr_high->frequency = sub_evt->data_high_snr_freq;
+ tlv += sizeof(MrvlIEtypes_DataHighSnrThreshold_t);
+ cmd_size += sizeof(MrvlIEtypes_DataHighSnrThreshold_t);
+ }
+ if (sub_evt->evt_bitmap & SUBSCRIBE_EVT_LINK_QUALITY) {
+ link_quality = (MrvlIEtypes_LinkQualityThreshold_t *)tlv;
+ link_quality->header.type =
+ wlan_cpu_to_le16(TLV_TYPE_LINK_QUALITY);
+ link_quality->header.len = wlan_cpu_to_le16(
+ sizeof(MrvlIEtypes_LinkQualityThreshold_t) -
+ sizeof(MrvlIEtypesHeader_t));
+ link_quality->link_snr = wlan_cpu_to_le16(sub_evt->link_snr);
+ link_quality->link_snr_freq =
+ wlan_cpu_to_le16(sub_evt->link_snr_freq);
+ link_quality->link_rate = wlan_cpu_to_le16(sub_evt->link_rate);
+ link_quality->link_rate_freq =
+ wlan_cpu_to_le16(sub_evt->link_rate_freq);
+ link_quality->link_tx_latency =
+ wlan_cpu_to_le16(sub_evt->link_tx_latency);
+ link_quality->link_tx_lantency_freq =
+ wlan_cpu_to_le16(sub_evt->link_tx_lantency_freq);
+ tlv += sizeof(MrvlIEtypes_LinkQualityThreshold_t);
+ cmd_size += sizeof(MrvlIEtypes_LinkQualityThreshold_t);
+ }
+ if (sub_evt->evt_bitmap & SUBSCRIBE_EVT_PRE_BEACON_LOST) {
+ pre_bcn_missed = (MrvlIETypes_PreBeaconMissed_t *)tlv;
+ pre_bcn_missed->header.type =
+ wlan_cpu_to_le16(TLV_TYPE_PRE_BCNMISS);
+ pre_bcn_missed->header.len =
+ wlan_cpu_to_le16(sizeof(MrvlIETypes_PreBeaconMissed_t) -
+ sizeof(MrvlIEtypesHeader_t));
+ pre_bcn_missed->value = sub_evt->pre_beacon_miss;
+ pre_bcn_missed->frequency = 0;
+ tlv += sizeof(MrvlIETypes_PreBeaconMissed_t);
+ cmd_size += sizeof(MrvlIETypes_PreBeaconMissed_t);
+ }
+done:
+ cmd->size = wlan_cpu_to_le16(cmd_size);
+ LEAVE();
+ return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ * @brief This function prepares command of OTP user data.
+ *
+ * @param pmpriv A pointer to mlan_private structure
+ * @param cmd A pointer to HostCmd_DS_COMMAND structure
+ * @param cmd_action the action: GET or SET
+ * @param pdata_buf A pointer to data buffer
+ * @return MLAN_STATUS_SUCCESS
+ */
+static mlan_status wlan_cmd_otp_user_data(pmlan_private pmpriv,
+ HostCmd_DS_COMMAND *cmd,
+ t_u16 cmd_action, t_void *pdata_buf)
+{
+ mlan_ds_misc_otp_user_data *user_data =
+ (mlan_ds_misc_otp_user_data *)pdata_buf;
+ HostCmd_DS_OTP_USER_DATA *cmd_user_data =
+ (HostCmd_DS_OTP_USER_DATA *)&cmd->params.otp_user_data;
+ t_u16 cmd_size = 0;
+
+ ENTER();
+
+ cmd->command = wlan_cpu_to_le16(HostCmd_CMD_OTP_READ_USER_DATA);
+ cmd_size = sizeof(HostCmd_DS_OTP_USER_DATA) + S_DS_GEN - 1;
+
+ cmd_user_data->action = wlan_cpu_to_le16(cmd_action);
+ cmd_user_data->reserved = 0;
+ cmd_user_data->user_data_length =
+ wlan_cpu_to_le16(user_data->user_data_length);
+ cmd_size += user_data->user_data_length;
+ cmd->size = wlan_cpu_to_le16(cmd_size);
+
+ LEAVE();
+ return MLAN_STATUS_SUCCESS;
+}
+
+#ifdef USB
+/**
+ * @brief This function prepares command of packet aggragation
+ *
+ * @param pmpriv A pointer to mlan_private structure
+ * @param cmd A pointer to HostCmd_DS_COMMAND structure
+ * @param cmd_action the action: GET or SET
+ * @param pdata_buf A pointer to data buffer
+ * @return MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ */
+static mlan_status
+wlan_cmd_packet_aggr_over_host_interface(pmlan_private pmpriv,
+ HostCmd_DS_COMMAND *cmd,
+ t_u16 cmd_action, t_void *pdata_buf)
+{
+ HostCmd_DS_PACKET_AGGR_OVER_HOST_INTERFACE *packet_aggr =
+ &cmd->params.packet_aggr;
+ MrvlIETypes_USBAggrParam_t *usb_aggr_param_tlv = MNULL;
+ mlan_ds_misc_usb_aggr_ctrl *usb_aggr_ctrl =
+ (mlan_ds_misc_usb_aggr_ctrl *)pdata_buf;
+ t_u8 *ptlv_buffer = (t_u8 *)packet_aggr->tlv_buf;
+ pmlan_adapter pmadapter = pmpriv->adapter;
+
+ ENTER();
+
+ usb_aggr_param_tlv = (MrvlIETypes_USBAggrParam_t *)ptlv_buffer;
+
+ cmd->command =
+ wlan_cpu_to_le16(HostCmd_CMD_PACKET_AGGR_OVER_HOST_INTERFACE);
+ packet_aggr->action = wlan_cpu_to_le16(cmd_action);
+ memset(pmadapter, usb_aggr_param_tlv, 0,
+ MRVL_USB_AGGR_PARAM_TLV_LEN + sizeof(MrvlIEtypesHeader_t));
+ usb_aggr_param_tlv->header.type =
+ wlan_cpu_to_le16(MRVL_USB_AGGR_PARAM_TLV_ID);
+ usb_aggr_param_tlv->header.len =
+ wlan_cpu_to_le16(MRVL_USB_AGGR_PARAM_TLV_LEN);
+ cmd->size = wlan_cpu_to_le16(
+ sizeof(HostCmd_DS_PACKET_AGGR_OVER_HOST_INTERFACE) + S_DS_GEN +
+ MRVL_USB_AGGR_PARAM_TLV_LEN + sizeof(MrvlIEtypesHeader_t) - 1);
+
+ if (pmadapter->data_sent || (!wlan_bypass_tx_list_empty(pmadapter)) ||
+ (!wlan_wmm_lists_empty(pmadapter))) {
+ /* Make sure this is not issued during traffic */
+ PRINTM(MERROR,
+ "USB aggregation parameters cannot be accessed during traffic.\n");
+ LEAVE();
+ return MLAN_STATUS_FAILURE;
+ }
+
+ if (cmd_action == HostCmd_ACT_GEN_SET) {
+ usb_aggr_param_tlv->enable = 0;
+ if (usb_aggr_ctrl->tx_aggr_ctrl.enable)
+ usb_aggr_param_tlv->enable |= MBIT(1);
+ usb_aggr_param_tlv->tx_aggr_align = wlan_cpu_to_le16(
+ usb_aggr_ctrl->tx_aggr_ctrl.aggr_align);
+ if (usb_aggr_ctrl->rx_deaggr_ctrl.enable)
+ usb_aggr_param_tlv->enable |= MBIT(0);
+ usb_aggr_param_tlv->rx_aggr_mode = wlan_cpu_to_le16(
+ usb_aggr_ctrl->rx_deaggr_ctrl.aggr_mode);
+ usb_aggr_param_tlv->rx_aggr_align = wlan_cpu_to_le16(
+ usb_aggr_ctrl->rx_deaggr_ctrl.aggr_align);
+ usb_aggr_param_tlv->rx_aggr_max = wlan_cpu_to_le16(
+ usb_aggr_ctrl->rx_deaggr_ctrl.aggr_max);
+ usb_aggr_param_tlv->rx_aggr_tmo = wlan_cpu_to_le16(
+ usb_aggr_ctrl->rx_deaggr_ctrl.aggr_tmo);
+ usb_aggr_param_tlv->enable =
+ wlan_cpu_to_le16(usb_aggr_param_tlv->enable);
+ }
+
+ LEAVE();
+ return MLAN_STATUS_SUCCESS;
+}
+#endif
+
+/**
+ * @brief This function prepares inactivity timeout command
+ *
+ * @param cmd A pointer to HostCmd_DS_COMMAND structure
+ * @param cmd_action the action: GET or SET
+ * @param pdata_buf A pointer to data buffer
+ * @return MLAN_STATUS_SUCCESS
+ */
+static mlan_status wlan_cmd_inactivity_timeout(HostCmd_DS_COMMAND *cmd,
+ t_u16 cmd_action,
+ t_void *pdata_buf)
+{
+ pmlan_ds_inactivity_to inac_to;
+ HostCmd_DS_INACTIVITY_TIMEOUT_EXT *cmd_inac_to =
+ &cmd->params.inactivity_to;
+
+ ENTER();
+
+ inac_to = (mlan_ds_inactivity_to *)pdata_buf;
+
+ cmd->size = wlan_cpu_to_le16(sizeof(HostCmd_DS_INACTIVITY_TIMEOUT_EXT) +
+ S_DS_GEN);
+ cmd->command = wlan_cpu_to_le16(cmd->command);
+ cmd_inac_to->action = wlan_cpu_to_le16(cmd_action);
+ if (cmd_action == HostCmd_ACT_GEN_SET) {
+ cmd_inac_to->timeout_unit =
+ wlan_cpu_to_le16((t_u16)inac_to->timeout_unit);
+ cmd_inac_to->unicast_timeout =
+ wlan_cpu_to_le16((t_u16)inac_to->unicast_timeout);
+ cmd_inac_to->mcast_timeout =
+ wlan_cpu_to_le16((t_u16)inac_to->mcast_timeout);
+ cmd_inac_to->ps_entry_timeout =
+ wlan_cpu_to_le16((t_u16)inac_to->ps_entry_timeout);
+ }
+
+ LEAVE();
+ return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ * @brief This function prepares Low Power Mode
+ *
+ * @param pmpriv A pointer to mlan_private structure
+ * @param cmd A pointer to HostCmd_DS_COMMAND structure
+ * @param cmd_action the action: GET or SET
+ * @param pdata_buf A pointer to data buffer
+ *
+ * @return MLAN_STATUS_SUCCESS
+ */
+static mlan_status wlan_cmd_low_pwr_mode(pmlan_private pmpriv,
+ HostCmd_DS_COMMAND *cmd,
+ t_void *pdata_buf)
+{
+ HostCmd_CONFIG_LOW_PWR_MODE *cmd_lpm_cfg =
+ &cmd->params.low_pwr_mode_cfg;
+ t_u8 *enable;
+
+ ENTER();
+
+ cmd->size = S_DS_GEN + sizeof(HostCmd_CONFIG_LOW_PWR_MODE);
+
+ enable = (t_u8 *)pdata_buf;
+ cmd->size = wlan_cpu_to_le16(cmd->size);
+ cmd->command = wlan_cpu_to_le16(cmd->command);
+ cmd_lpm_cfg->enable = *enable;
+
+ LEAVE();
+ return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ * @brief This function prepares DFS repeater mode configuration
+ *
+ * @param pmpriv A pointer to mlan_private structure
+ * @param cmd A pointer to HostCmd_DS_COMMAND structure
+ * @param cmd_action the action: GET or SET
+ * @param pdata_buf A pointer to data buffer
+ *
+ * @return MLAN_STATUS_SUCCESS
+ */
+static mlan_status wlan_cmd_dfs_repeater_cfg(pmlan_private pmpriv,
+ HostCmd_DS_COMMAND *cmd,
+ t_u16 cmd_action,
+ t_void *pdata_buf)
+{
+ mlan_ds_misc_dfs_repeater *dfs_repeater = MNULL;
+ HostCmd_DS_DFS_REPEATER_MODE *cmd_dfs_repeater =
+ &cmd->params.dfs_repeater;
+
+ ENTER();
+
+ cmd->size = S_DS_GEN + sizeof(HostCmd_DS_DFS_REPEATER_MODE);
+
+ dfs_repeater = (mlan_ds_misc_dfs_repeater *)pdata_buf;
+ cmd->size = wlan_cpu_to_le16(cmd->size);
+ cmd->command = wlan_cpu_to_le16(cmd->command);
+ cmd_dfs_repeater->action = wlan_cpu_to_le16(cmd_action);
+
+ if (cmd_action == HostCmd_ACT_GEN_SET)
+ cmd_dfs_repeater->mode = wlan_cpu_to_le16(dfs_repeater->mode);
+
+ LEAVE();
+ return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ * @brief This function prepares command of coalesce_config.
+ *
+ * @param pmpriv A pointer to mlan_private structure
+ * @param cmd A pointer to HostCmd_DS_COMMAND structure
+ * @param cmd_action The action: GET or SET
+ * @param pdata_buf A pointer to data buffer
+ *
+ * @return MLAN_STATUS_SUCCESS
+ */
+mlan_status wlan_cmd_coalesce_config(pmlan_private pmpriv,
+ HostCmd_DS_COMMAND *cmd, t_u16 cmd_action,
+ t_void *pdata_buf)
+{
+ HostCmd_DS_COALESCE_CONFIG *coalesce_config =
+ &cmd->params.coalesce_config;
+ mlan_ds_coalesce_cfg *cfg = (mlan_ds_coalesce_cfg *)pdata_buf;
+ t_u16 cnt, idx, length;
+ struct coalesce_filt_field_param *param;
+ struct coalesce_receive_filt_rule *rule;
+
+ ENTER();
+
+ cmd->size = sizeof(HostCmd_DS_COALESCE_CONFIG) + S_DS_GEN;
+ cmd->command = wlan_cpu_to_le16(HostCmd_CMD_COALESCE_CFG);
+ coalesce_config->action = wlan_cpu_to_le16(cmd_action);
+ coalesce_config->num_of_rules = wlan_cpu_to_le16(cfg->num_of_rules);
+ if (cmd_action == HostCmd_ACT_GEN_SET) {
+ rule = coalesce_config->rule;
+ for (cnt = 0; cnt < cfg->num_of_rules; cnt++) {
+ rule->header.type =
+ wlan_cpu_to_le16(TLV_TYPE_COALESCE_RULE);
+ rule->max_coalescing_delay = wlan_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 = wlan_cpu_to_le16(
+ cfg->rule[cnt].params[idx].offset);
+ memcpy_ext(pmpriv->adapter,
+ param->operand_byte_stream,
+ cfg->rule[cnt]
+ .params[idx]
+ .operand_byte_stream,
+ param->operand_len,
+ sizeof(param->operand_byte_stream));
+
+ length += sizeof(
+ struct coalesce_filt_field_param);
+
+ param++;
+ }
+
+ /* Total rule length is sizeof
+ * max_coalescing_delay(t_u16), num_of_fields(t_u8),
+ * pkt_type(t_u8) and total length of the all params
+ */
+ rule->header.len =
+ wlan_cpu_to_le16(length + sizeof(t_u16) +
+ sizeof(t_u8) + sizeof(t_u8));
+
+ /* Add the rule length to the command size*/
+ cmd->size += wlan_le16_to_cpu(rule->header.len) +
+ sizeof(MrvlIEtypesHeader_t);
+
+ rule = (void *)((t_u8 *)rule->params + length);
+ }
+ }
+ cmd->size = wlan_cpu_to_le16(cmd->size);
+ LEAVE();
+ return MLAN_STATUS_SUCCESS;
+}
+
+/********************************************************
+ * Global Functions
+ ********************************************************/
+
+static mlan_status wlan_cmd_get_sensor_temp(pmlan_private pmpriv,
+ HostCmd_DS_COMMAND *cmd,
+ t_u16 cmd_action)
+{
+ ENTER();
+
+ if (cmd_action != HostCmd_ACT_GEN_GET) {
+ PRINTM(MERROR, "wlan_cmd_get_sensor_temp: support GET only.\n");
+ LEAVE();
+ return MLAN_STATUS_FAILURE;
+ }
+
+ cmd->command = wlan_cpu_to_le16(HostCmd_DS_GET_SENSOR_TEMP);
+ cmd->size = wlan_cpu_to_le16(S_DS_GEN + 4);
+
+ LEAVE();
+ return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ * @brief This function prepares command of arb cfg
+ *
+ * @param pmpriv A pointer to mlan_private structure
+ * @param cmd A pointer to HostCmd_DS_COMMAND structure
+ * @param cmd_action the action: GET or SET
+ * @param pdata_buf A pointer to data buffer
+ * @return MLAN_STATUS_SUCCESS
+ */
+mlan_status wlan_cmd_arb_cfg(pmlan_private pmpriv, HostCmd_DS_COMMAND *cmd,
+ t_u16 cmd_action, t_void *pdata_buf)
+{
+ HostCmd_DS_CMD_ARB_CONFIG *cfg_cmd =
+ (HostCmd_DS_CMD_ARB_CONFIG *)&cmd->params.arb_cfg;
+ mlan_ds_misc_arb_cfg *misc_cfg = (mlan_ds_misc_arb_cfg *)pdata_buf;
+
+ ENTER();
+
+ cmd->command = wlan_cpu_to_le16(HostCmd_CMD_ARB_CONFIG);
+ cmd->size =
+ wlan_cpu_to_le16(sizeof(HostCmd_DS_CMD_ARB_CONFIG) + S_DS_GEN);
+ cfg_cmd->action = wlan_cpu_to_le16(cmd_action);
+
+ if (cmd_action == HostCmd_ACT_GEN_SET) {
+ cfg_cmd->arb_mode = wlan_cpu_to_le32(misc_cfg->arb_mode);
+ if (misc_cfg->arb_mode == 3) {
+#define DEF_ARB_TX_WIN 4
+#define DEF_ARB_TIMEOUT 0
+ pmpriv->add_ba_param.timeout = DEF_ARB_TIMEOUT;
+ pmpriv->add_ba_param.tx_win_size = DEF_ARB_TX_WIN;
+ } else {
+ pmpriv->add_ba_param.timeout =
+ MLAN_DEFAULT_BLOCK_ACK_TIMEOUT;
+ pmpriv->add_ba_param.tx_win_size =
+ MLAN_STA_AMPDU_DEF_TXWINSIZE;
+ }
+ }
+
+ LEAVE();
+ return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ * @brief This function sends get sta band channel command to firmware.
+ *
+ * @param priv A pointer to mlan_private structure
+ * @param cmd Hostcmd ID
+ * @return N/A
+ */
+static mlan_status wlan_cmd_sta_config(pmlan_private pmpriv,
+ HostCmd_DS_COMMAND *cmd,
+ t_u16 cmd_action,
+ mlan_ioctl_req *pioctl_buf,
+ t_void *pdata_buf)
+{
+ mlan_ds_bss *bss = MNULL;
+ HostCmd_DS_STA_CONFIGURE *sta_cfg_cmd = &cmd->params.sta_cfg;
+ MrvlIEtypes_channel_band_t *tlv_band_channel = MNULL;
+ mlan_status ret = MLAN_STATUS_FAILURE;
+
+ ENTER();
+ if (!pioctl_buf)
+ return ret;
+
+ if (pioctl_buf->req_id == MLAN_IOCTL_BSS) {
+ bss = (mlan_ds_bss *)pioctl_buf->pbuf;
+ if ((bss->sub_command == MLAN_OID_BSS_CHAN_INFO) &&
+ (cmd_action == HostCmd_ACT_GEN_GET)) {
+ cmd->command =
+ wlan_cpu_to_le16(HostCmd_CMD_STA_CONFIGURE);
+ cmd->size = wlan_cpu_to_le16(
+ S_DS_GEN + sizeof(HostCmd_DS_STA_CONFIGURE) +
+ sizeof(*tlv_band_channel));
+ sta_cfg_cmd->action = wlan_cpu_to_le16(cmd_action);
+ tlv_band_channel = (MrvlIEtypes_channel_band_t *)
+ sta_cfg_cmd->tlv_buffer;
+ memset(pmpriv->adapter, tlv_band_channel, 0x00,
+ sizeof(*tlv_band_channel));
+ tlv_band_channel->header.type =
+ wlan_cpu_to_le16(TLV_TYPE_CHANNELBANDLIST);
+ tlv_band_channel->header.len = wlan_cpu_to_le16(
+ sizeof(MrvlIEtypes_channel_band_t) -
+ sizeof(MrvlIEtypesHeader_t));
+ ret = MLAN_STATUS_SUCCESS;
+ }
+ }
+
+ LEAVE();
+ return ret;
+}
+
+/**
+ * @brief This function sends set and get auto tx command to firmware.
+ *
+ * @param pmpriv A pointer to mlan_private structure
+ * @param pcmd Hostcmd ID
+ * @param cmd_action Command action
+ * @param cmd_oid Cmd oid: treated as sub command
+ * @param pdata_buf A void pointer to information buffer
+ * @return N/A
+ */
+static mlan_status wlan_cmd_auto_tx(pmlan_private pmpriv,
+ HostCmd_DS_COMMAND *cmd, t_u16 cmd_action,
+ t_u32 cmd_oid, t_void *pdata_buf)
+{
+ HostCmd_DS_AUTO_TX *auto_tx_cmd = &cmd->params.auto_tx;
+ t_u8 *pos = (t_u8 *)auto_tx_cmd->tlv_buffer;
+ t_u16 len = 0;
+ MrvlIEtypes_Cloud_Keep_Alive_t *keep_alive_tlv = MNULL;
+ MrvlIEtypes_Keep_Alive_Ctrl_t *ctrl_tlv = MNULL;
+ MrvlIEtypes_Keep_Alive_Pkt_t *pkt_tlv = MNULL;
+ mlan_ds_misc_keep_alive *misc_keep_alive = MNULL;
+ t_u8 eth_ip[] = {0x08, 0x00};
+
+ ENTER();
+
+ cmd->command = wlan_cpu_to_le16(HostCmd_CMD_AUTO_TX);
+ cmd->size = S_DS_GEN + sizeof(HostCmd_DS_AUTO_TX);
+ auto_tx_cmd->action = wlan_cpu_to_le16(cmd_action);
+
+ switch (cmd_oid) {
+ case OID_CLOUD_KEEP_ALIVE:
+ misc_keep_alive = (mlan_ds_misc_keep_alive *)pdata_buf;
+ keep_alive_tlv = (MrvlIEtypes_Cloud_Keep_Alive_t *)pos;
+
+ keep_alive_tlv->header.type =
+ wlan_cpu_to_le16(TLV_TYPE_CLOUD_KEEP_ALIVE);
+ keep_alive_tlv->keep_alive_id = misc_keep_alive->mkeep_alive_id;
+ keep_alive_tlv->enable = misc_keep_alive->enable;
+ len = len + sizeof(keep_alive_tlv->keep_alive_id) +
+ sizeof(keep_alive_tlv->enable);
+ pos = pos + len + sizeof(MrvlIEtypesHeader_t);
+ if (cmd_action == HostCmd_ACT_GEN_SET) {
+ if (misc_keep_alive->enable) {
+ ctrl_tlv = (MrvlIEtypes_Keep_Alive_Ctrl_t *)pos;
+ ctrl_tlv->header.type = wlan_cpu_to_le16(
+ TLV_TYPE_KEEP_ALIVE_CTRL);
+ ctrl_tlv->header.len = wlan_cpu_to_le16(
+ sizeof(MrvlIEtypes_Keep_Alive_Ctrl_t) -
+ sizeof(MrvlIEtypesHeader_t));
+ ctrl_tlv->snd_interval = wlan_cpu_to_le32(
+ misc_keep_alive->send_interval);
+ ctrl_tlv->retry_interval = wlan_cpu_to_le16(
+ misc_keep_alive->retry_interval);
+ ctrl_tlv->retry_count = wlan_cpu_to_le16(
+ misc_keep_alive->retry_count);
+ len = len +
+ sizeof(MrvlIEtypes_Keep_Alive_Ctrl_t);
+
+ pos = pos +
+ sizeof(MrvlIEtypes_Keep_Alive_Ctrl_t);
+ pkt_tlv = (MrvlIEtypes_Keep_Alive_Pkt_t *)pos;
+ pkt_tlv->header.type = wlan_cpu_to_le16(
+ TLV_TYPE_KEEP_ALIVE_PKT);
+ memcpy_ext(pmpriv->adapter,
+ pkt_tlv->eth_header.dest_addr,
+ misc_keep_alive->dst_mac,
+ MLAN_MAC_ADDR_LENGTH,
+ MLAN_MAC_ADDR_LENGTH);
+ memcpy_ext(pmpriv->adapter,
+ pkt_tlv->eth_header.src_addr,
+ misc_keep_alive->src_mac,
+ MLAN_MAC_ADDR_LENGTH,
+ MLAN_MAC_ADDR_LENGTH);
+ memcpy_ext(
+ pmpriv->adapter,
+ (t_u8 *)&pkt_tlv->eth_header.h803_len,
+ eth_ip, sizeof(t_u16), sizeof(t_u16));
+ if (misc_keep_alive->ether_type)
+ pkt_tlv->eth_header
+ .h803_len = mlan_htons(
+ misc_keep_alive->ether_type);
+ else
+ memcpy_ext(pmpriv->adapter,
+ (t_u8 *)&pkt_tlv->eth_header
+ .h803_len,
+ eth_ip, sizeof(t_u16),
+ sizeof(t_u16));
+ pkt_tlv->header.len = wlan_cpu_to_le16(
+ sizeof(Eth803Hdr_t) +
+ misc_keep_alive->pkt_len);
+ len = len + sizeof(MrvlIEtypesHeader_t) +
+ sizeof(Eth803Hdr_t) +
+ misc_keep_alive->pkt_len;
+ } else {
+ pkt_tlv = (MrvlIEtypes_Keep_Alive_Pkt_t *)pos;
+ pkt_tlv->header.type = wlan_cpu_to_le16(
+ TLV_TYPE_KEEP_ALIVE_PKT);
+ pkt_tlv->header.len = 0;
+ len = len + sizeof(MrvlIEtypesHeader_t);
+ }
+ }
+ if (cmd_action == HostCmd_ACT_GEN_RESET) {
+ pkt_tlv = (MrvlIEtypes_Keep_Alive_Pkt_t *)pos;
+ pkt_tlv->header.type =
+ wlan_cpu_to_le16(TLV_TYPE_KEEP_ALIVE_PKT);
+ pkt_tlv->header.len = 0;
+ len = len + sizeof(MrvlIEtypesHeader_t);
+ }
+ keep_alive_tlv->header.len = wlan_cpu_to_le16(len);
+
+ cmd->size = cmd->size + len + sizeof(MrvlIEtypesHeader_t);
+ cmd->size = wlan_cpu_to_le16(cmd->size);
+ break;
+ default:
+ break;
+ }
+
+ LEAVE();
+ return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ * @brief This function check if the command is supported by firmware
+ *
+ * @param priv A pointer to mlan_private structure
+ * @param cmd_no Command number
+ *
+ * @return MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ */
+mlan_status wlan_is_cmd_allowed(mlan_private *priv, t_u16 cmd_no)
+{
+ mlan_status ret = MLAN_STATUS_SUCCESS;
+
+ ENTER();
+ if (priv->adapter->pcard_info->v16_fw_api) {
+ if (!IS_FW_SUPPORT_ADHOC(priv->adapter)) {
+ switch (cmd_no) {
+ case HostCmd_ACT_MAC_ADHOC_G_PROTECTION_ON:
+ case HostCmd_CMD_802_11_IBSS_COALESCING_STATUS:
+ case HostCmd_CMD_802_11_AD_HOC_START:
+ case HostCmd_CMD_802_11_AD_HOC_JOIN:
+ case HostCmd_CMD_802_11_AD_HOC_STOP:
+ ret = MLAN_STATUS_FAILURE;
+ break;
+ default:
+ break;
+ }
+ }
+ }
+ LEAVE();
+ return ret;
+}
+
+/**
+ * @brief This function prepare the command before sending to firmware.
+ *
+ * @param priv A pointer to mlan_private structure
+ * @param cmd_no Command number
+ * @param cmd_action Command action: GET or SET
+ * @param cmd_oid Cmd oid: treated as sub command
+ * @param pioctl_buf A pointer to MLAN IOCTL Request buffer
+ * @param pdata_buf A pointer to information buffer
+ * @param pcmd_buf A pointer to cmd buf
+ *
+ * @return MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ */
+mlan_status wlan_ops_sta_prepare_cmd(t_void *priv, t_u16 cmd_no,
+ t_u16 cmd_action, t_u32 cmd_oid,
+ t_void *pioctl_buf, t_void *pdata_buf,
+ t_void *pcmd_buf)
+{
+ HostCmd_DS_COMMAND *cmd_ptr = (HostCmd_DS_COMMAND *)pcmd_buf;
+ mlan_private *pmpriv = (mlan_private *)priv;
+ mlan_status ret = MLAN_STATUS_SUCCESS;
+
+ ENTER();
+
+ if (wlan_is_cmd_allowed(pmpriv, cmd_no)) {
+ PRINTM(MERROR, "FW don't support the command 0x%x\n", cmd_no);
+ return MLAN_STATUS_FAILURE;
+ }
+ /* Prepare command */
+ switch (cmd_no) {
+ case HostCmd_CMD_GET_HW_SPEC:
+ ret = wlan_cmd_get_hw_spec(pmpriv, cmd_ptr);
+ break;
+#ifdef SDIO
+ case HostCmd_CMD_SDIO_SP_RX_AGGR_CFG:
+ ret = wlan_cmd_sdio_rx_aggr_cfg(cmd_ptr, cmd_action, pdata_buf);
+ break;
+#endif
+ case HostCmd_CMD_CFG_DATA:
+ ret = wlan_cmd_cfg_data(pmpriv, cmd_ptr, cmd_action, cmd_oid,
+ pdata_buf);
+ break;
+ case HostCmd_CMD_MAC_CONTROL:
+ ret = wlan_cmd_mac_control(pmpriv, cmd_ptr, cmd_action,
+ pdata_buf);
+ break;
+ case HostCmd_CMD_802_11_MAC_ADDRESS:
+ ret = wlan_cmd_802_11_mac_address(pmpriv, cmd_ptr, cmd_action);
+ break;
+ case HostCmd_CMD_MAC_MULTICAST_ADR:
+ ret = wlan_cmd_mac_multicast_adr(pmpriv, cmd_ptr, cmd_action,
+ pdata_buf);
+ break;
+ case HostCmd_CMD_TX_RATE_CFG:
+ ret = wlan_cmd_tx_rate_cfg(pmpriv, cmd_ptr, cmd_action,
+ pdata_buf, pioctl_buf);
+ break;
+ case HostCmd_CMD_802_11_RF_ANTENNA:
+ ret = wlan_cmd_802_11_rf_antenna(pmpriv, cmd_ptr, cmd_action,
+ pdata_buf);
+ break;
+ case HostCmd_CMD_CW_MODE_CTRL:
+ ret = wlan_cmd_cw_mode_ctrl(pmpriv, cmd_ptr, cmd_action,
+ pdata_buf);
+ break;
+ case HostCmd_CMD_TXPWR_CFG:
+ ret = wlan_cmd_tx_power_cfg(pmpriv, cmd_ptr, cmd_action,
+ pdata_buf);
+ break;
+ case HostCmd_CMD_802_11_RF_TX_POWER:
+ ret = wlan_cmd_802_11_rf_tx_power(pmpriv, cmd_ptr, cmd_action,
+ pdata_buf);
+ break;
+ case HostCmd_CMD_802_11_PS_MODE_ENH:
+ ret = wlan_cmd_enh_power_mode(pmpriv, cmd_ptr, cmd_action,
+ (t_u16)cmd_oid, pdata_buf);
+ break;
+ case HostCmd_CMD_802_11_HS_CFG_ENH:
+ ret = wlan_cmd_802_11_hs_cfg(pmpriv, cmd_ptr, cmd_action,
+ (hs_config_param *)pdata_buf);
+ break;
+ case HostCmd_CMD_802_11_ROBUSTCOEX:
+ ret = wlan_cmd_robustcoex(pmpriv, cmd_ptr, cmd_action,
+ pdata_buf);
+ break;
+ case HostCmd_CMD_DMCS_CONFIG:
+ ret = wlan_cmd_dmcs_config(pmpriv, cmd_ptr, cmd_action,
+ pdata_buf);
+ break;
+#if defined(PCIE)
+ case HostCmd_CMD_SSU:
+ ret = wlan_cmd_ssu(pmpriv, cmd_ptr, cmd_action, pdata_buf);
+ break;
+#endif
+ case HOST_CMD_PMIC_CONFIGURE:
+ cmd_ptr->command = wlan_cpu_to_le16(cmd_no);
+ cmd_ptr->size = wlan_cpu_to_le16(S_DS_GEN);
+ break;
+ case HostCmd_CMD_802_11_SLEEP_PERIOD:
+ ret = wlan_cmd_802_11_sleep_period(pmpriv, cmd_ptr, cmd_action,
+ (t_u16 *)pdata_buf);
+ break;
+ case HostCmd_CMD_802_11_SLEEP_PARAMS:
+ ret = wlan_cmd_802_11_sleep_params(pmpriv, cmd_ptr, cmd_action,
+ (t_u16 *)pdata_buf);
+ break;
+ case HostCmd_CMD_802_11_SCAN:
+ ret = wlan_cmd_802_11_scan(pmpriv, cmd_ptr, pdata_buf);
+ break;
+ case HostCmd_CMD_802_11_BG_SCAN_CONFIG:
+ ret = wlan_cmd_bgscan_config(pmpriv, cmd_ptr, pdata_buf);
+ break;
+ case HostCmd_CMD_802_11_BG_SCAN_QUERY:
+ ret = wlan_cmd_802_11_bg_scan_query(pmpriv, cmd_ptr, pdata_buf);
+ break;
+ case HostCmd_CMD_802_11_ASSOCIATE:
+ ret = wlan_cmd_802_11_associate(pmpriv, cmd_ptr, pdata_buf);
+ break;
+ case HostCmd_CMD_802_11_DEAUTHENTICATE:
+ case HostCmd_CMD_802_11_DISASSOCIATE:
+ ret = wlan_cmd_802_11_deauthenticate(pmpriv, cmd_no, cmd_ptr,
+ pdata_buf);
+ break;
+ case HostCmd_CMD_802_11_AD_HOC_START:
+ ret = wlan_cmd_802_11_ad_hoc_start(pmpriv, cmd_ptr, pdata_buf);
+ break;
+ case HostCmd_CMD_802_11_AD_HOC_JOIN:
+ ret = wlan_cmd_802_11_ad_hoc_join(pmpriv, cmd_ptr, pdata_buf);
+ break;
+ case HostCmd_CMD_802_11_AD_HOC_STOP:
+ ret = wlan_cmd_802_11_ad_hoc_stop(pmpriv, cmd_ptr);
+ break;
+ case HostCmd_CMD_802_11_GET_LOG:
+ ret = wlan_cmd_802_11_get_log(pmpriv, cmd_ptr);
+ break;
+ case HostCmd_CMD_802_11_LINK_STATS:
+ ret = wlan_cmd_802_11_link_statistic(pmpriv, cmd_ptr,
+ cmd_action, pioctl_buf);
+ break;
+ case HostCmd_CMD_RSSI_INFO:
+ ret = wlan_cmd_802_11_rssi_info(pmpriv, cmd_ptr, cmd_action);
+ break;
+ case HostCmd_CMD_RSSI_INFO_EXT:
+ ret = wlan_cmd_802_11_rssi_info_ext(pmpriv, cmd_ptr, cmd_action,
+ pdata_buf);
+ break;
+ case HostCmd_CMD_802_11_SNMP_MIB:
+ ret = wlan_cmd_802_11_snmp_mib(pmpriv, cmd_ptr, cmd_action,
+ cmd_oid, pdata_buf);
+ break;
+ case HostCmd_CMD_802_11_RADIO_CONTROL:
+ ret = wlan_cmd_802_11_radio_control(pmpriv, cmd_ptr, cmd_action,
+ pdata_buf);
+ break;
+ case HostCmd_CMD_802_11_TX_RATE_QUERY:
+ cmd_ptr->command =
+ wlan_cpu_to_le16(HostCmd_CMD_802_11_TX_RATE_QUERY);
+ cmd_ptr->size = wlan_cpu_to_le16(sizeof(HostCmd_TX_RATE_QUERY) +
+ S_DS_GEN);
+ pmpriv->tx_rate = 0;
+ ret = MLAN_STATUS_SUCCESS;
+ break;
+ case HostCmd_CMD_VERSION_EXT:
+ cmd_ptr->command = wlan_cpu_to_le16(cmd_no);
+ cmd_ptr->params.verext.version_str_sel =
+ (t_u8)(*((t_u32 *)pdata_buf));
+ cmd_ptr->size = wlan_cpu_to_le16(
+ sizeof(HostCmd_DS_VERSION_EXT) + S_DS_GEN);
+ ret = MLAN_STATUS_SUCCESS;
+ break;
+ case HostCmd_CMD_RX_MGMT_IND:
+ cmd_ptr->command = wlan_cpu_to_le16(cmd_no);
+ cmd_ptr->params.rx_mgmt_ind.action =
+ wlan_cpu_to_le16(cmd_action);
+ cmd_ptr->params.rx_mgmt_ind.mgmt_subtype_mask =
+ wlan_cpu_to_le32((t_u32)(*((t_u32 *)pdata_buf)));
+ cmd_ptr->size = wlan_cpu_to_le16(
+ sizeof(HostCmd_DS_RX_MGMT_IND) + S_DS_GEN);
+ break;
+ case HostCmd_CMD_802_11_RF_CHANNEL:
+ ret = wlan_cmd_802_11_rf_channel(pmpriv, cmd_ptr, cmd_action,
+ pdata_buf);
+ break;
+ case HostCmd_CMD_FUNC_INIT:
+ if (pmpriv->adapter->hw_status == WlanHardwareStatusReset)
+ pmpriv->adapter->hw_status =
+ WlanHardwareStatusInitializing;
+ cmd_ptr->command = wlan_cpu_to_le16(cmd_no);
+ cmd_ptr->size = wlan_cpu_to_le16(S_DS_GEN);
+ break;
+ case HostCmd_CMD_FUNC_SHUTDOWN:
+ pmpriv->adapter->hw_status = WlanHardwareStatusReset;
+ cmd_ptr->command = wlan_cpu_to_le16(cmd_no);
+ cmd_ptr->size = wlan_cpu_to_le16(S_DS_GEN);
+ break;
+ case HostCmd_CMD_SOFT_RESET:
+ cmd_ptr->command = wlan_cpu_to_le16(cmd_no);
+ cmd_ptr->size = wlan_cpu_to_le16(S_DS_GEN);
+ break;
+ case HostCmd_CMD_11N_ADDBA_REQ:
+ ret = wlan_cmd_11n_addba_req(pmpriv, cmd_ptr, pdata_buf);
+ break;
+ case HostCmd_CMD_11N_DELBA:
+ ret = wlan_cmd_11n_delba(pmpriv, cmd_ptr, pdata_buf);
+ break;
+ case HostCmd_CMD_11N_ADDBA_RSP:
+ ret = wlan_cmd_11n_addba_rspgen(pmpriv, cmd_ptr, pdata_buf);
+ break;
+ case HostCmd_CMD_802_11_KEY_MATERIAL:
+ ret = wlan_cmd_802_11_key_material(pmpriv, cmd_ptr, cmd_action,
+ cmd_oid, pdata_buf);
+ break;
+ case HostCmd_CMD_GTK_REKEY_OFFLOAD_CFG:
+ ret = wlan_cmd_gtk_rekey_offload(pmpriv, cmd_ptr, cmd_action,
+ cmd_oid, pdata_buf);
+ break;
+
+ case HostCmd_CMD_SUPPLICANT_PMK:
+ ret = wlan_cmd_802_11_supplicant_pmk(pmpriv, cmd_ptr,
+ cmd_action, pdata_buf);
+ break;
+ case HostCmd_CMD_802_11_EAPOL_PKT:
+ ret = wlan_cmd_eapol_pkt(pmpriv, cmd_ptr, cmd_action,
+ pdata_buf);
+ break;
+ case HostCmd_CMD_SUPPLICANT_PROFILE:
+ ret = wlan_cmd_802_11_supplicant_profile(pmpriv, cmd_ptr,
+ cmd_action, pdata_buf);
+ break;
+
+ case HostCmd_CMD_802_11D_DOMAIN_INFO:
+ ret = wlan_cmd_802_11d_domain_info(pmpriv, cmd_ptr, cmd_action);
+ break;
+ case HostCmd_CMD_802_11_TPC_ADAPT_REQ:
+ case HostCmd_CMD_802_11_TPC_INFO:
+ case HostCmd_CMD_802_11_CHAN_SW_ANN:
+ case HostCmd_CMD_CHAN_REPORT_REQUEST:
+ ret = wlan_11h_cmd_process(pmpriv, cmd_ptr, pdata_buf);
+ break;
+ case HostCmd_CMD_RECONFIGURE_TX_BUFF:
+ ret = wlan_cmd_recfg_tx_buf(pmpriv, cmd_ptr, cmd_action,
+ pdata_buf);
+ break;
+ case HostCmd_CMD_AMSDU_AGGR_CTRL:
+ ret = wlan_cmd_amsdu_aggr_ctrl(pmpriv, cmd_ptr, cmd_action,
+ pdata_buf);
+ break;
+ case HostCmd_CMD_11N_CFG:
+ ret = wlan_cmd_11n_cfg(pmpriv, cmd_ptr, cmd_action, pdata_buf);
+ break;
+ case HostCmd_CMD_11AC_CFG:
+ ret = wlan_cmd_11ac_cfg(pmpriv, cmd_ptr, cmd_action, pdata_buf);
+ break;
+#if 0
+ case HostCmd_CMD_RECONFIGURE_TX_BUFF:
+ ret = wlan_cmd_recfg_tx_buf(pmpriv, cmd_ptr, cmd_action,
+ pdata_buf);
+ break;
+#endif
+ case HostCmd_CMD_TX_BF_CFG:
+ ret = wlan_cmd_tx_bf_cfg(pmpriv, cmd_ptr, cmd_action,
+ pdata_buf);
+ break;
+ case HostCmd_CMD_WMM_GET_STATUS:
+ PRINTM(MINFO, "WMM: WMM_GET_STATUS cmd sent\n");
+ cmd_ptr->command = wlan_cpu_to_le16(HostCmd_CMD_WMM_GET_STATUS);
+ cmd_ptr->size = wlan_cpu_to_le16(
+ sizeof(HostCmd_DS_WMM_GET_STATUS) + S_DS_GEN);
+ ret = MLAN_STATUS_SUCCESS;
+ break;
+ case HostCmd_CMD_WMM_ADDTS_REQ:
+ ret = wlan_cmd_wmm_addts_req(pmpriv, cmd_ptr, pdata_buf);
+ break;
+ case HostCmd_CMD_WMM_DELTS_REQ:
+ ret = wlan_cmd_wmm_delts_req(pmpriv, cmd_ptr, pdata_buf);
+ break;
+ case HostCmd_CMD_WMM_QUEUE_CONFIG:
+ ret = wlan_cmd_wmm_queue_config(pmpriv, cmd_ptr, pdata_buf);
+ break;
+ case HostCmd_CMD_WMM_QUEUE_STATS:
+ ret = wlan_cmd_wmm_queue_stats(pmpriv, cmd_ptr, pdata_buf);
+ break;
+ case HostCmd_CMD_WMM_TS_STATUS:
+ ret = wlan_cmd_wmm_ts_status(pmpriv, cmd_ptr, pdata_buf);
+ break;
+ case HostCmd_CMD_WMM_PARAM_CONFIG:
+ ret = wlan_cmd_wmm_param_config(pmpriv, cmd_ptr, cmd_action,
+ pdata_buf);
+ break;
+ case HostCmd_CMD_802_11_IBSS_COALESCING_STATUS:
+ ret = wlan_cmd_ibss_coalescing_status(pmpriv, cmd_ptr,
+ cmd_action, pdata_buf);
+ break;
+ case HostCmd_CMD_MGMT_IE_LIST:
+ ret = wlan_cmd_mgmt_ie_list(pmpriv, cmd_ptr, cmd_action,
+ pdata_buf);
+ break;
+ case HostCmd_CMD_802_11_SCAN_EXT:
+ ret = wlan_cmd_802_11_scan_ext(pmpriv, cmd_ptr, pdata_buf);
+ break;
+ case HostCmd_CMD_ECL_SYSTEM_CLOCK_CONFIG:
+ ret = wlan_cmd_sysclock_cfg(pmpriv, cmd_ptr, cmd_action,
+ pdata_buf);
+ break;
+ case HostCmd_CMD_MAC_REG_ACCESS:
+ case HostCmd_CMD_BBP_REG_ACCESS:
+ case HostCmd_CMD_RF_REG_ACCESS:
+ case HostCmd_CMD_CAU_REG_ACCESS:
+ case HostCmd_CMD_TARGET_ACCESS:
+ case HostCmd_CMD_802_11_EEPROM_ACCESS:
+ case HostCmd_CMD_BCA_REG_ACCESS:
+ ret = wlan_cmd_reg_access(pmpriv, cmd_ptr, cmd_action,
+ pdata_buf);
+ break;
+ case HostCmd_CMD_MEM_ACCESS:
+ ret = wlan_cmd_mem_access(cmd_ptr, cmd_action, pdata_buf);
+ break;
+ case HostCmd_CMD_INACTIVITY_TIMEOUT_EXT:
+ ret = wlan_cmd_inactivity_timeout(cmd_ptr, cmd_action,
+ pdata_buf);
+ break;
+ case HostCmd_CMD_GET_TSF:
+ ret = wlan_cmd_get_tsf(pmpriv, cmd_ptr, cmd_action);
+ break;
+#if defined(SDIO)
+ case HostCmd_CMD_SDIO_GPIO_INT_CONFIG:
+ ret = wlan_cmd_sdio_gpio_int(pmpriv, cmd_ptr, cmd_action,
+ pdata_buf);
+ break;
+#endif
+ case HostCmd_CMD_SET_BSS_MODE:
+ cmd_ptr->command = wlan_cpu_to_le16(cmd_no);
+#ifdef WIFI_DIRECT_SUPPORT
+ if (pdata_buf) {
+ cmd_ptr->params.bss_mode.con_type = *(t_u8 *)pdata_buf;
+ } else
+#endif
+ if (pmpriv->bss_mode == MLAN_BSS_MODE_IBSS)
+ cmd_ptr->params.bss_mode.con_type =
+ CONNECTION_TYPE_ADHOC;
+ else if (pmpriv->bss_mode == MLAN_BSS_MODE_INFRA)
+ cmd_ptr->params.bss_mode.con_type =
+ CONNECTION_TYPE_INFRA;
+ cmd_ptr->size = wlan_cpu_to_le16(
+ sizeof(HostCmd_DS_SET_BSS_MODE) + S_DS_GEN);
+ ret = MLAN_STATUS_SUCCESS;
+ break;
+ case HostCmd_CMD_MEASUREMENT_REQUEST:
+ case HostCmd_CMD_MEASUREMENT_REPORT:
+ ret = wlan_meas_cmd_process(pmpriv, cmd_ptr, pdata_buf);
+ break;
+#if defined(PCIE)
+#if defined(PCIE8997) || defined(PCIE8897)
+ case HostCmd_CMD_PCIE_HOST_BUF_DETAILS:
+ ret = wlan_cmd_pcie_host_buf_cfg(pmpriv, cmd_ptr, cmd_action,
+ pdata_buf);
+ break;
+#endif
+#endif
+ case HostCmd_CMD_802_11_REMAIN_ON_CHANNEL:
+ ret = wlan_cmd_remain_on_channel(pmpriv, cmd_ptr, cmd_action,
+ pdata_buf);
+ break;
+#ifdef WIFI_DIRECT_SUPPORT
+ case HOST_CMD_WIFI_DIRECT_MODE_CONFIG:
+ ret = wlan_cmd_wifi_direct_mode(pmpriv, cmd_ptr, cmd_action,
+ pdata_buf);
+ break;
+#endif
+ case HostCmd_CMD_802_11_SUBSCRIBE_EVENT:
+ ret = wlan_cmd_subscribe_event(pmpriv, cmd_ptr, cmd_action,
+ pdata_buf);
+ break;
+ case HostCmd_CMD_OTP_READ_USER_DATA:
+ ret = wlan_cmd_otp_user_data(pmpriv, cmd_ptr, cmd_action,
+ pdata_buf);
+ break;
+ case HostCmd_CMD_HS_WAKEUP_REASON:
+ ret = wlan_cmd_hs_wakeup_reason(pmpriv, cmd_ptr, pdata_buf);
+ break;
+ case HostCmd_CMD_REJECT_ADDBA_REQ:
+ ret = wlan_cmd_reject_addba_req(pmpriv, cmd_ptr, cmd_action,
+ pdata_buf);
+ break;
+ case HostCmd_CMD_PACKET_AGGR_CTRL:
+ ret = wlan_cmd_packet_aggr_ctrl(pmpriv, cmd_ptr, cmd_action,
+ pdata_buf);
+ break;
+#ifdef USB
+ case HostCmd_CMD_PACKET_AGGR_OVER_HOST_INTERFACE:
+ ret = wlan_cmd_packet_aggr_over_host_interface(
+ pmpriv, cmd_ptr, cmd_action, pdata_buf);
+ break;
+#endif
+#ifdef RX_PACKET_COALESCE
+ case HostCmd_CMD_RX_PKT_COALESCE_CFG:
+ ret = wlan_cmd_rx_pkt_coalesce_cfg(pmpriv, cmd_ptr, cmd_action,
+ pdata_buf);
+ break;
+#endif
+ case HostCMD_CONFIG_LOW_POWER_MODE:
+ ret = wlan_cmd_low_pwr_mode(pmpriv, cmd_ptr, pdata_buf);
+ break;
+ case HostCmd_DFS_REPEATER_MODE:
+ ret = wlan_cmd_dfs_repeater_cfg(pmpriv, cmd_ptr, cmd_action,
+ pdata_buf);
+ break;
+ case HostCmd_CMD_COALESCE_CFG:
+ ret = wlan_cmd_coalesce_config(pmpriv, cmd_ptr, cmd_action,
+ pdata_buf);
+ break;
+ case HostCmd_DS_GET_SENSOR_TEMP:
+ ret = wlan_cmd_get_sensor_temp(pmpriv, cmd_ptr, cmd_action);
+ break;
+ case HostCmd_CMD_802_11_MIMO_SWITCH:
+ ret = wlan_cmd_802_11_mimo_switch(pmpriv, cmd_ptr, pdata_buf);
+ break;
+ case HostCmd_CMD_STA_CONFIGURE:
+ ret = wlan_cmd_sta_config(pmpriv, cmd_ptr, cmd_action,
+ pioctl_buf, pdata_buf);
+ break;
+
+ case HostCmd_CMD_INDEPENDENT_RESET_CFG:
+ ret = wlan_cmd_ind_rst_cfg(cmd_ptr, cmd_action, pdata_buf);
+ break;
+
+ case HostCmd_CMD_802_11_PS_INACTIVITY_TIMEOUT:
+ ret = wlan_cmd_ps_inactivity_timeout(pmpriv, cmd_ptr,
+ cmd_action, pdata_buf);
+ break;
+ case HostCmd_CMD_CHAN_REGION_CFG:
+ cmd_ptr->command = wlan_cpu_to_le16(cmd_no);
+ cmd_ptr->size = wlan_cpu_to_le16(
+ sizeof(HostCmd_DS_CHAN_REGION_CFG) + S_DS_GEN);
+ cmd_ptr->params.reg_cfg.action = wlan_cpu_to_le16(cmd_action);
+ break;
+ case HostCmd_CMD_AUTO_TX:
+ ret = wlan_cmd_auto_tx(pmpriv, cmd_ptr, cmd_action, cmd_oid,
+ pdata_buf);
+ break;
+ case HOST_CMD_TX_RX_PKT_STATS:
+ ret = wlan_cmd_tx_rx_pkt_stats(pmpriv, cmd_ptr,
+ (pmlan_ioctl_req)pioctl_buf,
+ pdata_buf);
+ break;
+ case HostCmd_CMD_DYN_BW:
+ ret = wlan_cmd_config_dyn_bw(pmpriv, cmd_ptr, cmd_action,
+ pdata_buf);
+ break;
+ case HostCmd_CMD_BOOT_SLEEP:
+ ret = wlan_cmd_boot_sleep(pmpriv, cmd_ptr, cmd_action,
+ pdata_buf);
+ break;
+ case HostCmd_CMD_FW_DUMP_EVENT:
+ ret = wlan_cmd_fw_dump_event(pmpriv, cmd_ptr, cmd_action,
+ pdata_buf);
+ break;
+#if defined(DRV_EMBEDDED_SUPPLICANT)
+ case HostCmd_CMD_CRYPTO:
+ ret = wlan_cmd_crypto(pmpriv, cmd_ptr, cmd_action, pdata_buf);
+ break;
+#endif
+ case HostCmd_CMD_11AX_CFG:
+ ret = wlan_cmd_11ax_cfg(pmpriv, cmd_ptr, cmd_action, pdata_buf);
+ break;
+ case HostCmd_CMD_11AX_CMD:
+ ret = wlan_cmd_11ax_cmd(pmpriv, cmd_ptr, cmd_action, pdata_buf);
+ break;
+ case HostCmd_CMD_RANGE_EXT:
+ ret = wlan_cmd_range_ext(pmpriv, cmd_ptr, cmd_action,
+ pdata_buf);
+ break;
+ case HostCmd_CMD_TWT_CFG:
+ ret = wlan_cmd_twt_cfg(pmpriv, cmd_ptr, cmd_action, pdata_buf);
+ break;
+ case HostCmd_CMD_RX_ABORT_CFG:
+ ret = wlan_cmd_rxabortcfg(pmpriv, cmd_ptr, cmd_action,
+ pdata_buf);
+ break;
+ case HostCmd_CMD_RX_ABORT_CFG_EXT:
+ ret = wlan_cmd_rxabortcfg_ext(pmpriv, cmd_ptr, cmd_action,
+ pdata_buf);
+ break;
+ case HostCmd_CMD_ARB_CONFIG:
+ ret = wlan_cmd_arb_cfg(pmpriv, cmd_ptr, cmd_action, pdata_buf);
+ break;
+ case HostCmd_CMD_TX_AMPDU_PROT_MODE:
+ ret = wlan_cmd_tx_ampdu_prot_mode(pmpriv, cmd_ptr, cmd_action,
+ pdata_buf);
+ break;
+ case HostCmd_CMD_DOT11MC_UNASSOC_FTM_CFG:
+ ret = wlan_cmd_dot11mc_unassoc_ftm_cfg(pmpriv, cmd_ptr,
+ cmd_action, pdata_buf);
+ break;
+ case HostCmd_CMD_RATE_ADAPT_CFG:
+ ret = wlan_cmd_rate_adapt_cfg(pmpriv, cmd_ptr, cmd_action,
+ pdata_buf);
+ break;
+ case HostCmd_CMD_CCK_DESENSE_CFG:
+ ret = wlan_cmd_cck_desense_cfg(pmpriv, cmd_ptr, cmd_action,
+ pdata_buf);
+ break;
+ case HostCmd_CHANNEL_TRPC_CONFIG:
+ ret = wlan_cmd_get_chan_trpc_config(pmpriv, cmd_ptr, cmd_action,
+ pdata_buf);
+ break;
+ case HostCmd_CMD_LOW_POWER_MODE_CFG:
+ ret = wlan_cmd_set_get_low_power_mode_cfg(
+ pmpriv, cmd_ptr, cmd_action, pdata_buf);
+ break;
+ case HostCmd_CMD_MFG_COMMAND:
+ ret = wlan_cmd_mfg(pmpriv, cmd_ptr, cmd_action, pdata_buf);
+ break;
+ default:
+ PRINTM(MERROR, "PREP_CMD: unknown command- %#x\n", cmd_no);
+ ret = MLAN_STATUS_FAILURE;
+ break;
+ }
+
+ LEAVE();
+ return ret;
+}
+
+/**
+ * @brief This function issues commands to initialize firmware
+ *
+ * @param priv A pointer to mlan_private structure
+ * @param first_bss flag for first BSS
+ *
+ * @return MLAN_STATUS_PENDING or MLAN_STATUS_FAILURE
+ */
+mlan_status wlan_ops_sta_init_cmd(t_void *priv, t_u8 first_bss)
+{
+ pmlan_private pmpriv = (pmlan_private)priv;
+ mlan_status ret = MLAN_STATUS_SUCCESS;
+ mlan_ds_11n_amsdu_aggr_ctrl amsdu_aggr_ctrl;
+
+ ENTER();
+
+ if (!pmpriv) {
+ LEAVE();
+ return MLAN_STATUS_FAILURE;
+ }
+
+ if (first_bss == MTRUE) {
+ ret = wlan_adapter_init_cmd(pmpriv->adapter);
+ if (ret == MLAN_STATUS_FAILURE)
+ goto done;
+ }
+
+ /* get tx rate */
+ ret = wlan_prepare_cmd(pmpriv, HostCmd_CMD_TX_RATE_CFG,
+ HostCmd_ACT_GEN_GET, 0, MNULL, MNULL);
+ if (ret) {
+ ret = MLAN_STATUS_FAILURE;
+ goto done;
+ }
+ pmpriv->data_rate = 0;
+
+ /* get tx power */
+ ret = wlan_prepare_cmd(pmpriv, HostCmd_CMD_802_11_RF_TX_POWER,
+ HostCmd_ACT_GEN_GET, 0, MNULL, MNULL);
+ if (ret) {
+ ret = MLAN_STATUS_FAILURE;
+ goto done;
+ }
+
+ memset(pmpriv->adapter, &amsdu_aggr_ctrl, 0, sizeof(amsdu_aggr_ctrl));
+ amsdu_aggr_ctrl.enable = MLAN_ACT_ENABLE;
+ /* Send request to firmware */
+ ret = wlan_prepare_cmd(pmpriv, HostCmd_CMD_AMSDU_AGGR_CTRL,
+ HostCmd_ACT_GEN_SET, 0, MNULL,
+ (t_void *)&amsdu_aggr_ctrl);
+ if (ret) {
+ ret = MLAN_STATUS_FAILURE;
+ goto done;
+ }
+ /* MAC Control must be the last command in init_fw */
+ /* set MAC Control */
+ ret = wlan_prepare_cmd(pmpriv, HostCmd_CMD_MAC_CONTROL,
+ HostCmd_ACT_GEN_SET, 0, MNULL,
+ &pmpriv->curr_pkt_filter);
+ if (ret) {
+ ret = MLAN_STATUS_FAILURE;
+ goto done;
+ }
+ /** set last_init_cmd */
+ pmpriv->adapter->last_init_cmd = HostCmd_CMD_MAC_CONTROL;
+
+ if (first_bss == MFALSE) {
+ /* Get MAC address */
+ ret = wlan_prepare_cmd(pmpriv, HostCmd_CMD_802_11_MAC_ADDRESS,
+ HostCmd_ACT_GEN_GET, 0, MNULL, MNULL);
+ if (ret) {
+ ret = MLAN_STATUS_FAILURE;
+ goto done;
+ }
+ pmpriv->adapter->last_init_cmd = HostCmd_CMD_802_11_MAC_ADDRESS;
+ }
+
+ ret = MLAN_STATUS_PENDING;
+done:
+ LEAVE();
+ return ret;
+}
diff --git a/drivers/net/wireless/nxp/mxm_wifiex/wlan_src/mlan/mlan_sta_cmdresp.c b/drivers/net/wireless/nxp/mxm_wifiex/wlan_src/mlan/mlan_sta_cmdresp.c
new file mode 100644
index 000000000000..a7fee3788925
--- /dev/null
+++ b/drivers/net/wireless/nxp/mxm_wifiex/wlan_src/mlan/mlan_sta_cmdresp.c
@@ -0,0 +1,2749 @@
+/** @file mlan_sta_cmdresp.c
+ *
+ * @brief This file contains the handling of command
+ * responses generated by firmware.
+ *
+ *
+ * Copyright 2014-2020 NXP
+ *
+ * This software file (the File) is distributed by NXP
+ * under the terms of the GNU General Public License Version 2, June 1991
+ * (the License). You may use, redistribute and/or modify the 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.
+ *
+ */
+
+/******************************************************
+ * Change log:
+ * 10/21/2008: initial version
+ ******************************************************/
+
+#include "mlan.h"
+#include "mlan_join.h"
+#include "mlan_util.h"
+#include "mlan_fw.h"
+#include "mlan_main.h"
+#include "mlan_wmm.h"
+#include "mlan_11n.h"
+#include "mlan_11ac.h"
+#include "mlan_11ax.h"
+#include "mlan_11h.h"
+#include "mlan_meas.h"
+
+/********************************************************
+ * Local Variables
+ ********************************************************/
+
+/********************************************************
+ * Global Variables
+ ********************************************************/
+
+/********************************************************
+ * Local Functions
+ ********************************************************/
+
+/**
+ * @brief This function handles the command response error
+ *
+ * @param pmpriv A pointer to mlan_private structure
+ * @param resp A pointer to HostCmd_DS_COMMAND
+ * @param pioctl_buf A pointer to command buffer
+ *
+ * @return N/A
+ */
+static mlan_status wlan_process_cmdresp_error(mlan_private *pmpriv,
+ HostCmd_DS_COMMAND *resp,
+ mlan_ioctl_req *pioctl_buf)
+{
+ mlan_adapter *pmadapter = pmpriv->adapter;
+ pmlan_ioctl_req pscan_ioctl_req = MNULL;
+ mlan_callbacks *pcb = MNULL;
+#if defined(USB)
+ t_s32 i = 0;
+#endif
+ mlan_status ret = MLAN_STATUS_FAILURE;
+
+ ENTER();
+ if (resp->command != HostCmd_CMD_WMM_PARAM_CONFIG &&
+ resp->command != HostCmd_CMD_CHAN_REGION_CFG)
+ PRINTM(MERROR, "CMD_RESP: cmd %#x error, result=%#x\n",
+ resp->command, resp->result);
+ if (pioctl_buf)
+ pioctl_buf->status_code = MLAN_ERROR_FW_CMDRESP;
+
+ switch (resp->command) {
+ case HostCmd_CMD_802_11_PS_MODE_ENH: {
+ HostCmd_DS_802_11_PS_MODE_ENH *pm = &resp->params.psmode_enh;
+ PRINTM(MERROR,
+ "PS_MODE_ENH command failed: result=0x%x action=0x%X\n",
+ resp->result, wlan_le16_to_cpu(pm->action));
+ /*
+ * We do not re-try enter-ps command in ad-hoc mode.
+ */
+ if (wlan_le16_to_cpu(pm->action) == EN_AUTO_PS &&
+ (wlan_le16_to_cpu(pm->params.auto_ps.ps_bitmap) &
+ BITMAP_STA_PS) &&
+ pmpriv->bss_mode == MLAN_BSS_MODE_IBSS)
+ pmadapter->ps_mode = Wlan802_11PowerModeCAM;
+ } break;
+ case HostCmd_CMD_802_11_SCAN_EXT:
+ case HostCmd_CMD_802_11_SCAN:
+ /* Cancel all pending scan command */
+ wlan_flush_scan_queue(pmadapter);
+
+ pcb = (pmlan_callbacks)&pmadapter->callbacks;
+
+ wlan_request_cmd_lock(pmadapter);
+ pmadapter->scan_processing = MFALSE;
+ pscan_ioctl_req = pmadapter->pscan_ioctl_req;
+ pmadapter->pscan_ioctl_req = MNULL;
+ /* Need to indicate IOCTL complete */
+ if (pscan_ioctl_req) {
+ pscan_ioctl_req->status_code = MLAN_ERROR_CMD_SCAN_FAIL;
+ /* Indicate ioctl complete */
+ pcb->moal_ioctl_complete(
+ pmadapter->pmoal_handle,
+ (pmlan_ioctl_req)pscan_ioctl_req,
+ MLAN_STATUS_FAILURE);
+ }
+ wlan_release_cmd_lock(pmadapter);
+ wlan_recv_event(pmpriv, MLAN_EVENT_ID_DRV_SCAN_REPORT, MNULL);
+ break;
+
+ case HostCmd_CMD_MAC_CONTROL:
+ break;
+
+ case HostCmd_CMD_PACKET_AGGR_CTRL:
+#ifdef USB
+ if (IS_USB(pmadapter->card_type)) {
+ for (i = 0; i < MAX_USB_TX_PORT_NUM; i++)
+ pmadapter->pcard_usb->usb_tx_aggr[i]
+ .aggr_ctrl.enable = MFALSE;
+ pmadapter->pcard_usb->usb_rx_deaggr.aggr_ctrl.enable =
+ MFALSE;
+ }
+#endif
+ break;
+#ifdef USB
+ case HostCmd_CMD_PACKET_AGGR_OVER_HOST_INTERFACE:
+ pmadapter->pcard_usb->fw_usb_aggr = MFALSE;
+ for (i = 0; i < MAX_USB_TX_PORT_NUM; i++)
+ pmadapter->pcard_usb->usb_tx_aggr[i].aggr_ctrl.enable =
+ MFALSE;
+ pmadapter->pcard_usb->usb_rx_deaggr.aggr_ctrl.enable = MFALSE;
+ break;
+#endif
+ case HostCmd_CMD_802_11_ASSOCIATE:
+ wlan_reset_connect_state(pmpriv, MTRUE);
+ break;
+#ifdef SDIO
+ case HostCmd_CMD_SDIO_SP_RX_AGGR_CFG:
+ pmadapter->pcard_sd->sdio_rx_aggr_enable = MFALSE;
+ PRINTM(MMSG, "FW don't support SDIO single port rx aggr\n");
+ break;
+#endif
+
+ case HostCmd_CMD_MGMT_IE_LIST: {
+ HostCmd_DS_MGMT_IE_LIST_CFG *pmgmt_ie_list =
+ &(resp->params.mgmt_ie_list);
+ t_u16 resp_len = 0, travel_len = 0, index;
+ mlan_ds_misc_custom_ie *cust_ie = MNULL;
+ custom_ie *cptr;
+
+ if (wlan_le16_to_cpu(pmgmt_ie_list->action) ==
+ HostCmd_ACT_GEN_GET)
+ break;
+
+ cust_ie = (mlan_ds_misc_custom_ie *)&pmgmt_ie_list->ds_mgmt_ie;
+ if (cust_ie) {
+ cust_ie->type = wlan_le16_to_cpu(cust_ie->type);
+ resp_len = cust_ie->len =
+ wlan_le16_to_cpu(cust_ie->len);
+ travel_len = 0;
+ /* conversion for index, mask, len */
+ if (resp_len == sizeof(t_u16))
+ cust_ie->ie_data_list[0]
+ .ie_index = wlan_cpu_to_le16(
+ cust_ie->ie_data_list[0].ie_index);
+
+ while (resp_len > sizeof(t_u16)) {
+ cptr = (custom_ie *)(((t_u8 *)cust_ie
+ ->ie_data_list) +
+ travel_len);
+ index = cptr->ie_index =
+ wlan_le16_to_cpu(cptr->ie_index);
+ cptr->mgmt_subtype_mask = wlan_le16_to_cpu(
+ cptr->mgmt_subtype_mask);
+ cptr->ie_length =
+ wlan_le16_to_cpu(cptr->ie_length);
+ travel_len += cptr->ie_length +
+ sizeof(custom_ie) - MAX_IE_SIZE;
+ resp_len -= cptr->ie_length +
+ sizeof(custom_ie) - MAX_IE_SIZE;
+ if ((pmpriv->mgmt_ie[index].mgmt_subtype_mask ==
+ cptr->mgmt_subtype_mask) &&
+ (pmpriv->mgmt_ie[index].ie_length ==
+ cptr->ie_length) &&
+ !memcmp(pmpriv->adapter,
+ pmpriv->mgmt_ie[index].ie_buffer,
+ cptr->ie_buffer, cptr->ie_length)) {
+ PRINTM(MERROR,
+ "set custom ie fail, remove ie index :%d\n",
+ index);
+ memset(pmadapter,
+ &pmpriv->mgmt_ie[index], 0,
+ sizeof(custom_ie));
+ }
+ }
+ }
+ } break;
+ case HostCmd_CMD_CHAN_REGION_CFG:
+ ret = MLAN_STATUS_SUCCESS;
+ PRINTM(MCMND, "FW don't support chan region cfg command!\n");
+ break;
+#if defined(DRV_EMBEDDED_SUPPLICANT)
+ case HostCmd_CMD_CRYPTO:
+ PRINTM(MCMND, "crypto cmd result=0x%x!\n", resp->result);
+ ret = wlan_ret_crypto(pmpriv, resp, pioctl_buf);
+ break;
+#endif
+ default:
+ break;
+ }
+ /*
+ * Handling errors here
+ */
+ wlan_request_cmd_lock(pmadapter);
+ wlan_insert_cmd_to_free_q(pmadapter, pmadapter->curr_cmd);
+ pmadapter->curr_cmd = MNULL;
+ wlan_release_cmd_lock(pmadapter);
+
+ LEAVE();
+ return ret;
+}
+
+/**
+ * @brief This function handles the command response of RSSI info
+ *
+ * @param pmpriv A pointer to mlan_private structure
+ * @param resp A pointer to HostCmd_DS_COMMAND
+ * @param pioctl_buf A pointer to mlan_ioctl_req structure
+ *
+ * @return MLAN_STATUS_SUCCESS
+ */
+static mlan_status wlan_ret_802_11_rssi_info_ext(pmlan_private pmpriv,
+ HostCmd_DS_COMMAND *resp,
+ mlan_ioctl_req *pioctl_buf)
+{
+ HostCmd_DS_802_11_RSSI_INFO_EXT *prssi_info_rsp =
+ &resp->params.rssi_info_ext;
+ mlan_ds_get_signal *signal = MNULL;
+ mlan_ds_get_info *info = MNULL;
+ MrvlIEtypes_RSSI_EXT_t *signal_info_tlv = MNULL;
+ t_u16 tlv_left_len = 0, tlv_num = 0;
+ t_u16 tlv_id, tlv_len;
+
+ ENTER();
+
+ /* Need to indicate IOCTL complete */
+ if (pioctl_buf != MNULL) {
+ info = (mlan_ds_get_info *)pioctl_buf->pbuf;
+ signal_info_tlv =
+ (MrvlIEtypes_RSSI_EXT_t *)(prssi_info_rsp->tlv_buf);
+ tlv_left_len =
+ resp->size -
+ (sizeof(HostCmd_DS_802_11_RSSI_INFO_EXT) + S_DS_GEN);
+
+ while (tlv_left_len >= sizeof(MrvlIEtypes_RSSI_EXT_t)) {
+ tlv_id = wlan_le16_to_cpu(signal_info_tlv->header.type);
+ tlv_len = wlan_le16_to_cpu(signal_info_tlv->header.len);
+ if ((tlv_id != TLV_TYPE_RSSI_INFO) ||
+ (tlv_len != sizeof(MrvlIEtypes_RSSI_EXT_t) -
+ sizeof(MrvlIEtypesHeader_t))) {
+ PRINTM(MERROR,
+ "Invalid RSSI INFO TLV, type=%d, len=%d\n",
+ tlv_id, tlv_len);
+ break;
+ }
+
+ signal = (mlan_ds_get_signal *)&info->param
+ .signal_ext[tlv_num];
+ /* PATH ID */
+ signal->selector =
+ wlan_le16_to_cpu(signal_info_tlv->path_id);
+
+ /* RSSI */
+ signal->bcn_rssi_last = wlan_le16_to_cpu(
+ signal_info_tlv->bcn_rssi_last);
+ signal->bcn_rssi_avg =
+ wlan_le16_to_cpu(signal_info_tlv->bcn_rssi_avg);
+ signal->data_rssi_last = wlan_le16_to_cpu(
+ signal_info_tlv->data_rssi_last);
+ signal->data_rssi_avg = wlan_le16_to_cpu(
+ signal_info_tlv->data_rssi_avg);
+
+ /* SNR */
+ signal->bcn_snr_last = CAL_SNR(
+ wlan_le16_to_cpu(
+ signal_info_tlv->bcn_rssi_last),
+ wlan_le16_to_cpu(signal_info_tlv->bcn_nf_last));
+ signal->bcn_snr_avg = CAL_SNR(
+ wlan_le16_to_cpu(signal_info_tlv->bcn_rssi_avg),
+ wlan_le16_to_cpu(signal_info_tlv->bcn_nf_avg));
+ signal->data_snr_last = CAL_SNR(
+ wlan_le16_to_cpu(
+ signal_info_tlv->data_rssi_last),
+ wlan_le16_to_cpu(
+ signal_info_tlv->data_nf_last));
+ signal->data_snr_avg = CAL_SNR(
+ wlan_le16_to_cpu(
+ signal_info_tlv->data_rssi_avg),
+ wlan_le16_to_cpu(signal_info_tlv->data_nf_avg));
+
+ /* NF */
+ signal->bcn_nf_last =
+ wlan_le16_to_cpu(signal_info_tlv->bcn_nf_last);
+ signal->bcn_nf_avg =
+ wlan_le16_to_cpu(signal_info_tlv->bcn_nf_avg);
+ signal->data_nf_last =
+ wlan_le16_to_cpu(signal_info_tlv->data_nf_last);
+ signal->data_nf_avg =
+ wlan_le16_to_cpu(signal_info_tlv->data_nf_avg);
+
+ tlv_left_len -= sizeof(MrvlIEtypes_RSSI_EXT_t);
+ signal_info_tlv++;
+ tlv_num++;
+ if (tlv_num > MAX_PATH_NUM)
+ break;
+ }
+
+ pioctl_buf->data_read_written =
+ tlv_num * sizeof(mlan_ds_get_signal) + sizeof(t_u32);
+ }
+
+ LEAVE();
+ return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ * @brief This function handles the command response of RSSI info
+ *
+ * @param pmpriv A pointer to mlan_private structure
+ * @param resp A pointer to HostCmd_DS_COMMAND
+ * @param pioctl_buf A pointer to mlan_ioctl_req structure
+ *
+ * @return MLAN_STATUS_SUCCESS
+ */
+static mlan_status wlan_ret_802_11_rssi_info(pmlan_private pmpriv,
+ HostCmd_DS_COMMAND *resp,
+ mlan_ioctl_req *pioctl_buf)
+{
+ HostCmd_DS_802_11_RSSI_INFO_RSP *prssi_info_rsp =
+ &resp->params.rssi_info_rsp;
+ mlan_ds_get_info *pget_info = MNULL;
+ BSSDescriptor_t *pbss_desc;
+ t_s32 tbl_idx = 0;
+
+ ENTER();
+
+ pmpriv->data_rssi_last =
+ wlan_le16_to_cpu(prssi_info_rsp->data_rssi_last);
+ pmpriv->data_nf_last = wlan_le16_to_cpu(prssi_info_rsp->data_nf_last);
+
+ pmpriv->data_rssi_avg = wlan_le16_to_cpu(prssi_info_rsp->data_rssi_avg);
+ pmpriv->data_nf_avg = wlan_le16_to_cpu(prssi_info_rsp->data_nf_avg);
+
+ pmpriv->bcn_rssi_last = wlan_le16_to_cpu(prssi_info_rsp->bcn_rssi_last);
+ pmpriv->bcn_nf_last = wlan_le16_to_cpu(prssi_info_rsp->bcn_nf_last);
+
+ pmpriv->bcn_rssi_avg = wlan_le16_to_cpu(prssi_info_rsp->bcn_rssi_avg);
+ pmpriv->bcn_nf_avg = wlan_le16_to_cpu(prssi_info_rsp->bcn_nf_avg);
+
+ /* Get current BSS info */
+ pbss_desc = &pmpriv->curr_bss_params.bss_descriptor;
+ pbss_desc->rssi = -pmpriv->bcn_rssi_avg;
+ tbl_idx = wlan_find_ssid_in_list(pmpriv, &pbss_desc->ssid,
+ pbss_desc->mac_address,
+ pmpriv->bss_mode);
+ if (tbl_idx >= 0) {
+ pbss_desc = &pmpriv->adapter->pscan_table[tbl_idx];
+ pbss_desc->rssi = -pmpriv->bcn_rssi_avg;
+ }
+
+ /* Need to indicate IOCTL complete */
+ if (pioctl_buf != MNULL) {
+ pget_info = (mlan_ds_get_info *)pioctl_buf->pbuf;
+
+ memset(pmpriv->adapter, &pget_info->param.signal, 0,
+ sizeof(mlan_ds_get_signal));
+
+ pget_info->param.signal.selector = ALL_RSSI_INFO_MASK;
+
+ /* RSSI */
+ pget_info->param.signal.bcn_rssi_last = pmpriv->bcn_rssi_last;
+ pget_info->param.signal.bcn_rssi_avg = pmpriv->bcn_rssi_avg;
+ pget_info->param.signal.data_rssi_last = pmpriv->data_rssi_last;
+ pget_info->param.signal.data_rssi_avg = pmpriv->data_rssi_avg;
+
+ /* SNR */
+ pget_info->param.signal.bcn_snr_last =
+ CAL_SNR(pmpriv->bcn_rssi_last, pmpriv->bcn_nf_last);
+ pget_info->param.signal.bcn_snr_avg =
+ CAL_SNR(pmpriv->bcn_rssi_avg, pmpriv->bcn_nf_avg);
+ pget_info->param.signal.data_snr_last =
+ CAL_SNR(pmpriv->data_rssi_last, pmpriv->data_nf_last);
+ pget_info->param.signal.data_snr_avg =
+ CAL_SNR(pmpriv->data_rssi_avg, pmpriv->data_nf_avg);
+
+ /* NF */
+ pget_info->param.signal.bcn_nf_last = pmpriv->bcn_nf_last;
+ pget_info->param.signal.bcn_nf_avg = pmpriv->bcn_nf_avg;
+ pget_info->param.signal.data_nf_last = pmpriv->data_nf_last;
+ pget_info->param.signal.data_nf_avg = pmpriv->data_nf_avg;
+
+ pioctl_buf->data_read_written = sizeof(mlan_ds_get_info);
+ }
+
+ LEAVE();
+ return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ * @brief This function handles the command response of snmp_mib
+ *
+ * @param pmpriv A pointer to mlan_private structure
+ * @param resp A pointer to HostCmd_DS_COMMAND
+ * @param pioctl_buf A pointer to mlan_ioctl_req structure
+ *
+ * @return MLAN_STATUS_SUCCESS
+ */
+static mlan_status wlan_ret_802_11_snmp_mib(pmlan_private pmpriv,
+ HostCmd_DS_COMMAND *resp,
+ mlan_ioctl_req *pioctl_buf)
+{
+ HostCmd_DS_802_11_SNMP_MIB *psmib = &resp->params.smib;
+ t_u16 oid = wlan_le16_to_cpu(psmib->oid);
+ t_u16 query_type = wlan_le16_to_cpu(psmib->query_type);
+ t_u32 ul_temp;
+ mlan_ds_snmp_mib *mib = MNULL;
+
+ ENTER();
+
+ if (pioctl_buf)
+ mib = (mlan_ds_snmp_mib *)pioctl_buf->pbuf;
+
+ PRINTM(MINFO, "SNMP_RESP: value of the oid = 0x%x, query_type=0x%x\n",
+ oid, query_type);
+ PRINTM(MINFO, "SNMP_RESP: Buf size = 0x%x\n",
+ wlan_le16_to_cpu(psmib->buf_size));
+ if (query_type == HostCmd_ACT_GEN_GET) {
+ switch (oid) {
+ case DtimPeriod_i:
+ ul_temp = psmib->value[0];
+ PRINTM(MINFO, "SNMP_RESP: DTIM Period =%u\n", ul_temp);
+ if (mib)
+ mib->param.dtim_period = ul_temp;
+ break;
+ case FragThresh_i:
+ ul_temp = wlan_le16_to_cpu(*((t_u16 *)(psmib->value)));
+ PRINTM(MINFO, "SNMP_RESP: FragThsd =%u\n", ul_temp);
+ if (mib)
+ mib->param.frag_threshold = ul_temp;
+ break;
+
+ case RtsThresh_i:
+ ul_temp = wlan_le16_to_cpu(*((t_u16 *)(psmib->value)));
+ PRINTM(MINFO, "SNMP_RESP: RTSThsd =%u\n", ul_temp);
+ if (mib)
+ mib->param.rts_threshold = ul_temp;
+ break;
+
+ case ShortRetryLim_i:
+ ul_temp = wlan_le16_to_cpu(*((t_u16 *)(psmib->value)));
+ PRINTM(MINFO, "SNMP_RESP: TxRetryCount=%u\n", ul_temp);
+ if (mib)
+ mib->param.retry_count = ul_temp;
+ break;
+ case WwsMode_i:
+ ul_temp = wlan_le16_to_cpu(*((t_u16 *)(psmib->value)));
+ PRINTM(MINFO, "SNMP_RESP: WWSCfg =%u\n", ul_temp);
+ if (pioctl_buf)
+ ((mlan_ds_misc_cfg *)pioctl_buf->pbuf)
+ ->param.wws_cfg = ul_temp;
+ break;
+ case Thermal_i:
+ ul_temp = wlan_le32_to_cpu(*((t_u32 *)(psmib->value)));
+ PRINTM(MINFO, "SNMP_RESP: Thermal =%u\n", ul_temp);
+ if (pioctl_buf)
+ ((mlan_ds_misc_cfg *)pioctl_buf->pbuf)
+ ->param.thermal = ul_temp;
+ break;
+ case NullPktPeriod_i:
+ ul_temp = psmib->value[0];
+ PRINTM(MINFO, "SNMP_RESP: Auto NULL Pkt Period =%u\n",
+ ul_temp);
+ break;
+ default:
+ break;
+ }
+ } else { /* (query_type == HostCmd_ACT_GEN_SET) */
+ /* Update state for 11d */
+ if (oid == Dot11D_i) {
+ ul_temp = wlan_le16_to_cpu(*((t_u16 *)(psmib->value)));
+ /* Set 11d state to private */
+ pmpriv->state_11d.enable_11d = ul_temp;
+ /* Set user enable flag if called from ioctl */
+ if (pioctl_buf)
+ pmpriv->state_11d.user_enable_11d = ul_temp;
+ }
+ /* Update state for 11h */
+ if (oid == Dot11H_i) {
+ ul_temp = wlan_le16_to_cpu(*((t_u16 *)(psmib->value)));
+ /* Set 11h state to priv */
+ pmpriv->intf_state_11h.is_11h_active =
+ (ul_temp & ENABLE_11H_MASK);
+ /* Set radar_det state to adapter */
+ pmpriv->adapter->state_11h.is_master_radar_det_active =
+ (ul_temp & MASTER_RADAR_DET_MASK) ? MTRUE :
+ MFALSE;
+ pmpriv->adapter->state_11h.is_slave_radar_det_active =
+ (ul_temp & SLAVE_RADAR_DET_MASK) ? MTRUE :
+ MFALSE;
+ }
+ }
+
+ if (pioctl_buf) {
+ /* Indicate ioctl complete */
+ pioctl_buf->data_read_written = sizeof(mlan_ds_snmp_mib);
+ }
+
+ LEAVE();
+ return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ * @brief This function handles the command response of get_log
+ *
+ * @param pmpriv A pointer to mlan_private structure
+ * @param resp A pointer to HostCmd_DS_COMMAND
+ * @param pioctl_buf A pointer to mlan_ioctl_req structure
+ *
+ * @return MLAN_STATUS_SUCCESS
+ */
+static mlan_status wlan_ret_get_log(pmlan_private pmpriv,
+ HostCmd_DS_COMMAND *resp,
+ mlan_ioctl_req *pioctl_buf)
+{
+ HostCmd_DS_802_11_GET_LOG *pget_log =
+ (HostCmd_DS_802_11_GET_LOG *)&resp->params.get_log;
+ mlan_ds_get_info *pget_info = MNULL;
+ int i = 0;
+
+ ENTER();
+
+ if (pioctl_buf) {
+ pget_info = (mlan_ds_get_info *)pioctl_buf->pbuf;
+ pget_info->param.stats.mcast_tx_frame =
+ wlan_le32_to_cpu(pget_log->mcast_tx_frame);
+ pget_info->param.stats.failed =
+ wlan_le32_to_cpu(pget_log->failed);
+ pget_info->param.stats.retry =
+ wlan_le32_to_cpu(pget_log->retry);
+ pget_info->param.stats.multi_retry =
+ wlan_le32_to_cpu(pget_log->multiretry);
+ pget_info->param.stats.frame_dup =
+ wlan_le32_to_cpu(pget_log->frame_dup);
+ pget_info->param.stats.rts_success =
+ wlan_le32_to_cpu(pget_log->rts_success);
+ pget_info->param.stats.rts_failure =
+ wlan_le32_to_cpu(pget_log->rts_failure);
+ pget_info->param.stats.ack_failure =
+ wlan_le32_to_cpu(pget_log->ack_failure);
+ pget_info->param.stats.rx_frag =
+ wlan_le32_to_cpu(pget_log->rx_frag);
+ pget_info->param.stats.mcast_rx_frame =
+ wlan_le32_to_cpu(pget_log->mcast_rx_frame);
+ pget_info->param.stats.fcs_error =
+ wlan_le32_to_cpu(pget_log->fcs_error);
+ pget_info->param.stats.tx_frame =
+ wlan_le32_to_cpu(pget_log->tx_frame);
+ pget_info->param.stats.wep_icv_error[0] =
+ wlan_le32_to_cpu(pget_log->wep_icv_err_cnt[0]);
+ pget_info->param.stats.wep_icv_error[1] =
+ wlan_le32_to_cpu(pget_log->wep_icv_err_cnt[1]);
+ pget_info->param.stats.wep_icv_error[2] =
+ wlan_le32_to_cpu(pget_log->wep_icv_err_cnt[2]);
+ pget_info->param.stats.wep_icv_error[3] =
+ wlan_le32_to_cpu(pget_log->wep_icv_err_cnt[3]);
+ pget_info->param.stats.bcn_rcv_cnt =
+ wlan_le32_to_cpu(pget_log->bcn_rcv_cnt);
+ pget_info->param.stats.bcn_miss_cnt =
+ wlan_le32_to_cpu(pget_log->bcn_miss_cnt);
+ pget_info->param.stats.amsdu_rx_cnt = pmpriv->amsdu_rx_cnt;
+ pget_info->param.stats.msdu_in_rx_amsdu_cnt =
+ pmpriv->msdu_in_rx_amsdu_cnt;
+ pget_info->param.stats.amsdu_tx_cnt = pmpriv->amsdu_tx_cnt;
+ pget_info->param.stats.msdu_in_tx_amsdu_cnt =
+ pmpriv->msdu_in_tx_amsdu_cnt;
+ pget_info->param.stats.rx_stuck_issue_cnt[0] =
+ wlan_le32_to_cpu(pget_log->rx_stuck_issue_cnt[0]);
+ pget_info->param.stats.rx_stuck_issue_cnt[1] =
+ wlan_le32_to_cpu(pget_log->rx_stuck_issue_cnt[1]);
+ pget_info->param.stats.rx_stuck_recovery_cnt =
+ wlan_le32_to_cpu(pget_log->rx_stuck_recovery_cnt);
+ pget_info->param.stats.rx_stuck_tsf[0] =
+ wlan_le64_to_cpu(pget_log->rx_stuck_tsf[0]);
+ pget_info->param.stats.rx_stuck_tsf[1] =
+ wlan_le64_to_cpu(pget_log->rx_stuck_tsf[1]);
+ pget_info->param.stats.tx_watchdog_recovery_cnt =
+ wlan_le32_to_cpu(pget_log->tx_watchdog_recovery_cnt);
+ pget_info->param.stats.tx_watchdog_tsf[0] =
+ wlan_le64_to_cpu(pget_log->tx_watchdog_tsf[0]);
+ pget_info->param.stats.tx_watchdog_tsf[1] =
+ wlan_le64_to_cpu(pget_log->tx_watchdog_tsf[1]);
+ pget_info->param.stats.channel_switch_ann_sent =
+ wlan_le32_to_cpu(pget_log->channel_switch_ann_sent);
+ pget_info->param.stats.channel_switch_state =
+ wlan_le32_to_cpu(pget_log->channel_switch_state);
+ pget_info->param.stats.reg_class =
+ wlan_le32_to_cpu(pget_log->reg_class);
+ pget_info->param.stats.channel_number =
+ wlan_le32_to_cpu(pget_log->channel_number);
+ pget_info->param.stats.channel_switch_mode =
+ wlan_le32_to_cpu(pget_log->channel_switch_mode);
+ if (pmpriv->adapter->getlog_enable) {
+ pget_info->param.stats.tx_frag_cnt =
+ wlan_le32_to_cpu(pget_log->tx_frag_cnt);
+ for (i = 0; i < 8; i++) {
+ pget_info->param.stats.qos_tx_frag_cnt[i] =
+ wlan_le32_to_cpu(
+ pget_log->qos_tx_frag_cnt[i]);
+ pget_info->param.stats.qos_failed_cnt[i] =
+ wlan_le32_to_cpu(
+ pget_log->qos_failed_cnt[i]);
+ pget_info->param.stats.qos_retry_cnt[i] =
+ wlan_le32_to_cpu(
+ pget_log->qos_retry_cnt[i]);
+ pget_info->param.stats.qos_multi_retry_cnt[i] =
+ wlan_le32_to_cpu(
+ pget_log->qos_multi_retry_cnt[i]);
+ pget_info->param.stats.qos_frm_dup_cnt[i] =
+ wlan_le32_to_cpu(
+ pget_log->qos_frm_dup_cnt[i]);
+ pget_info->param.stats.qos_rts_suc_cnt[i] =
+ wlan_le32_to_cpu(
+ pget_log->qos_rts_suc_cnt[i]);
+ pget_info->param.stats.qos_rts_failure_cnt[i] =
+ wlan_le32_to_cpu(
+ pget_log->qos_rts_failure_cnt[i]);
+ pget_info->param.stats.qos_ack_failure_cnt[i] =
+ wlan_le32_to_cpu(
+ pget_log->qos_ack_failure_cnt[i]);
+ pget_info->param.stats.qos_rx_frag_cnt[i] =
+ wlan_le32_to_cpu(
+ pget_log->qos_rx_frag_cnt[i]);
+ pget_info->param.stats.qos_tx_frm_cnt[i] =
+ wlan_le32_to_cpu(
+ pget_log->qos_tx_frm_cnt[i]);
+ pget_info->param.stats.qos_discarded_frm_cnt
+ [i] = wlan_le32_to_cpu(
+ pget_log->qos_discarded_frm_cnt[i]);
+ pget_info->param.stats.qos_mpdus_rx_cnt[i] =
+ wlan_le32_to_cpu(
+ pget_log->qos_mpdus_rx_cnt[i]);
+ pget_info->param.stats.qos_retries_rx_cnt[i] =
+ wlan_le32_to_cpu(
+ pget_log->qos_retries_rx_cnt[i]);
+ }
+ pget_info->param.stats.cmacicv_errors =
+ wlan_le32_to_cpu(pget_log->cmacicv_errors);
+ pget_info->param.stats.cmac_replays =
+ wlan_le32_to_cpu(pget_log->cmac_replays);
+ pget_info->param.stats.mgmt_ccmp_replays =
+ wlan_le32_to_cpu(pget_log->mgmt_ccmp_replays);
+ pget_info->param.stats.tkipicv_errors =
+ wlan_le32_to_cpu(pget_log->tkipicv_errors);
+ pget_info->param.stats.tkip_replays =
+ wlan_le32_to_cpu(pget_log->tkip_replays);
+ pget_info->param.stats.ccmp_decrypt_errors =
+ wlan_le32_to_cpu(pget_log->ccmp_decrypt_errors);
+ pget_info->param.stats.ccmp_replays =
+ wlan_le32_to_cpu(pget_log->ccmp_replays);
+ pget_info->param.stats.tx_amsdu_cnt =
+ wlan_le32_to_cpu(pget_log->tx_amsdu_cnt);
+ pget_info->param.stats.failed_amsdu_cnt =
+ wlan_le32_to_cpu(pget_log->failed_amsdu_cnt);
+ pget_info->param.stats.retry_amsdu_cnt =
+ wlan_le32_to_cpu(pget_log->retry_amsdu_cnt);
+ pget_info->param.stats.multi_retry_amsdu_cnt =
+ wlan_le32_to_cpu(
+ pget_log->multi_retry_amsdu_cnt);
+ pget_info->param.stats.tx_octets_in_amsdu_cnt =
+ wlan_le64_to_cpu(
+ pget_log->tx_octets_in_amsdu_cnt);
+ pget_info->param.stats.amsdu_ack_failure_cnt =
+ wlan_le32_to_cpu(
+ pget_log->amsdu_ack_failure_cnt);
+ pget_info->param.stats.rx_amsdu_cnt =
+ wlan_le32_to_cpu(pget_log->rx_amsdu_cnt);
+ pget_info->param.stats.rx_octets_in_amsdu_cnt =
+ wlan_le64_to_cpu(
+ pget_log->rx_octets_in_amsdu_cnt);
+ pget_info->param.stats.tx_ampdu_cnt =
+ wlan_le32_to_cpu(pget_log->tx_ampdu_cnt);
+ pget_info->param.stats.tx_mpdus_in_ampdu_cnt =
+ wlan_le32_to_cpu(
+ pget_log->tx_mpdus_in_ampdu_cnt);
+ pget_info->param.stats.tx_octets_in_ampdu_cnt =
+ wlan_le64_to_cpu(
+ pget_log->tx_octets_in_ampdu_cnt);
+ pget_info->param.stats.ampdu_rx_cnt =
+ wlan_le32_to_cpu(pget_log->ampdu_rx_cnt);
+ pget_info->param.stats.mpdu_in_rx_ampdu_cnt =
+ wlan_le32_to_cpu(
+ pget_log->mpdu_in_rx_ampdu_cnt);
+ pget_info->param.stats.rx_octets_in_ampdu_cnt =
+ wlan_le64_to_cpu(
+ pget_log->rx_octets_in_ampdu_cnt);
+ pget_info->param.stats.ampdu_delimiter_crc_error_cnt =
+ wlan_le32_to_cpu(
+ pget_log->ampdu_delimiter_crc_error_cnt);
+
+ /* Indicate ioctl complete */
+ pioctl_buf->data_read_written =
+ sizeof(mlan_ds_get_info);
+ } else
+ pioctl_buf->data_read_written =
+ sizeof(mlan_ds_get_stats_org) +
+ sizeof(pget_info->sub_command);
+ }
+ LEAVE();
+ return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ * @brief Get power level and rate index
+ *
+ * @param pmpriv A pointer to mlan_private structure
+ * @param pdata_buf Pointer to the data buffer
+ *
+ * @return MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ */
+static mlan_status wlan_get_power_level(pmlan_private pmpriv, void *pdata_buf)
+{
+ t_u16 length = 0;
+ t_s8 max_power = -1, min_power = -1;
+ MrvlTypes_Power_Group_t *ppg_tlv = MNULL;
+ Power_Group_t *pg = MNULL;
+
+ ENTER();
+
+ if (pdata_buf) {
+ ppg_tlv = (MrvlTypes_Power_Group_t
+ *)((t_u8 *)pdata_buf +
+ sizeof(HostCmd_DS_TXPWR_CFG));
+ pg = (Power_Group_t *)((t_u8 *)ppg_tlv +
+ sizeof(MrvlTypes_Power_Group_t));
+ length = ppg_tlv->length;
+ if (length > 0) {
+ max_power = pg->power_max;
+ min_power = pg->power_min;
+ length -= sizeof(Power_Group_t);
+ }
+ while (length) {
+ 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(Power_Group_t);
+ }
+ if (ppg_tlv->length > 0) {
+ pmpriv->min_tx_power_level = min_power;
+ pmpriv->max_tx_power_level = max_power;
+ }
+ } else {
+ LEAVE();
+ return MLAN_STATUS_FAILURE;
+ }
+
+ LEAVE();
+ return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ * @brief This function handles the command response of tx_power_cfg
+ *
+ * @param pmpriv A pointer to mlan_private structure
+ * @param resp A pointer to HostCmd_DS_COMMAND
+ * @param pioctl_buf A pointer to mlan_ioctl_req structure
+ *
+ * @return MLAN_STATUS_SUCCESS
+ */
+static mlan_status wlan_ret_tx_power_cfg(pmlan_private pmpriv,
+ HostCmd_DS_COMMAND *resp,
+ mlan_ioctl_req *pioctl_buf)
+{
+ HostCmd_DS_TXPWR_CFG *ptxp_cfg = &resp->params.txp_cfg;
+ MrvlTypes_Power_Group_t *ppg_tlv = MNULL;
+ Power_Group_t *pg = MNULL;
+ t_u16 action = wlan_le16_to_cpu(ptxp_cfg->action);
+ mlan_ds_power_cfg *power = MNULL;
+ mlan_power_group *pwr_grp = MNULL;
+ t_u8 i = 0;
+
+ ENTER();
+
+ ppg_tlv = (MrvlTypes_Power_Group_t *)(ptxp_cfg->tlv_buf);
+ pg = (Power_Group_t *)((t_u8 *)ppg_tlv +
+ sizeof(MrvlTypes_Power_Group_t));
+
+ switch (action) {
+ case HostCmd_ACT_GEN_GET:
+ ppg_tlv->length = wlan_le16_to_cpu(ppg_tlv->length);
+ if (pmpriv->adapter->hw_status ==
+ WlanHardwareStatusInitializing)
+ wlan_get_power_level(pmpriv, ptxp_cfg);
+ pmpriv->tx_power_level = (t_s16)pg->power_min;
+ break;
+
+ case HostCmd_ACT_GEN_SET:
+ if (wlan_le32_to_cpu(ptxp_cfg->mode)) {
+ if (pg->power_max == pg->power_min)
+ pmpriv->tx_power_level = (t_s16)pg->power_min;
+ }
+ break;
+
+ default:
+ PRINTM(MERROR, "CMD_RESP: unknown command action %d\n", action);
+ LEAVE();
+ return MLAN_STATUS_SUCCESS;
+ }
+
+ PRINTM(MINFO, "Current TxPower Level = %d,Max Power=%d, Min Power=%d\n",
+ pmpriv->tx_power_level, pmpriv->max_tx_power_level,
+ pmpriv->min_tx_power_level);
+
+ if (pioctl_buf) {
+ power = (mlan_ds_power_cfg *)pioctl_buf->pbuf;
+ if (action == HostCmd_ACT_GEN_GET) {
+ if (power->sub_command == MLAN_OID_POWER_CFG) {
+ pioctl_buf->data_read_written =
+ sizeof(mlan_power_cfg_t) +
+ MLAN_SUB_COMMAND_SIZE;
+ power->param.power_cfg.power_level =
+ pmpriv->tx_power_level;
+ if (wlan_le32_to_cpu(ptxp_cfg->mode))
+ power->param.power_cfg.is_power_auto =
+ 0;
+ else
+ power->param.power_cfg.is_power_auto =
+ 1;
+ } else {
+ power->param.power_ext.num_pwr_grp = 0;
+ i = 0;
+ while ((ppg_tlv->length) &&
+ (i < MAX_POWER_GROUP)) {
+ pwr_grp = (mlan_power_group *)&power
+ ->param.power_ext
+ .power_group[i];
+ pwr_grp->first_rate_ind = 0;
+ pwr_grp->last_rate_ind = 0;
+ if (pg->modulation_class ==
+ MOD_CLASS_HR_DSSS) {
+ pwr_grp->rate_format =
+ MLAN_RATE_FORMAT_LG;
+ pwr_grp->first_rate_ind =
+ pg->first_rate_code;
+ pwr_grp->last_rate_ind =
+ pg->last_rate_code;
+ } else if (pg->modulation_class ==
+ MOD_CLASS_OFDM) {
+ pwr_grp->rate_format =
+ MLAN_RATE_FORMAT_LG;
+ pwr_grp->first_rate_ind =
+ MLAN_RATE_INDEX_OFDM0 +
+ pg->first_rate_code;
+ pwr_grp->last_rate_ind =
+ MLAN_RATE_INDEX_OFDM0 +
+ pg->last_rate_code;
+ } else if (pg->modulation_class ==
+ MOD_CLASS_HT) {
+ pwr_grp->rate_format =
+ MLAN_RATE_FORMAT_HT;
+ pwr_grp->first_rate_ind =
+ pg->first_rate_code;
+ pwr_grp->last_rate_ind =
+ pg->last_rate_code;
+ } else if (pg->modulation_class ==
+ MOD_CLASS_VHT) {
+ pwr_grp->rate_format =
+ MLAN_RATE_FORMAT_VHT;
+ pwr_grp->first_rate_ind =
+ (pg->first_rate_code) &
+ 0xF;
+ pwr_grp->last_rate_ind =
+ (pg->last_rate_code) &
+ 0xF;
+ // pwr_grp->nss = 1 +
+ // (pg->first_rate_code >> 4);
+ pwr_grp->nss =
+ 1 +
+ (pg->last_rate_code >>
+ 4);
+ }
+ pwr_grp->bandwidth = pg->ht_bandwidth;
+ pwr_grp->power_min = pg->power_min;
+ pwr_grp->power_max = pg->power_max;
+ pwr_grp->power_step = pg->power_step;
+ ppg_tlv->length -=
+ sizeof(Power_Group_t);
+ pg++;
+ i++;
+ }
+ power->param.power_ext.num_pwr_grp = i;
+ pioctl_buf->data_read_written =
+ sizeof(mlan_power_cfg_ext) +
+ MLAN_SUB_COMMAND_SIZE;
+ }
+ }
+ }
+
+ LEAVE();
+ return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ * @brief This function handles the command response of rf_tx_power
+ *
+ * @param pmpriv A pointer to mlan_private structure
+ * @param resp A pointer to HostCmd_DS_COMMAND
+ * @param pioctl_buf A pointer to mlan_ioctl_req structure
+ * @return MLAN_STATUS_SUCCESS
+ */
+static mlan_status wlan_ret_802_11_rf_tx_power(pmlan_private pmpriv,
+ HostCmd_DS_COMMAND *resp,
+ mlan_ioctl_req *pioctl_buf)
+{
+ HostCmd_DS_802_11_RF_TX_POWER *rtp = &resp->params.txp;
+ t_u16 action = wlan_le16_to_cpu(rtp->action);
+ mlan_ds_power_cfg *power = MNULL;
+
+ ENTER();
+
+ pmpriv->tx_power_level = wlan_le16_to_cpu(rtp->current_level);
+
+ if (action == HostCmd_ACT_GEN_GET) {
+ pmpriv->max_tx_power_level = rtp->max_power;
+ pmpriv->min_tx_power_level = rtp->min_power;
+ if (pioctl_buf) {
+ power = (mlan_ds_power_cfg *)pioctl_buf->pbuf;
+ if (power->sub_command == MLAN_OID_POWER_CFG) {
+ pioctl_buf->data_read_written =
+ sizeof(mlan_power_cfg_t) +
+ MLAN_SUB_COMMAND_SIZE;
+ power->param.power_cfg.power_level =
+ pmpriv->tx_power_level;
+ }
+ }
+ }
+
+ PRINTM(MINFO, "Current TxPower Level = %d,Max Power=%d, Min Power=%d\n",
+ pmpriv->tx_power_level, pmpriv->max_tx_power_level,
+ pmpriv->min_tx_power_level);
+
+ LEAVE();
+ return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ * @brief This function handles the command response of sleep_period
+ *
+ * @param pmpriv A pointer to mlan_private structure
+ * @param resp A pointer to HostCmd_DS_COMMAND
+ * @param pioctl_buf A pointer to mlan_ioctl_req structure
+ * @return MLAN_STATUS_SUCCESS
+ */
+static mlan_status wlan_ret_802_11_sleep_period(pmlan_private pmpriv,
+ HostCmd_DS_COMMAND *resp,
+ mlan_ioctl_req *pioctl_buf)
+{
+ HostCmd_DS_802_11_SLEEP_PERIOD *pcmd_sleep_pd = &resp->params.sleep_pd;
+ mlan_ds_pm_cfg *pm_cfg = MNULL;
+ t_u16 sleep_pd = 0;
+
+ ENTER();
+
+ sleep_pd = wlan_le16_to_cpu(pcmd_sleep_pd->sleep_pd);
+ if (pioctl_buf) {
+ pm_cfg = (mlan_ds_pm_cfg *)pioctl_buf->pbuf;
+ pm_cfg->param.sleep_period = (t_u32)sleep_pd;
+ pioctl_buf->data_read_written =
+ sizeof(pm_cfg->param.sleep_period) +
+ MLAN_SUB_COMMAND_SIZE;
+ }
+ pmpriv->adapter->sleep_period.period = sleep_pd;
+
+ pmpriv->adapter->pps_uapsd_mode = MFALSE;
+ if ((pmpriv->adapter->sleep_period.period != 0) &&
+ (pmpriv->adapter->sleep_period.period !=
+ SLEEP_PERIOD_RESERVED_FF)) {
+ pmpriv->adapter->gen_null_pkt = MTRUE;
+ } else {
+ pmpriv->adapter->delay_null_pkt = MFALSE;
+ pmpriv->adapter->gen_null_pkt = MFALSE;
+ }
+
+ LEAVE();
+ return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ * @brief This function handles the command response of sleep_params
+ *
+ * @param pmpriv A pointer to mlan_private structure
+ * @param resp A pointer to HostCmd_DS_COMMAND
+ * @param pioctl_buf A pointer to mlan_ioctl_req structure
+ * @return MLAN_STATUS_SUCCESS
+ */
+static mlan_status wlan_ret_802_11_sleep_params(pmlan_private pmpriv,
+ HostCmd_DS_COMMAND *resp,
+ mlan_ioctl_req *pioctl_buf)
+{
+ HostCmd_DS_802_11_SLEEP_PARAMS *presp_sp = &resp->params.sleep_param;
+ mlan_ds_pm_cfg *pm_cfg = MNULL;
+ mlan_ds_sleep_params *psp = MNULL;
+ sleep_params_t *psleep_params = &pmpriv->adapter->sleep_params;
+
+ ENTER();
+
+ psleep_params->sp_reserved = wlan_le16_to_cpu(presp_sp->reserved);
+ psleep_params->sp_error = wlan_le16_to_cpu(presp_sp->error);
+ psleep_params->sp_offset = wlan_le16_to_cpu(presp_sp->offset);
+ psleep_params->sp_stable_time = wlan_le16_to_cpu(presp_sp->stable_time);
+ psleep_params->sp_cal_control = presp_sp->cal_control;
+ psleep_params->sp_ext_sleep_clk = presp_sp->external_sleep_clk;
+
+ if (pioctl_buf) {
+ pm_cfg = (mlan_ds_pm_cfg *)pioctl_buf->pbuf;
+ psp = (mlan_ds_sleep_params *)&pm_cfg->param.sleep_params;
+
+ psp->error = (t_u32)psleep_params->sp_error;
+ psp->offset = (t_u32)psleep_params->sp_offset;
+ psp->stable_time = (t_u32)psleep_params->sp_stable_time;
+ psp->cal_control = (t_u32)psleep_params->sp_cal_control;
+ psp->ext_sleep_clk = (t_u32)psleep_params->sp_ext_sleep_clk;
+ psp->reserved = (t_u32)psleep_params->sp_reserved;
+
+ pioctl_buf->data_read_written =
+ sizeof(pm_cfg->param.sleep_params) +
+ MLAN_SUB_COMMAND_SIZE;
+ }
+
+ LEAVE();
+ return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ * @brief This function handles the command response of multicast_address
+ *
+ * @param pmpriv A pointer to mlan_private structure
+ * @param resp A pointer to HostCmd_DS_COMMAND
+ * @param pioctl_buf A pointer to mlan_ioctl_req structure
+ *
+ * @return MLAN_STATUS_SUCCESS
+ */
+static mlan_status wlan_ret_mac_multicast_adr(pmlan_private pmpriv,
+ HostCmd_DS_COMMAND *resp,
+ mlan_ioctl_req *pioctl_buf)
+{
+ ENTER();
+ if (pioctl_buf) {
+ pioctl_buf->data_read_written =
+ sizeof(mlan_multicast_list) + MLAN_SUB_COMMAND_SIZE;
+ }
+ LEAVE();
+ return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ * @brief This function handles the command response of deauthenticate
+ *
+ * @param pmpriv A pointer to mlan_private structure
+ * @param resp A pointer to HostCmd_DS_COMMAND
+ * @param pioctl_buf A pointer to mlan_ioctl_req structure
+ *
+ * @return MLAN_STATUS_SUCCESS
+ */
+static mlan_status wlan_ret_802_11_deauthenticate(pmlan_private pmpriv,
+ HostCmd_DS_COMMAND *resp,
+ mlan_ioctl_req *pioctl_buf)
+{
+ mlan_adapter *pmadapter = pmpriv->adapter;
+ t_u8 event_buf[32];
+ mlan_event *pevent = (mlan_event *)event_buf;
+ ENTER();
+
+ pmadapter->dbg.num_cmd_deauth++;
+
+ if (!memcmp(pmadapter, resp->params.deauth.mac_addr,
+ &pmpriv->curr_bss_params.bss_descriptor.mac_address,
+ sizeof(resp->params.deauth.mac_addr))) {
+ wlan_reset_connect_state(pmpriv, MTRUE);
+ }
+ if (pmpriv->adapter->state_rdh.stage == RDH_STOP_INTFS)
+ wlan_11h_radar_detected_callback((t_void *)pmpriv);
+ memset(pmadapter, event_buf, 0, sizeof(event_buf));
+ pevent->bss_index = pmpriv->bss_index;
+ pevent->event_id = MLAN_EVENT_ID_DRV_DISCONNECT_LOGGER;
+ pevent->event_len = sizeof(resp->params.deauth.reason_code);
+ memcpy_ext(pmpriv->adapter, (t_u8 *)pevent->event_buf,
+ &resp->params.deauth.reason_code, pevent->event_len,
+ pevent->event_len);
+ wlan_recv_event(pmpriv, MLAN_EVENT_ID_DRV_DISCONNECT_LOGGER, pevent);
+
+ LEAVE();
+ return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ * @brief This function handles the command response of ad_hoc_stop
+ *
+ * @param pmpriv A pointer to mlan_private structure
+ * @param resp A pointer to HostCmd_DS_COMMAND
+ * @param pioctl_buf A pointer to mlan_ioctl_req structure
+ *
+ * @return MLAN_STATUS_SUCCESS
+ */
+static mlan_status wlan_ret_802_11_ad_hoc_stop(pmlan_private pmpriv,
+ HostCmd_DS_COMMAND *resp,
+ mlan_ioctl_req *pioctl_buf)
+{
+ ENTER();
+
+ wlan_reset_connect_state(pmpriv, MTRUE);
+ if (pmpriv->adapter->state_rdh.stage == RDH_STOP_INTFS)
+ wlan_11h_radar_detected_callback((t_void *)pmpriv);
+ LEAVE();
+ return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ * @brief This function handles the command response of key_material
+ *
+ * @param pmpriv A pointer to mlan_private structure
+ * @param resp A pointer to HostCmd_DS_COMMAND
+ * @param pioctl_buf A pointer to mlan_ioctl_req structure
+ *
+ * @return MLAN_STATUS_SUCCESS
+ */
+static mlan_status wlan_ret_802_11_key_material(pmlan_private pmpriv,
+ HostCmd_DS_COMMAND *resp,
+ mlan_ioctl_req *pioctl_buf)
+{
+ HostCmd_DS_802_11_KEY_MATERIAL *pkey = &resp->params.key_material;
+ mlan_ds_sec_cfg *sec = MNULL;
+ t_u8 zero_kek[MLAN_KEK_LEN] = {0};
+
+ ENTER();
+
+ if (wlan_le16_to_cpu(pkey->action) == HostCmd_ACT_GEN_SET) {
+ if ((wlan_le16_to_cpu(pkey->key_param_set.key_info) &
+ KEY_INFO_TKIP_MCAST)) {
+ PRINTM(MINFO, "key: GTK is set\n");
+ pmpriv->wpa_is_gtk_set = MTRUE;
+ if (pmpriv->port_ctrl_mode == MTRUE) {
+ /* GTK is set, open the port */
+ PRINTM(MINFO,
+ "GTK_SET: Open port: WPA/WPA2 h-supp mode\n");
+ pmpriv->port_open = MTRUE;
+ }
+ if (memcmp(pmpriv->adapter, pmpriv->gtk_rekey.kek,
+ zero_kek, sizeof(zero_kek)) != 0) {
+ wlan_prepare_cmd(
+ pmpriv,
+ HostCmd_CMD_GTK_REKEY_OFFLOAD_CFG,
+ HostCmd_ACT_GEN_SET, 0, MNULL,
+ &pmpriv->gtk_rekey);
+ memset(pmpriv->adapter, &pmpriv->gtk_rekey, 0,
+ sizeof(mlan_ds_misc_gtk_rekey_data));
+ }
+ pmpriv->adapter->scan_block = MFALSE;
+ }
+ } else if (wlan_le16_to_cpu(pkey->action) == HostCmd_ACT_GEN_GET) {
+ if (pioctl_buf && (wlan_le16_to_cpu(pkey->key_param_set.type) ==
+ TLV_TYPE_KEY_PARAM_V2)) {
+ sec = (mlan_ds_sec_cfg *)pioctl_buf->pbuf;
+ memcpy_ext(pmpriv->adapter,
+ sec->param.encrypt_key.mac_addr,
+ pkey->key_param_set.mac_addr,
+ MLAN_MAC_ADDR_LENGTH,
+ sizeof(sec->param.encrypt_key.mac_addr));
+ sec->param.encrypt_key.key_index =
+ pkey->key_param_set.key_idx;
+ PRINTM(MIOCTL,
+ "key_type=%d, key_index=%d, key_info=0x%x " MACSTR
+ "\n",
+ pkey->key_param_set.key_type,
+ pkey->key_param_set.key_idx,
+ wlan_le16_to_cpu(pkey->key_param_set.key_info),
+ MAC2STR(sec->param.encrypt_key.mac_addr));
+ switch (pkey->key_param_set.key_type) {
+ case KEY_TYPE_ID_WAPI:
+ sec->param.encrypt_key.is_wapi_key = MTRUE;
+ sec->param.encrypt_key.key_len =
+ wlan_le16_to_cpu(
+ pkey->key_param_set.key_params
+ .wapi.key_len);
+ memcpy_ext(
+ pmpriv->adapter,
+ sec->param.encrypt_key.key_material,
+ pkey->key_param_set.key_params.wapi.key,
+ sec->param.encrypt_key.key_len,
+ sizeof(sec->param.encrypt_key
+ .key_material));
+ memcpy_ext(
+ pmpriv->adapter,
+ sec->param.encrypt_key.pn,
+ pkey->key_param_set.key_params.wapi.pn,
+ PN_SIZE,
+ sizeof(sec->param.encrypt_key.pn));
+ break;
+ case KEY_TYPE_ID_TKIP:
+ sec->param.encrypt_key.key_len =
+ wlan_le16_to_cpu(
+ pkey->key_param_set.key_params
+ .tkip.key_len);
+ memcpy_ext(
+ pmpriv->adapter,
+ sec->param.encrypt_key.key_material,
+ pkey->key_param_set.key_params.tkip.key,
+ sec->param.encrypt_key.key_len,
+ sizeof(sec->param.encrypt_key
+ .key_material));
+ memcpy_ext(
+ pmpriv->adapter,
+ sec->param.encrypt_key.pn,
+ pkey->key_param_set.key_params.tkip.pn,
+ WPA_PN_SIZE,
+ sizeof(sec->param.encrypt_key.pn));
+ break;
+ case KEY_TYPE_ID_AES:
+ sec->param.encrypt_key.key_len =
+ wlan_le16_to_cpu(
+ pkey->key_param_set.key_params
+ .aes.key_len);
+ memcpy_ext(
+ pmpriv->adapter,
+ sec->param.encrypt_key.key_material,
+ pkey->key_param_set.key_params.aes.key,
+ sec->param.encrypt_key.key_len,
+ sizeof(sec->param.encrypt_key
+ .key_material));
+ memcpy_ext(
+ pmpriv->adapter,
+ sec->param.encrypt_key.pn,
+ pkey->key_param_set.key_params.aes.pn,
+ WPA_PN_SIZE,
+ sizeof(sec->param.encrypt_key.pn));
+ break;
+ case KEY_TYPE_ID_AES_CMAC:
+ sec->param.encrypt_key.key_len =
+ wlan_le16_to_cpu(
+ pkey->key_param_set.key_params
+ .cmac_aes.key_len);
+ memcpy_ext(pmpriv->adapter,
+ sec->param.encrypt_key.key_material,
+ pkey->key_param_set.key_params
+ .cmac_aes.key,
+ sec->param.encrypt_key.key_len,
+ sizeof(sec->param.encrypt_key
+ .key_material));
+ memcpy_ext(pmpriv->adapter,
+ sec->param.encrypt_key.pn,
+ pkey->key_param_set.key_params
+ .cmac_aes.ipn,
+ IGTK_PN_SIZE,
+ sizeof(sec->param.encrypt_key.pn));
+ break;
+ case KEY_TYPE_ID_WEP:
+ sec->param.encrypt_key.key_len =
+ wlan_le16_to_cpu(
+ pkey->key_param_set.key_params
+ .wep.key_len);
+ memcpy_ext(
+ pmpriv->adapter,
+ sec->param.encrypt_key.key_material,
+ pkey->key_param_set.key_params.wep.key,
+ sec->param.encrypt_key.key_len,
+ sizeof(sec->param.encrypt_key
+ .key_material));
+ break;
+ }
+ }
+ }
+ LEAVE();
+ return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ * @brief Handle the supplicant profile response
+ *
+ * @param pmpriv A pointer to mlan_private structure
+ * @param resp A pointer to HostCmd_DS_COMMAND
+ * @param pioctl_buf A pointer to mlan_ioctl_req structure
+ *
+ * @return MLAN_STATUS_SUCCESS
+ */
+static mlan_status
+wlan_ret_802_11_supplicant_profile(pmlan_private pmpriv,
+ HostCmd_DS_COMMAND *resp,
+ mlan_ioctl_req *pioctl_buf)
+{
+ HostCmd_DS_802_11_SUPPLICANT_PROFILE *psup_profile =
+ &resp->params.esupplicant_profile;
+ MrvlIEtypesHeader_t *head;
+ MrvlIEtypes_EncrProto_t *encr_proto_tlv = MNULL;
+ MrvlIEtypes_Cipher_t *pcipher_tlv = MNULL;
+ mlan_ds_sec_cfg *sec = MNULL;
+ t_u8 *tlv;
+ int len;
+
+ ENTER();
+
+ len = resp->size - S_DS_GEN - sizeof(t_u16);
+ tlv = psup_profile->tlv_buf;
+ if (pioctl_buf) {
+ sec = (mlan_ds_sec_cfg *)pioctl_buf->pbuf;
+ while (len > 0) {
+ head = (MrvlIEtypesHeader_t *)tlv;
+ head->type = wlan_le16_to_cpu(head->type);
+ head->len = wlan_le16_to_cpu(head->len);
+ switch (head->type) {
+ case TLV_TYPE_ENCRYPTION_PROTO:
+ encr_proto_tlv =
+ (MrvlIEtypes_EncrProto_t *)head;
+ sec->param.esupp_mode.rsn_mode =
+ wlan_le16_to_cpu(
+ encr_proto_tlv->rsn_mode);
+ PRINTM(MINFO, "rsn_mode=0x%x\n",
+ sec->param.esupp_mode.rsn_mode);
+ break;
+ case TLV_TYPE_CIPHER:
+ pcipher_tlv = (MrvlIEtypes_Cipher_t *)head;
+ sec->param.esupp_mode.act_paircipher =
+ pcipher_tlv->pair_cipher;
+ sec->param.esupp_mode.act_groupcipher =
+ pcipher_tlv->group_cipher;
+ PRINTM(MINFO,
+ "paircipher=0x%x, groupcipher=0x%x\n",
+ sec->param.esupp_mode.act_paircipher,
+ sec->param.esupp_mode.act_groupcipher);
+ break;
+ }
+ len -= (head->len - sizeof(MrvlIEtypesHeader_t));
+ tlv = tlv + (head->len + sizeof(MrvlIEtypesHeader_t));
+ }
+ }
+
+ LEAVE();
+ return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ * @brief This function handles the command response of rf_channel
+ *
+ * @param pmpriv A pointer to mlan_private structure
+ * @param resp A pointer to HostCmd_DS_COMMAND
+ * @param pioctl_buf A pointer to mlan_ioctl_req structure
+ *
+ * @return MLAN_STATUS_SUCCESS
+ */
+static mlan_status wlan_ret_802_11_rf_channel(pmlan_private pmpriv,
+ HostCmd_DS_COMMAND *resp,
+ mlan_ioctl_req *pioctl_buf)
+{
+ HostCmd_DS_802_11_RF_CHANNEL *prf_channel = &resp->params.rf_channel;
+ t_u16 new_channel = wlan_le16_to_cpu(prf_channel->current_channel);
+ mlan_ds_bss *bss = MNULL;
+
+ ENTER();
+ if (pmpriv->curr_bss_params.bss_descriptor.channel != new_channel) {
+ PRINTM(MINFO, "Channel Switch: %d to %d\n",
+ pmpriv->curr_bss_params.bss_descriptor.channel,
+ new_channel);
+ /* Update the channel again */
+ pmpriv->curr_bss_params.bss_descriptor.channel = new_channel;
+ }
+ if (pioctl_buf) {
+ bss = (mlan_ds_bss *)pioctl_buf->pbuf;
+ bss->param.bss_chan.channel = new_channel;
+ }
+ LEAVE();
+ return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ * @brief Handle the ibss_coalescing_status resp
+ *
+ * @param pmpriv A pointer to mlan_private structure
+ * @param resp A pointer to HostCmd_DS_COMMAND
+ *
+ * @return MLAN_STATUS_SUCCESS
+ */
+static mlan_status wlan_ret_ibss_coalescing_status(pmlan_private pmpriv,
+ HostCmd_DS_COMMAND *resp)
+{
+ HostCmd_DS_802_11_IBSS_STATUS *pibss_coal_resp =
+ &(resp->params.ibss_coalescing);
+ t_u8 zero_mac[MLAN_MAC_ADDR_LENGTH] = {0, 0, 0, 0, 0, 0};
+
+ ENTER();
+
+ if (wlan_le16_to_cpu(pibss_coal_resp->action) == HostCmd_ACT_GEN_SET) {
+ LEAVE();
+ return MLAN_STATUS_SUCCESS;
+ }
+
+ PRINTM(MINFO, "New BSSID " MACSTR "\n",
+ MAC2STR(pibss_coal_resp->bssid));
+
+ /* If rsp has MNULL BSSID, Just return..... No Action */
+ if (!memcmp(pmpriv->adapter, pibss_coal_resp->bssid, zero_mac,
+ MLAN_MAC_ADDR_LENGTH)) {
+ PRINTM(MMSG, "New BSSID is MNULL\n");
+ LEAVE();
+ return MLAN_STATUS_SUCCESS;
+ }
+
+ /* If BSSID is diff, modify current BSS parameters */
+ if (memcmp(pmpriv->adapter,
+ pmpriv->curr_bss_params.bss_descriptor.mac_address,
+ pibss_coal_resp->bssid, MLAN_MAC_ADDR_LENGTH)) {
+ /* BSSID */
+ memcpy_ext(pmpriv->adapter,
+ pmpriv->curr_bss_params.bss_descriptor.mac_address,
+ pibss_coal_resp->bssid, MLAN_MAC_ADDR_LENGTH,
+ sizeof(pmpriv->curr_bss_params.bss_descriptor
+ .mac_address));
+
+ /* Beacon Interval and ATIM window */
+ pmpriv->curr_bss_params.bss_descriptor.beacon_period =
+ wlan_le16_to_cpu(pibss_coal_resp->beacon_interval);
+ pmpriv->curr_bss_params.bss_descriptor.atim_window =
+ wlan_le16_to_cpu(pibss_coal_resp->atim_window);
+
+ /* ERP Information */
+ pmpriv->curr_bss_params.bss_descriptor.erp_flags =
+ (t_u8)wlan_le16_to_cpu(
+ pibss_coal_resp->use_g_rate_protect);
+
+ pmpriv->adhoc_state = ADHOC_COALESCED;
+ }
+
+ LEAVE();
+ return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ * @brief This function handles the command response of MGMT_IE_LIST
+ *
+ * @param pmpriv A pointer to mlan_private structure
+ * @param resp A pointer to HostCmd_DS_COMMAND
+ * @param pioctl_buf A pointer to mlan_ioctl_req structure
+ *
+ * @return MLAN_STATUS_SUCCESS
+ */
+static mlan_status wlan_ret_mgmt_ie_list(pmlan_private pmpriv,
+ HostCmd_DS_COMMAND *resp,
+ mlan_ioctl_req *pioctl_buf)
+{
+ t_u16 resp_len = 0, travel_len = 0;
+ int i = 0;
+ mlan_ds_misc_cfg *misc = MNULL;
+ mlan_ds_misc_custom_ie *cust_ie = MNULL;
+ custom_ie *cptr;
+ tlvbuf_max_mgmt_ie *max_mgmt_ie = MNULL;
+ HostCmd_DS_MGMT_IE_LIST_CFG *pmgmt_ie_list =
+ &(resp->params.mgmt_ie_list);
+
+ ENTER();
+
+ if (wlan_le16_to_cpu(pmgmt_ie_list->action) == HostCmd_ACT_GEN_SET) {
+ if ((pmpriv->adapter->state_rdh.stage == RDH_SET_CUSTOM_IE) ||
+ (pmpriv->adapter->state_rdh.stage == RDH_REM_CUSTOM_IE))
+ if (!pmpriv->adapter->ecsa_enable)
+ wlan_11h_radar_detected_callback(
+ (t_void *)pmpriv);
+ LEAVE();
+ return MLAN_STATUS_SUCCESS;
+ }
+
+ misc = (mlan_ds_misc_cfg *)pioctl_buf->pbuf;
+ cust_ie = (mlan_ds_misc_custom_ie *)&pmgmt_ie_list->ds_mgmt_ie;
+ if (cust_ie) {
+ cust_ie->type = wlan_le16_to_cpu(cust_ie->type);
+ resp_len = cust_ie->len = wlan_le16_to_cpu(cust_ie->len);
+ travel_len = 0;
+ /* conversion for index, mask, len */
+ if (resp_len == sizeof(t_u16))
+ cust_ie->ie_data_list[0].ie_index = wlan_cpu_to_le16(
+ cust_ie->ie_data_list[0].ie_index);
+
+ while (resp_len > sizeof(t_u16)) {
+ cptr = (custom_ie *)(((t_u8 *)cust_ie->ie_data_list) +
+ travel_len);
+ cptr->ie_index = wlan_le16_to_cpu(cptr->ie_index);
+ cptr->mgmt_subtype_mask =
+ wlan_le16_to_cpu(cptr->mgmt_subtype_mask);
+ cptr->ie_length = wlan_le16_to_cpu(cptr->ie_length);
+ travel_len += cptr->ie_length + sizeof(custom_ie) -
+ MAX_IE_SIZE;
+ resp_len -= cptr->ie_length + sizeof(custom_ie) -
+ MAX_IE_SIZE;
+ }
+ memcpy_ext(pmpriv->adapter, &misc->param.cust_ie, cust_ie,
+ (cust_ie->len + sizeof(MrvlIEtypesHeader_t)),
+ sizeof(misc->param.cust_ie));
+ max_mgmt_ie =
+ (tlvbuf_max_mgmt_ie *)((t_u8 *)cust_ie + cust_ie->len +
+ sizeof(MrvlIEtypesHeader_t));
+ if (max_mgmt_ie) {
+ max_mgmt_ie->type = wlan_le16_to_cpu(max_mgmt_ie->type);
+ if (max_mgmt_ie->type == TLV_TYPE_MAX_MGMT_IE) {
+ max_mgmt_ie->len =
+ wlan_le16_to_cpu(max_mgmt_ie->len);
+ max_mgmt_ie->count =
+ wlan_le16_to_cpu(max_mgmt_ie->count);
+ for (i = 0; i < max_mgmt_ie->count; i++) {
+ max_mgmt_ie->info[i]
+ .buf_size = wlan_le16_to_cpu(
+ max_mgmt_ie->info[i].buf_size);
+ max_mgmt_ie->info[i]
+ .buf_count = wlan_le16_to_cpu(
+ max_mgmt_ie->info[i].buf_count);
+ }
+ /* Append max_mgmt_ie TLV after custom_ie */
+ memcpy_ext(
+ pmpriv->adapter,
+ (t_u8 *)&misc->param.cust_ie +
+ (cust_ie->len +
+ sizeof(MrvlIEtypesHeader_t)),
+ max_mgmt_ie,
+ max_mgmt_ie->len +
+ sizeof(MrvlIEtypesHeader_t),
+ sizeof(misc->param.cust_ie) -
+ (cust_ie->len +
+ sizeof(MrvlIEtypesHeader_t)));
+ }
+ }
+ }
+
+ LEAVE();
+ return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ * @brief This function handles the command response of sysclock
+ *
+ * @param pmpriv A pointer to mlan_private structure
+ * @param resp A pointer to HostCmd_DS_COMMAND
+ * @param pioctl_buf A pointer to mlan_ioctl_req structure
+ *
+ * @return MLAN_STATUS_SUCCESS
+ */
+static mlan_status wlan_ret_sysclock_cfg(pmlan_private pmpriv,
+ HostCmd_DS_COMMAND *resp,
+ mlan_ioctl_req *pioctl_buf)
+{
+ mlan_ds_misc_cfg *mis_ccfg = MNULL;
+ HostCmd_DS_ECL_SYSTEM_CLOCK_CONFIG *clk_cfg =
+ &resp->params.sys_clock_cfg;
+ int i = 0;
+
+ ENTER();
+
+ if (pioctl_buf) {
+ mis_ccfg = (mlan_ds_misc_cfg *)pioctl_buf->pbuf;
+ mis_ccfg->param.sys_clock.cur_sys_clk =
+ wlan_le16_to_cpu(clk_cfg->cur_sys_clk);
+ mis_ccfg->param.sys_clock.sys_clk_type =
+ wlan_le16_to_cpu(clk_cfg->sys_clk_type);
+ mis_ccfg->param.sys_clock.sys_clk_num =
+ wlan_le16_to_cpu(clk_cfg->sys_clk_len) / sizeof(t_u16);
+ for (i = 0; i < mis_ccfg->param.sys_clock.sys_clk_num; i++)
+ mis_ccfg->param.sys_clock.sys_clk[i] =
+ wlan_le16_to_cpu(clk_cfg->sys_clk[i]);
+ }
+
+ LEAVE();
+ return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ * @brief This function handles the command response of inactivity timeout
+ *
+ * @param pmpriv A pointer to mlan_private structure
+ * @param resp A pointer to HostCmd_DS_COMMAND
+ * @param pioctl_buf A pointer to command buffer
+ *
+ * @return MLAN_STATUS_SUCCESS
+ */
+static mlan_status wlan_ret_inactivity_timeout(pmlan_private pmpriv,
+ HostCmd_DS_COMMAND *resp,
+ mlan_ioctl_req *pioctl_buf)
+{
+ mlan_ds_pm_cfg *pmcfg = MNULL;
+ mlan_ds_inactivity_to *inac_to = MNULL;
+ HostCmd_DS_INACTIVITY_TIMEOUT_EXT *cmd_inac_to =
+ (HostCmd_DS_INACTIVITY_TIMEOUT_EXT *)&resp->params.inactivity_to;
+
+ ENTER();
+
+ if (pioctl_buf) {
+ pmcfg = (mlan_ds_pm_cfg *)pioctl_buf->pbuf;
+ inac_to = &pmcfg->param.inactivity_to;
+ inac_to->timeout_unit =
+ wlan_le16_to_cpu(cmd_inac_to->timeout_unit);
+ inac_to->unicast_timeout =
+ wlan_le16_to_cpu(cmd_inac_to->unicast_timeout);
+ inac_to->mcast_timeout =
+ wlan_le16_to_cpu(cmd_inac_to->mcast_timeout);
+ inac_to->ps_entry_timeout =
+ wlan_le16_to_cpu(cmd_inac_to->ps_entry_timeout);
+ }
+
+ LEAVE();
+ return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ * @brief This function handles the command response of
+ * subscribe event
+ *
+ * @param pmpriv A pointer to mlan_private structure
+ * @param resp A pointer to HostCmd_DS_COMMAND
+ * @param pioctl_buf A pointer to command buffer
+ *
+ * @return MLAN_STATUS_SUCCESS
+ */
+static mlan_status wlan_ret_subscribe_event(pmlan_private pmpriv,
+ HostCmd_DS_COMMAND *resp,
+ mlan_ioctl_req *pioctl_buf)
+{
+ HostCmd_DS_SUBSCRIBE_EVENT *evt =
+ (HostCmd_DS_SUBSCRIBE_EVENT *)&resp->params.subscribe_event;
+ mlan_ds_subscribe_evt *sub_evt = MNULL;
+ mlan_ds_misc_cfg *misc = MNULL;
+
+ ENTER();
+ if (pioctl_buf && (pioctl_buf->action == MLAN_ACT_GET)) {
+ misc = (mlan_ds_misc_cfg *)pioctl_buf->pbuf;
+ sub_evt = &misc->param.subscribe_event;
+ sub_evt->evt_bitmap = wlan_le16_to_cpu(evt->event_bitmap);
+ pioctl_buf->data_read_written = sizeof(mlan_ds_misc_cfg);
+ }
+ LEAVE();
+ return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ * @brief This function handles the command response of
+ * OTP user data
+ *
+ * @param pmpriv A pointer to mlan_private structure
+ * @param resp A pointer to HostCmd_DS_COMMAND
+ * @param pioctl_buf A pointer to command buffer
+ *
+ * @return MLAN_STATUS_SUCCESS
+ */
+static mlan_status wlan_ret_otp_user_data(pmlan_private pmpriv,
+ HostCmd_DS_COMMAND *resp,
+ mlan_ioctl_req *pioctl_buf)
+{
+ HostCmd_DS_OTP_USER_DATA *cmd_user_data =
+ (HostCmd_DS_OTP_USER_DATA *)&resp->params.otp_user_data;
+ mlan_ds_misc_otp_user_data *user_data = MNULL;
+
+ ENTER();
+ if (pioctl_buf && (pioctl_buf->action == MLAN_ACT_GET)) {
+ user_data = (mlan_ds_misc_otp_user_data *)pioctl_buf->pbuf;
+ user_data->user_data_length =
+ MIN(MAX_OTP_USER_DATA_LEN,
+ wlan_le16_to_cpu(cmd_user_data->user_data_length));
+ memcpy_ext(pmpriv->adapter, user_data->user_data,
+ cmd_user_data->user_data,
+ user_data->user_data_length,
+ sizeof(user_data->user_data));
+ pioctl_buf->data_read_written =
+ sizeof(mlan_ds_misc_otp_user_data) +
+ user_data->user_data_length;
+ }
+ LEAVE();
+ return MLAN_STATUS_SUCCESS;
+}
+
+#ifdef USB
+/**
+ * @brief This function handles the command response of
+ * packet aggregation
+ *
+ * @param pmpriv A pointer to mlan_private structure
+ * @param resp A pointer to HostCmd_DS_COMMAND
+ * @param pioctl_buf A pointer to command buffer
+ *
+ * @return MLAN_STATUS_SUCCESS
+ */
+static mlan_status
+wlan_ret_packet_aggr_over_host_interface(pmlan_private pmpriv,
+ HostCmd_DS_COMMAND *resp,
+ mlan_ioctl_req *pioctl_buf)
+{
+ mlan_ds_misc_cfg *misc = MNULL;
+ HostCmd_DS_PACKET_AGGR_OVER_HOST_INTERFACE *packet_aggr =
+ (HostCmd_DS_PACKET_AGGR_OVER_HOST_INTERFACE *)&resp->params
+ .packet_aggr;
+ MrvlIETypes_USBAggrParam_t *usb_aggr_param_tlv = MNULL;
+ mlan_ds_misc_usb_aggr_ctrl *usb_aggr_ctrl = MNULL;
+ t_u8 *ptlv_buffer = (t_u8 *)packet_aggr->tlv_buf;
+ mlan_adapter *pmadapter = pmpriv->adapter;
+ t_u16 tlv = 0;
+ int tlv_buf_len = 0;
+ t_u8 changed = 0;
+#if defined(USB)
+ t_s32 i = 0;
+#endif
+
+ ENTER();
+
+ tlv_buf_len =
+ resp->size -
+ (sizeof(HostCmd_DS_PACKET_AGGR_OVER_HOST_INTERFACE) + S_DS_GEN);
+
+ if (!pioctl_buf) {
+ LEAVE();
+ return MLAN_STATUS_SUCCESS;
+ }
+ while (tlv_buf_len > 0) {
+ changed = 0;
+ tlv = (*ptlv_buffer) | (*(ptlv_buffer + 1) << 8);
+ switch (tlv) {
+ case MRVL_USB_AGGR_PARAM_TLV_ID:
+ usb_aggr_param_tlv =
+ (MrvlIETypes_USBAggrParam_t *)ptlv_buffer;
+ misc = (mlan_ds_misc_cfg *)pioctl_buf->pbuf;
+ usb_aggr_ctrl = (mlan_ds_misc_usb_aggr_ctrl *)&(
+ misc->param.usb_aggr_params);
+ usb_aggr_param_tlv->header.len = wlan_le16_to_cpu(
+ usb_aggr_param_tlv->header.len);
+ usb_aggr_param_tlv->enable =
+ wlan_le16_to_cpu(usb_aggr_param_tlv->enable);
+#if defined(USB)
+ if (pioctl_buf->action == MLAN_ACT_SET) {
+ /* Update the Tx aggregation values in
+ * MLAN */
+ for (i = 0; i < MAX_USB_TX_PORT_NUM; i++) {
+ pmadapter->pcard_usb->usb_tx_aggr[i]
+ .aggr_ctrl.enable =
+ usb_aggr_ctrl->tx_aggr_ctrl
+ .enable;
+ if (pmadapter->pcard_usb->usb_tx_aggr[i]
+ .aggr_ctrl.aggr_mode !=
+ usb_aggr_ctrl->tx_aggr_ctrl
+ .aggr_mode) {
+ pmadapter->pcard_usb
+ ->usb_tx_aggr[i]
+ .aggr_ctrl.aggr_mode =
+ usb_aggr_ctrl
+ ->tx_aggr_ctrl
+ .aggr_mode;
+ changed = 1;
+ }
+ if (pmadapter->pcard_usb->usb_tx_aggr[i]
+ .aggr_ctrl.aggr_align !=
+ usb_aggr_ctrl->tx_aggr_ctrl
+ .aggr_align) {
+ pmadapter->pcard_usb
+ ->usb_tx_aggr[i]
+ .aggr_ctrl.aggr_align =
+ usb_aggr_ctrl
+ ->tx_aggr_ctrl
+ .aggr_align;
+ changed = 1;
+ }
+ if (pmadapter->pcard_usb->usb_tx_aggr[i]
+ .aggr_ctrl.aggr_max !=
+ usb_aggr_ctrl->tx_aggr_ctrl
+ .aggr_max) {
+ pmadapter->pcard_usb
+ ->usb_tx_aggr[i]
+ .aggr_ctrl.aggr_max =
+ usb_aggr_ctrl
+ ->tx_aggr_ctrl
+ .aggr_max;
+ changed = 1;
+ }
+ pmadapter->pcard_usb->usb_tx_aggr[i]
+ .aggr_ctrl.aggr_tmo =
+ usb_aggr_ctrl->tx_aggr_ctrl
+ .aggr_tmo;
+ }
+ } else {
+ if (usb_aggr_param_tlv->enable & MBIT(1))
+ usb_aggr_ctrl->tx_aggr_ctrl.enable =
+ MTRUE;
+ else
+ usb_aggr_ctrl->tx_aggr_ctrl.enable =
+ MFALSE;
+ usb_aggr_ctrl->tx_aggr_ctrl
+ .aggr_align = wlan_le16_to_cpu(
+ usb_aggr_param_tlv->tx_aggr_align);
+ usb_aggr_ctrl->tx_aggr_ctrl.aggr_mode =
+ pmadapter->pcard_usb->usb_tx_aggr[0]
+ .aggr_ctrl.aggr_mode;
+ usb_aggr_ctrl->tx_aggr_ctrl.aggr_max =
+ pmadapter->pcard_usb->usb_tx_aggr[0]
+ .aggr_ctrl.aggr_max;
+ usb_aggr_ctrl->tx_aggr_ctrl.aggr_tmo =
+ pmadapter->pcard_usb->usb_tx_aggr[0]
+ .aggr_ctrl.aggr_tmo;
+ }
+ if (changed)
+ wlan_reset_usb_tx_aggr(pmadapter);
+#endif
+
+#if defined(USB)
+ if (pioctl_buf->action == MLAN_ACT_SET) {
+ /* Update the Rx deaggregation values in
+ * MLAN */
+ pmadapter->pcard_usb->usb_rx_deaggr.aggr_ctrl
+ .enable =
+ usb_aggr_ctrl->rx_deaggr_ctrl.enable;
+ if (pmadapter->pcard_usb->usb_rx_deaggr
+ .aggr_ctrl.aggr_mode !=
+ usb_aggr_ctrl->rx_deaggr_ctrl.aggr_mode)
+ pmadapter->pcard_usb->usb_rx_deaggr
+ .aggr_ctrl.aggr_mode =
+ usb_aggr_ctrl->rx_deaggr_ctrl
+ .aggr_mode;
+ if (pmadapter->pcard_usb->usb_rx_deaggr
+ .aggr_ctrl.aggr_align !=
+ usb_aggr_ctrl->rx_deaggr_ctrl.aggr_align)
+ pmadapter->pcard_usb->usb_rx_deaggr
+ .aggr_ctrl.aggr_align =
+ usb_aggr_ctrl->rx_deaggr_ctrl
+ .aggr_align;
+ if (pmadapter->pcard_usb->usb_rx_deaggr
+ .aggr_ctrl.aggr_max !=
+ usb_aggr_ctrl->rx_deaggr_ctrl.aggr_max)
+ pmadapter->pcard_usb->usb_rx_deaggr
+ .aggr_ctrl.aggr_max =
+ usb_aggr_ctrl->rx_deaggr_ctrl
+ .aggr_max;
+ pmadapter->pcard_usb->usb_rx_deaggr.aggr_ctrl
+ .aggr_tmo =
+ usb_aggr_ctrl->rx_deaggr_ctrl.aggr_tmo;
+ } else {
+ if (usb_aggr_param_tlv->enable & MBIT(0))
+ usb_aggr_ctrl->rx_deaggr_ctrl.enable =
+ MTRUE;
+ else
+ usb_aggr_ctrl->rx_deaggr_ctrl.enable =
+ MFALSE;
+ usb_aggr_ctrl->rx_deaggr_ctrl
+ .aggr_mode = wlan_le16_to_cpu(
+ usb_aggr_param_tlv->rx_aggr_mode);
+ usb_aggr_ctrl->rx_deaggr_ctrl
+ .aggr_align = wlan_le16_to_cpu(
+ usb_aggr_param_tlv->rx_aggr_align);
+ usb_aggr_ctrl->rx_deaggr_ctrl.aggr_max =
+ wlan_le16_to_cpu(
+ usb_aggr_param_tlv->rx_aggr_max);
+ usb_aggr_ctrl->rx_deaggr_ctrl.aggr_tmo =
+ wlan_le16_to_cpu(
+ usb_aggr_param_tlv->rx_aggr_tmo);
+ }
+#endif
+ ptlv_buffer += usb_aggr_param_tlv->header.len +
+ sizeof(MrvlIEtypesHeader_t);
+ tlv_buf_len -= (usb_aggr_param_tlv->header.len +
+ sizeof(MrvlIEtypesHeader_t));
+ break;
+ default:
+ break;
+ }
+ }
+
+ LEAVE();
+ return MLAN_STATUS_SUCCESS;
+}
+#endif
+
+/**
+ * @brief This function handles the command response of
+ * DFS Repeater mode configuration
+ *
+ * @param pmpriv A pointer to mlan_private structure
+ * @param resp A pointer to HostCmd_DS_COMMAND
+ * @param pioctl_buf A pointer to command buffer
+ *
+ * @return MLAN_STATUS_SUCCESS
+ */
+static mlan_status wlan_ret_dfs_repeater_cfg(pmlan_private pmpriv,
+ HostCmd_DS_COMMAND *resp,
+ mlan_ioctl_req *pioctl_buf)
+{
+ HostCmd_DS_DFS_REPEATER_MODE *cmd_dfs_repeater =
+ &resp->params.dfs_repeater;
+ mlan_ds_misc_cfg *misc = MNULL;
+ mlan_ds_misc_dfs_repeater *dfs_cfg = MNULL;
+
+ ENTER();
+
+ if (pioctl_buf && (pioctl_buf->action == MLAN_ACT_GET)) {
+ misc = (mlan_ds_misc_cfg *)pioctl_buf->pbuf;
+ dfs_cfg =
+ (mlan_ds_misc_dfs_repeater *)&misc->param.dfs_repeater;
+ dfs_cfg->mode = wlan_le16_to_cpu(cmd_dfs_repeater->mode);
+ }
+ if (pioctl_buf && (pioctl_buf->action == MLAN_ACT_SET)) {
+ if (wlan_le16_to_cpu(cmd_dfs_repeater->mode) == 1) {
+ /* Set dfs_repeater mode to true/enabled
+ * for futher references.
+ */
+ pmpriv->adapter->dfs_repeater = MTRUE;
+ } else {
+ pmpriv->adapter->dfs_repeater = MFALSE;
+ }
+ }
+
+ LEAVE();
+ return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ * @brief This function handles the command response of coalesce config
+ *
+ * @param pmpriv A pointer to mlan_private structure
+ * @param resp A pointer to HostCmd_DS_COMMAND
+ * @param pioctl_buf A pointer to mlan_ioctl_req structure
+ *
+ * @return MLAN_STATUS_SUCCESS
+ */
+mlan_status wlan_ret_coalesce_config(pmlan_private pmpriv,
+ HostCmd_DS_COMMAND *resp,
+ mlan_ioctl_req *pioctl_buf)
+{
+ ENTER();
+ LEAVE();
+ return MLAN_STATUS_SUCCESS;
+}
+
+mlan_status wlan_ret_get_sensor_temp(pmlan_private pmpriv,
+ const HostCmd_DS_COMMAND *resp,
+ mlan_ioctl_req *pioctl_buf)
+{
+ mlan_ds_misc_cfg *pcfg = MNULL;
+ const HostCmd_DS_SENSOR_TEMP *pSensorT = &resp->params.temp_sensor;
+
+ ENTER();
+
+ if (pioctl_buf) {
+ pcfg = (mlan_ds_misc_cfg *)pioctl_buf->pbuf;
+ pcfg->param.sensor_temp.temperature =
+ wlan_le32_to_cpu(pSensorT->temperature);
+ PRINTM(MCMND, "get SOC temperature %u C \n",
+ pSensorT->temperature);
+ }
+
+ LEAVE();
+ return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ * @brief This function handles the command response of arb Cfg
+ *
+ * @param pmpriv A pointer to mlan_private structure
+ * @param resp A pointer to HostCmd_DS_COMMAND
+ * @param pioctl_buf A pointer to mlan_ioctl_req structure
+ *
+ * @return MLAN_STATUS_SUCCESS
+ */
+mlan_status wlan_ret_arb_cfg(pmlan_private pmpriv, HostCmd_DS_COMMAND *resp,
+ mlan_ioctl_req *pioctl_buf)
+{
+ HostCmd_DS_CMD_ARB_CONFIG *cfg_cmd =
+ (HostCmd_DS_CMD_ARB_CONFIG *)&resp->params.arb_cfg;
+ mlan_ds_misc_cfg *misc_cfg = MNULL;
+
+ ENTER();
+
+ if (pioctl_buf) {
+ misc_cfg = (mlan_ds_misc_cfg *)pioctl_buf->pbuf;
+ misc_cfg->param.arb_cfg.arb_mode =
+ wlan_le32_to_cpu(cfg_cmd->arb_mode);
+ }
+ LEAVE();
+ return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ * @brief This function handles the command response of sta get band and
+ * channel
+ *
+ * @param pmpriv A pointer to mlan_private structure
+ * @param resp A pointer to HostCmd_DS_COMMAND
+ * @param pioctl_buf A pointer to mlan_ioctl_req structure
+ *
+ * @return MLAN_STATUS_SUCCESS
+ */
+static mlan_status wlan_ret_sta_config(pmlan_private pmpriv,
+ HostCmd_DS_COMMAND *resp,
+ mlan_ioctl_req *pioctl_buf)
+{
+ HostCmd_DS_STA_CONFIGURE *cmdrsp_sta_cfg =
+ (HostCmd_DS_STA_CONFIGURE *)&resp->params.sta_cfg;
+ mlan_ds_bss *bss = MNULL;
+ MrvlIEtypes_channel_band_t *tlv_band_channel = MNULL;
+
+ ENTER();
+ if (pioctl_buf) {
+ if (pioctl_buf->req_id == MLAN_IOCTL_BSS) {
+ bss = (mlan_ds_bss *)pioctl_buf->pbuf;
+ if (bss->sub_command == MLAN_OID_BSS_CHAN_INFO) {
+ tlv_band_channel =
+ (MrvlIEtypes_channel_band_t *)
+ cmdrsp_sta_cfg->tlv_buffer;
+ bss->param.sta_channel.bandcfg =
+ tlv_band_channel->bandcfg;
+ bss->param.sta_channel.channel =
+ tlv_band_channel->channel;
+ bss->param.sta_channel.is_11n_enabled =
+ IS_11N_ENABLED(pmpriv);
+ if (bss->param.sta_channel.bandcfg.chanWidth ==
+ CHAN_BW_80MHZ)
+ bss->param.sta_channel.center_chan =
+ wlan_get_center_freq_idx(
+ pmpriv, BAND_AAC,
+ bss->param.sta_channel
+ .channel,
+ CHANNEL_BW_80MHZ);
+ PRINTM(MCMND,
+ "Get STA channel, band=0x%x, channel=%d, is_11n_enabled=%d center_chan=%d\n",
+ bss->param.sta_channel.bandcfg,
+ bss->param.sta_channel.channel,
+ bss->param.sta_channel.is_11n_enabled,
+ bss->param.sta_channel.center_chan);
+
+ pioctl_buf->data_read_written =
+ sizeof(mlan_ds_bss);
+ }
+ }
+ }
+ LEAVE();
+ return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ * @brief This function handles the command response of set/get auto tx
+ *
+ * @param pmpriv A pointer to mlan_private structure
+ * @param resp A pointer to HostCmd_DS_COMMAND
+ * @param pioctl_buf A pointer to mlan_ioctl_req structure
+ *
+ * @return MLAN_STATUS_SUCCESS
+ */
+static mlan_status wlan_ret_auto_tx(pmlan_private pmpriv,
+ HostCmd_DS_COMMAND *resp,
+ mlan_ioctl_req *pioctl_buf)
+{
+ HostCmd_DS_AUTO_TX *cmdrsp_auto_tx =
+ (HostCmd_DS_AUTO_TX *)&resp->params.auto_tx;
+ mlan_status status = MLAN_STATUS_SUCCESS;
+ MrvlIEtypesHeader_t *header = MNULL;
+ mlan_ds_misc_cfg *misc = MNULL;
+ t_u16 action;
+ t_u16 len = 0;
+ MrvlIEtypes_Cloud_Keep_Alive_t *keep_alive_tlv = MNULL;
+ MrvlIEtypes_Keep_Alive_Pkt_t *pkt_tlv = MNULL;
+ mlan_ds_misc_keep_alive *misc_keep_alive = MNULL;
+
+ ENTER();
+
+ action = wlan_le16_to_cpu(cmdrsp_auto_tx->action);
+ if (!pioctl_buf) {
+ PRINTM(MERROR, "ioctl is null\n");
+ LEAVE();
+ return MLAN_STATUS_FAILURE;
+ }
+
+ misc = (mlan_ds_misc_cfg *)pioctl_buf->pbuf;
+
+ if (!misc) {
+ PRINTM(MERROR, "misc is null\n");
+ LEAVE();
+ return MLAN_STATUS_FAILURE;
+ }
+
+ if (resp->result == HostCmd_RESULT_OK) {
+ header = (MrvlIEtypesHeader_t *)cmdrsp_auto_tx->tlv_buffer;
+ header->type = wlan_le16_to_cpu(header->type);
+ len = wlan_le16_to_cpu(header->len);
+ if (header->type == TLV_TYPE_CLOUD_KEEP_ALIVE) {
+ keep_alive_tlv = (MrvlIEtypes_Cloud_Keep_Alive_t *)
+ cmdrsp_auto_tx->tlv_buffer;
+ misc_keep_alive = (mlan_ds_misc_keep_alive *)&misc
+ ->param.keep_alive;
+ misc_keep_alive->mkeep_alive_id =
+ keep_alive_tlv->keep_alive_id;
+ misc_keep_alive->enable = keep_alive_tlv->enable;
+ if (((action == HostCmd_ACT_GEN_SET) ||
+ (action == HostCmd_ACT_GEN_RESET)) &&
+ !keep_alive_tlv->enable) {
+ len = len -
+ sizeof(keep_alive_tlv->keep_alive_id) -
+ sizeof(keep_alive_tlv->enable);
+ if (len > sizeof(MrvlIEtypesHeader_t)) {
+ header = (MrvlIEtypesHeader_t *)
+ keep_alive_tlv->tlv;
+ header->type =
+ wlan_le16_to_cpu(header->type);
+ len = wlan_le16_to_cpu(header->len) -
+ sizeof(Eth803Hdr_t);
+ if (header->type ==
+ TLV_TYPE_KEEP_ALIVE_PKT) {
+ pkt_tlv =
+ (MrvlIEtypes_Keep_Alive_Pkt_t
+ *)keep_alive_tlv
+ ->tlv;
+ memcpy_ext(
+ pmpriv->adapter,
+ misc_keep_alive->dst_mac,
+ pkt_tlv->eth_header
+ .dest_addr,
+ MLAN_MAC_ADDR_LENGTH,
+ sizeof(misc_keep_alive
+ ->dst_mac));
+ memcpy_ext(
+ pmpriv->adapter,
+ misc_keep_alive->src_mac,
+ pkt_tlv->eth_header
+ .src_addr,
+ MLAN_MAC_ADDR_LENGTH,
+ sizeof(misc_keep_alive
+ ->src_mac));
+ memcpy_ext(
+ pmpriv->adapter,
+ misc_keep_alive->packet,
+ pkt_tlv->ip_packet, len,
+ sizeof(misc_keep_alive
+ ->packet));
+ misc_keep_alive->pkt_len = len;
+ }
+ }
+ }
+ }
+ }
+
+ LEAVE();
+ return status;
+}
+
+/********************************************************
+ Global Functions
+********************************************************/
+
+/**
+ * @brief This function prepares command resp of MFG Continuous Tx
+ *
+ * @param pmpriv A pointer to mlan_private structure
+ * @param resp A pointer to HostCmd_DS_COMMAND
+ * @param pioctl_buf A pointer to mlan_ioctl_req structure
+ *
+ * @return MLAN_STATUS_SUCCESS
+ */
+static mlan_status wlan_ret_mfg_tx_cont(pmlan_private pmpriv,
+ HostCmd_DS_COMMAND *resp,
+ mlan_ioctl_req *pioctl_buf)
+{
+ mlan_ds_misc_cfg *misc = MNULL;
+ struct mfg_cmd_tx_cont *mcmd =
+ (struct mfg_cmd_tx_cont *)&resp->params.mfg_tx_cont;
+ struct mfg_cmd_tx_cont *cfg = MNULL;
+
+ ENTER();
+ if (!pioctl_buf) {
+ LEAVE();
+ return MLAN_STATUS_FAILURE;
+ }
+ misc = (mlan_ds_misc_cfg *)pioctl_buf->pbuf;
+ cfg = (struct mfg_cmd_tx_cont *)&misc->param.mfg_tx_cont;
+
+ cfg->error = wlan_le32_to_cpu(mcmd->error);
+ cfg->enable_tx = wlan_le32_to_cpu(mcmd->enable_tx);
+ cfg->cw_mode = wlan_le32_to_cpu(mcmd->cw_mode);
+ cfg->payload_pattern = wlan_le32_to_cpu(mcmd->payload_pattern);
+ cfg->cs_mode = wlan_le32_to_cpu(mcmd->cs_mode);
+ cfg->act_sub_ch = wlan_le32_to_cpu(mcmd->act_sub_ch);
+ cfg->tx_rate = wlan_le32_to_cpu(mcmd->tx_rate);
+
+ LEAVE();
+ return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ * @brief This function prepares command resp of MFG Tx frame
+ *
+ * @param pmpriv A pointer to mlan_private structure
+ * @param resp A pointer to HostCmd_DS_COMMAND
+ * @param pioctl_buf A pointer to mlan_ioctl_req structure
+ *
+ * @return MLAN_STATUS_SUCCESS
+ */
+static mlan_status wlan_ret_mfg_tx_frame(pmlan_private pmpriv,
+ HostCmd_DS_COMMAND *resp,
+ mlan_ioctl_req *pioctl_buf)
+{
+ mlan_ds_misc_cfg *misc = MNULL;
+ struct mfg_cmd_tx_frame2 *mcmd =
+ (struct mfg_cmd_tx_frame2 *)&resp->params.mfg_tx_frame2;
+ struct mfg_cmd_tx_frame2 *cfg = MNULL;
+
+ ENTER();
+ if (!pioctl_buf) {
+ LEAVE();
+ return MLAN_STATUS_FAILURE;
+ }
+ misc = (mlan_ds_misc_cfg *)pioctl_buf->pbuf;
+ cfg = (struct mfg_cmd_tx_frame2 *)&misc->param.mfg_tx_frame2;
+
+ cfg->error = wlan_le32_to_cpu(mcmd->error);
+ cfg->enable = wlan_le32_to_cpu(mcmd->enable);
+ cfg->data_rate = wlan_le32_to_cpu(mcmd->data_rate);
+ cfg->frame_pattern = wlan_le32_to_cpu(mcmd->frame_pattern);
+ cfg->frame_length = wlan_le32_to_cpu(mcmd->frame_length);
+ cfg->adjust_burst_sifs = wlan_le16_to_cpu(mcmd->adjust_burst_sifs);
+ cfg->burst_sifs_in_us = wlan_le32_to_cpu(mcmd->burst_sifs_in_us);
+ cfg->short_preamble = wlan_le32_to_cpu(mcmd->short_preamble);
+ cfg->act_sub_ch = wlan_le32_to_cpu(mcmd->act_sub_ch);
+ cfg->short_gi = wlan_le32_to_cpu(mcmd->short_gi);
+ cfg->tx_bf = wlan_le32_to_cpu(mcmd->tx_bf);
+ cfg->gf_mode = wlan_le32_to_cpu(mcmd->gf_mode);
+ cfg->stbc = wlan_le32_to_cpu(mcmd->stbc);
+ memcpy_ext(pmpriv->adapter, cfg->bssid, mcmd->bssid,
+ MLAN_MAC_ADDR_LENGTH, sizeof(cfg->bssid));
+
+ LEAVE();
+ return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ * @brief This function prepares command resp of MFG Cmd
+ *
+ * @param pmpriv A pointer to mlan_private structure
+ * @param resp A pointer to HostCmd_DS_COMMAND
+ * @param pioctl_buf A pointer to mlan_ioctl_req structure
+ *
+ * @return MLAN_STATUS_SUCCESS
+ */
+mlan_status wlan_ret_mfg(pmlan_private pmpriv, HostCmd_DS_COMMAND *resp,
+ mlan_ioctl_req *pioctl_buf)
+{
+ mlan_ds_misc_cfg *misc = MNULL;
+ struct mfg_cmd_generic_cfg *mcmd =
+ (struct mfg_cmd_generic_cfg *)&resp->params.mfg_generic_cfg;
+ struct mfg_cmd_generic_cfg *cfg = MNULL;
+ mlan_status ret = MLAN_STATUS_SUCCESS;
+
+ ENTER();
+ if (!pioctl_buf) {
+ LEAVE();
+ return MLAN_STATUS_FAILURE;
+ }
+ switch (wlan_le32_to_cpu(mcmd->mfg_cmd)) {
+ case MFG_CMD_TX_CONT:
+ ret = wlan_ret_mfg_tx_cont(pmpriv, resp, pioctl_buf);
+ goto cmd_mfg_done;
+ case MFG_CMD_TX_FRAME:
+ ret = wlan_ret_mfg_tx_frame(pmpriv, resp, pioctl_buf);
+ goto cmd_mfg_done;
+ case MFG_CMD_SET_TEST_MODE:
+ case MFG_CMD_UNSET_TEST_MODE:
+ case MFG_CMD_TX_ANT:
+ case MFG_CMD_RX_ANT:
+ case MFG_CMD_RF_CHAN:
+ case MFG_CMD_CLR_RX_ERR:
+ case MFG_CMD_RF_BAND_AG:
+ case MFG_CMD_RF_CHANNELBW:
+ case MFG_CMD_RFPWR:
+ break;
+ default:
+ ret = MLAN_STATUS_FAILURE;
+ goto cmd_mfg_done;
+ }
+ misc = (mlan_ds_misc_cfg *)pioctl_buf->pbuf;
+ cfg = (struct mfg_cmd_generic_cfg *)&misc->param.mfg_generic_cfg;
+
+ cfg->error = wlan_le32_to_cpu(mcmd->error);
+ cfg->data1 = wlan_le32_to_cpu(mcmd->data1);
+ cfg->data2 = wlan_le32_to_cpu(mcmd->data2);
+ cfg->data3 = wlan_le32_to_cpu(mcmd->data3);
+cmd_mfg_done:
+ LEAVE();
+ return ret;
+}
+
+/**
+ * @brief This function handles the station command response
+ *
+ * @param priv A pointer to mlan_private structure
+ * @param cmdresp_no cmd no
+ * @param pcmd_buf cmdresp buf
+ * @param pioctl A pointer to ioctl buf
+ *
+ * @return MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ */
+mlan_status wlan_ops_sta_process_cmdresp(t_void *priv, t_u16 cmdresp_no,
+ t_void *pcmd_buf, t_void *pioctl)
+{
+ mlan_status ret = MLAN_STATUS_SUCCESS;
+ mlan_private *pmpriv = (mlan_private *)priv;
+ HostCmd_DS_COMMAND *resp = (HostCmd_DS_COMMAND *)pcmd_buf;
+ mlan_ioctl_req *pioctl_buf = (mlan_ioctl_req *)pioctl;
+
+ mlan_adapter *pmadapter = pmpriv->adapter;
+#ifdef SDIO
+ int ctr;
+#endif
+
+ ENTER();
+
+ /* If the command is not successful, cleanup and return failure */
+ if ((resp->result != HostCmd_RESULT_OK)) {
+ ret = wlan_process_cmdresp_error(pmpriv, resp, pioctl_buf);
+ LEAVE();
+ return ret;
+ }
+ /* Command successful, handle response */
+ switch (cmdresp_no) {
+ case HostCmd_CMD_GET_HW_SPEC:
+ ret = wlan_ret_get_hw_spec(pmpriv, resp, pioctl_buf);
+ break;
+#ifdef SDIO
+ case HostCmd_CMD_SDIO_SP_RX_AGGR_CFG:
+ ret = wlan_ret_sdio_rx_aggr_cfg(pmpriv, resp);
+ break;
+#endif
+ case HostCmd_CMD_CFG_DATA:
+ ret = wlan_ret_cfg_data(pmpriv, resp, pioctl_buf);
+ break;
+ case HostCmd_CMD_MAC_CONTROL:
+ ret = wlan_ret_mac_control(pmpriv, resp, pioctl_buf);
+ break;
+ case HostCmd_CMD_802_11_MAC_ADDRESS:
+ ret = wlan_ret_802_11_mac_address(pmpriv, resp, pioctl_buf);
+ break;
+ case HostCmd_CMD_MAC_MULTICAST_ADR:
+ ret = wlan_ret_mac_multicast_adr(pmpriv, resp, pioctl_buf);
+ break;
+ case HostCmd_CMD_TX_RATE_CFG:
+ ret = wlan_ret_tx_rate_cfg(pmpriv, resp, pioctl_buf);
+ break;
+ case HostCmd_CMD_802_11_SCAN:
+ ret = wlan_ret_802_11_scan(pmpriv, resp, pioctl_buf);
+ pioctl_buf = MNULL;
+ pmadapter->curr_cmd->pioctl_buf = MNULL;
+ break;
+ case HostCmd_CMD_802_11_SCAN_EXT:
+ ret = wlan_ret_802_11_scan_ext(pmpriv, resp, pioctl_buf);
+ pioctl_buf = MNULL;
+ pmadapter->curr_cmd->pioctl_buf = MNULL;
+ break;
+ case HostCmd_CMD_802_11_BG_SCAN_CONFIG:
+ ret = wlan_ret_bgscan_config(pmpriv, resp, pioctl_buf);
+ break;
+ case HostCmd_CMD_802_11_BG_SCAN_QUERY:
+ ret = wlan_ret_802_11_bgscan_query(pmpriv, resp, pioctl_buf);
+ wlan_recv_event(pmpriv, MLAN_EVENT_ID_DRV_BGSCAN_RESULT, MNULL);
+ PRINTM(MINFO, "CMD_RESP: BG_SCAN result is ready!\n");
+ break;
+ case HostCmd_CMD_TXPWR_CFG:
+ ret = wlan_ret_tx_power_cfg(pmpriv, resp, pioctl_buf);
+ break;
+
+ case HostCmd_CMD_802_11_RF_TX_POWER:
+ ret = wlan_ret_802_11_rf_tx_power(pmpriv, resp, pioctl_buf);
+ break;
+
+ case HostCmd_CMD_802_11_PS_MODE_ENH:
+ ret = wlan_ret_enh_power_mode(pmpriv, resp, pioctl_buf);
+ break;
+ case HostCmd_CMD_802_11_HS_CFG_ENH:
+ ret = wlan_ret_802_11_hs_cfg(pmpriv, resp, pioctl_buf);
+ break;
+ case HostCmd_CMD_802_11_SLEEP_PERIOD:
+ ret = wlan_ret_802_11_sleep_period(pmpriv, resp, pioctl_buf);
+ break;
+ case HostCmd_CMD_802_11_SLEEP_PARAMS:
+ ret = wlan_ret_802_11_sleep_params(pmpriv, resp, pioctl_buf);
+ break;
+ case HostCmd_CMD_802_11_ROBUSTCOEX:
+ break;
+ case HostCmd_CMD_DMCS_CONFIG:
+ ret = wlan_ret_dmcs_config(pmpriv, resp, pioctl_buf);
+ break;
+#if defined(PCIE)
+ case HostCmd_CMD_SSU:
+ PRINTM(MCMND,
+ "SSU cmdresp:number_of_buffers %d, buffer_size %d rec_len %d\n",
+ resp->params.ssu_params.number_of_buffers,
+ resp->params.ssu_params.buffer_size,
+ resp->params.ssu_params.rec_len);
+ break;
+#endif
+ case HostCmd_CMD_802_11_ASSOCIATE:
+ ret = wlan_ret_802_11_associate(pmpriv, resp, pioctl_buf);
+ break;
+ case HostCmd_CMD_802_11_DEAUTHENTICATE:
+ case HostCmd_CMD_802_11_DISASSOCIATE:
+ ret = wlan_ret_802_11_deauthenticate(pmpriv, resp, pioctl_buf);
+ break;
+ case HostCmd_CMD_802_11_AD_HOC_START:
+ case HostCmd_CMD_802_11_AD_HOC_JOIN:
+ ret = wlan_ret_802_11_ad_hoc(pmpriv, resp, pioctl_buf);
+ break;
+ case HostCmd_CMD_802_11_AD_HOC_STOP:
+ ret = wlan_ret_802_11_ad_hoc_stop(pmpriv, resp, pioctl_buf);
+ break;
+ case HostCmd_CMD_802_11_GET_LOG:
+ ret = wlan_ret_get_log(pmpriv, resp, pioctl_buf);
+ break;
+ case HostCmd_CMD_802_11_LINK_STATS:
+ ret = wlan_ret_get_link_statistic(pmpriv, resp, pioctl_buf);
+ break;
+ case HostCmd_CMD_RSSI_INFO_EXT:
+ ret = wlan_ret_802_11_rssi_info_ext(pmpriv, resp, pioctl_buf);
+ break;
+ case HostCmd_CMD_RSSI_INFO:
+ ret = wlan_ret_802_11_rssi_info(pmpriv, resp, pioctl_buf);
+ break;
+ case HostCmd_CMD_802_11_SNMP_MIB:
+ ret = wlan_ret_802_11_snmp_mib(pmpriv, resp, pioctl_buf);
+ break;
+ case HostCmd_CMD_802_11_RADIO_CONTROL:
+ ret = wlan_ret_802_11_radio_control(pmpriv, resp, pioctl_buf);
+ break;
+ case HostCmd_CMD_802_11_TX_RATE_QUERY:
+ ret = wlan_ret_802_11_tx_rate_query(pmpriv, resp, pioctl_buf);
+ break;
+ case HostCmd_CMD_802_11_RF_CHANNEL:
+ ret = wlan_ret_802_11_rf_channel(pmpriv, resp, pioctl_buf);
+ break;
+ case HostCmd_CMD_802_11_RF_ANTENNA:
+ ret = wlan_ret_802_11_rf_antenna(pmpriv, resp, pioctl_buf);
+ break;
+ case HostCmd_CMD_CW_MODE_CTRL:
+ ret = wlan_ret_cw_mode_ctrl(pmpriv, resp, pioctl_buf);
+ break;
+ case HostCmd_CMD_VERSION_EXT:
+ ret = wlan_ret_ver_ext(pmpriv, resp, pioctl_buf);
+ break;
+ case HostCmd_CMD_RX_MGMT_IND:
+ ret = wlan_ret_rx_mgmt_ind(pmpriv, resp, pioctl_buf);
+ break;
+ case HostCmd_CMD_FUNC_INIT:
+ case HostCmd_CMD_FUNC_SHUTDOWN:
+ break;
+ case HostCmd_CMD_802_11_KEY_MATERIAL:
+ ret = wlan_ret_802_11_key_material(pmpriv, resp, pioctl_buf);
+ break;
+ case HostCmd_CMD_GTK_REKEY_OFFLOAD_CFG:
+ break;
+ case HostCmd_CMD_SUPPLICANT_PMK:
+ ret = wlan_ret_802_11_supplicant_pmk(pmpriv, resp, pioctl_buf);
+ break;
+ case HostCmd_CMD_SUPPLICANT_PROFILE:
+ ret = wlan_ret_802_11_supplicant_profile(pmpriv, resp,
+ pioctl_buf);
+ break;
+ case HostCmd_CMD_802_11_EAPOL_PKT:
+ break;
+ case HostCmd_CMD_802_11D_DOMAIN_INFO:
+ ret = wlan_ret_802_11d_domain_info(pmpriv, resp);
+ break;
+ case HostCmd_CMD_802_11_TPC_ADAPT_REQ:
+ case HostCmd_CMD_802_11_TPC_INFO:
+ case HostCmd_CMD_802_11_CHAN_SW_ANN:
+ case HostCmd_CMD_CHAN_REPORT_REQUEST:
+ ret = wlan_11h_cmdresp_process(pmpriv, resp);
+ break;
+ case HostCmd_CMD_11N_ADDBA_REQ:
+ ret = wlan_ret_11n_addba_req(pmpriv, resp);
+ break;
+ case HostCmd_CMD_11N_DELBA:
+ ret = wlan_ret_11n_delba(pmpriv, resp);
+ break;
+ case HostCmd_CMD_11N_ADDBA_RSP:
+ ret = wlan_ret_11n_addba_resp(pmpriv, resp);
+ break;
+ case HostCmd_CMD_RECONFIGURE_TX_BUFF:
+ wlan_set_tx_pause_flag(pmpriv, MFALSE);
+
+ pmadapter->tx_buf_size =
+ (t_u16)wlan_le16_to_cpu(resp->params.tx_buf.buff_size);
+#ifdef SDIO
+ if (IS_SD(pmadapter->card_type)) {
+ pmadapter->tx_buf_size = (pmadapter->tx_buf_size /
+ MLAN_SDIO_BLOCK_SIZE) *
+ MLAN_SDIO_BLOCK_SIZE;
+ pmadapter->pcard_sd->mp_end_port = wlan_le16_to_cpu(
+ resp->params.tx_buf.mp_end_port);
+ pmadapter->pcard_sd->mp_data_port_mask =
+ pmadapter->pcard_sd->reg->data_port_mask;
+
+ for (ctr = 1;
+ ctr <= MAX_PORT - pmadapter->pcard_sd->mp_end_port;
+ ctr++) {
+ pmadapter->pcard_sd->mp_data_port_mask &=
+ ~(1 << (MAX_PORT - ctr));
+ }
+
+ pmadapter->pcard_sd->curr_wr_port = 0;
+ pmadapter->pcard_sd->mpa_tx.pkt_aggr_limit =
+ MIN(SDIO_MP_AGGR_DEF_PKT_LIMIT,
+ (pmadapter->pcard_sd->mp_end_port >> 1));
+ PRINTM(MCMND, "end port %d, data port mask %x\n",
+ wlan_le16_to_cpu(
+ resp->params.tx_buf.mp_end_port),
+ pmadapter->pcard_sd->mp_data_port_mask);
+ }
+#endif
+ pmadapter->curr_tx_buf_size = pmadapter->tx_buf_size;
+ PRINTM(MCMND, "max_tx_buf_size=%d, tx_buf_size=%d\n",
+ pmadapter->max_tx_buf_size, pmadapter->tx_buf_size);
+ break;
+ case HostCmd_CMD_AMSDU_AGGR_CTRL:
+ ret = wlan_ret_amsdu_aggr_ctrl(pmpriv, resp, pioctl_buf);
+ break;
+ case HostCmd_CMD_WMM_GET_STATUS:
+ ret = wlan_ret_wmm_get_status(
+ pmpriv, resp->params.get_wmm_status.queue_status_tlv,
+ resp->size - S_DS_GEN);
+ break;
+ case HostCmd_CMD_WMM_ADDTS_REQ:
+ ret = wlan_ret_wmm_addts_req(pmpriv, resp, pioctl_buf);
+ break;
+ case HostCmd_CMD_WMM_DELTS_REQ:
+ ret = wlan_ret_wmm_delts_req(pmpriv, resp, pioctl_buf);
+ break;
+ case HostCmd_CMD_WMM_QUEUE_CONFIG:
+ ret = wlan_ret_wmm_queue_config(pmpriv, resp, pioctl_buf);
+ break;
+ case HostCmd_CMD_WMM_QUEUE_STATS:
+ ret = wlan_ret_wmm_queue_stats(pmpriv, resp, pioctl_buf);
+ break;
+ case HostCmd_CMD_WMM_TS_STATUS:
+ ret = wlan_ret_wmm_ts_status(pmpriv, resp, pioctl_buf);
+ break;
+ case HostCmd_CMD_WMM_PARAM_CONFIG:
+ ret = wlan_ret_wmm_param_config(pmpriv, resp, pioctl_buf);
+ break;
+ case HostCmd_CMD_802_11_IBSS_COALESCING_STATUS:
+ ret = wlan_ret_ibss_coalescing_status(pmpriv, resp);
+ break;
+ case HostCmd_CMD_MGMT_IE_LIST:
+ ret = wlan_ret_mgmt_ie_list(pmpriv, resp, pioctl_buf);
+ break;
+ case HostCmd_CMD_11N_CFG:
+ ret = wlan_ret_11n_cfg(pmpriv, resp, pioctl_buf);
+ break;
+ case HostCmd_CMD_11AC_CFG:
+ ret = wlan_ret_11ac_cfg(pmpriv, resp, pioctl_buf);
+ break;
+#if 0
+ case HostCmd_CMD_RECONFIGURE_TX_BUFF:
+ pmadapter->tx_buf_size = (t_u16)wlan_le16_to_cpu(resp->params.
+ tx_buf.buff_size);
+ break;
+#endif
+ case HostCmd_CMD_TX_BF_CFG:
+ ret = wlan_ret_tx_bf_cfg(pmpriv, resp, pioctl_buf);
+ break;
+ case HostCmd_CMD_ECL_SYSTEM_CLOCK_CONFIG:
+ ret = wlan_ret_sysclock_cfg(pmpriv, resp, pioctl_buf);
+ break;
+ case HostCmd_CMD_MAC_REG_ACCESS:
+ case HostCmd_CMD_BBP_REG_ACCESS:
+ case HostCmd_CMD_RF_REG_ACCESS:
+ case HostCmd_CMD_CAU_REG_ACCESS:
+ case HostCmd_CMD_TARGET_ACCESS:
+ case HostCmd_CMD_802_11_EEPROM_ACCESS:
+ case HostCmd_CMD_BCA_REG_ACCESS:
+ ret = wlan_ret_reg_access(pmpriv->adapter, cmdresp_no, resp,
+ pioctl_buf);
+ break;
+ case HostCmd_CMD_MEM_ACCESS:
+ ret = wlan_ret_mem_access(pmpriv, resp, pioctl_buf);
+ break;
+ case HostCmd_CMD_INACTIVITY_TIMEOUT_EXT:
+ ret = wlan_ret_inactivity_timeout(pmpriv, resp, pioctl_buf);
+ break;
+#if defined(SDIO)
+ case HostCmd_CMD_SDIO_GPIO_INT_CONFIG:
+ break;
+#endif
+ case HostCmd_CMD_SET_BSS_MODE:
+ break;
+ case HostCmd_CMD_MEASUREMENT_REQUEST:
+ case HostCmd_CMD_MEASUREMENT_REPORT:
+ ret = wlan_meas_cmdresp_process(pmpriv, resp);
+ break;
+#if defined(PCIE)
+#if defined(PCIE8997) || defined(PCIE8897)
+ case HostCmd_CMD_PCIE_HOST_BUF_DETAILS:
+ PRINTM(MINFO, "PCIE host buffer configuration successful.\n");
+ break;
+#endif
+#endif
+ case HostCmd_CMD_802_11_REMAIN_ON_CHANNEL:
+ ret = wlan_ret_remain_on_channel(pmpriv, resp, pioctl_buf);
+ break;
+#ifdef WIFI_DIRECT_SUPPORT
+ case HOST_CMD_WIFI_DIRECT_MODE_CONFIG:
+ ret = wlan_ret_wifi_direct_mode(pmpriv, resp, pioctl_buf);
+ break;
+#endif
+ case HostCmd_CMD_802_11_SUBSCRIBE_EVENT:
+ ret = wlan_ret_subscribe_event(pmpriv, resp, pioctl_buf);
+ break;
+ case HostCmd_CMD_OTP_READ_USER_DATA:
+ ret = wlan_ret_otp_user_data(pmpriv, resp, pioctl_buf);
+ break;
+ case HostCmd_CMD_HS_WAKEUP_REASON:
+ ret = wlan_ret_hs_wakeup_reason(pmpriv, resp, pioctl_buf);
+ break;
+ case HostCmd_CMD_REJECT_ADDBA_REQ:
+ ret = wlan_ret_reject_addba_req(pmpriv, resp, pioctl_buf);
+ break;
+ case HostCmd_CMD_PACKET_AGGR_CTRL:
+ ret = wlan_ret_packet_aggr_ctrl(pmpriv, resp, pioctl_buf);
+ break;
+#ifdef USB
+ case HostCmd_CMD_PACKET_AGGR_OVER_HOST_INTERFACE:
+ ret = wlan_ret_packet_aggr_over_host_interface(pmpriv, resp,
+ pioctl_buf);
+ break;
+#endif
+#ifdef RX_PACKET_COALESCE
+ case HostCmd_CMD_RX_PKT_COALESCE_CFG:
+ ret = wlan_ret_rx_pkt_coalesce_cfg(pmpriv, resp, pioctl_buf);
+ break;
+#endif
+ case HostCMD_CONFIG_LOW_POWER_MODE:
+ break;
+ case HostCmd_DFS_REPEATER_MODE:
+ ret = wlan_ret_dfs_repeater_cfg(pmpriv, resp, pioctl_buf);
+ break;
+ case HostCmd_CMD_COALESCE_CFG:
+ ret = wlan_ret_coalesce_config(pmpriv, resp, pioctl_buf);
+ break;
+ case HostCmd_CMD_MEF_CFG:
+ break;
+ case HostCmd_DS_GET_SENSOR_TEMP:
+ ret = wlan_ret_get_sensor_temp(pmpriv, resp, pioctl_buf);
+ break;
+ case HostCmd_CMD_802_11_MIMO_SWITCH:
+ break;
+ case HostCmd_CMD_STA_CONFIGURE:
+ ret = wlan_ret_sta_config(pmpriv, resp, pioctl_buf);
+ break;
+ case HOST_CMD_PMIC_CONFIGURE:
+ break;
+ case HostCmd_CMD_INDEPENDENT_RESET_CFG:
+ ret = wlan_ret_ind_rst_cfg(pmpriv, resp, pioctl_buf);
+ break;
+ case HostCmd_CMD_802_11_PS_INACTIVITY_TIMEOUT:
+ break;
+ case HostCmd_CMD_GET_TSF:
+ ret = wlan_ret_get_tsf(pmpriv, resp, pioctl_buf);
+ break;
+ case HostCmd_CMD_CHAN_REGION_CFG:
+ ret = wlan_ret_chan_region_cfg(pmpriv, resp, pioctl_buf);
+ break;
+ case HostCmd_CMD_AUTO_TX:
+ ret = wlan_ret_auto_tx(pmpriv, resp, pioctl_buf);
+ break;
+ case HOST_CMD_TX_RX_PKT_STATS:
+ ret = wlan_ret_tx_rx_pkt_stats(pmpriv, resp, pioctl_buf);
+ break;
+ case HostCmd_CMD_DYN_BW:
+ ret = wlan_ret_dyn_bw(pmpriv, resp, pioctl_buf);
+ break;
+ case HostCmd_CMD_BOOT_SLEEP:
+ ret = wlan_ret_boot_sleep(pmpriv, resp, pioctl_buf);
+ break;
+#if defined(DRV_EMBEDDED_SUPPLICANT)
+ case HostCmd_CMD_CRYPTO:
+ ret = wlan_ret_crypto(pmpriv, resp, pioctl_buf);
+ break;
+#endif
+ case HostCmd_CMD_11AX_CFG:
+ ret = wlan_ret_11ax_cfg(pmpriv, resp, pioctl_buf);
+ break;
+ case HostCmd_CMD_11AX_CMD:
+ ret = wlan_ret_11ax_cmd(pmpriv, resp, pioctl_buf);
+ break;
+ case HostCmd_CMD_RANGE_EXT:
+ ret = wlan_ret_range_ext(pmpriv, resp, pioctl_buf);
+ break;
+ case HostCmd_CMD_TWT_CFG:
+ break;
+ case HostCmd_CMD_RX_ABORT_CFG:
+ ret = wlan_ret_rxabortcfg(pmpriv, resp, pioctl_buf);
+ break;
+ case HostCmd_CMD_RX_ABORT_CFG_EXT:
+ ret = wlan_ret_rxabortcfg_ext(pmpriv, resp, pioctl_buf);
+ break;
+ case HostCmd_CMD_ARB_CONFIG:
+ ret = wlan_ret_arb_cfg(pmpriv, resp, pioctl_buf);
+ break;
+ case HostCmd_CMD_TX_AMPDU_PROT_MODE:
+ ret = wlan_ret_tx_ampdu_prot_mode(pmpriv, resp, pioctl_buf);
+ break;
+ case HostCmd_CMD_DOT11MC_UNASSOC_FTM_CFG:
+ ret = wlan_ret_dot11mc_unassoc_ftm_cfg(pmpriv, resp,
+ pioctl_buf);
+ break;
+ case HostCmd_CMD_RATE_ADAPT_CFG:
+ ret = wlan_ret_rate_adapt_cfg(pmpriv, resp, pioctl_buf);
+ break;
+ case HostCmd_CMD_CCK_DESENSE_CFG:
+ ret = wlan_ret_cck_desense_cfg(pmpriv, resp, pioctl_buf);
+ break;
+ case HostCmd_CHANNEL_TRPC_CONFIG:
+ ret = wlan_ret_get_chan_trpc_config(pmpriv, resp, pioctl_buf);
+ break;
+ case HostCmd_CMD_LOW_POWER_MODE_CFG:
+ ret = wlan_ret_set_get_low_power_mode_cfg(pmpriv, resp,
+ pioctl_buf);
+ break;
+ case HostCmd_CMD_MFG_COMMAND:
+ ret = wlan_ret_mfg(pmpriv, resp, pioctl_buf);
+ break;
+ default:
+ PRINTM(MERROR, "CMD_RESP: Unknown command response %#x\n",
+ resp->command);
+ break;
+ }
+
+ LEAVE();
+ return ret;
+}
diff --git a/drivers/net/wireless/nxp/mxm_wifiex/wlan_src/mlan/mlan_sta_event.c b/drivers/net/wireless/nxp/mxm_wifiex/wlan_src/mlan/mlan_sta_event.c
new file mode 100644
index 000000000000..cc96e9ac7e12
--- /dev/null
+++ b/drivers/net/wireless/nxp/mxm_wifiex/wlan_src/mlan/mlan_sta_event.c
@@ -0,0 +1,1026 @@
+/** @file mlan_sta_event.c
+ *
+ * @brief This file contains MLAN event handling.
+ *
+ *
+ * Copyright 2014-2020 NXP
+ *
+ * This software file (the File) is distributed by NXP
+ * under the terms of the GNU General Public License Version 2, June 1991
+ * (the License). You may use, redistribute and/or modify the 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.
+ *
+ */
+
+/********************************************************
+Change log:
+ 10/13/2008: initial version
+********************************************************/
+
+#include "mlan.h"
+#include "mlan_join.h"
+#include "mlan_util.h"
+#include "mlan_fw.h"
+#include "mlan_main.h"
+#include "mlan_wmm.h"
+#include "mlan_11n.h"
+#include "mlan_11h.h"
+#ifdef DRV_EMBEDDED_SUPPLICANT
+#include "authenticator_api.h"
+#endif
+#ifdef PCIE
+#include "mlan_pcie.h"
+#endif /* PCIE */
+
+/********************************************************
+ Global Variables
+********************************************************/
+
+/********************************************************
+ Local Functions
+********************************************************/
+
+/**
+ * @brief This function handles link lost, deauth and
+ * disassoc events.
+ *
+ * @param pmpriv A pointer to mlan_private structure
+ * @return N/A
+ */
+static t_void wlan_handle_disconnect_event(pmlan_private pmpriv)
+{
+ ENTER();
+
+ if (pmpriv->media_connected == MTRUE)
+ wlan_reset_connect_state(pmpriv, MTRUE);
+
+ LEAVE();
+}
+
+/********************************************************
+ Global Functions
+********************************************************/
+/**
+ * @brief This function handles disconnect event, reports disconnect
+ * to upper layer, cleans tx/rx packets,
+ * resets link state etc.
+ *
+ * @param priv A pointer to mlan_private structure
+ * @param drv_disconnect Flag indicating the driver should disconnect
+ * and flush pending packets.
+ *
+ * @return N/A
+ */
+t_void wlan_reset_connect_state(pmlan_private priv, t_u8 drv_disconnect)
+{
+ mlan_adapter *pmadapter = priv->adapter;
+ mlan_status ret = MLAN_STATUS_SUCCESS;
+ state_11d_t enable;
+ t_u8 event_buf[100];
+ mlan_event *pevent = (mlan_event *)event_buf;
+
+ ENTER();
+
+ PRINTM(MINFO, "Handles disconnect event.\n");
+
+#ifdef UAP_SUPPORT
+ /* If DFS repeater mode is enabled and station interface disconnects
+ * then make sure that all uAPs are stopped.
+ */
+ if (pmadapter->dfs_repeater)
+ wlan_dfs_rep_disconnect(pmadapter);
+#endif
+
+ if (drv_disconnect) {
+ priv->media_connected = MFALSE;
+ pmadapter->state_rdh.tx_block = MFALSE;
+ wlan_11h_check_update_radar_det_state(priv);
+ }
+
+ if (priv->port_ctrl_mode == MTRUE) {
+ /* Close the port on Disconnect */
+ PRINTM(MINFO, "DISC: port_status = CLOSED\n");
+ priv->port_open = MFALSE;
+ }
+ memset(pmadapter, &priv->gtk_rekey, 0,
+ sizeof(mlan_ds_misc_gtk_rekey_data));
+ priv->tx_pause = MFALSE;
+ pmadapter->scan_block = MFALSE;
+
+ /* 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_rate_info = 0;
+ priv->max_amsdu = 0;
+ priv->amsdu_disable = MFALSE;
+ wlan_coex_ampdu_rxwinsize(pmadapter);
+
+ priv->sec_info.ewpa_enabled = MFALSE;
+ priv->sec_info.wpa_enabled = MFALSE;
+ priv->sec_info.wpa2_enabled = MFALSE;
+ priv->wpa_ie_len = 0;
+#ifdef DRV_EMBEDDED_SUPPLICANT
+ supplicantStopSessionTimer(priv->psapriv);
+ supplicantClrEncryptKey(priv->psapriv);
+ supplicantDisable(priv->psapriv);
+#endif
+
+ priv->sec_info.wapi_enabled = MFALSE;
+ priv->wapi_ie_len = 0;
+ priv->sec_info.wapi_key_on = MFALSE;
+
+ priv->wps.session_enable = MFALSE;
+ memset(priv->adapter, (t_u8 *)&priv->wps.wps_ie, 0x00,
+ sizeof(priv->wps.wps_ie));
+ priv->sec_info.osen_enabled = MFALSE;
+ priv->osen_ie_len = 0;
+
+ priv->sec_info.encryption_mode = MLAN_ENCRYPTION_MODE_NONE;
+
+ /*Enable auto data rate */
+ priv->is_data_rate_auto = MTRUE;
+ priv->data_rate = 0;
+
+ if (priv->bss_mode == MLAN_BSS_MODE_IBSS) {
+ priv->adhoc_state = ADHOC_IDLE;
+ priv->adhoc_is_link_sensed = MFALSE;
+ priv->intf_state_11h.adhoc_auto_sel_chan = MTRUE;
+ }
+
+ if (drv_disconnect) {
+ /* Free Tx and Rx packets, report disconnect to upper layer */
+ wlan_clean_txrx(priv);
+
+ /* Need to erase the current SSID and BSSID info */
+ memset(pmadapter, &priv->curr_bss_params, 0x00,
+ sizeof(priv->curr_bss_params));
+ }
+ pmadapter->tx_lock_flag = MFALSE;
+ pmadapter->pps_uapsd_mode = MFALSE;
+ pmadapter->delay_null_pkt = MFALSE;
+ if (priv->bss_type == MLAN_BSS_TYPE_STA)
+ pmadapter->hs_wake_interval = 0;
+
+ if ((wlan_fw_11d_is_enabled(priv)) &&
+ (priv->state_11d.user_enable_11d == DISABLE_11D)) {
+ priv->state_11d.enable_11d = DISABLE_11D;
+ enable = DISABLE_11D;
+
+ /* Send cmd to FW to enable/disable 11D function */
+ ret = wlan_prepare_cmd(priv, HostCmd_CMD_802_11_SNMP_MIB,
+ HostCmd_ACT_GEN_SET, Dot11D_i, MNULL,
+ &enable);
+ if (ret)
+ PRINTM(MERROR, "11D: Failed to enable 11D\n");
+ }
+ if (pmadapter->num_cmd_timeout && pmadapter->curr_cmd &&
+ (pmadapter->cmd_timer_is_set == MFALSE)) {
+ LEAVE();
+ return;
+ }
+
+ pevent->bss_index = priv->bss_index;
+ pevent->event_id = MLAN_EVENT_ID_FW_DISCONNECTED;
+ pevent->event_len = sizeof(priv->disconnect_reason_code);
+ memcpy_ext(priv->adapter, pevent->event_buf,
+ &priv->disconnect_reason_code, pevent->event_len,
+ pevent->event_len);
+ wlan_recv_event(priv, MLAN_EVENT_ID_FW_DISCONNECTED, pevent);
+ priv->disconnect_reason_code = 0;
+
+ LEAVE();
+}
+
+/**
+ * @brief This function sends the OBSS scan parameters to the application
+ *
+ * @param pmpriv A pointer to mlan_private structure
+ *
+ * @return N/A
+ */
+t_void wlan_2040_coex_event(pmlan_private pmpriv)
+{
+ t_u8 event_buf[100];
+ mlan_event *pevent = (mlan_event *)event_buf;
+ t_u8 ele_len;
+
+ ENTER();
+
+ if (pmpriv->curr_bss_params.bss_descriptor.poverlap_bss_scan_param &&
+ pmpriv->curr_bss_params.bss_descriptor.poverlap_bss_scan_param
+ ->ieee_hdr.element_id == OVERLAPBSSSCANPARAM) {
+ ele_len = pmpriv->curr_bss_params.bss_descriptor
+ .poverlap_bss_scan_param->ieee_hdr.len;
+ pevent->bss_index = pmpriv->bss_index;
+ pevent->event_id = MLAN_EVENT_ID_DRV_OBSS_SCAN_PARAM;
+ pevent->event_len = ele_len;
+ /* Copy OBSS scan parameters */
+ memcpy_ext(pmpriv->adapter, (t_u8 *)pevent->event_buf,
+ (t_u8 *)&pmpriv->curr_bss_params.bss_descriptor
+ .poverlap_bss_scan_param->obss_scan_param,
+ ele_len, pevent->event_len);
+ wlan_recv_event(pmpriv, MLAN_EVENT_ID_DRV_OBSS_SCAN_PARAM,
+ pevent);
+ }
+
+ LEAVE();
+}
+
+/**
+ * @brief This function will process tx pause event
+ *
+ * @param priv A pointer to mlan_private
+ * @param pevent A pointer to event buf
+ *
+ * @return N/A
+ */
+static void wlan_process_sta_tx_pause_event(pmlan_private priv,
+ pmlan_buffer pevent)
+{
+ t_u16 tlv_type, tlv_len;
+ int tlv_buf_left = pevent->data_len - sizeof(t_u32);
+ MrvlIEtypesHeader_t *tlv =
+ (MrvlIEtypesHeader_t *)(pevent->pbuf + pevent->data_offset +
+ sizeof(t_u32));
+ MrvlIEtypes_tx_pause_t *tx_pause_tlv;
+ t_u8 *bssid = MNULL;
+ ENTER();
+ if (priv->media_connected)
+ bssid = priv->curr_bss_params.bss_descriptor.mac_address;
+ while (tlv_buf_left >= (int)sizeof(MrvlIEtypesHeader_t)) {
+ tlv_type = wlan_le16_to_cpu(tlv->type);
+ tlv_len = wlan_le16_to_cpu(tlv->len);
+ if ((sizeof(MrvlIEtypesHeader_t) + tlv_len) >
+ (unsigned int)tlv_buf_left) {
+ PRINTM(MERROR, "wrong tlv: tlvLen=%d, tlvBufLeft=%d\n",
+ tlv_len, tlv_buf_left);
+ break;
+ }
+ if (tlv_type == TLV_TYPE_TX_PAUSE) {
+ tx_pause_tlv = (MrvlIEtypes_tx_pause_t *)tlv;
+ PRINTM(MCMND, "TxPause: " MACSTR " pause=%d, pkts=%d\n",
+ MAC2STR(tx_pause_tlv->peermac),
+ tx_pause_tlv->tx_pause, tx_pause_tlv->pkt_cnt);
+
+ if (bssid &&
+ !memcmp(priv->adapter, bssid, tx_pause_tlv->peermac,
+ MLAN_MAC_ADDR_LENGTH)) {
+ if (tx_pause_tlv->tx_pause)
+ priv->tx_pause = MTRUE;
+ else
+ priv->tx_pause = MFALSE;
+ }
+ }
+ tlv_buf_left -= (sizeof(MrvlIEtypesHeader_t) + tlv_len);
+ tlv = (MrvlIEtypesHeader_t *)((t_u8 *)tlv + tlv_len +
+ sizeof(MrvlIEtypesHeader_t));
+ }
+
+ LEAVE();
+ return;
+}
+
+/**
+ * @brief This function will print diconnect reason code according
+ * to IEEE 802.11 spec
+ *
+ * @param reason_code reason code for the deauth/disaccoc
+ * received from firmware
+ * @return N/A
+ */
+static void wlan_print_disconnect_reason(t_u16 reason_code)
+{
+ ENTER();
+
+ switch (reason_code) {
+ case MLAN_REASON_UNSPECIFIED:
+ PRINTM(MMSG, "wlan: REASON: Unspecified reason\n");
+ break;
+ case MLAN_REASON_PREV_AUTH_NOT_VALID:
+ PRINTM(MMSG,
+ "wlan: REASON: Previous authentication no longer valid\n");
+ break;
+ case MLAN_REASON_DEAUTH_LEAVING:
+ PRINTM(MMSG,
+ "wlan: REASON: (Deauth) Sending STA is leaving (or has left) IBSS or ESS\n");
+ break;
+ case MLAN_REASON_DISASSOC_DUE_TO_INACTIVITY:
+ PRINTM(MMSG,
+ "wlan: REASON: Disassociated due to inactivity \n");
+ break;
+ case MLAN_REASON_DISASSOC_AP_BUSY:
+ PRINTM(MMSG,
+ "wlan: REASON: (Disassociated) AP unable to handle all connected STAs\n");
+ break;
+ case MLAN_REASON_CLASS2_FRAME_FROM_NOAUTH_STA:
+ PRINTM(MMSG,
+ "wlan: REASON: Class 2 frame was received from nonauthenticated STA\n");
+ break;
+ case MLAN_REASON_CLASS3_FRAME_FROM_NOASSOC_STA:
+ PRINTM(MMSG,
+ "wlan: REASON: Class 3 frame was received from nonassociated STA\n");
+ break;
+ case MLAN_REASON_DISASSOC_STA_HAS_LEFT:
+ PRINTM(MMSG,
+ "wlan: REASON: (Disassocated) Sending STA is leaving (or has left) BSS\n");
+ break;
+ case MLAN_REASON_STA_REQ_ASSOC_WITHOUT_AUTH:
+ PRINTM(MMSG,
+ "wlan: REASON: STA requesting (re)assoc is not authenticated with responding STA\n");
+ break;
+ default:
+ break;
+ }
+
+ LEAVE();
+ return;
+}
+
+/**
+ * @brief This function handles events generated by firmware
+ *
+ * @param priv A pointer to mlan_private structure
+ *
+ * @return MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ */
+mlan_status wlan_ops_sta_process_event(t_void *priv)
+{
+ pmlan_private pmpriv = (pmlan_private)priv;
+ pmlan_adapter pmadapter = pmpriv->adapter;
+ mlan_status ret = MLAN_STATUS_SUCCESS;
+ t_u32 eventcause = pmadapter->event_cause;
+ t_u8 *event_buf = MNULL;
+ t_u8 *evt_buf = MNULL;
+ pmlan_buffer pmbuf = pmadapter->pmlan_buffer_event;
+ t_u16 reason_code;
+ pmlan_callbacks pcb = &pmadapter->callbacks;
+ mlan_event *pevent = MNULL;
+ chan_band_info *pchan_band_info = MNULL;
+ t_u8 radar_chan;
+ t_u16 enable = 0;
+
+ ENTER();
+
+ if (!pmbuf) {
+ LEAVE();
+ return MLAN_STATUS_FAILURE;
+ }
+
+ /* Event length check */
+ if ((pmbuf->data_len - sizeof(eventcause)) > MAX_EVENT_SIZE) {
+ pmbuf->status_code = MLAN_ERROR_PKT_SIZE_INVALID;
+ LEAVE();
+ return MLAN_STATUS_FAILURE;
+ }
+
+ /* Allocate memory for event buffer */
+ ret = pcb->moal_malloc(pmadapter->pmoal_handle,
+ MAX_EVENT_SIZE + sizeof(mlan_event),
+ MLAN_MEM_DEF, &event_buf);
+ if ((ret != MLAN_STATUS_SUCCESS) || !event_buf) {
+ PRINTM(MERROR, "Could not allocate buffer for event buf\n");
+ if (pmbuf)
+ pmbuf->status_code = MLAN_ERROR_NO_MEM;
+ goto done;
+ }
+ pevent = (pmlan_event)event_buf;
+ memset(pmadapter, event_buf, 0, MAX_EVENT_SIZE);
+
+ if (eventcause != EVENT_PS_SLEEP && eventcause != EVENT_PS_AWAKE &&
+ pmbuf->data_len > sizeof(eventcause))
+ DBG_HEXDUMP(MEVT_D, "EVENT", pmbuf->pbuf + pmbuf->data_offset,
+ pmbuf->data_len);
+
+ switch (eventcause) {
+ case EVENT_DUMMY_HOST_WAKEUP_SIGNAL:
+ PRINTM(MERROR,
+ "Invalid EVENT: DUMMY_HOST_WAKEUP_SIGNAL, ignoring it\n");
+ break;
+ case EVENT_LINK_SENSED:
+ PRINTM(MEVENT, "EVENT: LINK_SENSED\n");
+ pmpriv->adhoc_is_link_sensed = MTRUE;
+ wlan_recv_event(pmpriv, MLAN_EVENT_ID_FW_ADHOC_LINK_SENSED,
+ MNULL);
+ break;
+
+ case EVENT_DEAUTHENTICATED:
+ if (pmpriv->wps.session_enable) {
+ PRINTM(MMSG,
+ "wlan: Receive deauth event in wps session\n");
+ break;
+ }
+ reason_code = wlan_le16_to_cpu(*(t_u16 *)(pmbuf->pbuf +
+ pmbuf->data_offset +
+ sizeof(eventcause)));
+ PRINTM(MMSG, "wlan: EVENT: Deauthenticated (reason 0x%x)\n",
+ reason_code);
+ wlan_print_disconnect_reason(reason_code);
+ pmpriv->disconnect_reason_code = reason_code;
+ pmadapter->dbg.num_event_deauth++;
+ wlan_handle_disconnect_event(pmpriv);
+
+ break;
+
+ case EVENT_DISASSOCIATED:
+ if (pmpriv->wps.session_enable) {
+ PRINTM(MMSG,
+ "wlan: Receive disassociate event in wps session\n");
+ break;
+ }
+ reason_code = wlan_le16_to_cpu(*(t_u16 *)(pmbuf->pbuf +
+ pmbuf->data_offset +
+ sizeof(eventcause)));
+ PRINTM(MMSG, "wlan: EVENT: Disassociated (reason 0x%x)\n",
+ reason_code);
+ wlan_print_disconnect_reason(reason_code);
+ pmpriv->disconnect_reason_code = reason_code;
+ pmadapter->dbg.num_event_disassoc++;
+ wlan_handle_disconnect_event(pmpriv);
+ break;
+
+ case EVENT_LINK_LOST:
+ reason_code = wlan_le16_to_cpu(*(t_u16 *)(pmbuf->pbuf +
+ pmbuf->data_offset +
+ sizeof(eventcause)));
+ PRINTM(MMSG, "wlan: EVENT: Link lost (reason 0x%x)\n",
+ reason_code);
+ pmpriv->disconnect_reason_code = reason_code;
+ pmadapter->dbg.num_event_link_lost++;
+ wlan_handle_disconnect_event(pmpriv);
+ break;
+
+ case EVENT_PS_SLEEP:
+ PRINTM(MINFO, "EVENT: SLEEP\n");
+ PRINTM_NETINTF(MEVENT, pmpriv);
+ PRINTM(MEVENT, "_");
+
+ /* Handle unexpected PS SLEEP event */
+ if (pmadapter->ps_state == PS_STATE_SLEEP_CFM)
+ break;
+ pmadapter->ps_state = PS_STATE_PRE_SLEEP;
+
+ wlan_check_ps_cond(pmadapter);
+ break;
+
+ case EVENT_PS_AWAKE:
+ PRINTM(MINFO, "EVENT: AWAKE\n");
+ PRINTM_NETINTF(MEVENT, pmpriv);
+ PRINTM(MEVENT, "|");
+ if (!pmadapter->pps_uapsd_mode && pmpriv->media_connected &&
+ (pmpriv->port_open || !pmpriv->port_ctrl_mode) &&
+ pmadapter->sleep_period.period) {
+ pmadapter->pps_uapsd_mode = MTRUE;
+ PRINTM(MEVENT, "PPS/UAPSD mode activated\n");
+ }
+ /* Handle unexpected PS AWAKE event */
+ if (pmadapter->ps_state == PS_STATE_SLEEP_CFM)
+ break;
+ pmadapter->tx_lock_flag = MFALSE;
+ if (pmadapter->pps_uapsd_mode && pmadapter->gen_null_pkt) {
+ if (MTRUE ==
+ wlan_check_last_packet_indication(pmpriv)) {
+ if (!pmadapter->data_sent) {
+ if (wlan_send_null_packet(
+ pmpriv,
+ MRVDRV_TxPD_POWER_MGMT_NULL_PACKET |
+ MRVDRV_TxPD_POWER_MGMT_LAST_PACKET) ==
+ MLAN_STATUS_SUCCESS) {
+ LEAVE();
+ return MLAN_STATUS_SUCCESS;
+ }
+ }
+ }
+ }
+ pmadapter->ps_state = PS_STATE_AWAKE;
+ pmadapter->pm_wakeup_card_req = MFALSE;
+ pmadapter->pm_wakeup_fw_try = MFALSE;
+ break;
+
+ case EVENT_HS_ACT_REQ:
+ PRINTM(MEVENT, "EVENT: HS_ACT_REQ\n");
+ ret = wlan_prepare_cmd(priv, HostCmd_CMD_802_11_HS_CFG_ENH, 0,
+ 0, MNULL, MNULL);
+ break;
+ case EVENT_MIC_ERR_UNICAST:
+ PRINTM(MEVENT, "EVENT: UNICAST MIC ERROR\n");
+ wlan_recv_event(pmpriv, MLAN_EVENT_ID_FW_MIC_ERR_UNI, MNULL);
+ break;
+
+ case EVENT_MIC_ERR_MULTICAST:
+ PRINTM(MEVENT, "EVENT: MULTICAST MIC ERROR\n");
+ wlan_recv_event(pmpriv, MLAN_EVENT_ID_FW_MIC_ERR_MUL, MNULL);
+ break;
+ case EVENT_MIB_CHANGED:
+ case EVENT_INIT_DONE:
+ break;
+
+ case EVENT_ADHOC_BCN_LOST:
+ PRINTM(MEVENT, "EVENT: ADHOC_BCN_LOST\n");
+ pmpriv->adhoc_is_link_sensed = MFALSE;
+ wlan_clean_txrx(pmpriv);
+ wlan_recv_event(pmpriv, MLAN_EVENT_ID_FW_ADHOC_LINK_LOST,
+ MNULL);
+ break;
+
+ case EVENT_FW_DEBUG_INFO:
+ pevent->bss_index = pmpriv->bss_index;
+ pevent->event_id = MLAN_EVENT_ID_FW_DEBUG_INFO;
+ pevent->event_len = pmbuf->data_len - sizeof(eventcause);
+ memcpy_ext(pmadapter, (t_u8 *)pevent->event_buf,
+ pmbuf->pbuf + pmbuf->data_offset +
+ sizeof(eventcause),
+ pevent->event_len, pevent->event_len);
+ PRINTM(MEVENT, "EVENT: FW Debug Info %s\n",
+ (t_u8 *)pevent->event_buf);
+ wlan_recv_event(pmpriv, pevent->event_id, pevent);
+ break;
+
+ case EVENT_BG_SCAN_REPORT:
+ PRINTM(MEVENT, "EVENT: BGS_REPORT\n");
+ pmadapter->bgscan_reported = MTRUE;
+ wlan_recv_event(pmpriv, MLAN_EVENT_ID_FW_BG_SCAN, MNULL);
+ break;
+ case EVENT_BG_SCAN_STOPPED:
+ PRINTM(MEVENT, "EVENT: BGS_STOPPED\n");
+ wlan_recv_event(pmpriv, MLAN_EVENT_ID_FW_BG_SCAN_STOPPED,
+ MNULL);
+ break;
+
+ case EVENT_PORT_RELEASE:
+ PRINTM(MEVENT, "EVENT: PORT RELEASE\n");
+ /* Open the port for e-supp mode */
+ if (pmpriv->port_ctrl_mode == MTRUE) {
+ PRINTM(MINFO, "PORT_REL: port_status = OPEN\n");
+ pmpriv->port_open = MTRUE;
+ }
+ pmadapter->scan_block = MFALSE;
+ wlan_recv_event(pmpriv, MLAN_EVENT_ID_FW_PORT_RELEASE, MNULL);
+ break;
+
+ case EVENT_STOP_TX:
+ PRINTM(MEVENT, "EVENT: Stop Tx (%#x)\n", eventcause);
+ wlan_11h_tx_disable(pmpriv); /* this fn will send event up to
+ MOAL */
+ break;
+ case EVENT_START_TX:
+ PRINTM(MEVENT, "EVENT: Start Tx (%#x)\n", eventcause);
+ wlan_11h_tx_enable(pmpriv); /* this fn will send event up to
+ MOAL */
+ break;
+ case EVENT_CHANNEL_SWITCH:
+ PRINTM(MEVENT, "EVENT: Channel Switch (%#x)\n", eventcause);
+ if (pmadapter->ecsa_enable) {
+ MrvlIEtypes_channel_band_t *pchan_info =
+ (MrvlIEtypes_channel_band_t
+ *)(pmadapter->event_body);
+ t_u8 channel = pchan_info->channel;
+ chan_freq_power_t *cfp = MNULL;
+ DBG_HEXDUMP(MCMD_D, "chan band config",
+ (t_u8 *)pchan_info,
+ sizeof(MrvlIEtypes_channel_band_t));
+ PRINTM(MEVENT, "Switch to channel %d success!\n",
+ channel);
+#define MAX_CHANNEL_BAND_B 14
+ if (channel <= MAX_CHANNEL_BAND_B)
+ cfp = wlan_find_cfp_by_band_and_channel(
+ pmadapter, BAND_B, channel);
+ else
+ cfp = wlan_find_cfp_by_band_and_channel(
+ pmadapter, BAND_A, channel);
+ pmpriv->curr_bss_params.bss_descriptor.channel =
+ channel;
+ if (cfp)
+ pmpriv->curr_bss_params.bss_descriptor.freq =
+ cfp->freq;
+ else
+ pmpriv->curr_bss_params.bss_descriptor.freq = 0;
+ if (pmpriv->adapter->state_rdh.stage ==
+ RDH_SET_CUSTOM_IE) {
+ pmadapter->state_rdh.stage =
+ RDH_RESTART_TRAFFIC;
+ wlan_11h_radar_detected_handling(pmadapter,
+ pmpriv);
+ }
+ pmadapter->state_rdh.tx_block = MFALSE;
+ /* Setup event buffer */
+ pevent->bss_index = pmpriv->bss_index;
+ pevent->event_id =
+ MLAN_EVENT_ID_FW_CHAN_SWITCH_COMPLETE;
+ pevent->event_len = sizeof(chan_band_info);
+ pchan_band_info = (chan_band_info *)pevent->event_buf;
+ /* Copy event data */
+ memcpy_ext(pmadapter, (t_u8 *)&pchan_band_info->bandcfg,
+ (t_u8 *)&pchan_info->bandcfg,
+ sizeof(pchan_info->bandcfg),
+ sizeof(pchan_band_info->bandcfg));
+ pchan_band_info->channel = pchan_info->channel;
+ if (pchan_band_info->bandcfg.chanWidth == CHAN_BW_80MHZ)
+ pchan_band_info->center_chan =
+ wlan_get_center_freq_idx(
+ priv, BAND_AAC,
+ pchan_info->channel,
+ CHANNEL_BW_80MHZ);
+ wlan_recv_event(pmpriv,
+ MLAN_EVENT_ID_FW_CHAN_SWITCH_COMPLETE,
+ pevent);
+ }
+ break;
+ case EVENT_CHANNEL_SWITCH_ANN:
+ PRINTM_NETINTF(MEVENT, pmpriv);
+ PRINTM(MEVENT, "EVENT: Channel Switch Announcement\n");
+ /* Here, pass up event first, as handling will send deauth */
+ wlan_recv_event(pmpriv, MLAN_EVENT_ID_FW_CHANNEL_SWITCH_ANN,
+ MNULL);
+ wlan_11h_handle_event_chanswann(pmpriv);
+ break;
+ case EVENT_RADAR_DETECTED:
+ PRINTM_NETINTF(MEVENT, pmpriv);
+ PRINTM(MEVENT, "EVENT: Radar Detected\n");
+
+ /* Send as passthru first, this event can cause other events */
+ pevent->bss_index = pmpriv->bss_index;
+ pevent->event_id = MLAN_EVENT_ID_DRV_PASSTHRU;
+ pevent->event_len = pmbuf->data_len;
+ memcpy_ext(pmadapter, (t_u8 *)pevent->event_buf,
+ pmbuf->pbuf + pmbuf->data_offset, pevent->event_len,
+ pevent->event_len);
+ wlan_recv_event(pmpriv, pevent->event_id, pevent);
+
+ if (pmadapter->state_rdh.stage == RDH_OFF) {
+ pmadapter->state_rdh.stage = RDH_CHK_INTFS;
+ wlan_11h_radar_detected_handling(pmadapter, pmpriv);
+ } else {
+ PRINTM(MEVENT, "Ignore Event Radar Detected - handling"
+ " already in progress.\n");
+ }
+
+ break;
+
+ case EVENT_CHANNEL_REPORT_RDY:
+ PRINTM_NETINTF(MEVENT, pmpriv);
+ PRINTM(MEVENT, "EVENT: Channel Report Ready\n");
+ pevent->bss_index = pmpriv->bss_index;
+ pevent->event_id = MLAN_EVENT_ID_FW_CHANNEL_REPORT_RDY;
+ pevent->event_len = pmbuf->data_len - sizeof(eventcause);
+ /* Copy event data */
+ memcpy_ext(pmadapter, (t_u8 *)pevent->event_buf,
+ pmbuf->pbuf + pmbuf->data_offset +
+ sizeof(eventcause),
+ pevent->event_len, pevent->event_len);
+ /* Handle / pass event data */
+ ret = wlan_11h_handle_event_chanrpt_ready(pmpriv, pevent,
+ &radar_chan);
+ /* Also send this event as passthru */
+ pevent->event_id = MLAN_EVENT_ID_DRV_PASSTHRU;
+ pevent->event_len = pmbuf->data_len;
+ memcpy_ext(pmadapter, (t_u8 *)pevent->event_buf,
+ pmbuf->pbuf + pmbuf->data_offset, pevent->event_len,
+ pevent->event_len);
+ wlan_recv_event(pmpriv, pevent->event_id, pevent);
+ /* Send up this Event to unblock MOAL waitqueue */
+ wlan_recv_event(pmpriv, MLAN_EVENT_ID_DRV_MEAS_REPORT, MNULL);
+ break;
+ case EVENT_EXT_SCAN_REPORT:
+ PRINTM(MEVENT, "EVENT: EXT_SCAN Report (%d)\n",
+ pmbuf->data_len);
+ if (pmadapter->pscan_ioctl_req && pmadapter->ext_scan)
+ ret = wlan_handle_event_ext_scan_report(priv, pmbuf);
+ break;
+ case EVENT_EXT_SCAN_STATUS_REPORT:
+ PRINTM(MEVENT, "EVENT: EXT_SCAN status report (%d)\n",
+ pmbuf->data_len);
+ pmadapter->ext_scan_timeout = MFALSE;
+ ret = wlan_handle_event_ext_scan_status(priv, pmbuf);
+ break;
+ case EVENT_MEAS_REPORT_RDY:
+ PRINTM(MEVENT, "EVENT: Measurement Report Ready (%#x)\n",
+ eventcause);
+ ret = wlan_prepare_cmd(priv, HostCmd_CMD_MEASUREMENT_REPORT,
+ HostCmd_ACT_GEN_SET, 0, 0, MNULL);
+ break;
+ case EVENT_WMM_STATUS_CHANGE:
+ if (pmbuf &&
+ pmbuf->data_len >
+ sizeof(eventcause) + sizeof(MrvlIEtypesHeader_t)) {
+ PRINTM(MEVENT, "EVENT: WMM status changed: %d\n",
+ pmbuf->data_len);
+
+ evt_buf = (pmbuf->pbuf + pmbuf->data_offset +
+ sizeof(eventcause));
+
+ wlan_ret_wmm_get_status(pmpriv, evt_buf,
+ pmbuf->data_len -
+ sizeof(eventcause));
+ } else {
+ PRINTM(MEVENT, "EVENT: WMM status changed\n");
+ ret = wlan_cmd_wmm_status_change(pmpriv);
+ }
+ break;
+
+ case EVENT_RSSI_LOW:
+ PRINTM(MEVENT, "EVENT: Beacon RSSI_LOW\n");
+ pevent->bss_index = pmpriv->bss_index;
+ pevent->event_id = MLAN_EVENT_ID_FW_BCN_RSSI_LOW;
+ pevent->event_len = sizeof(t_u16);
+ /** Fw send bcnRssi low value in event reason field*/
+ memcpy_ext(pmadapter, (t_u8 *)pevent->event_buf,
+ (t_u8 *)&pmadapter->event_body, pevent->event_len,
+ pevent->event_len);
+ wlan_recv_event(pmpriv, pevent->event_id, pevent);
+ break;
+ case EVENT_SNR_LOW:
+ PRINTM(MEVENT, "EVENT: Beacon SNR_LOW\n");
+ wlan_recv_event(pmpriv, MLAN_EVENT_ID_FW_BCN_SNR_LOW, MNULL);
+ break;
+ case EVENT_MAX_FAIL:
+ PRINTM(MEVENT, "EVENT: MAX_FAIL\n");
+ wlan_recv_event(pmpriv, MLAN_EVENT_ID_FW_MAX_FAIL, MNULL);
+ break;
+ case EVENT_RSSI_HIGH:
+ PRINTM(MEVENT, "EVENT: Beacon RSSI_HIGH\n");
+ pevent->bss_index = pmpriv->bss_index;
+ pevent->event_id = MLAN_EVENT_ID_FW_BCN_RSSI_HIGH;
+ pevent->event_len = sizeof(t_u16);
+ /** Fw send bcnRssi high value in event reason field*/
+ memcpy_ext(pmadapter, (t_u8 *)pevent->event_buf,
+ (t_u8 *)&pmadapter->event_body, pevent->event_len,
+ pevent->event_len);
+ wlan_recv_event(pmpriv, pevent->event_id, pevent);
+ break;
+ case EVENT_SNR_HIGH:
+ PRINTM(MEVENT, "EVENT: Beacon SNR_HIGH\n");
+ wlan_recv_event(pmpriv, MLAN_EVENT_ID_FW_BCN_SNR_HIGH, MNULL);
+ break;
+ case EVENT_DATA_RSSI_LOW:
+ PRINTM(MEVENT, "EVENT: Data RSSI_LOW\n");
+ wlan_recv_event(pmpriv, MLAN_EVENT_ID_FW_DATA_RSSI_LOW, MNULL);
+ break;
+ case EVENT_DATA_SNR_LOW:
+ PRINTM(MEVENT, "EVENT: Data SNR_LOW\n");
+ wlan_recv_event(pmpriv, MLAN_EVENT_ID_FW_DATA_SNR_LOW, MNULL);
+ break;
+ case EVENT_DATA_RSSI_HIGH:
+ PRINTM(MEVENT, "EVENT: Data RSSI_HIGH\n");
+ wlan_recv_event(pmpriv, MLAN_EVENT_ID_FW_DATA_RSSI_HIGH, MNULL);
+ break;
+ case EVENT_DATA_SNR_HIGH:
+ PRINTM(MEVENT, "EVENT: Data SNR_HIGH\n");
+ wlan_recv_event(pmpriv, MLAN_EVENT_ID_FW_DATA_SNR_HIGH, MNULL);
+ break;
+ case EVENT_LINK_QUALITY:
+ PRINTM(MEVENT, "EVENT: Link Quality\n");
+ wlan_recv_event(pmpriv, MLAN_EVENT_ID_FW_LINK_QUALITY, MNULL);
+ break;
+ case EVENT_PRE_BEACON_LOST:
+ PRINTM(MEVENT, "EVENT: Pre-Beacon Lost\n");
+ wlan_recv_event(pmpriv, MLAN_EVENT_ID_FW_PRE_BCN_LOST, MNULL);
+ break;
+ case EVENT_IBSS_COALESCED:
+ PRINTM(MEVENT, "EVENT: IBSS_COALESCED\n");
+ ret = wlan_prepare_cmd(
+ pmpriv, HostCmd_CMD_802_11_IBSS_COALESCING_STATUS,
+ HostCmd_ACT_GEN_GET, 0, MNULL, MNULL);
+ break;
+ case EVENT_ADDBA:
+ PRINTM(MEVENT, "EVENT: ADDBA Request\n");
+ if (pmpriv->media_connected == MTRUE)
+ ret = wlan_prepare_cmd(pmpriv,
+ HostCmd_CMD_11N_ADDBA_RSP,
+ HostCmd_ACT_GEN_SET, 0, MNULL,
+ pmadapter->event_body);
+ else
+ PRINTM(MERROR,
+ "Ignore ADDBA Request event in disconnected state\n");
+ break;
+ case EVENT_DELBA:
+ PRINTM(MEVENT, "EVENT: DELBA Request\n");
+ if (pmpriv->media_connected == MTRUE)
+ wlan_11n_delete_bastream(pmpriv, pmadapter->event_body);
+ else
+ PRINTM(MERROR,
+ "Ignore DELBA Request event in disconnected state\n");
+ break;
+ case EVENT_BA_STREAM_TIMEOUT:
+ PRINTM(MEVENT, "EVENT: BA Stream timeout\n");
+ if (pmpriv->media_connected == MTRUE)
+ wlan_11n_ba_stream_timeout(
+ pmpriv, (HostCmd_DS_11N_BATIMEOUT *)
+ pmadapter->event_body);
+ else
+ PRINTM(MERROR,
+ "Ignore BA Stream timeout event in disconnected state\n");
+ break;
+ case EVENT_RXBA_SYNC:
+ PRINTM(MEVENT, "EVENT: RXBA_SYNC\n");
+ wlan_11n_rxba_sync_event(pmpriv, pmadapter->event_body,
+ pmbuf->data_len - sizeof(eventcause));
+ break;
+ case EVENT_AMSDU_AGGR_CTRL:
+ PRINTM(MEVENT, "EVENT: AMSDU_AGGR_CTRL %d\n",
+ *(t_u16 *)pmadapter->event_body);
+ pmadapter->tx_buf_size =
+ MIN(pmadapter->curr_tx_buf_size,
+ wlan_le16_to_cpu(*(t_u16 *)pmadapter->event_body));
+ if (pmbuf->data_len == sizeof(eventcause) + sizeof(t_u32)) {
+ enable = wlan_le16_to_cpu(
+ *(t_u16 *)(pmadapter->event_body +
+ sizeof(t_u16)));
+ if (enable)
+ pmpriv->amsdu_disable = MFALSE;
+ else
+ pmpriv->amsdu_disable = MTRUE;
+ PRINTM(MEVENT, "amsdu_disable=%d\n",
+ pmpriv->amsdu_disable);
+ }
+ PRINTM(MEVENT, "tx_buf_size %d\n", pmadapter->tx_buf_size);
+ break;
+
+ case EVENT_WEP_ICV_ERR:
+ PRINTM(MEVENT, "EVENT: WEP ICV error\n");
+ pevent->bss_index = pmpriv->bss_index;
+ pevent->event_id = MLAN_EVENT_ID_FW_WEP_ICV_ERR;
+ pevent->event_len = sizeof(Event_WEP_ICV_ERR);
+ memcpy_ext(pmadapter, (t_u8 *)pevent->event_buf,
+ pmadapter->event_body, pevent->event_len,
+ pevent->event_len);
+ wlan_recv_event(pmpriv, MLAN_EVENT_ID_FW_WEP_ICV_ERR, pevent);
+ break;
+
+ case EVENT_BW_CHANGE:
+ PRINTM(MEVENT, "EVENT: BW Change\n");
+ pevent->bss_index = pmpriv->bss_index;
+ pevent->event_id = MLAN_EVENT_ID_FW_BW_CHANGED;
+ pevent->event_len = sizeof(t_u8);
+ /* Copy event body from the event buffer */
+ memcpy_ext(pmadapter, (t_u8 *)pevent->event_buf,
+ pmadapter->event_body, pevent->event_len,
+ pevent->event_len);
+#ifdef UAP_SUPPORT
+ if (pmadapter->dfs_repeater)
+ wlan_dfs_rep_bw_change(pmadapter);
+#endif
+ wlan_recv_event(pmpriv, MLAN_EVENT_ID_FW_BW_CHANGED, pevent);
+ break;
+
+#ifdef WIFI_DIRECT_SUPPORT
+ case EVENT_WIFIDIRECT_GENERIC_EVENT:
+ PRINTM(MEVENT, "EVENT: WIFIDIRECT event %d\n", eventcause);
+ pevent->bss_index = pmpriv->bss_index;
+ pevent->event_id = MLAN_EVENT_ID_DRV_PASSTHRU;
+ pevent->event_len = pmbuf->data_len;
+ memcpy_ext(pmadapter, (t_u8 *)pevent->event_buf,
+ pmbuf->pbuf + pmbuf->data_offset, pevent->event_len,
+ pevent->event_len);
+ wlan_recv_event(pmpriv, pevent->event_id, pevent);
+ break;
+ case EVENT_WIFIDIRECT_SERVICE_DISCOVERY:
+ PRINTM(MEVENT, "EVENT: WIFIDIRECT service discovery event %d\n",
+ eventcause);
+ pevent->bss_index = pmpriv->bss_index;
+ pevent->event_id = MLAN_EVENT_ID_DRV_PASSTHRU;
+ pevent->event_len = pmbuf->data_len;
+ memcpy_ext(pmadapter, (t_u8 *)pevent->event_buf,
+ pmbuf->pbuf + pmbuf->data_offset, pevent->event_len,
+ pevent->event_len);
+ wlan_recv_event(pmpriv, pevent->event_id, pevent);
+ break;
+#endif /* WIFI_DIRECT_SUPPORT */
+ case EVENT_REMAIN_ON_CHANNEL_EXPIRED:
+ PRINTM_NETINTF(MEVENT, pmpriv);
+ PRINTM(MEVENT, "EVENT: REMAIN_ON_CHANNEL_EXPIRED reason=%d\n",
+ *(t_u16 *)pmadapter->event_body);
+ wlan_recv_event(pmpriv, MLAN_EVENT_ID_DRV_FLUSH_RX_WORK, MNULL);
+ wlan_recv_event(pmpriv, MLAN_EVENT_ID_FW_REMAIN_ON_CHAN_EXPIRED,
+ MNULL);
+ break;
+
+ case EVENT_TX_DATA_PAUSE:
+ PRINTM(MEVENT, "EVENT: TX_DATA_PAUSE\n");
+ wlan_process_sta_tx_pause_event(priv, pmbuf);
+ break;
+
+ case EVENT_IBSS_STATION_CONNECT:
+ break;
+ case EVENT_IBSS_STATION_DISCONNECT:
+ break;
+ case EVENT_SAD_REPORT: {
+#ifdef DEBUG_LEVEL1
+ t_u8 *pevt_dat =
+ pmbuf->pbuf + pmbuf->data_offset + sizeof(t_u32);
+#endif
+ PRINTM(MEVENT,
+ "EVENT: Antenna Diversity %d (%d, %d, %d, %d)\n",
+ eventcause, pevt_dat[0] + 1, pevt_dat[1] + 1,
+ pevt_dat[2], pevt_dat[3]);
+ } break;
+
+ case EVENT_FW_DUMP_INFO:
+ PRINTM(MINFO, "EVENT: Dump FW info\n");
+ pevent->bss_index = pmpriv->bss_index;
+ pevent->event_id = MLAN_EVENT_ID_FW_DUMP_INFO;
+ pevent->event_len = pmbuf->data_len;
+ memcpy_ext(pmadapter, (t_u8 *)pevent->event_buf,
+ pmbuf->pbuf + pmbuf->data_offset, pevent->event_len,
+ pevent->event_len);
+ wlan_recv_event(pmpriv, pevent->event_id, pevent);
+ break;
+ case EVENT_TX_STATUS_REPORT:
+ PRINTM(MINFO, "EVENT: TX_STATUS\n");
+ pevent->bss_index = pmpriv->bss_index;
+ pevent->event_id = MLAN_EVENT_ID_FW_TX_STATUS;
+ pevent->event_len = pmbuf->data_len;
+ memcpy_ext(pmadapter, (t_u8 *)pevent->event_buf,
+ pmbuf->pbuf + pmbuf->data_offset, pevent->event_len,
+ pevent->event_len);
+
+ wlan_recv_event(pmpriv, pevent->event_id, pevent);
+ break;
+ case EVENT_BT_COEX_WLAN_PARA_CHANGE:
+ PRINTM(MEVENT, "EVENT: BT coex wlan param update\n");
+ wlan_bt_coex_wlan_param_update_event(pmpriv, pmbuf);
+ break;
+
+#if defined(PCIE)
+ case EVENT_SSU_DUMP_DMA:
+ PRINTM(MEVENT, "EVENT: EVENT_SSU_DUMP_DMA\n");
+ if (!pmadapter->ssu_buf || !pmadapter->ssu_buf->pbuf)
+ break;
+
+ /* If ADMA is supported, SSU header could not be received with
+ * SSU data. Instead, SSU header is received through this event.
+ * So, copy the header into the buffer before passing the buffer
+ * to upper layer for file writting
+ */
+ memcpy_ext(pmadapter,
+ (t_u8 *)pmadapter->ssu_buf->pbuf +
+ pmadapter->ssu_buf->data_offset,
+ pmbuf->pbuf + pmbuf->data_offset +
+ sizeof(eventcause),
+ (pmbuf->data_len - sizeof(eventcause)),
+ (pmbuf->data_len - sizeof(eventcause)));
+
+ DBG_HEXDUMP(MEVT_D, "SSU data",
+ (t_u8 *)pmadapter->ssu_buf->pbuf +
+ pmadapter->ssu_buf->data_offset,
+ 512);
+ pevent->bss_index = pmpriv->bss_index;
+ pevent->event_id = MLAN_EVENT_ID_SSU_DUMP_FILE;
+ pevent->event_len = MLAN_SSU_BUF_SIZE;
+ *(t_ptr *)pevent->event_buf = (t_ptr)pmadapter->ssu_buf->pbuf +
+ pmadapter->ssu_buf->data_offset;
+ wlan_recv_event(pmpriv, pevent->event_id, pevent);
+ wlan_free_ssu_pcie_buf(pmadapter);
+ break;
+#endif
+ case EVENT_MEF_HOST_WAKEUP:
+ PRINTM(MEVENT, "EVENT: EVENT_MEF_HOST_WAKEUP len=%d\n",
+ pmbuf->data_len);
+ break;
+ case EVENT_MANAGEMENT_FRAME_WAKEUP:
+ PRINTM(MEVENT, "EVENT: EVENT_MANAGEMENT_FRAME_WAKEUP HOST\n");
+ break;
+ case EVENT_CLOUD_KEEP_ALIVE_RETRY_FAIL:
+ break;
+ case EVENT_VDLL_IND:
+ wlan_process_vdll_event(pmpriv, pmbuf);
+ break;
+ case EVENT_FW_HANG_REPORT:
+ if (pmbuf->data_len < (sizeof(eventcause) + sizeof(t_u16))) {
+ PRINTM(MEVENT,
+ "EVENT: EVENT_FW_HANG_REPORT skip for len too short: %d\n",
+ pmbuf->data_len);
+ break;
+ }
+ PRINTM(MEVENT, "EVENT: EVENT_FW_HANG_REPORT reasoncode=%d\n",
+ wlan_le16_to_cpu(*(t_u16 *)(pmbuf->pbuf +
+ pmbuf->data_offset +
+ sizeof(eventcause))));
+ pmadapter->fw_hang_report = MTRUE;
+ wlan_recv_event(pmpriv, MLAN_EVENT_ID_DRV_DBG_DUMP, MNULL);
+ break;
+ default:
+ PRINTM(MEVENT, "EVENT: unknown event id: %#x\n", eventcause);
+ wlan_recv_event(pmpriv, MLAN_EVENT_ID_FW_UNKNOWN, MNULL);
+ break;
+ }
+done:
+ if (event_buf)
+ pcb->moal_mfree(pmadapter->pmoal_handle, event_buf);
+ LEAVE();
+ return ret;
+}
diff --git a/drivers/net/wireless/nxp/mxm_wifiex/wlan_src/mlan/mlan_sta_ioctl.c b/drivers/net/wireless/nxp/mxm_wifiex/wlan_src/mlan/mlan_sta_ioctl.c
new file mode 100644
index 000000000000..c565144f04ac
--- /dev/null
+++ b/drivers/net/wireless/nxp/mxm_wifiex/wlan_src/mlan/mlan_sta_ioctl.c
@@ -0,0 +1,5615 @@
+/** @file mlan_sta_ioctl.c
+ *
+ * @brief This file contains the functions for station ioctl.
+ *
+ *
+ * Copyright 2014-2020 NXP
+ *
+ * This software file (the File) is distributed by NXP
+ * under the terms of the GNU General Public License Version 2, June 1991
+ * (the License). You may use, redistribute and/or modify the 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.
+ *
+ */
+
+/******************************************************
+Change log:
+ 10/21/2008: initial version
+******************************************************/
+
+#include "mlan.h"
+#include "mlan_join.h"
+#include "mlan_util.h"
+#include "mlan_fw.h"
+#include "mlan_main.h"
+#include "mlan_wmm.h"
+#include "mlan_11n.h"
+#include "mlan_11ac.h"
+#include "mlan_11ax.h"
+#include "mlan_11h.h"
+#ifdef DRV_EMBEDDED_SUPPLICANT
+#include "authenticator_api.h"
+#endif
+
+/********************************************************
+ Local Variables
+********************************************************/
+
+/********************************************************
+ Global Variables
+********************************************************/
+
+/********************************************************
+ Local Functions
+********************************************************/
+
+/**
+ * @brief Get signal information
+ *
+ * @param pmadapter A pointer to mlan_adapter structure
+ * @param pioctl_req A pointer to ioctl request buffer
+ *
+ * @return MLAN_STATUS_PENDING --success, otherwise fail
+ */
+static mlan_status wlan_get_info_signal(pmlan_adapter pmadapter,
+ pmlan_ioctl_req pioctl_req)
+{
+ pmlan_private pmpriv = MNULL;
+ mlan_status ret = MLAN_STATUS_SUCCESS;
+
+ ENTER();
+
+ if (pioctl_req != MNULL) {
+ pmpriv = pmadapter->priv[pioctl_req->bss_index];
+ } else {
+ PRINTM(MERROR, "MLAN IOCTL information is not present\n");
+ ret = MLAN_STATUS_FAILURE;
+ goto exit;
+ }
+
+ /* Check information buffer length of MLAN IOCTL */
+ if (pioctl_req->buf_len < sizeof(mlan_ds_get_signal)) {
+ PRINTM(MWARN,
+ "MLAN IOCTL information buffer length is too short.\n");
+ pioctl_req->data_read_written = 0;
+ pioctl_req->buf_len_needed = sizeof(mlan_ds_get_signal);
+ pioctl_req->status_code = MLAN_ERROR_INVALID_PARAMETER;
+ ret = MLAN_STATUS_RESOURCE;
+ goto exit;
+ }
+
+ /* Signal info can be obtained only if connected */
+ if (pmpriv->media_connected == MFALSE) {
+ PRINTM(MINFO, "Can not get signal in disconnected state\n");
+ pioctl_req->status_code = MLAN_ERROR_IOCTL_INVALID;
+ ret = MLAN_STATUS_FAILURE;
+ goto exit;
+ }
+
+ /* Send request to firmware */
+ ret = wlan_prepare_cmd(pmpriv, HostCmd_CMD_RSSI_INFO,
+ HostCmd_ACT_GEN_GET, 0, (t_void *)pioctl_req,
+ MNULL);
+
+ if (ret == MLAN_STATUS_SUCCESS)
+ ret = MLAN_STATUS_PENDING;
+
+exit:
+ LEAVE();
+ return ret;
+}
+
+/**
+ * @brief Get signal information
+ *
+ * @param pmadapter A pointer to mlan_adapter structure
+ * @param pioctl_req A pointer to ioctl request buffer
+ *
+ * @return MLAN_STATUS_PENDING --success, otherwise fail
+ */
+static mlan_status wlan_get_info_signal_ext(pmlan_adapter pmadapter,
+ pmlan_ioctl_req pioctl_req)
+{
+ pmlan_private pmpriv = MNULL;
+ mlan_status ret = MLAN_STATUS_SUCCESS;
+ mlan_ds_get_info *info = MNULL;
+
+ ENTER();
+
+ if (pioctl_req != MNULL) {
+ pmpriv = pmadapter->priv[pioctl_req->bss_index];
+ } else {
+ PRINTM(MERROR, "MLAN IOCTL information is not present\n");
+ ret = MLAN_STATUS_FAILURE;
+ goto exit;
+ }
+ info = (mlan_ds_get_info *)pioctl_req->pbuf;
+
+ /* Check information buffer length of MLAN IOCTL */
+ if (pioctl_req->buf_len < sizeof(mlan_ds_get_info)) {
+ PRINTM(MWARN,
+ "MLAN IOCTL information buffer length is too short.\n");
+ pioctl_req->data_read_written = 0;
+ pioctl_req->buf_len_needed = sizeof(mlan_ds_get_info);
+ pioctl_req->status_code = MLAN_ERROR_INVALID_PARAMETER;
+ ret = MLAN_STATUS_RESOURCE;
+ goto exit;
+ }
+
+ /* Send request to firmware */
+ ret = wlan_prepare_cmd(pmpriv, HostCmd_CMD_RSSI_INFO_EXT,
+ HostCmd_ACT_GEN_GET, 0, (t_void *)pioctl_req,
+ (t_void *)info);
+
+ if (ret == MLAN_STATUS_SUCCESS)
+ ret = MLAN_STATUS_PENDING;
+
+exit:
+ LEAVE();
+ return ret;
+}
+
+/**
+ * @brief Get statistics information
+ *
+ * @param pmadapter A pointer to mlan_adapter structure
+ * @param pioctl_req A pointer to ioctl request buffer
+ *
+ * @return MLAN_STATUS_PENDING --success, otherwise fail
+ */
+static mlan_status wlan_get_info_stats(pmlan_adapter pmadapter,
+ pmlan_ioctl_req pioctl_req)
+{
+ pmlan_private pmpriv = MNULL;
+ mlan_status ret = MLAN_STATUS_SUCCESS;
+
+ ENTER();
+
+ if (pioctl_req != MNULL) {
+ pmpriv = pmadapter->priv[pioctl_req->bss_index];
+ } else {
+ PRINTM(MERROR, "MLAN IOCTL information is not present\n");
+ ret = MLAN_STATUS_FAILURE;
+ goto exit;
+ }
+
+ /* Check information buffer length of MLAN IOCTL */
+ if (pioctl_req->buf_len < sizeof(mlan_ds_get_stats)) {
+ PRINTM(MWARN,
+ "MLAN IOCTL information buffer length is too short.\n");
+ pioctl_req->data_read_written = 0;
+ pioctl_req->buf_len_needed = sizeof(mlan_ds_get_stats);
+ pioctl_req->status_code = MLAN_ERROR_INVALID_PARAMETER;
+ ret = MLAN_STATUS_RESOURCE;
+ goto exit;
+ }
+
+ /* Send request to firmware */
+ ret = wlan_prepare_cmd(pmpriv, HostCmd_CMD_802_11_GET_LOG,
+ HostCmd_ACT_GEN_GET, 0, (t_void *)pioctl_req,
+ MNULL);
+
+ if (ret == MLAN_STATUS_SUCCESS)
+ ret = MLAN_STATUS_PENDING;
+
+exit:
+ LEAVE();
+ return ret;
+}
+
+/**
+ * @brief Get sta channel information
+ *
+ * @param pmadapter A pointer to mlan_adapter structure
+ * @param pioctl_req A pointer to ioctl request buffer
+ *
+ * @return MLAN_STATUS_PENDING --success, otherwise fail
+ */
+static mlan_status wlan_bss_ioctl_get_chan_info(pmlan_adapter pmadapter,
+ pmlan_ioctl_req pioctl_req)
+{
+ pmlan_private pmpriv = MNULL;
+ mlan_status ret = MLAN_STATUS_SUCCESS;
+
+ ENTER();
+
+ if (pioctl_req != MNULL) {
+ pmpriv = pmadapter->priv[pioctl_req->bss_index];
+ } else {
+ PRINTM(MERROR, "MLAN IOCTL information is not present\n");
+ ret = MLAN_STATUS_FAILURE;
+ goto exit;
+ }
+
+ /* Check information buffer length of MLAN IOCTL */
+ if (pioctl_req->buf_len < sizeof(chan_band_info)) {
+ PRINTM(MWARN,
+ "MLAN IOCTL information buffer length is too short.\n");
+ pioctl_req->data_read_written = 0;
+ pioctl_req->buf_len_needed = sizeof(chan_band_info);
+ pioctl_req->status_code = MLAN_ERROR_INVALID_PARAMETER;
+ ret = MLAN_STATUS_RESOURCE;
+ goto exit;
+ }
+
+ /* Send request to firmware */
+ ret = wlan_prepare_cmd(pmpriv, HostCmd_CMD_STA_CONFIGURE,
+ HostCmd_ACT_GEN_GET, 0, (t_void *)pioctl_req,
+ MNULL);
+
+ if (ret == MLAN_STATUS_SUCCESS)
+ ret = MLAN_STATUS_PENDING;
+
+exit:
+ LEAVE();
+ return ret;
+}
+
+/**
+ * @brief Get BSS information
+ *
+ * @param pmadapter A pointer to mlan_adapter structure
+ * @param pioctl_req A pointer to ioctl request buffer
+ *
+ * @return MLAN_STATUS_SUCCESS --success
+ */
+static mlan_status wlan_get_info_bss_info(pmlan_adapter pmadapter,
+ pmlan_ioctl_req pioctl_req)
+{
+ pmlan_private pmpriv = pmadapter->priv[pioctl_req->bss_index];
+ mlan_status ret = MLAN_STATUS_SUCCESS;
+ mlan_ds_get_info *info;
+ BSSDescriptor_t *pbss_desc;
+ t_s32 tbl_idx = 0;
+
+ ENTER();
+
+ /* Get current BSS info */
+ pbss_desc = &pmpriv->curr_bss_params.bss_descriptor;
+ info = (mlan_ds_get_info *)pioctl_req->pbuf;
+
+ /* BSS mode */
+ info->param.bss_info.bss_mode = pmpriv->bss_mode;
+
+ /* SSID */
+ memcpy_ext(pmadapter, &info->param.bss_info.ssid, &pbss_desc->ssid,
+ sizeof(mlan_802_11_ssid), sizeof(mlan_802_11_ssid));
+
+ /* BSSID */
+ memcpy_ext(pmadapter, &info->param.bss_info.bssid,
+ &pbss_desc->mac_address, MLAN_MAC_ADDR_LENGTH,
+ MLAN_MAC_ADDR_LENGTH);
+
+ /* Channel */
+ info->param.bss_info.bss_chan = pbss_desc->channel;
+
+ /* Beacon interval */
+ info->param.bss_info.beacon_interval = pbss_desc->beacon_period;
+
+ /* Band */
+ info->param.bss_info.bss_band = (t_u8)pbss_desc->bss_band;
+
+ /* Region code */
+ info->param.bss_info.region_code = pmadapter->region_code;
+
+ /* Scan table index if connected */
+ info->param.bss_info.scan_table_idx = 0;
+ info->param.bss_info.scan_block = pmadapter->scan_block;
+ if (pmpriv->media_connected == MTRUE) {
+ tbl_idx = wlan_find_ssid_in_list(pmpriv, &pbss_desc->ssid,
+ pbss_desc->mac_address,
+ pmpriv->bss_mode);
+ if (tbl_idx >= 0)
+ info->param.bss_info.scan_table_idx = tbl_idx;
+ }
+
+ /* Connection status */
+ info->param.bss_info.media_connected = pmpriv->media_connected;
+
+ /* Radio status */
+ info->param.bss_info.radio_on = pmadapter->radio_on;
+
+ /* Tx power information */
+ info->param.bss_info.max_power_level = pmpriv->max_tx_power_level;
+ info->param.bss_info.min_power_level = pmpriv->min_tx_power_level;
+
+ /* AdHoc state */
+ info->param.bss_info.adhoc_state = pmpriv->adhoc_state;
+
+ /* Last beacon NF */
+ info->param.bss_info.bcn_nf_last = pmpriv->bcn_nf_last;
+
+ /* wep status */
+ if (pmpriv->sec_info.wep_status == Wlan802_11WEPEnabled)
+ info->param.bss_info.wep_status = MTRUE;
+ else
+ info->param.bss_info.wep_status = MFALSE;
+
+ info->param.bss_info.is_hs_configured = pmadapter->is_hs_configured;
+ info->param.bss_info.is_deep_sleep = pmadapter->is_deep_sleep;
+
+ /* Capability Info */
+ info->param.bss_info.capability_info = 0;
+ memcpy_ext(pmadapter, &info->param.bss_info.capability_info,
+ &pbss_desc->cap_info,
+ sizeof(info->param.bss_info.capability_info),
+ sizeof(info->param.bss_info.capability_info));
+
+ memset(pmadapter, &info->param.bss_info.ext_cap, 0, sizeof(ExtCap_t));
+ if (pbss_desc->pext_cap) {
+ memcpy_ext(pmadapter, &info->param.bss_info.ext_cap,
+ (t_u8 *)pbss_desc->pext_cap +
+ sizeof(IEEEtypes_Header_t),
+ pbss_desc->pext_cap->ieee_hdr.len,
+ sizeof(info->param.bss_info.ext_cap));
+ }
+
+ /* Listen Interval */
+ info->param.bss_info.listen_interval = pmpriv->listen_interval;
+
+ /* Association ID */
+ if (pmpriv->assoc_rsp_buf)
+ info->param.bss_info.assoc_id =
+ (t_u16)((IEEEtypes_AssocRsp_t *)pmpriv->assoc_rsp_buf)
+ ->a_id;
+ else
+ info->param.bss_info.assoc_id = 0;
+
+ /* AP/Peer supported rates */
+ memset(pmadapter, info->param.bss_info.peer_supp_rates, 0,
+ sizeof(info->param.bss_info.peer_supp_rates));
+ memcpy_ext(pmadapter, info->param.bss_info.peer_supp_rates,
+ pbss_desc->supported_rates,
+ sizeof(pbss_desc->supported_rates),
+ sizeof(info->param.bss_info.peer_supp_rates));
+ if (pbss_desc->pmd_ie) {
+ info->param.bss_info.mdid = pbss_desc->pmd_ie->mdid;
+ info->param.bss_info.ft_cap = pbss_desc->pmd_ie->ft_cap;
+ }
+ pioctl_req->data_read_written =
+ sizeof(mlan_bss_info) + MLAN_SUB_COMMAND_SIZE;
+
+ LEAVE();
+ return ret;
+}
+
+/**
+ * @brief Get information handler
+ *
+ * @param pmadapter A pointer to mlan_adapter structure
+ * @param pioctl_req A pointer to ioctl request buffer
+ *
+ * @return MLAN_STATUS_SUCCESS --success, otherwise fail
+ */
+static mlan_status wlan_get_info_ioctl(pmlan_adapter pmadapter,
+ pmlan_ioctl_req pioctl_req)
+{
+ mlan_status status = MLAN_STATUS_SUCCESS;
+ mlan_ds_get_info *pget_info = MNULL;
+ mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index];
+
+ ENTER();
+
+ pget_info = (mlan_ds_get_info *)pioctl_req->pbuf;
+
+ switch (pget_info->sub_command) {
+ case MLAN_OID_GET_STATS:
+ status = wlan_get_info_stats(pmadapter, pioctl_req);
+ break;
+ case MLAN_OID_GET_SIGNAL:
+ status = wlan_get_info_signal(pmadapter, pioctl_req);
+ break;
+ case MLAN_OID_GET_SIGNAL_EXT:
+ status = wlan_get_info_signal_ext(pmadapter, pioctl_req);
+ break;
+ case MLAN_OID_GET_FW_INFO:
+ pioctl_req->data_read_written =
+ sizeof(mlan_fw_info) + MLAN_SUB_COMMAND_SIZE;
+ pget_info->param.fw_info.fw_ver = pmadapter->fw_release_number;
+ memcpy_ext(pmadapter, &pget_info->param.fw_info.mac_addr,
+ pmpriv->curr_addr, MLAN_MAC_ADDR_LENGTH,
+ MLAN_MAC_ADDR_LENGTH);
+ pget_info->param.fw_info.fw_bands = pmadapter->fw_bands;
+ pget_info->param.fw_info.region_code = pmadapter->region_code;
+ if (pmadapter->otp_region && pmadapter->otp_region->force_reg)
+ pget_info->param.fw_info.force_reg = MTRUE;
+ else
+ pget_info->param.fw_info.force_reg = MFALSE;
+ pget_info->param.fw_info.ecsa_enable = pmadapter->ecsa_enable;
+ pget_info->param.fw_info.getlog_enable =
+ pmadapter->getlog_enable;
+ pget_info->param.fw_info.hw_dev_mcs_support =
+ pmadapter->hw_dev_mcs_support;
+ pget_info->param.fw_info.hw_dot_11n_dev_cap =
+ pmadapter->hw_dot_11n_dev_cap;
+ pget_info->param.fw_info.usr_dev_mcs_support =
+ pmpriv->usr_dev_mcs_support;
+ if (IS_FW_SUPPORT_NO_80MHZ(pmadapter))
+ pget_info->param.fw_info.prohibit_80mhz = MTRUE;
+ else
+ pget_info->param.fw_info.prohibit_80mhz = MFALSE;
+ pget_info->param.fw_info.hw_dot_11ac_mcs_support =
+ pmadapter->hw_dot_11ac_mcs_support;
+ pget_info->param.fw_info.hw_dot_11ac_dev_cap =
+ pmadapter->hw_dot_11ac_dev_cap;
+ pget_info->param.fw_info.usr_dot_11ac_dev_cap_bg =
+ pmpriv->usr_dot_11ac_dev_cap_bg;
+ pget_info->param.fw_info.usr_dot_11ac_mcs_support =
+ pmpriv->usr_dot_11ac_mcs_support;
+ pget_info->param.fw_info.usr_dot_11ac_dev_cap_a =
+ pmpriv->usr_dot_11ac_dev_cap_a;
+ pget_info->param.fw_info.hw_hecap_len = pmadapter->hw_hecap_len;
+ pget_info->param.fw_info.hw_2g_hecap_len =
+ pmadapter->hw_2g_hecap_len;
+ memcpy_ext(pmadapter, pget_info->param.fw_info.hw_he_cap,
+ pmadapter->hw_he_cap, pmadapter->hw_hecap_len,
+ sizeof(pget_info->param.fw_info.hw_he_cap));
+ memcpy_ext(pmadapter, pget_info->param.fw_info.hw_2g_he_cap,
+ pmadapter->hw_2g_he_cap, pmadapter->hw_2g_hecap_len,
+ sizeof(pget_info->param.fw_info.hw_2g_he_cap));
+ pget_info->param.fw_info.fw_supplicant_support =
+ IS_FW_SUPPORT_SUPPLICANT(pmadapter) ? 0x01 : 0x00;
+ pget_info->param.fw_info.antinfo = pmadapter->antinfo;
+ pget_info->param.fw_info.max_ap_assoc_sta =
+ pmadapter->max_sta_conn;
+ break;
+ case MLAN_OID_GET_BSS_INFO:
+ status = wlan_get_info_bss_info(pmadapter, pioctl_req);
+ break;
+ case MLAN_OID_GET_DEBUG_INFO:
+ status = wlan_get_info_debug_info(pmadapter, pioctl_req);
+ break;
+ case MLAN_OID_GET_VER_EXT:
+ status = wlan_get_info_ver_ext(pmadapter, pioctl_req);
+ break;
+ case MLAN_OID_LINK_STATS:
+ status = wlan_ioctl_link_statistic(pmpriv, pioctl_req);
+ break;
+ default:
+ pioctl_req->status_code = MLAN_ERROR_IOCTL_INVALID;
+ status = MLAN_STATUS_FAILURE;
+ break;
+ }
+
+ LEAVE();
+ return status;
+}
+
+/**
+ * @brief Set/Get SNMP MIB handler
+ *
+ * @param pmadapter A pointer to mlan_adapter structure
+ * @param pioctl_req A pointer to ioctl request buffer
+ *
+ * @return MLAN_STATUS_PENDING --success, otherwise fail
+ */
+static mlan_status wlan_snmp_mib_ioctl(pmlan_adapter pmadapter,
+ pmlan_ioctl_req pioctl_req)
+{
+ pmlan_private pmpriv = pmadapter->priv[pioctl_req->bss_index];
+ mlan_status ret = MLAN_STATUS_SUCCESS;
+ t_u16 cmd_action = 0;
+ t_u16 cmd_oid = 0;
+ mlan_ds_snmp_mib *mib = MNULL;
+ t_u32 value = 0;
+
+ ENTER();
+
+ if (pioctl_req->buf_len < sizeof(mlan_ds_snmp_mib)) {
+ PRINTM(MWARN,
+ "MLAN IOCTL information buffer length is too short.\n");
+ pioctl_req->data_read_written = 0;
+ pioctl_req->buf_len_needed = sizeof(mlan_ds_snmp_mib);
+ pioctl_req->status_code = MLAN_ERROR_INVALID_PARAMETER;
+ ret = MLAN_STATUS_RESOURCE;
+ goto exit;
+ }
+
+ mib = (mlan_ds_snmp_mib *)pioctl_req->pbuf;
+ if (pioctl_req->action == MLAN_ACT_SET)
+ cmd_action = HostCmd_ACT_GEN_SET;
+ else
+ cmd_action = HostCmd_ACT_GEN_GET;
+
+ switch (mib->sub_command) {
+ case MLAN_OID_SNMP_MIB_RTS_THRESHOLD:
+ value = mib->param.rts_threshold;
+ cmd_oid = RtsThresh_i;
+ break;
+ case MLAN_OID_SNMP_MIB_FRAG_THRESHOLD:
+ value = mib->param.frag_threshold;
+ cmd_oid = FragThresh_i;
+ break;
+ case MLAN_OID_SNMP_MIB_RETRY_COUNT:
+ value = mib->param.retry_count;
+ cmd_oid = ShortRetryLim_i;
+ break;
+ case MLAN_OID_SNMP_MIB_DTIM_PERIOD:
+ value = mib->param.dtim_period;
+ cmd_oid = DtimPeriod_i;
+ break;
+ case MLAN_OID_SNMP_MIB_SIGNALEXT_ENABLE:
+ value = mib->param.signalext_enable;
+ cmd_oid = SignalextEnable_i;
+ break;
+ }
+
+ /* Send request to firmware */
+ ret = wlan_prepare_cmd(pmpriv, HostCmd_CMD_802_11_SNMP_MIB, cmd_action,
+ cmd_oid, (t_void *)pioctl_req, &value);
+
+ if (ret == MLAN_STATUS_SUCCESS)
+ ret = MLAN_STATUS_PENDING;
+
+exit:
+ LEAVE();
+ return ret;
+}
+
+/**
+ * @brief Radio command handler
+ *
+ * @param pmadapter A pointer to mlan_adapter structure
+ * @param pioctl_req A pointer to ioctl request buffer
+ *
+ * @return MLAN_STATUS_SUCCESS --success, otherwise fail
+ */
+static mlan_status wlan_radio_ioctl(pmlan_adapter pmadapter,
+ pmlan_ioctl_req pioctl_req)
+{
+ mlan_status status = MLAN_STATUS_SUCCESS;
+ mlan_ds_radio_cfg *radio_cfg = MNULL;
+
+ ENTER();
+
+ if (pioctl_req->buf_len < sizeof(mlan_ds_radio_cfg)) {
+ PRINTM(MWARN,
+ "MLAN IOCTL information buffer length is too short.\n");
+ pioctl_req->data_read_written = 0;
+ pioctl_req->buf_len_needed = sizeof(mlan_ds_radio_cfg);
+ pioctl_req->status_code = MLAN_ERROR_INVALID_PARAMETER;
+ LEAVE();
+ return MLAN_STATUS_RESOURCE;
+ }
+ radio_cfg = (mlan_ds_radio_cfg *)pioctl_req->pbuf;
+ switch (radio_cfg->sub_command) {
+ case MLAN_OID_RADIO_CTRL:
+ status = wlan_radio_ioctl_radio_ctl(pmadapter, pioctl_req);
+ break;
+ case MLAN_OID_BAND_CFG:
+ status = wlan_radio_ioctl_band_cfg(pmadapter, pioctl_req);
+ break;
+ case MLAN_OID_ANT_CFG:
+ status = wlan_radio_ioctl_ant_cfg(pmadapter, pioctl_req);
+ break;
+ case MLAN_OID_REMAIN_CHAN_CFG:
+ status =
+ wlan_radio_ioctl_remain_chan_cfg(pmadapter, pioctl_req);
+ break;
+ case MLAN_OID_MIMO_SWITCH:
+ status =
+ wlan_radio_ioctl_mimo_switch_cfg(pmadapter, pioctl_req);
+ break;
+ default:
+ pioctl_req->status_code = MLAN_ERROR_IOCTL_INVALID;
+ status = MLAN_STATUS_FAILURE;
+ break;
+ }
+
+ LEAVE();
+ return status;
+}
+
+/**
+ * @brief Set/Get MAC address
+ *
+ * @param pmadapter A pointer to mlan_adapter structure
+ * @param pioctl_req A pointer to ioctl request buffer
+ *
+ * @return MLAN_STATUS_PENDING --success, otherwise fail
+ */
+static mlan_status wlan_bss_ioctl_mac_address(pmlan_adapter pmadapter,
+ pmlan_ioctl_req pioctl_req)
+{
+ mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index];
+ mlan_ds_bss *bss = MNULL;
+ t_u16 cmd_action;
+ mlan_status ret = MLAN_STATUS_SUCCESS;
+
+ ENTER();
+
+ bss = (mlan_ds_bss *)pioctl_req->pbuf;
+ if (pioctl_req->action == MLAN_ACT_GET) {
+ cmd_action = HostCmd_ACT_GEN_GET;
+ } else {
+ cmd_action = HostCmd_ACT_GEN_SET;
+ memcpy_ext(pmadapter, pmpriv->curr_addr, &bss->param.mac_addr,
+ MLAN_MAC_ADDR_LENGTH, MLAN_MAC_ADDR_LENGTH);
+ }
+
+ /* Send request to firmware */
+ ret = wlan_prepare_cmd(pmpriv, HostCmd_CMD_802_11_MAC_ADDRESS,
+ cmd_action, 0, (t_void *)pioctl_req, MNULL);
+ if (ret == MLAN_STATUS_SUCCESS)
+ ret = MLAN_STATUS_PENDING;
+
+ LEAVE();
+ return ret;
+}
+
+/**
+ * @brief Set multicast list
+ *
+ * @param pmadapter A pointer to mlan_adapter structure
+ * @param pioctl_req A pointer to ioctl request buffer
+ *
+ * @return MLAN_STATUS_SUCCESS/MLAN_STATUS_PENDING --success,
+ * otherwise fail
+ */
+static mlan_status wlan_bss_ioctl_set_multicast_list(pmlan_adapter pmadapter,
+ pmlan_ioctl_req pioctl_req)
+{
+ mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index];
+ mlan_ds_bss *bss = MNULL;
+ mlan_status ret = MLAN_STATUS_SUCCESS;
+ t_u16 old_pkt_filter;
+
+ ENTER();
+
+ old_pkt_filter = pmpriv->curr_pkt_filter;
+ bss = (mlan_ds_bss *)pioctl_req->pbuf;
+ if (pioctl_req->action == MLAN_ACT_GET) {
+ pioctl_req->status_code = MLAN_ERROR_IOCTL_INVALID;
+ ret = MLAN_STATUS_FAILURE;
+ goto exit;
+ }
+ pioctl_req->data_read_written =
+ sizeof(mlan_multicast_list) + MLAN_SUB_COMMAND_SIZE;
+ if (bss->param.multicast_list.mode == MLAN_PROMISC_MODE) {
+ PRINTM(MINFO, "Enable Promiscuous mode\n");
+ pmpriv->curr_pkt_filter |= HostCmd_ACT_MAC_PROMISCUOUS_ENABLE;
+ pmpriv->curr_pkt_filter &=
+ ~HostCmd_ACT_MAC_ALL_MULTICAST_ENABLE;
+ } else {
+ /* Multicast */
+ pmpriv->curr_pkt_filter &= ~HostCmd_ACT_MAC_PROMISCUOUS_ENABLE;
+ if (bss->param.multicast_list.mode == MLAN_ALL_MULTI_MODE) {
+ PRINTM(MINFO, "Enabling All Multicast!\n");
+ pmpriv->curr_pkt_filter |=
+ HostCmd_ACT_MAC_ALL_MULTICAST_ENABLE;
+ } else {
+ pmpriv->curr_pkt_filter &=
+ ~HostCmd_ACT_MAC_ALL_MULTICAST_ENABLE;
+ if (bss->param.multicast_list.num_multicast_addr) {
+ PRINTM(MINFO, "Set multicast list=%d\n",
+ bss->param.multicast_list
+ .num_multicast_addr);
+ /* Set multicast addresses to firmware */
+ if (old_pkt_filter == pmpriv->curr_pkt_filter) {
+ /* Send request to firmware */
+ ret = wlan_prepare_cmd(
+ pmpriv,
+ HostCmd_CMD_MAC_MULTICAST_ADR,
+ HostCmd_ACT_GEN_SET, 0,
+ (t_void *)pioctl_req,
+ &bss->param.multicast_list);
+ if (ret == MLAN_STATUS_SUCCESS)
+ ret = MLAN_STATUS_PENDING;
+ } else {
+ /* Send request to firmware */
+ ret = wlan_prepare_cmd(
+ pmpriv,
+ HostCmd_CMD_MAC_MULTICAST_ADR,
+ HostCmd_ACT_GEN_SET, 0, MNULL,
+ &bss->param.multicast_list);
+ }
+ if (ret)
+ goto exit;
+ }
+ }
+ }
+ PRINTM(MINFO, "old_pkt_filter=0x%x, curr_pkt_filter=0x%x\n",
+ old_pkt_filter, pmpriv->curr_pkt_filter);
+ if (old_pkt_filter != pmpriv->curr_pkt_filter) {
+ ret = wlan_prepare_cmd(pmpriv, HostCmd_CMD_MAC_CONTROL,
+ HostCmd_ACT_GEN_SET, 0,
+ (t_void *)pioctl_req,
+ &pmpriv->curr_pkt_filter);
+ if (ret == MLAN_STATUS_SUCCESS)
+ ret = MLAN_STATUS_PENDING;
+ }
+
+exit:
+ LEAVE();
+ return ret;
+}
+
+/**
+ * @brief Get channel list
+ *
+ * @param pmadapter A pointer to mlan_adapter structure
+ * @param pioctl_req A pointer to ioctl request buffer
+ *
+ * @return MLAN_STATUS_SUCCESS --success, otherwise fail
+ */
+static mlan_status wlan_bss_ioctl_get_channel_list(pmlan_adapter pmadapter,
+ pmlan_ioctl_req pioctl_req)
+{
+ mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index];
+ mlan_ds_bss *bss = MNULL;
+ mlan_status ret = MLAN_STATUS_SUCCESS;
+ chan_freq_power_t *cfp;
+ t_u32 i, j;
+
+ ENTER();
+
+ bss = (mlan_ds_bss *)pioctl_req->pbuf;
+ if (pioctl_req->action != MLAN_ACT_GET) {
+ pioctl_req->status_code = MLAN_ERROR_IOCTL_INVALID;
+ LEAVE();
+ return MLAN_STATUS_FAILURE;
+ }
+ if ((wlan_11d_is_enabled(pmpriv) && pmpriv->media_connected == MTRUE) &&
+ ((pmpriv->bss_mode == MLAN_BSS_MODE_INFRA) ||
+ (pmpriv->bss_mode == MLAN_BSS_MODE_IBSS &&
+ pmpriv->adhoc_state != ADHOC_STARTED))) {
+ t_u8 chan_no;
+ t_u8 band;
+
+ parsed_region_chan_11d_t *parsed_region_chan = MNULL;
+ parsed_region_chan_11d_t region_chan;
+
+ BSSDescriptor_t *pbss_desc =
+ &pmpriv->curr_bss_params.bss_descriptor;
+
+ memset(pmadapter, &region_chan, 0,
+ sizeof(parsed_region_chan_11d_t));
+
+ /*If country IE is present in the associated AP then return the
+ channel list from country IE
+ else return it from the learning table*/
+
+ if (wlan_11d_parse_domain_info(
+ pmadapter, &pbss_desc->country_info,
+ (t_u8)pbss_desc->bss_band,
+ &region_chan) == MLAN_STATUS_SUCCESS) {
+ parsed_region_chan = &region_chan;
+ } else {
+ parsed_region_chan = &pmadapter->parsed_region_chan;
+ }
+
+ PRINTM(MINFO, "no_of_chan=%d\n",
+ parsed_region_chan->no_of_chan);
+
+ for (i = 0;
+ (bss->param.chanlist.num_of_chan < MLAN_MAX_CHANNEL_NUM) &&
+ (i < parsed_region_chan->no_of_chan);
+ i++) {
+ chan_no = parsed_region_chan->chan_pwr[i].chan;
+ band = parsed_region_chan->chan_pwr[i].band;
+ PRINTM(MINFO, "band=%d, chan_no=%d\n", band, chan_no);
+ bss->param.chanlist.cf[bss->param.chanlist.num_of_chan]
+ .channel = (t_u32)chan_no;
+ bss->param.chanlist.cf[bss->param.chanlist.num_of_chan]
+ .freq = (t_u32)wlan_11d_chan_2_freq(
+ pmadapter, chan_no, band);
+ bss->param.chanlist.num_of_chan++;
+ }
+ } else {
+ for (j = 0;
+ (bss->param.chanlist.num_of_chan < MLAN_MAX_CHANNEL_NUM) &&
+ (j < MAX_REGION_CHANNEL_NUM);
+ j++) {
+ cfp = pmadapter->region_channel[j].pcfp;
+ for (i = 0; (bss->param.chanlist.num_of_chan <
+ MLAN_MAX_CHANNEL_NUM) &&
+ pmadapter->region_channel[j].valid && cfp &&
+ (i < pmadapter->region_channel[j].num_cfp);
+ i++) {
+ bss->param.chanlist
+ .cf[bss->param.chanlist.num_of_chan]
+ .channel = (t_u32)cfp->channel;
+ bss->param.chanlist
+ .cf[bss->param.chanlist.num_of_chan]
+ .freq = (t_u32)cfp->freq;
+ bss->param.chanlist.num_of_chan++;
+ cfp++;
+ }
+ }
+ }
+
+ PRINTM(MINFO, "num of channel=%d\n", bss->param.chanlist.num_of_chan);
+
+ LEAVE();
+ return ret;
+}
+
+/** Highest channel used in 2.4GHz band */
+#define MAX_CHANNEL_BAND_B (14)
+
+/** Highest frequency used in 2.4GHz band */
+#define MAX_FREQUENCY_BAND_B (2484)
+
+/**
+ * @brief Set/Get BSS channel
+ *
+ * @param pmadapter A pointer to mlan_adapter structure
+ * @param pioctl_req A pointer to ioctl request buffer
+ *
+ * @return MLAN_STATUS_SUCCESS --success, otherwise fail
+ */
+static mlan_status wlan_bss_ioctl_channel(pmlan_adapter pmadapter,
+ pmlan_ioctl_req pioctl_req)
+{
+ mlan_private *pmpriv = MNULL;
+ mlan_ds_bss *bss = MNULL;
+ mlan_status ret = MLAN_STATUS_SUCCESS;
+ chan_freq_power_t *cfp = MNULL;
+ ENTER();
+
+ if ((pioctl_req == MNULL) || (pioctl_req->pbuf == MNULL)) {
+ PRINTM(MERROR, "Request buffer not found!\n");
+ LEAVE();
+ return MLAN_STATUS_FAILURE;
+ }
+ pmpriv = pmadapter->priv[pioctl_req->bss_index];
+ bss = (mlan_ds_bss *)pioctl_req->pbuf;
+ if (pioctl_req->action == MLAN_ACT_GET) {
+ cfp = wlan_find_cfp_by_band_and_channel(
+ pmadapter, pmpriv->curr_bss_params.band,
+ (t_u16)pmpriv->curr_bss_params.bss_descriptor.channel);
+ if (cfp) {
+ bss->param.bss_chan.channel = cfp->channel;
+ bss->param.bss_chan.freq = cfp->freq;
+ } else {
+ pioctl_req->status_code = MLAN_ERROR_INVALID_PARAMETER;
+ ret = MLAN_STATUS_FAILURE;
+ }
+ pioctl_req->data_read_written =
+ sizeof(chan_freq) + MLAN_SUB_COMMAND_SIZE;
+ LEAVE();
+ return ret;
+ }
+ if (!bss->param.bss_chan.channel && !bss->param.bss_chan.freq) {
+ pioctl_req->status_code = MLAN_ERROR_INVALID_PARAMETER;
+ LEAVE();
+ return MLAN_STATUS_FAILURE;
+ }
+ if (pmadapter->adhoc_start_band & BAND_A)
+ pmadapter->adhoc_start_band = BAND_G | BAND_B;
+ if (bss->param.bss_chan.channel) {
+ if (bss->param.bss_chan.channel <= MAX_CHANNEL_BAND_B)
+ cfp = wlan_find_cfp_by_band_and_channel(
+ pmadapter, BAND_B,
+ (t_u16)bss->param.bss_chan.channel);
+ if (!cfp) {
+ cfp = wlan_find_cfp_by_band_and_channel(
+ pmadapter, BAND_A,
+ (t_u16)bss->param.bss_chan.channel);
+ if (cfp) {
+ pmadapter->adhoc_start_band = BAND_A;
+ }
+ }
+ } else {
+ if (bss->param.bss_chan.freq <= MAX_FREQUENCY_BAND_B)
+ cfp = wlan_find_cfp_by_band_and_freq(
+ pmadapter, BAND_B, bss->param.bss_chan.freq);
+ if (!cfp) {
+ cfp = wlan_find_cfp_by_band_and_freq(
+ pmadapter, BAND_A, bss->param.bss_chan.freq);
+ if (cfp) {
+ pmadapter->adhoc_start_band = BAND_A;
+ }
+ }
+ }
+ if (!cfp || !cfp->channel) {
+ PRINTM(MERROR, "Invalid channel/freq\n");
+ if (pioctl_req)
+ pioctl_req->status_code = MLAN_ERROR_INVALID_PARAMETER;
+ LEAVE();
+ return MLAN_STATUS_FAILURE;
+ }
+ pmpriv->adhoc_channel = (t_u8)cfp->channel;
+ pmpriv->intf_state_11h.adhoc_auto_sel_chan = MFALSE;
+ bss->param.bss_chan.channel = cfp->channel;
+ bss->param.bss_chan.freq = cfp->freq;
+
+ LEAVE();
+ return ret;
+}
+
+/**
+ * @brief Set/Get BSS mode
+ *
+ * @param pmadapter A pointer to mlan_adapter structure
+ * @param pioctl_req A pointer to ioctl request buffer
+ *
+ * @return MLAN_STATUS_SUCCESS/MLAN_STATUS_PENDING --success,
+ * otherwise fail
+ */
+static mlan_status wlan_bss_ioctl_mode(pmlan_adapter pmadapter,
+ pmlan_ioctl_req pioctl_req)
+{
+ mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index];
+ mlan_ds_bss *bss = MNULL;
+ mlan_status ret = MLAN_STATUS_SUCCESS;
+ bss = (mlan_ds_bss *)pioctl_req->pbuf;
+
+ ENTER();
+
+ if (pioctl_req->action == MLAN_ACT_GET) {
+ bss->param.bss_mode = pmpriv->bss_mode;
+ pioctl_req->data_read_written =
+ sizeof(t_u32) + MLAN_SUB_COMMAND_SIZE;
+ goto exit;
+ }
+
+ if ((pmpriv->bss_mode == bss->param.bss_mode) ||
+ (bss->param.bss_mode == MLAN_BSS_MODE_AUTO)) {
+ PRINTM(MINFO, "Already set to required mode! No change!\n");
+ pmpriv->bss_mode = bss->param.bss_mode;
+ goto exit;
+ }
+
+ if (pmpriv->bss_mode != MLAN_BSS_MODE_AUTO)
+ ret = wlan_disconnect(pmpriv, MNULL, MNULL);
+ else
+ ret = wlan_disconnect(pmpriv, pioctl_req, MNULL);
+
+ if (pmpriv->sec_info.authentication_mode != MLAN_AUTH_MODE_AUTO)
+ pmpriv->sec_info.authentication_mode = MLAN_AUTH_MODE_OPEN;
+ pmpriv->bss_mode = bss->param.bss_mode;
+ if (pmpriv->bss_mode == MLAN_BSS_MODE_INFRA)
+ pmpriv->port_ctrl_mode = MTRUE;
+ else
+ pmpriv->port_ctrl_mode = MFALSE;
+ if (pmpriv->bss_mode != MLAN_BSS_MODE_AUTO) {
+ ret = wlan_prepare_cmd(pmpriv, HostCmd_CMD_SET_BSS_MODE,
+ HostCmd_ACT_GEN_SET, 0,
+ (t_void *)pioctl_req, MNULL);
+ if (ret == MLAN_STATUS_SUCCESS)
+ ret = MLAN_STATUS_PENDING;
+ }
+exit:
+ LEAVE();
+ return ret;
+}
+
+/**
+ * @brief Start BSS
+ *
+ * @param pmadapter A pointer to mlan_adapter structure
+ * @param pioctl_req A pointer to ioctl request buffer
+ *
+ * @return MLAN_STATUS_PENDING --success, otherwise fail
+ */
+static mlan_status wlan_bss_ioctl_start(pmlan_adapter pmadapter,
+ pmlan_ioctl_req pioctl_req)
+{
+ mlan_status ret = MLAN_STATUS_SUCCESS;
+ mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index];
+ mlan_ds_bss *bss = (mlan_ds_bss *)pioctl_req->pbuf;
+ t_s32 i = -1;
+ t_u8 zero_mac[] = {0, 0, 0, 0, 0, 0};
+
+ ENTER();
+
+ /* Before ASSOC REQ, If "port ctrl" mode is enabled,
+ * move the port to CLOSED state */
+ if (pmpriv->port_ctrl_mode == MTRUE) {
+ PRINTM(MINFO, "bss_ioctl_start(): port_state=CLOSED\n");
+ pmpriv->prior_port_status = pmpriv->port_open;
+ pmpriv->port_open = MFALSE;
+ }
+ pmadapter->scan_block = MFALSE;
+
+ if (pmpriv->bss_mode == MLAN_BSS_MODE_INFRA) {
+ if (!bss->param.ssid_bssid.idx ||
+ bss->param.ssid_bssid.idx > pmadapter->num_in_scan_table) {
+ /* Search for the requested SSID in the scan table */
+ if (bss->param.ssid_bssid.ssid.ssid_len) {
+ if (memcmp(pmadapter,
+ &bss->param.ssid_bssid.bssid,
+ zero_mac, sizeof(zero_mac)))
+ i = wlan_find_ssid_in_list(
+ pmpriv,
+ &bss->param.ssid_bssid.ssid,
+ (t_u8 *)&bss->param.ssid_bssid
+ .bssid,
+ MLAN_BSS_MODE_INFRA);
+ else
+ i = wlan_find_ssid_in_list(
+ pmpriv,
+ &bss->param.ssid_bssid.ssid,
+ MNULL, MLAN_BSS_MODE_INFRA);
+ } else {
+ i = wlan_find_bssid_in_list(
+ pmpriv,
+ (t_u8 *)&bss->param.ssid_bssid.bssid,
+ MLAN_BSS_MODE_INFRA);
+ }
+ } else {
+ /* use bsslist index number to assoicate */
+ i = wlan_is_network_compatible(
+ pmpriv, bss->param.ssid_bssid.idx - 1,
+ pmpriv->bss_mode);
+ }
+ if (i >= 0) {
+ /* block if upper-layer tries to reconnect before new
+ * scan */
+ if (wlan_11h_get_csa_closed_channel(pmpriv) ==
+ (t_u8)pmadapter->pscan_table[i].channel) {
+ PRINTM(MINFO,
+ "Attempt to reconnect on csa_closed_chan(%d)\n",
+ pmadapter->pscan_table[i].channel);
+ pioctl_req->status_code =
+ MLAN_ERROR_INVALID_PARAMETER;
+ ret = MLAN_STATUS_FAILURE;
+ goto start_ssid_done;
+ }
+ PRINTM(MINFO,
+ "SSID found in scan list ... associating...\n");
+ pmpriv->curr_bss_params.host_mlme =
+ bss->param.ssid_bssid.host_mlme;
+ /* Clear any past association response stored for
+ * application retrieval */
+ pmpriv->assoc_rsp_size = 0;
+ pmpriv->curr_chan_flags =
+ bss->param.ssid_bssid.channel_flags;
+ if (IS_FW_SUPPORT_NO_80MHZ(pmadapter))
+ pmpriv->curr_chan_flags |= CHAN_FLAGS_NO_80MHZ;
+ ret = wlan_associate(pmpriv, pioctl_req,
+ &pmadapter->pscan_table[i]);
+ if (ret)
+ goto start_ssid_done;
+ } else { /* i >= 0 */
+ PRINTM(MERROR,
+ "SSID not found in scan list: ssid=%s, " MACSTR
+ ", idx=%d\n",
+ bss->param.ssid_bssid.ssid.ssid,
+ MAC2STR(bss->param.ssid_bssid.bssid),
+ (int)bss->param.ssid_bssid.idx);
+ pioctl_req->status_code = MLAN_ERROR_INVALID_PARAMETER;
+ ret = MLAN_STATUS_FAILURE;
+ goto start_ssid_done;
+ }
+ } else {
+ /* Adhoc mode */
+ /* If the requested SSID matches current SSID, return */
+ if (bss->param.ssid_bssid.ssid.ssid_len &&
+ (!wlan_ssid_cmp(pmadapter,
+ &pmpriv->curr_bss_params.bss_descriptor.ssid,
+ &bss->param.ssid_bssid.ssid))) {
+ ret = MLAN_STATUS_SUCCESS;
+ goto start_ssid_done;
+ }
+
+ /* Exit Adhoc mode first */
+ PRINTM(MINFO, "Sending Adhoc Stop\n");
+ ret = wlan_disconnect(pmpriv, MNULL, MNULL);
+ if (ret)
+ goto start_ssid_done;
+
+ pmpriv->adhoc_is_link_sensed = MFALSE;
+
+ if (!bss->param.ssid_bssid.idx ||
+ bss->param.ssid_bssid.idx > pmadapter->num_in_scan_table) {
+ /* Search for the requested network in the scan table */
+ if (bss->param.ssid_bssid.ssid.ssid_len) {
+ i = wlan_find_ssid_in_list(
+ pmpriv, &bss->param.ssid_bssid.ssid,
+ MNULL, MLAN_BSS_MODE_IBSS);
+ } else {
+ i = wlan_find_bssid_in_list(
+ pmpriv,
+ (t_u8 *)&bss->param.ssid_bssid.bssid,
+ MLAN_BSS_MODE_IBSS);
+ }
+ } else {
+ /* use bsslist index number to assoicate */
+ i = wlan_is_network_compatible(
+ pmpriv, bss->param.ssid_bssid.idx - 1,
+ pmpriv->bss_mode);
+ }
+
+ if (i >= 0) {
+ PRINTM(MINFO,
+ "Network found in scan list ... joining ...\n");
+ pmpriv->curr_chan_flags =
+ bss->param.ssid_bssid.channel_flags;
+ ret = wlan_adhoc_join(pmpriv, pioctl_req,
+ &pmadapter->pscan_table[i]);
+ if (ret)
+ goto start_ssid_done;
+ } else { /* i >= 0 */
+ PRINTM(MINFO,
+ "Network not found in the list, "
+ "creating adhoc with ssid = %s\n",
+ bss->param.ssid_bssid.ssid.ssid);
+ pmpriv->curr_chan_flags =
+ bss->param.ssid_bssid.channel_flags;
+ ret = wlan_adhoc_start(pmpriv, pioctl_req,
+ &bss->param.ssid_bssid.ssid);
+ if (ret)
+ goto start_ssid_done;
+ }
+ }
+
+ if (ret == MLAN_STATUS_SUCCESS)
+ ret = MLAN_STATUS_PENDING;
+
+start_ssid_done:
+ LEAVE();
+ return ret;
+}
+
+/**
+ * @brief Stop BSS
+ *
+ * @param pmadapter A pointer to mlan_adapter structure
+ * @param pioctl_req A pointer to ioctl request buffer
+ *
+ * @return MLAN_STATUS_SUCCESS/MLAN_STATUS_PENDING --success,
+ * otherwise fail
+ */
+static mlan_status wlan_bss_ioctl_stop(pmlan_adapter pmadapter,
+ pmlan_ioctl_req pioctl_req)
+{
+ mlan_status ret = MLAN_STATUS_SUCCESS;
+ pmlan_private pmpriv = pmadapter->priv[pioctl_req->bss_index];
+ mlan_ds_bss *bss = (mlan_ds_bss *)pioctl_req->pbuf;
+
+ ENTER();
+
+ ret = wlan_disconnect(pmpriv, pioctl_req, &bss->param.deauth_param);
+
+ LEAVE();
+ return ret;
+}
+
+/**
+ * @brief Set/Get IBSS channel
+ *
+ * @param pmadapter A pointer to mlan_adapter structure
+ * @param pioctl_req A pointer to ioctl request buffer
+ *
+ * @return MLAN_STATUS_SUCCESS/MLAN_STATUS_PENDING --success,
+ * otherwise fail
+ */
+static mlan_status wlan_bss_ioctl_ibss_channel(pmlan_adapter pmadapter,
+ pmlan_ioctl_req pioctl_req)
+{
+ mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index];
+ mlan_ds_bss *bss = MNULL;
+ mlan_status ret = MLAN_STATUS_SUCCESS;
+ t_u16 cmd_action;
+
+ ENTER();
+
+ bss = (mlan_ds_bss *)pioctl_req->pbuf;
+ if (pioctl_req->action == MLAN_ACT_GET) {
+ if (pmpriv->media_connected == MFALSE) {
+ bss->param.bss_chan.channel = pmpriv->adhoc_channel;
+ goto exit;
+ }
+ cmd_action = HostCmd_ACT_GEN_GET;
+ } else {
+ cmd_action = HostCmd_ACT_GEN_SET;
+ pmpriv->adhoc_channel = (t_u8)bss->param.bss_chan.channel;
+ pmpriv->intf_state_11h.adhoc_auto_sel_chan = MFALSE;
+ }
+
+ /* Send request to firmware */
+ ret = wlan_prepare_cmd(pmpriv, HostCmd_CMD_802_11_RF_CHANNEL,
+ cmd_action, 0, (t_void *)pioctl_req,
+ &bss->param.bss_chan.channel);
+ if (ret == MLAN_STATUS_SUCCESS)
+ ret = MLAN_STATUS_PENDING;
+
+exit:
+ LEAVE();
+ return ret;
+}
+
+/**
+ * @brief Set/Get Listen Interval
+ *
+ * @param pmadapter A pointer to mlan_adapter structure
+ * @param pioctl_req A pointer to ioctl request buffer
+ *
+ * @return MLAN_STATUS_SUCCESS/MLAN_STATUS_PENDING --success,
+ * otherwise fail
+ */
+static mlan_status wlan_bss_ioctl_listen_interval(pmlan_adapter pmadapter,
+ pmlan_ioctl_req pioctl_req)
+{
+ mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index];
+ mlan_ds_bss *bss = MNULL;
+
+ ENTER();
+
+ bss = (mlan_ds_bss *)pioctl_req->pbuf;
+ if (pioctl_req->action == MLAN_ACT_GET)
+ bss->param.listen_interval = pmpriv->listen_interval;
+ else
+ pmpriv->listen_interval = bss->param.listen_interval;
+
+ LEAVE();
+ return MLAN_STATUS_SUCCESS;
+}
+
+/*
+ * @brief Set/Get beacon interval
+ *
+ * @param pmadapter A pointer to mlan_adapter structure
+ * @param pioctl_req A pointer to ioctl request buffer
+ *
+ * @return MLAN_STATUS_SUCCESS --success
+ */
+static mlan_status wlan_bss_ioctl_beacon_interval(pmlan_adapter pmadapter,
+ pmlan_ioctl_req pioctl_req)
+{
+ mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index];
+ mlan_ds_bss *bss = MNULL;
+ mlan_status ret = MLAN_STATUS_SUCCESS;
+ ENTER();
+ bss = (mlan_ds_bss *)pioctl_req->pbuf;
+ if (pioctl_req->action == MLAN_ACT_GET) {
+ bss->param.bcn_interval = pmpriv->beacon_period;
+ if (pmpriv->media_connected == MTRUE)
+ bss->param.bcn_interval =
+ pmpriv->curr_bss_params.bss_descriptor
+ .beacon_period;
+ } else
+ pmpriv->beacon_period = (t_u16)bss->param.bcn_interval;
+ pioctl_req->data_read_written = sizeof(t_u32) + MLAN_SUB_COMMAND_SIZE;
+ LEAVE();
+ return ret;
+}
+
+/**
+ * @brief Set/Get ATIM window
+ *
+ * @param pmadapter A pointer to mlan_adapter structure
+ * @param pioctl_req A pointer to ioctl request buffer
+ *
+ * @return MLAN_STATUS_SUCCESS --success
+ */
+static mlan_status wlan_bss_ioctl_atim_window(pmlan_adapter pmadapter,
+ pmlan_ioctl_req pioctl_req)
+{
+ mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index];
+ mlan_ds_bss *bss = MNULL;
+ mlan_status ret = MLAN_STATUS_SUCCESS;
+ ENTER();
+ bss = (mlan_ds_bss *)pioctl_req->pbuf;
+ if (pioctl_req->action == MLAN_ACT_GET) {
+ bss->param.atim_window = pmpriv->atim_window;
+ if (pmpriv->media_connected == MTRUE)
+ bss->param.atim_window =
+ pmpriv->curr_bss_params.bss_descriptor
+ .atim_window;
+ } else
+ pmpriv->atim_window = (t_u16)bss->param.atim_window;
+
+ pioctl_req->data_read_written = sizeof(t_u32) + MLAN_SUB_COMMAND_SIZE;
+ LEAVE();
+ return ret;
+}
+
+/**
+ * @brief Query embe
+ *
+ * @param priv A pointer to mlan_private structure
+ * @param pioctl_req A pointer to ioctl request buffer
+ *
+ * @return MLAN_STATUS_SUCCESS -- success, otherwise fail
+ */
+static mlan_status wlan_query_passphrase(mlan_private *priv,
+ pmlan_ioctl_req pioctl_req)
+{
+ mlan_adapter *pmadapter = priv->adapter;
+ pmlan_callbacks pcb = &pmadapter->callbacks;
+ mlan_ds_bss *bss = MNULL;
+ mlan_ssid_bssid *ssid_bssid = MNULL;
+ mlan_ds_sec_cfg *sec = MNULL;
+ mlan_ds_passphrase *sec_pp;
+ int i = 0;
+ BSSDescriptor_t *pbss_desc;
+ mlan_status ret = MLAN_STATUS_SUCCESS;
+
+ ENTER();
+
+ bss = (mlan_ds_bss *)pioctl_req->pbuf;
+ ssid_bssid = &bss->param.ssid_bssid;
+
+ ret = pcb->moal_malloc(pmadapter->pmoal_handle, sizeof(mlan_ds_sec_cfg),
+ MLAN_MEM_DEF, (t_u8 **)&sec);
+ if (ret || !sec) {
+ PRINTM(MERROR, "Could not allocate sec!\n");
+ LEAVE();
+ return ret;
+ }
+ memset(pmadapter, sec, 0, sizeof(mlan_ds_sec_cfg));
+ sec_pp = (mlan_ds_passphrase *)&sec->param.passphrase;
+ sec_pp->psk_type = MLAN_PSK_QUERY;
+ if (ssid_bssid->ssid.ssid_len == 0) {
+ i = wlan_find_bssid_in_list(priv, (t_u8 *)&ssid_bssid->bssid,
+ MLAN_BSS_MODE_AUTO);
+ if (i >= 0) {
+ pbss_desc = &pmadapter->pscan_table[i];
+ memcpy_ext(pmadapter, (t_u8 *)&sec_pp->ssid,
+ &pbss_desc->ssid, sizeof(mlan_802_11_ssid),
+ sizeof(mlan_802_11_ssid));
+ } else
+ memcpy_ext(pmadapter, (t_u8 *)&sec_pp->bssid,
+ &ssid_bssid->bssid, MLAN_MAC_ADDR_LENGTH,
+ MLAN_MAC_ADDR_LENGTH);
+ } else {
+ memcpy_ext(pmadapter, (t_u8 *)&sec_pp->ssid, &ssid_bssid->ssid,
+ sizeof(mlan_802_11_ssid), sizeof(mlan_802_11_ssid));
+ }
+
+ /* Send request to firmware */
+ ret = wlan_prepare_cmd(priv, HostCmd_CMD_SUPPLICANT_PMK,
+ HostCmd_ACT_GEN_GET, 0, (t_void *)pioctl_req,
+ (t_void *)sec);
+ if (sec)
+ pcb->moal_mfree(pmadapter->pmoal_handle, (t_u8 *)sec);
+ LEAVE();
+ return ret;
+}
+
+/**
+ * @brief Search for a BSS
+ *
+ * @param pmadapter A pointer to mlan_adapter structure
+ * @param pioctl_req A pointer to ioctl request buffer
+ *
+ * @return MLAN_STATUS_SUCCESS/MLAN_STATUS_PENDING --success,
+ * otherwise fail
+ */
+mlan_status wlan_bss_ioctl_find_bss(pmlan_adapter pmadapter,
+ pmlan_ioctl_req pioctl_req)
+{
+ mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index];
+ mlan_status ret = MLAN_STATUS_SUCCESS;
+#ifdef DRV_EMBEDDED_SUPPLICANT
+ mlan_ds_bss *bss = MNULL;
+ mlan_ssid_bssid *ssid_bssid = MNULL;
+#endif
+
+ ENTER();
+
+ if (pmpriv->ewpa_query) {
+ if (wlan_query_passphrase(pmpriv, pioctl_req) ==
+ MLAN_STATUS_SUCCESS) {
+ PRINTM(MINFO, "Find BSS ioctl: query passphrase\n");
+ LEAVE();
+ return MLAN_STATUS_PENDING;
+ }
+ }
+#ifdef DRV_EMBEDDED_SUPPLICANT
+ if (!IS_FW_SUPPORT_SUPPLICANT(pmpriv->adapter)) {
+ bss = (mlan_ds_bss *)pioctl_req->pbuf;
+ ssid_bssid = &bss->param.ssid_bssid;
+ supplicantQueryPassphraseAndEnable(pmpriv->psapriv,
+ (t_u8 *)ssid_bssid);
+ }
+#endif
+
+ ret = wlan_find_bss(pmpriv, pioctl_req);
+
+ LEAVE();
+ return ret;
+}
+
+/**
+ * @brief Search for a BSS
+ *
+ * @param pmadapter A pointer to mlan_adapter structure
+ * @param pioctl_req A pointer to ioctl request buffer
+ *
+ * @return MLAN_STATUS_SUCCESS/MLAN_STATUS_PENDING --success,
+ * otherwise fail
+ */
+mlan_status wlan_bss_ioctl_find_bssid(pmlan_adapter pmadapter,
+ pmlan_ioctl_req pioctl_req)
+{
+ mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index];
+ mlan_ds_bss *bss = MNULL;
+ mlan_status ret = MLAN_STATUS_SUCCESS;
+ int i = 0;
+
+ ENTER();
+ bss = (mlan_ds_bss *)pioctl_req->pbuf;
+ i = wlan_find_bssid_in_list(pmpriv, (t_u8 *)&bss->param.bssid,
+ MLAN_BSS_MODE_AUTO);
+ if (i < 0) {
+ PRINTM(MCMND, "Can not find bssid " MACSTR "\n",
+ MAC2STR((t_u8 *)&bss->param.bssid));
+ pioctl_req->status_code = MLAN_ERROR_INVALID_PARAMETER;
+ LEAVE();
+ return MLAN_STATUS_FAILURE;
+ }
+ PRINTM(MCMND, "Find bssid " MACSTR "\n",
+ MAC2STR((t_u8 *)&bss->param.bssid));
+ LEAVE();
+ return ret;
+}
+
+/**
+ * @brief Check if BSS channel is valid for Station's region
+ *
+ * @param pmadapter A pointer to mlan_adapter structure
+ * @param pioctl_req A pointer to ioctl request buffer
+ *
+ * @return MLAN_STATUS_SUCCESS/MLAN_STATUS_PENDING --success,
+ * otherwise fail
+ */
+mlan_status wlan_bss_ioctl_bss_11d_check_channel(pmlan_adapter pmadapter,
+ pmlan_ioctl_req pioctl_req)
+{
+ mlan_status ret = MLAN_STATUS_SUCCESS;
+ mlan_ds_bss *bss = MNULL;
+ mlan_ssid_bssid *ssid_bssid = MNULL;
+
+ ENTER();
+
+ bss = (mlan_ds_bss *)pioctl_req->pbuf;
+ ssid_bssid = &bss->param.ssid_bssid;
+
+ PRINTM(MINFO, "ssid: %s idx:%d\n", ssid_bssid->ssid.ssid,
+ ssid_bssid->idx);
+ PRINTM(MINFO, "band:%d channel:%d\n", (t_u8)ssid_bssid->bss_band,
+ (t_u32)ssid_bssid->channel);
+
+ /* check if this channel is supported in the region */
+ if (!wlan_find_cfp_by_band_and_channel(pmadapter,
+ (t_u8)ssid_bssid->bss_band,
+ (t_u32)ssid_bssid->channel)) {
+ PRINTM(MERROR, "Unsupported Channel for region 0x%x\n",
+ pmadapter->region_code);
+ ret = MLAN_STATUS_FAILURE;
+ }
+
+ LEAVE();
+ return ret;
+}
+
+/**
+ * @brief BSS command handler
+ *
+ * @param pmadapter A pointer to mlan_adapter structure
+ * @param pioctl_req A pointer to ioctl request buffer
+ *
+ * @return MLAN_STATUS_SUCCESS --success, otherwise fail
+ */
+static mlan_status wlan_bss_ioctl(pmlan_adapter pmadapter,
+ pmlan_ioctl_req pioctl_req)
+{
+ mlan_status status = MLAN_STATUS_SUCCESS;
+ mlan_ds_bss *bss = MNULL;
+
+ ENTER();
+
+ if (pioctl_req->buf_len < sizeof(mlan_ds_bss)) {
+ PRINTM(MWARN, "MLAN bss IOCTL length is too short.\n");
+ pioctl_req->data_read_written = 0;
+ pioctl_req->buf_len_needed = sizeof(mlan_ds_bss);
+ pioctl_req->status_code = MLAN_ERROR_INVALID_PARAMETER;
+ LEAVE();
+ return MLAN_STATUS_RESOURCE;
+ }
+
+ bss = (mlan_ds_bss *)pioctl_req->pbuf;
+
+ switch (bss->sub_command) {
+ case MLAN_OID_BSS_START:
+ status = wlan_bss_ioctl_start(pmadapter, pioctl_req);
+ break;
+ case MLAN_OID_BSS_STOP:
+ status = wlan_bss_ioctl_stop(pmadapter, pioctl_req);
+ break;
+ case MLAN_OID_BSS_MODE:
+ status = wlan_bss_ioctl_mode(pmadapter, pioctl_req);
+ break;
+ case MLAN_OID_BSS_CHANNEL:
+ status = wlan_bss_ioctl_channel(pmadapter, pioctl_req);
+ break;
+ case MLAN_OID_BSS_CHANNEL_LIST:
+ status = wlan_bss_ioctl_get_channel_list(pmadapter, pioctl_req);
+ break;
+ case MLAN_OID_BSS_MAC_ADDR:
+ status = wlan_bss_ioctl_mac_address(pmadapter, pioctl_req);
+ break;
+ case MLAN_OID_BSS_MULTICAST_LIST:
+ status = wlan_bss_ioctl_set_multicast_list(pmadapter,
+ pioctl_req);
+ break;
+ case MLAN_OID_BSS_FIND_BSS:
+ status = wlan_bss_ioctl_find_bss(pmadapter, pioctl_req);
+ break;
+ case MLAN_OID_BSS_FIND_BSSID:
+ status = wlan_bss_ioctl_find_bssid(pmadapter, pioctl_req);
+ break;
+ case MLAN_OID_IBSS_BCN_INTERVAL:
+ status = wlan_bss_ioctl_beacon_interval(pmadapter, pioctl_req);
+ break;
+ case MLAN_OID_IBSS_ATIM_WINDOW:
+ status = wlan_bss_ioctl_atim_window(pmadapter, pioctl_req);
+ break;
+ case MLAN_OID_IBSS_CHANNEL:
+ status = wlan_bss_ioctl_ibss_channel(pmadapter, pioctl_req);
+ break;
+#if defined(STA_SUPPORT) && defined(UAP_SUPPORT)
+ case MLAN_OID_BSS_ROLE:
+ util_enqueue_list_tail(pmadapter->pmoal_handle,
+ &pmadapter->ioctl_pending_q,
+ (pmlan_linked_list)pioctl_req,
+ pmadapter->callbacks.moal_spin_lock,
+ pmadapter->callbacks.moal_spin_unlock);
+ pmadapter->pending_ioctl = MTRUE;
+ status = MLAN_STATUS_PENDING;
+ break;
+#endif
+#ifdef WIFI_DIRECT_SUPPORT
+ case MLAN_OID_WIFI_DIRECT_MODE:
+ status = wlan_bss_ioctl_wifi_direct_mode(pmadapter, pioctl_req);
+ break;
+#endif
+ case MLAN_OID_BSS_LISTEN_INTERVAL:
+ status = wlan_bss_ioctl_listen_interval(pmadapter, pioctl_req);
+ break;
+ case MLAN_OID_BSS_REMOVE:
+ status = wlan_bss_ioctl_bss_remove(pmadapter, pioctl_req);
+ break;
+
+ case MLAN_OID_BSS_11D_CHECK_CHANNEL:
+ status = wlan_bss_ioctl_bss_11d_check_channel(pmadapter,
+ pioctl_req);
+ break;
+ case MLAN_OID_BSS_CHAN_INFO:
+ status = wlan_bss_ioctl_get_chan_info(pmadapter, pioctl_req);
+ break;
+ default:
+ status = MLAN_STATUS_FAILURE;
+ break;
+ }
+
+ LEAVE();
+ return status;
+}
+
+/**
+ * @brief Get supported rates
+ *
+ * @param pmadapter A pointer to mlan_adapter structure
+ * @param pioctl_req A pointer to ioctl request buffer
+ *
+ * @return MLAN_STATUS_SUCCESS --success, otherwise fail
+ */
+static mlan_status
+wlan_rate_ioctl_get_supported_rate(pmlan_adapter pmadapter,
+ pmlan_ioctl_req pioctl_req)
+{
+ mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index];
+ mlan_ds_rate *rate = MNULL;
+ mlan_status ret = MLAN_STATUS_SUCCESS;
+
+ ENTER();
+ if (pioctl_req->action != MLAN_ACT_GET) {
+ pioctl_req->status_code = MLAN_ERROR_IOCTL_INVALID;
+ LEAVE();
+ return MLAN_STATUS_FAILURE;
+ }
+ rate = (mlan_ds_rate *)pioctl_req->pbuf;
+ if (rate->param.rate_band_cfg.config_bands &&
+ rate->param.rate_band_cfg.bss_mode)
+ wlan_get_active_data_rates(
+ pmpriv, rate->param.rate_band_cfg.bss_mode,
+ rate->param.rate_band_cfg.config_bands,
+ rate->param.rates);
+ else
+ wlan_get_active_data_rates(pmpriv, pmpriv->bss_mode,
+ (pmpriv->bss_mode ==
+ MLAN_BSS_MODE_INFRA) ?
+ pmpriv->config_bands :
+ pmadapter->adhoc_start_band,
+ rate->param.rates);
+ pioctl_req->data_read_written =
+ MLAN_SUPPORTED_RATES + MLAN_SUB_COMMAND_SIZE;
+ LEAVE();
+ return ret;
+}
+
+/**
+ * @brief Rate command handler
+ *
+ * @param pmadapter A pointer to mlan_adapter structure
+ * @param pioctl_req A pointer to ioctl request buffer
+ *
+ * @return MLAN_STATUS_SUCCESS/MLAN_STATUS_PENDING --success,
+ * otherwise fail
+ */
+static mlan_status wlan_rate_ioctl(pmlan_adapter pmadapter,
+ pmlan_ioctl_req pioctl_req)
+{
+ mlan_status status = MLAN_STATUS_SUCCESS;
+ mlan_ds_rate *rate = MNULL;
+
+ ENTER();
+
+ if (pioctl_req->buf_len < sizeof(mlan_ds_rate)) {
+ PRINTM(MWARN, "MLAN bss IOCTL length is too short.\n");
+ pioctl_req->data_read_written = 0;
+ pioctl_req->buf_len_needed = sizeof(mlan_ds_rate);
+ pioctl_req->status_code = MLAN_ERROR_INVALID_PARAMETER;
+ LEAVE();
+ return MLAN_STATUS_RESOURCE;
+ }
+ rate = (mlan_ds_rate *)pioctl_req->pbuf;
+ switch (rate->sub_command) {
+ case MLAN_OID_RATE_CFG:
+ status = wlan_rate_ioctl_cfg(pmadapter, pioctl_req);
+ break;
+ case MLAN_OID_GET_DATA_RATE:
+ status = wlan_rate_ioctl_get_data_rate(pmadapter, pioctl_req);
+ break;
+ case MLAN_OID_SUPPORTED_RATES:
+ status = wlan_rate_ioctl_get_supported_rate(pmadapter,
+ pioctl_req);
+ break;
+ default:
+ pioctl_req->status_code = MLAN_ERROR_IOCTL_INVALID;
+ status = MLAN_STATUS_FAILURE;
+ break;
+ }
+ LEAVE();
+ return status;
+}
+
+/**
+ * @brief Get Tx power configuration
+ *
+ * @param pmadapter A pointer to mlan_adapter structure
+ * @param cmd_no Firmware command number used to retrieve power values
+ * @param pioctl_req A pointer to ioctl request buffer
+ *
+ * @return MLAN_STATUS_PENDING --success, otherwise fail
+ */
+static mlan_status wlan_power_ioctl_get_power(pmlan_adapter pmadapter,
+ t_u16 cmd_no,
+ pmlan_ioctl_req pioctl_req)
+{
+ mlan_status ret = MLAN_STATUS_SUCCESS;
+ mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index];
+
+ ENTER();
+
+ /* Send request to firmware */
+ ret = wlan_prepare_cmd(pmpriv, cmd_no, HostCmd_ACT_GEN_GET, 0,
+ (t_void *)pioctl_req, MNULL);
+
+ if (ret == MLAN_STATUS_SUCCESS)
+ ret = MLAN_STATUS_PENDING;
+
+ LEAVE();
+ return ret;
+}
+
+/**
+ * @brief Set Tx power configuration
+ *
+ * @param pmadapter A pointer to mlan_adapter structure
+ * @param pioctl_req A pointer to ioctl request buffer
+ *
+ * @return MLAN_STATUS_PENDING --success, otherwise fail
+ */
+static mlan_status wlan_power_ioctl_set_power(pmlan_adapter pmadapter,
+ pmlan_ioctl_req pioctl_req)
+{
+ mlan_ds_power_cfg *power = MNULL;
+ mlan_status ret = MLAN_STATUS_SUCCESS;
+
+ HostCmd_DS_TXPWR_CFG *txp_cfg = MNULL;
+ MrvlTypes_Power_Group_t *pg_tlv = MNULL;
+ Power_Group_t *pg = MNULL;
+ pmlan_callbacks pcb = &pmadapter->callbacks;
+ t_u8 *buf = MNULL;
+ t_s8 dbm = 0;
+ mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index];
+
+ ENTER();
+
+ power = (mlan_ds_power_cfg *)pioctl_req->pbuf;
+ if (!power->param.power_cfg.is_power_auto) {
+ dbm = (t_s8)power->param.power_cfg.power_level;
+ if ((dbm < pmpriv->min_tx_power_level) ||
+ (dbm > pmpriv->max_tx_power_level)) {
+ PRINTM(MERROR,
+ "The set txpower value %d dBm is out of range (%d dBm-%d dBm)!\n",
+ dbm, pmpriv->min_tx_power_level,
+ pmpriv->max_tx_power_level);
+ pioctl_req->status_code = MLAN_ERROR_INVALID_PARAMETER;
+ ret = MLAN_STATUS_FAILURE;
+ goto exit;
+ }
+ }
+
+ ret = pcb->moal_malloc(pmadapter->pmoal_handle,
+ MRVDRV_SIZE_OF_CMD_BUFFER, MLAN_MEM_DEF, &buf);
+ if (ret != MLAN_STATUS_SUCCESS || buf == MNULL) {
+ PRINTM(MERROR,
+ "ALLOC_CMD_BUF: Failed to allocate command buffer\n");
+ pioctl_req->status_code = MLAN_ERROR_NO_MEM;
+ ret = MLAN_STATUS_FAILURE;
+ goto exit;
+ }
+ memset(pmadapter, buf, 0, MRVDRV_SIZE_OF_CMD_BUFFER);
+ txp_cfg = (HostCmd_DS_TXPWR_CFG *)buf;
+ txp_cfg->action = HostCmd_ACT_GEN_SET;
+ if (!power->param.power_cfg.is_power_auto) {
+ txp_cfg->mode = 1;
+ pg_tlv = (MrvlTypes_Power_Group_t
+ *)(buf + sizeof(HostCmd_DS_TXPWR_CFG));
+ pg_tlv->type = TLV_TYPE_POWER_GROUP;
+ pg_tlv->length = 4 * sizeof(Power_Group_t);
+ pg = (Power_Group_t *)(buf + sizeof(HostCmd_DS_TXPWR_CFG) +
+ sizeof(MrvlTypes_Power_Group_t));
+ /* 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 = (t_s8)dbm;
+ pg->power_max = (t_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 = (t_s8)dbm;
+ pg->power_max = (t_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 = (t_s8)dbm;
+ pg->power_max = (t_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 = (t_s8)dbm;
+ pg->power_max = (t_s8)dbm;
+ pg->ht_bandwidth = HT_BW_40;
+ }
+
+ /* Send request to firmware */
+ ret = wlan_prepare_cmd(pmpriv, HostCmd_CMD_TXPWR_CFG,
+ HostCmd_ACT_GEN_SET, 0, (t_void *)pioctl_req,
+ buf);
+
+ if (ret == MLAN_STATUS_SUCCESS)
+ ret = MLAN_STATUS_PENDING;
+
+ if (buf)
+ pcb->moal_mfree(pmadapter->pmoal_handle, buf);
+
+exit:
+ LEAVE();
+ return ret;
+}
+
+/**
+ * @brief Set extended power configuration
+ *
+ * @param pmadapter A pointer to mlan_adapter structure
+ * @param pioctl_req A pointer to ioctl request buffer
+ *
+ * @return MLAN_STATUS_PENDING --success, otherwise fail
+ */
+static mlan_status wlan_power_ioctl_set_power_ext(pmlan_adapter pmadapter,
+ pmlan_ioctl_req pioctl_req)
+{
+ mlan_status ret = MLAN_STATUS_SUCCESS;
+ mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index];
+ mlan_ds_power_cfg *power = MNULL;
+ pmlan_callbacks pcb = &pmadapter->callbacks;
+ t_u8 *buf = MNULL;
+ HostCmd_DS_TXPWR_CFG *txp_cfg = MNULL;
+ MrvlTypes_Power_Group_t *pg_tlv = MNULL;
+ Power_Group_t *pg = MNULL;
+ mlan_power_group *pwr_grp = MNULL;
+
+ ENTER();
+
+ power = (mlan_ds_power_cfg *)pioctl_req->pbuf;
+ ret = pcb->moal_malloc(pmadapter->pmoal_handle,
+ MRVDRV_SIZE_OF_CMD_BUFFER, MLAN_MEM_DEF, &buf);
+ if (ret != MLAN_STATUS_SUCCESS || buf == MNULL) {
+ PRINTM(MERROR,
+ "ALLOC_CMD_BUF: Failed to allocate command buffer\n");
+ pioctl_req->status_code = MLAN_ERROR_NO_MEM;
+ ret = MLAN_STATUS_FAILURE;
+ goto exit;
+ }
+ memset(pmadapter, buf, 0, MRVDRV_SIZE_OF_CMD_BUFFER);
+ txp_cfg = (HostCmd_DS_TXPWR_CFG *)buf;
+ txp_cfg->action = HostCmd_ACT_GEN_SET;
+ pwr_grp = &power->param.power_ext.power_group[0];
+ if (pwr_grp->rate_format == TX_PWR_CFG_AUTO_CTRL_OFF)
+ txp_cfg->mode = 0;
+ else {
+ txp_cfg->mode = 1;
+
+ pg_tlv = (MrvlTypes_Power_Group_t
+ *)(buf + sizeof(HostCmd_DS_TXPWR_CFG));
+ pg_tlv->type = TLV_TYPE_POWER_GROUP;
+ pg_tlv->length = sizeof(Power_Group_t);
+ pg = (Power_Group_t *)(buf + sizeof(HostCmd_DS_TXPWR_CFG) +
+ sizeof(MrvlTypes_Power_Group_t));
+ pg->ht_bandwidth = pwr_grp->bandwidth;
+ pg->power_min = (t_s8)pwr_grp->power_min;
+ pg->power_max = (t_s8)pwr_grp->power_max;
+ pg->power_step = (t_s8)pwr_grp->power_step;
+
+ if (pwr_grp->rate_format == MLAN_RATE_FORMAT_LG) {
+ if (pwr_grp->first_rate_ind <=
+ MLAN_RATE_INDEX_HRDSSS3) {
+ pg->modulation_class = MOD_CLASS_HR_DSSS;
+ } else {
+ pg->modulation_class = MOD_CLASS_OFDM;
+ pwr_grp->first_rate_ind -=
+ MLAN_RATE_INDEX_OFDM0;
+ pwr_grp->last_rate_ind -= MLAN_RATE_INDEX_OFDM0;
+ }
+ pg->first_rate_code = (t_u8)pwr_grp->first_rate_ind;
+ pg->last_rate_code = (t_u8)pwr_grp->last_rate_ind;
+ } else if (pwr_grp->rate_format == MLAN_RATE_FORMAT_HT) {
+ pg->modulation_class = MOD_CLASS_HT;
+ pg->first_rate_code = (t_u8)pwr_grp->first_rate_ind;
+ pg->last_rate_code = (t_u8)pwr_grp->last_rate_ind;
+ } else if (pwr_grp->rate_format == MLAN_RATE_FORMAT_VHT) {
+ pg->modulation_class = MOD_CLASS_VHT;
+ pg->first_rate_code =
+ (t_u8)((pwr_grp->first_rate_ind & 0xF) |
+ ((pwr_grp->nss - 1) << 4));
+ pg->last_rate_code =
+ (t_u8)((pwr_grp->last_rate_ind & 0xF) |
+ ((pwr_grp->nss - 1) << 4));
+ } else {
+ pioctl_req->status_code = MLAN_ERROR_INVALID_PARAMETER;
+ ret = MLAN_STATUS_FAILURE;
+ }
+ }
+ if (ret == MLAN_STATUS_FAILURE) {
+ if (buf)
+ pcb->moal_mfree(pmadapter->pmoal_handle, buf);
+ goto exit;
+ }
+
+ /* Send request to firmware */
+ ret = wlan_prepare_cmd(pmpriv, HostCmd_CMD_TXPWR_CFG,
+ HostCmd_ACT_GEN_SET, 0, (t_void *)pioctl_req,
+ buf);
+ if (ret == MLAN_STATUS_SUCCESS)
+ ret = MLAN_STATUS_PENDING;
+ if (buf)
+ pcb->moal_mfree(pmadapter->pmoal_handle, buf);
+
+exit:
+ LEAVE();
+ return ret;
+}
+
+/**
+ * @brief Power configuration command handler
+ *
+ * @param pmadapter A pointer to mlan_adapter structure
+ * @param pioctl_req A pointer to ioctl request buffer
+ *
+ * @return MLAN_STATUS_SUCCESS --success, otherwise fail
+ */
+static mlan_status wlan_power_ioctl(pmlan_adapter pmadapter,
+ pmlan_ioctl_req pioctl_req)
+{
+ mlan_status status = MLAN_STATUS_SUCCESS;
+ mlan_ds_power_cfg *power = MNULL;
+
+ ENTER();
+
+ if (pioctl_req->buf_len < sizeof(mlan_ds_power_cfg)) {
+ PRINTM(MWARN, "MLAN bss IOCTL length is too short.\n");
+ pioctl_req->data_read_written = 0;
+ pioctl_req->buf_len_needed = sizeof(mlan_ds_power_cfg);
+ pioctl_req->status_code = MLAN_ERROR_INVALID_PARAMETER;
+ LEAVE();
+ return MLAN_STATUS_RESOURCE;
+ }
+ power = (mlan_ds_power_cfg *)pioctl_req->pbuf;
+ switch (power->sub_command) {
+ case MLAN_OID_POWER_CFG:
+ if (pioctl_req->action == MLAN_ACT_GET)
+ status = wlan_power_ioctl_get_power(
+ pmadapter, HostCmd_CMD_TXPWR_CFG, pioctl_req);
+ else
+ status = wlan_power_ioctl_set_power(pmadapter,
+ pioctl_req);
+ break;
+
+ case MLAN_OID_POWER_CFG_EXT:
+ if (pioctl_req->action == MLAN_ACT_GET)
+ status = wlan_power_ioctl_get_power(
+ pmadapter, HostCmd_CMD_TXPWR_CFG, pioctl_req);
+ else
+ status = wlan_power_ioctl_set_power_ext(pmadapter,
+ pioctl_req);
+ break;
+ case MLAN_OID_POWER_LOW_POWER_MODE:
+ status = wlan_power_ioctl_set_get_lpm(pmadapter, pioctl_req);
+ break;
+ default:
+ pioctl_req->status_code = MLAN_ERROR_IOCTL_INVALID;
+ status = MLAN_STATUS_FAILURE;
+ break;
+ }
+ LEAVE();
+ return status;
+}
+
+/**
+ * @brief Set power save configurations
+ *
+ * @param pmadapter A pointer to mlan_adapter structure
+ * @param pioctl_req A pointer to ioctl request buffer
+ * @param ps_mode Power save mode
+ *
+ * @return MLAN_STATUS_PENDING --success, otherwise fail
+ */
+static mlan_status wlan_pm_ioctl_ps_mode(pmlan_adapter pmadapter,
+ pmlan_ioctl_req pioctl_req,
+ t_u16 ps_mode)
+{
+ mlan_status ret = MLAN_STATUS_SUCCESS;
+ mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index];
+ t_u16 sub_cmd;
+
+ ENTER();
+
+ if (pioctl_req->action == MLAN_ACT_SET) {
+ sub_cmd = (pmadapter->ps_mode == Wlan802_11PowerModePSP) ?
+ EN_AUTO_PS :
+ DIS_AUTO_PS;
+ ret = wlan_prepare_cmd(pmpriv, HostCmd_CMD_802_11_PS_MODE_ENH,
+ sub_cmd, BITMAP_STA_PS,
+ (t_void *)pioctl_req, MNULL);
+ if ((ret == MLAN_STATUS_SUCCESS) && (sub_cmd == DIS_AUTO_PS)) {
+ ret = wlan_prepare_cmd(pmpriv,
+ HostCmd_CMD_802_11_PS_MODE_ENH,
+ GET_PS, 0, MNULL, MNULL);
+ }
+ } else {
+ ret = wlan_prepare_cmd(pmpriv, HostCmd_CMD_802_11_PS_MODE_ENH,
+ GET_PS, 0, (t_void *)pioctl_req, MNULL);
+ }
+
+ if (ret == MLAN_STATUS_SUCCESS)
+ ret = MLAN_STATUS_PENDING;
+
+ LEAVE();
+ return ret;
+}
+
+/**
+ * @brief Set/Get Inactivity timeout extend
+ *
+ * @param pmadapter A pointer to mlan_adapter structure
+ * @param pioctl_req A pointer to ioctl request buffer
+ *
+ * @return MLAN_STATUS_PENDING --success, otherwise fail
+ */
+static mlan_status wlan_pm_ioctl_inactivity_timeout(pmlan_adapter pmadapter,
+ pmlan_ioctl_req pioctl_req)
+{
+ mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index];
+ mlan_ds_pm_cfg *pmcfg = MNULL;
+ mlan_status ret = MLAN_STATUS_SUCCESS;
+ t_u16 cmd_action = 0;
+
+ ENTER();
+
+ pmcfg = (mlan_ds_pm_cfg *)pioctl_req->pbuf;
+ cmd_action = HostCmd_ACT_GEN_GET;
+ if (pioctl_req->action == MLAN_ACT_SET)
+ cmd_action = HostCmd_ACT_GEN_SET;
+
+ /* Send request to firmware */
+ ret = wlan_prepare_cmd(pmpriv, HostCmd_CMD_INACTIVITY_TIMEOUT_EXT,
+ cmd_action, 0, (t_void *)pioctl_req,
+ (t_void *)&pmcfg->param.inactivity_to);
+
+ if (ret == MLAN_STATUS_SUCCESS)
+ ret = MLAN_STATUS_PENDING;
+
+ LEAVE();
+ return ret;
+}
+
+/**
+ * @brief Enable/Disable Auto Deep Sleep
+ *
+ * @param pmadapter A pointer to mlan_adapter structure
+ * @param pioctl_req A pointer to ioctl request buffer
+ *
+ * @return MLAN_STATUS_PENDING --success, otherwise fail
+ */
+static mlan_status wlan_set_auto_deep_sleep(pmlan_adapter pmadapter,
+ pmlan_ioctl_req pioctl_req)
+{
+ mlan_status ret = MLAN_STATUS_SUCCESS;
+ pmlan_private pmpriv =
+ (pmlan_private)pmadapter->priv[pioctl_req->bss_index];
+ mlan_ds_auto_ds auto_ds;
+ t_u32 mode;
+
+ ENTER();
+
+ if (((mlan_ds_pm_cfg *)pioctl_req->pbuf)
+ ->param.auto_deep_sleep.auto_ds == DEEP_SLEEP_ON) {
+ auto_ds.auto_ds = DEEP_SLEEP_ON;
+ PRINTM(MINFO, "Auto Deep Sleep: on\n");
+ mode = EN_AUTO_PS;
+ } else {
+ auto_ds.auto_ds = DEEP_SLEEP_OFF;
+ PRINTM(MINFO, "Auto Deep Sleep: off\n");
+ mode = DIS_AUTO_PS;
+ }
+ if (((mlan_ds_pm_cfg *)pioctl_req->pbuf)->param.auto_deep_sleep.idletime)
+ auto_ds.idletime = ((mlan_ds_pm_cfg *)pioctl_req->pbuf)
+ ->param.auto_deep_sleep.idletime;
+ else
+ auto_ds.idletime = pmadapter->idle_time;
+ /* note: the command could be queued and executed
+ later if there is command in progress. */
+ ret = wlan_prepare_cmd(pmpriv, HostCmd_CMD_802_11_PS_MODE_ENH,
+ (t_u16)mode, BITMAP_AUTO_DS,
+ (t_void *)pioctl_req, &auto_ds);
+ if (ret) {
+ LEAVE();
+ return ret;
+ }
+ ret = MLAN_STATUS_PENDING;
+ LEAVE();
+ return ret;
+}
+
+/**
+ * @brief Set/Get sleep period
+ *
+ * @param pmadapter A pointer to mlan_adapter structure
+ * @param pioctl_req A pointer to ioctl request buffer
+ *
+ * @return MLAN_STATUS_PENDING --success, otherwise fail
+ */
+static mlan_status wlan_set_get_sleep_pd(pmlan_adapter pmadapter,
+ pmlan_ioctl_req pioctl_req)
+{
+ mlan_status ret = MLAN_STATUS_SUCCESS;
+ pmlan_private pmpriv = pmadapter->priv[pioctl_req->bss_index];
+ mlan_ds_pm_cfg *pm_cfg = MNULL;
+ t_u16 cmd_action = 0, sleep_pd = 0;
+
+ ENTER();
+
+ pm_cfg = (mlan_ds_pm_cfg *)pioctl_req->pbuf;
+ cmd_action = HostCmd_ACT_GEN_GET;
+ if (pioctl_req->action == MLAN_ACT_SET) {
+ cmd_action = HostCmd_ACT_GEN_SET;
+ sleep_pd = (t_u16)pm_cfg->param.sleep_period;
+ }
+
+ ret = wlan_prepare_cmd(pmpriv, HostCmd_CMD_802_11_SLEEP_PERIOD,
+ cmd_action, 0, (t_void *)pioctl_req, &sleep_pd);
+
+ if (ret == MLAN_STATUS_SUCCESS)
+ ret = MLAN_STATUS_PENDING;
+
+ LEAVE();
+ return ret;
+}
+
+/**
+ * @brief Set/Get PS configuration parameter
+ *
+ * @param pmadapter A pointer to mlan_adapter structure
+ * @param pioctl_req A pointer to ioctl request buffer
+ *
+ * @return MLAN_STATUS_SUCCESS --success
+ */
+static mlan_status wlan_set_get_ps_cfg(pmlan_adapter pmadapter,
+ pmlan_ioctl_req pioctl_req)
+{
+ mlan_ds_pm_cfg *pm_cfg = MNULL;
+
+ ENTER();
+
+ pm_cfg = (mlan_ds_pm_cfg *)pioctl_req->pbuf;
+ if (pioctl_req->action == MLAN_ACT_GET) {
+ pm_cfg->param.ps_cfg.ps_null_interval =
+ (t_u32)pmadapter->null_pkt_interval;
+ pm_cfg->param.ps_cfg.multiple_dtim_interval =
+ (t_u32)pmadapter->multiple_dtim;
+ pm_cfg->param.ps_cfg.listen_interval =
+ (t_u32)pmadapter->local_listen_interval;
+ pm_cfg->param.ps_cfg.bcn_miss_timeout =
+ (t_u32)pmadapter->bcn_miss_time_out;
+ pm_cfg->param.ps_cfg.delay_to_ps =
+ (t_u32)pmadapter->delay_to_ps;
+ pm_cfg->param.ps_cfg.ps_mode =
+ (t_u32)pmadapter->enhanced_ps_mode;
+ } else {
+ if (pm_cfg->param.ps_cfg.ps_null_interval)
+ pmadapter->null_pkt_interval =
+ (t_u16)pm_cfg->param.ps_cfg.ps_null_interval;
+ else
+ pm_cfg->param.ps_cfg.ps_null_interval =
+ (t_u32)pmadapter->null_pkt_interval;
+ if (pm_cfg->param.ps_cfg.multiple_dtim_interval)
+ pmadapter->multiple_dtim =
+ (t_u16)pm_cfg->param.ps_cfg
+ .multiple_dtim_interval;
+ else
+ pm_cfg->param.ps_cfg.multiple_dtim_interval =
+ (t_u32)pmadapter->multiple_dtim;
+ if (((t_s32)pm_cfg->param.ps_cfg.listen_interval) ==
+ MRVDRV_LISTEN_INTERVAL_DISABLE)
+ pmadapter->local_listen_interval = 0;
+ else if (pm_cfg->param.ps_cfg.listen_interval)
+ pmadapter->local_listen_interval =
+ (t_u16)pm_cfg->param.ps_cfg.listen_interval;
+ else
+ pm_cfg->param.ps_cfg.listen_interval =
+ (t_u32)pmadapter->local_listen_interval;
+ if (pm_cfg->param.ps_cfg.bcn_miss_timeout)
+ pmadapter->bcn_miss_time_out =
+ (t_u16)pm_cfg->param.ps_cfg.bcn_miss_timeout;
+ else
+ pm_cfg->param.ps_cfg.bcn_miss_timeout =
+ (t_u32)pmadapter->bcn_miss_time_out;
+ if (pm_cfg->param.ps_cfg.delay_to_ps != DELAY_TO_PS_UNCHANGED)
+ pmadapter->delay_to_ps =
+ (t_u16)pm_cfg->param.ps_cfg.delay_to_ps;
+ else
+ pm_cfg->param.ps_cfg.delay_to_ps =
+ (t_u32)pmadapter->delay_to_ps;
+ if (pm_cfg->param.ps_cfg.ps_mode)
+ pmadapter->enhanced_ps_mode =
+ (t_u16)pm_cfg->param.ps_cfg.ps_mode;
+ else
+ pm_cfg->param.ps_cfg.ps_mode =
+ (t_u32)pmadapter->enhanced_ps_mode;
+ }
+ pioctl_req->data_read_written = sizeof(t_u32) + MLAN_SUB_COMMAND_SIZE;
+
+ LEAVE();
+ return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ * @brief Set/Get PS configuration parameter
+ *
+ * @param pmadapter A pointer to mlan_adapter structure
+ * @param pioctl_req A pointer to ioctl request buffer
+ *
+ * @return MLAN_STATUS_SUCCESS --success
+ */
+static mlan_status wlan_set_get_bcn_timeout(pmlan_adapter pmadapter,
+ pmlan_ioctl_req pioctl_req)
+{
+ mlan_status ret = MLAN_STATUS_SUCCESS;
+ mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index];
+ mlan_ds_pm_cfg *pm_cfg = MNULL;
+
+ ENTER();
+
+ pm_cfg = (mlan_ds_pm_cfg *)pioctl_req->pbuf;
+
+ /* Send command to firmware */
+ ret = wlan_prepare_cmd(pmpriv, HostCmd_CMD_802_11_PS_MODE_ENH,
+ EN_AUTO_PS, BITMAP_BCN_TMO, (t_void *)pioctl_req,
+ &pm_cfg->param.bcn_timeout);
+
+ if (ret == MLAN_STATUS_SUCCESS)
+ ret = MLAN_STATUS_PENDING;
+
+ LEAVE();
+ return ret;
+}
+
+/**
+ * @brief Get/Set the sleep parameters
+ *
+ * @param pmadapter A pointer to mlan_adapter structure
+ * @param pioctl_req A pointer to ioctl request buffer
+ *
+ * @return MLAN_STATUS_PENDING --success, otherwise fail
+ */
+static mlan_status wlan_set_get_sleep_params(pmlan_adapter pmadapter,
+ pmlan_ioctl_req pioctl_req)
+{
+ mlan_status ret = MLAN_STATUS_SUCCESS;
+ mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index];
+ mlan_ds_pm_cfg *pm_cfg = MNULL;
+ t_u16 cmd_action = 0;
+
+ ENTER();
+
+ pm_cfg = (mlan_ds_pm_cfg *)pioctl_req->pbuf;
+ cmd_action = HostCmd_ACT_GEN_GET;
+ if (pioctl_req->action == MLAN_ACT_SET)
+ cmd_action = HostCmd_ACT_GEN_SET;
+
+ /* Send command to firmware */
+ ret = wlan_prepare_cmd(pmpriv, HostCmd_CMD_802_11_SLEEP_PARAMS,
+ cmd_action, 0, (t_void *)pioctl_req,
+ &pm_cfg->param.sleep_params);
+
+ if (ret == MLAN_STATUS_SUCCESS)
+ ret = MLAN_STATUS_PENDING;
+
+ LEAVE();
+ return ret;
+}
+
+/**
+ * @brief config management frame wakeup filter
+ *
+ * @param pmadapter A pointer to mlan_adapter structure
+ * @param pioctl_req A pointer to ioctl request buffer
+ *
+ * @return MLAN_STATUS_PENDING --success, otherwise fail
+ */
+mlan_status wlan_config_mgmt_filter(pmlan_adapter pmadapter,
+ pmlan_ioctl_req pioctl_req)
+{
+ mlan_status ret = MLAN_STATUS_SUCCESS;
+ mlan_ds_pm_cfg *pm_cfg = MNULL;
+ int i = 0;
+
+ ENTER();
+
+ memset(pmadapter, pmadapter->mgmt_filter, 0,
+ sizeof(mlan_mgmt_frame_wakeup) * MAX_MGMT_FRAME_FILTER);
+ pm_cfg = (mlan_ds_pm_cfg *)pioctl_req->pbuf;
+ if (pioctl_req->action == MLAN_ACT_SET) {
+ for (i = 0; i < MAX_MGMT_FRAME_FILTER; i++)
+ if (!pm_cfg->param.mgmt_filter[i].type)
+ break;
+ memcpy_ext(pmadapter, (t_u8 *)pmadapter->mgmt_filter,
+ (t_u8 *)pm_cfg->param.mgmt_filter,
+ (i + 1) * sizeof(mlan_mgmt_frame_wakeup),
+ sizeof(pmadapter->mgmt_filter));
+ } else if (pioctl_req->action == MLAN_ACT_GET)
+ PRINTM(MERROR, "Get not support\n");
+ LEAVE();
+ return ret;
+}
+
+/**
+ * @brief Power save command handler
+ *
+ * @param pmadapter A pointer to mlan_adapter structure
+ * @param pioctl_req A pointer to ioctl request buffer
+ *
+ * @return MLAN_STATUS_SUCCESS --success, otherwise fail
+ */
+static mlan_status wlan_pm_ioctl(pmlan_adapter pmadapter,
+ pmlan_ioctl_req pioctl_req)
+{
+ mlan_status status = MLAN_STATUS_SUCCESS;
+ mlan_ds_pm_cfg *pm = MNULL;
+
+ ENTER();
+
+ if (pioctl_req->buf_len < sizeof(mlan_ds_pm_cfg)) {
+ PRINTM(MWARN, "MLAN bss IOCTL length is too short.\n");
+ pioctl_req->data_read_written = 0;
+ pioctl_req->buf_len_needed = sizeof(mlan_ds_pm_cfg);
+ LEAVE();
+ return MLAN_STATUS_RESOURCE;
+ }
+ pm = (mlan_ds_pm_cfg *)pioctl_req->pbuf;
+ switch (pm->sub_command) {
+ case MLAN_OID_PM_CFG_IEEE_PS:
+ switch (pioctl_req->action) {
+ case MLAN_ACT_SET:
+ /**Block ieee power save disable command when bt coex
+ * enable*/
+ if (pmadapter->coex_scan && !pm->param.ps_mode)
+ break;
+ if (pm->param.ps_mode)
+ pmadapter->ps_mode = Wlan802_11PowerModePSP;
+ else
+ pmadapter->ps_mode = Wlan802_11PowerModeCAM;
+ status = wlan_pm_ioctl_ps_mode(pmadapter, pioctl_req,
+ pmadapter->ps_mode);
+ break;
+ case MLAN_ACT_GET:
+ status = wlan_pm_ioctl_ps_mode(pmadapter, pioctl_req,
+ pmadapter->ps_mode);
+ break;
+ default:
+ pioctl_req->status_code = MLAN_ERROR_IOCTL_INVALID;
+ status = MLAN_STATUS_FAILURE;
+ break;
+ }
+ break;
+ case MLAN_OID_PM_CFG_HS_CFG:
+ status = wlan_pm_ioctl_hscfg(pmadapter, pioctl_req);
+ break;
+ case MLAN_OID_PM_CFG_INACTIVITY_TO:
+ status =
+ wlan_pm_ioctl_inactivity_timeout(pmadapter, pioctl_req);
+ break;
+ case MLAN_OID_PM_CFG_DEEP_SLEEP:
+ switch (pioctl_req->action) {
+ case MLAN_ACT_SET:
+ if (pmadapter->is_deep_sleep &&
+ pm->param.auto_deep_sleep.auto_ds ==
+ DEEP_SLEEP_ON) {
+ PRINTM(MMSG,
+ "Station already in enhanced deep sleep mode\n");
+ status = MLAN_STATUS_FAILURE;
+ break;
+ } else if (!pmadapter->is_deep_sleep &&
+ pm->param.auto_deep_sleep.auto_ds ==
+ DEEP_SLEEP_OFF) {
+ PRINTM(MMSG,
+ "Station already not in enhanced deep sleep mode\n");
+ status = MLAN_STATUS_FAILURE;
+ break;
+ }
+ status =
+ wlan_set_auto_deep_sleep(pmadapter, pioctl_req);
+ break;
+ case MLAN_ACT_GET:
+ if (pmadapter->is_deep_sleep) {
+ pm->param.auto_deep_sleep.auto_ds =
+ DEEP_SLEEP_ON;
+ pm->param.auto_deep_sleep.idletime =
+ pmadapter->idle_time;
+ } else
+ pm->param.auto_deep_sleep.auto_ds =
+ DEEP_SLEEP_OFF;
+ break;
+ default:
+ pioctl_req->status_code = MLAN_ERROR_IOCTL_INVALID;
+ status = MLAN_STATUS_FAILURE;
+ break;
+ }
+ break;
+ case MLAN_OID_PM_CFG_PS_CFG:
+ status = wlan_set_get_ps_cfg(pmadapter, pioctl_req);
+ break;
+ case MLAN_OID_PM_CFG_SLEEP_PD:
+ status = wlan_set_get_sleep_pd(pmadapter, pioctl_req);
+ break;
+ case MLAN_OID_PM_CFG_SLEEP_PARAMS:
+ status = wlan_set_get_sleep_params(pmadapter, pioctl_req);
+ break;
+ case MLAN_OID_PM_INFO:
+ status = wlan_get_pm_info(pmadapter, pioctl_req);
+ break;
+ case MLAN_OID_PM_HS_WAKEUP_REASON:
+ status = wlan_get_hs_wakeup_reason(pmadapter, pioctl_req);
+ break;
+ case MLAN_OID_PM_MGMT_FILTER:
+ status = wlan_config_mgmt_filter(pmadapter, pioctl_req);
+ break;
+ case MLAN_OID_PM_CFG_BCN_TIMEOUT:
+ status = wlan_set_get_bcn_timeout(pmadapter, pioctl_req);
+ break;
+ default:
+ pioctl_req->status_code = MLAN_ERROR_IOCTL_INVALID;
+ status = MLAN_STATUS_FAILURE;
+ break;
+ }
+ LEAVE();
+ return status;
+}
+
+/**
+ * @brief Set/Get WPA IE
+ *
+ * @param priv A pointer to mlan_private structure
+ * @param ie_data_ptr A pointer to IE
+ * @param ie_len Length of the IE
+ *
+ * @return MLAN_STATUS_SUCCESS --success, otherwise fail
+ */
+static mlan_status wlan_set_wpa_ie_helper(mlan_private *priv, t_u8 *ie_data_ptr,
+ t_u16 ie_len)
+{
+ ENTER();
+
+ if (ie_len) {
+ if (ie_len > sizeof(priv->wpa_ie)) {
+ PRINTM(MERROR, "failed to copy, WPA IE is too big\n");
+ LEAVE();
+ return MLAN_STATUS_FAILURE;
+ }
+ memcpy_ext(priv->adapter, priv->wpa_ie, ie_data_ptr, ie_len,
+ sizeof(priv->wpa_ie));
+ priv->wpa_ie_len = (t_u8)ie_len;
+ PRINTM(MIOCTL, "Set Wpa_ie_len=%d IE=%#x\n", priv->wpa_ie_len,
+ priv->wpa_ie[0]);
+ DBG_HEXDUMP(MCMD_D, "Wpa_ie", priv->wpa_ie, priv->wpa_ie_len);
+ if (priv->wpa_ie[0] == WPA_IE) {
+ priv->sec_info.wpa_enabled = MTRUE;
+ } else if (priv->wpa_ie[0] == RSN_IE) {
+ priv->sec_info.wpa2_enabled = MTRUE;
+ } else {
+ priv->sec_info.wpa_enabled = MFALSE;
+ priv->sec_info.wpa2_enabled = MFALSE;
+ }
+ } else {
+ memset(priv->adapter, priv->wpa_ie, 0, sizeof(priv->wpa_ie));
+ priv->wpa_ie_len = 0;
+ PRINTM(MINFO, "Reset Wpa_ie_len=%d IE=%#x\n", priv->wpa_ie_len,
+ priv->wpa_ie[0]);
+ priv->sec_info.wpa_enabled = MFALSE;
+ priv->sec_info.wpa2_enabled = MFALSE;
+ }
+
+ LEAVE();
+ return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ * @brief Set OSEN IE
+ *
+ * @param priv A pointer to mlan_private structure
+ * @param ie_data_ptr A pointer to IE
+ * @param ie_len Length of the IE
+ *
+ * @return MLAN_STATUS_SUCCESS --success, otherwise fail
+ */
+static mlan_status wlan_set_osen_ie(mlan_private *priv, t_u8 *ie_data_ptr,
+ t_u16 ie_len)
+{
+ ENTER();
+ if (ie_len) {
+ if (ie_len > sizeof(priv->osen_ie)) {
+ PRINTM(MWARN, "failed to copy, WAPI IE is too big\n");
+ LEAVE();
+ return MLAN_STATUS_FAILURE;
+ }
+ memcpy_ext(priv->adapter, priv->osen_ie, ie_data_ptr, ie_len,
+ sizeof(priv->osen_ie));
+ priv->osen_ie_len = (t_u8)ie_len;
+ PRINTM(MIOCTL, "Set osen_ie_len=%d IE=%#x\n", priv->osen_ie_len,
+ priv->osen_ie[0]);
+ DBG_HEXDUMP(MCMD_D, "osen_ie", priv->osen_ie,
+ priv->osen_ie_len);
+ priv->sec_info.osen_enabled = MTRUE;
+ } else {
+ memset(priv->adapter, priv->osen_ie, 0, sizeof(priv->osen_ie));
+ priv->osen_ie_len = (t_u8)ie_len;
+ PRINTM(MINFO, "Reset osen_ie_len=%d IE=%#x\n",
+ priv->osen_ie_len, priv->osen_ie[0]);
+ priv->sec_info.osen_enabled = MFALSE;
+ }
+ LEAVE();
+ return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ * @brief Set WAPI IE
+ *
+ * @param priv A pointer to mlan_private structure
+ * @param ie_data_ptr A pointer to IE
+ * @param ie_len Length of the IE
+ *
+ * @return MLAN_STATUS_SUCCESS --success, otherwise fail
+ */
+static mlan_status wlan_set_wapi_ie(mlan_private *priv, t_u8 *ie_data_ptr,
+ t_u16 ie_len)
+{
+ ENTER();
+ if (ie_len) {
+ if (ie_len > sizeof(priv->wapi_ie)) {
+ PRINTM(MWARN, "failed to copy, WAPI IE is too big\n");
+ LEAVE();
+ return MLAN_STATUS_FAILURE;
+ }
+ memcpy_ext(priv->adapter, priv->wapi_ie, ie_data_ptr, ie_len,
+ sizeof(priv->wapi_ie));
+ priv->wapi_ie_len = (t_u8)ie_len;
+ PRINTM(MIOCTL, "Set wapi_ie_len=%d IE=%#x\n", priv->wapi_ie_len,
+ priv->wapi_ie[0]);
+ DBG_HEXDUMP(MCMD_D, "wapi_ie", priv->wapi_ie,
+ priv->wapi_ie_len);
+ if (priv->wapi_ie[0] == WAPI_IE)
+ priv->sec_info.wapi_enabled = MTRUE;
+ } else {
+ memset(priv->adapter, priv->wapi_ie, 0, sizeof(priv->wapi_ie));
+ priv->wapi_ie_len = (t_u8)ie_len;
+ PRINTM(MINFO, "Reset wapi_ie_len=%d IE=%#x\n",
+ priv->wapi_ie_len, priv->wapi_ie[0]);
+ priv->sec_info.wapi_enabled = MFALSE;
+ }
+ LEAVE();
+ return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ * @brief Set/Get WAPI status
+ *
+ * @param pmadapter A pointer to mlan_adapter structure
+ * @param pioctl_req A pointer to ioctl request buffer
+ *
+ * @return MLAN_STATUS_SUCCESS --success
+ */
+static mlan_status wlan_sec_ioctl_wapi_enable(pmlan_adapter pmadapter,
+ pmlan_ioctl_req pioctl_req)
+{
+ mlan_status ret = MLAN_STATUS_SUCCESS;
+ mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index];
+ mlan_ds_sec_cfg *sec = MNULL;
+ ENTER();
+ sec = (mlan_ds_sec_cfg *)pioctl_req->pbuf;
+ if (pioctl_req->action == MLAN_ACT_GET) {
+ if (pmpriv->wapi_ie_len)
+ sec->param.wapi_enabled = MTRUE;
+ else
+ sec->param.wapi_enabled = MFALSE;
+ } else {
+ if (sec->param.wapi_enabled == MFALSE)
+ wlan_set_wapi_ie(pmpriv, MNULL, 0);
+ }
+ pioctl_req->data_read_written = sizeof(t_u32) + MLAN_SUB_COMMAND_SIZE;
+ LEAVE();
+ return ret;
+}
+
+/**
+ * @brief Set WAPI key
+ *
+ * @param pmadapter A pointer to mlan_adapter structure
+ * @param pioctl_req A pointer to ioctl request buffer
+ *
+ * @return MLAN_STATUS_PENDING --success, otherwise fail
+ */
+static mlan_status wlan_sec_ioctl_set_wapi_key(pmlan_adapter pmadapter,
+ pmlan_ioctl_req pioctl_req)
+{
+ mlan_status ret = MLAN_STATUS_SUCCESS;
+ mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index];
+ mlan_ds_sec_cfg *sec = MNULL;
+ ENTER();
+
+ sec = (mlan_ds_sec_cfg *)pioctl_req->pbuf;
+ ret = wlan_prepare_cmd(pmpriv, HostCmd_CMD_802_11_KEY_MATERIAL,
+ HostCmd_ACT_GEN_SET, KEY_INFO_ENABLED,
+ (t_void *)pioctl_req, &sec->param.encrypt_key);
+ if (ret == MLAN_STATUS_SUCCESS)
+ ret = MLAN_STATUS_PENDING;
+
+ LEAVE();
+ return ret;
+}
+
+/**
+ * @brief Set/Get Port Control status
+ *
+ * @param pmadapter A pointer to mlan_adapter structure
+ * @param pioctl_req A pointer to ioctl request buffer
+ *
+ * @return MLAN_STATUS_SUCCESS --success, otherwise fail
+ */
+static mlan_status wlan_sec_ioctl_port_ctrl_enable(pmlan_adapter pmadapter,
+ pmlan_ioctl_req pioctl_req)
+{
+ mlan_status ret = MLAN_STATUS_SUCCESS;
+ mlan_ds_sec_cfg *sec = MNULL;
+ mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index];
+
+ ENTER();
+
+ sec = (mlan_ds_sec_cfg *)pioctl_req->pbuf;
+ if (pioctl_req->action == MLAN_ACT_GET) {
+ if (pmpriv->port_ctrl_mode)
+ sec->param.port_ctrl_enabled = MTRUE;
+ else
+ sec->param.port_ctrl_enabled = MFALSE;
+ } else {
+ if (sec->param.port_ctrl_enabled) {
+ pmpriv->port_ctrl_mode = MTRUE;
+ pmpriv->port_open = MFALSE;
+ } else {
+ if (pmpriv->port_ctrl_mode == MTRUE) {
+ pmpriv->port_ctrl_mode = MFALSE;
+ /* Cleanup the bypass TX queue */
+ wlan_cleanup_bypass_txq(pmpriv);
+ }
+ }
+ }
+ PRINTM(MINFO, "port_ctrl: port_ctrl_mode=%d port_open=%d\n",
+ pmpriv->port_ctrl_mode, pmpriv->port_open);
+
+ LEAVE();
+ return ret;
+}
+
+/**
+ * @brief Set/Get authentication mode
+ *
+ * @param pmadapter A pointer to mlan_adapter structure
+ * @param pioctl_req A pointer to ioctl request buffer
+ *
+ * @return MLAN_STATUS_SUCCESS --success
+ */
+static mlan_status wlan_sec_ioctl_auth_mode(pmlan_adapter pmadapter,
+ pmlan_ioctl_req pioctl_req)
+{
+ mlan_status ret = MLAN_STATUS_SUCCESS;
+ mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index];
+ mlan_ds_sec_cfg *sec = MNULL;
+ ENTER();
+ sec = (mlan_ds_sec_cfg *)pioctl_req->pbuf;
+ if (pioctl_req->action == MLAN_ACT_GET)
+ sec->param.auth_mode = pmpriv->sec_info.authentication_mode;
+ else
+ pmpriv->sec_info.authentication_mode = sec->param.auth_mode;
+
+ pioctl_req->data_read_written = sizeof(t_u32) + MLAN_SUB_COMMAND_SIZE;
+ LEAVE();
+ return ret;
+}
+
+/**
+ * @brief Set/Get encryption mode
+ *
+ * @param pmadapter A pointer to mlan_adapter structure
+ * @param pioctl_req A pointer to ioctl request buffer
+ *
+ * @return MLAN_STATUS_SUCCESS --success
+ */
+static mlan_status wlan_sec_ioctl_encrypt_mode(pmlan_adapter pmadapter,
+ pmlan_ioctl_req pioctl_req)
+{
+ mlan_status ret = MLAN_STATUS_SUCCESS;
+ mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index];
+ mlan_ds_sec_cfg *sec = MNULL;
+ ENTER();
+ sec = (mlan_ds_sec_cfg *)pioctl_req->pbuf;
+ if (pioctl_req->action == MLAN_ACT_GET)
+ sec->param.encrypt_mode = pmpriv->sec_info.encryption_mode;
+ else
+ pmpriv->sec_info.encryption_mode = sec->param.encrypt_mode;
+
+ pioctl_req->data_read_written = sizeof(t_u32) + MLAN_SUB_COMMAND_SIZE;
+ LEAVE();
+ return ret;
+}
+
+/**
+ * @brief Get Random charactor
+ *
+ * @param pmadapter A pointer to mlan_adapter structure
+ *
+ * @return random charactor
+ */
+t_u8 wlan_get_random_charactor(pmlan_adapter pmadapter)
+{
+ t_u32 sec, usec;
+ t_u8 ch = 0;
+
+ ENTER();
+
+ pmadapter->callbacks.moal_get_system_time(pmadapter->pmoal_handle, &sec,
+ &usec);
+ sec = (sec & 0xFFFF) + (sec >> 16);
+ usec = (usec & 0xFFFF) + (usec >> 16);
+ ch = (((sec << 16) + usec) % 26) + 'a';
+ LEAVE();
+ return ch;
+}
+
+/**
+ * @brief Set/Get WPA status
+ *
+ * @param pmadapter A pointer to mlan_adapter structure
+ * @param pioctl_req A pointer to ioctl request buffer
+ *
+ * @return MLAN_STATUS_SUCCESS --success
+ */
+static mlan_status wlan_sec_ioctl_wpa_enable(pmlan_adapter pmadapter,
+ pmlan_ioctl_req pioctl_req)
+{
+ mlan_status ret = MLAN_STATUS_SUCCESS;
+ mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index];
+ mlan_ds_sec_cfg *sec = MNULL;
+ ENTER();
+ sec = (mlan_ds_sec_cfg *)pioctl_req->pbuf;
+ if (pioctl_req->action == MLAN_ACT_GET) {
+ if (pmpriv->wpa_ie_len)
+ sec->param.wpa_enabled = MTRUE;
+ else
+ sec->param.wpa_enabled = MFALSE;
+ } else {
+ if (sec->param.wpa_enabled == MFALSE)
+ wlan_set_wpa_ie_helper(pmpriv, MNULL, 0);
+ }
+ pioctl_req->data_read_written = sizeof(t_u32) + MLAN_SUB_COMMAND_SIZE;
+ LEAVE();
+ return ret;
+}
+
+/**
+ * @brief Set WEP keys
+ *
+ * @param pmadapter A pointer to mlan_adapter structure
+ * @param pioctl_req A pointer to ioctl request buffer
+ *
+ * @return MLAN_STATUS_PENDING --success, otherwise fail
+ */
+static mlan_status wlan_sec_ioctl_set_wep_key(pmlan_adapter pmadapter,
+ pmlan_ioctl_req pioctl_req)
+{
+ mlan_status ret = MLAN_STATUS_SUCCESS;
+ mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index];
+ mlan_ds_sec_cfg *sec = MNULL;
+ mrvl_wep_key_t *pwep_key = MNULL;
+ int index;
+ int i = 0;
+
+ ENTER();
+
+ if (pmpriv->wep_key_curr_index >= MRVL_NUM_WEP_KEY)
+ pmpriv->wep_key_curr_index = 0;
+ pwep_key = &pmpriv->wep_key[pmpriv->wep_key_curr_index];
+ sec = (mlan_ds_sec_cfg *)pioctl_req->pbuf;
+ if (sec->param.encrypt_key.key_index == MLAN_KEY_INDEX_DEFAULT) {
+ index = pmpriv->wep_key_curr_index;
+ sec->param.encrypt_key.key_index = index;
+ } else {
+ if (sec->param.encrypt_key.key_index >= MRVL_NUM_WEP_KEY) {
+ if ((sec->param.encrypt_key.key_remove == MTRUE) &&
+ (sec->param.encrypt_key.key_index <= 5)) {
+ /* call firmware remove key */
+ ret = wlan_prepare_cmd(
+ pmpriv, HostCmd_CMD_802_11_KEY_MATERIAL,
+ HostCmd_ACT_GEN_SET, 0,
+ (t_void *)pioctl_req,
+ &sec->param.encrypt_key);
+ if (ret == MLAN_STATUS_SUCCESS)
+ ret = MLAN_STATUS_PENDING;
+ goto exit;
+ }
+ PRINTM(MERROR, "Key_index is invalid\n");
+ ret = MLAN_STATUS_FAILURE;
+ goto exit;
+ }
+ index = sec->param.encrypt_key.key_index;
+ }
+
+ if ((sec->param.encrypt_key.key_disable == MTRUE) ||
+ (sec->param.encrypt_key.key_remove == MTRUE)) {
+ pmpriv->sec_info.wep_status = Wlan802_11WEPDisabled;
+ /* remove key */
+ if (sec->param.encrypt_key.key_remove == MTRUE) {
+ memset(pmadapter, &pmpriv->wep_key[index], 0,
+ sizeof(mrvl_wep_key_t));
+ /* call firmware remove key */
+ ret = wlan_prepare_cmd(pmpriv,
+ HostCmd_CMD_802_11_KEY_MATERIAL,
+ HostCmd_ACT_GEN_SET, 0, MNULL,
+ &sec->param.encrypt_key);
+ if (ret)
+ goto exit;
+ }
+ } else {
+ if (sec->param.encrypt_key.key_len) {
+ if ((sec->param.encrypt_key.key_len !=
+ WEP_104_BIT_LEN) &&
+ (sec->param.encrypt_key.key_len !=
+ WEP_40_BIT_LEN)) {
+ PRINTM(MERROR, "Invalid wep key len=%d\n",
+ sec->param.encrypt_key.key_len);
+ /* We will use random key to clear the key
+ * buffer in FW */
+ if (sec->param.encrypt_key.key_len <
+ WEP_40_BIT_LEN)
+ sec->param.encrypt_key.key_len =
+ WEP_40_BIT_LEN;
+ else
+ sec->param.encrypt_key.key_len =
+ WEP_104_BIT_LEN;
+ for (i = 0; i < sec->param.encrypt_key.key_len;
+ i++)
+ sec->param.encrypt_key.key_material[i] =
+ wlan_get_random_charactor(
+ pmadapter);
+ }
+ pwep_key = &pmpriv->wep_key[index];
+ /* Cleanup */
+ memset(pmadapter, pwep_key, 0, sizeof(mrvl_wep_key_t));
+ /* Copy the key in the driver */
+
+ memcpy_ext(pmadapter, pwep_key->key_material,
+ sec->param.encrypt_key.key_material,
+ sec->param.encrypt_key.key_len,
+ MRVL_KEY_BUFFER_SIZE_IN_BYTE);
+ pwep_key->key_index = index;
+ pwep_key->key_length = sec->param.encrypt_key.key_len;
+ if (pmpriv->sec_info.wep_status !=
+ Wlan802_11WEPEnabled) {
+ /*
+ * The status is set as Key Absent
+ * so as to make sure we display the
+ * keys when iwlist mlanX key is used
+ */
+ pmpriv->sec_info.wep_status =
+ Wlan802_11WEPKeyAbsent;
+ }
+ }
+ if (sec->param.encrypt_key.is_current_wep_key == MTRUE) {
+ /* Copy the required key as the current key */
+ pwep_key = &pmpriv->wep_key[index];
+ if (!pwep_key->key_length) {
+ if (&pmpriv->sec_info.wpa_enabled ||
+ &pmpriv->sec_info.wpa2_enabled ||
+ &pmpriv->sec_info.wapi_enabled) {
+ ret = MLAN_STATUS_SUCCESS;
+ goto exit;
+ }
+ PRINTM(MERROR,
+ "Key %d not set,so cannot enable it\n",
+ index);
+ pioctl_req->status_code =
+ MLAN_ERROR_CMD_RESP_FAIL;
+ ret = MLAN_STATUS_FAILURE;
+ goto exit;
+ }
+ pmpriv->wep_key_curr_index = (t_u16)index;
+ pmpriv->sec_info.wep_status = Wlan802_11WEPEnabled;
+ }
+ if (sec->param.encrypt_key.key_flags && pwep_key->key_length) {
+ pmpriv->wep_key_curr_index = (t_u16)index;
+ // Only do this if the key is an xmit key. If the key
+ // is a group key, we might be in wpa/wep mixed mode in
+ // which case we don't want to set wep_status =
+ // Wlan802_11WEPEnabled because that enables WEP at the
+ // MAC controller level and WPA stops working properly.
+ if (sec->param.encrypt_key.key_flags &
+ KEY_FLAG_SET_TX_KEY) {
+ pmpriv->sec_info.wep_status =
+ Wlan802_11WEPEnabled;
+ }
+ }
+ }
+ if (pmpriv->sec_info.wep_status == Wlan802_11WEPEnabled)
+ pmpriv->curr_pkt_filter |= HostCmd_ACT_MAC_WEP_ENABLE;
+ else
+ pmpriv->curr_pkt_filter &= ~HostCmd_ACT_MAC_WEP_ENABLE;
+
+ /* Send request to firmware */
+ if (pmpriv->sec_info.wep_status == Wlan802_11WEPEnabled &&
+ pwep_key->key_length) {
+ ret = wlan_prepare_cmd(pmpriv, HostCmd_CMD_MAC_CONTROL,
+ HostCmd_ACT_GEN_SET, 0, MNULL,
+ &pmpriv->curr_pkt_filter);
+ if (ret)
+ goto exit;
+ if (!sec->param.encrypt_key.key_len) {
+ sec->param.encrypt_key.key_index = pwep_key->key_index;
+ sec->param.encrypt_key.key_len = pwep_key->key_length;
+ memcpy_ext(pmadapter,
+ sec->param.encrypt_key.key_material,
+ pwep_key->key_material,
+ sec->param.encrypt_key.key_len,
+ MLAN_MAX_KEY_LENGTH);
+ }
+ ret = wlan_prepare_cmd(pmpriv, HostCmd_CMD_802_11_KEY_MATERIAL,
+ HostCmd_ACT_GEN_SET, 0,
+ (t_void *)pioctl_req,
+ &sec->param.encrypt_key);
+ } else {
+ if (pwep_key->key_length) {
+ if (!sec->param.encrypt_key.key_len) {
+ sec->param.encrypt_key.key_index =
+ pwep_key->key_index;
+ sec->param.encrypt_key.key_len =
+ pwep_key->key_length;
+ memcpy_ext(pmadapter,
+ sec->param.encrypt_key.key_material,
+ pwep_key->key_material,
+ sec->param.encrypt_key.key_len,
+ MLAN_MAX_KEY_LENGTH);
+ }
+ ret = wlan_prepare_cmd(pmpriv,
+ HostCmd_CMD_802_11_KEY_MATERIAL,
+ HostCmd_ACT_GEN_SET, 0, MNULL,
+ &sec->param.encrypt_key);
+ if (ret)
+ goto exit;
+ }
+ ret = wlan_prepare_cmd(pmpriv, HostCmd_CMD_MAC_CONTROL,
+ HostCmd_ACT_GEN_SET, 0,
+ (t_void *)pioctl_req,
+ &pmpriv->curr_pkt_filter);
+ }
+ if (ret == MLAN_STATUS_SUCCESS)
+ ret = MLAN_STATUS_PENDING;
+
+exit:
+ LEAVE();
+ return ret;
+}
+
+/**
+ * @brief Set WPA key
+ *
+ * @param pmadapter A pointer to mlan_adapter structure
+ * @param pioctl_req A pointer to ioctl request buffer
+ *
+ * @return MLAN_STATUS_PENDING --success, otherwise fail
+ */
+static mlan_status wlan_sec_ioctl_set_wpa_key(pmlan_adapter pmadapter,
+ pmlan_ioctl_req pioctl_req)
+{
+ mlan_status ret = MLAN_STATUS_SUCCESS;
+ mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index];
+ mlan_ds_sec_cfg *sec = MNULL;
+
+ ENTER();
+
+ sec = (mlan_ds_sec_cfg *)pioctl_req->pbuf;
+ /* Current driver only supports key length of up to 32 bytes */
+ if (sec->param.encrypt_key.key_len > MLAN_MAX_KEY_LENGTH) {
+ PRINTM(MERROR, "Key length is incorrect\n");
+ pioctl_req->status_code = MLAN_ERROR_INVALID_PARAMETER;
+ ret = MLAN_STATUS_FAILURE;
+ goto exit;
+ }
+
+ ret = wlan_prepare_cmd(pmpriv, HostCmd_CMD_802_11_KEY_MATERIAL,
+ HostCmd_ACT_GEN_SET, 0, (t_void *)pioctl_req,
+ &sec->param.encrypt_key);
+
+ if (ret == MLAN_STATUS_SUCCESS)
+ ret = MLAN_STATUS_PENDING;
+
+exit:
+ LEAVE();
+ return ret;
+}
+
+/**
+ * @brief Get security keys
+ *
+ * @param pmadapter A pointer to mlan_adapter structure
+ * @param pioctl_req A pointer to ioctl request buffer
+ *
+ * @return MLAN_STATUS_SUCCESS --success, otherwise fail
+ */
+static mlan_status wlan_sec_ioctl_get_key(pmlan_adapter pmadapter,
+ pmlan_ioctl_req pioctl_req)
+{
+ mlan_status ret = MLAN_STATUS_SUCCESS;
+ mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index];
+ mlan_ds_sec_cfg *sec = MNULL;
+ int index;
+ ENTER();
+
+ sec = (mlan_ds_sec_cfg *)pioctl_req->pbuf;
+
+ if (pmpriv->wep_key_curr_index >= MRVL_NUM_WEP_KEY)
+ pmpriv->wep_key_curr_index = 0;
+
+ if ((pmpriv->sec_info.wep_status == Wlan802_11WEPEnabled) ||
+ (pmpriv->sec_info.wep_status == Wlan802_11WEPKeyAbsent) ||
+ pmpriv->sec_info.ewpa_enabled || pmpriv->sec_info.wpa_enabled ||
+ pmpriv->sec_info.wpa2_enabled) {
+ sec->param.encrypt_key.key_disable = MFALSE;
+ } else {
+ sec->param.encrypt_key.key_disable = MTRUE;
+ }
+ if (sec->param.encrypt_key.key_index == MLAN_KEY_INDEX_DEFAULT) {
+ if ((pmpriv->wep_key[pmpriv->wep_key_curr_index].key_length) &&
+ (pmpriv->sec_info.wep_status == Wlan802_11WEPEnabled)) {
+ index = pmpriv->wep_key_curr_index;
+ sec->param.encrypt_key.key_index =
+ pmpriv->wep_key[index].key_index;
+ memcpy_ext(pmadapter,
+ sec->param.encrypt_key.key_material,
+ pmpriv->wep_key[index].key_material,
+ pmpriv->wep_key[index].key_length,
+ MLAN_MAX_KEY_LENGTH);
+ sec->param.encrypt_key.key_len =
+ MIN(MLAN_MAX_KEY_LENGTH,
+ pmpriv->wep_key[index].key_length);
+ } else if ((pmpriv->sec_info.wpa_enabled) ||
+ (pmpriv->sec_info.ewpa_enabled) ||
+ (pmpriv->sec_info.wpa2_enabled) ||
+ (pmpriv->sec_info.wapi_enabled)) {
+ /* Return WPA enabled */
+ sec->param.encrypt_key.key_disable = MFALSE;
+ memcpy_ext(pmadapter,
+ sec->param.encrypt_key.key_material,
+ pmpriv->aes_key.key_material,
+ pmpriv->aes_key.key_len,
+ MLAN_MAX_KEY_LENGTH);
+ sec->param.encrypt_key.key_len = MIN(
+ MLAN_MAX_KEY_LENGTH, pmpriv->aes_key.key_len);
+ } else {
+ sec->param.encrypt_key.key_disable = MTRUE;
+ }
+ } else {
+ index = sec->param.encrypt_key.key_index;
+ if (pmpriv->wep_key[index].key_length) {
+ sec->param.encrypt_key.key_index =
+ pmpriv->wep_key[index].key_index;
+ memcpy_ext(pmadapter,
+ sec->param.encrypt_key.key_material,
+ pmpriv->wep_key[index].key_material,
+ pmpriv->wep_key[index].key_length,
+ MLAN_MAX_KEY_LENGTH);
+ sec->param.encrypt_key.key_len =
+ MIN(MLAN_MAX_KEY_LENGTH,
+ pmpriv->wep_key[index].key_length);
+ } else if ((pmpriv->sec_info.wpa_enabled) ||
+ (pmpriv->sec_info.ewpa_enabled) ||
+ (pmpriv->sec_info.wpa2_enabled) ||
+ (pmpriv->sec_info.wapi_enabled)) {
+ /* Return WPA enabled */
+ sec->param.encrypt_key.key_disable = MFALSE;
+ } else {
+ sec->param.encrypt_key.key_disable = MTRUE;
+ }
+ }
+
+ LEAVE();
+ return ret;
+}
+
+/**
+ * @brief Set security key(s)
+ *
+ * @param pmadapter A pointer to mlan_adapter structure
+ * @param pioctl_req A pointer to ioctl request buffer
+ *
+ * @return MLAN_STATUS_SUCCESS/MLAN_STATUS_PENDING --success,
+ * otherwise fail
+ */
+static mlan_status wlan_sec_ioctl_encrypt_key(pmlan_adapter pmadapter,
+ pmlan_ioctl_req pioctl_req)
+{
+ mlan_status status = MLAN_STATUS_SUCCESS;
+ mlan_ds_sec_cfg *sec = MNULL;
+ ENTER();
+ sec = (mlan_ds_sec_cfg *)pioctl_req->pbuf;
+ if (pioctl_req->action == MLAN_ACT_SET) {
+ if (sec->param.encrypt_key.is_wapi_key)
+ status = wlan_sec_ioctl_set_wapi_key(pmadapter,
+ pioctl_req);
+ else if (sec->param.encrypt_key.key_len > MAX_WEP_KEY_SIZE)
+ status = wlan_sec_ioctl_set_wpa_key(pmadapter,
+ pioctl_req);
+ else
+ status = wlan_sec_ioctl_set_wep_key(pmadapter,
+ pioctl_req);
+ } else {
+ status = wlan_sec_ioctl_get_key(pmadapter, pioctl_req);
+ }
+ LEAVE();
+ return status;
+}
+
+/**
+ * @brief Query Encrpyt key
+ *
+ * @param pmadapter A pointer to mlan_adapter structure
+ * @param pioctl_req A pointer to ioctl request buffer
+ *
+ * @return MLAN_STATUS_PENDING --success, otherwise fail
+ */
+static mlan_status wlan_sec_ioctl_query_key(pmlan_adapter pmadapter,
+ pmlan_ioctl_req pioctl_req)
+{
+ mlan_status ret = MLAN_STATUS_SUCCESS;
+ mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index];
+ mlan_ds_sec_cfg *sec = MNULL;
+
+ ENTER();
+
+ sec = (mlan_ds_sec_cfg *)pioctl_req->pbuf;
+ /* Current driver only supports get PTK/GTK */
+ if (pmpriv->port_open &&
+ (pmpriv->sec_info.wpa_enabled || pmpriv->sec_info.wpa2_enabled ||
+ pmpriv->sec_info.wapi_enabled)) {
+ /* Send request to firmware */
+ ret = wlan_prepare_cmd(pmpriv, HostCmd_CMD_802_11_KEY_MATERIAL,
+ HostCmd_ACT_GEN_GET, KEY_INFO_ENABLED,
+ (t_void *)pioctl_req,
+ &sec->param.encrypt_key);
+
+ if (ret == MLAN_STATUS_SUCCESS)
+ ret = MLAN_STATUS_PENDING;
+ }
+ LEAVE();
+ return ret;
+}
+
+/**
+ * @brief Set/Get esupplicant status
+ *
+ * @param pmadapter A pointer to mlan_adapter structure
+ * @param pioctl_req A pointer to ioctl request buffer
+ *
+ * @return MLAN_STATUS_SUCCESS --success
+ */
+static mlan_status wlan_sec_ioctl_ewpa_enable(pmlan_adapter pmadapter,
+ pmlan_ioctl_req pioctl_req)
+{
+ mlan_status ret = MLAN_STATUS_SUCCESS;
+ mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index];
+ mlan_ds_sec_cfg *sec = MNULL;
+ ENTER();
+ sec = (mlan_ds_sec_cfg *)pioctl_req->pbuf;
+ if (pioctl_req->action == MLAN_ACT_GET) {
+ sec->param.ewpa_enabled = pmpriv->sec_info.ewpa_enabled;
+ } else {
+ pmpriv->sec_info.ewpa_enabled = (t_u8)sec->param.ewpa_enabled;
+ PRINTM(MINFO, "Set: ewpa_enabled = %d\n",
+ (int)pmpriv->sec_info.ewpa_enabled);
+ }
+ pioctl_req->data_read_written = sizeof(t_u32) + MLAN_SUB_COMMAND_SIZE;
+ LEAVE();
+ return ret;
+}
+
+/**
+ * @brief Get esupplicant mode
+ *
+ * @param pmadapter A pointer to mlan_adapter structure
+ * @param pioctl_req A pointer to ioctl request buffer
+ *
+ * @return MLAN_STATUS_PENDING --success, otherwise fail
+ */
+static mlan_status wlan_sec_ioctl_esupp_mode(pmlan_adapter pmadapter,
+ pmlan_ioctl_req pioctl_req)
+{
+ mlan_status ret = MLAN_STATUS_SUCCESS;
+ mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index];
+ t_u16 cmd_action = 0;
+ mlan_ds_sec_cfg *sec = MNULL;
+
+ ENTER();
+
+ sec = (mlan_ds_sec_cfg *)pioctl_req->pbuf;
+ if (pioctl_req->action == MLAN_ACT_SET) {
+ cmd_action = HostCmd_ACT_GEN_SET;
+ if (pmpriv->media_connected == MTRUE) {
+ PRINTM(MERROR,
+ "Cannot set esupplicant mode configuration while connected.\n");
+ pioctl_req->status_code = MLAN_ERROR_IOCTL_INVALID;
+ ret = MLAN_STATUS_FAILURE;
+ goto exit;
+ }
+ if (!sec->param.esupp_mode.rsn_mode ||
+ (sec->param.esupp_mode.rsn_mode & RSN_TYPE_VALID_BITS) !=
+ sec->param.esupp_mode.rsn_mode) {
+ PRINTM(MERROR, "Invalid RSN mode\n");
+ pioctl_req->status_code = MLAN_ERROR_IOCTL_INVALID;
+ ret = MLAN_STATUS_FAILURE;
+ goto exit;
+ }
+ if (!sec->param.esupp_mode.act_paircipher ||
+ (sec->param.esupp_mode.act_paircipher &
+ EMBED_CIPHER_VALID_BITS) !=
+ sec->param.esupp_mode.act_paircipher) {
+ PRINTM(MERROR, "Invalid pairwise cipher\n");
+ pioctl_req->status_code = MLAN_ERROR_IOCTL_INVALID;
+ ret = MLAN_STATUS_FAILURE;
+ goto exit;
+ }
+ if (!sec->param.esupp_mode.act_groupcipher ||
+ (sec->param.esupp_mode.act_groupcipher &
+ EMBED_CIPHER_VALID_BITS) !=
+ sec->param.esupp_mode.act_groupcipher) {
+ PRINTM(MERROR, "Invalid group cipher\n");
+ pioctl_req->status_code = MLAN_ERROR_IOCTL_INVALID;
+ ret = MLAN_STATUS_FAILURE;
+ goto exit;
+ }
+ } else {
+ cmd_action = HostCmd_ACT_GEN_GET_CURRENT;
+ }
+
+ /* Send request to firmware */
+ if (sec) {
+ ret = wlan_prepare_cmd(pmpriv, HostCmd_CMD_SUPPLICANT_PROFILE,
+ cmd_action, 0, (t_void *)pioctl_req,
+ &sec->param.esupp_mode);
+ } else {
+ ret = wlan_prepare_cmd(pmpriv, HostCmd_CMD_SUPPLICANT_PROFILE,
+ cmd_action, 0, (t_void *)pioctl_req,
+ MNULL);
+ }
+ if (ret == MLAN_STATUS_SUCCESS)
+ ret = MLAN_STATUS_PENDING;
+
+exit:
+ LEAVE();
+ return ret;
+}
+
+/**
+ * @brief Security configuration handler
+ *
+ * @param pmadapter A pointer to mlan_adapter structure
+ * @param pioctl_req A pointer to ioctl request buffer
+ *
+ * @return MLAN_STATUS_SUCCESS/MLAN_STATUS_PENDING --success,
+ * otherwise fail
+ */
+static mlan_status wlan_sec_cfg_ioctl(pmlan_adapter pmadapter,
+ pmlan_ioctl_req pioctl_req)
+{
+ mlan_status status = MLAN_STATUS_SUCCESS;
+ mlan_ds_sec_cfg *sec = MNULL;
+
+ ENTER();
+
+ if (pioctl_req->buf_len < sizeof(mlan_ds_sec_cfg)) {
+ PRINTM(MWARN, "MLAN bss IOCTL length is too short.\n");
+ pioctl_req->data_read_written = 0;
+ pioctl_req->buf_len_needed = sizeof(mlan_ds_sec_cfg);
+ pioctl_req->status_code = MLAN_ERROR_INVALID_PARAMETER;
+ LEAVE();
+ return MLAN_STATUS_RESOURCE;
+ }
+ sec = (mlan_ds_sec_cfg *)pioctl_req->pbuf;
+ switch (sec->sub_command) {
+ case MLAN_OID_SEC_CFG_AUTH_MODE:
+ status = wlan_sec_ioctl_auth_mode(pmadapter, pioctl_req);
+ break;
+ case MLAN_OID_SEC_CFG_ENCRYPT_MODE:
+ status = wlan_sec_ioctl_encrypt_mode(pmadapter, pioctl_req);
+ break;
+ case MLAN_OID_SEC_CFG_WPA_ENABLED:
+ status = wlan_sec_ioctl_wpa_enable(pmadapter, pioctl_req);
+ break;
+ case MLAN_OID_SEC_CFG_WAPI_ENABLED:
+ status = wlan_sec_ioctl_wapi_enable(pmadapter, pioctl_req);
+ break;
+ case MLAN_OID_SEC_CFG_PORT_CTRL_ENABLED:
+ status = wlan_sec_ioctl_port_ctrl_enable(pmadapter, pioctl_req);
+ break;
+ case MLAN_OID_SEC_CFG_ENCRYPT_KEY:
+ status = wlan_sec_ioctl_encrypt_key(pmadapter, pioctl_req);
+ break;
+ case MLAN_OID_SEC_QUERY_KEY:
+ status = wlan_sec_ioctl_query_key(pmadapter, pioctl_req);
+ break;
+ case MLAN_OID_SEC_CFG_PASSPHRASE:
+ status = wlan_sec_ioctl_passphrase(pmadapter, pioctl_req);
+ break;
+ case MLAN_OID_SEC_CFG_EWPA_ENABLED:
+ status = wlan_sec_ioctl_ewpa_enable(pmadapter, pioctl_req);
+ break;
+ case MLAN_OID_SEC_CFG_ESUPP_MODE:
+ status = wlan_sec_ioctl_esupp_mode(pmadapter, pioctl_req);
+ break;
+
+ default:
+ pioctl_req->status_code = MLAN_ERROR_IOCTL_INVALID;
+ status = MLAN_STATUS_FAILURE;
+ break;
+ }
+ LEAVE();
+ return status;
+}
+
+/**
+ * @brief Append/Reset IE buffer.
+ *
+ * Pass an opaque block of data, expected to be IEEE IEs, to the driver
+ * for eventual passthrough to the firmware in an associate/join
+ * (and potentially start) command. This function is the main body
+ * for both wlan_set_gen_ie_ioctl and wlan_set_gen_ie
+ *
+ * Data is appended to an existing buffer and then wrapped in a passthrough
+ * TLV in the command API to the firmware. The firmware treats the data
+ * as a transparent passthrough to the transmitted management frame.
+ *
+ * @param priv A pointer to mlan_private structure
+ * @param ie_data_ptr A pointer to iwreq structure
+ * @param ie_len Length of the IE or IE block passed in ie_data_ptr
+ *
+ * @return MLAN_STATUS_SUCCESS --success, otherwise fail
+ */
+static int wlan_set_gen_ie_helper(mlan_private *priv, t_u8 *ie_data_ptr,
+ t_u16 ie_len)
+{
+ mlan_status ret = MLAN_STATUS_SUCCESS;
+ IEEEtypes_VendorHeader_t *pvendor_ie;
+ const t_u8 wpa_oui[] = {0x00, 0x50, 0xf2, 0x01};
+ const t_u8 wps_oui[] = {0x00, 0x50, 0xf2, 0x04};
+ const t_u8 osen_oui[] = {0x50, 0x6f, 0x9a, 0x12};
+ t_u8 i = 0, temp[12] = {0};
+
+ ENTER();
+
+ /* If the passed length is zero, reset the buffer */
+ if (!ie_len) {
+ priv->gen_ie_buf_len = 0;
+ priv->wps.session_enable = MFALSE;
+ wlan_set_wpa_ie_helper(priv, MNULL, 0);
+ wlan_set_wapi_ie(priv, MNULL, 0);
+ wlan_set_osen_ie(priv, MNULL, 0);
+ } else if (!ie_data_ptr) {
+ /* MNULL check */
+ ret = MLAN_STATUS_FAILURE;
+ } else {
+ pvendor_ie = (IEEEtypes_VendorHeader_t *)ie_data_ptr;
+ if (pvendor_ie->element_id == EXT_CAPABILITY) {
+ memcpy_ext(priv->adapter, temp, &priv->ext_cap,
+ sizeof(priv->ext_cap), sizeof(temp));
+ for (i = 0;
+ i < MIN(sizeof(priv->ext_cap), pvendor_ie->len);
+ i++)
+ temp[i] |= ie_data_ptr[2 + i];
+ memcpy_ext(priv->adapter, &priv->ext_cap, temp,
+ sizeof(temp), sizeof(priv->ext_cap));
+ } else
+ /* Test to see if it is a WPA IE, if not, then it is a
+ gen IE*/
+ if (((pvendor_ie->element_id == WPA_IE) &&
+ (!memcmp(priv->adapter, pvendor_ie->oui, wpa_oui,
+ sizeof(wpa_oui)))) ||
+ (pvendor_ie->element_id == RSN_IE)) {
+ /* IE is a WPA/WPA2 IE so call set_wpa function */
+ ret = wlan_set_wpa_ie_helper(priv, ie_data_ptr, ie_len);
+ priv->wps.session_enable = MFALSE;
+ } else if (pvendor_ie->element_id == WAPI_IE) {
+ /* IE is a WAPI IE so call set_wapi function */
+ ret = wlan_set_wapi_ie(priv, ie_data_ptr, ie_len);
+ } else if ((pvendor_ie->element_id == VENDOR_SPECIFIC_221) &&
+ (!memcmp(priv->adapter, pvendor_ie->oui, osen_oui,
+ sizeof(osen_oui)))) {
+ /* IE is a OSEN IE so call set_osen function */
+ ret = wlan_set_osen_ie(priv, ie_data_ptr, ie_len);
+
+ } else if ((pvendor_ie->element_id == WPS_IE) &&
+ (priv->wps.session_enable == MFALSE) &&
+ (!memcmp(priv->adapter, pvendor_ie->oui, wps_oui,
+ sizeof(wps_oui)))) {
+ /*
+ * Discard first two byte (Element ID and Length)
+ * because they are not needed in the case of setting
+ * WPS_IE
+ */
+ if (pvendor_ie->len > 4) {
+ memcpy_ext(priv->adapter,
+ (t_u8 *)&priv->wps.wps_ie,
+ ie_data_ptr, ie_len,
+ sizeof(IEEEtypes_VendorSpecific_t));
+ HEXDUMP("wps_ie", (t_u8 *)&priv->wps.wps_ie,
+ priv->wps.wps_ie.vend_hdr.len + 2);
+ } else {
+ /* Only wps oui exist, reset driver wps buffer
+ */
+ memset(priv->adapter, (t_u8 *)&priv->wps.wps_ie,
+ 0x00, sizeof(priv->wps.wps_ie));
+ PRINTM(MINFO, "wps_ie cleared\n");
+ }
+ } else {
+ /*
+ * 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 =
+ (IEEEtypes_VendorHeader_t *)ie_data_ptr;
+ if ((pvendor_ie->element_id == WPS_IE) &&
+ (!memcmp(priv->adapter, pvendor_ie->oui,
+ wps_oui, sizeof(wps_oui)))) {
+ priv->wps.session_enable = MTRUE;
+ PRINTM(MINFO, "WPS Session Enabled.\n");
+ }
+
+ /* Append the passed data to the end of
+ * the genIeBuffer */
+ memcpy_ext(priv->adapter,
+ priv->gen_ie_buf +
+ priv->gen_ie_buf_len,
+ ie_data_ptr, ie_len,
+ MRVDRV_GENIE_BUF_SIZE -
+ priv->gen_ie_buf_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 = MLAN_STATUS_FAILURE;
+ }
+ }
+ }
+
+ /* Return MLAN_STATUS_SUCCESS, or MLAN_STATUS_FAILURE for error case */
+ LEAVE();
+ return ret;
+}
+
+/**
+ * @brief Set/Get WWS mode
+ *
+ * @param pmadapter A pointer to mlan_adapter structure
+ * @param pioctl_req A pointer to ioctl request buffer
+ *
+ * @return MLAN_STATUS_PENDING --success, otherwise fail
+ */
+static mlan_status wlan_misc_ioctl_wws_cfg(pmlan_adapter pmadapter,
+ pmlan_ioctl_req pioctl_req)
+{
+ pmlan_private pmpriv = pmadapter->priv[pioctl_req->bss_index];
+ mlan_status ret = MLAN_STATUS_SUCCESS;
+ mlan_ds_misc_cfg *misc_cfg = MNULL;
+ t_u16 cmd_action = 0;
+ t_u32 enable = 0;
+
+ ENTER();
+
+ if (pioctl_req->buf_len < sizeof(mlan_ds_misc_cfg)) {
+ PRINTM(MWARN,
+ "MLAN IOCTL information buffer length is too short.\n");
+ pioctl_req->data_read_written = 0;
+ pioctl_req->buf_len_needed = sizeof(mlan_ds_misc_cfg);
+ pioctl_req->status_code = MLAN_ERROR_INVALID_PARAMETER;
+ ret = MLAN_STATUS_RESOURCE;
+ goto exit;
+ }
+
+ misc_cfg = (mlan_ds_misc_cfg *)pioctl_req->pbuf;
+ if (pioctl_req->action == MLAN_ACT_SET)
+ cmd_action = HostCmd_ACT_GEN_SET;
+ else
+ cmd_action = HostCmd_ACT_GEN_GET;
+
+ enable = misc_cfg->param.wws_cfg;
+
+ /* Send request to firmware */
+ ret = wlan_prepare_cmd(pmpriv, HostCmd_CMD_802_11_SNMP_MIB, cmd_action,
+ WwsMode_i, (t_void *)pioctl_req, &enable);
+
+ if (ret == MLAN_STATUS_SUCCESS)
+ ret = MLAN_STATUS_PENDING;
+
+exit:
+ LEAVE();
+ return ret;
+}
+
+/**
+ * @brief Set/Get 11D status
+ *
+ * @param pmadapter A pointer to mlan_adapter structure
+ * @param pioctl_req A pointer to ioctl request buffer
+ *
+ * @return MLAN_STATUS_SUCCESS/MLAN_STATUS_PENDING --success,
+ * otherwise fail
+ */
+static mlan_status wlan_11d_cfg_ioctl_enable(pmlan_adapter pmadapter,
+ pmlan_ioctl_req pioctl_req)
+{
+ mlan_status ret = MLAN_STATUS_SUCCESS;
+ mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index];
+ mlan_ds_11d_cfg *pcfg_11d = MNULL;
+
+ ENTER();
+
+ pcfg_11d = (mlan_ds_11d_cfg *)pioctl_req->pbuf;
+
+ if (pioctl_req->action == MLAN_ACT_SET) {
+ if (pmpriv->media_connected == MTRUE) {
+ PRINTM(MIOCTL,
+ "11D setting cannot be changed while interface is active.\n");
+ ret = MLAN_STATUS_FAILURE;
+ goto done;
+ }
+
+ PRINTM(MINFO, "11D: 11dcfg SET=%d\n",
+ pcfg_11d->param.enable_11d);
+
+ /* Compare with current settings */
+ if (pmpriv->state_11d.user_enable_11d !=
+ pcfg_11d->param.enable_11d) {
+ ret = wlan_11d_enable(
+ pmpriv, pioctl_req,
+ (state_11d_t)pcfg_11d->param.enable_11d);
+ if (ret == MLAN_STATUS_SUCCESS)
+ ret = MLAN_STATUS_PENDING;
+ } else {
+ PRINTM(MINFO,
+ "11D: same as current setting, do nothing\n");
+ }
+ } else {
+ pcfg_11d->param.enable_11d =
+ (t_u32)pmpriv->state_11d.user_enable_11d;
+ pioctl_req->data_read_written =
+ sizeof(t_u32) + MLAN_SUB_COMMAND_SIZE;
+ PRINTM(MINFO, "11D: 11dcfg GET=%d\n",
+ pcfg_11d->param.enable_11d);
+ }
+
+done:
+ LEAVE();
+ return ret;
+}
+
+/**
+ * @brief Clear 11D chan table
+ *
+ * @param pmadapter A pointer to mlan_adapter structure
+ * @param pioctl_req A pointer to ioctl request buffer
+ *
+ * @return MLAN_STATUS_SUCCESS --success
+ */
+static mlan_status wlan_11d_clr_chan_table(pmlan_adapter pmadapter,
+ pmlan_ioctl_req pioctl_req)
+{
+ mlan_status ret = MLAN_STATUS_SUCCESS;
+ mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index];
+
+ ENTER();
+
+ if (pioctl_req->action == MLAN_ACT_SET) {
+ PRINTM(MINFO, "11D: 11dclrtbl SET\n");
+
+ if (wlan_11d_clear_parsedtable(pmpriv) == MLAN_STATUS_SUCCESS)
+ PRINTM(MINFO,
+ "11D: cleared parsed_region_chan (now no_of_chan=%d)\n",
+ pmadapter->parsed_region_chan.no_of_chan);
+ }
+
+ LEAVE();
+ return ret;
+}
+
+/**
+ * @brief 11D configuration handler
+ *
+ * @param pmadapter A pointer to mlan_adapter structure
+ * @param pioctl_req A pointer to ioctl request buffer
+ *
+ * @return MLAN_STATUS_SUCCESS/MLAN_STATUS_PENDING --success,
+ * otherwise fail
+ */
+static mlan_status wlan_11d_cfg_ioctl(pmlan_adapter pmadapter,
+ pmlan_ioctl_req pioctl_req)
+{
+ mlan_status status = MLAN_STATUS_SUCCESS;
+ mlan_ds_11d_cfg *pcfg_11d = MNULL;
+
+ ENTER();
+
+ if (pioctl_req->buf_len < sizeof(mlan_ds_11d_cfg)) {
+ PRINTM(MWARN, "MLAN bss IOCTL length is too short.\n");
+ pioctl_req->data_read_written = 0;
+ pioctl_req->buf_len_needed = sizeof(mlan_ds_11d_cfg);
+ pioctl_req->status_code = MLAN_ERROR_INVALID_PARAMETER;
+ status = MLAN_STATUS_RESOURCE;
+ goto exit;
+ }
+
+ pcfg_11d = (mlan_ds_11d_cfg *)pioctl_req->pbuf;
+ switch (pcfg_11d->sub_command) {
+ case MLAN_OID_11D_CFG_ENABLE:
+ status = wlan_11d_cfg_ioctl_enable(pmadapter, pioctl_req);
+ break;
+ case MLAN_OID_11D_CLR_CHAN_TABLE:
+ status = wlan_11d_clr_chan_table(pmadapter, pioctl_req);
+ break;
+ case MLAN_OID_11D_DOMAIN_INFO_EXT:
+ status = wlan_11d_cfg_domain_info(pmadapter, pioctl_req);
+ break;
+ default:
+ pioctl_req->status_code = MLAN_ERROR_IOCTL_INVALID;
+ status = MLAN_STATUS_FAILURE;
+ break;
+ }
+
+exit:
+ LEAVE();
+ return status;
+}
+
+/**
+ * @brief WPS configuration handler
+ *
+ * @param pmadapter A pointer to mlan_adapter structure
+ * @param pioctl_req A pointer to ioctl request buffer
+ *
+ * @return MLAN_STATUS_SUCCESS --success, otherwise fail
+ */
+static mlan_status wlan_wps_cfg_ioctl(pmlan_adapter pmadapter,
+ pmlan_ioctl_req pioctl_req)
+{
+ mlan_status status = MLAN_STATUS_SUCCESS;
+ mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index];
+ mlan_ds_wps_cfg *pwps = MNULL;
+
+ ENTER();
+
+ if (pioctl_req->buf_len < sizeof(mlan_ds_wps_cfg)) {
+ PRINTM(MWARN, "MLAN bss IOCTL length is too short.\n");
+ pioctl_req->data_read_written = 0;
+ pioctl_req->buf_len_needed = sizeof(mlan_ds_wps_cfg);
+ pioctl_req->status_code = MLAN_ERROR_INVALID_PARAMETER;
+ LEAVE();
+ return MLAN_STATUS_RESOURCE;
+ }
+
+ pwps = (mlan_ds_wps_cfg *)pioctl_req->pbuf;
+ switch (pwps->sub_command) {
+ case MLAN_OID_WPS_CFG_SESSION:
+ if (pioctl_req->action == MLAN_ACT_SET) {
+ if (pwps->param.wps_session ==
+ MLAN_WPS_CFG_SESSION_START)
+ pmpriv->wps.session_enable = MTRUE;
+ else
+ pmpriv->wps.session_enable = MFALSE;
+ } else {
+ pwps->param.wps_session =
+ (t_u32)pmpriv->wps.session_enable;
+ pioctl_req->data_read_written = sizeof(t_u32);
+ PRINTM(MINFO, "wpscfg GET=%d\n",
+ pwps->param.wps_session);
+ }
+ break;
+ default:
+ pioctl_req->status_code = MLAN_ERROR_IOCTL_INVALID;
+ status = MLAN_STATUS_FAILURE;
+ break;
+ }
+
+ LEAVE();
+ return status;
+}
+
+/**
+ * @brief register memory access handler
+ *
+ * @param pmadapter A pointer to mlan_adapter structure
+ * @param pioctl_req A pointer to ioctl request buffer
+ *
+ * @return MLAN_STATUS_PENDING --success, otherwise fail
+ */
+static mlan_status wlan_reg_mem_ioctl(pmlan_adapter pmadapter,
+ pmlan_ioctl_req pioctl_req)
+{
+ mlan_status status = MLAN_STATUS_SUCCESS;
+ mlan_ds_reg_mem *reg_mem = MNULL;
+
+ ENTER();
+
+ if (pioctl_req->buf_len < sizeof(mlan_ds_reg_mem)) {
+ PRINTM(MWARN, "MLAN REG_MEM IOCTL length is too short\n");
+ pioctl_req->data_read_written = 0;
+ pioctl_req->buf_len_needed = sizeof(mlan_ds_reg_mem);
+ pioctl_req->status_code = MLAN_ERROR_INVALID_PARAMETER;
+ LEAVE();
+ return MLAN_STATUS_RESOURCE;
+ }
+ reg_mem = (mlan_ds_reg_mem *)pioctl_req->pbuf;
+ switch (reg_mem->sub_command) {
+ case MLAN_OID_REG_RW:
+ status = wlan_reg_mem_ioctl_reg_rw(pmadapter, pioctl_req);
+ break;
+ case MLAN_OID_EEPROM_RD:
+ status = wlan_reg_mem_ioctl_read_eeprom(pmadapter, pioctl_req);
+ break;
+ case MLAN_OID_MEM_RW:
+ status = wlan_reg_mem_ioctl_mem_rw(pmadapter, pioctl_req);
+ break;
+ default:
+ pioctl_req->status_code = MLAN_ERROR_IOCTL_INVALID;
+ status = MLAN_STATUS_FAILURE;
+ break;
+ }
+ LEAVE();
+ return status;
+}
+
+/**
+ * @brief 802.11h ad-hoc start channel check
+ *
+ * @param pmadapter A pointer to mlan_adapter structure
+ * @param pioctl_req A pointer to ioctl request buffer
+ *
+ * @return MLAN_STATUS_PENDING --success, otherwise fail
+ */
+static mlan_status wlan_11h_channel_check_req(pmlan_adapter pmadapter,
+ pmlan_ioctl_req pioctl_req)
+{
+ pmlan_private pmpriv = MNULL;
+ mlan_status ret = MLAN_STATUS_FAILURE;
+ t_u8 chan_width = CHAN_BW_20MHZ;
+ Band_Config_t bandcfg;
+
+ ENTER();
+
+ if (pioctl_req != MNULL) {
+ pmpriv = pmadapter->priv[pioctl_req->bss_index];
+ } else {
+ PRINTM(MERROR, "MLAN IOCTL information is not present\n");
+ LEAVE();
+ return MLAN_STATUS_FAILURE;
+ }
+
+ memset(pmadapter, &bandcfg, 0, sizeof(Band_Config_t));
+ pmpriv->adhoc_state = ADHOC_STARTING;
+
+ if ((pmadapter->adhoc_start_band & BAND_A)) {
+ if (pmpriv->intf_state_11h.adhoc_auto_sel_chan)
+ pmpriv->adhoc_channel =
+ wlan_11h_get_adhoc_start_channel(pmpriv);
+
+ /*
+ * Check if the region and channel requires a channel
+ * availability check.
+ */
+ if (wlan_11h_radar_detect_required(pmpriv,
+ pmpriv->adhoc_channel) &&
+ !wlan_11h_is_channel_under_nop(pmadapter,
+ pmpriv->adhoc_channel)) {
+ /*
+ * Radar detection is required for this channel, make
+ * sure 11h is activated in the firmware
+ */
+ ret = wlan_11h_activate(pmpriv, MNULL, MTRUE);
+ ret = wlan_11h_config_master_radar_det(pmpriv, MTRUE);
+ ret = wlan_11h_check_update_radar_det_state(pmpriv);
+
+ /* Check for radar on the channel */
+ if ((pmadapter->chan_bandwidth ==
+ CHANNEL_BW_40MHZ_ABOVE) ||
+ (pmadapter->chan_bandwidth ==
+ CHANNEL_BW_40MHZ_BELOW)) {
+ chan_width = CHAN_BW_40MHZ;
+ if (pmadapter->chanrpt_param_bandcfg) {
+ bandcfg.chan2Offset =
+ pmadapter->chan_bandwidth;
+ }
+ } else if (pmadapter->chan_bandwidth ==
+ CHANNEL_BW_80MHZ)
+ chan_width = CHAN_BW_80MHZ;
+ if (pmadapter->chanrpt_param_bandcfg) {
+ bandcfg.chanWidth = chan_width;
+ bandcfg.chanBand = BAND_5GHZ;
+ } else {
+ *((t_u8 *)&bandcfg) = chan_width;
+ }
+
+ ret = wlan_11h_issue_radar_detect(pmpriv, pioctl_req,
+ pmpriv->adhoc_channel,
+ bandcfg);
+ if (ret == MLAN_STATUS_SUCCESS)
+ ret = MLAN_STATUS_PENDING;
+ }
+ }
+
+ LEAVE();
+ return ret;
+}
+
+/**
+ * @brief 802.11h set/get local power constraint
+ *
+ * @param pmadapter A pointer to mlan_adapter structure
+ * @param pioctl_req A pointer to ioctl request buffer
+ *
+ * @return MLAN_STATUS_SUCCESS
+ */
+static mlan_status
+wlan_11h_ioctl_local_power_constraint(pmlan_adapter pmadapter,
+ pmlan_ioctl_req pioctl_req)
+{
+ mlan_ds_11h_cfg *ds_11hcfg = MNULL;
+ t_s8 *plocalpower = &pmadapter->state_11h.usr_def_power_constraint;
+
+ ENTER();
+
+ ds_11hcfg = (mlan_ds_11h_cfg *)pioctl_req->pbuf;
+
+ if (pioctl_req->action == MLAN_ACT_GET)
+ ds_11hcfg->param.usr_local_power_constraint = *plocalpower;
+ else
+ *plocalpower = ds_11hcfg->param.usr_local_power_constraint;
+
+ LEAVE();
+ return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ * @brief 11h configuration handler
+ *
+ * @param pmadapter A pointer to mlan_adapter structure
+ * @param pioctl_req A pointer to ioctl request buffer
+ *
+ * @return MLAN_STATUS_SUCCESS/MLAN_STATUS_PENDING --success,
+ * otherwise fail
+ */
+static mlan_status wlan_11h_cfg_ioctl(pmlan_adapter pmadapter,
+ pmlan_ioctl_req pioctl_req)
+{
+ mlan_status status = MLAN_STATUS_SUCCESS;
+ mlan_ds_11h_cfg *ds_11hcfg = MNULL;
+
+ ENTER();
+
+ if (pioctl_req->buf_len < sizeof(mlan_ds_11h_cfg)) {
+ PRINTM(MWARN, "MLAN 11H IOCTL length is too short.\n");
+ pioctl_req->data_read_written = 0;
+ pioctl_req->buf_len_needed = sizeof(mlan_ds_11h_cfg);
+ pioctl_req->status_code = MLAN_ERROR_INVALID_PARAMETER;
+ LEAVE();
+ return MLAN_STATUS_RESOURCE;
+ }
+ ds_11hcfg = (mlan_ds_11h_cfg *)pioctl_req->pbuf;
+
+ switch (ds_11hcfg->sub_command) {
+ case MLAN_OID_11H_CHANNEL_CHECK:
+ status = wlan_11h_channel_check_req(pmadapter, pioctl_req);
+ break;
+ case MLAN_OID_11H_LOCAL_POWER_CONSTRAINT:
+ status = wlan_11h_ioctl_local_power_constraint(pmadapter,
+ pioctl_req);
+ break;
+ case MLAN_OID_11H_DFS_TESTING:
+ status = wlan_11h_ioctl_dfs_testing(pmadapter, pioctl_req);
+ break;
+ case MLAN_OID_11H_DFS_W53_CFG:
+ status = wlan_11h_ioctl_dfs_w53_cfg(pmadapter, pioctl_req);
+ break;
+ default:
+ pioctl_req->status_code = MLAN_ERROR_IOCTL_INVALID;
+ status = MLAN_STATUS_FAILURE;
+ break;
+ }
+
+ LEAVE();
+ return status;
+}
+
+/**
+ * @brief Set/Get generic IE
+ *
+ * @param pmadapter A pointer to mlan_adapter structure
+ * @param pioctl_req A pointer to ioctl request buffer
+ *
+ * @return MLAN_STATUS_SUCCESS --success, otherwise fail
+ */
+static mlan_status wlan_misc_ioctl_gen_ie(pmlan_adapter pmadapter,
+ pmlan_ioctl_req pioctl_req)
+{
+ mlan_status ret = MLAN_STATUS_SUCCESS;
+ mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index];
+ mlan_ds_misc_cfg *misc = MNULL;
+
+ ENTER();
+
+ misc = (mlan_ds_misc_cfg *)pioctl_req->pbuf;
+ switch (misc->param.gen_ie.type) {
+ case MLAN_IE_TYPE_GEN_IE:
+ if (pioctl_req->action == MLAN_ACT_GET) {
+ misc->param.gen_ie.len = pmpriv->wpa_ie_len;
+ memcpy_ext(pmadapter, misc->param.gen_ie.ie_data,
+ pmpriv->wpa_ie, misc->param.gen_ie.len,
+ MAX_IE_SIZE);
+ } else {
+ wlan_set_gen_ie_helper(pmpriv,
+ misc->param.gen_ie.ie_data,
+ (t_u16)misc->param.gen_ie.len);
+ }
+ break;
+ default:
+ PRINTM(MERROR, "Invalid IE type\n");
+ pioctl_req->status_code = MLAN_ERROR_INVALID_PARAMETER;
+ ret = MLAN_STATUS_FAILURE;
+ }
+ pioctl_req->data_read_written =
+ sizeof(mlan_ds_misc_gen_ie) + MLAN_SUB_COMMAND_SIZE;
+ LEAVE();
+ return ret;
+}
+
+/**
+ * @brief Perform warm reset
+ *
+ * @param pmadapter A pointer to mlan_adapter structure
+ * @param pioctl_req A pointer to ioctl request buffer
+ *
+ * @return MLAN_STATUS_PENDING --success, MLAN_STATUS_FAILURE
+ */
+mlan_status wlan_misc_ioctl_warm_reset(pmlan_adapter pmadapter,
+ pmlan_ioctl_req pioctl_req)
+{
+ pmlan_private pmpriv = pmadapter->priv[pioctl_req->bss_index];
+ mlan_status ret = MLAN_STATUS_SUCCESS;
+ pmlan_callbacks pcb = &pmadapter->callbacks;
+ pmlan_buffer pmbuf;
+ t_s32 i = 0;
+ mlan_ds_misc_cfg *misc = (mlan_ds_misc_cfg *)pioctl_req->pbuf;
+
+ ENTER();
+ mlan_block_rx_process(pmadapter, MTRUE);
+
+ /* Cancel all pending commands and complete ioctls */
+ if (misc->param.fw_reload)
+ wlan_cancel_all_pending_cmd(pmadapter, MTRUE);
+
+ /** Init all the head nodes and free all the locks here */
+ for (i = 0; i < pmadapter->priv_num; i++)
+ wlan_free_priv(pmadapter->priv[i]);
+
+ while ((pmbuf = (pmlan_buffer)util_dequeue_list(
+ pmadapter->pmoal_handle, &pmadapter->rx_data_queue,
+ pcb->moal_spin_lock, pcb->moal_spin_unlock))) {
+ pmadapter->ops.data_complete(pmadapter, pmbuf,
+ MLAN_STATUS_FAILURE);
+ }
+ pmadapter->rx_pkts_queued = 0;
+
+ /* Initialize adapter structure */
+ wlan_init_adapter(pmadapter);
+ pmadapter->hw_status = WlanHardwareStatusInitializing;
+
+ /* Initialize private structures */
+ for (i = 0; i < pmadapter->priv_num; i++) {
+ if (pmadapter->priv[i])
+ wlan_init_priv(pmadapter->priv[i]);
+ }
+ mlan_block_rx_process(pmadapter, MFALSE);
+
+ if (misc->param.fw_reload != MTRUE) {
+ /* Restart the firmware */
+ ret = wlan_prepare_cmd(pmpriv, HostCmd_CMD_FUNC_SHUTDOWN,
+ HostCmd_ACT_GEN_SET, 0, MNULL, MNULL);
+ if (ret)
+ goto done;
+ }
+
+ /* Issue firmware initialize commands for first BSS,
+ * for other interfaces it will be called after getting
+ * the last init command response of previous interface
+ */
+ pmpriv = wlan_get_priv(pmadapter, MLAN_BSS_ROLE_ANY);
+ if (!pmpriv) {
+ ret = MLAN_STATUS_FAILURE;
+ LEAVE();
+ return ret;
+ }
+ ret = wlan_adapter_get_hw_spec(pmpriv->adapter);
+ if (ret == MLAN_STATUS_FAILURE) {
+ LEAVE();
+ return ret;
+ }
+ ret = pmpriv->ops.init_cmd(pmpriv, MTRUE);
+ if (ret == MLAN_STATUS_FAILURE) {
+ LEAVE();
+ return ret;
+ }
+ if (ret == MLAN_STATUS_PENDING)
+ pmadapter->pwarm_reset_ioctl_req = pioctl_req;
+done:
+ LEAVE();
+ return ret;
+}
+
+#ifdef SDIO
+/**
+ * @brief Reconfigure SDIO multiport aggregation parameters
+ *
+ * @param pmadapter A pointer to mlan_adapter structure
+ * @param pioctl_req A pointer to ioctl request buffer
+ *
+ * @return MLAN_STATUS_SUCCESS --success, otherwise fail
+ */
+static mlan_status wlan_misc_ioctl_sdio_mpa_ctrl(pmlan_adapter pmadapter,
+ pmlan_ioctl_req pioctl_req)
+{
+ mlan_status ret = MLAN_STATUS_SUCCESS;
+ pmlan_private pmpriv = pmadapter->priv[pioctl_req->bss_index];
+ mlan_ds_misc_cfg *misc = (mlan_ds_misc_cfg *)pioctl_req->pbuf;
+ mlan_ds_misc_sdio_mpa_ctrl *mpa_ctrl = MNULL;
+
+ ENTER();
+
+ mpa_ctrl = &misc->param.mpa_ctrl;
+
+ if (pioctl_req->action == MLAN_ACT_SET) {
+ if (pmpriv->media_connected == MTRUE) {
+ PRINTM(MMSG,
+ "SDIO MPA CTRL: not allowed in connected state\n");
+ pioctl_req->status_code = MLAN_ERROR_IOCTL_INVALID;
+ ret = MLAN_STATUS_FAILURE;
+ goto exit;
+ }
+
+ if (mpa_ctrl->tx_enable > 1) {
+ pioctl_req->status_code = MLAN_ERROR_INVALID_PARAMETER;
+ ret = MLAN_STATUS_FAILURE;
+ goto exit;
+ }
+
+ if (mpa_ctrl->rx_enable > 1) {
+ pioctl_req->status_code = MLAN_ERROR_INVALID_PARAMETER;
+ ret = MLAN_STATUS_FAILURE;
+ goto exit;
+ }
+
+ if (mpa_ctrl->tx_max_ports > SDIO_MP_AGGR_DEF_PKT_LIMIT) {
+ pioctl_req->status_code = MLAN_ERROR_INVALID_PARAMETER;
+ ret = MLAN_STATUS_FAILURE;
+ goto exit;
+ }
+
+ if (mpa_ctrl->rx_max_ports > SDIO_MP_AGGR_DEF_PKT_LIMIT) {
+ pioctl_req->status_code = MLAN_ERROR_INVALID_PARAMETER;
+ ret = MLAN_STATUS_FAILURE;
+ goto exit;
+ }
+
+ if (mpa_ctrl->tx_buf_size || mpa_ctrl->rx_buf_size) {
+ wlan_free_sdio_mpa_buffers(pmadapter);
+
+ if (mpa_ctrl->tx_buf_size > 0)
+ pmadapter->pcard_sd->mpa_tx.buf_size =
+ mpa_ctrl->tx_buf_size;
+
+ if (mpa_ctrl->rx_buf_size > 0)
+ pmadapter->pcard_sd->mpa_rx.buf_size =
+ mpa_ctrl->rx_buf_size;
+
+ if (wlan_alloc_sdio_mpa_buffers(
+ pmadapter,
+ pmadapter->pcard_sd->mpa_tx.buf_size,
+ pmadapter->pcard_sd->mpa_rx.buf_size) !=
+ MLAN_STATUS_SUCCESS) {
+ PRINTM(MERROR,
+ "Failed to allocate sdio mp-a buffers\n");
+ pioctl_req->status_code = MLAN_ERROR_NO_MEM;
+ ret = MLAN_STATUS_FAILURE;
+ goto exit;
+ }
+ }
+
+ if (mpa_ctrl->tx_max_ports > 0)
+ pmadapter->pcard_sd->mpa_tx.pkt_aggr_limit =
+ mpa_ctrl->tx_max_ports;
+ if (mpa_ctrl->rx_max_ports > 0)
+ pmadapter->pcard_sd->mpa_rx.pkt_aggr_limit =
+ mpa_ctrl->rx_max_ports;
+
+ pmadapter->pcard_sd->mpa_tx.enabled = (t_u8)mpa_ctrl->tx_enable;
+ pmadapter->pcard_sd->mpa_rx.enabled = (t_u8)mpa_ctrl->rx_enable;
+
+ } else {
+ mpa_ctrl->tx_enable =
+ (t_u16)pmadapter->pcard_sd->mpa_tx.enabled;
+ mpa_ctrl->rx_enable =
+ (t_u16)pmadapter->pcard_sd->mpa_rx.enabled;
+ mpa_ctrl->tx_buf_size =
+ (t_u16)pmadapter->pcard_sd->mpa_tx.buf_size;
+ mpa_ctrl->rx_buf_size =
+ (t_u16)pmadapter->pcard_sd->mpa_rx.buf_size;
+ mpa_ctrl->tx_max_ports =
+ (t_u16)pmadapter->pcard_sd->mpa_tx.pkt_aggr_limit;
+ mpa_ctrl->rx_max_ports =
+ (t_u16)pmadapter->pcard_sd->mpa_rx.pkt_aggr_limit;
+ }
+
+exit:
+ LEAVE();
+ return ret;
+}
+#endif
+
+/**
+ * @brief Set/Get system clock configuration
+ *
+ * @param pmadapter A pointer to mlan_adapter structure
+ * @param pioctl_req A pointer to ioctl request buffer
+ *
+ * @return MLAN_STATUS_PENDING --success, otherwise fail
+ */
+static mlan_status wlan_misc_ioctl_sysclock(pmlan_adapter pmadapter,
+ pmlan_ioctl_req pioctl_req)
+{
+ mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index];
+ mlan_ds_misc_cfg *misc = MNULL;
+ mlan_status ret = MLAN_STATUS_SUCCESS;
+ t_u16 cmd_action = 0;
+
+ ENTER();
+
+ misc = (mlan_ds_misc_cfg *)pioctl_req->pbuf;
+ if (pioctl_req->action == MLAN_ACT_GET)
+ cmd_action = HostCmd_ACT_GEN_GET;
+ else
+ cmd_action = HostCmd_ACT_GEN_SET;
+
+ /* Send request to firmware */
+ ret = wlan_prepare_cmd(pmpriv, HostCmd_CMD_ECL_SYSTEM_CLOCK_CONFIG,
+ cmd_action, 0, (t_void *)pioctl_req,
+ (t_void *)&misc->param.sys_clock);
+
+ if (ret == MLAN_STATUS_SUCCESS)
+ ret = MLAN_STATUS_PENDING;
+
+ LEAVE();
+ return ret;
+}
+
+/**
+ * @brief Get the associate response
+ *
+ * @param pmadapter A pointer to mlan_adapter structure
+ * @param pioctl_req A pointer to ioctl request buffer
+ *
+ * @return MLAN_STATUS_SUCCESS --success
+ */
+static mlan_status wlan_misc_ioctl_get_assoc_rsp(pmlan_adapter pmadapter,
+ pmlan_ioctl_req pioctl_req)
+{
+ mlan_ds_misc_cfg *misc = MNULL;
+ mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index];
+ mlan_status ret = MLAN_STATUS_SUCCESS;
+
+ ENTER();
+
+ misc = (mlan_ds_misc_cfg *)pioctl_req->pbuf;
+ if ((pioctl_req->action == MLAN_ACT_GET) && pmpriv->assoc_rsp_size) {
+ memcpy_ext(pmadapter, misc->param.assoc_resp.assoc_resp_buf,
+ pmpriv->assoc_rsp_buf, pmpriv->assoc_rsp_size,
+ ASSOC_RSP_BUF_SIZE);
+ misc->param.assoc_resp.assoc_resp_len =
+ MIN(ASSOC_RSP_BUF_SIZE, pmpriv->assoc_rsp_size);
+ }
+
+ LEAVE();
+ return ret;
+}
+
+/**
+ * @brief Send function softreset command to firmware
+ *
+ * @param pmadapter A pointer to mlan_adapter structure
+ * @param pioctl_req A pointer to ioctl request buffer
+ *
+ * @return MLAN_STATUS_PENDING --success, otherwise fail
+ */
+static mlan_status wlan_misc_ioctl_soft_reset(pmlan_adapter pmadapter,
+ pmlan_ioctl_req pioctl_req)
+{
+ mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index];
+ mlan_status ret = MLAN_STATUS_SUCCESS;
+
+ ENTER();
+ /* Send command to firmware */
+ ret = wlan_prepare_cmd(pmpriv, HostCmd_CMD_SOFT_RESET,
+ HostCmd_ACT_GEN_SET, 0, (t_void *)pioctl_req,
+ MNULL);
+
+ if (ret == MLAN_STATUS_SUCCESS)
+ ret = MLAN_STATUS_PENDING;
+ LEAVE();
+ return ret;
+}
+
+/**
+ * @brief Get the thermal reading
+ *
+ * @param pmadapter A pointer to mlan_adapter structure
+ * @param pioctl_req A pointer to ioctl request buffer
+ *
+ * @return MLAN_STATUS_PENDING -- success, otherwise fail
+ */
+mlan_status wlan_misc_ioctl_thermal(pmlan_adapter pmadapter,
+ pmlan_ioctl_req pioctl_req)
+{
+ mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index];
+ mlan_status ret = MLAN_STATUS_SUCCESS;
+ mlan_ds_misc_cfg *misc = MNULL;
+ t_u16 cmd_action = 0;
+
+ ENTER();
+
+ if (pioctl_req->buf_len < sizeof(mlan_ds_misc_cfg)) {
+ PRINTM(MWARN,
+ "MLAN IOCTL information buffer length is too short.\n");
+ pioctl_req->data_read_written = 0;
+ pioctl_req->buf_len_needed = sizeof(mlan_ds_misc_cfg);
+ pioctl_req->status_code = MLAN_ERROR_INVALID_PARAMETER;
+ LEAVE();
+ return MLAN_STATUS_RESOURCE;
+ }
+
+ misc = (mlan_ds_misc_cfg *)pioctl_req->pbuf;
+ if (pioctl_req->action == MLAN_ACT_SET) {
+ PRINTM(MERROR, "Thermal reading setting is not allowed!\n");
+ LEAVE();
+ return MLAN_STATUS_FAILURE;
+ } else {
+ cmd_action = HostCmd_ACT_GEN_GET;
+ }
+
+ /* Send command to firmware */
+ ret = wlan_prepare_cmd(pmpriv, HostCmd_CMD_802_11_SNMP_MIB, cmd_action,
+ Thermal_i, (t_void *)pioctl_req, MNULL);
+
+ if (ret == MLAN_STATUS_SUCCESS)
+ ret = MLAN_STATUS_PENDING;
+
+ LEAVE();
+ return ret;
+}
+
+/**
+ * @brief Get/Set subscribe event
+ *
+ * @param pmadapter A pointer to mlan_adapter structure
+ * @param pioctl_req A pointer to ioctl request buffer
+ *
+ * @return MLAN_STATUS_PENDING -- success, otherwise fail
+ */
+mlan_status wlan_misc_ioctl_subscribe_evt(pmlan_adapter pmadapter,
+ pmlan_ioctl_req pioctl_req)
+{
+ mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index];
+ mlan_status ret = MLAN_STATUS_SUCCESS;
+ mlan_ds_misc_cfg *misc = MNULL;
+ t_u16 cmd_action = 0;
+
+ ENTER();
+
+ misc = (mlan_ds_misc_cfg *)pioctl_req->pbuf;
+ if (pioctl_req->action == MLAN_ACT_SET)
+ cmd_action = HostCmd_ACT_GEN_SET;
+ else
+ cmd_action = HostCmd_ACT_GEN_GET;
+
+ /* Send command to firmware */
+ ret = wlan_prepare_cmd(pmpriv, HostCmd_CMD_802_11_SUBSCRIBE_EVENT,
+ cmd_action, 0, (t_void *)pioctl_req,
+ &misc->param.subscribe_event);
+
+ if (ret == MLAN_STATUS_SUCCESS)
+ ret = MLAN_STATUS_PENDING;
+
+ LEAVE();
+ return ret;
+}
+
+#define FLTR_BUF_IP_OFFSET 24
+#define FLTR_BUF_IP_OFFSET_2_IP_1 9
+#define FLTR_BUF_IP_OFFSET_2_IP_2 26
+
+/**
+ * @brief Enable/Disable Auto ARP resonse
+ *
+ * @param pmadapter A pointer to mlan_adapter structure
+ * @param pioctl_req A pointer to ioctl request buffer
+ * @param ipv4_addr ipv4 Address
+ * @param num_ipv4 Number of ipv4 Addresses
+ *
+ * @return MLAN_STATUS_PENDING --success, otherwise fail
+ */
+mlan_status wlan_ipaddr_auto_arp_resp(pmlan_adapter pmadapter,
+ pmlan_ioctl_req pioctl_req,
+ t_u32 *ipv4_addr, t_u8 num_ipv4)
+{
+ mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index];
+ mlan_status ret = MLAN_STATUS_SUCCESS;
+ HostCmd_DS_GEN *hostcmd_hdr;
+ HostCmd_DS_MEF_CFG *mefcmd;
+ pmlan_callbacks pcb = &pmadapter->callbacks;
+ mlan_ds_misc_cmd *hostcmd;
+ t_u32 buf_len = 0;
+ t_u8 *buf, *filter;
+
+ t_u8 fltr_buf[] = {0x01, 0x10, 0x21, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x01, 0x08, 0x06, 0x02, 0x02, 0x14, 0x00, 0x00,
+ 0x00, 0x01, 0x41, 0x01, 0x00, 0x00, 0x00, 0x01,
+ 0xc0, 0xa8, 0x01, 0x6d, 0x04, 0x02, 0x2e, 0x00,
+ 0x00, 0x00, 0x01, 0x41, 0x44};
+ t_u8 fltr_buf_2_ip[] = {0x01, 0x10, 0x33, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x01, 0xc0, 0xa8, 0x01, 0x6d, 0x04, 0x02, 0x2e,
+ 0x00, 0x00, 0x00, 0x01, 0x41, 0x01, 0x00, 0x00,
+ 0x00, 0x01, 0xc0, 0xa8, 0x02, 0x6d, 0x04, 0x02,
+ 0x2e, 0x00, 0x00, 0x00, 0x01, 0x41, 0x45, 0x01,
+ 0x00, 0x00, 0x00, 0x01, 0x08, 0x06, 0x02, 0x02,
+ 0x14, 0x00, 0x00, 0x00, 0x01, 0x41, 0x44};
+
+ ENTER();
+
+ ret = pcb->moal_malloc(pmadapter->pmoal_handle,
+ sizeof(mlan_ds_misc_cmd), MLAN_MEM_DEF,
+ (t_u8 **)&hostcmd);
+
+ if (ret != MLAN_STATUS_SUCCESS || hostcmd == MNULL) {
+ PRINTM(MERROR, "Failed to allocate hostcmd buffer\n");
+ pioctl_req->status_code = MLAN_ERROR_NO_MEM;
+ LEAVE();
+ return MLAN_STATUS_FAILURE;
+ }
+
+ memset(pmpriv->adapter, hostcmd, 0, sizeof(mlan_ds_misc_cmd));
+ buf = hostcmd->cmd;
+
+ /* Prepare hostcmd buffer */
+ hostcmd_hdr = (HostCmd_DS_GEN *)(buf);
+ hostcmd_hdr->command = wlan_cpu_to_le16(HostCmd_CMD_MEF_CFG);
+ mefcmd = (HostCmd_DS_MEF_CFG *)(buf + S_DS_GEN);
+ buf_len = S_DS_GEN;
+
+ if (!ipv4_addr) {
+ PRINTM(MINFO, "Disable Auto ARP Response\n");
+ mefcmd->criteria = wlan_cpu_to_le32(0);
+ mefcmd->nentries = wlan_cpu_to_le16(0);
+ buf_len += sizeof(HostCmd_DS_MEF_CFG);
+ } else {
+ /* Event bit (bit2) of HS conditions should be masked out */
+ mefcmd->criteria = wlan_cpu_to_le32(
+ pmpriv->adapter->hs_cfg.conditions & ~MBIT(2));
+ mefcmd->nentries = wlan_cpu_to_le16(1);
+ buf_len += sizeof(HostCmd_DS_MEF_CFG);
+ filter = buf + buf_len;
+ if (num_ipv4 == 1) {
+ memcpy_ext(pmpriv->adapter, filter, fltr_buf,
+ sizeof(fltr_buf), sizeof(fltr_buf));
+ memcpy_ext(pmpriv->adapter, &filter[FLTR_BUF_IP_OFFSET],
+ &ipv4_addr[0], sizeof(t_u32), sizeof(t_u32));
+ buf_len += sizeof(fltr_buf);
+ } else if (num_ipv4 >= 2) {
+ memcpy_ext(pmpriv->adapter, filter, fltr_buf_2_ip,
+ sizeof(fltr_buf_2_ip),
+ sizeof(fltr_buf_2_ip));
+ memcpy_ext(pmpriv->adapter,
+ &filter[FLTR_BUF_IP_OFFSET_2_IP_1],
+ &ipv4_addr[0], sizeof(t_u32), sizeof(t_u32));
+ memcpy_ext(pmpriv->adapter,
+ &filter[FLTR_BUF_IP_OFFSET_2_IP_2],
+ &ipv4_addr[1], sizeof(t_u32), sizeof(t_u32));
+ buf_len += sizeof(fltr_buf_2_ip);
+ }
+ }
+ hostcmd_hdr->size = wlan_cpu_to_le16(buf_len);
+ hostcmd->len = buf_len;
+
+ /* Send command to firmware */
+ ret = wlan_prepare_cmd(pmpriv, 0, 0, 0, (t_void *)pioctl_req,
+ (t_void *)hostcmd);
+ if (ret == MLAN_STATUS_SUCCESS)
+ ret = MLAN_STATUS_PENDING;
+
+ pcb->moal_mfree(pmadapter->pmoal_handle, (t_u8 *)hostcmd);
+
+ LEAVE();
+ return ret;
+}
+
+/**
+ * @brief MEF configuration
+ *
+ * @param pmadapter A pointer to mlan_adapter structure
+ * @param pioctl_req A pointer to ioctl request buffer
+ *
+ * @return MLAN_STATUS_PENDING --success, otherwise fail
+ */
+mlan_status wlan_misc_ioctl_mef_cfg(pmlan_adapter pmadapter,
+ pmlan_ioctl_req pioctl_req)
+{
+ mlan_status ret = MLAN_STATUS_SUCCESS;
+ mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index];
+ mlan_ds_misc_mef_cfg *mef_cfg =
+ &((mlan_ds_misc_cfg *)pioctl_req->pbuf)->param.mef_cfg;
+ pmlan_callbacks pcb = &pmadapter->callbacks;
+ HostCmd_DS_GEN *hostcmd_hdr;
+ HostCmd_DS_MEF_CFG *mefcmd;
+ mlan_ds_misc_cmd *hostcmd = MNULL;
+ t_u32 buf_len = 0;
+ t_u8 *buf, *filter;
+ t_u8 fltr_buf[] = {0x02, 0x00, 0x2f, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01,
+ 0x01, 0x00, 0x5e, 0x03, 0x02, 0x00, 0x00, 0x00, 0x00,
+ 0x01, 0x41, 0x06, 0x00, 0x00, 0x00, 0x01, 0xff, 0x01,
+ 0x02, 0x00, 0x00, 0x00, 0x00, 0x01, 0x41, 0x45, 0x01,
+ 0x00, 0x00, 0x00, 0x01, 0x33, 0x33, 0x02, 0x02, 0x00,
+ 0x00, 0x00, 0x00, 0x01, 0x41, 0x45};
+
+ ENTER();
+
+ /* GET operation */
+ if (pioctl_req->action == MLAN_ACT_GET) {
+ /* TODO: need to store for get operation */
+ goto done;
+ }
+
+ ret = pcb->moal_malloc(pmadapter->pmoal_handle,
+ sizeof(mlan_ds_misc_cmd), MLAN_MEM_DEF,
+ (t_u8 **)&hostcmd);
+
+ if (ret != MLAN_STATUS_SUCCESS || hostcmd == MNULL) {
+ PRINTM(MERROR, "Failed to allocate hostcmd buffer\n");
+ pioctl_req->status_code = MLAN_ERROR_NO_MEM;
+ ret = MLAN_STATUS_FAILURE;
+ goto done;
+ }
+
+ memset(pmpriv->adapter, hostcmd, 0, sizeof(mlan_ds_misc_cmd));
+ buf = hostcmd->cmd;
+
+ /* Prepare hostcmd buffer */
+ hostcmd_hdr = (HostCmd_DS_GEN *)(buf);
+ hostcmd_hdr->command = wlan_cpu_to_le16(HostCmd_CMD_MEF_CFG);
+ mefcmd = (HostCmd_DS_MEF_CFG *)(buf + S_DS_GEN);
+ buf_len = S_DS_GEN;
+
+ switch (mef_cfg->sub_id) {
+ case MEF_CFG_DISABLE:
+ PRINTM(MINFO, "Disable MEF\n");
+ mefcmd->criteria = wlan_cpu_to_le32(0);
+ mefcmd->nentries = wlan_cpu_to_le16(0);
+ buf_len += sizeof(HostCmd_DS_MEF_CFG);
+ break;
+ case MEF_CFG_RX_FILTER_ENABLE:
+ PRINTM(MINFO, "Enable Rx filter\n");
+ mefcmd->criteria = wlan_cpu_to_le32((MBIT(3) | MBIT(0)));
+ mefcmd->nentries = wlan_cpu_to_le16(1);
+ buf_len += sizeof(HostCmd_DS_MEF_CFG);
+ filter = buf + buf_len;
+ memcpy_ext(pmpriv->adapter, filter, fltr_buf, sizeof(fltr_buf),
+ MRVDRV_SIZE_OF_CMD_BUFFER - buf_len);
+ buf_len += sizeof(fltr_buf);
+ break;
+ case MEF_CFG_AUTO_ARP_RESP:
+ PRINTM(MINFO, "Enable auto ARP response\n");
+ /* TODO */
+ break;
+ case MEF_CFG_HOSTCMD:
+ PRINTM(MINFO, "MEF hostcmd from MOAL\n");
+ filter = buf + buf_len;
+ memcpy_ext(pmpriv->adapter, filter, mef_cfg->param.cmd_buf.cmd,
+ mef_cfg->param.cmd_buf.len,
+ MRVDRV_SIZE_OF_CMD_BUFFER - buf_len);
+ buf_len += mef_cfg->param.cmd_buf.len;
+ break;
+ default:
+ PRINTM(MERROR, "Invalid sub ID parameter\n");
+ pioctl_req->status_code = MLAN_ERROR_INVALID_PARAMETER;
+ ret = MLAN_STATUS_FAILURE;
+ goto done;
+ break;
+ }
+ hostcmd_hdr->size = wlan_cpu_to_le16(buf_len);
+ hostcmd->len = buf_len;
+
+ /* Send command to firmware */
+ ret = wlan_prepare_cmd(pmpriv, 0, 0, 0, (t_void *)pioctl_req,
+ (t_void *)hostcmd);
+ if (ret == MLAN_STATUS_SUCCESS)
+ ret = MLAN_STATUS_PENDING;
+
+done:
+ if (hostcmd)
+ pcb->moal_mfree(pmadapter->pmoal_handle, (t_u8 *)hostcmd);
+
+ LEAVE();
+ return ret;
+}
+
+/**
+ * @brief ipaddr configuration
+ *
+ * @param pmadapter A pointer to mlan_adapter structure
+ * @param pioctl_req A pointer to ioctl request buffer
+ *
+ * @return MLAN_STATUS_PENDING --success, otherwise fail
+ */
+mlan_status wlan_misc_ioctl_ipaddr_cfg(pmlan_adapter pmadapter,
+ pmlan_ioctl_req pioctl_req)
+{
+ mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index];
+ mlan_ds_misc_cfg *misc = (mlan_ds_misc_cfg *)pioctl_req->pbuf;
+ mlan_status ret = MLAN_STATUS_SUCCESS;
+ t_u32 ipv4_addr[MAX_IPADDR] = {0};
+ int i = 0;
+
+ ENTER();
+
+ /* GET operation */
+ if (pioctl_req->action == MLAN_ACT_GET) {
+ memcpy_ext(pmadapter, misc->param.ipaddr_cfg.ip_addr,
+ pmpriv->ip_addr, IPADDR_LEN, IPADDR_LEN);
+ misc->param.ipaddr_cfg.op_code = pmpriv->op_code;
+ goto done;
+ }
+ /* only one IP is supported in current firmware */
+ for (i = 0; i < misc->param.ipaddr_cfg.ip_addr_num; i++) {
+ memcpy_ext(pmadapter, &ipv4_addr[i],
+ misc->param.ipaddr_cfg.ip_addr[i], sizeof(t_u32),
+ sizeof(t_u32));
+ }
+
+ if (misc->param.ipaddr_cfg.op_code != MLAN_IPADDR_OP_IP_REMOVE &&
+ !misc->param.ipaddr_cfg.ip_addr_num) {
+ PRINTM(MERROR, "Invalid IPv4 address\n");
+ pioctl_req->status_code = MLAN_ERROR_INVALID_PARAMETER;
+ ret = MLAN_STATUS_FAILURE;
+ goto done;
+ }
+
+ /* Save the values in MLAN */
+ if (pioctl_req->action == MLAN_ACT_SET) {
+ pmpriv->op_code = misc->param.ipaddr_cfg.op_code;
+ memcpy_ext(pmadapter, pmpriv->ip_addr,
+ misc->param.ipaddr_cfg.ip_addr, IPADDR_LEN,
+ IPADDR_LEN);
+ }
+
+done:
+ LEAVE();
+ return ret;
+}
+
+/**
+ * @brief CFP code configuration
+ *
+ * @param pmadapter A pointer to mlan_adapter structure
+ * @param pioctl_req A pointer to ioctl request buffer
+ *
+ * @return MLAN_STATUS_PENDING --success, otherwise fail
+ */
+mlan_status wlan_misc_ioctl_cfp_code_cfg(pmlan_adapter pmadapter,
+ pmlan_ioctl_req pioctl_req)
+{
+ mlan_status ret = MLAN_STATUS_SUCCESS;
+ mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index];
+ mlan_ds_misc_cfg *misc = (mlan_ds_misc_cfg *)pioctl_req->pbuf;
+ mlan_ds_misc_cfp_code *cfp_code = MNULL;
+ t_u32 region_bg = 0;
+ t_u32 region_a = 0;
+ int i;
+
+ ENTER();
+
+ cfp_code = &misc->param.cfp_code;
+ if (pioctl_req->action == MLAN_ACT_SET) {
+ if (pmadapter->otp_region && pmadapter->otp_region->force_reg) {
+ PRINTM(MERROR,
+ "ForceRegionRule is set in the on-chip OTP"
+ "memory\n");
+ ret = MLAN_STATUS_FAILURE;
+ goto done;
+ }
+ /* Save the values in MLAN */
+ if (!cfp_code->cfp_code_bg)
+ cfp_code->cfp_code_bg = pmadapter->cfp_code_bg;
+ for (i = 0; i < MRVDRV_MAX_REGION_CODE; i++) {
+ /* Use the region code to search for the index */
+ if (cfp_code->cfp_code_bg == region_code_index[i]) {
+ region_bg = cfp_code->cfp_code_bg;
+ break;
+ }
+ }
+ if (!cfp_code->cfp_code_a)
+ cfp_code->cfp_code_a = pmadapter->cfp_code_a;
+ for (i = 0; i < MRVDRV_MAX_REGION_CODE; i++) {
+ /* Use the region code to search for the index */
+ if (cfp_code->cfp_code_a == region_code_index[i]) {
+ region_a = cfp_code->cfp_code_a;
+ break;
+ }
+ }
+ if (!region_a) {
+ for (i = 0; i < MRVDRV_MAX_CFP_CODE_A; i++) {
+ /* Use the CFP code to search for the index */
+ if (cfp_code->cfp_code_a == cfp_code_index_a[i])
+ break;
+ }
+ if (i >= MRVDRV_MAX_CFP_CODE_A) {
+ PRINTM(MERROR,
+ "CFP Code not identified for A\n");
+ pioctl_req->status_code =
+ MLAN_ERROR_INVALID_PARAMETER;
+ ret = MLAN_STATUS_FAILURE;
+ goto done;
+ }
+ }
+ pmadapter->cfp_code_bg = (t_u8)cfp_code->cfp_code_bg;
+ pmadapter->cfp_code_a = (t_u8)cfp_code->cfp_code_a;
+ if (region_bg && region_a && (region_bg == region_a))
+ pmadapter->region_code = pmadapter->cfp_code_a;
+ else
+ pmadapter->region_code = 0;
+ if (wlan_set_regiontable(pmpriv, (t_u8)pmadapter->region_code,
+ pmadapter->config_bands |
+ pmadapter->adhoc_start_band)) {
+ pioctl_req->status_code = MLAN_ERROR_INVALID_PARAMETER;
+ ret = MLAN_STATUS_FAILURE;
+ goto done;
+ }
+ } else {
+ /* GET operation */
+ cfp_code->cfp_code_bg = pmadapter->cfp_code_bg;
+ cfp_code->cfp_code_a = pmadapter->cfp_code_a;
+ }
+
+done:
+ LEAVE();
+ return ret;
+}
+
+/**
+ * @brief This function sets up country code and downloads CMD to FW
+ *
+ * @param pmadapter A pointer to mlan_adapter structure
+ * @param pioctl_req Pointer to the IOCTL request buffer
+ *
+ * @return MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ */
+mlan_status wlan_misc_ioctl_country_code(pmlan_adapter pmadapter,
+ mlan_ioctl_req *pioctl_req)
+{
+ mlan_status ret = MLAN_STATUS_SUCCESS;
+ mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index];
+ mlan_ds_misc_country_code *country_code = MNULL;
+ mlan_ds_misc_cfg *cfg_misc = MNULL;
+ t_u8 cfp_bg = 0, cfp_a = 0;
+
+ ENTER();
+
+ cfg_misc = (mlan_ds_misc_cfg *)pioctl_req->pbuf;
+ country_code = &cfg_misc->param.country_code;
+
+ if (pioctl_req->action == MLAN_ACT_SET) {
+ if (pmadapter->otp_region && pmadapter->otp_region->force_reg) {
+ PRINTM(MERROR,
+ "ForceRegionRule is set in the on-chip OTP"
+ "memory\n");
+ ret = MLAN_STATUS_FAILURE;
+ goto done;
+ }
+ /* Update region code and table based on country code */
+ if (wlan_misc_country_2_cfp_table_code(
+ pmadapter, country_code->country_code, &cfp_bg,
+ &cfp_a)) {
+ PRINTM(MERROR, "Country code not found!\n");
+ pioctl_req->status_code = MLAN_ERROR_INVALID_PARAMETER;
+ ret = MLAN_STATUS_FAILURE;
+ goto done;
+ }
+ pmadapter->cfp_code_bg = cfp_bg;
+ pmadapter->cfp_code_a = cfp_a;
+ if (cfp_a)
+ pmadapter->region_code = cfp_a;
+ else if (cfp_bg)
+ pmadapter->region_code = cfp_bg;
+ else
+ pmadapter->region_code = 0;
+ if (wlan_set_regiontable(pmpriv, pmadapter->region_code,
+ pmadapter->config_bands |
+ pmadapter->adhoc_start_band)) {
+ pioctl_req->status_code = MLAN_ERROR_INVALID_PARAMETER;
+ ret = MLAN_STATUS_FAILURE;
+ goto done;
+ }
+ memcpy_ext(pmadapter, pmadapter->country_code,
+ country_code->country_code, COUNTRY_CODE_LEN,
+ COUNTRY_CODE_LEN);
+ } else {
+ /* GET operation */
+ memcpy_ext(pmadapter, country_code->country_code,
+ pmadapter->country_code, COUNTRY_CODE_LEN,
+ COUNTRY_CODE_LEN);
+ }
+
+done:
+ LEAVE();
+ return ret;
+}
+
+/**
+ * @brief Configure MFPC and MFPR for management frame protection
+ *
+ * @param pmadapter A pointer to mlan_adapter structure
+ * @param pioctl_req Pointer to the IOCTL request buffer
+ *
+ * @return MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ */
+mlan_status wlan_misc_pmfcfg(pmlan_adapter pmadapter,
+ mlan_ioctl_req *pioctl_req)
+{
+ pmlan_private pmpriv = pmadapter->priv[pioctl_req->bss_index];
+ mlan_status ret = MLAN_STATUS_SUCCESS;
+ mlan_ds_misc_cfg *cfg_misc = MNULL;
+ mlan_ds_misc_pmfcfg *pmfcfg;
+
+ cfg_misc = (mlan_ds_misc_cfg *)pioctl_req->pbuf;
+ pmfcfg = &cfg_misc->param.pmfcfg;
+
+ if (pioctl_req->action == MLAN_ACT_SET) {
+ pmpriv->pmfcfg.mfpc = pmfcfg->mfpc;
+ pmpriv->pmfcfg.mfpr = pmfcfg->mfpr;
+ } else {
+ /* GET operation */
+ pmfcfg->mfpc = pmpriv->pmfcfg.mfpc;
+ pmfcfg->mfpr = pmpriv->pmfcfg.mfpr;
+ }
+
+ LEAVE();
+ return ret;
+}
+
+/**
+ * @brief HW ARB Cfg
+ *
+ * @param pmadapter A pointer to mlan_adapter structure
+ * @param pioctl_req A pointer to ioctl request buffer
+ *
+ * @return MLAN_STATUS_PENDING --success, otherwise fail
+ */
+mlan_status wlan_misc_ioctl_arb_cfg(pmlan_adapter pmadapter,
+ pmlan_ioctl_req pioctl_req)
+{
+ mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index];
+ mlan_ds_misc_cfg *pmisc = (mlan_ds_misc_cfg *)pioctl_req->pbuf;
+ mlan_status ret = MLAN_STATUS_SUCCESS;
+ t_u16 cmd_action = 0;
+
+ ENTER();
+
+ if (pioctl_req->action == MLAN_ACT_SET)
+ cmd_action = HostCmd_ACT_GEN_SET;
+ else
+ cmd_action = HostCmd_ACT_GEN_GET;
+ ret = wlan_prepare_cmd(pmpriv, HostCmd_CMD_ARB_CONFIG, cmd_action, 0,
+ (t_void *)pioctl_req, &(pmisc->param.arb_cfg));
+ if (ret == MLAN_STATUS_SUCCESS)
+ ret = MLAN_STATUS_PENDING;
+
+ LEAVE();
+ return ret;
+}
+
+/**
+ * @brief Save tp accounting command configurations.
+ *
+ * @param pmadapter A pointer to mlan_adapter structure
+ * @param pioctl_req A pointer to ioctl request buffer
+ *
+ * @return MLAN_STATUS_PENDING --success, otherwise fail
+ */
+mlan_status wlan_misc_ioctl_tp_state(pmlan_adapter pmadapter,
+ pmlan_ioctl_req pioctl_req)
+{
+ mlan_ds_misc_cfg *pmisc = (mlan_ds_misc_cfg *)pioctl_req->pbuf;
+ mlan_status ret = MLAN_STATUS_SUCCESS;
+
+ ENTER();
+
+ pmadapter->tp_state_on = pmisc->param.tp_state.on;
+ pmadapter->tp_state_drop_point = pmisc->param.tp_state.drop_point;
+
+ LEAVE();
+ return ret;
+}
+
+mlan_status wlan_misc_ioctl_get_sensor_temp(pmlan_adapter pmadapter,
+ pmlan_ioctl_req pioctl_req)
+{
+ mlan_status ret = MLAN_STATUS_SUCCESS;
+ mlan_ds_misc_cfg *misc = MNULL;
+ t_u16 cmd_action = 0;
+ mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index];
+
+ ENTER();
+
+ misc = (mlan_ds_misc_cfg *)pioctl_req->pbuf;
+
+ if (pioctl_req->action == MLAN_ACT_GET)
+ cmd_action = HostCmd_ACT_GEN_GET;
+ else {
+ PRINTM(MERROR, " sensor temp only support get operation \n");
+ LEAVE();
+ return MLAN_STATUS_FAILURE;
+ }
+
+ /* Send request to firmware */
+ ret = wlan_prepare_cmd(pmpriv, HostCmd_DS_GET_SENSOR_TEMP, cmd_action,
+ 0, (t_void *)pioctl_req, MNULL);
+
+ if (ret == MLAN_STATUS_SUCCESS)
+ ret = MLAN_STATUS_PENDING;
+
+ LEAVE();
+ return ret;
+}
+
+/**
+ * @brief Gtk Rekey Offload
+ *
+ * @param pmadapter A pointer to mlan_adapter structure
+ * @param pioctl_req A pointer to ioctl request buffer
+ *
+ * @return MLAN_STATUS_SUCCESS --success, otherwise fail
+ */
+mlan_status wlan_misc_ioctl_gtk_rekey_offload(pmlan_adapter pmadapter,
+ pmlan_ioctl_req pioctl_req)
+{
+ mlan_status ret = MLAN_STATUS_SUCCESS;
+ mlan_ds_misc_cfg *misc_cfg = MNULL;
+ t_u16 cmd_action = 0;
+ mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index];
+
+ ENTER();
+ misc_cfg = (mlan_ds_misc_cfg *)pioctl_req->pbuf;
+ if (pioctl_req->action == MLAN_ACT_SET)
+ cmd_action = HostCmd_ACT_GEN_SET;
+ else if (pioctl_req->action == MLAN_ACT_CLEAR)
+ cmd_action = HostCmd_ACT_GEN_REMOVE;
+ else
+ cmd_action = HostCmd_ACT_GEN_GET;
+
+ if (!pmpriv->wpa_is_gtk_set) {
+ /* Store the gtk rekey data if it has already set gtk */
+ memcpy_ext(pmadapter, &pmpriv->gtk_rekey,
+ &misc_cfg->param.gtk_rekey,
+ sizeof(mlan_ds_misc_gtk_rekey_data),
+ sizeof(mlan_ds_misc_gtk_rekey_data));
+ LEAVE();
+ return ret;
+ }
+ /* Send request to firmware if it hasn't set gtk yet */
+ ret = wlan_prepare_cmd(pmpriv, HostCmd_CMD_GTK_REKEY_OFFLOAD_CFG,
+ cmd_action, 0, (t_void *)pioctl_req,
+ &misc_cfg->param.gtk_rekey);
+
+ if (ret == MLAN_STATUS_SUCCESS)
+ ret = MLAN_STATUS_PENDING;
+
+ LEAVE();
+ return ret;
+}
+
+/**
+ * @brief cloud keep alive
+ *
+ * @param pmadapter A pointer to mlan_adapter structure
+ * @param pioctl_req Pointer to the IOCTL request buffer
+ *
+ * @return MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ */
+mlan_status wlan_misc_cloud_keep_alive(pmlan_adapter pmadapter,
+ mlan_ioctl_req *pioctl_req)
+{
+ pmlan_private pmpriv = pmadapter->priv[pioctl_req->bss_index];
+ mlan_ds_misc_cfg *misc = MNULL;
+ t_u16 cmd_action = 0;
+ mlan_status ret = MLAN_STATUS_SUCCESS;
+
+ ENTER();
+
+ misc = (mlan_ds_misc_cfg *)pioctl_req->pbuf;
+
+ if (pioctl_req->action == MLAN_ACT_SET)
+ cmd_action = HostCmd_ACT_GEN_SET;
+ else if (pioctl_req->action == MLAN_ACT_GET) {
+ cmd_action = HostCmd_ACT_GEN_GET;
+ } else if (pioctl_req->action == MLAN_ACT_RESET) {
+ cmd_action = HostCmd_ACT_GEN_RESET;
+ } else {
+ cmd_action = HostCmd_ACT_GEN_REMOVE;
+ }
+
+ /* Send request to firmware */
+ ret = wlan_prepare_cmd(pmpriv, HostCmd_CMD_AUTO_TX, cmd_action,
+ OID_CLOUD_KEEP_ALIVE, (t_void *)pioctl_req,
+ &misc->param.keep_alive);
+
+ if (ret == MLAN_STATUS_SUCCESS)
+ ret = MLAN_STATUS_PENDING;
+
+ LEAVE();
+ return ret;
+}
+
+/**
+ * @brief Miscellaneous configuration handler
+ *
+ * @param pmadapter A pointer to mlan_adapter structure
+ * @param pioctl_req A pointer to ioctl request buffer
+ *
+ * @return MLAN_STATUS_SUCCESS/MLAN_STATUS_PENDING --success,
+ * otherwise fail
+ */
+static mlan_status wlan_misc_cfg_ioctl(pmlan_adapter pmadapter,
+ pmlan_ioctl_req pioctl_req)
+{
+ mlan_status status = MLAN_STATUS_SUCCESS;
+ mlan_ds_misc_cfg *misc = MNULL;
+
+ ENTER();
+
+ if ((pioctl_req == MNULL) || (pioctl_req->pbuf == MNULL)) {
+ PRINTM(MERROR, "Request buffer not found!\n");
+ LEAVE();
+ return MLAN_STATUS_FAILURE;
+ }
+ if (pioctl_req->buf_len < sizeof(mlan_ds_misc_cfg)) {
+ PRINTM(MWARN, "MLAN bss IOCTL length is too short.\n");
+ pioctl_req->data_read_written = 0;
+ pioctl_req->buf_len_needed = sizeof(mlan_ds_misc_cfg);
+ pioctl_req->status_code = MLAN_ERROR_INVALID_PARAMETER;
+ LEAVE();
+ return MLAN_STATUS_RESOURCE;
+ }
+ misc = (mlan_ds_misc_cfg *)pioctl_req->pbuf;
+ switch (misc->sub_command) {
+ case MLAN_OID_MISC_GEN_IE:
+ status = wlan_misc_ioctl_gen_ie(pmadapter, pioctl_req);
+ break;
+ case MLAN_OID_MISC_REGION:
+ status = wlan_misc_ioctl_region(pmadapter, pioctl_req);
+ break;
+ case MLAN_OID_MISC_WARM_RESET:
+ util_enqueue_list_tail(pmadapter->pmoal_handle,
+ &pmadapter->ioctl_pending_q,
+ (pmlan_linked_list)pioctl_req,
+ pmadapter->callbacks.moal_spin_lock,
+ pmadapter->callbacks.moal_spin_unlock);
+ pmadapter->pending_ioctl = MTRUE;
+ status = MLAN_STATUS_PENDING;
+ break;
+#ifdef SDIO
+ case MLAN_OID_MISC_SDIO_MPA_CTRL:
+ status = wlan_misc_ioctl_sdio_mpa_ctrl(pmadapter, pioctl_req);
+ break;
+#endif
+ case MLAN_OID_MISC_HOST_CMD:
+ status = wlan_misc_ioctl_host_cmd(pmadapter, pioctl_req);
+ break;
+ case MLAN_OID_MISC_SYS_CLOCK:
+ status = wlan_misc_ioctl_sysclock(pmadapter, pioctl_req);
+ break;
+ case MLAN_OID_MISC_WWS:
+ status = wlan_misc_ioctl_wws_cfg(pmadapter, pioctl_req);
+ break;
+ case MLAN_OID_MISC_ASSOC_RSP:
+ status = wlan_misc_ioctl_get_assoc_rsp(pmadapter, pioctl_req);
+ break;
+ case MLAN_OID_MISC_INIT_SHUTDOWN:
+ status = wlan_misc_ioctl_init_shutdown(pmadapter, pioctl_req);
+ break;
+ case MLAN_OID_MISC_SOFT_RESET:
+ status = wlan_misc_ioctl_soft_reset(pmadapter, pioctl_req);
+ break;
+ case MLAN_OID_MISC_CUSTOM_IE:
+ status = wlan_misc_ioctl_custom_ie_list(pmadapter, pioctl_req,
+ MTRUE);
+ break;
+
+ case MLAN_OID_MISC_MAC_CONTROL:
+ status = wlan_misc_ioctl_mac_control(pmadapter, pioctl_req);
+ break;
+ case MLAN_OID_MISC_MEF_CFG:
+ status = wlan_misc_ioctl_mef_cfg(pmadapter, pioctl_req);
+ break;
+ case MLAN_OID_MISC_RX_MGMT_IND:
+ status = wlan_reg_rx_mgmt_ind(pmadapter, pioctl_req);
+ break;
+#ifdef DEBUG_LEVEL1
+ case MLAN_OID_MISC_DRVDBG:
+ status = wlan_set_drvdbg(pmadapter, pioctl_req);
+ break;
+#endif
+ case MLAN_OID_MISC_IP_ADDR:
+ status = wlan_misc_ioctl_ipaddr_cfg(pmadapter, pioctl_req);
+ break;
+ case MLAN_OID_MISC_CFP_CODE:
+ status = wlan_misc_ioctl_cfp_code_cfg(pmadapter, pioctl_req);
+ break;
+ case MLAN_OID_MISC_COUNTRY_CODE:
+ status = wlan_misc_ioctl_country_code(pmadapter, pioctl_req);
+ break;
+ case MLAN_OID_MISC_THERMAL:
+ status = wlan_misc_ioctl_thermal(pmadapter, pioctl_req);
+ break;
+ case MLAN_OID_MISC_SUBSCRIBE_EVENT:
+ status = wlan_misc_ioctl_subscribe_evt(pmadapter, pioctl_req);
+ break;
+ case MLAN_OID_MISC_HOTSPOT_CFG:
+ status = wlan_misc_hotspot_cfg(pmadapter, pioctl_req);
+ break;
+ case MLAN_OID_MISC_OTP_USER_DATA:
+ status = wlan_misc_otp_user_data(pmadapter, pioctl_req);
+ break;
+#ifdef USB
+ case MLAN_OID_MISC_USB_AGGR_CTRL:
+ status = wlan_misc_ioctl_usb_aggr_ctrl(pmadapter, pioctl_req);
+ break;
+#endif
+ case MLAN_OID_MISC_AGGR_CTRL:
+ status = wlan_misc_ioctl_aggr_ctrl(pmadapter, pioctl_req);
+ break;
+ case MLAN_OID_MISC_TXCONTROL:
+ status = wlan_misc_ioctl_txcontrol(pmadapter, pioctl_req);
+ break;
+#ifdef STA_SUPPORT
+ case MLAN_OID_MISC_EXT_CAP_CFG:
+ status = wlan_misc_ext_capa_cfg(pmadapter, pioctl_req);
+ break;
+#endif
+ case MLAN_OID_MISC_PMFCFG:
+ status = wlan_misc_pmfcfg(pmadapter, pioctl_req);
+ break;
+#ifdef RX_PACKET_COALESCE
+ case MLAN_OID_MISC_RX_PACKET_COALESCE:
+ status = wlan_misc_ioctl_rx_pkt_coalesce_config(pmadapter,
+ pioctl_req);
+ break;
+#endif
+ case MLAN_OID_MISC_LOW_PWR_MODE:
+ status = wlan_misc_ioctl_low_pwr_mode(pmadapter, pioctl_req);
+ break;
+ case MLAN_OID_MISC_PMIC_CFG:
+ status = wlan_misc_ioctl_pmic_configure(pmadapter, pioctl_req);
+ break;
+ case MLAN_OID_MISC_CWMODE_CTRL:
+ status = wlan_misc_ioctl_cwmode_ctrl(pmadapter, pioctl_req);
+ break;
+ case MLAN_OID_MISC_MEF_FLT_CFG:
+ status = wlan_misc_ioctl_mef_flt_cfg(pmadapter, pioctl_req);
+ break;
+ case MLAN_OID_MISC_DFS_REAPTER_MODE:
+ status =
+ wlan_misc_ioctl_dfs_repeater_cfg(pmadapter, pioctl_req);
+ break;
+ case MLAN_OID_MISC_COALESCE_CFG:
+ status = wlan_misc_ioctl_coalesce_cfg(pmadapter, pioctl_req);
+ break;
+ case MLAN_OID_MISC_GET_SENSOR_TEMP:
+ status = wlan_misc_ioctl_get_sensor_temp(pmadapter, pioctl_req);
+ break;
+ case MLAN_OID_MISC_OPER_CLASS:
+ status = wlan_misc_ioctl_oper_class(pmadapter, pioctl_req);
+ break;
+ case MLAN_OID_MISC_OPER_CLASS_CHECK:
+ status = wlan_misc_ioctl_operclass_validation(pmadapter,
+ pioctl_req);
+ break;
+ case MLAN_OID_MISC_GTK_REKEY_OFFLOAD:
+ status = wlan_misc_ioctl_gtk_rekey_offload(pmadapter,
+ pioctl_req);
+ break;
+ case MLAN_OID_MISC_IND_RST_CFG:
+ status = wlan_misc_ioctl_ind_rst_cfg(pmadapter, pioctl_req);
+ break;
+ case MLAN_OID_MISC_GET_TSF:
+ status = wlan_misc_ioctl_get_tsf(pmadapter, pioctl_req);
+ break;
+ case MLAN_OID_MISC_GET_CHAN_REGION_CFG:
+ status = wlan_misc_chan_reg_cfg(pmadapter, pioctl_req);
+ break;
+ case MLAN_OID_MISC_CLOUD_KEEP_ALIVE:
+ status = wlan_misc_cloud_keep_alive(pmadapter, pioctl_req);
+ break;
+ case MLAN_OID_MISC_DYN_BW:
+ status = wlan_misc_ioctl_dyn_bw(pmadapter, pioctl_req);
+ break;
+ case MLAN_OID_MISC_FW_DUMP_EVENT:
+ status = wlan_misc_ioctl_fw_dump_event(pmadapter, pioctl_req);
+ break;
+ case MLAN_OID_MISC_PER_PKT_CFG:
+ status = wlan_misc_per_pkt_cfg(pmadapter, pioctl_req);
+ break;
+ case MLAN_OID_MISC_ROBUSTCOEX:
+ status = wlan_misc_robustcoex(pmadapter, pioctl_req);
+ break;
+ case MLAN_OID_MISC_DMCS_CONFIG:
+ status = wlan_misc_dmcs_config(pmadapter, pioctl_req);
+ break;
+ case MLAN_OID_MISC_GET_TX_RX_HISTOGRAM:
+ status = wlan_get_tx_rx_histogram(pmadapter, pioctl_req);
+ break;
+ case MLAN_OID_MISC_BOOT_SLEEP:
+ status = wlan_misc_bootsleep(pmadapter, pioctl_req);
+ break;
+ case MLAN_OID_MISC_CFP_INFO:
+ status = wlan_get_cfpinfo(pmadapter, pioctl_req);
+ break;
+#if defined(PCIE)
+ case MLAN_OID_MISC_SSU:
+ if (pmadapter->ssu_buf)
+ status = MLAN_STATUS_FAILURE;
+ else
+ status = wlan_misc_ssu(pmadapter, pioctl_req);
+ break;
+#endif
+ case MLAN_OID_MISC_RX_ABORT_CFG:
+ status = wlan_misc_ioctl_rxabortcfg(pmadapter, pioctl_req);
+ break;
+ case MLAN_OID_MISC_RX_ABORT_CFG_EXT:
+ status = wlan_misc_ioctl_rxabortcfg_ext(pmadapter, pioctl_req);
+ break;
+ case MLAN_OID_MISC_TX_AMPDU_PROT_MODE:
+ status = wlan_misc_ioctl_tx_ampdu_prot_mode(pmadapter,
+ pioctl_req);
+ break;
+ case MLAN_OID_MISC_DOT11MC_UNASSOC_FTM_CFG:
+ status = wlan_misc_ioctl_dot11mc_unassoc_ftm_cfg(pmadapter,
+ pioctl_req);
+ break;
+ case MLAN_OID_MISC_RATE_ADAPT_CFG:
+ status = wlan_misc_ioctl_rate_adapt_cfg(pmadapter, pioctl_req);
+ break;
+ case MLAN_OID_MISC_CCK_DESENSE_CFG:
+ status = wlan_misc_ioctl_cck_desense_cfg(pmadapter, pioctl_req);
+ break;
+ case MLAN_OID_MISC_GET_REGIONPWR_CFG:
+ status = wlan_get_rgchnpwr_cfg(pmadapter, pioctl_req);
+ break;
+ case MLAN_OID_MISC_GET_CHAN_TRPC_CFG:
+ status = wlan_get_chan_trpc_cfg(pmadapter, pioctl_req);
+ break;
+ case MLAN_OID_MISC_RF_TEST_GENERIC:
+ case MLAN_OID_MISC_RF_TEST_TX_CONT:
+ case MLAN_OID_MISC_RF_TEST_TX_FRAME:
+ status = wlan_misc_ioctl_rf_test_cfg(pmadapter, pioctl_req);
+ break;
+ case MLAN_OID_MISC_ARB_CONFIG:
+ status = wlan_misc_ioctl_arb_cfg(pmadapter, pioctl_req);
+ break;
+ case MLAN_OID_MISC_RANGE_EXT:
+ status = wlan_misc_ioctl_range_ext(pmadapter, pioctl_req);
+ break;
+ case MLAN_OID_MISC_TP_STATE:
+ status = wlan_misc_ioctl_tp_state(pmadapter, pioctl_req);
+ break;
+ default:
+ if (pioctl_req)
+ pioctl_req->status_code = MLAN_ERROR_IOCTL_INVALID;
+ status = MLAN_STATUS_FAILURE;
+ break;
+ }
+ LEAVE();
+ return status;
+}
+
+/**
+ * @brief Set/Get scan configuration parameter
+ *
+ * @param pmadapter A pointer to mlan_adapter structure
+ * @param pioctl_req A pointer to ioctl request buffer
+ * @param action Set/Get
+ *
+ * @return MLAN_STATUS_SUCCESS --success
+ */
+static mlan_status wlan_set_get_scan_cfg(pmlan_adapter pmadapter,
+ pmlan_ioctl_req pioctl_req,
+ t_u32 action)
+{
+ mlan_ds_scan *scan = MNULL;
+
+ ENTER();
+
+ scan = (mlan_ds_scan *)pioctl_req->pbuf;
+ if (action == MLAN_ACT_SET) {
+ if (scan->param.scan_cfg.scan_type)
+ pmadapter->scan_type =
+ (t_u8)scan->param.scan_cfg.scan_type;
+ if (scan->param.scan_cfg.scan_mode)
+ pmadapter->scan_mode = scan->param.scan_cfg.scan_mode;
+ if (scan->param.scan_cfg.scan_probe)
+ pmadapter->scan_probes =
+ (t_u16)scan->param.scan_cfg.scan_probe;
+ if (scan->param.scan_cfg.scan_time.specific_scan_time)
+ pmadapter->specific_scan_time =
+ (t_u16)scan->param.scan_cfg.scan_time
+ .specific_scan_time;
+ if (scan->param.scan_cfg.scan_time.active_scan_time)
+ pmadapter->active_scan_time =
+ (t_u16)scan->param.scan_cfg.scan_time
+ .active_scan_time;
+ if (scan->param.scan_cfg.scan_time.passive_scan_time)
+ pmadapter->passive_scan_time =
+ (t_u16)scan->param.scan_cfg.scan_time
+ .passive_scan_time;
+ if (scan->param.scan_cfg.passive_to_active_scan)
+ pmadapter->passive_to_active_scan =
+ scan->param.scan_cfg.passive_to_active_scan;
+ if (scan->param.scan_cfg.ext_scan)
+ pmadapter->ext_scan = scan->param.scan_cfg.ext_scan - 1;
+ pmadapter->scan_chan_gap = scan->param.scan_cfg.scan_chan_gap;
+ }
+ scan->param.scan_cfg.scan_type = (t_u32)pmadapter->scan_type;
+ scan->param.scan_cfg.scan_mode = pmadapter->scan_mode;
+ scan->param.scan_cfg.scan_probe = (t_u32)pmadapter->scan_probes;
+ scan->param.scan_cfg.scan_time.specific_scan_time =
+ (t_u32)pmadapter->specific_scan_time;
+ scan->param.scan_cfg.scan_time.active_scan_time =
+ (t_u32)pmadapter->active_scan_time;
+ scan->param.scan_cfg.scan_time.passive_scan_time =
+ (t_u32)pmadapter->passive_scan_time;
+ scan->param.scan_cfg.passive_to_active_scan =
+ pmadapter->passive_to_active_scan;
+ scan->param.scan_cfg.ext_scan = pmadapter->ext_scan + 1;
+ scan->param.scan_cfg.scan_chan_gap = pmadapter->scan_chan_gap;
+ pioctl_req->data_read_written = sizeof(t_u32) + MLAN_SUB_COMMAND_SIZE;
+
+ LEAVE();
+ return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ * @brief Set/Get scan
+ *
+ * @param pmadapter A pointer to mlan_adapter structure
+ * @param pioctl_req A pointer to ioctl request buffer
+ *
+ * @return MLAN_STATUS_SUCCESS/MLAN_STATUS_PENDING --success,
+ * otherwise fail
+ */
+static mlan_status wlan_scan_ioctl(pmlan_adapter pmadapter,
+ pmlan_ioctl_req pioctl_req)
+{
+ pmlan_private pmpriv = pmadapter->priv[pioctl_req->bss_index];
+ mlan_status status = MLAN_STATUS_SUCCESS;
+ mlan_ds_scan *pscan;
+
+ ENTER();
+
+ pscan = (mlan_ds_scan *)pioctl_req->pbuf;
+ if (pscan->sub_command == MLAN_OID_SCAN_CONFIG ||
+ pscan->sub_command == MLAN_OID_SCAN_BGSCAN_CONFIG)
+ goto start_config;
+ if (pmadapter->scan_processing && pioctl_req->action == MLAN_ACT_SET &&
+ pscan->sub_command != MLAN_OID_SCAN_CANCEL) {
+ PRINTM(MINFO, "Scan already in process...\n");
+ LEAVE();
+ return status;
+ }
+
+ if (pmadapter->scan_block && pioctl_req->action == MLAN_ACT_SET) {
+ PRINTM(MERROR, "Scan is blocked during association...\n");
+ LEAVE();
+ return MLAN_STATUS_FAILURE;
+ }
+start_config:
+ /* Set scan */
+ if (pioctl_req->action == MLAN_ACT_SET) {
+ switch (pscan->sub_command) {
+ case MLAN_OID_SCAN_NORMAL:
+ status = wlan_scan_networks(pmpriv, pioctl_req, MNULL);
+ break;
+ case MLAN_OID_SCAN_SPECIFIC_SSID:
+ status = wlan_scan_specific_ssid(
+ pmpriv, pioctl_req,
+ &pscan->param.scan_req.scan_ssid);
+ break;
+ case MLAN_OID_SCAN_USER_CONFIG:
+ status = wlan_scan_networks(
+ pmpriv, pioctl_req,
+ (wlan_user_scan_cfg *)
+ pscan->param.user_scan.scan_cfg_buf);
+ break;
+ case MLAN_OID_SCAN_CONFIG:
+ status = wlan_set_get_scan_cfg(pmadapter, pioctl_req,
+ MLAN_ACT_SET);
+ break;
+ case MLAN_OID_SCAN_CANCEL:
+ status = wlan_cancel_pending_scan_cmd(pmadapter,
+ pioctl_req);
+ break;
+ case MLAN_OID_SCAN_TABLE_FLUSH:
+ status = wlan_flush_scan_table(pmadapter);
+ break;
+ case MLAN_OID_SCAN_BGSCAN_CONFIG:
+ /* Send request to firmware */
+ status = wlan_prepare_cmd(
+ pmpriv, HostCmd_CMD_802_11_BG_SCAN_CONFIG,
+ HostCmd_ACT_GEN_SET, 0, (t_void *)pioctl_req,
+ pscan->param.user_scan.scan_cfg_buf);
+ break;
+ default:
+ pioctl_req->status_code = MLAN_ERROR_IOCTL_INVALID;
+ status = MLAN_STATUS_FAILURE;
+ break;
+ }
+
+ if ((status == MLAN_STATUS_SUCCESS) &&
+ (pscan->sub_command != MLAN_OID_SCAN_TABLE_FLUSH) &&
+ (pscan->sub_command != MLAN_OID_SCAN_CANCEL) &&
+ (pscan->sub_command != MLAN_OID_SCAN_CONFIG)) {
+ PRINTM(MINFO,
+ "wlan_scan_ioctl: return MLAN_STATUS_PENDING\n");
+ status = MLAN_STATUS_PENDING;
+ }
+ }
+ /* Get scan */
+ else {
+ if (pscan->sub_command == MLAN_OID_SCAN_CONFIG) {
+ status = wlan_set_get_scan_cfg(pmadapter, pioctl_req,
+ MLAN_ACT_GET);
+ } else if (pscan->sub_command ==
+ MLAN_OID_SCAN_GET_CURRENT_BSS) {
+ pscan->param.scan_resp.num_in_scan_table =
+ pmadapter->num_in_scan_table;
+ pscan->param.scan_resp.pscan_table =
+ (t_u8 *)&pmpriv->curr_bss_params.bss_descriptor;
+ pioctl_req->data_read_written =
+ sizeof(mlan_scan_resp) + MLAN_SUB_COMMAND_SIZE;
+ } else {
+ if (pmadapter->bgscan_reported) {
+ pmadapter->bgscan_reported = MFALSE;
+ /* Clear the previous scan result */
+ memset(pmadapter, pmadapter->pscan_table, 0x00,
+ sizeof(BSSDescriptor_t) *
+ MRVDRV_MAX_BSSID_LIST);
+ pmadapter->num_in_scan_table = 0;
+ pmadapter->pbcn_buf_end = pmadapter->bcn_buf;
+ status = wlan_prepare_cmd(
+ pmpriv,
+ HostCmd_CMD_802_11_BG_SCAN_QUERY,
+ HostCmd_ACT_GEN_GET, 0,
+ (t_void *)pioctl_req, MNULL);
+ if (status == MLAN_STATUS_SUCCESS) {
+ PRINTM(MINFO,
+ "wlan_scan_ioctl: return MLAN_STATUS_PENDING\n");
+ status = MLAN_STATUS_PENDING;
+ }
+ } else {
+ pscan->param.scan_resp.pscan_table =
+ (t_u8 *)pmadapter->pscan_table;
+ pscan->param.scan_resp.num_in_scan_table =
+ pmadapter->num_in_scan_table;
+ pscan->param.scan_resp.age_in_secs =
+ pmadapter->age_in_secs;
+ pioctl_req->data_read_written =
+ sizeof(mlan_scan_resp) +
+ MLAN_SUB_COMMAND_SIZE;
+ pscan->param.scan_resp.pchan_stats =
+ (t_u8 *)pmadapter->pchan_stats;
+ pscan->param.scan_resp.num_in_chan_stats =
+ pmadapter->num_in_chan_stats;
+ }
+ }
+ }
+
+ LEAVE();
+ return status;
+}
+
+/********************************************************
+ Global Functions
+********************************************************/
+
+/**
+ * @brief Set ewpa mode
+ *
+ * @param priv A pointer to mlan_private structure
+ * @param psec_pp A pointer to mlan_ds_passphrase structure
+ *
+ * @return MLAN_STATUS_SUCCESS
+ */
+mlan_status wlan_set_ewpa_mode(mlan_private *priv, mlan_ds_passphrase *psec_pp)
+{
+ ENTER();
+
+ if ((psec_pp->psk_type == MLAN_PSK_PASSPHRASE &&
+ psec_pp->psk.passphrase.passphrase_len > 0) ||
+ (psec_pp->psk_type == MLAN_PSK_PMK))
+ priv->sec_info.ewpa_enabled = MTRUE;
+ else
+ priv->sec_info.ewpa_enabled = MFALSE;
+
+ PRINTM(MINFO, "Set ewpa mode = %d\n", priv->sec_info.ewpa_enabled);
+
+ LEAVE();
+ return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ * @brief Search for a BSS
+ *
+ * @param pmpriv A pointer to mlan_private structure
+ * @param pioctl_req A pointer to ioctl request buffer
+ *
+ * @return MLAN_STATUS_SUCCESS --success, otherwise
+ * fail
+ */
+mlan_status wlan_find_bss(mlan_private *pmpriv, pmlan_ioctl_req pioctl_req)
+{
+ mlan_adapter *pmadapter = pmpriv->adapter;
+ mlan_ds_bss *bss = MNULL;
+ mlan_status ret = MLAN_STATUS_SUCCESS;
+ t_u8 zero_mac[] = {0, 0, 0, 0, 0, 0};
+ t_u8 mac[MLAN_MAC_ADDR_LENGTH];
+ int i = 0;
+ BSSDescriptor_t *pbss_desc = MNULL;
+
+ ENTER();
+
+ bss = (mlan_ds_bss *)pioctl_req->pbuf;
+
+ if (memcmp(pmadapter, &bss->param.ssid_bssid.bssid, zero_mac,
+ sizeof(zero_mac))) {
+ if (bss->param.ssid_bssid.ssid.ssid_len) /* ssid & bssid */
+ i = wlan_find_ssid_in_list(
+ pmpriv, &bss->param.ssid_bssid.ssid,
+ (t_u8 *)&bss->param.ssid_bssid.bssid,
+ pmpriv->bss_mode);
+ else
+ i = wlan_find_bssid_in_list(
+ pmpriv, (t_u8 *)&bss->param.ssid_bssid.bssid,
+ pmpriv->bss_mode);
+ if (i < 0) {
+ memcpy_ext(pmadapter, mac, &bss->param.ssid_bssid.bssid,
+ sizeof(mac), MLAN_MAC_ADDR_LENGTH);
+ PRINTM(MIOCTL, "Can not find bssid " MACSTR "\n",
+ MAC2STR(mac));
+ pioctl_req->status_code = MLAN_ERROR_INVALID_PARAMETER;
+ LEAVE();
+ return MLAN_STATUS_FAILURE;
+ }
+ pbss_desc = &pmadapter->pscan_table[i];
+ memcpy_ext(pmadapter, &bss->param.ssid_bssid.ssid,
+ &pbss_desc->ssid, sizeof(mlan_802_11_ssid),
+ sizeof(mlan_802_11_ssid));
+ bss->param.ssid_bssid.rssi = pbss_desc->rssi;
+ bss->param.ssid_bssid.channel = (t_u16)pbss_desc->channel;
+
+ bss->param.ssid_bssid.bss_band = pbss_desc->bss_band;
+ /* index in bss list,start from 1 */
+ bss->param.ssid_bssid.idx = i + 1;
+ } else if (bss->param.ssid_bssid.ssid.ssid_len) {
+ i = wlan_find_ssid_in_list(pmpriv, &bss->param.ssid_bssid.ssid,
+ MNULL, pmpriv->bss_mode);
+ if (i < 0) {
+ PRINTM(MIOCTL, "Can not find ssid %s\n",
+ bss->param.ssid_bssid.ssid.ssid);
+ pioctl_req->status_code = MLAN_ERROR_INVALID_PARAMETER;
+ LEAVE();
+ return MLAN_STATUS_FAILURE;
+ }
+ pbss_desc = &pmadapter->pscan_table[i];
+ memcpy_ext(pmadapter, (t_u8 *)&bss->param.ssid_bssid.bssid,
+ (t_u8 *)&pbss_desc->mac_address,
+ MLAN_MAC_ADDR_LENGTH, MLAN_MAC_ADDR_LENGTH);
+ bss->param.ssid_bssid.rssi = pbss_desc->rssi;
+ bss->param.ssid_bssid.channel = (t_u16)pbss_desc->channel;
+
+ bss->param.ssid_bssid.bss_band = pbss_desc->bss_band;
+ /* index in bss list, start from 1 */
+ bss->param.ssid_bssid.idx = i + 1;
+ } else {
+ ret = wlan_find_best_network(pmpriv, &bss->param.ssid_bssid);
+ }
+
+ if (pbss_desc) {
+ /**if rsn do not have ft akm, don't set ft cap and ft md*/
+ if (pbss_desc->pmd_ie &&
+ wlan_ft_akm_is_used(pmpriv, (t_u8 *)pbss_desc->prsn_ie)) {
+ bss->param.ssid_bssid.ft_md = pbss_desc->pmd_ie->mdid;
+ bss->param.ssid_bssid.ft_cap =
+ pbss_desc->pmd_ie->ft_cap;
+ }
+ }
+
+ LEAVE();
+ return ret;
+}
+
+/**
+ * @brief MLAN station ioctl handler
+ *
+ * @param adapter A pointer to mlan_adapter structure
+ * @param pioctl_req A pointer to ioctl request buffer
+ *
+ * @return MLAN_STATUS_SUCCESS/MLAN_STATUS_PENDING --success,
+ * otherwise fail
+ */
+mlan_status wlan_ops_sta_ioctl(t_void *adapter, pmlan_ioctl_req pioctl_req)
+{
+ pmlan_adapter pmadapter = (pmlan_adapter)adapter;
+ mlan_status status = MLAN_STATUS_SUCCESS;
+
+ ENTER();
+
+ switch (pioctl_req->req_id) {
+ case MLAN_IOCTL_SCAN:
+ status = wlan_scan_ioctl(pmadapter, pioctl_req);
+ break;
+ case MLAN_IOCTL_BSS:
+ status = wlan_bss_ioctl(pmadapter, pioctl_req);
+ break;
+ case MLAN_IOCTL_RADIO_CFG:
+ status = wlan_radio_ioctl(pmadapter, pioctl_req);
+ break;
+ case MLAN_IOCTL_SNMP_MIB:
+ status = wlan_snmp_mib_ioctl(pmadapter, pioctl_req);
+ break;
+ case MLAN_IOCTL_GET_INFO:
+ status = wlan_get_info_ioctl(pmadapter, pioctl_req);
+ break;
+ case MLAN_IOCTL_SEC_CFG:
+ status = wlan_sec_cfg_ioctl(pmadapter, pioctl_req);
+ break;
+ case MLAN_IOCTL_RATE:
+ status = wlan_rate_ioctl(pmadapter, pioctl_req);
+ break;
+ case MLAN_IOCTL_POWER_CFG:
+ status = wlan_power_ioctl(pmadapter, pioctl_req);
+ break;
+ case MLAN_IOCTL_PM_CFG:
+ status = wlan_pm_ioctl(pmadapter, pioctl_req);
+ break;
+ case MLAN_IOCTL_WMM_CFG:
+ status = wlan_wmm_cfg_ioctl(pmadapter, pioctl_req);
+ break;
+ case MLAN_IOCTL_WPS_CFG:
+ status = wlan_wps_cfg_ioctl(pmadapter, pioctl_req);
+ break;
+ case MLAN_IOCTL_11N_CFG:
+ status = wlan_11n_cfg_ioctl(pmadapter, pioctl_req);
+ break;
+ case MLAN_IOCTL_11D_CFG:
+ status = wlan_11d_cfg_ioctl(pmadapter, pioctl_req);
+ break;
+ case MLAN_IOCTL_REG_MEM:
+ status = wlan_reg_mem_ioctl(pmadapter, pioctl_req);
+ break;
+ case MLAN_IOCTL_MISC_CFG:
+ status = wlan_misc_cfg_ioctl(pmadapter, pioctl_req);
+ break;
+ case MLAN_IOCTL_11H_CFG:
+ status = wlan_11h_cfg_ioctl(pmadapter, pioctl_req);
+ break;
+ case MLAN_IOCTL_11AC_CFG:
+ status = wlan_11ac_cfg_ioctl(pmadapter, pioctl_req);
+ break;
+ case MLAN_IOCTL_11AX_CFG:
+ status = wlan_11ax_cfg_ioctl(pmadapter, pioctl_req);
+ break;
+ default:
+ pioctl_req->status_code = MLAN_ERROR_IOCTL_INVALID;
+ status = MLAN_STATUS_FAILURE;
+ break;
+ }
+ LEAVE();
+ return status;
+}
diff --git a/drivers/net/wireless/nxp/mxm_wifiex/wlan_src/mlan/mlan_sta_rx.c b/drivers/net/wireless/nxp/mxm_wifiex/wlan_src/mlan/mlan_sta_rx.c
new file mode 100644
index 000000000000..af9a143e9adf
--- /dev/null
+++ b/drivers/net/wireless/nxp/mxm_wifiex/wlan_src/mlan/mlan_sta_rx.c
@@ -0,0 +1,488 @@
+/** @file mlan_sta_rx.c
+ *
+ * @brief This file contains the handling of RX in MLAN
+ * module.
+ *
+ *
+ * Copyright 2014-2020 NXP
+ *
+ * This software file (the File) is distributed by NXP
+ * under the terms of the GNU General Public License Version 2, June 1991
+ * (the License). You may use, redistribute and/or modify the 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.
+ *
+ */
+
+/********************************************************
+Change log:
+ 10/27/2008: initial version
+********************************************************/
+
+#include "mlan.h"
+#include "mlan_join.h"
+#include "mlan_util.h"
+#include "mlan_fw.h"
+#include "mlan_main.h"
+#include "mlan_11n_aggr.h"
+#include "mlan_11n_rxreorder.h"
+#ifdef DRV_EMBEDDED_SUPPLICANT
+#include "authenticator_api.h"
+#endif
+
+/********************************************************
+ Local Variables
+********************************************************/
+
+/** Ethernet II header */
+typedef struct {
+ /** Ethernet II header destination address */
+ t_u8 dest_addr[MLAN_MAC_ADDR_LENGTH];
+ /** Ethernet II header source address */
+ t_u8 src_addr[MLAN_MAC_ADDR_LENGTH];
+ /** Ethernet II header length */
+ t_u16 ethertype;
+
+} EthII_Hdr_t;
+
+/** IPv4 ARP request header */
+typedef MLAN_PACK_START struct {
+ /** Hardware type */
+ t_u16 Htype;
+ /** Protocol type */
+ t_u16 Ptype;
+ /** Hardware address length */
+ t_u8 addr_len;
+ /** Protocol address length */
+ t_u8 proto_len;
+ /** Operation code */
+ t_u16 op_code;
+ /** Source mac address */
+ t_u8 src_mac[MLAN_MAC_ADDR_LENGTH];
+ /** Sender IP address */
+ t_u8 src_ip[4];
+ /** Destination mac address */
+ t_u8 dst_mac[MLAN_MAC_ADDR_LENGTH];
+ /** Destination IP address */
+ t_u8 dst_ip[4];
+} MLAN_PACK_END IPv4_ARP_t;
+
+/** IPv6 Nadv packet header */
+typedef MLAN_PACK_START struct {
+ /** IP protocol version */
+ t_u8 version;
+ /** flow label */
+ t_u8 flow_lab[3];
+ /** Payload length */
+ t_u16 payload_len;
+ /** Next header type */
+ t_u8 next_hdr;
+ /** Hot limit */
+ t_u8 hop_limit;
+ /** Source address */
+ t_u8 src_addr[16];
+ /** Destination address */
+ t_u8 dst_addr[16];
+ /** ICMP type */
+ t_u8 icmp_type;
+ /** IPv6 Code */
+ t_u8 ipv6_code;
+ /** IPv6 Checksum */
+ t_u16 ipv6_checksum;
+ /** Flags */
+ t_u32 flags;
+ /** Target address */
+ t_u8 taget_addr[16];
+ /** Reserved */
+ t_u8 rev[8];
+} MLAN_PACK_END IPv6_Nadv_t;
+
+/********************************************************
+ Global functions
+********************************************************/
+/**
+ * @brief This function check and discard IPv4 and IPv6 gratuitous broadcast
+ * packets
+ *
+ * @param prx_pkt A pointer to RxPacketHdr_t structure of received packet
+ * @param pmadapter A pointer to pmlan_adapter structure
+ * @return TRUE if found such type of packets, FALSE not found
+ */
+static t_u8 discard_gratuitous_ARP_msg(RxPacketHdr_t *prx_pkt,
+ pmlan_adapter pmadapter)
+{
+ t_u8 proto_ARP_type[] = {0x08, 0x06};
+ t_u8 proto_ARP_type_v6[] = {0x86, 0xDD};
+ IPv4_ARP_t *parp_hdr;
+ IPv6_Nadv_t *pNadv_hdr;
+ t_u8 ret = MFALSE;
+
+ /* IPV4 pkt check
+ * A gratuitous ARP is an ARP packet
+ * where the source and destination IP are both set to
+ * the IP of the machine issuing the packet.
+ */
+ if (memcmp(pmadapter, proto_ARP_type, &prx_pkt->eth803_hdr.h803_len,
+ sizeof(proto_ARP_type)) == 0) {
+ parp_hdr = (IPv4_ARP_t *)(&prx_pkt->rfc1042_hdr);
+ /* Graguitous ARP can be ARP request or ARP reply*/
+ if ((parp_hdr->op_code == mlan_htons(0x01)) ||
+ (parp_hdr->op_code == mlan_htons(0x02)))
+ if (memcmp(pmadapter, parp_hdr->src_ip,
+ parp_hdr->dst_ip, 4) == 0)
+ ret = MTRUE;
+ }
+
+ /* IPV6 pkt check
+ * An unsolicited Neighbor Advertisement pkt is
+ * marked by a cleared Solicited Flag
+ */
+ if (memcmp(pmadapter, proto_ARP_type_v6, &prx_pkt->eth803_hdr.h803_len,
+ sizeof(proto_ARP_type_v6)) == 0) {
+ pNadv_hdr = (IPv6_Nadv_t *)(&prx_pkt->rfc1042_hdr);
+ /* Check Nadv type: next header is ICMPv6 and
+ * icmp type is Nadv */
+ if (pNadv_hdr->next_hdr == 0x3A && pNadv_hdr->icmp_type == 0x88)
+ if ((pNadv_hdr->flags & mlan_htonl(0x40000000)) == 0)
+ ret = MTRUE;
+ }
+
+ return ret;
+}
+
+/**
+ * @brief This function processes received packet and forwards it
+ * to kernel/upper layer
+ *
+ * @param pmadapter A pointer to mlan_adapter
+ * @param pmbuf A pointer to mlan_buffer which includes the received packet
+ *
+ * @return MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ */
+mlan_status wlan_process_rx_packet(pmlan_adapter pmadapter, pmlan_buffer pmbuf)
+{
+ mlan_status ret = MLAN_STATUS_SUCCESS;
+ pmlan_private priv = pmadapter->priv[pmbuf->bss_index];
+ RxPacketHdr_t *prx_pkt;
+ RxPD *prx_pd;
+ int hdr_chop;
+ EthII_Hdr_t *peth_hdr;
+ t_u8 rfc1042_eth_hdr[MLAN_MAC_ADDR_LENGTH] = {0xaa, 0xaa, 0x03,
+ 0x00, 0x00, 0x00};
+ t_u8 snap_oui_802_h[MLAN_MAC_ADDR_LENGTH] = {0xaa, 0xaa, 0x03,
+ 0x00, 0x00, 0xf8};
+ t_u8 appletalk_aarp_type[2] = {0x80, 0xf3};
+ t_u8 ipx_snap_type[2] = {0x81, 0x37};
+#ifdef DRV_EMBEDDED_SUPPLICANT
+ t_u8 eapol_type[2] = {0x88, 0x8e};
+#endif
+ t_u8 ext_rate_info = 0;
+
+ ENTER();
+
+ prx_pd = (RxPD *)(pmbuf->pbuf + pmbuf->data_offset);
+ prx_pkt = (RxPacketHdr_t *)((t_u8 *)prx_pd + prx_pd->rx_pkt_offset);
+
+/** Small debug type */
+#define DBG_TYPE_SMALL 2
+/** Size of debugging structure */
+#define SIZE_OF_DBG_STRUCT 4
+ if (prx_pd->rx_pkt_type == PKT_TYPE_DEBUG) {
+ t_u8 dbg_type;
+ dbg_type = *(t_u8 *)&prx_pkt->eth803_hdr;
+ if (dbg_type == DBG_TYPE_SMALL) {
+ PRINTM(MFW_D, "\n");
+ DBG_HEXDUMP(MFW_D, "FWDBG",
+ (char *)((t_u8 *)&prx_pkt->eth803_hdr +
+ SIZE_OF_DBG_STRUCT),
+ prx_pd->rx_pkt_length);
+ PRINTM(MFW_D, "FWDBG::\n");
+ }
+ goto done;
+ }
+
+ PRINTM(MINFO,
+ "RX Data: data_len - prx_pd->rx_pkt_offset = %d - %d = %d\n",
+ pmbuf->data_len, prx_pd->rx_pkt_offset,
+ pmbuf->data_len - prx_pd->rx_pkt_offset);
+
+ HEXDUMP("RX Data: Dest", prx_pkt->eth803_hdr.dest_addr,
+ sizeof(prx_pkt->eth803_hdr.dest_addr));
+ HEXDUMP("RX Data: Src", prx_pkt->eth803_hdr.src_addr,
+ sizeof(prx_pkt->eth803_hdr.src_addr));
+
+ if ((memcmp(pmadapter, &prx_pkt->rfc1042_hdr, snap_oui_802_h,
+ sizeof(snap_oui_802_h)) == 0) ||
+ ((memcmp(pmadapter, &prx_pkt->rfc1042_hdr, rfc1042_eth_hdr,
+ sizeof(rfc1042_eth_hdr)) == 0) &&
+ memcmp(pmadapter, &prx_pkt->rfc1042_hdr.snap_type,
+ appletalk_aarp_type, sizeof(appletalk_aarp_type)) &&
+ memcmp(pmadapter, &prx_pkt->rfc1042_hdr.snap_type, ipx_snap_type,
+ sizeof(ipx_snap_type)))) {
+ /*
+ * 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.
+ */
+ peth_hdr =
+ (EthII_Hdr_t *)((t_u8 *)&prx_pkt->eth803_hdr +
+ sizeof(prx_pkt->eth803_hdr) +
+ sizeof(prx_pkt->rfc1042_hdr) -
+ sizeof(prx_pkt->eth803_hdr.dest_addr) -
+ sizeof(prx_pkt->eth803_hdr.src_addr) -
+ sizeof(prx_pkt->rfc1042_hdr.snap_type));
+
+ memcpy_ext(pmadapter, peth_hdr->src_addr,
+ prx_pkt->eth803_hdr.src_addr,
+ sizeof(peth_hdr->src_addr),
+ sizeof(peth_hdr->src_addr));
+ memcpy_ext(pmadapter, peth_hdr->dest_addr,
+ prx_pkt->eth803_hdr.dest_addr,
+ sizeof(peth_hdr->dest_addr),
+ sizeof(peth_hdr->dest_addr));
+
+ /* Chop off the RxPD + the excess memory from the 802.2/llc/snap
+ * header that was removed.
+ */
+ hdr_chop = (t_u32)((t_ptr)peth_hdr - (t_ptr)prx_pd);
+ } else {
+ HEXDUMP("RX Data: LLC/SNAP", (t_u8 *)&prx_pkt->rfc1042_hdr,
+ sizeof(prx_pkt->rfc1042_hdr));
+ if ((priv->hotspot_cfg & HOTSPOT_ENABLED) &&
+ discard_gratuitous_ARP_msg(prx_pkt, pmadapter)) {
+ ret = MLAN_STATUS_SUCCESS;
+ PRINTM(MDATA,
+ "Bypass sending Gratuitous ARP frame to Kernel.\n");
+ goto done;
+ }
+ /* Chop off the RxPD */
+ hdr_chop = (t_u32)((t_ptr)&prx_pkt->eth803_hdr - (t_ptr)prx_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
+ */
+ pmbuf->data_len -= hdr_chop;
+ pmbuf->data_offset += hdr_chop;
+ pmbuf->pparent = MNULL;
+ DBG_HEXDUMP(MDAT_D, "RxPD", (t_u8 *)prx_pd,
+ MIN(sizeof(RxPD), MAX_DATA_DUMP_LEN));
+ DBG_HEXDUMP(MDAT_D, "Rx Payload",
+ ((t_u8 *)prx_pd + prx_pd->rx_pkt_offset),
+ MIN(prx_pd->rx_pkt_length, MAX_DATA_DUMP_LEN));
+
+ priv->rxpd_rate = prx_pd->rx_rate;
+ pmadapter->callbacks.moal_get_system_time(pmadapter->pmoal_handle,
+ &pmbuf->out_ts_sec,
+ &pmbuf->out_ts_usec);
+ PRINTM_NETINTF(MDATA, priv);
+ PRINTM(MDATA, "%lu.%06lu : Data => kernel seq_num=%d tid=%d\n",
+ pmbuf->out_ts_sec, pmbuf->out_ts_usec, prx_pd->seq_num,
+ prx_pd->priority);
+
+#ifdef DRV_EMBEDDED_SUPPLICANT
+ if (supplicantIsEnabled(priv->psapriv) &&
+ (!memcmp(pmadapter, &prx_pkt->eth803_hdr.h803_len, eapol_type,
+ sizeof(eapol_type)))) {
+ // BML_SET_OFFSET(bufDesc, offset);
+ if (ProcessEAPoLPkt(priv->psapriv, pmbuf)) {
+ pmadapter->ops.data_complete(pmadapter, pmbuf, ret);
+ ret = MLAN_STATUS_SUCCESS;
+ PRINTM(MMSG,
+ "host supplicant eapol pkt process done.\n");
+
+ LEAVE();
+ return ret;
+ }
+ }
+#endif
+
+ if (MFALSE || priv->rx_pkt_info) {
+ ext_rate_info = (t_u8)(prx_pd->rx_info >> 16);
+ pmbuf->u.rx_info.data_rate =
+ wlan_index_to_data_rate(priv->adapter, prx_pd->rx_rate,
+ prx_pd->rate_info,
+ ext_rate_info);
+
+ pmbuf->u.rx_info.channel =
+ (prx_pd->rx_info & RXPD_CHAN_MASK) >> 5;
+ pmbuf->u.rx_info.antenna = prx_pd->antenna;
+ pmbuf->u.rx_info.rssi = prx_pd->snr - prx_pd->nf;
+ }
+ ret = pmadapter->callbacks.moal_recv_packet(pmadapter->pmoal_handle,
+ pmbuf);
+ if (ret == MLAN_STATUS_FAILURE) {
+ pmbuf->status_code = MLAN_ERROR_PKT_INVALID;
+ PRINTM(MERROR,
+ "STA Rx Error: moal_recv_packet returned error\n");
+ }
+done:
+ if (ret != MLAN_STATUS_PENDING)
+ pmadapter->ops.data_complete(pmadapter, pmbuf, ret);
+#ifdef USB
+ else if (IS_USB(pmadapter->card_type))
+ pmadapter->callbacks.moal_recv_complete(pmadapter->pmoal_handle,
+ MNULL, MLAN_USB_EP_DATA,
+ MLAN_STATUS_SUCCESS);
+#endif
+ LEAVE();
+
+ return ret;
+}
+
+/**
+ * @brief This function processes the received buffer
+ *
+ * @param adapter A pointer to mlan_adapter
+ * @param pmbuf A pointer to the received buffer
+ *
+ * @return MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ */
+mlan_status wlan_ops_sta_process_rx_packet(t_void *adapter, pmlan_buffer pmbuf)
+{
+ pmlan_adapter pmadapter = (pmlan_adapter)adapter;
+ mlan_status ret = MLAN_STATUS_SUCCESS;
+ RxPD *prx_pd;
+ RxPacketHdr_t *prx_pkt;
+ pmlan_private priv = pmadapter->priv[pmbuf->bss_index];
+ t_u8 ta[MLAN_MAC_ADDR_LENGTH];
+ t_u16 rx_pkt_type = 0;
+ wlan_mgmt_pkt *pmgmt_pkt_hdr = MNULL;
+
+ sta_node *sta_ptr = MNULL;
+ t_u16 adj_rx_rate = 0;
+ t_u8 antenna = 0;
+ ENTER();
+
+ prx_pd = (RxPD *)(pmbuf->pbuf + pmbuf->data_offset);
+ /* Endian conversion */
+ endian_convert_RxPD(prx_pd);
+ rx_pkt_type = prx_pd->rx_pkt_type;
+ prx_pkt = (RxPacketHdr_t *)((t_u8 *)prx_pd + prx_pd->rx_pkt_offset);
+
+ if ((prx_pd->rx_pkt_offset + prx_pd->rx_pkt_length) !=
+ (t_u16)pmbuf->data_len) {
+ PRINTM(MERROR,
+ "Wrong rx packet: len=%d,rx_pkt_offset=%d,"
+ " rx_pkt_length=%d\n",
+ pmbuf->data_len, prx_pd->rx_pkt_offset,
+ prx_pd->rx_pkt_length);
+ pmbuf->status_code = MLAN_ERROR_PKT_SIZE_INVALID;
+ ret = MLAN_STATUS_FAILURE;
+ pmadapter->ops.data_complete(pmadapter, pmbuf, ret);
+ goto done;
+ }
+ pmbuf->data_len = prx_pd->rx_pkt_offset + prx_pd->rx_pkt_length;
+
+ if (pmadapter->priv[pmbuf->bss_index]->mgmt_frame_passthru_mask &&
+ prx_pd->rx_pkt_type == PKT_TYPE_MGMT_FRAME) {
+ /* Check if this is mgmt packet and needs to
+ * forwarded to app as an event
+ */
+ pmgmt_pkt_hdr = (wlan_mgmt_pkt *)((t_u8 *)prx_pd +
+ prx_pd->rx_pkt_offset);
+ pmgmt_pkt_hdr->frm_len =
+ wlan_le16_to_cpu(pmgmt_pkt_hdr->frm_len);
+
+ if ((pmgmt_pkt_hdr->wlan_header.frm_ctl &
+ IEEE80211_FC_MGMT_FRAME_TYPE_MASK) == 0)
+ wlan_process_802dot11_mgmt_pkt(
+ pmadapter->priv[pmbuf->bss_index],
+ (t_u8 *)&pmgmt_pkt_hdr->wlan_header,
+ pmgmt_pkt_hdr->frm_len + sizeof(wlan_mgmt_pkt) -
+ sizeof(pmgmt_pkt_hdr->frm_len),
+ prx_pd);
+ pmadapter->ops.data_complete(pmadapter, pmbuf, ret);
+ goto done;
+ }
+ if (rx_pkt_type != PKT_TYPE_BAR) {
+ priv->rxpd_rate_info = prx_pd->rate_info;
+ priv->rxpd_rate = prx_pd->rx_rate;
+ priv->rxpd_rx_info = (t_u8)(prx_pd->rx_info >> 16);
+ if (priv->bss_type == MLAN_BSS_TYPE_STA) {
+ antenna = wlan_adjust_antenna(priv, prx_pd);
+ adj_rx_rate = wlan_adjust_data_rate(
+ priv, priv->rxpd_rate, priv->rxpd_rate_info);
+ pmadapter->callbacks.moal_hist_data_add(
+ pmadapter->pmoal_handle, pmbuf->bss_index,
+ adj_rx_rate, prx_pd->snr, prx_pd->nf, antenna);
+ }
+ }
+
+ /*
+ * 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)) ||
+ memcmp(priv->adapter, priv->curr_addr,
+ prx_pkt->eth803_hdr.dest_addr, MLAN_MAC_ADDR_LENGTH)) {
+ priv->snr = prx_pd->snr;
+ priv->nf = prx_pd->nf;
+ wlan_process_rx_packet(pmadapter, pmbuf);
+ goto done;
+ }
+
+ if (queuing_ra_based(priv)) {
+ memcpy_ext(pmadapter, ta, prx_pkt->eth803_hdr.src_addr,
+ MLAN_MAC_ADDR_LENGTH, MLAN_MAC_ADDR_LENGTH);
+ if (prx_pd->priority < MAX_NUM_TID) {
+ PRINTM(MDATA, "adhoc/tdls packet %p " MACSTR "\n",
+ pmbuf, MAC2STR(ta));
+ sta_ptr = wlan_get_station_entry(priv, ta);
+ if (sta_ptr) {
+ sta_ptr->rx_seq[prx_pd->priority] =
+ prx_pd->seq_num;
+ sta_ptr->snr = prx_pd->snr;
+ sta_ptr->nf = prx_pd->nf;
+ }
+ if (!sta_ptr || !sta_ptr->is_11n_enabled) {
+ wlan_process_rx_packet(pmadapter, pmbuf);
+ goto done;
+ }
+ }
+ } else {
+ priv->snr = prx_pd->snr;
+ priv->nf = prx_pd->nf;
+ if ((rx_pkt_type != PKT_TYPE_BAR) &&
+ (prx_pd->priority < MAX_NUM_TID))
+ priv->rx_seq[prx_pd->priority] = prx_pd->seq_num;
+ memcpy_ext(pmadapter, ta,
+ priv->curr_bss_params.bss_descriptor.mac_address,
+ MLAN_MAC_ADDR_LENGTH, MLAN_MAC_ADDR_LENGTH);
+ }
+ if ((priv->port_ctrl_mode == MTRUE && priv->port_open == MFALSE) &&
+ (rx_pkt_type != PKT_TYPE_BAR)) {
+ mlan_11n_rxreorder_pkt(priv, prx_pd->seq_num, prx_pd->priority,
+ ta, (t_u8)prx_pd->rx_pkt_type,
+ (t_void *)RX_PKT_DROPPED_IN_FW);
+ if (rx_pkt_type == PKT_TYPE_AMSDU) {
+ pmbuf->data_len = prx_pd->rx_pkt_length;
+ pmbuf->data_offset += prx_pd->rx_pkt_offset;
+ wlan_11n_deaggregate_pkt(priv, pmbuf);
+ } else {
+ wlan_process_rx_packet(pmadapter, pmbuf);
+ }
+ goto done;
+ }
+ /* Reorder and send to OS */
+ ret = mlan_11n_rxreorder_pkt(priv, prx_pd->seq_num, prx_pd->priority,
+ ta, (t_u8)prx_pd->rx_pkt_type,
+ (void *)pmbuf);
+ if (ret || (rx_pkt_type == PKT_TYPE_BAR))
+ pmadapter->ops.data_complete(pmadapter, pmbuf, ret);
+
+done:
+
+ LEAVE();
+ return ret;
+}
diff --git a/drivers/net/wireless/nxp/mxm_wifiex/wlan_src/mlan/mlan_sta_tx.c b/drivers/net/wireless/nxp/mxm_wifiex/wlan_src/mlan/mlan_sta_tx.c
new file mode 100644
index 000000000000..737f2baca4ee
--- /dev/null
+++ b/drivers/net/wireless/nxp/mxm_wifiex/wlan_src/mlan/mlan_sta_tx.c
@@ -0,0 +1,326 @@
+/** @file mlan_sta_tx.c
+ *
+ * @brief This file contains the handling of data packet
+ * transmission in MLAN module.
+ *
+ *
+ * Copyright 2014-2020 NXP
+ *
+ * This software file (the File) is distributed by NXP
+ * under the terms of the GNU General Public License Version 2, June 1991
+ * (the License). You may use, redistribute and/or modify the 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.
+ *
+ */
+
+/********************************************************
+Change log:
+ 10/21/2008: initial version
+********************************************************/
+
+#include "mlan.h"
+#include "mlan_join.h"
+#include "mlan_util.h"
+#include "mlan_fw.h"
+#include "mlan_main.h"
+#include "mlan_wmm.h"
+
+/********************************************************
+ Local Variables
+********************************************************/
+
+/********************************************************
+ Global Variables
+********************************************************/
+
+/********************************************************
+ Local Functions
+********************************************************/
+
+/********************************************************
+ Global functions
+********************************************************/
+/**
+ * @brief This function fill the txpd for tx packet
+ *
+ * @param priv A pointer to mlan_private structure
+ * @param pmbuf A pointer to the mlan_buffer for process
+ *
+ * @return headptr or MNULL
+ */
+t_void *wlan_ops_sta_process_txpd(t_void *priv, pmlan_buffer pmbuf)
+{
+ mlan_private *pmpriv = (mlan_private *)priv;
+ pmlan_adapter pmadapter = pmpriv->adapter;
+ TxPD *plocal_tx_pd;
+ t_u8 *head_ptr = MNULL;
+ t_u32 pkt_type;
+ t_u32 tx_control;
+
+ ENTER();
+
+ if (!pmbuf->data_len) {
+ PRINTM(MERROR, "STA Tx Error: Invalid packet length: %d\n",
+ pmbuf->data_len);
+ pmbuf->status_code = MLAN_ERROR_PKT_SIZE_INVALID;
+ goto done;
+ }
+ if (pmbuf->buf_type == MLAN_BUF_TYPE_RAW_DATA) {
+ memcpy_ext(pmpriv->adapter, &pkt_type,
+ pmbuf->pbuf + pmbuf->data_offset, sizeof(pkt_type),
+ sizeof(pkt_type));
+ memcpy_ext(pmpriv->adapter, &tx_control,
+ pmbuf->pbuf + pmbuf->data_offset + sizeof(pkt_type),
+ sizeof(tx_control), sizeof(tx_control));
+ pmbuf->data_offset += sizeof(pkt_type) + sizeof(tx_control);
+ pmbuf->data_len -= sizeof(pkt_type) + sizeof(tx_control);
+ }
+
+ if (pmbuf->data_offset <
+ (sizeof(TxPD) + pmpriv->intf_hr_len + DMA_ALIGNMENT)) {
+ PRINTM(MERROR,
+ "not enough space for TxPD: headroom=%d pkt_len=%d, required=%d\n",
+ pmbuf->data_offset, pmbuf->data_len,
+ sizeof(TxPD) + pmpriv->intf_hr_len + DMA_ALIGNMENT);
+ pmbuf->status_code = MLAN_ERROR_PKT_SIZE_INVALID;
+ goto done;
+ }
+
+ /* head_ptr should be aligned */
+ head_ptr = pmbuf->pbuf + pmbuf->data_offset - sizeof(TxPD) -
+ pmpriv->intf_hr_len;
+ head_ptr = (t_u8 *)((t_ptr)head_ptr & ~((t_ptr)(DMA_ALIGNMENT - 1)));
+
+ plocal_tx_pd = (TxPD *)(head_ptr + pmpriv->intf_hr_len);
+ memset(pmadapter, plocal_tx_pd, 0, sizeof(TxPD));
+ /* Set the BSS number to TxPD */
+ plocal_tx_pd->bss_num = GET_BSS_NUM(pmpriv);
+ plocal_tx_pd->bss_type = pmpriv->bss_type;
+ plocal_tx_pd->tx_pkt_length = (t_u16)pmbuf->data_len;
+
+ plocal_tx_pd->priority = (t_u8)pmbuf->priority;
+ plocal_tx_pd->pkt_delay_2ms =
+ wlan_wmm_compute_driver_packet_delay(pmpriv, pmbuf);
+
+ if (plocal_tx_pd->priority <
+ NELEMENTS(pmpriv->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
+ */
+ plocal_tx_pd->tx_control =
+ pmpriv->wmm.user_pri_pkt_tx_ctrl[plocal_tx_pd->priority];
+ if (pmadapter->pps_uapsd_mode) {
+ if (MTRUE == wlan_check_last_packet_indication(pmpriv)) {
+ pmadapter->tx_lock_flag = MTRUE;
+ plocal_tx_pd->flags =
+ MRVDRV_TxPD_POWER_MGMT_LAST_PACKET;
+ }
+ }
+ /* Offset of actual data */
+ plocal_tx_pd->tx_pkt_offset = (t_u16)(
+ (t_ptr)pmbuf->pbuf + pmbuf->data_offset - (t_ptr)plocal_tx_pd);
+
+ if (!plocal_tx_pd->tx_control) {
+ /* TxCtrl set by user or default */
+ plocal_tx_pd->tx_control = pmpriv->pkt_tx_ctrl;
+ }
+
+ if (pmbuf->buf_type == MLAN_BUF_TYPE_RAW_DATA) {
+ plocal_tx_pd->tx_pkt_type = (t_u16)pkt_type;
+ plocal_tx_pd->tx_control = tx_control;
+ }
+
+ if (pmbuf->flags & MLAN_BUF_FLAG_TX_STATUS) {
+ plocal_tx_pd->tx_control_1 |= pmbuf->tx_seq_num << 8;
+ plocal_tx_pd->flags |= MRVDRV_TxPD_FLAGS_TX_PACKET_STATUS;
+ }
+ if (pmbuf->flags & MLAN_BUF_FLAG_TX_CTRL) {
+ if (pmbuf->u.tx_info.data_rate) {
+ plocal_tx_pd->tx_control |=
+ (wlan_ieee_rateid_to_mrvl_rateid(
+ pmpriv, pmbuf->u.tx_info.data_rate,
+ MNULL)
+ << 16);
+ plocal_tx_pd->tx_control |= TXPD_TXRATE_ENABLE;
+ }
+ plocal_tx_pd->tx_control_1 |= pmbuf->u.tx_info.channel << 21;
+ if (pmbuf->u.tx_info.bw) {
+ plocal_tx_pd->tx_control_1 |= pmbuf->u.tx_info.bw << 16;
+ plocal_tx_pd->tx_control_1 |= TXPD_BW_ENABLE;
+ }
+ if (pmbuf->u.tx_info.tx_power.tp.hostctl)
+ plocal_tx_pd->tx_control |=
+ (t_u32)pmbuf->u.tx_info.tx_power.val;
+ if (pmbuf->u.tx_info.retry_limit) {
+ plocal_tx_pd->tx_control |= pmbuf->u.tx_info.retry_limit
+ << 8;
+ plocal_tx_pd->tx_control |= TXPD_RETRY_ENABLE;
+ }
+ }
+ endian_convert_TxPD(plocal_tx_pd);
+
+ /* Adjust the data offset and length to include TxPD in pmbuf */
+ pmbuf->data_len += pmbuf->data_offset;
+ pmbuf->data_offset = (t_u32)(head_ptr - pmbuf->pbuf);
+ pmbuf->data_len -= pmbuf->data_offset;
+
+done:
+ LEAVE();
+ return head_ptr;
+}
+
+/**
+ * @brief This function tells firmware to send a NULL data packet.
+ *
+ * @param priv A pointer to mlan_private structure
+ * @param flags Transmit Pkt Flags
+ *
+ * @return MLAN_STATUS_SUCCESS/MLAN_STATUS_PENDING --success, otherwise
+ * failure
+ */
+mlan_status wlan_send_null_packet(pmlan_private priv, t_u8 flags)
+{
+ pmlan_adapter pmadapter = MNULL;
+ TxPD *ptx_pd;
+/* sizeof(TxPD) + Interface specific header */
+#define NULL_PACKET_HDR 256
+ t_u32 data_len = NULL_PACKET_HDR;
+ pmlan_buffer pmbuf = MNULL;
+ t_u8 *ptr;
+ mlan_status ret = MLAN_STATUS_SUCCESS;
+#ifdef DEBUG_LEVEL1
+ t_u32 sec = 0, usec = 0;
+#endif
+
+ ENTER();
+
+ if (!priv) {
+ LEAVE();
+ return MLAN_STATUS_FAILURE;
+ }
+ pmadapter = priv->adapter;
+
+ if (pmadapter->surprise_removed == MTRUE) {
+ ret = MLAN_STATUS_FAILURE;
+ goto done;
+ }
+
+ if (priv->media_connected == MFALSE) {
+ ret = MLAN_STATUS_FAILURE;
+ goto done;
+ }
+
+ if (pmadapter->data_sent == MTRUE) {
+ ret = MLAN_STATUS_FAILURE;
+ goto done;
+ }
+
+ pmbuf = wlan_alloc_mlan_buffer(pmadapter, data_len, 0,
+ MOAL_MALLOC_BUFFER);
+ if (!pmbuf) {
+ ret = MLAN_STATUS_FAILURE;
+ goto done;
+ }
+ memset(pmadapter, pmbuf->pbuf, 0, data_len);
+ pmbuf->bss_index = priv->bss_index;
+ pmbuf->buf_type = MLAN_BUF_TYPE_DATA;
+ pmbuf->flags |= MLAN_BUF_FLAG_NULL_PKT;
+ ptr = pmbuf->pbuf + pmbuf->data_offset;
+ pmbuf->data_len = sizeof(TxPD) + priv->intf_hr_len;
+ ptx_pd = (TxPD *)(ptr + priv->intf_hr_len);
+ ptx_pd->tx_control = priv->pkt_tx_ctrl;
+ ptx_pd->flags = flags;
+ ptx_pd->priority = WMM_HIGHEST_PRIORITY;
+ ptx_pd->tx_pkt_offset = sizeof(TxPD);
+ /* Set the BSS number to TxPD */
+ ptx_pd->bss_num = GET_BSS_NUM(priv);
+ ptx_pd->bss_type = priv->bss_type;
+
+ endian_convert_TxPD(ptx_pd);
+
+ ret = pmadapter->ops.host_to_card(priv, MLAN_TYPE_DATA, pmbuf, MNULL);
+
+ switch (ret) {
+#ifdef USB
+ case MLAN_STATUS_PRESOURCE:
+ PRINTM(MINFO, "MLAN_STATUS_PRESOURCE is returned\n");
+ break;
+#endif
+ case MLAN_STATUS_RESOURCE:
+ wlan_free_mlan_buffer(pmadapter, pmbuf);
+ PRINTM(MERROR, "STA Tx Error: Failed to send NULL packet!\n");
+ pmadapter->dbg.num_tx_host_to_card_failure++;
+ goto done;
+ case MLAN_STATUS_FAILURE:
+ wlan_free_mlan_buffer(pmadapter, pmbuf);
+ PRINTM(MERROR, "STA Tx Error: Failed to send NULL packet!\n");
+ pmadapter->dbg.num_tx_host_to_card_failure++;
+ goto done;
+ case MLAN_STATUS_SUCCESS:
+ wlan_free_mlan_buffer(pmadapter, pmbuf);
+ PRINTM(MINFO, "STA Tx: Successfully send the NULL packet\n");
+ pmadapter->tx_lock_flag = MTRUE;
+ break;
+ case MLAN_STATUS_PENDING:
+ pmadapter->tx_lock_flag = MTRUE;
+ break;
+ default:
+ break;
+ }
+
+ PRINTM_GET_SYS_TIME(MDATA, &sec, &usec);
+ PRINTM_NETINTF(MDATA, priv);
+ PRINTM(MDATA, "%lu.%06lu : Null data => FW\n", sec, usec);
+ DBG_HEXDUMP(MDAT_D, "Null data", ptr, sizeof(TxPD) + priv->intf_hr_len);
+done:
+ LEAVE();
+ return ret;
+}
+
+/**
+ * @brief This function checks if we need to send last packet indication.
+ *
+ * @param priv A pointer to mlan_private structure
+ *
+ * @return MTRUE or MFALSE
+ */
+t_u8 wlan_check_last_packet_indication(pmlan_private priv)
+{
+ pmlan_adapter pmadapter = priv->adapter;
+ t_u8 ret = MFALSE;
+ t_u8 prop_ps = MTRUE;
+
+ ENTER();
+
+ if (!pmadapter->sleep_period.period) {
+ LEAVE();
+ return ret;
+ }
+ if (wlan_bypass_tx_list_empty(pmadapter) &&
+ wlan_wmm_lists_empty(pmadapter)) {
+ if (((priv->curr_bss_params.wmm_uapsd_enabled == MTRUE) &&
+ priv->wmm_qosinfo) ||
+ prop_ps)
+
+ ret = MTRUE;
+ }
+ if (ret && !pmadapter->cmd_sent && !pmadapter->curr_cmd &&
+ !wlan_is_cmd_pending(pmadapter)) {
+ pmadapter->delay_null_pkt = MFALSE;
+ ret = MTRUE;
+ } else {
+ ret = MFALSE;
+ pmadapter->delay_null_pkt = MTRUE;
+ }
+ LEAVE();
+ return ret;
+}
diff --git a/drivers/net/wireless/nxp/mxm_wifiex/wlan_src/mlan/mlan_txrx.c b/drivers/net/wireless/nxp/mxm_wifiex/wlan_src/mlan/mlan_txrx.c
new file mode 100644
index 000000000000..a8c93d5322db
--- /dev/null
+++ b/drivers/net/wireless/nxp/mxm_wifiex/wlan_src/mlan/mlan_txrx.c
@@ -0,0 +1,424 @@
+/**
+ * @file mlan_txrx.c
+ *
+ * @brief This file contains the handling of TX/RX in MLAN
+ *
+ *
+ * Copyright 2014-2020 NXP
+ *
+ * This software file (the File) is distributed by NXP
+ * under the terms of the GNU General Public License Version 2, June 1991
+ * (the License). You may use, redistribute and/or modify the 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.
+ *
+ */
+
+/*************************************************************
+Change Log:
+ 05/11/2009: initial version
+************************************************************/
+
+#include "mlan.h"
+#ifdef STA_SUPPORT
+#include "mlan_join.h"
+#endif
+#include "mlan_util.h"
+#include "mlan_fw.h"
+#include "mlan_main.h"
+#include "mlan_wmm.h"
+
+/********************************************************
+ Local Variables
+********************************************************/
+
+/********************************************************
+ Global Variables
+********************************************************/
+
+/********************************************************
+ Local Functions
+********************************************************/
+
+/********************************************************
+ Global Functions
+********************************************************/
+/**
+ * @brief This function processes the received buffer
+ *
+ * @param pmadapter A pointer to mlan_adapter
+ * @param pmbuf A pointer to the received buffer
+ *
+ * @return MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ */
+mlan_status wlan_handle_rx_packet(pmlan_adapter pmadapter, pmlan_buffer pmbuf)
+{
+ mlan_status ret = MLAN_STATUS_SUCCESS;
+ pmlan_private priv = MNULL;
+ RxPD *prx_pd;
+#ifdef DEBUG_LEVEL1
+ t_u32 sec = 0, usec = 0;
+#endif
+
+ ENTER();
+
+ prx_pd = (RxPD *)(pmbuf->pbuf + pmbuf->data_offset);
+ /* Get the BSS number from RxPD, get corresponding priv */
+ priv = wlan_get_priv_by_id(pmadapter, prx_pd->bss_num & BSS_NUM_MASK,
+ prx_pd->bss_type);
+ if (!priv)
+ priv = wlan_get_priv(pmadapter, MLAN_BSS_ROLE_ANY);
+ if (!priv) {
+ ret = MLAN_STATUS_FAILURE;
+ goto done;
+ }
+ pmbuf->bss_index = priv->bss_index;
+ PRINTM_GET_SYS_TIME(MDATA, &sec, &usec);
+ PRINTM_NETINTF(MDATA, priv);
+ PRINTM(MDATA, "%lu.%06lu : Data <= FW\n", sec, usec);
+ ret = priv->ops.process_rx_packet(pmadapter, pmbuf);
+
+done:
+ LEAVE();
+ return ret;
+}
+
+/**
+ * @brief This function checks the conditions and sends packet to device
+ *
+ * @param priv A pointer to mlan_private structure
+ * @param pmbuf A pointer to the mlan_buffer for process
+ * @param tx_param A pointer to mlan_tx_param structure
+ *
+ * @return MLAN_STATUS_SUCCESS/MLAN_STATUS_PENDING --success, otherwise
+ * failure
+ */
+mlan_status wlan_process_tx(pmlan_private priv, pmlan_buffer pmbuf,
+ mlan_tx_param *tx_param)
+{
+ mlan_status ret = MLAN_STATUS_SUCCESS;
+ pmlan_adapter pmadapter = priv->adapter;
+ t_u8 *head_ptr = MNULL;
+#ifdef DEBUG_LEVEL1
+ t_u32 sec = 0, usec = 0;
+#endif
+#ifdef STA_SUPPORT
+ PTxPD plocal_tx_pd = MNULL;
+#endif
+
+ ENTER();
+ head_ptr = (t_u8 *)priv->ops.process_txpd(priv, pmbuf);
+ if (!head_ptr) {
+ pmbuf->status_code = MLAN_ERROR_PKT_INVALID;
+ ret = MLAN_STATUS_FAILURE;
+ goto done;
+ }
+#ifdef STA_SUPPORT
+ if (GET_BSS_ROLE(priv) == MLAN_BSS_ROLE_STA)
+ plocal_tx_pd = (TxPD *)(head_ptr + priv->intf_hr_len);
+#endif
+ if (pmadapter->tp_state_on)
+ pmadapter->callbacks.moal_tp_accounting(pmadapter->pmoal_handle,
+ pmbuf, 4);
+ if (pmadapter->tp_state_drop_point == 4)
+ goto done;
+ else {
+ ret = pmadapter->ops.host_to_card(priv, MLAN_TYPE_DATA, pmbuf,
+ tx_param);
+ }
+done:
+ switch (ret) {
+#ifdef USB
+ case MLAN_STATUS_PRESOURCE:
+ PRINTM(MINFO, "MLAN_STATUS_PRESOURCE is returned\n");
+ DBG_HEXDUMP(MDAT_D, "Tx", head_ptr + priv->intf_hr_len,
+ MIN(pmbuf->data_len + sizeof(TxPD),
+ MAX_DATA_DUMP_LEN));
+ break;
+#endif
+ case MLAN_STATUS_RESOURCE:
+#ifdef STA_SUPPORT
+ if ((GET_BSS_ROLE(priv) == MLAN_BSS_ROLE_STA) &&
+ pmadapter->pps_uapsd_mode &&
+ (pmadapter->tx_lock_flag == MTRUE)) {
+ pmadapter->tx_lock_flag = MFALSE;
+ if (plocal_tx_pd != MNULL)
+ plocal_tx_pd->flags = 0;
+ }
+#endif
+ PRINTM(MINFO, "MLAN_STATUS_RESOURCE is returned\n");
+ break;
+ case MLAN_STATUS_FAILURE:
+ pmadapter->dbg.num_tx_host_to_card_failure++;
+ pmbuf->status_code = MLAN_ERROR_DATA_TX_FAIL;
+ wlan_write_data_complete(pmadapter, pmbuf, ret);
+ break;
+ case MLAN_STATUS_PENDING:
+ DBG_HEXDUMP(MDAT_D, "Tx", head_ptr + priv->intf_hr_len,
+ MIN(pmbuf->data_len + sizeof(TxPD),
+ MAX_DATA_DUMP_LEN));
+ break;
+ case MLAN_STATUS_SUCCESS:
+ DBG_HEXDUMP(MDAT_D, "Tx", head_ptr + priv->intf_hr_len,
+ MIN(pmbuf->data_len + sizeof(TxPD),
+ MAX_DATA_DUMP_LEN));
+ wlan_write_data_complete(pmadapter, pmbuf, ret);
+ break;
+ default:
+ break;
+ }
+
+ if ((ret == MLAN_STATUS_SUCCESS) || (ret == MLAN_STATUS_PENDING)) {
+ PRINTM_GET_SYS_TIME(MDATA, &sec, &usec);
+ PRINTM_NETINTF(MDATA, priv);
+ PRINTM(MDATA, "%lu.%06lu : Data => FW\n", sec, usec);
+ }
+ LEAVE();
+ return ret;
+}
+
+/**
+ * @brief Packet send completion handling
+ *
+ * @param pmadapter A pointer to mlan_adapter structure
+ * @param pmbuf A pointer to mlan_buffer structure
+ * @param status Callback status
+ *
+ * @return MLAN_STATUS_SUCCESS
+ */
+mlan_status wlan_write_data_complete(pmlan_adapter pmadapter,
+ pmlan_buffer pmbuf, mlan_status status)
+{
+ mlan_status ret = MLAN_STATUS_SUCCESS;
+ pmlan_callbacks pcb;
+
+ ENTER();
+
+ MASSERT(pmadapter && pmbuf);
+ if (!pmadapter || !pmbuf) {
+ LEAVE();
+ return MLAN_STATUS_FAILURE;
+ }
+
+ pcb = &pmadapter->callbacks;
+
+ if ((pmbuf->buf_type == MLAN_BUF_TYPE_DATA) ||
+ (pmbuf->buf_type == MLAN_BUF_TYPE_RAW_DATA)) {
+ PRINTM(MINFO, "wlan_write_data_complete: DATA %p\n", pmbuf);
+#if defined(USB)
+ if ((pmbuf->flags & MLAN_BUF_FLAG_USB_TX_AGGR) &&
+ pmbuf->use_count) {
+ pmlan_buffer pmbuf_next;
+ t_u32 i, use_count = pmbuf->use_count;
+ for (i = 0; i <= use_count; i++) {
+ pmbuf_next = pmbuf->pnext;
+ if (pmbuf->flags & MLAN_BUF_FLAG_MOAL_TX_BUF)
+ pcb->moal_send_packet_complete(
+ pmadapter->pmoal_handle, pmbuf,
+ status);
+ else
+ wlan_free_mlan_buffer(pmadapter, pmbuf);
+ pmbuf = pmbuf_next;
+ }
+ } else {
+#endif
+ if (pmbuf->flags & MLAN_BUF_FLAG_MOAL_TX_BUF) {
+ /* pmbuf was allocated by MOAL */
+ pcb->moal_send_packet_complete(
+ pmadapter->pmoal_handle, pmbuf, status);
+ } else {
+ /* pmbuf was allocated by MLAN */
+ wlan_free_mlan_buffer(pmadapter, pmbuf);
+ }
+#if defined(USB)
+ }
+#endif
+ }
+
+ LEAVE();
+ return ret;
+}
+
+/**
+ * @brief Packet receive completion callback handler
+ *
+ * @param pmadapter A pointer to mlan_adapter structure
+ * @param pmbuf A pointer to mlan_buffer structure
+ * @param status Callback status
+ *
+ * @return MLAN_STATUS_SUCCESS
+ */
+mlan_status wlan_recv_packet_complete(pmlan_adapter pmadapter,
+ pmlan_buffer pmbuf, mlan_status status)
+{
+ mlan_status ret = MLAN_STATUS_SUCCESS;
+ pmlan_callbacks pcb;
+
+ ENTER();
+
+ MASSERT(pmadapter && pmbuf);
+ if (!pmadapter || !pmbuf) {
+ LEAVE();
+ return MLAN_STATUS_FAILURE;
+ }
+
+ pcb = &pmadapter->callbacks;
+ MASSERT(pmbuf->bss_index < pmadapter->priv_num);
+
+ if (pmbuf->pparent) {
+ /** we will free the pparaent at the end of deaggr */
+ wlan_free_mlan_buffer(pmadapter, pmbuf);
+ } else {
+ pmadapter->ops.data_complete(pmadapter, pmbuf, status);
+ }
+
+ LEAVE();
+ return ret;
+}
+
+/**
+ * @brief Add packet to Bypass TX queue
+ *
+ * @param pmadapter Pointer to the mlan_adapter driver data struct
+ * @param pmbuf Pointer to the mlan_buffer data struct
+ *
+ * @return N/A
+ */
+t_void wlan_add_buf_bypass_txqueue(mlan_adapter *pmadapter, pmlan_buffer pmbuf)
+{
+ pmlan_private priv = pmadapter->priv[pmbuf->bss_index];
+ ENTER();
+
+ if (pmbuf->buf_type != MLAN_BUF_TYPE_RAW_DATA)
+ pmbuf->buf_type = MLAN_BUF_TYPE_DATA;
+ pmadapter->callbacks.moal_spin_lock(pmadapter->pmoal_handle,
+ priv->bypass_txq.plock);
+ pmadapter->bypass_pkt_count++;
+ util_enqueue_list_tail(pmadapter->pmoal_handle, &priv->bypass_txq,
+ (pmlan_linked_list)pmbuf, MNULL, MNULL);
+ pmadapter->callbacks.moal_spin_unlock(pmadapter->pmoal_handle,
+ priv->bypass_txq.plock);
+ LEAVE();
+}
+
+/**
+ * @brief Check if packets are available in Bypass TX queue
+ *
+ * @param pmadapter Pointer to the mlan_adapter driver data struct
+ *
+ * @return MFALSE if not empty; MTRUE if empty
+ */
+INLINE t_u8 wlan_bypass_tx_list_empty(mlan_adapter *pmadapter)
+{
+ return (pmadapter->bypass_pkt_count) ? MFALSE : MTRUE;
+}
+
+/**
+ * @brief Clean up the By-pass TX queue
+ *
+ * @param priv Pointer to the mlan_private data struct
+ *
+ * @return N/A
+ */
+t_void wlan_cleanup_bypass_txq(mlan_private *priv)
+{
+ pmlan_buffer pmbuf;
+ mlan_adapter *pmadapter = priv->adapter;
+ ENTER();
+ pmadapter->callbacks.moal_spin_lock(pmadapter->pmoal_handle,
+ priv->bypass_txq.plock);
+ while ((pmbuf = (pmlan_buffer)util_peek_list(pmadapter->pmoal_handle,
+ &priv->bypass_txq, MNULL,
+ MNULL))) {
+ util_unlink_list(pmadapter->pmoal_handle, &priv->bypass_txq,
+ (pmlan_linked_list)pmbuf, MNULL, MNULL);
+ wlan_write_data_complete(pmadapter, pmbuf, MLAN_STATUS_FAILURE);
+ pmadapter->bypass_pkt_count--;
+ }
+ pmadapter->callbacks.moal_spin_unlock(pmadapter->pmoal_handle,
+ priv->bypass_txq.plock);
+ LEAVE();
+}
+
+/**
+ * @brief Transmit the By-passed packet awaiting in by-pass queue
+ *
+ * @param pmadapter Pointer to the mlan_adapter driver data struct
+ *
+ * @return N/A
+ */
+t_void wlan_process_bypass_tx(pmlan_adapter pmadapter)
+{
+ pmlan_buffer pmbuf;
+ mlan_tx_param tx_param;
+ mlan_status status = MLAN_STATUS_SUCCESS;
+ pmlan_private priv;
+ int j = 0;
+ ENTER();
+ do {
+ for (j = 0; j < pmadapter->priv_num; ++j) {
+ priv = pmadapter->priv[j];
+ if (priv) {
+ pmbuf = (pmlan_buffer)util_dequeue_list(
+ pmadapter->pmoal_handle,
+ &priv->bypass_txq,
+ pmadapter->callbacks.moal_spin_lock,
+ pmadapter->callbacks.moal_spin_unlock);
+ if (pmbuf) {
+ pmadapter->callbacks.moal_spin_lock(
+ pmadapter->pmoal_handle,
+ priv->bypass_txq.plock);
+ pmadapter->bypass_pkt_count--;
+ pmadapter->callbacks.moal_spin_unlock(
+ pmadapter->pmoal_handle,
+ priv->bypass_txq.plock);
+ PRINTM(MINFO,
+ "Dequeuing bypassed packet %p\n",
+ pmbuf);
+ if (wlan_bypass_tx_list_empty(
+ pmadapter))
+ tx_param.next_pkt_len = 0;
+ else
+ tx_param.next_pkt_len =
+ pmbuf->data_len;
+ status = wlan_process_tx(
+ pmadapter->priv[pmbuf->bss_index],
+ pmbuf, &tx_param);
+
+ if (status == MLAN_STATUS_RESOURCE) {
+ /* Queue the packet again so
+ * that it will be TX'ed later
+ */
+ pmadapter->callbacks.moal_spin_lock(
+ pmadapter->pmoal_handle,
+ priv->bypass_txq.plock);
+ pmadapter->bypass_pkt_count++;
+ util_enqueue_list_head(
+ pmadapter->pmoal_handle,
+ &priv->bypass_txq,
+ (pmlan_linked_list)pmbuf,
+ pmadapter->callbacks
+ .moal_spin_lock,
+ pmadapter->callbacks
+ .moal_spin_unlock);
+ pmadapter->callbacks.moal_spin_unlock(
+ pmadapter->pmoal_handle,
+ priv->bypass_txq.plock);
+ }
+ break;
+ } else {
+ PRINTM(MINFO, "Nothing to send\n");
+ }
+ }
+ }
+ } while (!pmadapter->data_sent && !pmadapter->tx_lock_flag &&
+ !wlan_bypass_tx_list_empty(pmadapter));
+ LEAVE();
+}
diff --git a/drivers/net/wireless/nxp/mxm_wifiex/wlan_src/mlan/mlan_uap.h b/drivers/net/wireless/nxp/mxm_wifiex/wlan_src/mlan/mlan_uap.h
new file mode 100644
index 000000000000..f6f85b851591
--- /dev/null
+++ b/drivers/net/wireless/nxp/mxm_wifiex/wlan_src/mlan/mlan_uap.h
@@ -0,0 +1,57 @@
+/** @file mlan_uap.h
+ *
+ * @brief This file contains related macros, enum, and struct
+ * of uap functionalities
+ *
+ *
+ * Copyright 2014-2020 NXP
+ *
+ * This software file (the File) is distributed by NXP
+ * under the terms of the GNU General Public License Version 2, June 1991
+ * (the License). You may use, redistribute and/or modify the 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.
+ *
+ */
+
+/********************************************************
+Change log:
+ 02/05/2009: initial version
+********************************************************/
+
+#ifndef _MLAN_UAP_H_
+#define _MLAN_UAP_H_
+
+mlan_status wlan_uap_get_channel(pmlan_private pmpriv);
+
+mlan_status wlan_uap_set_channel(pmlan_private pmpriv,
+ Band_Config_t uap_band_cfg, t_u8 channel);
+
+mlan_status wlan_uap_get_beacon_dtim(pmlan_private pmpriv);
+
+mlan_status wlan_ops_uap_ioctl(t_void *adapter, pmlan_ioctl_req pioctl_req);
+
+mlan_status wlan_ops_uap_prepare_cmd(t_void *priv, t_u16 cmd_no,
+ t_u16 cmd_action, t_u32 cmd_oid,
+ t_void *pioctl_buf, t_void *pdata_buf,
+ t_void *pcmd_buf);
+
+mlan_status wlan_ops_uap_process_cmdresp(t_void *priv, t_u16 cmdresp_no,
+ t_void *pcmd_buf, t_void *pioctl);
+
+mlan_status wlan_ops_uap_process_rx_packet(t_void *adapter, pmlan_buffer pmbuf);
+
+mlan_status wlan_ops_uap_process_event(t_void *priv);
+
+t_void *wlan_ops_uap_process_txpd(t_void *priv, pmlan_buffer pmbuf);
+
+mlan_status wlan_ops_uap_init_cmd(t_void *priv, t_u8 first_bss);
+
+#endif /* _MLAN_UAP_H_ */
diff --git a/drivers/net/wireless/nxp/mxm_wifiex/wlan_src/mlan/mlan_uap_cmdevent.c b/drivers/net/wireless/nxp/mxm_wifiex/wlan_src/mlan/mlan_uap_cmdevent.c
new file mode 100644
index 000000000000..1f905eb56b33
--- /dev/null
+++ b/drivers/net/wireless/nxp/mxm_wifiex/wlan_src/mlan/mlan_uap_cmdevent.c
@@ -0,0 +1,5587 @@
+/** @file mlan_uap_cmdevent.c
+ *
+ * @brief This file contains the handling of AP mode command and event
+ *
+ *
+ * Copyright 2014-2020 NXP
+ *
+ * This software file (the File) is distributed by NXP
+ * under the terms of the GNU General Public License Version 2, June 1991
+ * (the License). You may use, redistribute and/or modify the 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.
+ *
+ */
+
+/********************************************************
+Change log:
+ 02/05/2009: initial version
+********************************************************/
+
+#include "mlan.h"
+#include "mlan_util.h"
+#include "mlan_fw.h"
+#ifdef STA_SUPPORT
+#include "mlan_join.h"
+#endif
+#include "mlan_main.h"
+#include "mlan_uap.h"
+#ifdef SDIO
+#include "mlan_sdio.h"
+#endif /* SDIO */
+#include "mlan_11n.h"
+#include "mlan_11h.h"
+#include "mlan_11ac.h"
+#include "mlan_11ax.h"
+#ifdef DRV_EMBEDDED_AUTHENTICATOR
+#include "authenticator_api.h"
+#endif
+#ifdef PCIE
+#include "mlan_pcie.h"
+#endif /* PCIE */
+/********************************************************
+ Local Functions
+********************************************************/
+
+/**
+ * @brief This function prepares command of BAND_STEERING_CFG
+ *
+ * @param pmpriv A pointer to mlan_private structure
+ * @param cmd A pointer to HostCmd_DS_COMMAND structure
+ * @param cmd_action
+ * @param pdata_buf A pointer to data buffer
+ * @return MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ */
+mlan_status wlan_cmd_set_get_band_steering_cfg(pmlan_private pmpriv,
+ HostCmd_DS_COMMAND *cmd,
+ t_u16 cmd_action,
+ t_void *pdata_buf)
+{
+ mlan_ds_band_steer_cfg *pband_steer_cfg =
+ (mlan_ds_band_steer_cfg *)pdata_buf;
+ ENTER();
+
+ cmd->command = wlan_cpu_to_le16(HostCmd_CMD_802_11_BAND_STEERING);
+ cmd->size =
+ wlan_cpu_to_le16(sizeof(HostCmd_DS_BAND_STEERING) + S_DS_GEN);
+ cmd->params.band_steer_info.state = pband_steer_cfg->state;
+ cmd->params.band_steer_info.block_2g_prb_req =
+ pband_steer_cfg->block_2g_prb_req;
+ cmd->params.band_steer_info.max_btm_req_allowed =
+ pband_steer_cfg->max_btm_req_allowed;
+ cmd->params.band_steer_info.action = cmd_action;
+
+ LEAVE();
+ return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ * @brief This function handle response of HostCmd_CMD_802_11_BAND_STEERING
+ *
+ * @param pmpriv A pointer to mlan_private structure
+ * @param resp Pointer to command response buffer
+ *
+ * @return MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ */
+mlan_status wlan_ret_set_get_band_steering_cfg(mlan_private *pmpriv,
+ HostCmd_DS_COMMAND *resp,
+ mlan_ioctl_req *pioctl_buf)
+{
+ mlan_status ret = MLAN_STATUS_SUCCESS;
+ HostCmd_DS_BAND_STEERING *pband_steer_info =
+ &resp->params.band_steer_info;
+ mlan_ds_misc_cfg *pband_steer;
+
+ ENTER();
+
+ pband_steer = (mlan_ds_misc_cfg *)pioctl_buf->pbuf;
+
+ pband_steer->param.band_steer_cfg.action = pband_steer_info->action;
+ pband_steer->param.band_steer_cfg.state = pband_steer_info->state;
+ pband_steer->param.band_steer_cfg.block_2g_prb_req =
+ pband_steer_info->block_2g_prb_req;
+ pband_steer->param.band_steer_cfg.max_btm_req_allowed =
+ pband_steer_info->max_btm_req_allowed;
+
+ LEAVE();
+ return ret;
+}
+
+/**
+ * @brief This function prepares command of BEACON_STUCK_CFG
+ *
+ * @param pmpriv A pointer to mlan_private structure
+ * @param cmd A pointer to HostCmd_DS_COMMAND structure
+ * @param cmd_action
+ * @param pdata_buf A pointer to data buffer
+ * @return MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ */
+mlan_status wlan_cmd_set_get_beacon_stuck_cfg(IN pmlan_private pmpriv,
+ IN HostCmd_DS_COMMAND *cmd,
+ IN t_u16 cmd_action,
+ IN t_void *pdata_buf)
+{
+ HostCmd_DS_BEACON_STUCK_CFG *pbeacon_stuck_param_cfg =
+ (HostCmd_DS_BEACON_STUCK_CFG *)(pdata_buf + sizeof(t_u32));
+
+ ENTER();
+
+ cmd->command = wlan_cpu_to_le16(HostCmd_CMD_UAP_BEACON_STUCK_CFG);
+ cmd->size = wlan_cpu_to_le16(sizeof(HostCmd_DS_BEACON_STUCK_CFG) +
+ S_DS_GEN);
+ cmd->params.beacon_stuck_cfg.beacon_stuck_detect_count =
+ pbeacon_stuck_param_cfg->beacon_stuck_detect_count;
+ cmd->params.beacon_stuck_cfg.recovery_confirm_count =
+ pbeacon_stuck_param_cfg->recovery_confirm_count;
+ cmd->params.beacon_stuck_cfg.action = cmd_action;
+
+ LEAVE();
+ return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ * @brief This function handle response of HostCmd_CMD_UAP_BEACON_STUCK_CFG
+ *
+ * @param pmpriv A pointer to mlan_private structure
+ * @param resp Pointer to command response buffer
+ *
+ * @return MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ */
+mlan_status wlan_ret_set_get_beacon_stuck_cfg(mlan_private *pmpriv,
+ HostCmd_DS_COMMAND *resp,
+ mlan_ioctl_req *pioctl_buf)
+{
+ mlan_status ret = MLAN_STATUS_SUCCESS;
+ HostCmd_DS_BEACON_STUCK_CFG *pbeacon_stuck_param_cfg =
+ &resp->params.beacon_stuck_cfg;
+ mlan_ds_misc_cfg *pbeacon_stuck;
+
+ ENTER();
+
+ pbeacon_stuck = (mlan_ds_misc_cfg *)pioctl_buf->pbuf;
+
+ pbeacon_stuck->param.beacon_stuck_cfg.action =
+ pbeacon_stuck_param_cfg->action;
+ pbeacon_stuck->param.beacon_stuck_cfg.beacon_stuck_detect_count =
+ pbeacon_stuck_param_cfg->beacon_stuck_detect_count;
+ pbeacon_stuck->param.beacon_stuck_cfg.recovery_confirm_count =
+ pbeacon_stuck_param_cfg->recovery_confirm_count;
+
+ LEAVE();
+ return ret;
+}
+
+/**
+ * @brief This function handles the command response error
+ *
+ * @param pmpriv A pointer to mlan_private structure
+ * @param resp A pointer to HostCmd_DS_COMMAND
+ * @param pioctl_buf A pointer to command buffer
+ *
+ * @return N/A
+ */
+static mlan_status uap_process_cmdresp_error(mlan_private *pmpriv,
+ HostCmd_DS_COMMAND *resp,
+ mlan_ioctl_req *pioctl_buf)
+{
+ mlan_adapter *pmadapter = pmpriv->adapter;
+#if defined(USB)
+ t_u8 i;
+#endif
+ mlan_status ret = MLAN_STATUS_FAILURE;
+
+ ENTER();
+ if (resp->command != HostCmd_CMD_WMM_PARAM_CONFIG ||
+ resp->command != HostCmd_CMD_CHAN_REGION_CFG)
+ PRINTM(MERROR, "CMD_RESP: cmd %#x error, result=%#x\n",
+ resp->command, resp->result);
+ if (pioctl_buf)
+ pioctl_buf->status_code = resp->result;
+ /*
+ * Handling errors here
+ */
+ switch (resp->command) {
+#ifdef SDIO
+ case HostCmd_CMD_SDIO_SP_RX_AGGR_CFG:
+ pmadapter->pcard_sd->sdio_rx_aggr_enable = MFALSE;
+ PRINTM(MMSG, "FW don't support SDIO single port rx aggr\n");
+ break;
+#endif
+
+ case HOST_CMD_APCMD_SYS_CONFIGURE: {
+ HostCmd_DS_SYS_CONFIG *sys_config =
+ (HostCmd_DS_SYS_CONFIG *)&resp->params.sys_config;
+ t_u16 resp_len = 0, travel_len = 0, index;
+ mlan_ds_misc_custom_ie *cust_ie = MNULL;
+ mlan_ds_misc_cfg *misc = MNULL;
+ custom_ie *cptr;
+
+ if (!pioctl_buf || (pioctl_buf->req_id != MLAN_IOCTL_MISC_CFG))
+ break;
+ misc = (mlan_ds_misc_cfg *)pioctl_buf->pbuf;
+ if ((pioctl_buf->action == MLAN_ACT_SET) &&
+ (misc->sub_command == MLAN_OID_MISC_CUSTOM_IE)) {
+ cust_ie = (mlan_ds_misc_custom_ie *)
+ sys_config->tlv_buffer;
+ if (cust_ie) {
+ cust_ie->type = wlan_le16_to_cpu(cust_ie->type);
+ resp_len = cust_ie->len =
+ wlan_le16_to_cpu(cust_ie->len);
+ travel_len = 0;
+ /* conversion for index, mask, len */
+ if (resp_len == sizeof(t_u16))
+ cust_ie->ie_data_list[0].ie_index =
+ wlan_cpu_to_le16(
+ cust_ie->ie_data_list[0]
+ .ie_index);
+
+ while (resp_len > sizeof(t_u16)) {
+ cptr = (custom_ie
+ *)(((t_u8 *)cust_ie
+ ->ie_data_list) +
+ travel_len);
+ index = cptr->ie_index =
+ wlan_le16_to_cpu(
+ cptr->ie_index);
+ cptr->mgmt_subtype_mask =
+ wlan_le16_to_cpu(
+ cptr->mgmt_subtype_mask);
+ cptr->ie_length = wlan_le16_to_cpu(
+ cptr->ie_length);
+ travel_len += cptr->ie_length +
+ sizeof(custom_ie) -
+ MAX_IE_SIZE;
+ resp_len -= cptr->ie_length +
+ sizeof(custom_ie) -
+ MAX_IE_SIZE;
+ if ((pmpriv->mgmt_ie[index]
+ .mgmt_subtype_mask ==
+ cptr->mgmt_subtype_mask) &&
+ (pmpriv->mgmt_ie[index].ie_length ==
+ cptr->ie_length) &&
+ !memcmp(pmpriv->adapter,
+ pmpriv->mgmt_ie[index]
+ .ie_buffer,
+ cptr->ie_buffer,
+ cptr->ie_length)) {
+ PRINTM(MERROR,
+ "set custom ie fail, remove ie index :%d\n",
+ index);
+ memset(pmadapter,
+ &pmpriv->mgmt_ie[index],
+ 0, sizeof(custom_ie));
+ }
+ }
+ }
+ }
+ } break;
+ case HostCmd_CMD_PACKET_AGGR_CTRL:
+#ifdef USB
+ if (IS_USB(pmadapter->card_type)) {
+ for (i = 0; i < MAX_USB_TX_PORT_NUM; i++)
+ pmadapter->pcard_usb->usb_tx_aggr[i]
+ .aggr_ctrl.enable = MFALSE;
+ pmadapter->pcard_usb->usb_rx_deaggr.aggr_ctrl.enable =
+ MFALSE;
+ }
+#endif
+ break;
+ case HostCmd_CMD_CHAN_REGION_CFG:
+ ret = MLAN_STATUS_SUCCESS;
+ PRINTM(MCMND, "FW don't support chan region cfg command!\n");
+ break;
+#if defined(DRV_EMBEDDED_AUTHENTICATOR)
+ case HostCmd_CMD_CRYPTO:
+ PRINTM(MCMND, "crypto cmd result=0x%x!\n", resp->result);
+ ret = wlan_ret_crypto(pmpriv, resp, pioctl_buf);
+ break;
+#endif
+ default:
+ break;
+ }
+
+ wlan_request_cmd_lock(pmadapter);
+ wlan_insert_cmd_to_free_q(pmadapter, pmadapter->curr_cmd);
+ pmadapter->curr_cmd = MNULL;
+ wlan_release_cmd_lock(pmadapter);
+
+ LEAVE();
+ return ret;
+}
+
+/**
+ * @brief This function will return the pointer to station entry in station
+ * list table which matches the give mac address
+ *
+ * @param priv A pointer to mlan_private
+ *
+ * @return A pointer to structure sta_node
+ */
+void wlan_notify_station_deauth(mlan_private *priv)
+{
+ sta_node *sta_ptr;
+ t_u8 event_buf[100];
+ mlan_event *pevent = (mlan_event *)event_buf;
+ t_u8 *pbuf;
+
+ ENTER();
+ sta_ptr = (sta_node *)util_peek_list(
+ priv->adapter->pmoal_handle, &priv->sta_list,
+ priv->adapter->callbacks.moal_spin_lock,
+ priv->adapter->callbacks.moal_spin_unlock);
+ if (!sta_ptr) {
+ LEAVE();
+ return;
+ }
+ while (sta_ptr != (sta_node *)&priv->sta_list) {
+ memset(priv->adapter, event_buf, 0, sizeof(event_buf));
+ pevent->bss_index = priv->bss_index;
+ pevent->event_id = MLAN_EVENT_ID_UAP_FW_STA_DISCONNECT;
+ pevent->event_len = MLAN_MAC_ADDR_LENGTH + 2;
+ pbuf = (t_u8 *)pevent->event_buf;
+ /* reason field set to 0, Unspecified */
+ memcpy_ext(priv->adapter, pbuf + 2, sta_ptr->mac_addr,
+ MLAN_MAC_ADDR_LENGTH, MLAN_MAC_ADDR_LENGTH);
+ wlan_recv_event(priv, pevent->event_id, pevent);
+ sta_ptr = sta_ptr->pnext;
+ }
+ LEAVE();
+ return;
+}
+
+/**
+ * @brief This function prepares command of hs_cfg.
+ *
+ * @param pmpriv A pointer to mlan_private structure
+ * @param cmd A pointer to HostCmd_DS_COMMAND structure
+ * @param cmd_action The action: GET or SET
+ * @param pdata_buf A pointer to data buffer
+ *
+ * @return MLAN_STATUS_SUCCESS
+ */
+static mlan_status wlan_uap_cmd_802_11_hs_cfg(pmlan_private pmpriv,
+ HostCmd_DS_COMMAND *cmd,
+ t_u16 cmd_action,
+ hs_config_param *pdata_buf)
+{
+ pmlan_adapter pmadapter = pmpriv->adapter;
+ HostCmd_DS_802_11_HS_CFG_ENH *phs_cfg =
+ (HostCmd_DS_802_11_HS_CFG_ENH *)&(cmd->params.opt_hs_cfg);
+ t_u8 *tlv = (t_u8 *)phs_cfg + sizeof(HostCmd_DS_802_11_HS_CFG_ENH);
+ MrvlIEtypes_HsWakeHoldoff_t *holdoff_tlv = MNULL;
+ MrvlIEtypes_HS_Antmode_t *antmode_tlv = MNULL;
+ MrvlIEtypes_WakeupSourceGPIO_t *gpio_tlv = MNULL;
+ MrvlIEtypes_MgmtFrameFilter_t *mgmt_filter_tlv = MNULL;
+ MrvlIEtypes_WakeupExtend_t *ext_tlv = MNULL;
+
+ ENTER();
+ cmd->command = wlan_cpu_to_le16(HostCmd_CMD_802_11_HS_CFG_ENH);
+ cmd->size = wlan_cpu_to_le16(S_DS_GEN +
+ sizeof(HostCmd_DS_802_11_HS_CFG_ENH));
+
+ if (pdata_buf == MNULL) {
+ phs_cfg->action = wlan_cpu_to_le16(HS_ACTIVATE);
+ phs_cfg->params.hs_activate.resp_ctrl =
+ wlan_cpu_to_le16(RESP_NEEDED);
+ } else {
+ phs_cfg->action = wlan_cpu_to_le16(HS_CONFIGURE);
+ phs_cfg->params.hs_config.conditions =
+ wlan_cpu_to_le32(pdata_buf->conditions);
+ phs_cfg->params.hs_config.gpio = pdata_buf->gpio;
+ phs_cfg->params.hs_config.gap = pdata_buf->gap;
+ if (pmpriv->adapter->min_wake_holdoff) {
+ cmd->size = wlan_cpu_to_le16(
+ S_DS_GEN +
+ sizeof(HostCmd_DS_802_11_HS_CFG_ENH) +
+ sizeof(MrvlIEtypes_HsWakeHoldoff_t));
+ holdoff_tlv = (MrvlIEtypes_HsWakeHoldoff_t *)tlv;
+ holdoff_tlv->header.type =
+ wlan_cpu_to_le16(TLV_TYPE_HS_WAKE_HOLDOFF);
+ holdoff_tlv->header.len = wlan_cpu_to_le16(
+ sizeof(MrvlIEtypes_HsWakeHoldoff_t) -
+ sizeof(MrvlIEtypesHeader_t));
+ holdoff_tlv->min_wake_holdoff = wlan_cpu_to_le16(
+ pmpriv->adapter->min_wake_holdoff);
+ tlv += sizeof(MrvlIEtypes_HsWakeHoldoff_t);
+ }
+ PRINTM(MCMND,
+ "HS_CFG_CMD: condition:0x%x gpio:0x%x gap:0x%x holdoff=%d\n",
+ phs_cfg->params.hs_config.conditions,
+ phs_cfg->params.hs_config.gpio,
+ phs_cfg->params.hs_config.gap,
+ pmpriv->adapter->min_wake_holdoff);
+
+ if (pmadapter->param_type_ind == 1) {
+ cmd->size += sizeof(MrvlIEtypes_WakeupSourceGPIO_t);
+ gpio_tlv = (MrvlIEtypes_WakeupSourceGPIO_t *)tlv;
+ gpio_tlv->header.type = wlan_cpu_to_le16(
+ TLV_TYPE_HS_WAKEUP_SOURCE_GPIO);
+ gpio_tlv->header.len = wlan_cpu_to_le16(
+ sizeof(MrvlIEtypes_WakeupSourceGPIO_t) -
+ sizeof(MrvlIEtypesHeader_t));
+ gpio_tlv->ind_gpio = (t_u8)pmadapter->ind_gpio;
+ gpio_tlv->level = (t_u8)pmadapter->level;
+ tlv += sizeof(MrvlIEtypes_WakeupSourceGPIO_t);
+ }
+ if (pmadapter->param_type_ext == 2) {
+ cmd->size += sizeof(MrvlIEtypes_WakeupExtend_t);
+ ext_tlv = (MrvlIEtypes_WakeupExtend_t *)tlv;
+ ext_tlv->header.type =
+ wlan_cpu_to_le16(TLV_TYPE_WAKEUP_EXTEND);
+ ext_tlv->header.len = wlan_cpu_to_le16(
+ sizeof(MrvlIEtypes_WakeupExtend_t) -
+ sizeof(MrvlIEtypesHeader_t));
+ ext_tlv->event_force_ignore =
+ wlan_cpu_to_le32(pmadapter->event_force_ignore);
+ ext_tlv->event_use_ext_gap =
+ wlan_cpu_to_le32(pmadapter->event_use_ext_gap);
+ ext_tlv->ext_gap = pmadapter->ext_gap;
+ ext_tlv->gpio_wave = pmadapter->gpio_wave;
+ tlv += sizeof(MrvlIEtypes_WakeupExtend_t);
+ }
+ if (pmadapter->mgmt_filter[0].type) {
+ int i = 0;
+ mgmt_frame_filter mgmt_filter[MAX_MGMT_FRAME_FILTER];
+ memset(pmadapter, mgmt_filter, 0,
+ MAX_MGMT_FRAME_FILTER *
+ sizeof(mgmt_frame_filter));
+ mgmt_filter_tlv = (MrvlIEtypes_MgmtFrameFilter_t *)tlv;
+ mgmt_filter_tlv->header.type =
+ wlan_cpu_to_le16(TLV_TYPE_MGMT_FRAME_WAKEUP);
+ tlv += sizeof(MrvlIEtypesHeader_t);
+ while (i < MAX_MGMT_FRAME_FILTER &&
+ pmadapter->mgmt_filter[i].type) {
+ mgmt_filter[i].action =
+ (t_u8)pmadapter->mgmt_filter[i].action;
+ mgmt_filter[i].type =
+ (t_u8)pmadapter->mgmt_filter[i].type;
+ mgmt_filter[i].frame_mask = wlan_cpu_to_le32(
+ pmadapter->mgmt_filter[i].frame_mask);
+ i++;
+ }
+ memcpy_ext(pmadapter, (t_u8 *)mgmt_filter_tlv->filter,
+ (t_u8 *)mgmt_filter,
+ i * sizeof(mgmt_frame_filter),
+ sizeof(mgmt_filter_tlv->filter));
+ tlv += i * sizeof(mgmt_frame_filter);
+ mgmt_filter_tlv->header.len =
+ wlan_cpu_to_le16(i * sizeof(mgmt_frame_filter));
+ cmd->size += i * sizeof(mgmt_frame_filter) +
+ sizeof(MrvlIEtypesHeader_t);
+ }
+ if (pmadapter->hs_mimo_switch) {
+ cmd->size += sizeof(MrvlIEtypes_HS_Antmode_t);
+ antmode_tlv = (MrvlIEtypes_HS_Antmode_t *)tlv;
+ antmode_tlv->header.type =
+ wlan_cpu_to_le16(TLV_TYPE_HS_ANTMODE);
+ antmode_tlv->header.len = wlan_cpu_to_le16(
+ sizeof(MrvlIEtypes_HS_Antmode_t) -
+ sizeof(MrvlIEtypesHeader_t));
+ antmode_tlv->txpath_antmode = ANTMODE_FW_DECISION;
+ antmode_tlv->rxpath_antmode = ANTMODE_FW_DECISION;
+ tlv += sizeof(MrvlIEtypes_HS_Antmode_t);
+ PRINTM(MCMND,
+ "hs_mimo_switch=%d, txpath_antmode=%d, rxpath_antmode=%d\n",
+ pmadapter->hs_mimo_switch,
+ antmode_tlv->txpath_antmode,
+ antmode_tlv->rxpath_antmode);
+ }
+ }
+ LEAVE();
+ return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ * @brief This function prepares command of Tx data pause
+ *
+ * @param pmpriv A pointer to mlan_private structure
+ * @param cmd A pointer to HostCmd_DS_COMMAND structure
+ * @param cmd_action the action: GET or SET
+ * @param pdata_buf A pointer to data buffer
+ * @return MLAN_STATUS_SUCCESS
+ */
+static mlan_status wlan_uap_cmd_txdatapause(pmlan_private pmpriv,
+ HostCmd_DS_COMMAND *cmd,
+ t_u16 cmd_action, t_void *pdata_buf)
+{
+ HostCmd_DS_CMD_TX_DATA_PAUSE *pause_cmd =
+ (HostCmd_DS_CMD_TX_DATA_PAUSE *)&cmd->params.tx_data_pause;
+ mlan_ds_misc_tx_datapause *data_pause =
+ (mlan_ds_misc_tx_datapause *)pdata_buf;
+
+ ENTER();
+
+ cmd->command = wlan_cpu_to_le16(HostCmd_CMD_CFG_TX_DATA_PAUSE);
+ cmd->size = wlan_cpu_to_le16(sizeof(HostCmd_DS_CMD_TX_DATA_PAUSE) +
+ S_DS_GEN);
+ pause_cmd->action = wlan_cpu_to_le16(cmd_action);
+
+ if (cmd_action == HostCmd_ACT_GEN_SET) {
+ pause_cmd->enable_tx_pause = (t_u8)data_pause->tx_pause;
+ pause_cmd->pause_tx_count = (t_u8)data_pause->tx_buf_cnt;
+ }
+
+ LEAVE();
+ return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ * @brief This function handles the command response of Tx data pause
+ *
+ * @param pmpriv A pointer to mlan_private structure
+ * @param resp A pointer to HostCmd_DS_COMMAND
+ * @param pioctl_buf A pointer to mlan_ioctl_req structure
+ *
+ * @return MLAN_STATUS_SUCCESS
+ */
+static mlan_status wlan_uap_ret_txdatapause(pmlan_private pmpriv,
+ HostCmd_DS_COMMAND *resp,
+ mlan_ioctl_req *pioctl_buf)
+{
+ HostCmd_DS_CMD_TX_DATA_PAUSE *pause_cmd =
+ (HostCmd_DS_CMD_TX_DATA_PAUSE *)&resp->params.tx_data_pause;
+ mlan_ds_misc_cfg *misc_cfg = MNULL;
+
+ ENTER();
+
+ if (pioctl_buf) {
+ misc_cfg = (mlan_ds_misc_cfg *)pioctl_buf->pbuf;
+ misc_cfg->param.tx_datapause.tx_pause =
+ pause_cmd->enable_tx_pause;
+ misc_cfg->param.tx_datapause.tx_buf_cnt =
+ pause_cmd->pause_tx_count;
+ }
+ LEAVE();
+ return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ * @brief This function will process tx pause event
+ *
+ * @param priv A pointer to mlan_private
+ * @param pevent A pointer to event buf
+ *
+ * @return N/A
+ */
+static void wlan_process_tx_pause_event(pmlan_private priv, pmlan_buffer pevent)
+{
+ t_u16 tlv_type, tlv_len;
+ int tlv_buf_left = pevent->data_len - sizeof(t_u32);
+ MrvlIEtypesHeader_t *tlv =
+ (MrvlIEtypesHeader_t *)(pevent->pbuf + pevent->data_offset +
+ sizeof(t_u32));
+ MrvlIEtypes_tx_pause_t *tx_pause_tlv;
+ sta_node *sta_ptr = MNULL;
+ t_u8 bc_mac[] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
+ t_u32 total_pkts_queued;
+ t_u16 tx_pkts_queued = 0;
+ ;
+
+ ENTER();
+
+ total_pkts_queued =
+ util_scalar_read(priv->adapter->pmoal_handle,
+ &priv->wmm.tx_pkts_queued, MNULL, MNULL);
+ while (tlv_buf_left >= (int)sizeof(MrvlIEtypesHeader_t)) {
+ tlv_type = wlan_le16_to_cpu(tlv->type);
+ tlv_len = wlan_le16_to_cpu(tlv->len);
+ if ((sizeof(MrvlIEtypesHeader_t) + tlv_len) >
+ (unsigned int)tlv_buf_left) {
+ PRINTM(MERROR, "wrong tlv: tlvLen=%d, tlvBufLeft=%d\n",
+ tlv_len, tlv_buf_left);
+ break;
+ }
+ if (tlv_type == TLV_TYPE_TX_PAUSE) {
+ tx_pause_tlv = (MrvlIEtypes_tx_pause_t *)tlv;
+
+ if (!memcmp(priv->adapter, bc_mac,
+ tx_pause_tlv->peermac,
+ MLAN_MAC_ADDR_LENGTH))
+ tx_pkts_queued = wlan_update_ralist_tx_pause(
+ priv, tx_pause_tlv->peermac,
+ tx_pause_tlv->tx_pause);
+ else if (!memcmp(priv->adapter, priv->curr_addr,
+ tx_pause_tlv->peermac,
+ MLAN_MAC_ADDR_LENGTH)) {
+ if (tx_pause_tlv->tx_pause)
+ priv->tx_pause = MTRUE;
+ else
+ priv->tx_pause = MFALSE;
+ } else {
+ sta_ptr = wlan_get_station_entry(
+ priv, tx_pause_tlv->peermac);
+ if (sta_ptr) {
+ if (sta_ptr->tx_pause !=
+ tx_pause_tlv->tx_pause) {
+ sta_ptr->tx_pause =
+ tx_pause_tlv->tx_pause;
+ tx_pkts_queued =
+ wlan_update_ralist_tx_pause(
+ priv,
+ tx_pause_tlv
+ ->peermac,
+ tx_pause_tlv
+ ->tx_pause);
+ }
+ }
+ }
+ if (!tx_pause_tlv->tx_pause)
+ total_pkts_queued += tx_pkts_queued;
+ PRINTM(MCMND,
+ "TxPause: " MACSTR
+ " pause=%d, pkts=%d pending=%d total=%d\n",
+ MAC2STR(tx_pause_tlv->peermac),
+ tx_pause_tlv->tx_pause, tx_pause_tlv->pkt_cnt,
+ tx_pkts_queued, total_pkts_queued);
+ }
+ tlv_buf_left -= (sizeof(MrvlIEtypesHeader_t) + tlv_len);
+ tlv = (MrvlIEtypesHeader_t *)((t_u8 *)tlv + tlv_len +
+ sizeof(MrvlIEtypesHeader_t));
+ }
+
+ LEAVE();
+ return;
+}
+
+/**
+ * @brief This function prepares command for config uap settings
+ *
+ * @param pmpriv A pointer to mlan_private structure
+ * @param cmd A pointer to HostCmd_DS_COMMAND structure
+ * @param cmd_action the action: GET or SET
+ * @param pioctl_buf A pointer to mlan_ioctl_req structure
+ * @return MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ */
+static mlan_status wlan_uap_cmd_ap_config(pmlan_private pmpriv,
+ HostCmd_DS_COMMAND *cmd,
+ t_u16 cmd_action,
+ pmlan_ioctl_req pioctl_buf)
+{
+ mlan_ds_bss *bss = MNULL;
+ HostCmd_DS_SYS_CONFIG *sys_config =
+ (HostCmd_DS_SYS_CONFIG *)&cmd->params.sys_config;
+ t_u8 *tlv = MNULL;
+ MrvlIEtypes_MacAddr_t *tlv_mac = MNULL;
+ MrvlIEtypes_SsIdParamSet_t *tlv_ssid = MNULL;
+ MrvlIEtypes_beacon_period_t *tlv_beacon_period = MNULL;
+ MrvlIEtypes_dtim_period_t *tlv_dtim_period = MNULL;
+ MrvlIEtypes_RatesParamSet_t *tlv_rates = MNULL;
+ MrvlIEtypes_tx_rate_t *tlv_txrate = MNULL;
+ MrvlIEtypes_mcbc_rate_t *tlv_mcbc_rate = MNULL;
+ MrvlIEtypes_tx_power_t *tlv_tx_power = MNULL;
+ MrvlIEtypes_bcast_ssid_t *tlv_bcast_ssid = MNULL;
+ MrvlIEtypes_antenna_mode_t *tlv_antenna = MNULL;
+ MrvlIEtypes_pkt_forward_t *tlv_pkt_forward = MNULL;
+ MrvlIEtypes_max_sta_count_t *tlv_sta_count = MNULL;
+ MrvlIEtypes_sta_ageout_t *tlv_sta_ageout = MNULL;
+ MrvlIEtypes_ps_sta_ageout_t *tlv_ps_sta_ageout = MNULL;
+ MrvlIEtypes_rts_threshold_t *tlv_rts_threshold = MNULL;
+ MrvlIEtypes_frag_threshold_t *tlv_frag_threshold = MNULL;
+ MrvlIEtypes_retry_limit_t *tlv_retry_limit = MNULL;
+ MrvlIEtypes_eapol_pwk_hsk_timeout_t *tlv_pairwise_timeout = MNULL;
+ MrvlIEtypes_eapol_pwk_hsk_retries_t *tlv_pairwise_retries = MNULL;
+ MrvlIEtypes_eapol_gwk_hsk_timeout_t *tlv_groupwise_timeout = MNULL;
+ MrvlIEtypes_eapol_gwk_hsk_retries_t *tlv_groupwise_retries = MNULL;
+ MrvlIEtypes_mgmt_ie_passthru_t *tlv_mgmt_ie_passthru = MNULL;
+ MrvlIEtypes_2040_coex_enable_t *tlv_2040_coex_enable = MNULL;
+ MrvlIEtypes_mac_filter_t *tlv_mac_filter = MNULL;
+ MrvlIEtypes_channel_band_t *tlv_chan_band = MNULL;
+ MrvlIEtypes_ChanListParamSet_t *tlv_chan_list = MNULL;
+ ChanScanParamSet_t *pscan_chan = MNULL;
+ MrvlIEtypes_auth_type_t *tlv_auth_type = MNULL;
+ MrvlIEtypes_encrypt_protocol_t *tlv_encrypt_protocol = MNULL;
+ MrvlIEtypes_akmp_t *tlv_akmp = MNULL;
+ MrvlIEtypes_pwk_cipher_t *tlv_pwk_cipher = MNULL;
+ MrvlIEtypes_gwk_cipher_t *tlv_gwk_cipher = MNULL;
+ MrvlIEtypes_rsn_replay_prot_t *tlv_rsn_prot = MNULL;
+ MrvlIEtypes_passphrase_t *tlv_passphrase = MNULL;
+ MrvlIEtypes_group_rekey_time_t *tlv_rekey_time = MNULL;
+ MrvlIEtypes_wep_key_t *tlv_wep_key = MNULL;
+ MrvlIETypes_HTCap_t *tlv_htcap = MNULL;
+ MrvlIEtypes_wmm_parameter_t *tlv_wmm_parameter = MNULL;
+ MrvlIEtypes_preamble_t *tlv_preamble = MNULL;
+
+ t_u32 cmd_size = 0;
+ t_u8 zero_mac[] = {0, 0, 0, 0, 0, 0};
+ t_u16 i;
+ t_u16 ac;
+#if defined(PCIE9098) || defined(SD9098) || defined(USB9098) || \
+ defined(PCIE9097) || defined(SD9097) || defined(USB9097)
+ int rx_mcs_supp = 0;
+#endif
+
+ ENTER();
+ if (pioctl_buf == MNULL) {
+ LEAVE();
+ return MLAN_STATUS_FAILURE;
+ }
+
+ bss = (mlan_ds_bss *)pioctl_buf->pbuf;
+
+ cmd->command = wlan_cpu_to_le16(HOST_CMD_APCMD_SYS_CONFIGURE);
+ sys_config->action = wlan_cpu_to_le16(cmd_action);
+ cmd_size = sizeof(HostCmd_DS_SYS_CONFIG) - 1 + S_DS_GEN;
+
+ tlv = (t_u8 *)sys_config->tlv_buffer;
+ if (memcmp(pmpriv->adapter, zero_mac, &bss->param.bss_config.mac_addr,
+ MLAN_MAC_ADDR_LENGTH)) {
+ tlv_mac = (MrvlIEtypes_MacAddr_t *)tlv;
+ tlv_mac->header.type =
+ wlan_cpu_to_le16(TLV_TYPE_UAP_MAC_ADDRESS);
+ tlv_mac->header.len = wlan_cpu_to_le16(MLAN_MAC_ADDR_LENGTH);
+ memcpy_ext(pmpriv->adapter, tlv_mac->mac,
+ &bss->param.bss_config.mac_addr,
+ MLAN_MAC_ADDR_LENGTH, MLAN_MAC_ADDR_LENGTH);
+ cmd_size += sizeof(MrvlIEtypes_MacAddr_t);
+ tlv += sizeof(MrvlIEtypes_MacAddr_t);
+ }
+
+ if (bss->param.bss_config.bandcfg.scanMode == SCAN_MODE_ACS) {
+ /* ACS is not allowed when DFS repeater mode is on */
+ if (pmpriv->adapter->dfs_repeater) {
+ PRINTM(MERROR, "ACS is not allowed when"
+ "DFS repeater mode is on.\n");
+ return MLAN_STATUS_FAILURE;
+ }
+ }
+
+ if (bss->param.bss_config.ssid.ssid_len) {
+ tlv_ssid = (MrvlIEtypes_SsIdParamSet_t *)tlv;
+ tlv_ssid->header.type = wlan_cpu_to_le16(TLV_TYPE_SSID);
+ tlv_ssid->header.len = wlan_cpu_to_le16(
+ (t_u16)bss->param.bss_config.ssid.ssid_len);
+ memcpy_ext(pmpriv->adapter, tlv_ssid->ssid,
+ bss->param.bss_config.ssid.ssid,
+ bss->param.bss_config.ssid.ssid_len,
+ MLAN_MAX_SSID_LENGTH);
+ cmd_size += sizeof(MrvlIEtypesHeader_t) +
+ bss->param.bss_config.ssid.ssid_len;
+ tlv += sizeof(MrvlIEtypesHeader_t) +
+ bss->param.bss_config.ssid.ssid_len;
+ }
+
+ if ((bss->param.bss_config.beacon_period >= MIN_BEACON_PERIOD) &&
+ (bss->param.bss_config.beacon_period <= MAX_BEACON_PERIOD)) {
+ tlv_beacon_period = (MrvlIEtypes_beacon_period_t *)tlv;
+ tlv_beacon_period->header.type =
+ wlan_cpu_to_le16(TLV_TYPE_UAP_BEACON_PERIOD);
+ tlv_beacon_period->header.len = wlan_cpu_to_le16(sizeof(t_u16));
+ tlv_beacon_period->beacon_period =
+ wlan_cpu_to_le16(bss->param.bss_config.beacon_period);
+ cmd_size += sizeof(MrvlIEtypes_beacon_period_t);
+ tlv += sizeof(MrvlIEtypes_beacon_period_t);
+ }
+
+ if ((bss->param.bss_config.dtim_period >= MIN_DTIM_PERIOD) &&
+ (bss->param.bss_config.dtim_period <= MAX_DTIM_PERIOD)) {
+ tlv_dtim_period = (MrvlIEtypes_dtim_period_t *)tlv;
+ tlv_dtim_period->header.type =
+ wlan_cpu_to_le16(TLV_TYPE_UAP_DTIM_PERIOD);
+ tlv_dtim_period->header.len = wlan_cpu_to_le16(sizeof(t_u8));
+ tlv_dtim_period->dtim_period =
+ bss->param.bss_config.dtim_period;
+ cmd_size += sizeof(MrvlIEtypes_dtim_period_t);
+ tlv += sizeof(MrvlIEtypes_dtim_period_t);
+ }
+
+ if (bss->param.bss_config.rates[0]) {
+ tlv_rates = (MrvlIEtypes_RatesParamSet_t *)tlv;
+ tlv_rates->header.type = wlan_cpu_to_le16(TLV_TYPE_RATES);
+ for (i = 0;
+ i < MAX_DATA_RATES && bss->param.bss_config.rates[i];
+ i++) {
+ tlv_rates->rates[i] = bss->param.bss_config.rates[i];
+ }
+ tlv_rates->header.len = wlan_cpu_to_le16(i);
+ cmd_size += sizeof(MrvlIEtypesHeader_t) + i;
+ tlv += sizeof(MrvlIEtypesHeader_t) + i;
+ }
+
+ if (bss->param.bss_config.tx_data_rate <= DATA_RATE_54M) {
+ tlv_txrate = (MrvlIEtypes_tx_rate_t *)tlv;
+ tlv_txrate->header.type =
+ wlan_cpu_to_le16(TLV_TYPE_UAP_TX_DATA_RATE);
+ tlv_txrate->header.len = wlan_cpu_to_le16(sizeof(t_u16));
+ tlv_txrate->tx_data_rate =
+ wlan_cpu_to_le16(bss->param.bss_config.tx_data_rate);
+ cmd_size += sizeof(MrvlIEtypes_tx_rate_t);
+ tlv += sizeof(MrvlIEtypes_tx_rate_t);
+ }
+
+ if (bss->param.bss_config.tx_beacon_rate <= DATA_RATE_54M) {
+ tlv_txrate = (MrvlIEtypes_tx_rate_t *)tlv;
+ tlv_txrate->header.type =
+ wlan_cpu_to_le16(TLV_TYPE_UAP_TX_BEACON_RATE);
+ tlv_txrate->header.len = wlan_cpu_to_le16(sizeof(t_u16));
+ tlv_txrate->tx_data_rate =
+ wlan_cpu_to_le16(bss->param.bss_config.tx_beacon_rate);
+ cmd_size += sizeof(MrvlIEtypes_tx_rate_t);
+ tlv += sizeof(MrvlIEtypes_tx_rate_t);
+ }
+
+ if (bss->param.bss_config.mcbc_data_rate <= DATA_RATE_54M) {
+ tlv_mcbc_rate = (MrvlIEtypes_mcbc_rate_t *)tlv;
+ tlv_mcbc_rate->header.type =
+ wlan_cpu_to_le16(TLV_TYPE_UAP_MCBC_DATA_RATE);
+ tlv_mcbc_rate->header.len = wlan_cpu_to_le16(sizeof(t_u16));
+ tlv_mcbc_rate->mcbc_data_rate =
+ wlan_cpu_to_le16(bss->param.bss_config.mcbc_data_rate);
+ cmd_size += sizeof(MrvlIEtypes_mcbc_rate_t);
+ tlv += sizeof(MrvlIEtypes_mcbc_rate_t);
+ }
+
+ if (bss->param.bss_config.tx_power_level <= MAX_TX_POWER) {
+ tlv_tx_power = (MrvlIEtypes_tx_power_t *)tlv;
+ tlv_tx_power->header.type =
+ wlan_cpu_to_le16(TLV_TYPE_UAP_TX_POWER);
+ tlv_tx_power->header.len = wlan_cpu_to_le16(sizeof(t_u8));
+ tlv_tx_power->tx_power = bss->param.bss_config.tx_power_level;
+ cmd_size += sizeof(MrvlIEtypes_tx_power_t);
+ tlv += sizeof(MrvlIEtypes_tx_power_t);
+ }
+
+ if (bss->param.bss_config.bcast_ssid_ctl <= MAX_BCAST_SSID_CTL) {
+ tlv_bcast_ssid = (MrvlIEtypes_bcast_ssid_t *)tlv;
+ tlv_bcast_ssid->header.type =
+ wlan_cpu_to_le16(TLV_TYPE_UAP_BCAST_SSID_CTL);
+ tlv_bcast_ssid->header.len = wlan_cpu_to_le16(sizeof(t_u8));
+ tlv_bcast_ssid->bcast_ssid_ctl =
+ bss->param.bss_config.bcast_ssid_ctl;
+ cmd_size += sizeof(MrvlIEtypes_bcast_ssid_t);
+ tlv += sizeof(MrvlIEtypes_bcast_ssid_t);
+ }
+
+ if ((bss->param.bss_config.tx_antenna == ANTENNA_MODE_A) ||
+ (bss->param.bss_config.tx_antenna == ANTENNA_MODE_B)) {
+ tlv_antenna = (MrvlIEtypes_antenna_mode_t *)tlv;
+ tlv_antenna->header.type =
+ wlan_cpu_to_le16(TLV_TYPE_UAP_ANTENNA_CTL);
+ tlv_antenna->header.len =
+ wlan_cpu_to_le16(sizeof(t_u8) + sizeof(t_u8));
+ tlv_antenna->which_antenna = TX_ANTENNA;
+ tlv_antenna->antenna_mode = bss->param.bss_config.tx_antenna;
+ cmd_size += sizeof(MrvlIEtypes_antenna_mode_t);
+ tlv += sizeof(MrvlIEtypes_antenna_mode_t);
+ }
+
+ if ((bss->param.bss_config.rx_antenna == ANTENNA_MODE_A) ||
+ (bss->param.bss_config.rx_antenna == ANTENNA_MODE_B)) {
+ tlv_antenna = (MrvlIEtypes_antenna_mode_t *)tlv;
+ tlv_antenna->header.type =
+ wlan_cpu_to_le16(TLV_TYPE_UAP_ANTENNA_CTL);
+ tlv_antenna->header.len =
+ wlan_cpu_to_le16(sizeof(t_u8) + sizeof(t_u8));
+ tlv_antenna->which_antenna = RX_ANTENNA;
+ tlv_antenna->antenna_mode = bss->param.bss_config.rx_antenna;
+ cmd_size += sizeof(MrvlIEtypes_antenna_mode_t);
+ tlv += sizeof(MrvlIEtypes_antenna_mode_t);
+ }
+
+ if (bss->param.bss_config.pkt_forward_ctl <= MAX_PKT_FWD_CTRL) {
+ tlv_pkt_forward = (MrvlIEtypes_pkt_forward_t *)tlv;
+ tlv_pkt_forward->header.type =
+ wlan_cpu_to_le16(TLV_TYPE_UAP_PKT_FWD_CTL);
+ tlv_pkt_forward->header.len = wlan_cpu_to_le16(sizeof(t_u8));
+ tlv_pkt_forward->pkt_forward_ctl =
+ bss->param.bss_config.pkt_forward_ctl;
+ cmd_size += sizeof(MrvlIEtypes_pkt_forward_t);
+ tlv += sizeof(MrvlIEtypes_pkt_forward_t);
+ }
+
+ if (bss->param.bss_config.max_sta_count <= MAX_STA_COUNT) {
+ tlv_sta_count = (MrvlIEtypes_max_sta_count_t *)tlv;
+ tlv_sta_count->header.type =
+ wlan_cpu_to_le16(TLV_TYPE_UAP_MAX_STA_CNT);
+ tlv_sta_count->header.len = wlan_cpu_to_le16(sizeof(t_u16));
+ tlv_sta_count->max_sta_count =
+ wlan_cpu_to_le16(bss->param.bss_config.max_sta_count);
+ cmd_size += sizeof(MrvlIEtypes_max_sta_count_t);
+ tlv += sizeof(MrvlIEtypes_max_sta_count_t);
+ }
+
+ if (((bss->param.bss_config.sta_ageout_timer >= MIN_STAGE_OUT_TIME) &&
+ (bss->param.bss_config.sta_ageout_timer <= MAX_STAGE_OUT_TIME)) ||
+ (bss->param.bss_config.sta_ageout_timer == 0)) {
+ tlv_sta_ageout = (MrvlIEtypes_sta_ageout_t *)tlv;
+ tlv_sta_ageout->header.type =
+ wlan_cpu_to_le16(TLV_TYPE_UAP_STA_AGEOUT_TIMER);
+ tlv_sta_ageout->header.len = wlan_cpu_to_le16(sizeof(t_u32));
+ tlv_sta_ageout->sta_ageout_timer = wlan_cpu_to_le32(
+ bss->param.bss_config.sta_ageout_timer);
+ cmd_size += sizeof(MrvlIEtypes_sta_ageout_t);
+ tlv += sizeof(MrvlIEtypes_sta_ageout_t);
+ }
+
+ if (((bss->param.bss_config.ps_sta_ageout_timer >= MIN_STAGE_OUT_TIME) &&
+ (bss->param.bss_config.ps_sta_ageout_timer <=
+ MAX_STAGE_OUT_TIME)) ||
+ (bss->param.bss_config.ps_sta_ageout_timer == 0)) {
+ tlv_ps_sta_ageout = (MrvlIEtypes_ps_sta_ageout_t *)tlv;
+ tlv_ps_sta_ageout->header.type =
+ wlan_cpu_to_le16(TLV_TYPE_UAP_PS_STA_AGEOUT_TIMER);
+ tlv_ps_sta_ageout->header.len = wlan_cpu_to_le16(sizeof(t_u32));
+ tlv_ps_sta_ageout->ps_sta_ageout_timer = wlan_cpu_to_le32(
+ bss->param.bss_config.ps_sta_ageout_timer);
+ cmd_size += sizeof(MrvlIEtypes_ps_sta_ageout_t);
+ tlv += sizeof(MrvlIEtypes_ps_sta_ageout_t);
+ }
+ if (bss->param.bss_config.rts_threshold <= MAX_RTS_THRESHOLD) {
+ tlv_rts_threshold = (MrvlIEtypes_rts_threshold_t *)tlv;
+ tlv_rts_threshold->header.type =
+ wlan_cpu_to_le16(TLV_TYPE_UAP_RTS_THRESHOLD);
+ tlv_rts_threshold->header.len = wlan_cpu_to_le16(sizeof(t_u16));
+ tlv_rts_threshold->rts_threshold =
+ wlan_cpu_to_le16(bss->param.bss_config.rts_threshold);
+ cmd_size += sizeof(MrvlIEtypes_rts_threshold_t);
+ tlv += sizeof(MrvlIEtypes_rts_threshold_t);
+ }
+
+ if ((bss->param.bss_config.frag_threshold >= MIN_FRAG_THRESHOLD) &&
+ (bss->param.bss_config.frag_threshold <= MAX_FRAG_THRESHOLD)) {
+ tlv_frag_threshold = (MrvlIEtypes_frag_threshold_t *)tlv;
+ tlv_frag_threshold->header.type =
+ wlan_cpu_to_le16(TLV_TYPE_UAP_FRAG_THRESHOLD);
+ tlv_frag_threshold->header.len =
+ wlan_cpu_to_le16(sizeof(t_u16));
+ tlv_frag_threshold->frag_threshold =
+ wlan_cpu_to_le16(bss->param.bss_config.frag_threshold);
+ cmd_size += sizeof(MrvlIEtypes_frag_threshold_t);
+ tlv += sizeof(MrvlIEtypes_frag_threshold_t);
+ }
+
+ if (bss->param.bss_config.retry_limit <= MAX_RETRY_LIMIT) {
+ tlv_retry_limit = (MrvlIEtypes_retry_limit_t *)tlv;
+ tlv_retry_limit->header.type =
+ wlan_cpu_to_le16(TLV_TYPE_UAP_RETRY_LIMIT);
+ tlv_retry_limit->header.len = wlan_cpu_to_le16(sizeof(t_u8));
+ tlv_retry_limit->retry_limit =
+ (t_u8)bss->param.bss_config.retry_limit;
+ cmd_size += sizeof(MrvlIEtypes_retry_limit_t);
+ tlv += sizeof(MrvlIEtypes_retry_limit_t);
+ }
+
+#ifdef DRV_EMBEDDED_AUTHENTICATOR
+ if (IS_FW_SUPPORT_AUTHENTICATOR(pmpriv->adapter)) {
+#endif
+ if (bss->param.bss_config.pairwise_update_timeout <
+ (MAX_VALID_DWORD)) {
+ tlv_pairwise_timeout =
+ (MrvlIEtypes_eapol_pwk_hsk_timeout_t *)tlv;
+ tlv_pairwise_timeout->header.type = wlan_cpu_to_le16(
+ TLV_TYPE_UAP_EAPOL_PWK_HSK_TIMEOUT);
+ tlv_pairwise_timeout->header.len =
+ wlan_cpu_to_le16(sizeof(t_u32));
+ tlv_pairwise_timeout
+ ->pairwise_update_timeout = wlan_cpu_to_le32(
+ bss->param.bss_config.pairwise_update_timeout);
+ cmd_size += sizeof(MrvlIEtypes_eapol_pwk_hsk_timeout_t);
+ tlv += sizeof(MrvlIEtypes_eapol_pwk_hsk_timeout_t);
+ }
+
+ if (bss->param.bss_config.pwk_retries < (MAX_VALID_DWORD)) {
+ tlv_pairwise_retries =
+ (MrvlIEtypes_eapol_pwk_hsk_retries_t *)tlv;
+ tlv_pairwise_retries->header.type = wlan_cpu_to_le16(
+ TLV_TYPE_UAP_EAPOL_PWK_HSK_RETRIES);
+ tlv_pairwise_retries->header.len =
+ wlan_cpu_to_le16(sizeof(t_u32));
+ tlv_pairwise_retries->pwk_retries = wlan_cpu_to_le32(
+ bss->param.bss_config.pwk_retries);
+ cmd_size += sizeof(MrvlIEtypes_eapol_pwk_hsk_retries_t);
+ tlv += sizeof(MrvlIEtypes_eapol_pwk_hsk_retries_t);
+ }
+
+ if (bss->param.bss_config.groupwise_update_timeout <
+ (MAX_VALID_DWORD)) {
+ tlv_groupwise_timeout =
+ (MrvlIEtypes_eapol_gwk_hsk_timeout_t *)tlv;
+ tlv_groupwise_timeout->header.type = wlan_cpu_to_le16(
+ TLV_TYPE_UAP_EAPOL_GWK_HSK_TIMEOUT);
+ tlv_groupwise_timeout->header.len =
+ wlan_cpu_to_le16(sizeof(t_u32));
+ tlv_groupwise_timeout
+ ->groupwise_update_timeout = wlan_cpu_to_le32(
+ bss->param.bss_config.groupwise_update_timeout);
+ cmd_size += sizeof(MrvlIEtypes_eapol_gwk_hsk_timeout_t);
+ tlv += sizeof(MrvlIEtypes_eapol_gwk_hsk_timeout_t);
+ }
+
+ if (bss->param.bss_config.gwk_retries < (MAX_VALID_DWORD)) {
+ tlv_groupwise_retries =
+ (MrvlIEtypes_eapol_gwk_hsk_retries_t *)tlv;
+ tlv_groupwise_retries->header.type = wlan_cpu_to_le16(
+ TLV_TYPE_UAP_EAPOL_GWK_HSK_RETRIES);
+ tlv_groupwise_retries->header.len =
+ wlan_cpu_to_le16(sizeof(t_u32));
+ tlv_groupwise_retries->gwk_retries = wlan_cpu_to_le32(
+ bss->param.bss_config.gwk_retries);
+ cmd_size += sizeof(MrvlIEtypes_eapol_gwk_hsk_retries_t);
+ tlv += sizeof(MrvlIEtypes_eapol_gwk_hsk_retries_t);
+ }
+#ifdef DRV_EMBEDDED_AUTHENTICATOR
+ }
+#endif
+ if ((bss->param.bss_config.filter.filter_mode <=
+ MAC_FILTER_MODE_BLOCK_MAC) &&
+ (bss->param.bss_config.filter.mac_count <= MAX_MAC_FILTER_NUM)) {
+ tlv_mac_filter = (MrvlIEtypes_mac_filter_t *)tlv;
+ tlv_mac_filter->header.type =
+ wlan_cpu_to_le16(TLV_TYPE_UAP_STA_MAC_ADDR_FILTER);
+ tlv_mac_filter->header.len = wlan_cpu_to_le16(
+ 2 + MLAN_MAC_ADDR_LENGTH *
+ bss->param.bss_config.filter.mac_count);
+ tlv_mac_filter->count =
+ (t_u8)bss->param.bss_config.filter.mac_count;
+ tlv_mac_filter->filter_mode =
+ (t_u8)bss->param.bss_config.filter.filter_mode;
+ memcpy_ext(pmpriv->adapter, tlv_mac_filter->mac_address,
+ (t_u8 *)bss->param.bss_config.filter.mac_list,
+ MLAN_MAC_ADDR_LENGTH *
+ bss->param.bss_config.filter.mac_count,
+ MLAN_MAC_ADDR_LENGTH * MAX_MAC_FILTER_NUM);
+ cmd_size += sizeof(MrvlIEtypesHeader_t) + 2 +
+ MLAN_MAC_ADDR_LENGTH *
+ bss->param.bss_config.filter.mac_count;
+ tlv += sizeof(MrvlIEtypesHeader_t) + 2 +
+ MLAN_MAC_ADDR_LENGTH *
+ bss->param.bss_config.filter.mac_count;
+ }
+
+ if (((bss->param.bss_config.bandcfg.scanMode == SCAN_MODE_MANUAL) &&
+ (bss->param.bss_config.channel > 0) &&
+ (bss->param.bss_config.channel <= MLAN_MAX_CHANNEL)) ||
+ (bss->param.bss_config.bandcfg.scanMode == SCAN_MODE_ACS)) {
+ tlv_chan_band = (MrvlIEtypes_channel_band_t *)tlv;
+ tlv_chan_band->header.type =
+ wlan_cpu_to_le16(TLV_TYPE_UAP_CHAN_BAND_CONFIG);
+ tlv_chan_band->header.len =
+ wlan_cpu_to_le16(sizeof(t_u8) + sizeof(t_u8));
+ tlv_chan_band->bandcfg = bss->param.bss_config.bandcfg;
+ tlv_chan_band->channel = bss->param.bss_config.channel;
+ cmd_size += sizeof(MrvlIEtypes_channel_band_t);
+ tlv += sizeof(MrvlIEtypes_channel_band_t);
+ }
+
+ if ((bss->param.bss_config.num_of_chan) &&
+ (bss->param.bss_config.num_of_chan <= MLAN_MAX_CHANNEL)) {
+ tlv_chan_list = (MrvlIEtypes_ChanListParamSet_t *)tlv;
+ tlv_chan_list->header.type =
+ wlan_cpu_to_le16(TLV_TYPE_CHANLIST);
+ tlv_chan_list->header.len = wlan_cpu_to_le16(
+ (t_u16)(sizeof(ChanScanParamSet_t) *
+ bss->param.bss_config.num_of_chan));
+ pscan_chan = tlv_chan_list->chan_scan_param;
+ for (i = 0; i < bss->param.bss_config.num_of_chan; i++) {
+ pscan_chan->chan_number =
+ bss->param.bss_config.chan_list[i].chan_number;
+ pscan_chan->bandcfg =
+ bss->param.bss_config.chan_list[i].bandcfg;
+ pscan_chan++;
+ }
+ cmd_size += sizeof(tlv_chan_list->header) +
+ (sizeof(ChanScanParamSet_t) *
+ bss->param.bss_config.num_of_chan);
+ tlv += sizeof(tlv_chan_list->header) +
+ (sizeof(ChanScanParamSet_t) *
+ bss->param.bss_config.num_of_chan);
+ }
+
+ if ((bss->param.bss_config.auth_mode <= MLAN_AUTH_MODE_SHARED) ||
+ (bss->param.bss_config.auth_mode == MLAN_AUTH_MODE_AUTO)) {
+ tlv_auth_type = (MrvlIEtypes_auth_type_t *)tlv;
+ tlv_auth_type->header.type =
+ wlan_cpu_to_le16(TLV_TYPE_AUTH_TYPE);
+ tlv_auth_type->header.len = wlan_cpu_to_le16(sizeof(t_u8));
+ tlv_auth_type->auth_type =
+ (t_u8)bss->param.bss_config.auth_mode;
+ cmd_size += sizeof(MrvlIEtypes_auth_type_t);
+ tlv += sizeof(MrvlIEtypes_auth_type_t);
+ }
+
+ if (bss->param.bss_config.protocol) {
+ tlv_encrypt_protocol = (MrvlIEtypes_encrypt_protocol_t *)tlv;
+ tlv_encrypt_protocol->header.type =
+ wlan_cpu_to_le16(TLV_TYPE_UAP_ENCRYPT_PROTOCOL);
+ tlv_encrypt_protocol->header.len =
+ wlan_cpu_to_le16(sizeof(t_u16));
+ tlv_encrypt_protocol->protocol =
+ wlan_cpu_to_le16(bss->param.bss_config.protocol);
+ cmd_size += sizeof(MrvlIEtypes_encrypt_protocol_t);
+ tlv += sizeof(MrvlIEtypes_encrypt_protocol_t);
+ }
+
+ if ((bss->param.bss_config.protocol & PROTOCOL_WPA) ||
+ (bss->param.bss_config.protocol & PROTOCOL_WPA2) ||
+ (bss->param.bss_config.protocol & PROTOCOL_EAP)) {
+ tlv_akmp = (MrvlIEtypes_akmp_t *)tlv;
+ tlv_akmp->header.type = wlan_cpu_to_le16(TLV_TYPE_UAP_AKMP);
+ tlv_akmp->key_mgmt =
+ wlan_cpu_to_le16(bss->param.bss_config.key_mgmt);
+ tlv_akmp->header.len = sizeof(t_u16);
+ tlv_akmp->key_mgmt_operation = wlan_cpu_to_le16(
+ bss->param.bss_config.key_mgmt_operation);
+ tlv_akmp->header.len += sizeof(t_u16);
+ tlv_akmp->header.len = wlan_cpu_to_le16(tlv_akmp->header.len);
+ cmd_size += sizeof(MrvlIEtypes_akmp_t);
+ tlv += sizeof(MrvlIEtypes_akmp_t);
+
+ if (bss->param.bss_config.wpa_cfg.pairwise_cipher_wpa &
+ VALID_CIPHER_BITMAP) {
+ tlv_pwk_cipher = (MrvlIEtypes_pwk_cipher_t *)tlv;
+ tlv_pwk_cipher->header.type =
+ wlan_cpu_to_le16(TLV_TYPE_PWK_CIPHER);
+ tlv_pwk_cipher->header.len = wlan_cpu_to_le16(
+ sizeof(t_u16) + sizeof(t_u8) + sizeof(t_u8));
+ tlv_pwk_cipher->protocol =
+ wlan_cpu_to_le16(PROTOCOL_WPA);
+ tlv_pwk_cipher->pairwise_cipher =
+ bss->param.bss_config.wpa_cfg
+ .pairwise_cipher_wpa;
+ cmd_size += sizeof(MrvlIEtypes_pwk_cipher_t);
+ tlv += sizeof(MrvlIEtypes_pwk_cipher_t);
+ }
+
+ if (bss->param.bss_config.wpa_cfg.pairwise_cipher_wpa2 &
+ VALID_CIPHER_BITMAP) {
+ tlv_pwk_cipher = (MrvlIEtypes_pwk_cipher_t *)tlv;
+ tlv_pwk_cipher->header.type =
+ wlan_cpu_to_le16(TLV_TYPE_PWK_CIPHER);
+ tlv_pwk_cipher->header.len = wlan_cpu_to_le16(
+ sizeof(t_u16) + sizeof(t_u8) + sizeof(t_u8));
+ tlv_pwk_cipher->protocol =
+ wlan_cpu_to_le16(PROTOCOL_WPA2);
+ tlv_pwk_cipher->pairwise_cipher =
+ bss->param.bss_config.wpa_cfg
+ .pairwise_cipher_wpa2;
+ cmd_size += sizeof(MrvlIEtypes_pwk_cipher_t);
+ tlv += sizeof(MrvlIEtypes_pwk_cipher_t);
+ }
+
+ if (bss->param.bss_config.wpa_cfg.group_cipher &
+ VALID_CIPHER_BITMAP) {
+ tlv_gwk_cipher = (MrvlIEtypes_gwk_cipher_t *)tlv;
+ tlv_gwk_cipher->header.type =
+ wlan_cpu_to_le16(TLV_TYPE_GWK_CIPHER);
+ tlv_gwk_cipher->header.len =
+ wlan_cpu_to_le16(sizeof(t_u8) + sizeof(t_u8));
+ tlv_gwk_cipher->group_cipher =
+ bss->param.bss_config.wpa_cfg.group_cipher;
+ cmd_size += sizeof(MrvlIEtypes_gwk_cipher_t);
+ tlv += sizeof(MrvlIEtypes_gwk_cipher_t);
+ }
+
+ if (bss->param.bss_config.wpa_cfg.rsn_protection <= MTRUE) {
+ tlv_rsn_prot = (MrvlIEtypes_rsn_replay_prot_t *)tlv;
+ tlv_rsn_prot->header.type = wlan_cpu_to_le16(
+ TLV_TYPE_UAP_RSN_REPLAY_PROTECT);
+ tlv_rsn_prot->header.len =
+ wlan_cpu_to_le16(sizeof(t_u8));
+ tlv_rsn_prot->rsn_replay_prot =
+ bss->param.bss_config.wpa_cfg.rsn_protection;
+ cmd_size += sizeof(MrvlIEtypes_rsn_replay_prot_t);
+ tlv += sizeof(MrvlIEtypes_rsn_replay_prot_t);
+ }
+
+#ifdef DRV_EMBEDDED_AUTHENTICATOR
+ if (IS_FW_SUPPORT_AUTHENTICATOR(pmpriv->adapter)) {
+#endif
+ if (bss->param.bss_config.wpa_cfg.length) {
+ tlv_passphrase =
+ (MrvlIEtypes_passphrase_t *)tlv;
+ tlv_passphrase->header.type = wlan_cpu_to_le16(
+ TLV_TYPE_UAP_WPA_PASSPHRASE);
+ tlv_passphrase->header
+ .len = (t_u16)wlan_cpu_to_le16(
+ bss->param.bss_config.wpa_cfg.length);
+ memcpy_ext(
+ pmpriv->adapter,
+ tlv_passphrase->passphrase,
+ bss->param.bss_config.wpa_cfg.passphrase,
+ bss->param.bss_config.wpa_cfg.length,
+ bss->param.bss_config.wpa_cfg.length);
+ cmd_size +=
+ sizeof(MrvlIEtypesHeader_t) +
+ bss->param.bss_config.wpa_cfg.length;
+ tlv += sizeof(MrvlIEtypesHeader_t) +
+ bss->param.bss_config.wpa_cfg.length;
+ }
+
+ if (bss->param.bss_config.wpa_cfg.gk_rekey_time <
+ MAX_GRP_TIMER) {
+ tlv_rekey_time =
+ (MrvlIEtypes_group_rekey_time_t *)tlv;
+ tlv_rekey_time->header.type = wlan_cpu_to_le16(
+ TLV_TYPE_UAP_GRP_REKEY_TIME);
+ tlv_rekey_time->header.len =
+ wlan_cpu_to_le16(sizeof(t_u32));
+ tlv_rekey_time->gk_rekey_time =
+ wlan_cpu_to_le32(
+ bss->param.bss_config.wpa_cfg
+ .gk_rekey_time);
+ cmd_size +=
+ sizeof(MrvlIEtypes_group_rekey_time_t);
+ tlv += sizeof(MrvlIEtypes_group_rekey_time_t);
+ }
+#ifdef DRV_EMBEDDED_AUTHENTICATOR
+ }
+#endif
+ } else {
+ if ((bss->param.bss_config.wep_cfg.key0.length) &&
+ ((bss->param.bss_config.wep_cfg.key0.length == 5) ||
+ (bss->param.bss_config.wep_cfg.key0.length == 10) ||
+ (bss->param.bss_config.wep_cfg.key0.length == 13) ||
+ (bss->param.bss_config.wep_cfg.key0.length == 26))) {
+ tlv_wep_key = (MrvlIEtypes_wep_key_t *)tlv;
+ tlv_wep_key->header.type =
+ wlan_cpu_to_le16(TLV_TYPE_UAP_WEP_KEY);
+ tlv_wep_key->header.len = wlan_cpu_to_le16(
+ 2 + bss->param.bss_config.wep_cfg.key0.length);
+ tlv_wep_key->key_index =
+ bss->param.bss_config.wep_cfg.key0.key_index;
+ tlv_wep_key->is_default =
+ bss->param.bss_config.wep_cfg.key0.is_default;
+ memcpy_ext(pmpriv->adapter, tlv_wep_key->key,
+ bss->param.bss_config.wep_cfg.key0.key,
+ bss->param.bss_config.wep_cfg.key0.length,
+ bss->param.bss_config.wep_cfg.key0.length);
+ cmd_size += sizeof(MrvlIEtypesHeader_t) + 2 +
+ bss->param.bss_config.wep_cfg.key0.length;
+ tlv += sizeof(MrvlIEtypesHeader_t) + 2 +
+ bss->param.bss_config.wep_cfg.key0.length;
+ }
+
+ if ((bss->param.bss_config.wep_cfg.key1.length) &&
+ ((bss->param.bss_config.wep_cfg.key1.length == 5) ||
+ (bss->param.bss_config.wep_cfg.key1.length == 10) ||
+ (bss->param.bss_config.wep_cfg.key1.length == 13) ||
+ (bss->param.bss_config.wep_cfg.key1.length == 26))) {
+ tlv_wep_key = (MrvlIEtypes_wep_key_t *)tlv;
+ tlv_wep_key->header.type =
+ wlan_cpu_to_le16(TLV_TYPE_UAP_WEP_KEY);
+ tlv_wep_key->header.len = wlan_cpu_to_le16(
+ 2 + bss->param.bss_config.wep_cfg.key1.length);
+ tlv_wep_key->key_index =
+ bss->param.bss_config.wep_cfg.key1.key_index;
+ tlv_wep_key->is_default =
+ bss->param.bss_config.wep_cfg.key1.is_default;
+ memcpy_ext(pmpriv->adapter, tlv_wep_key->key,
+ bss->param.bss_config.wep_cfg.key1.key,
+ bss->param.bss_config.wep_cfg.key1.length,
+ bss->param.bss_config.wep_cfg.key1.length);
+ cmd_size += sizeof(MrvlIEtypesHeader_t) + 2 +
+ bss->param.bss_config.wep_cfg.key1.length;
+ tlv += sizeof(MrvlIEtypesHeader_t) + 2 +
+ bss->param.bss_config.wep_cfg.key1.length;
+ }
+
+ if ((bss->param.bss_config.wep_cfg.key2.length) &&
+ ((bss->param.bss_config.wep_cfg.key2.length == 5) ||
+ (bss->param.bss_config.wep_cfg.key2.length == 10) ||
+ (bss->param.bss_config.wep_cfg.key2.length == 13) ||
+ (bss->param.bss_config.wep_cfg.key2.length == 26))) {
+ tlv_wep_key = (MrvlIEtypes_wep_key_t *)tlv;
+ tlv_wep_key->header.type =
+ wlan_cpu_to_le16(TLV_TYPE_UAP_WEP_KEY);
+ tlv_wep_key->header.len = wlan_cpu_to_le16(
+ 2 + bss->param.bss_config.wep_cfg.key2.length);
+ tlv_wep_key->key_index =
+ bss->param.bss_config.wep_cfg.key2.key_index;
+ tlv_wep_key->is_default =
+ bss->param.bss_config.wep_cfg.key2.is_default;
+ memcpy_ext(pmpriv->adapter, tlv_wep_key->key,
+ bss->param.bss_config.wep_cfg.key2.key,
+ bss->param.bss_config.wep_cfg.key2.length,
+ bss->param.bss_config.wep_cfg.key2.length);
+ cmd_size += sizeof(MrvlIEtypesHeader_t) + 2 +
+ bss->param.bss_config.wep_cfg.key2.length;
+ tlv += sizeof(MrvlIEtypesHeader_t) + 2 +
+ bss->param.bss_config.wep_cfg.key2.length;
+ }
+
+ if ((bss->param.bss_config.wep_cfg.key3.length) &&
+ ((bss->param.bss_config.wep_cfg.key3.length == 5) ||
+ (bss->param.bss_config.wep_cfg.key3.length == 10) ||
+ (bss->param.bss_config.wep_cfg.key3.length == 13) ||
+ (bss->param.bss_config.wep_cfg.key3.length == 26))) {
+ tlv_wep_key = (MrvlIEtypes_wep_key_t *)tlv;
+ tlv_wep_key->header.type =
+ wlan_cpu_to_le16(TLV_TYPE_UAP_WEP_KEY);
+ tlv_wep_key->header.len = wlan_cpu_to_le16(
+ 2 + bss->param.bss_config.wep_cfg.key3.length);
+ tlv_wep_key->key_index =
+ bss->param.bss_config.wep_cfg.key3.key_index;
+ tlv_wep_key->is_default =
+ bss->param.bss_config.wep_cfg.key3.is_default;
+ memcpy_ext(pmpriv->adapter, tlv_wep_key->key,
+ bss->param.bss_config.wep_cfg.key3.key,
+ bss->param.bss_config.wep_cfg.key3.length,
+ bss->param.bss_config.wep_cfg.key3.length);
+ cmd_size += sizeof(MrvlIEtypesHeader_t) + 2 +
+ bss->param.bss_config.wep_cfg.key3.length;
+ tlv += sizeof(MrvlIEtypesHeader_t) + 2 +
+ bss->param.bss_config.wep_cfg.key3.length;
+ }
+ }
+ if (bss->param.bss_config.ht_cap_info) {
+ tlv_htcap = (MrvlIETypes_HTCap_t *)tlv;
+ tlv_htcap->header.type = wlan_cpu_to_le16(HT_CAPABILITY);
+ tlv_htcap->header.len = wlan_cpu_to_le16(sizeof(HTCap_t));
+ tlv_htcap->ht_cap.ht_cap_info =
+ wlan_cpu_to_le16(bss->param.bss_config.ht_cap_info);
+ tlv_htcap->ht_cap.ampdu_param =
+ bss->param.bss_config.ampdu_param;
+ memcpy_ext(pmpriv->adapter, tlv_htcap->ht_cap.supported_mcs_set,
+ bss->param.bss_config.supported_mcs_set, 16,
+ sizeof(tlv_htcap->ht_cap.supported_mcs_set));
+#if defined(PCIE9098) || defined(SD9098) || defined(USB9098) || \
+ defined(PCIE9097) || defined(SD9097) || defined(USB9097)
+ if (IS_CARD9098(pmpriv->adapter->card_type) ||
+ IS_CARD9097(pmpriv->adapter->card_type)) {
+ if (bss->param.bss_config.supported_mcs_set[0]) {
+ if (bss->param.bss_config.bandcfg.chanBand ==
+ BAND_5GHZ)
+ rx_mcs_supp = GET_RXMCSSUPP(
+ pmpriv->adapter->user_htstream >>
+ 8);
+ else
+ rx_mcs_supp = GET_RXMCSSUPP(
+ pmpriv->adapter->user_htstream);
+
+ if (rx_mcs_supp == 0x1) {
+ tlv_htcap->ht_cap.supported_mcs_set[0] =
+ 0xFF;
+ tlv_htcap->ht_cap.supported_mcs_set[1] =
+ 0;
+ } else if (rx_mcs_supp == 0x2) {
+ tlv_htcap->ht_cap.supported_mcs_set[0] =
+ 0xFF;
+ tlv_htcap->ht_cap.supported_mcs_set[1] =
+ 0xFF;
+ }
+ }
+ }
+#endif
+ tlv_htcap->ht_cap.ht_ext_cap =
+ wlan_cpu_to_le16(bss->param.bss_config.ht_ext_cap);
+ tlv_htcap->ht_cap.tx_bf_cap =
+ wlan_cpu_to_le32(bss->param.bss_config.tx_bf_cap);
+ tlv_htcap->ht_cap.asel = bss->param.bss_config.asel;
+ cmd_size += sizeof(MrvlIETypes_HTCap_t);
+ tlv += sizeof(MrvlIETypes_HTCap_t);
+ }
+ if (bss->param.bss_config.mgmt_ie_passthru_mask < (MAX_VALID_DWORD)) {
+ tlv_mgmt_ie_passthru = (MrvlIEtypes_mgmt_ie_passthru_t *)tlv;
+ tlv_mgmt_ie_passthru->header.type =
+ wlan_cpu_to_le16(TLV_TYPE_UAP_MGMT_IE_PASSTHRU_MASK);
+ tlv_mgmt_ie_passthru->header.len =
+ wlan_cpu_to_le16(sizeof(t_u32));
+ /* keep copy in private data */
+ pmpriv->mgmt_frame_passthru_mask =
+ bss->param.bss_config.mgmt_ie_passthru_mask;
+ tlv_mgmt_ie_passthru->mgmt_ie_mask = wlan_cpu_to_le32(
+ bss->param.bss_config.mgmt_ie_passthru_mask);
+ cmd_size += sizeof(MrvlIEtypes_mgmt_ie_passthru_t);
+ tlv += sizeof(MrvlIEtypes_mgmt_ie_passthru_t);
+ }
+ if ((bss->param.bss_config.enable_2040coex == 0) ||
+ (bss->param.bss_config.enable_2040coex == 1)) {
+ tlv_2040_coex_enable = (MrvlIEtypes_2040_coex_enable_t *)tlv;
+ tlv_2040_coex_enable->header.type =
+ wlan_cpu_to_le16(TLV_TYPE_2040_BSS_COEX_CONTROL);
+ tlv_2040_coex_enable->header.len =
+ wlan_cpu_to_le16(sizeof(t_u8));
+ tlv_2040_coex_enable->enable_2040coex =
+ bss->param.bss_config.enable_2040coex;
+ cmd_size += sizeof(MrvlIEtypes_2040_coex_enable_t);
+ tlv += sizeof(MrvlIEtypes_2040_coex_enable_t);
+ }
+ if ((bss->param.bss_config.uap_host_based_config == MTRUE) ||
+ (bss->param.bss_config.wmm_para.qos_info & 0x80 ||
+ bss->param.bss_config.wmm_para.qos_info == 0x00)) {
+ tlv_wmm_parameter = (MrvlIEtypes_wmm_parameter_t *)tlv;
+ tlv_wmm_parameter->header.type =
+ wlan_cpu_to_le16(TLV_TYPE_VENDOR_SPECIFIC_IE);
+ tlv_wmm_parameter->header.len = wlan_cpu_to_le16(
+ sizeof(bss->param.bss_config.wmm_para));
+ memcpy_ext(pmpriv->adapter, tlv_wmm_parameter->wmm_para.ouitype,
+ bss->param.bss_config.wmm_para.ouitype,
+ sizeof(tlv_wmm_parameter->wmm_para.ouitype),
+ sizeof(tlv_wmm_parameter->wmm_para.ouitype));
+ tlv_wmm_parameter->wmm_para.ouisubtype =
+ bss->param.bss_config.wmm_para.ouisubtype;
+ tlv_wmm_parameter->wmm_para.version =
+ bss->param.bss_config.wmm_para.version;
+ tlv_wmm_parameter->wmm_para.qos_info =
+ bss->param.bss_config.wmm_para.qos_info;
+ for (ac = 0; ac < 4; ac++) {
+ tlv_wmm_parameter->wmm_para.ac_params[ac]
+ .aci_aifsn.aifsn =
+ bss->param.bss_config.wmm_para.ac_params[ac]
+ .aci_aifsn.aifsn;
+ tlv_wmm_parameter->wmm_para.ac_params[ac].aci_aifsn.aci =
+ bss->param.bss_config.wmm_para.ac_params[ac]
+ .aci_aifsn.aci;
+ tlv_wmm_parameter->wmm_para.ac_params[ac].ecw.ecw_max =
+ bss->param.bss_config.wmm_para.ac_params[ac]
+ .ecw.ecw_max;
+ tlv_wmm_parameter->wmm_para.ac_params[ac].ecw.ecw_min =
+ bss->param.bss_config.wmm_para.ac_params[ac]
+ .ecw.ecw_min;
+ tlv_wmm_parameter->wmm_para.ac_params[ac].tx_op_limit =
+ wlan_cpu_to_le16(bss->param.bss_config.wmm_para
+ .ac_params[ac]
+ .tx_op_limit);
+ }
+ cmd_size += sizeof(MrvlIEtypes_wmm_parameter_t);
+ tlv += sizeof(MrvlIEtypes_wmm_parameter_t);
+ }
+#ifdef DRV_EMBEDDED_AUTHENTICATOR
+ if (!IS_FW_SUPPORT_AUTHENTICATOR(pmpriv->adapter))
+ AuthenticatorBssConfig(pmpriv->psapriv,
+ (t_u8 *)&bss->param.bss_config, 0, 0, 0);
+#endif
+ if (pmpriv->adapter->pcard_info->v17_fw_api &&
+ bss->param.bss_config.preamble_type) {
+ tlv_preamble = (MrvlIEtypes_preamble_t *)tlv;
+ tlv_preamble->header.type =
+ wlan_cpu_to_le16(TLV_TYPE_UAP_PREAMBLE_CTL);
+ tlv_preamble->header.len =
+ wlan_cpu_to_le16(sizeof(MrvlIEtypes_preamble_t) -
+ sizeof(MrvlIEtypesHeader_t));
+ tlv_preamble->preamble_type =
+ wlan_cpu_to_le16(bss->param.bss_config.preamble_type);
+
+ cmd_size += sizeof(MrvlIEtypes_preamble_t);
+ tlv += sizeof(MrvlIEtypes_preamble_t);
+ }
+
+ cmd->size = (t_u16)wlan_cpu_to_le16(cmd_size);
+ PRINTM(MCMND, "AP config: cmd_size=%d\n", cmd_size);
+ LEAVE();
+ return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ * @brief This function prepares command of sys_config
+ *
+ * @param pmpriv A pointer to mlan_private structure
+ * @param cmd A pointer to HostCmd_DS_COMMAND structure
+ * @param cmd_action the action: GET or SET
+ * @param pioctl_buf A pointer to mlan_ioctl_req structure
+ * @return MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ */
+static mlan_status wlan_uap_cmd_sys_configure(pmlan_private pmpriv,
+ HostCmd_DS_COMMAND *cmd,
+ t_u16 cmd_action,
+ pmlan_ioctl_req pioctl_buf,
+ t_void *pdata_buf)
+{
+ mlan_ds_bss *bss = MNULL;
+ HostCmd_DS_SYS_CONFIG *sys_config =
+ (HostCmd_DS_SYS_CONFIG *)&cmd->params.sys_config;
+ MrvlIEtypes_MacAddr_t *mac_tlv = MNULL;
+ MrvlIEtypes_channel_band_t *pdat_tlv_cb = MNULL;
+ MrvlIEtypes_beacon_period_t *bcn_pd_tlv = MNULL,
+ *pdat_tlv_bcnpd = MNULL;
+ MrvlIEtypes_dtim_period_t *dtim_pd_tlv = MNULL,
+ *pdat_tlv_dtimpd = MNULL;
+ MrvlIEtypes_wmm_parameter_t *tlv_wmm_parameter = MNULL;
+ MrvlIEtypes_ChanListParamSet_t *tlv_chan_list = MNULL;
+ ChanScanParamSet_t *pscan_chan = MNULL;
+ MrvlIEtypes_channel_band_t *chan_band_tlv = MNULL;
+ MrvlIEtypes_chan_bw_oper_t *poper_class_tlv = MNULL;
+ t_u8 length = 0;
+ t_u8 curr_oper_class = 1;
+ t_u8 *oper_class_ie = (t_u8 *)sys_config->tlv_buffer;
+ t_u16 i = 0;
+ t_u8 ac = 0;
+ mlan_ds_misc_custom_ie *cust_ie = MNULL;
+ mlan_ds_misc_cfg *misc = MNULL;
+ MrvlIEtypesHeader_t *ie_header =
+ (MrvlIEtypesHeader_t *)sys_config->tlv_buffer;
+ MrvlIEtypesHeader_t *pdata_header = (MrvlIEtypesHeader_t *)pdata_buf;
+ t_u8 *ie = (t_u8 *)sys_config->tlv_buffer + sizeof(MrvlIEtypesHeader_t);
+ t_u16 req_len = 0, travel_len = 0;
+ custom_ie *cptr = MNULL;
+ mlan_status ret = MLAN_STATUS_SUCCESS;
+
+ ENTER();
+
+ cmd->command = wlan_cpu_to_le16(HOST_CMD_APCMD_SYS_CONFIGURE);
+ sys_config->action = wlan_cpu_to_le16(cmd_action);
+ cmd->size =
+ wlan_cpu_to_le16(sizeof(HostCmd_DS_SYS_CONFIG) - 1 + S_DS_GEN);
+ if (pioctl_buf == MNULL) {
+ if (pdata_buf) {
+ switch (pdata_header->type) {
+ case TLV_TYPE_UAP_CHAN_BAND_CONFIG:
+ pdat_tlv_cb =
+ (MrvlIEtypes_channel_band_t *)pdata_buf;
+ chan_band_tlv = (MrvlIEtypes_channel_band_t *)
+ sys_config->tlv_buffer;
+ cmd->size = wlan_cpu_to_le16(
+ sizeof(HostCmd_DS_SYS_CONFIG) - 1 +
+ S_DS_GEN +
+ sizeof(MrvlIEtypes_channel_band_t));
+ chan_band_tlv->header.type = wlan_cpu_to_le16(
+ TLV_TYPE_UAP_CHAN_BAND_CONFIG);
+ chan_band_tlv->header.len = wlan_cpu_to_le16(
+ sizeof(MrvlIEtypes_channel_band_t) -
+ sizeof(MrvlIEtypesHeader_t));
+ if (cmd_action) {
+ chan_band_tlv->bandcfg =
+ pdat_tlv_cb->bandcfg;
+ chan_band_tlv->channel =
+ pdat_tlv_cb->channel;
+ }
+ ret = MLAN_STATUS_SUCCESS;
+ break;
+ case TLV_TYPE_UAP_BEACON_PERIOD:
+ pdat_tlv_bcnpd = (MrvlIEtypes_beacon_period_t *)
+ pdata_buf;
+ bcn_pd_tlv = (MrvlIEtypes_beacon_period_t *)
+ sys_config->tlv_buffer;
+ cmd->size = sizeof(HostCmd_DS_SYS_CONFIG) - 1 +
+ S_DS_GEN +
+ sizeof(MrvlIEtypes_beacon_period_t);
+ bcn_pd_tlv->header.type = wlan_cpu_to_le16(
+ TLV_TYPE_UAP_BEACON_PERIOD);
+ bcn_pd_tlv->header.len = wlan_cpu_to_le16(
+ sizeof(MrvlIEtypes_beacon_period_t) -
+ sizeof(MrvlIEtypesHeader_t));
+ if (cmd_action) {
+ bcn_pd_tlv->beacon_period =
+ wlan_cpu_to_le16(
+ pdat_tlv_bcnpd
+ ->beacon_period);
+ }
+ /* Add TLV_UAP_DTIM_PERIOD if it follws in
+ * pdata_buf */
+ pdat_tlv_dtimpd =
+ (MrvlIEtypes_dtim_period_t
+ *)(((t_u8 *)pdata_buf) +
+ sizeof(MrvlIEtypes_beacon_period_t));
+ if (TLV_TYPE_UAP_DTIM_PERIOD ==
+ pdat_tlv_dtimpd->header.type) {
+ dtim_pd_tlv =
+ (MrvlIEtypes_dtim_period_t
+ *)(sys_config
+ ->tlv_buffer +
+ sizeof(MrvlIEtypes_beacon_period_t));
+ cmd->size += sizeof(
+ MrvlIEtypes_dtim_period_t);
+ dtim_pd_tlv->header
+ .type = wlan_cpu_to_le16(
+ TLV_TYPE_UAP_DTIM_PERIOD);
+ dtim_pd_tlv->header
+ .len = wlan_cpu_to_le16(
+ sizeof(MrvlIEtypes_dtim_period_t) -
+ sizeof(MrvlIEtypesHeader_t));
+ if (cmd_action) {
+ dtim_pd_tlv->dtim_period =
+ pdat_tlv_dtimpd
+ ->dtim_period;
+ }
+ }
+ /* Finalize cmd size */
+ cmd->size = wlan_cpu_to_le16(cmd->size);
+ ret = MLAN_STATUS_SUCCESS;
+ break;
+ case TLV_TYPE_MGMT_IE:
+ cust_ie = (mlan_ds_misc_custom_ie *)pdata_buf;
+ cmd->size = wlan_cpu_to_le16(
+ sizeof(HostCmd_DS_SYS_CONFIG) - 1 +
+ S_DS_GEN + sizeof(MrvlIEtypesHeader_t) +
+ cust_ie->len);
+ ie_header->type =
+ wlan_cpu_to_le16(TLV_TYPE_MGMT_IE);
+ ie_header->len = wlan_cpu_to_le16(cust_ie->len);
+
+ if (ie) {
+ req_len = cust_ie->len;
+ travel_len = 0;
+ /* conversion for index, mask, len */
+ if (req_len == sizeof(t_u16))
+ cust_ie->ie_data_list[0]
+ .ie_index = wlan_cpu_to_le16(
+ cust_ie->ie_data_list[0]
+ .ie_index);
+ while (req_len > sizeof(t_u16)) {
+ cptr = (custom_ie
+ *)(((t_u8 *)&cust_ie
+ ->ie_data_list) +
+ travel_len);
+ travel_len +=
+ cptr->ie_length +
+ sizeof(custom_ie) -
+ MAX_IE_SIZE;
+ req_len -= cptr->ie_length +
+ sizeof(custom_ie) -
+ MAX_IE_SIZE;
+ cptr->ie_index =
+ wlan_cpu_to_le16(
+ cptr->ie_index);
+ cptr->mgmt_subtype_mask = wlan_cpu_to_le16(
+ cptr->mgmt_subtype_mask);
+ cptr->ie_length =
+ wlan_cpu_to_le16(
+ cptr->ie_length);
+ }
+ memcpy_ext(pmpriv->adapter, ie,
+ cust_ie->ie_data_list,
+ cust_ie->len, cust_ie->len);
+ }
+ break;
+ case REGULATORY_CLASS:
+ poper_class_tlv =
+ (MrvlIEtypes_chan_bw_oper_t *)pdata_buf;
+ ret = wlan_get_curr_oper_class(
+ pmpriv,
+ poper_class_tlv->ds_chan_bw_oper.channel,
+ poper_class_tlv->ds_chan_bw_oper
+ .bandwidth,
+ &curr_oper_class);
+ if (ret != MLAN_STATUS_SUCCESS) {
+ PRINTM(MERROR,
+ "Can not get current oper class! bandwidth = %d, channel = %d\n",
+ poper_class_tlv->ds_chan_bw_oper
+ .bandwidth,
+ poper_class_tlv->ds_chan_bw_oper
+ .channel);
+ }
+
+ if (cmd_action == HostCmd_ACT_GEN_SET)
+ length =
+ wlan_add_supported_oper_class_ie(
+ pmpriv, &oper_class_ie,
+ curr_oper_class);
+ cmd->size = wlan_cpu_to_le16(
+ sizeof(HostCmd_DS_SYS_CONFIG) - 1 +
+ S_DS_GEN + length);
+ break;
+ case TLV_TYPE_UAP_MAX_STA_CNT_PER_CHIP:
+ memcpy_ext(
+ pmpriv->adapter, sys_config->tlv_buffer,
+ pdata_buf,
+ sizeof(MrvlIEtypes_uap_max_sta_cnt_t),
+ sizeof(MrvlIEtypes_uap_max_sta_cnt_t));
+ cmd->size = wlan_cpu_to_le16(
+ sizeof(HostCmd_DS_SYS_CONFIG) - 1 +
+ S_DS_GEN +
+ sizeof(MrvlIEtypes_uap_max_sta_cnt_t));
+ break;
+ default:
+ PRINTM(MERROR,
+ "Wrong data, or missing TLV_TYPE 0x%04x handler.\n",
+ *(t_u16 *)pdata_buf);
+ break;
+ }
+ goto done;
+ } else {
+ mac_tlv =
+ (MrvlIEtypes_MacAddr_t *)sys_config->tlv_buffer;
+ cmd->size = wlan_cpu_to_le16(
+ sizeof(HostCmd_DS_SYS_CONFIG) - 1 + S_DS_GEN +
+ sizeof(MrvlIEtypes_MacAddr_t));
+ mac_tlv->header.type =
+ wlan_cpu_to_le16(TLV_TYPE_UAP_MAC_ADDRESS);
+ mac_tlv->header.len =
+ wlan_cpu_to_le16(MLAN_MAC_ADDR_LENGTH);
+ ret = MLAN_STATUS_SUCCESS;
+ goto done;
+ }
+ }
+ if (pioctl_buf->req_id == MLAN_IOCTL_BSS) {
+ bss = (mlan_ds_bss *)pioctl_buf->pbuf;
+ if (bss->sub_command == MLAN_OID_BSS_MAC_ADDR) {
+ mac_tlv =
+ (MrvlIEtypes_MacAddr_t *)sys_config->tlv_buffer;
+ cmd->size = wlan_cpu_to_le16(
+ sizeof(HostCmd_DS_SYS_CONFIG) - 1 + S_DS_GEN +
+ sizeof(MrvlIEtypes_MacAddr_t));
+ mac_tlv->header.type =
+ wlan_cpu_to_le16(TLV_TYPE_UAP_MAC_ADDRESS);
+ mac_tlv->header.len =
+ wlan_cpu_to_le16(MLAN_MAC_ADDR_LENGTH);
+ if (cmd_action == HostCmd_ACT_GEN_SET)
+ memcpy_ext(pmpriv->adapter, mac_tlv->mac,
+ &bss->param.mac_addr,
+ MLAN_MAC_ADDR_LENGTH,
+ MLAN_MAC_ADDR_LENGTH);
+ } else if (bss->sub_command == MLAN_OID_UAP_CFG_WMM_PARAM) {
+ tlv_wmm_parameter = (MrvlIEtypes_wmm_parameter_t *)
+ sys_config->tlv_buffer;
+ cmd->size = wlan_cpu_to_le16(
+ sizeof(HostCmd_DS_SYS_CONFIG) - 1 + S_DS_GEN +
+ sizeof(MrvlIEtypes_wmm_parameter_t));
+ tlv_wmm_parameter->header.type =
+ wlan_cpu_to_le16(TLV_TYPE_AP_WMM_PARAM);
+ tlv_wmm_parameter->header.len = wlan_cpu_to_le16(
+ sizeof(bss->param.ap_wmm_para));
+ if (cmd_action == HostCmd_ACT_GEN_SET) {
+ for (ac = 0; ac < 4; ac++) {
+ tlv_wmm_parameter->wmm_para
+ .ac_params[ac]
+ .aci_aifsn.aifsn =
+ bss->param.ap_wmm_para
+ .ac_params[ac]
+ .aci_aifsn.aifsn;
+ tlv_wmm_parameter->wmm_para
+ .ac_params[ac]
+ .aci_aifsn.aci =
+ bss->param.ap_wmm_para
+ .ac_params[ac]
+ .aci_aifsn.aci;
+ tlv_wmm_parameter->wmm_para
+ .ac_params[ac]
+ .ecw.ecw_max =
+ bss->param.ap_wmm_para
+ .ac_params[ac]
+ .ecw.ecw_max;
+ tlv_wmm_parameter->wmm_para
+ .ac_params[ac]
+ .ecw.ecw_min =
+ bss->param.ap_wmm_para
+ .ac_params[ac]
+ .ecw.ecw_min;
+ tlv_wmm_parameter->wmm_para
+ .ac_params[ac]
+ .tx_op_limit = wlan_cpu_to_le16(
+ bss->param.ap_wmm_para
+ .ac_params[ac]
+ .tx_op_limit);
+ }
+ }
+ } else if (bss->sub_command == MLAN_OID_UAP_SCAN_CHANNELS) {
+ tlv_chan_list = (MrvlIEtypes_ChanListParamSet_t *)
+ sys_config->tlv_buffer;
+ tlv_chan_list->header.type =
+ wlan_cpu_to_le16(TLV_TYPE_CHANLIST);
+ if (bss->param.ap_scan_channels.num_of_chan &&
+ bss->param.ap_scan_channels.num_of_chan <=
+ MLAN_MAX_CHANNEL) {
+ cmd->size = wlan_cpu_to_le16(
+ sizeof(HostCmd_DS_SYS_CONFIG) - 1 +
+ S_DS_GEN +
+ sizeof(tlv_chan_list->header) +
+ sizeof(ChanScanParamSet_t) *
+ bss->param.ap_scan_channels
+ .num_of_chan);
+ tlv_chan_list->header.len = wlan_cpu_to_le16(
+ (t_u16)(sizeof(ChanScanParamSet_t) *
+ bss->param.ap_scan_channels
+ .num_of_chan));
+ pscan_chan = tlv_chan_list->chan_scan_param;
+ for (i = 0;
+ i <
+ bss->param.ap_scan_channels.num_of_chan;
+ i++) {
+ pscan_chan->chan_number =
+ bss->param.ap_scan_channels
+ .chan_list[i]
+ .chan_number;
+ pscan_chan->bandcfg =
+ bss->param.ap_scan_channels
+ .chan_list[i]
+ .bandcfg;
+ pscan_chan++;
+ }
+ PRINTM(MCMND,
+ "Set AP scan channel list = %d\n",
+ bss->param.ap_scan_channels.num_of_chan);
+ } else {
+ tlv_chan_list->header.len = wlan_cpu_to_le16(
+ (t_u16)(sizeof(ChanScanParamSet_t) *
+ MLAN_MAX_CHANNEL));
+ cmd->size = wlan_cpu_to_le16(
+ sizeof(HostCmd_DS_SYS_CONFIG) - 1 +
+ S_DS_GEN +
+ sizeof(MrvlIEtypes_ChanListParamSet_t) +
+ sizeof(ChanScanParamSet_t) *
+ MLAN_MAX_CHANNEL);
+ }
+ } else if (bss->sub_command == MLAN_OID_UAP_CHANNEL) {
+ chan_band_tlv = (MrvlIEtypes_channel_band_t *)
+ sys_config->tlv_buffer;
+ cmd->size = wlan_cpu_to_le16(
+ sizeof(HostCmd_DS_SYS_CONFIG) - 1 + S_DS_GEN +
+ sizeof(MrvlIEtypes_channel_band_t));
+ chan_band_tlv->header.type =
+ wlan_cpu_to_le16(TLV_TYPE_UAP_CHAN_BAND_CONFIG);
+ chan_band_tlv->header.len = wlan_cpu_to_le16(
+ sizeof(MrvlIEtypes_channel_band_t) -
+ sizeof(MrvlIEtypesHeader_t));
+ if (cmd_action == HostCmd_ACT_GEN_SET) {
+ chan_band_tlv->bandcfg =
+ bss->param.ap_channel.bandcfg;
+ chan_band_tlv->channel =
+ bss->param.ap_channel.channel;
+ PRINTM(MCMND,
+ "Set AP channel, band=%d, channel=%d\n",
+ bss->param.ap_channel.bandcfg,
+ bss->param.ap_channel.channel);
+ }
+ } else if ((bss->sub_command == MLAN_OID_UAP_BSS_CONFIG) &&
+ (cmd_action == HostCmd_ACT_GEN_SET)) {
+ ret = wlan_uap_cmd_ap_config(pmpriv, cmd, cmd_action,
+ pioctl_buf);
+ goto done;
+ }
+ } else if (pioctl_buf->req_id == MLAN_IOCTL_MISC_CFG) {
+ misc = (mlan_ds_misc_cfg *)pioctl_buf->pbuf;
+ if ((misc->sub_command == MLAN_OID_MISC_GEN_IE) &&
+ (misc->param.gen_ie.type == MLAN_IE_TYPE_GEN_IE)) {
+ cmd->size = wlan_cpu_to_le16(
+ sizeof(HostCmd_DS_SYS_CONFIG) - 1 + S_DS_GEN +
+ sizeof(MrvlIEtypesHeader_t) +
+ misc->param.gen_ie.len);
+ ie_header->type = wlan_cpu_to_le16(TLV_TYPE_WAPI_IE);
+ ie_header->len =
+ wlan_cpu_to_le16(misc->param.gen_ie.len);
+ if (cmd_action == HostCmd_ACT_GEN_SET)
+ memcpy_ext(pmpriv->adapter, ie,
+ misc->param.gen_ie.ie_data,
+ misc->param.gen_ie.len,
+ misc->param.gen_ie.len);
+ }
+ if ((misc->sub_command == MLAN_OID_MISC_CUSTOM_IE) &&
+ (misc->param.cust_ie.type == TLV_TYPE_MGMT_IE)) {
+ cmd->size = wlan_cpu_to_le16(
+ sizeof(HostCmd_DS_SYS_CONFIG) - 1 + S_DS_GEN +
+ sizeof(MrvlIEtypesHeader_t) +
+ misc->param.cust_ie.len);
+ ie_header->type = wlan_cpu_to_le16(TLV_TYPE_MGMT_IE);
+ ie_header->len =
+ wlan_cpu_to_le16(misc->param.cust_ie.len);
+
+ if (ie) {
+ req_len = misc->param.cust_ie.len;
+ travel_len = 0;
+ /* conversion for index, mask, len */
+ if (req_len == sizeof(t_u16))
+ misc->param.cust_ie.ie_data_list[0]
+ .ie_index = wlan_cpu_to_le16(
+ misc->param.cust_ie
+ .ie_data_list[0]
+ .ie_index);
+ while (req_len > sizeof(t_u16)) {
+ cptr = (custom_ie
+ *)(((t_u8 *)&misc->param
+ .cust_ie
+ .ie_data_list) +
+ travel_len);
+ travel_len += cptr->ie_length +
+ sizeof(custom_ie) -
+ MAX_IE_SIZE;
+ req_len -= cptr->ie_length +
+ sizeof(custom_ie) -
+ MAX_IE_SIZE;
+ cptr->ie_index = wlan_cpu_to_le16(
+ cptr->ie_index);
+ cptr->mgmt_subtype_mask =
+ wlan_cpu_to_le16(
+ cptr->mgmt_subtype_mask);
+ cptr->ie_length = wlan_cpu_to_le16(
+ cptr->ie_length);
+ }
+ if (misc->param.cust_ie.len)
+ memcpy_ext(
+ pmpriv->adapter, ie,
+ misc->param.cust_ie.ie_data_list,
+ misc->param.cust_ie.len,
+ misc->param.cust_ie.len);
+ }
+ }
+ }
+done:
+ LEAVE();
+ return ret;
+}
+
+/**
+ * @brief This function handles command resp for get uap settings
+ *
+ * @param pmpriv A pointer to mlan_private structure
+ * @param resp A pointer to HostCmd_DS_COMMAND
+ * @param pioctl_buf A pointer to mlan_ioctl_req structure
+ *
+ * @return MLAN_STATUS_SUCCESS
+ */
+static mlan_status wlan_uap_ret_cmd_ap_config(pmlan_private pmpriv,
+ HostCmd_DS_COMMAND *resp,
+ mlan_ioctl_req *pioctl_buf)
+{
+ HostCmd_DS_SYS_CONFIG *sys_config =
+ (HostCmd_DS_SYS_CONFIG *)&resp->params.sys_config;
+ mlan_ds_bss *bss = MNULL;
+ MrvlIEtypesHeader_t *tlv = MNULL;
+ t_u16 tlv_buf_left = 0;
+ t_u16 tlv_type = 0;
+ t_u16 tlv_len = 0;
+ MrvlIEtypes_MacAddr_t *tlv_mac = MNULL;
+ MrvlIEtypes_SsIdParamSet_t *tlv_ssid = MNULL;
+ MrvlIEtypes_beacon_period_t *tlv_beacon_period = MNULL;
+ MrvlIEtypes_dtim_period_t *tlv_dtim_period = MNULL;
+ MrvlIEtypes_RatesParamSet_t *tlv_rates = MNULL;
+ MrvlIEtypes_tx_rate_t *tlv_txrate = MNULL;
+ MrvlIEtypes_mcbc_rate_t *tlv_mcbc_rate = MNULL;
+ MrvlIEtypes_tx_power_t *tlv_tx_power = MNULL;
+ MrvlIEtypes_bcast_ssid_t *tlv_bcast_ssid = MNULL;
+ MrvlIEtypes_antenna_mode_t *tlv_antenna = MNULL;
+ MrvlIEtypes_pkt_forward_t *tlv_pkt_forward = MNULL;
+ MrvlIEtypes_max_sta_count_t *tlv_sta_count = MNULL;
+ MrvlIEtypes_sta_ageout_t *tlv_sta_ageout = MNULL;
+ MrvlIEtypes_ps_sta_ageout_t *tlv_ps_sta_ageout = MNULL;
+ MrvlIEtypes_rts_threshold_t *tlv_rts_threshold = MNULL;
+ MrvlIEtypes_frag_threshold_t *tlv_frag_threshold = MNULL;
+ MrvlIEtypes_retry_limit_t *tlv_retry_limit = MNULL;
+ MrvlIEtypes_eapol_pwk_hsk_timeout_t *tlv_pairwise_timeout = MNULL;
+ MrvlIEtypes_eapol_pwk_hsk_retries_t *tlv_pairwise_retries = MNULL;
+ MrvlIEtypes_eapol_gwk_hsk_timeout_t *tlv_groupwise_timeout = MNULL;
+ MrvlIEtypes_eapol_gwk_hsk_retries_t *tlv_groupwise_retries = MNULL;
+ MrvlIEtypes_mgmt_ie_passthru_t *tlv_mgmt_ie_passthru = MNULL;
+ MrvlIEtypes_2040_coex_enable_t *tlv_2040_coex_enable = MNULL;
+ MrvlIEtypes_mac_filter_t *tlv_mac_filter = MNULL;
+ MrvlIEtypes_channel_band_t *tlv_chan_band = MNULL;
+ MrvlIEtypes_ChanListParamSet_t *tlv_chan_list = MNULL;
+ ChanScanParamSet_t *pscan_chan = MNULL;
+ MrvlIEtypes_auth_type_t *tlv_auth_type = MNULL;
+ MrvlIEtypes_encrypt_protocol_t *tlv_encrypt_protocol = MNULL;
+ MrvlIEtypes_akmp_t *tlv_akmp = MNULL;
+ MrvlIEtypes_pwk_cipher_t *tlv_pwk_cipher = MNULL;
+ MrvlIEtypes_gwk_cipher_t *tlv_gwk_cipher = MNULL;
+ MrvlIEtypes_rsn_replay_prot_t *tlv_rsn_prot = MNULL;
+ MrvlIEtypes_passphrase_t *tlv_passphrase = MNULL;
+#ifdef WIFI_DIRECT_SUPPORT
+ MrvlIEtypes_psk_t *tlv_psk = MNULL;
+#endif /* WIFI_DIRECT_SUPPORT */
+ MrvlIEtypes_group_rekey_time_t *tlv_rekey_time = MNULL;
+ MrvlIEtypes_wep_key_t *tlv_wep_key = MNULL;
+ MrvlIEtypes_preamble_t *tlv_preamble = MNULL;
+ MrvlIEtypes_bss_status_t *tlv_bss_status = MNULL;
+ MrvlIETypes_HTCap_t *tlv_htcap = MNULL;
+ MrvlIEtypes_wmm_parameter_t *tlv_wmm_parameter = MNULL;
+
+ wep_key *pkey = MNULL;
+ t_u16 i;
+ t_u16 ac;
+
+ ENTER();
+
+ bss = (mlan_ds_bss *)pioctl_buf->pbuf;
+ tlv = (MrvlIEtypesHeader_t *)sys_config->tlv_buffer;
+ tlv_buf_left =
+ resp->size - (sizeof(HostCmd_DS_SYS_CONFIG) - 1 + S_DS_GEN);
+
+ while (tlv_buf_left >= sizeof(MrvlIEtypesHeader_t)) {
+ tlv_type = wlan_le16_to_cpu(tlv->type);
+ tlv_len = wlan_le16_to_cpu(tlv->len);
+
+ if (tlv_buf_left < (tlv_len + sizeof(MrvlIEtypesHeader_t))) {
+ PRINTM(MERROR,
+ "Error processing uAP sys config TLVs, bytes left < TLV length\n");
+ break;
+ }
+
+ switch (tlv_type) {
+ case TLV_TYPE_UAP_MAC_ADDRESS:
+ tlv_mac = (MrvlIEtypes_MacAddr_t *)tlv;
+ memcpy_ext(pmpriv->adapter,
+ &bss->param.bss_config.mac_addr,
+ tlv_mac->mac, MLAN_MAC_ADDR_LENGTH,
+ MLAN_MAC_ADDR_LENGTH);
+ break;
+ case TLV_TYPE_SSID:
+ tlv_ssid = (MrvlIEtypes_SsIdParamSet_t *)tlv;
+ bss->param.bss_config.ssid.ssid_len =
+ MIN(MLAN_MAX_SSID_LENGTH, tlv_len);
+ memcpy_ext(pmpriv->adapter,
+ bss->param.bss_config.ssid.ssid,
+ tlv_ssid->ssid, tlv_len,
+ MLAN_MAX_SSID_LENGTH);
+ break;
+ case TLV_TYPE_UAP_BEACON_PERIOD:
+ tlv_beacon_period = (MrvlIEtypes_beacon_period_t *)tlv;
+ bss->param.bss_config.beacon_period = wlan_le16_to_cpu(
+ tlv_beacon_period->beacon_period);
+ pmpriv->uap_state_chan_cb.beacon_period =
+ wlan_le16_to_cpu(
+ tlv_beacon_period->beacon_period);
+ break;
+ case TLV_TYPE_UAP_DTIM_PERIOD:
+ tlv_dtim_period = (MrvlIEtypes_dtim_period_t *)tlv;
+ bss->param.bss_config.dtim_period =
+ tlv_dtim_period->dtim_period;
+ pmpriv->uap_state_chan_cb.dtim_period =
+ tlv_dtim_period->dtim_period;
+ break;
+ case TLV_TYPE_RATES:
+ tlv_rates = (MrvlIEtypes_RatesParamSet_t *)tlv;
+ memcpy_ext(pmpriv->adapter, bss->param.bss_config.rates,
+ tlv_rates->rates, tlv_len, MAX_DATA_RATES);
+ break;
+ case TLV_TYPE_UAP_TX_DATA_RATE:
+ tlv_txrate = (MrvlIEtypes_tx_rate_t *)tlv;
+ bss->param.bss_config.tx_data_rate =
+ wlan_le16_to_cpu(tlv_txrate->tx_data_rate);
+ break;
+ case TLV_TYPE_UAP_TX_BEACON_RATE:
+ tlv_txrate = (MrvlIEtypes_tx_rate_t *)tlv;
+ bss->param.bss_config.tx_beacon_rate =
+ wlan_le16_to_cpu(tlv_txrate->tx_data_rate);
+ break;
+ case TLV_TYPE_UAP_MCBC_DATA_RATE:
+ tlv_mcbc_rate = (MrvlIEtypes_mcbc_rate_t *)tlv;
+ bss->param.bss_config.mcbc_data_rate =
+ wlan_le16_to_cpu(tlv_mcbc_rate->mcbc_data_rate);
+ break;
+ case TLV_TYPE_UAP_TX_POWER:
+ tlv_tx_power = (MrvlIEtypes_tx_power_t *)tlv;
+ bss->param.bss_config.tx_power_level =
+ tlv_tx_power->tx_power;
+ break;
+ case TLV_TYPE_UAP_BCAST_SSID_CTL:
+ tlv_bcast_ssid = (MrvlIEtypes_bcast_ssid_t *)tlv;
+ bss->param.bss_config.bcast_ssid_ctl =
+ tlv_bcast_ssid->bcast_ssid_ctl;
+ break;
+ case TLV_TYPE_UAP_ANTENNA_CTL:
+ tlv_antenna = (MrvlIEtypes_antenna_mode_t *)tlv;
+ if (tlv_antenna->which_antenna == TX_ANTENNA)
+ bss->param.bss_config.tx_antenna =
+ tlv_antenna->antenna_mode;
+ else if (tlv_antenna->which_antenna == RX_ANTENNA)
+ bss->param.bss_config.rx_antenna =
+ tlv_antenna->antenna_mode;
+ break;
+ case TLV_TYPE_UAP_PKT_FWD_CTL:
+ tlv_pkt_forward = (MrvlIEtypes_pkt_forward_t *)tlv;
+ bss->param.bss_config.pkt_forward_ctl =
+ tlv_pkt_forward->pkt_forward_ctl;
+ break;
+ case TLV_TYPE_UAP_MAX_STA_CNT:
+ tlv_sta_count = (MrvlIEtypes_max_sta_count_t *)tlv;
+ bss->param.bss_config.max_sta_count =
+ wlan_le16_to_cpu(tlv_sta_count->max_sta_count);
+ break;
+ case TLV_TYPE_UAP_STA_AGEOUT_TIMER:
+ tlv_sta_ageout = (MrvlIEtypes_sta_ageout_t *)tlv;
+ bss->param.bss_config.sta_ageout_timer =
+ wlan_le32_to_cpu(
+ tlv_sta_ageout->sta_ageout_timer);
+ break;
+ case TLV_TYPE_UAP_PS_STA_AGEOUT_TIMER:
+ tlv_ps_sta_ageout = (MrvlIEtypes_ps_sta_ageout_t *)tlv;
+ bss->param.bss_config.ps_sta_ageout_timer =
+ wlan_le32_to_cpu(
+ tlv_ps_sta_ageout->ps_sta_ageout_timer);
+ break;
+ case TLV_TYPE_UAP_RTS_THRESHOLD:
+ tlv_rts_threshold = (MrvlIEtypes_rts_threshold_t *)tlv;
+ bss->param.bss_config.rts_threshold = wlan_le16_to_cpu(
+ tlv_rts_threshold->rts_threshold);
+ break;
+ case TLV_TYPE_UAP_FRAG_THRESHOLD:
+ tlv_frag_threshold =
+ (MrvlIEtypes_frag_threshold_t *)tlv;
+ bss->param.bss_config.frag_threshold = wlan_le16_to_cpu(
+ tlv_frag_threshold->frag_threshold);
+ break;
+ case TLV_TYPE_UAP_RETRY_LIMIT:
+ tlv_retry_limit = (MrvlIEtypes_retry_limit_t *)tlv;
+ bss->param.bss_config.retry_limit =
+ tlv_retry_limit->retry_limit;
+ break;
+ case TLV_TYPE_UAP_EAPOL_PWK_HSK_TIMEOUT:
+ tlv_pairwise_timeout =
+ (MrvlIEtypes_eapol_pwk_hsk_timeout_t *)tlv;
+ bss->param.bss_config
+ .pairwise_update_timeout = wlan_le32_to_cpu(
+ tlv_pairwise_timeout->pairwise_update_timeout);
+ break;
+ case TLV_TYPE_UAP_EAPOL_PWK_HSK_RETRIES:
+ tlv_pairwise_retries =
+ (MrvlIEtypes_eapol_pwk_hsk_retries_t *)tlv;
+ bss->param.bss_config.pwk_retries = wlan_le32_to_cpu(
+ tlv_pairwise_retries->pwk_retries);
+ break;
+ case TLV_TYPE_UAP_EAPOL_GWK_HSK_TIMEOUT:
+ tlv_groupwise_timeout =
+ (MrvlIEtypes_eapol_gwk_hsk_timeout_t *)tlv;
+ bss->param.bss_config.groupwise_update_timeout =
+ wlan_le32_to_cpu(
+ tlv_groupwise_timeout
+ ->groupwise_update_timeout);
+ break;
+ case TLV_TYPE_UAP_EAPOL_GWK_HSK_RETRIES:
+ tlv_groupwise_retries =
+ (MrvlIEtypes_eapol_gwk_hsk_retries_t *)tlv;
+ bss->param.bss_config.gwk_retries = wlan_le32_to_cpu(
+ tlv_groupwise_retries->gwk_retries);
+ break;
+ case TLV_TYPE_UAP_MGMT_IE_PASSTHRU_MASK:
+ tlv_mgmt_ie_passthru =
+ (MrvlIEtypes_mgmt_ie_passthru_t *)tlv;
+ bss->param.bss_config.mgmt_ie_passthru_mask =
+ wlan_le32_to_cpu(
+ tlv_mgmt_ie_passthru->mgmt_ie_mask);
+ break;
+ case TLV_TYPE_2040_BSS_COEX_CONTROL:
+ tlv_2040_coex_enable =
+ (MrvlIEtypes_2040_coex_enable_t *)tlv;
+ bss->param.bss_config.enable_2040coex =
+ tlv_2040_coex_enable->enable_2040coex;
+ break;
+ case TLV_TYPE_UAP_STA_MAC_ADDR_FILTER:
+ tlv_mac_filter = (MrvlIEtypes_mac_filter_t *)tlv;
+ bss->param.bss_config.filter.mac_count =
+ MIN(MAX_MAC_FILTER_NUM, tlv_mac_filter->count);
+ bss->param.bss_config.filter.filter_mode =
+ tlv_mac_filter->filter_mode;
+ memcpy_ext(
+ pmpriv->adapter,
+ (t_u8 *)bss->param.bss_config.filter.mac_list,
+ tlv_mac_filter->mac_address,
+ MLAN_MAC_ADDR_LENGTH *
+ bss->param.bss_config.filter.mac_count,
+ sizeof(bss->param.bss_config.filter.mac_list));
+ break;
+ case TLV_TYPE_UAP_CHAN_BAND_CONFIG:
+ tlv_chan_band = (MrvlIEtypes_channel_band_t *)tlv;
+ bss->param.bss_config.bandcfg = tlv_chan_band->bandcfg;
+ bss->param.bss_config.channel = tlv_chan_band->channel;
+ pmpriv->uap_state_chan_cb.bandcfg =
+ tlv_chan_band->bandcfg;
+ pmpriv->uap_state_chan_cb.channel =
+ tlv_chan_band->channel;
+ break;
+ case TLV_TYPE_CHANLIST:
+ tlv_chan_list = (MrvlIEtypes_ChanListParamSet_t *)tlv;
+ bss->param.bss_config.num_of_chan =
+ tlv_len / sizeof(ChanScanParamSet_t);
+ pscan_chan = tlv_chan_list->chan_scan_param;
+ for (i = 0; i < bss->param.bss_config.num_of_chan;
+ i++) {
+ bss->param.bss_config.chan_list[i].chan_number =
+ pscan_chan->chan_number;
+ bss->param.bss_config.chan_list[i].bandcfg =
+ pscan_chan->bandcfg;
+ pscan_chan++;
+ }
+ break;
+ case TLV_TYPE_AUTH_TYPE:
+ tlv_auth_type = (MrvlIEtypes_auth_type_t *)tlv;
+ bss->param.bss_config.auth_mode =
+ tlv_auth_type->auth_type;
+ break;
+ case TLV_TYPE_UAP_ENCRYPT_PROTOCOL:
+ tlv_encrypt_protocol =
+ (MrvlIEtypes_encrypt_protocol_t *)tlv;
+ bss->param.bss_config.protocol = wlan_le16_to_cpu(
+ tlv_encrypt_protocol->protocol);
+ break;
+ case TLV_TYPE_UAP_AKMP:
+ tlv_akmp = (MrvlIEtypes_akmp_t *)tlv;
+ bss->param.bss_config.key_mgmt =
+ wlan_le16_to_cpu(tlv_akmp->key_mgmt);
+ if (tlv_len > sizeof(t_u16))
+ bss->param.bss_config.key_mgmt_operation =
+ wlan_le16_to_cpu(
+ tlv_akmp->key_mgmt_operation);
+ break;
+ case TLV_TYPE_PWK_CIPHER:
+ tlv_pwk_cipher = (MrvlIEtypes_pwk_cipher_t *)tlv;
+ if (wlan_le16_to_cpu(tlv_pwk_cipher->protocol) &
+ PROTOCOL_WPA)
+ bss->param.bss_config.wpa_cfg
+ .pairwise_cipher_wpa =
+ tlv_pwk_cipher->pairwise_cipher;
+ if (wlan_le16_to_cpu(tlv_pwk_cipher->protocol) &
+ PROTOCOL_WPA2)
+ bss->param.bss_config.wpa_cfg
+ .pairwise_cipher_wpa2 =
+ tlv_pwk_cipher->pairwise_cipher;
+ if (wlan_le16_to_cpu(tlv_pwk_cipher->protocol) &
+ PROTOCOL_WPA3_SAE)
+ bss->param.bss_config.wpa_cfg
+ .pairwise_cipher_wpa2 =
+ tlv_pwk_cipher->pairwise_cipher;
+ break;
+ case TLV_TYPE_GWK_CIPHER:
+ tlv_gwk_cipher = (MrvlIEtypes_gwk_cipher_t *)tlv;
+ bss->param.bss_config.wpa_cfg.group_cipher =
+ tlv_gwk_cipher->group_cipher;
+ break;
+ case TLV_TYPE_UAP_RSN_REPLAY_PROTECT:
+ tlv_rsn_prot = (MrvlIEtypes_rsn_replay_prot_t *)tlv;
+ bss->param.bss_config.wpa_cfg.rsn_protection =
+ tlv_rsn_prot->rsn_replay_prot;
+ break;
+ case TLV_TYPE_UAP_WPA_PASSPHRASE:
+ tlv_passphrase = (MrvlIEtypes_passphrase_t *)tlv;
+ bss->param.bss_config.wpa_cfg.length =
+ MIN(MLAN_PMK_HEXSTR_LENGTH, tlv_len);
+ memcpy_ext(pmpriv->adapter,
+ bss->param.bss_config.wpa_cfg.passphrase,
+ tlv_passphrase->passphrase,
+ bss->param.bss_config.wpa_cfg.length,
+ sizeof(bss->param.bss_config.wpa_cfg
+ .passphrase));
+ break;
+#ifdef WIFI_DIRECT_SUPPORT
+ case TLV_TYPE_UAP_PSK:
+ tlv_psk = (MrvlIEtypes_psk_t *)tlv;
+ memcpy_ext(pmpriv->adapter, bss->param.bss_config.psk,
+ tlv_psk->psk, tlv_len, MLAN_MAX_KEY_LENGTH);
+ break;
+#endif /* WIFI_DIRECT_SUPPORT */
+ case TLV_TYPE_UAP_GRP_REKEY_TIME:
+ tlv_rekey_time = (MrvlIEtypes_group_rekey_time_t *)tlv;
+ bss->param.bss_config.wpa_cfg.gk_rekey_time =
+ wlan_le32_to_cpu(tlv_rekey_time->gk_rekey_time);
+ break;
+ case TLV_TYPE_UAP_WEP_KEY:
+ tlv_wep_key = (MrvlIEtypes_wep_key_t *)tlv;
+ pkey = MNULL;
+ if (tlv_wep_key->key_index == 0)
+ pkey = &bss->param.bss_config.wep_cfg.key0;
+ else if (tlv_wep_key->key_index == 1)
+ pkey = &bss->param.bss_config.wep_cfg.key1;
+ else if (tlv_wep_key->key_index == 2)
+ pkey = &bss->param.bss_config.wep_cfg.key2;
+ else if (tlv_wep_key->key_index == 3)
+ pkey = &bss->param.bss_config.wep_cfg.key3;
+ if (pkey) {
+ pkey->key_index = tlv_wep_key->key_index;
+ pkey->is_default = tlv_wep_key->is_default;
+ pkey->length =
+ MIN(MAX_WEP_KEY_SIZE, (tlv_len - 2));
+ memcpy_ext(pmpriv->adapter, pkey->key,
+ tlv_wep_key->key, pkey->length,
+ pkey->length);
+ }
+ break;
+ case TLV_TYPE_UAP_PREAMBLE_CTL:
+ tlv_preamble = (MrvlIEtypes_preamble_t *)tlv;
+ bss->param.bss_config.preamble_type =
+ tlv_preamble->preamble_type;
+ break;
+ case TLV_TYPE_BSS_STATUS:
+ tlv_bss_status = (MrvlIEtypes_bss_status_t *)tlv;
+ bss->param.bss_config.bss_status =
+ wlan_le16_to_cpu(tlv_bss_status->bss_status);
+ pmpriv->uap_bss_started =
+ (bss->param.bss_config.bss_status) ? MTRUE :
+ MFALSE;
+ break;
+ case TLV_TYPE_HT_CAPABILITY:
+ tlv_htcap = (MrvlIETypes_HTCap_t *)tlv;
+ bss->param.bss_config.ht_cap_info =
+ wlan_le16_to_cpu(tlv_htcap->ht_cap.ht_cap_info);
+ bss->param.bss_config.ampdu_param =
+ tlv_htcap->ht_cap.ampdu_param;
+ memcpy_ext(
+ pmpriv->adapter,
+ bss->param.bss_config.supported_mcs_set,
+ tlv_htcap->ht_cap.supported_mcs_set, 16,
+ sizeof(bss->param.bss_config.supported_mcs_set));
+ bss->param.bss_config.ht_ext_cap =
+ wlan_le16_to_cpu(tlv_htcap->ht_cap.ht_ext_cap);
+ bss->param.bss_config.tx_bf_cap =
+ wlan_le32_to_cpu(tlv_htcap->ht_cap.tx_bf_cap);
+ bss->param.bss_config.asel = tlv_htcap->ht_cap.asel;
+ break;
+ case TLV_TYPE_VENDOR_SPECIFIC_IE:
+ tlv_wmm_parameter = (MrvlIEtypes_wmm_parameter_t *)tlv;
+ bss->param.bss_config.wmm_para.qos_info =
+ tlv_wmm_parameter->wmm_para.qos_info;
+ for (ac = 0; ac < 4; ac++) {
+ bss->param.bss_config.wmm_para.ac_params[ac]
+ .aci_aifsn.aifsn =
+ tlv_wmm_parameter->wmm_para
+ .ac_params[ac]
+ .aci_aifsn.aifsn;
+ bss->param.bss_config.wmm_para.ac_params[ac]
+ .aci_aifsn.aci =
+ tlv_wmm_parameter->wmm_para
+ .ac_params[ac]
+ .aci_aifsn.aci;
+ bss->param.bss_config.wmm_para.ac_params[ac]
+ .ecw.ecw_max =
+ tlv_wmm_parameter->wmm_para
+ .ac_params[ac]
+ .ecw.ecw_max;
+ bss->param.bss_config.wmm_para.ac_params[ac]
+ .ecw.ecw_min =
+ tlv_wmm_parameter->wmm_para
+ .ac_params[ac]
+ .ecw.ecw_min;
+ bss->param.bss_config.wmm_para.ac_params[ac]
+ .tx_op_limit = wlan_le16_to_cpu(
+ tlv_wmm_parameter->wmm_para
+ .ac_params[ac]
+ .tx_op_limit);
+ }
+ break;
+ }
+
+ tlv_buf_left -= tlv_len + sizeof(MrvlIEtypesHeader_t);
+ tlv = (MrvlIEtypesHeader_t *)((t_u8 *)tlv + tlv_len +
+ sizeof(MrvlIEtypesHeader_t));
+ }
+#ifdef DRV_EMBEDDED_AUTHENTICATOR
+ if (!IS_FW_SUPPORT_AUTHENTICATOR(pmpriv->adapter))
+ AuthenticatorBssConfig(pmpriv->psapriv,
+ (t_u8 *)&bss->param.bss_config, 0, 0, 1);
+#endif
+ LEAVE();
+ return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ * @brief This function handles the command response of sys_reset
+ * Clear various private state variables used by DFS.
+ *
+ * @param pmpriv A pointer to mlan_private structure
+ * @param resp A pointer to HostCmd_DS_COMMAND
+ * @param pioctl_buf A pointer to mlan_ioctl_req structure
+ *
+ * @return MLAN_STATUS_SUCCESS
+ */
+static mlan_status wlan_uap_ret_sys_reset(pmlan_private pmpriv,
+ HostCmd_DS_COMMAND *resp,
+ mlan_ioctl_req *pioctl_buf)
+{
+ ENTER();
+
+ memset(pmpriv->adapter, &(pmpriv->uap_state_chan_cb.bandcfg), 0,
+ sizeof(pmpriv->uap_state_chan_cb.bandcfg));
+ pmpriv->uap_state_chan_cb.channel = 0;
+ pmpriv->uap_state_chan_cb.beacon_period = 0;
+ pmpriv->uap_state_chan_cb.dtim_period = 0;
+
+ /* assume default 11d/11h states are off, should check with FW */
+ /* currently don't clear domain_info... global, could be from STA */
+ wlan_11d_priv_init(pmpriv);
+ wlan_11h_priv_init(pmpriv);
+
+ LEAVE();
+ return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ * @brief This function handles the command response of sys_config
+ *
+ * @param pmpriv A pointer to mlan_private structure
+ * @param resp A pointer to HostCmd_DS_COMMAND
+ * @param pioctl_buf A pointer to mlan_ioctl_req structure
+ *
+ * @return MLAN_STATUS_SUCCESS
+ */
+static mlan_status wlan_uap_ret_sys_config(pmlan_private pmpriv,
+ HostCmd_DS_COMMAND *resp,
+ mlan_ioctl_req *pioctl_buf)
+{
+ int resp_len = 0, travel_len = 0;
+ int i = 0;
+ custom_ie *cptr;
+ HostCmd_DS_SYS_CONFIG *sys_config =
+ (HostCmd_DS_SYS_CONFIG *)&resp->params.sys_config;
+ mlan_ds_bss *bss = MNULL;
+ mlan_ds_misc_cfg *misc = MNULL;
+ MrvlIEtypes_MacAddr_t *tlv =
+ (MrvlIEtypes_MacAddr_t *)sys_config->tlv_buffer;
+ mlan_ds_misc_custom_ie *cust_ie = MNULL;
+ tlvbuf_max_mgmt_ie *max_mgmt_ie = MNULL;
+ MrvlIEtypes_wmm_parameter_t *tlv_wmm_parameter =
+ (MrvlIEtypes_wmm_parameter_t *)sys_config->tlv_buffer;
+ MrvlIEtypes_ChanListParamSet_t *tlv_chan_list =
+ (MrvlIEtypes_ChanListParamSet_t *)sys_config->tlv_buffer;
+ MrvlIEtypes_channel_band_t *chan_band_tlv =
+ (MrvlIEtypes_channel_band_t *)sys_config->tlv_buffer;
+ ChanScanParamSet_t *pscan_chan = MNULL;
+ t_u8 ac = 0;
+ MrvlIEtypes_channel_band_t *tlv_cb = MNULL;
+ MrvlIEtypes_beacon_period_t *tlv_bcnpd = MNULL;
+ MrvlIEtypes_dtim_period_t *tlv_dtimpd = MNULL;
+ MrvlIEtypes_uap_max_sta_cnt_t *tlv_uap_max_sta = MNULL;
+
+ ENTER();
+ if (pioctl_buf) {
+ if (pioctl_buf->req_id == MLAN_IOCTL_BSS) {
+ bss = (mlan_ds_bss *)pioctl_buf->pbuf;
+ if (bss->sub_command == MLAN_OID_BSS_MAC_ADDR) {
+ if (TLV_TYPE_UAP_MAC_ADDRESS ==
+ wlan_le16_to_cpu(tlv->header.type)) {
+ memcpy_ext(pmpriv->adapter,
+ &bss->param.mac_addr,
+ tlv->mac,
+ MLAN_MAC_ADDR_LENGTH,
+ MLAN_MAC_ADDR_LENGTH);
+ }
+ } else if (bss->sub_command ==
+ MLAN_OID_UAP_CFG_WMM_PARAM) {
+ if (TLV_TYPE_AP_WMM_PARAM ==
+ wlan_le16_to_cpu(
+ tlv_wmm_parameter->header.type)) {
+ if (wlan_le16_to_cpu(
+ tlv_wmm_parameter->header
+ .len) <
+ sizeof(bss->param.ap_wmm_para)) {
+ PRINTM(MCMND,
+ "FW don't support AP WMM PARAM\n");
+ } else {
+ bss->param.ap_wmm_para.reserved =
+ MLAN_STATUS_COMPLETE;
+ for (ac = 0; ac < 4; ac++) {
+ bss->param.ap_wmm_para
+ .ac_params[ac]
+ .aci_aifsn
+ .aifsn =
+ tlv_wmm_parameter
+ ->wmm_para
+ .ac_params
+ [ac]
+ .aci_aifsn
+ .aifsn;
+ bss->param.ap_wmm_para
+ .ac_params[ac]
+ .aci_aifsn.aci =
+ tlv_wmm_parameter
+ ->wmm_para
+ .ac_params
+ [ac]
+ .aci_aifsn
+ .aci;
+ bss->param.ap_wmm_para
+ .ac_params[ac]
+ .ecw.ecw_max =
+ tlv_wmm_parameter
+ ->wmm_para
+ .ac_params
+ [ac]
+ .ecw
+ .ecw_max;
+ bss->param.ap_wmm_para
+ .ac_params[ac]
+ .ecw.ecw_min =
+ tlv_wmm_parameter
+ ->wmm_para
+ .ac_params
+ [ac]
+ .ecw
+ .ecw_min;
+ bss->param.ap_wmm_para
+ .ac_params[ac]
+ .tx_op_limit = wlan_le16_to_cpu(
+ tlv_wmm_parameter
+ ->wmm_para
+ .ac_params
+ [ac]
+ .tx_op_limit);
+ PRINTM(MCMND,
+ "ac=%d, aifsn=%d, aci=%d, ecw_max=%d, ecw_min=%d, tx_op=%d\n",
+ ac,
+ bss->param
+ .ap_wmm_para
+ .ac_params
+ [ac]
+ .aci_aifsn
+ .aifsn,
+ bss->param
+ .ap_wmm_para
+ .ac_params
+ [ac]
+ .aci_aifsn
+ .aci,
+ bss->param
+ .ap_wmm_para
+ .ac_params
+ [ac]
+ .ecw
+ .ecw_max,
+ bss->param
+ .ap_wmm_para
+ .ac_params
+ [ac]
+ .ecw
+ .ecw_min,
+ bss->param
+ .ap_wmm_para
+ .ac_params
+ [ac]
+ .tx_op_limit);
+ }
+ }
+ }
+ } else if (bss->sub_command ==
+ MLAN_OID_UAP_SCAN_CHANNELS) {
+ if (TLV_TYPE_CHANLIST ==
+ wlan_le16_to_cpu(
+ tlv_chan_list->header.type)) {
+ pscan_chan =
+ tlv_chan_list->chan_scan_param;
+ bss->param.ap_scan_channels.num_of_chan =
+ 0;
+ for (i = 0;
+ i <
+ wlan_le16_to_cpu(
+ tlv_chan_list->header.len) /
+ sizeof(ChanScanParamSet_t);
+ i++) {
+ if (bss->param.ap_scan_channels
+ .remove_nop_channel &&
+ wlan_11h_is_channel_under_nop(
+ pmpriv->adapter,
+ pscan_chan
+ ->chan_number)) {
+ bss->param
+ .ap_scan_channels
+ .num_remvoed_channel++;
+ PRINTM(MCMND,
+ "Remove nop channel=%d\n",
+ pscan_chan
+ ->chan_number);
+ pscan_chan++;
+ continue;
+ }
+ bss->param.ap_scan_channels
+ .chan_list
+ [bss->param
+ .ap_scan_channels
+ .num_of_chan]
+ .chan_number =
+ pscan_chan->chan_number;
+ bss->param.ap_scan_channels
+ .chan_list
+ [bss->param
+ .ap_scan_channels
+ .num_of_chan]
+ .bandcfg =
+ pscan_chan->bandcfg;
+ bss->param.ap_scan_channels
+ .num_of_chan++;
+ pscan_chan++;
+ }
+ PRINTM(MCMND,
+ "AP scan channel list=%d\n",
+ bss->param.ap_scan_channels
+ .num_of_chan);
+ }
+ } else if (bss->sub_command == MLAN_OID_UAP_CHANNEL) {
+ if (TLV_TYPE_UAP_CHAN_BAND_CONFIG ==
+ wlan_le16_to_cpu(
+ chan_band_tlv->header.type)) {
+ bss->param.ap_channel.bandcfg =
+ chan_band_tlv->bandcfg;
+ bss->param.ap_channel.channel =
+ chan_band_tlv->channel;
+ bss->param.ap_channel.is_11n_enabled =
+ pmpriv->is_11n_enabled;
+ bss->param.ap_channel.is_dfs_chan =
+ wlan_11h_radar_detect_required(
+ pmpriv,
+ bss->param.ap_channel
+ .channel);
+ if (chan_band_tlv->bandcfg.chanWidth ==
+ CHAN_BW_80MHZ)
+ bss->param.ap_channel
+ .center_chan =
+ wlan_get_center_freq_idx(
+ pmpriv,
+ BAND_AAC,
+ chan_band_tlv
+ ->channel,
+ CHANNEL_BW_80MHZ);
+ PRINTM(MCMND,
+ "AP channel, band=0x%x, channel=%d, is_11n_enabled=%d center_chan=%d\n",
+ bss->param.ap_channel.bandcfg,
+ bss->param.ap_channel.channel,
+ bss->param.ap_channel
+ .is_11n_enabled,
+ bss->param.ap_channel
+ .center_chan);
+ }
+ } else if ((bss->sub_command ==
+ MLAN_OID_UAP_BSS_CONFIG) &&
+ (pioctl_buf->action == MLAN_ACT_GET)) {
+ wlan_uap_ret_cmd_ap_config(pmpriv, resp,
+ pioctl_buf);
+ }
+ }
+ if (pioctl_buf->req_id == MLAN_IOCTL_MISC_CFG) {
+ misc = (mlan_ds_misc_cfg *)pioctl_buf->pbuf;
+ cust_ie = (mlan_ds_misc_custom_ie *)
+ sys_config->tlv_buffer;
+ if ((pioctl_buf->action == MLAN_ACT_GET ||
+ pioctl_buf->action == MLAN_ACT_SET) &&
+ (misc->sub_command == MLAN_OID_MISC_CUSTOM_IE)) {
+ cust_ie->type = wlan_le16_to_cpu(cust_ie->type);
+ resp_len = cust_ie->len =
+ wlan_le16_to_cpu(cust_ie->len);
+ travel_len = 0;
+ /* conversion for index, mask, len */
+ if (resp_len == sizeof(t_u16))
+ cust_ie->ie_data_list[0].ie_index =
+ wlan_cpu_to_le16(
+ cust_ie->ie_data_list[0]
+ .ie_index);
+
+ while (resp_len > sizeof(t_u16)) {
+ cptr = (custom_ie
+ *)(((t_u8 *)cust_ie
+ ->ie_data_list) +
+ travel_len);
+ cptr->ie_index = wlan_le16_to_cpu(
+ cptr->ie_index);
+ cptr->mgmt_subtype_mask =
+ wlan_le16_to_cpu(
+ cptr->mgmt_subtype_mask);
+ cptr->ie_length = wlan_le16_to_cpu(
+ cptr->ie_length);
+ travel_len += cptr->ie_length +
+ sizeof(custom_ie) -
+ MAX_IE_SIZE;
+ resp_len -= cptr->ie_length +
+ sizeof(custom_ie) -
+ MAX_IE_SIZE;
+ }
+ memcpy_ext(pmpriv->adapter,
+ &misc->param.cust_ie, cust_ie,
+ cust_ie->len +
+ sizeof(MrvlIEtypesHeader_t),
+ sizeof(mlan_ds_misc_custom_ie) -
+ sizeof(tlvbuf_max_mgmt_ie));
+ max_mgmt_ie =
+ (tlvbuf_max_mgmt_ie
+ *)(sys_config->tlv_buffer +
+ cust_ie->len +
+ sizeof(MrvlIEtypesHeader_t));
+ if (max_mgmt_ie) {
+ max_mgmt_ie->type = wlan_le16_to_cpu(
+ max_mgmt_ie->type);
+ if (max_mgmt_ie->type ==
+ TLV_TYPE_MAX_MGMT_IE) {
+ max_mgmt_ie->len =
+ wlan_le16_to_cpu(
+ max_mgmt_ie
+ ->len);
+ max_mgmt_ie->count =
+ wlan_le16_to_cpu(
+ max_mgmt_ie
+ ->count);
+ for (i = 0;
+ i < max_mgmt_ie->count;
+ i++) {
+ max_mgmt_ie->info[i]
+ .buf_size = wlan_le16_to_cpu(
+ max_mgmt_ie
+ ->info[i]
+ .buf_size);
+ max_mgmt_ie->info[i]
+ .buf_count = wlan_le16_to_cpu(
+ max_mgmt_ie
+ ->info[i]
+ .buf_count);
+ }
+ /* Append max_mgmt_ie TLV after
+ * custom_ie */
+ memcpy_ext(
+ pmpriv->adapter,
+ (t_u8 *)&misc->param
+ .cust_ie +
+ (cust_ie->len +
+ sizeof(MrvlIEtypesHeader_t)),
+ max_mgmt_ie,
+ max_mgmt_ie->len +
+ sizeof(MrvlIEtypesHeader_t),
+ sizeof(tlvbuf_max_mgmt_ie));
+ }
+ }
+ }
+ }
+ } else { /* no ioctl: driver generated get/set */
+ switch (wlan_le16_to_cpu(tlv->header.type)) {
+ case TLV_TYPE_UAP_MAC_ADDRESS:
+ memcpy_ext(pmpriv->adapter, pmpriv->curr_addr, tlv->mac,
+ MLAN_MAC_ADDR_LENGTH, MLAN_MAC_ADDR_LENGTH);
+ break;
+ case TLV_TYPE_UAP_MAX_STA_CNT_PER_CHIP:
+ tlv_uap_max_sta = (MrvlIEtypes_uap_max_sta_cnt_t *)tlv;
+ pmpriv->adapter->max_sta_conn =
+ wlan_le16_to_cpu(tlv_uap_max_sta->uap_max_sta);
+ PRINTM(MCMND, "Uap max_sta per chip=%d\n",
+ wlan_le16_to_cpu(tlv_uap_max_sta->uap_max_sta));
+ break;
+ case TLV_TYPE_UAP_CHAN_BAND_CONFIG:
+ tlv_cb = (MrvlIEtypes_channel_band_t *)tlv;
+ pmpriv->uap_state_chan_cb.bandcfg = tlv_cb->bandcfg;
+ pmpriv->uap_state_chan_cb.channel = tlv_cb->channel;
+ /* call callback waiting for channel info */
+ if (pmpriv->uap_state_chan_cb.get_chan_callback)
+ pmpriv->uap_state_chan_cb.get_chan_callback(
+ pmpriv);
+ break;
+ case TLV_TYPE_UAP_BEACON_PERIOD:
+ tlv_bcnpd = (MrvlIEtypes_beacon_period_t *)tlv;
+ pmpriv->uap_state_chan_cb.beacon_period =
+ wlan_le16_to_cpu(tlv_bcnpd->beacon_period);
+ /* copy dtim_period as well if it follows */
+ tlv_dtimpd =
+ (MrvlIEtypes_dtim_period_t
+ *)(((t_u8 *)tlv) +
+ sizeof(MrvlIEtypes_beacon_period_t));
+ if (TLV_TYPE_UAP_DTIM_PERIOD ==
+ wlan_le16_to_cpu(tlv_dtimpd->header.type))
+ pmpriv->uap_state_chan_cb.dtim_period =
+ tlv_dtimpd->dtim_period;
+ /* call callback waiting for beacon/dtim info */
+ if (pmpriv->uap_state_chan_cb.get_chan_callback)
+ pmpriv->uap_state_chan_cb.get_chan_callback(
+ pmpriv);
+ break;
+ case TLV_TYPE_MGMT_IE:
+ if ((pmpriv->adapter->state_rdh.stage ==
+ RDH_SET_CUSTOM_IE) ||
+ (pmpriv->adapter->state_rdh.stage ==
+ RDH_REM_CUSTOM_IE)) {
+ if (!pmpriv->adapter->ecsa_enable)
+ wlan_11h_radar_detected_callback(
+ (t_void *)pmpriv);
+ }
+ break;
+ }
+ }
+ LEAVE();
+ return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ * @brief This function prepares command of snmp_mib
+ *
+ * @param pmpriv A pointer to mlan_private structure
+ * @param cmd A pointer to HostCmd_DS_COMMAND structure
+ * @param cmd_action the action: GET or SET
+ * @param cmd_oid Cmd oid: treated as sub command
+ * @param pioctl_buf A pointer to mlan_ioctl_req structure
+ * @param pdata_buf A pointer to information buffer
+ * @return MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ */
+static mlan_status wlan_uap_cmd_snmp_mib(pmlan_private pmpriv,
+ HostCmd_DS_COMMAND *cmd,
+ t_u16 cmd_action, t_u32 cmd_oid,
+ pmlan_ioctl_req pioctl_buf,
+ t_void *pdata_buf)
+{
+ HostCmd_DS_802_11_SNMP_MIB *psnmp_mib = &cmd->params.smib;
+ HostCmd_DS_UAP_802_11_SNMP_MIB *puap_snmp_mib = &cmd->params.uap_smib;
+
+ mlan_status ret = MLAN_STATUS_SUCCESS;
+ t_u8 *psnmp_oid = MNULL;
+ t_u32 ul_temp;
+ t_u8 i;
+
+ t_u8 snmp_oids[] = {
+ tkip_mic_failures,
+ ccmp_decrypt_errors,
+ wep_undecryptable_count,
+ wep_icv_error_count,
+ decrypt_failure_count,
+ dot11_mcast_tx_count,
+ dot11_failed_count,
+ dot11_retry_count,
+ dot11_multi_retry_count,
+ dot11_frame_dup_count,
+ dot11_rts_success_count,
+ dot11_rts_failure_count,
+ dot11_ack_failure_count,
+ dot11_rx_fragment_count,
+ dot11_mcast_rx_frame_count,
+ dot11_fcs_error_count,
+ dot11_tx_frame_count,
+ dot11_rsna_tkip_cm_invoked,
+ dot11_rsna_4way_hshk_failures,
+ };
+
+ ENTER();
+
+ if (cmd_action == HostCmd_ACT_GEN_GET) {
+ cmd->command = wlan_cpu_to_le16(HostCmd_CMD_802_11_SNMP_MIB);
+ psnmp_mib->query_type = wlan_cpu_to_le16(HostCmd_ACT_GEN_GET);
+ if (cmd_oid == StopDeauth_i) {
+ psnmp_mib->oid = wlan_cpu_to_le16((t_u16)StopDeauth_i);
+ psnmp_mib->buf_size = wlan_cpu_to_le16(sizeof(t_u8));
+ cmd->size = wlan_cpu_to_le16(
+ sizeof(HostCmd_DS_802_11_SNMP_MIB) + S_DS_GEN);
+ } else {
+ cmd->size = wlan_cpu_to_le16(
+ sizeof(t_u16) + S_DS_GEN +
+ sizeof(snmp_oids) *
+ sizeof(MrvlIEtypes_snmp_oid_t));
+ psnmp_oid = (t_u8 *)&puap_snmp_mib->snmp_data;
+ for (i = 0; i < sizeof(snmp_oids); i++) {
+ /* SNMP OID header type */
+ *(t_u16 *)psnmp_oid =
+ wlan_cpu_to_le16(snmp_oids[i]);
+ psnmp_oid += sizeof(t_u16);
+ /* SNMP OID header length */
+ *(t_u16 *)psnmp_oid =
+ wlan_cpu_to_le16(sizeof(t_u32));
+ psnmp_oid += sizeof(t_u16) + sizeof(t_u32);
+ }
+ }
+ } else { /* cmd_action == ACT_SET */
+ cmd->command = wlan_cpu_to_le16(HostCmd_CMD_802_11_SNMP_MIB);
+ cmd->size = sizeof(HostCmd_DS_802_11_SNMP_MIB) - 1 + S_DS_GEN;
+ psnmp_mib->query_type = wlan_cpu_to_le16(HostCmd_ACT_GEN_SET);
+
+ switch (cmd_oid) {
+ case Dot11D_i:
+ case Dot11H_i:
+ psnmp_mib->oid = wlan_cpu_to_le16((t_u16)cmd_oid);
+ psnmp_mib->buf_size = wlan_cpu_to_le16(sizeof(t_u16));
+ ul_temp = *(t_u32 *)pdata_buf;
+ *((t_u16 *)(psnmp_mib->value)) =
+ wlan_cpu_to_le16((t_u16)ul_temp);
+ cmd->size += sizeof(t_u16);
+ break;
+ case ECSAEnable_i:
+ psnmp_mib->oid = wlan_cpu_to_le16((t_u16)cmd_oid);
+ psnmp_mib->buf_size = wlan_cpu_to_le16(sizeof(t_u8));
+ psnmp_mib->value[0] = *((t_u8 *)pdata_buf);
+ cmd->size += sizeof(t_u8);
+ break;
+ case StopDeauth_i:
+ psnmp_mib->oid = wlan_cpu_to_le16((t_u16)cmd_oid);
+ psnmp_mib->buf_size = wlan_cpu_to_le16(sizeof(t_u8));
+ psnmp_mib->value[0] = *((t_u8 *)pdata_buf);
+ cmd->size += sizeof(t_u8);
+ break;
+ default:
+ PRINTM(MERROR, "Unsupported OID.\n");
+ ret = MLAN_STATUS_FAILURE;
+ break;
+ }
+ cmd->size = wlan_cpu_to_le16(cmd->size);
+ }
+
+ LEAVE();
+ return ret;
+}
+
+/**
+ * @brief This function prepares command of get_log.
+ *
+ * @param pmpriv A pointer to mlan_private structure
+ * @param cmd A pointer to HostCmd_DS_COMMAND structure
+ *
+ * @return MLAN_STATUS_SUCCESS
+ */
+static mlan_status wlan_uap_cmd_802_11_get_log(pmlan_private pmpriv,
+ HostCmd_DS_COMMAND *cmd)
+{
+ ENTER();
+ cmd->command = wlan_cpu_to_le16(HostCmd_CMD_802_11_GET_LOG);
+ cmd->size =
+ wlan_cpu_to_le16(sizeof(HostCmd_DS_802_11_GET_LOG) + S_DS_GEN);
+ LEAVE();
+ return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ * @brief This function prepares command of bss_start.
+ *
+ * @param pmpriv A pointer to mlan_private structure
+ * @param cmd A pointer to HostCmd_DS_COMMAND structure
+ *
+ * @return MLAN_STATUS_SUCCESS
+ */
+static mlan_status wlan_uap_cmd_bss_start(pmlan_private pmpriv,
+ HostCmd_DS_COMMAND *cmd)
+{
+ MrvlIEtypes_HostMlme_t *tlv;
+
+ ENTER();
+ cmd->command = wlan_cpu_to_le16(HOST_CMD_APCMD_BSS_START);
+ cmd->size = S_DS_GEN;
+ if (pmpriv->uap_host_based & UAP_FLAG_HOST_MLME) {
+ tlv = (MrvlIEtypes_HostMlme_t *)((t_u8 *)cmd + cmd->size);
+ tlv->header.type = wlan_cpu_to_le16(TLV_TYPE_HOST_MLME);
+ tlv->header.len = wlan_cpu_to_le16(sizeof(tlv->host_mlme));
+ tlv->host_mlme = MTRUE;
+ cmd->size += sizeof(MrvlIEtypes_HostMlme_t);
+ }
+ cmd->size = wlan_cpu_to_le16(cmd->size);
+ LEAVE();
+ return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ * @brief This function handles the command response of snmp_mib
+ *
+ * @param pmpriv A pointer to mlan_private structure
+ * @param resp A pointer to HostCmd_DS_COMMAND
+ * @param pioctl_buf A pointer to mlan_ioctl_req structure
+ *
+ * @return MLAN_STATUS_SUCCESS
+ */
+static mlan_status wlan_uap_ret_snmp_mib(pmlan_private pmpriv,
+ HostCmd_DS_COMMAND *resp,
+ mlan_ioctl_req *pioctl_buf)
+{
+ pmlan_adapter pmadapter = pmpriv->adapter;
+ HostCmd_DS_802_11_SNMP_MIB *psnmp_mib =
+ (HostCmd_DS_802_11_SNMP_MIB *)&resp->params.smib;
+ mlan_ds_get_info *info;
+ mlan_ds_snmp_mib *mib = MNULL;
+ t_u16 oid = wlan_le16_to_cpu(psnmp_mib->oid);
+ t_u8 *psnmp_oid = MNULL;
+ t_u32 data;
+ t_u16 tlv_buf_left = 0;
+ t_u16 tlv_type = 0;
+ t_u16 query_type = wlan_le16_to_cpu(psnmp_mib->query_type);
+
+ ENTER();
+ if (query_type == HostCmd_ACT_GEN_GET) {
+ if (!pioctl_buf) {
+ LEAVE();
+ return MLAN_STATUS_SUCCESS;
+ }
+ if (oid == StopDeauth_i) {
+ mib = (mlan_ds_snmp_mib *)pioctl_buf->pbuf;
+ if (mib)
+ mib->param.deauthctrl = psnmp_mib->value[0];
+ LEAVE();
+ return MLAN_STATUS_SUCCESS;
+ }
+ info = (mlan_ds_get_info *)pioctl_buf->pbuf;
+ tlv_buf_left = resp->size - (sizeof(t_u16) + S_DS_GEN);
+ psnmp_oid = (t_u8 *)&psnmp_mib->oid;
+ while (tlv_buf_left >= sizeof(MrvlIEtypes_snmp_oid_t)) {
+ tlv_type = wlan_le16_to_cpu(*(t_u16 *)psnmp_oid);
+ psnmp_oid += sizeof(t_u16) + sizeof(t_u16);
+ memcpy_ext(pmadapter, &data, psnmp_oid, sizeof(t_u32),
+ sizeof(t_u32));
+ switch (tlv_type) {
+ case tkip_mic_failures:
+ info->param.ustats.tkip_mic_failures =
+ wlan_le32_to_cpu(data);
+ break;
+ case ccmp_decrypt_errors:
+ info->param.ustats.ccmp_decrypt_errors =
+ wlan_le32_to_cpu(data);
+ break;
+ case wep_undecryptable_count:
+ info->param.ustats.wep_undecryptable_count =
+ wlan_le32_to_cpu(data);
+ break;
+ case wep_icv_error_count:
+ info->param.ustats.wep_icv_error_count =
+ wlan_le32_to_cpu(data);
+ break;
+ case decrypt_failure_count:
+ info->param.ustats.decrypt_failure_count =
+ wlan_le32_to_cpu(data);
+ break;
+ case dot11_mcast_tx_count:
+ info->param.ustats.mcast_tx_count =
+ wlan_le32_to_cpu(data);
+ break;
+ case dot11_failed_count:
+ info->param.ustats.failed_count =
+ wlan_le32_to_cpu(data);
+ break;
+ case dot11_retry_count:
+ info->param.ustats.retry_count =
+ wlan_le32_to_cpu(data);
+ break;
+ case dot11_multi_retry_count:
+ info->param.ustats.multi_retry_count =
+ wlan_le32_to_cpu(data);
+ break;
+ case dot11_frame_dup_count:
+ info->param.ustats.frame_dup_count =
+ wlan_le32_to_cpu(data);
+ break;
+ case dot11_rts_success_count:
+ info->param.ustats.rts_success_count =
+ wlan_le32_to_cpu(data);
+ break;
+ case dot11_rts_failure_count:
+ info->param.ustats.rts_failure_count =
+ wlan_le32_to_cpu(data);
+ break;
+ case dot11_ack_failure_count:
+ info->param.ustats.ack_failure_count =
+ wlan_le32_to_cpu(data);
+ break;
+ case dot11_rx_fragment_count:
+ info->param.ustats.rx_fragment_count =
+ wlan_le32_to_cpu(data);
+ break;
+ case dot11_mcast_rx_frame_count:
+ info->param.ustats.mcast_rx_frame_count =
+ wlan_le32_to_cpu(data);
+ break;
+ case dot11_fcs_error_count:
+ info->param.ustats.fcs_error_count =
+ wlan_le32_to_cpu(data);
+ break;
+ case dot11_tx_frame_count:
+ info->param.ustats.tx_frame_count =
+ wlan_le32_to_cpu(data);
+ break;
+ case dot11_rsna_tkip_cm_invoked:
+ info->param.ustats.rsna_tkip_cm_invoked =
+ wlan_le32_to_cpu(data);
+ break;
+ case dot11_rsna_4way_hshk_failures:
+ info->param.ustats.rsna_4way_hshk_failures =
+ wlan_le32_to_cpu(data);
+ break;
+ }
+ tlv_buf_left -= sizeof(MrvlIEtypes_snmp_oid_t);
+ psnmp_oid += sizeof(t_u32);
+ }
+ } else { /* ACT_SET */
+ switch (wlan_le16_to_cpu(psnmp_mib->oid)) {
+ case Dot11D_i:
+ data = wlan_le16_to_cpu(*((t_u16 *)(psnmp_mib->value)));
+ /* Set 11d state to private */
+ pmpriv->state_11d.enable_11d = data;
+ /* Set user enable flag if called from ioctl */
+ if (pioctl_buf)
+ pmpriv->state_11d.user_enable_11d = data;
+ break;
+ case Dot11H_i:
+ data = wlan_le16_to_cpu(*((t_u16 *)(psnmp_mib->value)));
+ /* Set 11h state to priv */
+ pmpriv->intf_state_11h.is_11h_active =
+ (data & ENABLE_11H_MASK);
+ /* Set radar_det state to adapter */
+ pmpriv->adapter->state_11h.is_master_radar_det_active =
+ (data & MASTER_RADAR_DET_MASK) ? MTRUE : MFALSE;
+ pmpriv->adapter->state_11h.is_slave_radar_det_active =
+ (data & SLAVE_RADAR_DET_MASK) ? MTRUE : MFALSE;
+ break;
+ }
+ }
+
+ LEAVE();
+ return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ * @brief This function handles the command response of get_log
+ *
+ * @param pmpriv A pointer to mlan_private structure
+ * @param resp A pointer to HostCmd_DS_COMMAND
+ * @param pioctl_buf A pointer to mlan_ioctl_req structure
+ *
+ * @return MLAN_STATUS_SUCCESS
+ */
+static mlan_status wlan_uap_ret_get_log(pmlan_private pmpriv,
+ HostCmd_DS_COMMAND *resp,
+ mlan_ioctl_req *pioctl_buf)
+{
+ HostCmd_DS_802_11_GET_LOG *pget_log =
+ (HostCmd_DS_802_11_GET_LOG *)&resp->params.get_log;
+ mlan_ds_get_info *pget_info = MNULL;
+ int i = 0;
+
+ ENTER();
+
+ if (pioctl_buf) {
+ pget_info = (mlan_ds_get_info *)pioctl_buf->pbuf;
+ pget_info->param.stats.mcast_tx_frame =
+ wlan_le32_to_cpu(pget_log->mcast_tx_frame);
+ pget_info->param.stats.failed =
+ wlan_le32_to_cpu(pget_log->failed);
+ pget_info->param.stats.retry =
+ wlan_le32_to_cpu(pget_log->retry);
+ pget_info->param.stats.multi_retry =
+ wlan_le32_to_cpu(pget_log->multiretry);
+ pget_info->param.stats.frame_dup =
+ wlan_le32_to_cpu(pget_log->frame_dup);
+ pget_info->param.stats.rts_success =
+ wlan_le32_to_cpu(pget_log->rts_success);
+ pget_info->param.stats.rts_failure =
+ wlan_le32_to_cpu(pget_log->rts_failure);
+ pget_info->param.stats.ack_failure =
+ wlan_le32_to_cpu(pget_log->ack_failure);
+ pget_info->param.stats.rx_frag =
+ wlan_le32_to_cpu(pget_log->rx_frag);
+ pget_info->param.stats.mcast_rx_frame =
+ wlan_le32_to_cpu(pget_log->mcast_rx_frame);
+ pget_info->param.stats.fcs_error =
+ wlan_le32_to_cpu(pget_log->fcs_error);
+ pget_info->param.stats.tx_frame =
+ wlan_le32_to_cpu(pget_log->tx_frame);
+ pget_info->param.stats.wep_icv_error[0] =
+ wlan_le32_to_cpu(pget_log->wep_icv_err_cnt[0]);
+ pget_info->param.stats.wep_icv_error[1] =
+ wlan_le32_to_cpu(pget_log->wep_icv_err_cnt[1]);
+ pget_info->param.stats.wep_icv_error[2] =
+ wlan_le32_to_cpu(pget_log->wep_icv_err_cnt[2]);
+ pget_info->param.stats.wep_icv_error[3] =
+ wlan_le32_to_cpu(pget_log->wep_icv_err_cnt[3]);
+ pget_info->param.stats.bcn_rcv_cnt =
+ wlan_le32_to_cpu(pget_log->bcn_rcv_cnt);
+ pget_info->param.stats.bcn_miss_cnt =
+ wlan_le32_to_cpu(pget_log->bcn_miss_cnt);
+ pget_info->param.stats.amsdu_rx_cnt = pmpriv->amsdu_rx_cnt;
+ pget_info->param.stats.msdu_in_rx_amsdu_cnt =
+ pmpriv->msdu_in_rx_amsdu_cnt;
+ pget_info->param.stats.amsdu_tx_cnt = pmpriv->amsdu_tx_cnt;
+ pget_info->param.stats.msdu_in_tx_amsdu_cnt =
+ pmpriv->msdu_in_tx_amsdu_cnt;
+ pget_info->param.stats.rx_stuck_issue_cnt[0] =
+ wlan_le32_to_cpu(pget_log->rx_stuck_issue_cnt[0]);
+ pget_info->param.stats.rx_stuck_issue_cnt[1] =
+ wlan_le32_to_cpu(pget_log->rx_stuck_issue_cnt[1]);
+ pget_info->param.stats.rx_stuck_recovery_cnt =
+ wlan_le32_to_cpu(pget_log->rx_stuck_recovery_cnt);
+ pget_info->param.stats.rx_stuck_tsf[0] =
+ wlan_le64_to_cpu(pget_log->rx_stuck_tsf[0]);
+ pget_info->param.stats.rx_stuck_tsf[1] =
+ wlan_le64_to_cpu(pget_log->rx_stuck_tsf[1]);
+ pget_info->param.stats.tx_watchdog_recovery_cnt =
+ wlan_le32_to_cpu(pget_log->tx_watchdog_recovery_cnt);
+ pget_info->param.stats.tx_watchdog_tsf[0] =
+ wlan_le64_to_cpu(pget_log->tx_watchdog_tsf[0]);
+ pget_info->param.stats.tx_watchdog_tsf[1] =
+ wlan_le64_to_cpu(pget_log->tx_watchdog_tsf[1]);
+ pget_info->param.stats.channel_switch_ann_sent =
+ wlan_le32_to_cpu(pget_log->channel_switch_ann_sent);
+ pget_info->param.stats.channel_switch_state =
+ wlan_le32_to_cpu(pget_log->channel_switch_state);
+ pget_info->param.stats.reg_class =
+ wlan_le32_to_cpu(pget_log->reg_class);
+ pget_info->param.stats.channel_number =
+ wlan_le32_to_cpu(pget_log->channel_number);
+ pget_info->param.stats.channel_switch_mode =
+ wlan_le32_to_cpu(pget_log->channel_switch_mode);
+ if (pmpriv->adapter->getlog_enable) {
+ pget_info->param.stats.tx_frag_cnt =
+ wlan_le32_to_cpu(pget_log->tx_frag_cnt);
+ for (i = 0; i < 8; i++) {
+ pget_info->param.stats.qos_tx_frag_cnt[i] =
+ wlan_le32_to_cpu(
+ pget_log->qos_tx_frag_cnt[i]);
+ pget_info->param.stats.qos_failed_cnt[i] =
+ wlan_le32_to_cpu(
+ pget_log->qos_failed_cnt[i]);
+ pget_info->param.stats.qos_retry_cnt[i] =
+ wlan_le32_to_cpu(
+ pget_log->qos_retry_cnt[i]);
+ pget_info->param.stats.qos_multi_retry_cnt[i] =
+ wlan_le32_to_cpu(
+ pget_log->qos_multi_retry_cnt[i]);
+ pget_info->param.stats.qos_frm_dup_cnt[i] =
+ wlan_le32_to_cpu(
+ pget_log->qos_frm_dup_cnt[i]);
+ pget_info->param.stats.qos_rts_suc_cnt[i] =
+ wlan_le32_to_cpu(
+ pget_log->qos_rts_suc_cnt[i]);
+ pget_info->param.stats.qos_rts_failure_cnt[i] =
+ wlan_le32_to_cpu(
+ pget_log->qos_rts_failure_cnt[i]);
+ pget_info->param.stats.qos_ack_failure_cnt[i] =
+ wlan_le32_to_cpu(
+ pget_log->qos_ack_failure_cnt[i]);
+ pget_info->param.stats.qos_rx_frag_cnt[i] =
+ wlan_le32_to_cpu(
+ pget_log->qos_rx_frag_cnt[i]);
+ pget_info->param.stats.qos_tx_frm_cnt[i] =
+ wlan_le32_to_cpu(
+ pget_log->qos_tx_frm_cnt[i]);
+ pget_info->param.stats.qos_discarded_frm_cnt
+ [i] = wlan_le32_to_cpu(
+ pget_log->qos_discarded_frm_cnt[i]);
+ pget_info->param.stats.qos_mpdus_rx_cnt[i] =
+ wlan_le32_to_cpu(
+ pget_log->qos_mpdus_rx_cnt[i]);
+ pget_info->param.stats.qos_retries_rx_cnt[i] =
+ wlan_le32_to_cpu(
+ pget_log->qos_retries_rx_cnt[i]);
+ }
+ pget_info->param.stats.mgmt_ccmp_replays =
+ wlan_le32_to_cpu(pget_log->mgmt_ccmp_replays);
+ pget_info->param.stats.tx_amsdu_cnt =
+ wlan_le32_to_cpu(pget_log->tx_amsdu_cnt);
+ pget_info->param.stats.failed_amsdu_cnt =
+ wlan_le32_to_cpu(pget_log->failed_amsdu_cnt);
+ pget_info->param.stats.retry_amsdu_cnt =
+ wlan_le32_to_cpu(pget_log->retry_amsdu_cnt);
+ pget_info->param.stats.multi_retry_amsdu_cnt =
+ wlan_le32_to_cpu(
+ pget_log->multi_retry_amsdu_cnt);
+ pget_info->param.stats.tx_octets_in_amsdu_cnt =
+ wlan_le64_to_cpu(
+ pget_log->tx_octets_in_amsdu_cnt);
+ pget_info->param.stats.amsdu_ack_failure_cnt =
+ wlan_le32_to_cpu(
+ pget_log->amsdu_ack_failure_cnt);
+ pget_info->param.stats.rx_amsdu_cnt =
+ wlan_le32_to_cpu(pget_log->rx_amsdu_cnt);
+ pget_info->param.stats.rx_octets_in_amsdu_cnt =
+ wlan_le64_to_cpu(
+ pget_log->rx_octets_in_amsdu_cnt);
+ pget_info->param.stats.tx_ampdu_cnt =
+ wlan_le32_to_cpu(pget_log->tx_ampdu_cnt);
+ pget_info->param.stats.tx_mpdus_in_ampdu_cnt =
+ wlan_le32_to_cpu(
+ pget_log->tx_mpdus_in_ampdu_cnt);
+ pget_info->param.stats.tx_octets_in_ampdu_cnt =
+ wlan_le64_to_cpu(
+ pget_log->tx_octets_in_ampdu_cnt);
+ pget_info->param.stats.ampdu_rx_cnt =
+ wlan_le32_to_cpu(pget_log->ampdu_rx_cnt);
+ pget_info->param.stats.mpdu_in_rx_ampdu_cnt =
+ wlan_le32_to_cpu(
+ pget_log->mpdu_in_rx_ampdu_cnt);
+ pget_info->param.stats.rx_octets_in_ampdu_cnt =
+ wlan_le64_to_cpu(
+ pget_log->rx_octets_in_ampdu_cnt);
+ pget_info->param.stats.ampdu_delimiter_crc_error_cnt =
+ wlan_le32_to_cpu(
+ pget_log->ampdu_delimiter_crc_error_cnt);
+
+ /* Indicate ioctl complete */
+ pioctl_buf->data_read_written =
+ sizeof(mlan_ds_get_info);
+ } else
+ pioctl_buf->data_read_written =
+ sizeof(mlan_ds_get_stats_org) +
+ sizeof(pget_info->sub_command);
+ }
+ LEAVE();
+ return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ * @brief This function prepares command of deauth station
+ *
+ * @param pmpriv A pointer to mlan_private structure
+ * @param cmd A pointer to HostCmd_DS_COMMAND structure
+ * @param pdata_buf A pointer to data buffer
+ * @return MLAN_STATUS_SUCCESS
+ */
+static mlan_status wlan_uap_cmd_sta_deauth(pmlan_private pmpriv,
+ HostCmd_DS_COMMAND *cmd,
+ t_void *pdata_buf)
+{
+ HostCmd_DS_STA_DEAUTH *pcmd_sta_deauth =
+ (HostCmd_DS_STA_DEAUTH *)&cmd->params.sta_deauth;
+ mlan_deauth_param *deauth = (mlan_deauth_param *)pdata_buf;
+
+ ENTER();
+ cmd->command = wlan_cpu_to_le16(HOST_CMD_APCMD_STA_DEAUTH);
+ cmd->size = wlan_cpu_to_le16(S_DS_GEN + sizeof(HostCmd_DS_STA_DEAUTH));
+ memcpy_ext(pmpriv->adapter, pcmd_sta_deauth->mac, deauth->mac_addr,
+ MLAN_MAC_ADDR_LENGTH, MLAN_MAC_ADDR_LENGTH);
+ pcmd_sta_deauth->reason = wlan_cpu_to_le16(deauth->reason_code);
+ LEAVE();
+ return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ * @brief This function prepares command of report mic_err
+ *
+ * @param pmpriv A pointer to mlan_private structure
+ * @param cmd A pointer to HostCmd_DS_COMMAND structure
+ * @param pdata_buf A pointer to data buffer
+ * @return MLAN_STATUS_SUCCESS
+ */
+static mlan_status wlan_uap_cmd_report_mic(pmlan_private pmpriv,
+ HostCmd_DS_COMMAND *cmd,
+ t_void *pdata_buf)
+{
+ HostCmd_DS_REPORT_MIC *pcmd_report_mic =
+ (HostCmd_DS_REPORT_MIC *)&cmd->params.report_mic;
+
+ ENTER();
+ cmd->command = wlan_cpu_to_le16(HOST_CMD_APCMD_REPORT_MIC);
+ cmd->size = wlan_cpu_to_le16(S_DS_GEN + sizeof(HostCmd_DS_REPORT_MIC));
+ memcpy_ext(pmpriv->adapter, pcmd_report_mic->mac, pdata_buf,
+ MLAN_MAC_ADDR_LENGTH, MLAN_MAC_ADDR_LENGTH);
+ LEAVE();
+ return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ * @brief This function prepares command of key material
+ *
+ * @param pmpriv A pointer to mlan_private structure
+ * @param cmd A pointer to HostCmd_DS_COMMAND structure
+ * @param cmd_action The action: GET or SET
+ * @param cmd_oid OID: ENABLE or DISABLE
+ * @param pdata_buf A pointer to data buffer
+ * @return MLAN_STATUS_SUCCESS
+ */
+static mlan_status wlan_uap_cmd_key_material(pmlan_private pmpriv,
+ HostCmd_DS_COMMAND *cmd,
+ t_u16 cmd_action, t_u16 cmd_oid,
+ t_void *pdata_buf)
+{
+ HostCmd_DS_802_11_KEY_MATERIAL *pkey_material =
+ &cmd->params.key_material;
+ mlan_ds_encrypt_key *pkey = (mlan_ds_encrypt_key *)pdata_buf;
+ mlan_status ret = MLAN_STATUS_SUCCESS;
+ sta_node *sta_ptr = MNULL;
+
+ ENTER();
+ if (!pkey) {
+ ret = MLAN_STATUS_FAILURE;
+ goto done;
+ }
+ cmd->command = wlan_cpu_to_le16(HostCmd_CMD_802_11_KEY_MATERIAL);
+ pkey_material->action = wlan_cpu_to_le16(cmd_action);
+ if (cmd_action == HostCmd_ACT_GEN_GET) {
+ cmd->size = wlan_cpu_to_le16(sizeof(pkey_material->action) +
+ S_DS_GEN);
+ goto done;
+ }
+ memset(pmpriv->adapter, &pkey_material->key_param_set, 0,
+ sizeof(MrvlIEtype_KeyParamSetV2_t));
+ if (pkey->key_flags & KEY_FLAG_REMOVE_KEY) {
+ pkey_material->action =
+ wlan_cpu_to_le16(HostCmd_ACT_GEN_REMOVE);
+ pkey_material->key_param_set.type =
+ wlan_cpu_to_le16(TLV_TYPE_KEY_PARAM_V2);
+ pkey_material->key_param_set.length =
+ wlan_cpu_to_le16(KEY_PARAMS_FIXED_LEN);
+ pkey_material->key_param_set.key_idx =
+ pkey->key_index & KEY_INDEX_MASK;
+ pkey_material->key_param_set.key_info = wlan_cpu_to_le16(
+ KEY_INFO_MCAST_KEY | KEY_INFO_UCAST_KEY);
+ memcpy_ext(pmpriv->adapter,
+ pkey_material->key_param_set.mac_addr,
+ pkey->mac_addr, MLAN_MAC_ADDR_LENGTH,
+ MLAN_MAC_ADDR_LENGTH);
+ cmd->size = wlan_cpu_to_le16(sizeof(MrvlIEtypesHeader_t) +
+ S_DS_GEN + KEY_PARAMS_FIXED_LEN +
+ sizeof(pkey_material->action));
+ PRINTM(MCMND, "Remove Key\n");
+ goto done;
+ }
+ pkey_material->action = wlan_cpu_to_le16(HostCmd_ACT_GEN_SET);
+ pkey_material->key_param_set.key_idx = pkey->key_index & KEY_INDEX_MASK;
+ pkey_material->key_param_set.type =
+ wlan_cpu_to_le16(TLV_TYPE_KEY_PARAM_V2);
+ pkey_material->key_param_set.key_info = KEY_INFO_ENABLE_KEY;
+ memcpy_ext(pmpriv->adapter, pkey_material->key_param_set.mac_addr,
+ pkey->mac_addr, MLAN_MAC_ADDR_LENGTH, MLAN_MAC_ADDR_LENGTH);
+ if (pkey->key_len <= MAX_WEP_KEY_SIZE) {
+ pkey_material->key_param_set.length = wlan_cpu_to_le16(
+ KEY_PARAMS_FIXED_LEN + sizeof(wep_param_t));
+ pkey_material->key_param_set.key_type = KEY_TYPE_ID_WEP;
+ pkey_material->key_param_set.key_info |=
+ KEY_INFO_MCAST_KEY | KEY_INFO_UCAST_KEY;
+ if (pkey_material->key_param_set.key_idx ==
+ (pmpriv->wep_key_curr_index & KEY_INDEX_MASK))
+ pkey_material->key_param_set.key_info |=
+ KEY_INFO_DEFAULT_KEY;
+ pkey_material->key_param_set.key_info =
+ wlan_cpu_to_le16(pkey_material->key_param_set.key_info);
+ pkey_material->key_param_set.key_params.wep.key_len =
+ wlan_cpu_to_le16(pkey->key_len);
+ memcpy_ext(pmpriv->adapter,
+ pkey_material->key_param_set.key_params.wep.key,
+ pkey->key_material, pkey->key_len, MAX_WEP_KEY_SIZE);
+ cmd->size = wlan_cpu_to_le16(sizeof(MrvlIEtypesHeader_t) +
+ S_DS_GEN + KEY_PARAMS_FIXED_LEN +
+ sizeof(wep_param_t) +
+ sizeof(pkey_material->action));
+ PRINTM(MCMND, "Set WEP Key\n");
+ goto done;
+ }
+ if (pkey->key_flags & KEY_FLAG_GROUP_KEY)
+ pkey_material->key_param_set.key_info |= KEY_INFO_MCAST_KEY;
+ else
+ pkey_material->key_param_set.key_info |= KEY_INFO_UCAST_KEY;
+ if (pkey->key_flags & KEY_FLAG_AES_MCAST_IGTK)
+ pkey_material->key_param_set.key_info = KEY_INFO_CMAC_AES_KEY;
+ if (pkey->key_flags & KEY_FLAG_SET_TX_KEY)
+ pkey_material->key_param_set.key_info |=
+ KEY_INFO_TX_KEY | KEY_INFO_RX_KEY;
+ else
+ pkey_material->key_param_set.key_info |= KEY_INFO_TX_KEY;
+ if (pkey->is_wapi_key) {
+ pkey_material->key_param_set.key_type = KEY_TYPE_ID_WAPI;
+ memcpy_ext(pmpriv->adapter,
+ pkey_material->key_param_set.key_params.wapi.pn,
+ pkey->pn, PN_SIZE, PN_SIZE);
+ pkey_material->key_param_set.key_params.wapi.key_len =
+ wlan_cpu_to_le16(MIN(WAPI_KEY_SIZE, pkey->key_len));
+ memcpy_ext(pmpriv->adapter,
+ pkey_material->key_param_set.key_params.wapi.key,
+ pkey->key_material, pkey->key_len, WAPI_KEY_SIZE);
+ if (!pmpriv->sec_info.wapi_key_on)
+ pkey_material->key_param_set.key_info |=
+ KEY_INFO_DEFAULT_KEY;
+ if (pkey->key_flags & KEY_FLAG_GROUP_KEY) {
+ pmpriv->sec_info.wapi_key_on = MTRUE;
+ } else {
+ /* WAPI pairwise key: unicast */
+ sta_ptr =
+ wlan_add_station_entry(pmpriv, pkey->mac_addr);
+ if (sta_ptr) {
+ PRINTM(MCMND, "station: wapi_key_on\n");
+ sta_ptr->wapi_key_on = MTRUE;
+ }
+ }
+ pkey_material->key_param_set.key_info =
+ wlan_cpu_to_le16(pkey_material->key_param_set.key_info);
+ pkey_material->key_param_set.length = wlan_cpu_to_le16(
+ KEY_PARAMS_FIXED_LEN + sizeof(wapi_param));
+ cmd->size = wlan_cpu_to_le16(sizeof(MrvlIEtypesHeader_t) +
+ S_DS_GEN + KEY_PARAMS_FIXED_LEN +
+ sizeof(wapi_param) +
+ sizeof(pkey_material->action));
+ PRINTM(MCMND, "Set WAPI Key\n");
+ goto done;
+ }
+ pkey_material->key_param_set.key_info |= KEY_INFO_DEFAULT_KEY;
+ pkey_material->key_param_set.key_info =
+ wlan_cpu_to_le16(pkey_material->key_param_set.key_info);
+ if (pkey->key_len == WPA_AES_KEY_LEN &&
+ !(pkey->key_flags & KEY_FLAG_AES_MCAST_IGTK)) {
+ if (pkey->key_flags &
+ (KEY_FLAG_RX_SEQ_VALID | KEY_FLAG_TX_SEQ_VALID))
+ memcpy_ext(
+ pmpriv->adapter,
+ pkey_material->key_param_set.key_params.aes.pn,
+ pkey->pn, SEQ_MAX_SIZE, WPA_PN_SIZE);
+ pkey_material->key_param_set.key_type = KEY_TYPE_ID_AES;
+ pkey_material->key_param_set.key_params.aes.key_len =
+ wlan_cpu_to_le16(pkey->key_len);
+ memcpy_ext(pmpriv->adapter,
+ pkey_material->key_param_set.key_params.aes.key,
+ pkey->key_material, pkey->key_len, WPA_AES_KEY_LEN);
+ pkey_material->key_param_set.length = wlan_cpu_to_le16(
+ KEY_PARAMS_FIXED_LEN + sizeof(aes_param));
+ cmd->size = wlan_cpu_to_le16(sizeof(MrvlIEtypesHeader_t) +
+ S_DS_GEN + KEY_PARAMS_FIXED_LEN +
+ sizeof(aes_param) +
+ sizeof(pkey_material->action));
+ PRINTM(MCMND, "Set AES Key\n");
+ goto done;
+ }
+ if (pkey->key_len == WPA_IGTK_KEY_LEN &&
+ (pkey->key_flags & KEY_FLAG_AES_MCAST_IGTK)) {
+ if (pkey->key_flags &
+ (KEY_FLAG_RX_SEQ_VALID | KEY_FLAG_TX_SEQ_VALID))
+ memcpy_ext(pmpriv->adapter,
+ pkey_material->key_param_set.key_params
+ .cmac_aes.ipn,
+ pkey->pn, SEQ_MAX_SIZE, IGTK_PN_SIZE);
+ pkey_material->key_param_set.key_info &=
+ ~(wlan_cpu_to_le16(KEY_INFO_MCAST_KEY));
+ pkey_material->key_param_set.key_info |=
+ wlan_cpu_to_le16(KEY_INFO_AES_MCAST_IGTK);
+ pkey_material->key_param_set.key_type = KEY_TYPE_ID_AES_CMAC;
+ pkey_material->key_param_set.key_params.cmac_aes.key_len =
+ wlan_cpu_to_le16(pkey->key_len);
+ memcpy_ext(pmpriv->adapter,
+ pkey_material->key_param_set.key_params.cmac_aes.key,
+ pkey->key_material, pkey->key_len, CMAC_AES_KEY_LEN);
+ pkey_material->key_param_set.length = wlan_cpu_to_le16(
+ KEY_PARAMS_FIXED_LEN + sizeof(cmac_aes_param));
+ cmd->size = wlan_cpu_to_le16(sizeof(MrvlIEtypesHeader_t) +
+ S_DS_GEN + KEY_PARAMS_FIXED_LEN +
+ sizeof(cmac_aes_param) +
+ sizeof(pkey_material->action));
+ PRINTM(MCMND, "Set CMAC AES Key\n");
+ goto done;
+ }
+ if (pkey->key_len == WPA_TKIP_KEY_LEN) {
+ if (pkey->key_flags &
+ (KEY_FLAG_RX_SEQ_VALID | KEY_FLAG_TX_SEQ_VALID))
+ memcpy_ext(
+ pmpriv->adapter,
+ pkey_material->key_param_set.key_params.tkip.pn,
+ pkey->pn, SEQ_MAX_SIZE, WPA_PN_SIZE);
+ pkey_material->key_param_set.key_type = KEY_TYPE_ID_TKIP;
+ pkey_material->key_param_set.key_params.tkip.key_len =
+ wlan_cpu_to_le16(pkey->key_len);
+ memcpy_ext(pmpriv->adapter,
+ pkey_material->key_param_set.key_params.tkip.key,
+ pkey->key_material, pkey->key_len, WPA_TKIP_KEY_LEN);
+ pkey_material->key_param_set.length = wlan_cpu_to_le16(
+ KEY_PARAMS_FIXED_LEN + sizeof(tkip_param));
+ cmd->size = wlan_cpu_to_le16(sizeof(MrvlIEtypesHeader_t) +
+ S_DS_GEN + KEY_PARAMS_FIXED_LEN +
+ sizeof(tkip_param) +
+ sizeof(pkey_material->action));
+ PRINTM(MCMND, "Set TKIP Key\n");
+ }
+done:
+ LEAVE();
+ return ret;
+}
+
+/**
+ * @brief This function handles the command response of sta_list
+ *
+ * @param pmpriv A pointer to mlan_private structure
+ * @param resp A pointer to HostCmd_DS_COMMAND
+ * @param pioctl_buf A pointer to mlan_ioctl_req structure
+ *
+ * @return MLAN_STATUS_SUCCESS
+ */
+static mlan_status wlan_uap_ret_sta_list(pmlan_private pmpriv,
+ HostCmd_DS_COMMAND *resp,
+ mlan_ioctl_req *pioctl_buf)
+{
+ HostCmd_DS_STA_LIST *sta_list =
+ (HostCmd_DS_STA_LIST *)&resp->params.sta_list;
+ mlan_ds_get_info *info;
+ MrvlIEtypes_sta_info_t *tlv = MNULL;
+ t_u8 i = 0;
+ sta_node *sta_ptr;
+ t_u8 tlv_len = 0;
+ t_u8 *buf = MNULL;
+
+ ENTER();
+ if (pioctl_buf) {
+ info = (mlan_ds_get_info *)pioctl_buf->pbuf;
+ info->param.sta_list.sta_count =
+ wlan_le16_to_cpu(sta_list->sta_count);
+ buf = sta_list->tlv_buf;
+ tlv = (MrvlIEtypes_sta_info_t *)buf;
+ info->param.sta_list.sta_count =
+ MIN(info->param.sta_list.sta_count, MAX_NUM_CLIENTS);
+ pioctl_buf->data_read_written =
+ sizeof(info->param.sta_list.sta_count);
+ for (i = 0; i < info->param.sta_list.sta_count; i++) {
+ tlv_len = wlan_le16_to_cpu(tlv->header.len);
+ memcpy_ext(pmpriv->adapter,
+ info->param.sta_list.info[i].mac_address,
+ tlv->mac_address, MLAN_MAC_ADDR_LENGTH,
+ MLAN_MAC_ADDR_LENGTH);
+ info->param.sta_list.info[i].ie_len =
+ tlv_len + sizeof(MrvlIEtypesHeader_t) -
+ sizeof(MrvlIEtypes_sta_info_t);
+ if (info->param.sta_list.info[i].ie_len)
+ memcpy_ext(pmpriv->adapter,
+ info->param.sta_list.info[i].ie_buf,
+ tlv->ie_buf,
+ info->param.sta_list.info[i].ie_len,
+ info->param.sta_list.info[i].ie_len);
+ info->param.sta_list.info[i].power_mgmt_status =
+ tlv->power_mgmt_status;
+ info->param.sta_list.info[i].rssi = tlv->rssi;
+ sta_ptr = wlan_get_station_entry(pmpriv,
+ tlv->mac_address);
+ if (sta_ptr) {
+ info->param.sta_list.info[i].bandmode =
+ sta_ptr->bandmode;
+ memcpy_ext(
+ pmpriv->adapter,
+ &(info->param.sta_list.info[i].stats),
+ &(sta_ptr->stats), sizeof(sta_stats),
+ sizeof(sta_stats));
+ } else
+ info->param.sta_list.info[i].bandmode = 0xFF;
+ pioctl_buf->data_read_written +=
+ sizeof(sta_info) +
+ info->param.sta_list.info[i].ie_len;
+ buf += sizeof(MrvlIEtypes_sta_info_t) +
+ info->param.sta_list.info[i].ie_len;
+ tlv = (MrvlIEtypes_sta_info_t *)buf;
+ }
+ PRINTM(MCMND, "Total sta_list size=%d\n",
+ pioctl_buf->data_read_written);
+ }
+
+ LEAVE();
+ return MLAN_STATUS_SUCCESS;
+}
+
+/** Fixed size of bss start event */
+#define BSS_START_EVENT_FIX_SIZE 12
+
+/**
+ * @brief This function will search for the specific ie
+ *
+ * @param priv A pointer to mlan_private
+ * @param pevent A pointer to event buf
+ *
+ * @return N/A
+ */
+static void wlan_check_uap_capability(pmlan_private priv, pmlan_buffer pevent)
+{
+ t_u16 tlv_type, tlv_len;
+ int tlv_buf_left = pevent->data_len - BSS_START_EVENT_FIX_SIZE;
+ MrvlIEtypesHeader_t *tlv =
+ (MrvlIEtypesHeader_t *)(pevent->pbuf + pevent->data_offset +
+ BSS_START_EVENT_FIX_SIZE);
+
+ const t_u8 wmm_oui[4] = {0x00, 0x50, 0xf2, 0x02};
+ IEEEtypes_WmmParameter_t wmm_param_ie;
+ MrvlIEtypes_channel_band_t *pchan_info;
+ t_u8 event_buf[100];
+ mlan_event *event = (mlan_event *)event_buf;
+ chan_band_info *pchan_band_info = (chan_band_info *)event->event_buf;
+ MrvlIEtypes_He_cap_t *pext_tlv = MNULL;
+
+ ENTER();
+ priv->wmm_enabled = MFALSE;
+ priv->pkt_fwd = MFALSE;
+ priv->is_11n_enabled = MFALSE;
+ priv->is_11ac_enabled = MFALSE;
+ priv->is_11ax_enabled = MFALSE;
+
+ while (tlv_buf_left >= (int)sizeof(MrvlIEtypesHeader_t)) {
+ tlv_type = wlan_le16_to_cpu(tlv->type);
+ tlv_len = wlan_le16_to_cpu(tlv->len);
+ if ((sizeof(MrvlIEtypesHeader_t) + tlv_len) >
+ (unsigned int)tlv_buf_left) {
+ PRINTM(MERROR, "wrong tlv: tlvLen=%d, tlvBufLeft=%d\n",
+ tlv_len, tlv_buf_left);
+ break;
+ }
+ if (tlv_type == HT_CAPABILITY) {
+ DBG_HEXDUMP(MCMD_D, "HT_CAP tlv", tlv,
+ tlv_len + sizeof(MrvlIEtypesHeader_t));
+ priv->is_11n_enabled = MTRUE;
+ }
+ if (tlv_type == VHT_CAPABILITY) {
+ DBG_HEXDUMP(MCMD_D, "VHT_CAP tlv", tlv,
+ tlv_len + sizeof(MrvlIEtypesHeader_t));
+ priv->is_11ac_enabled = MTRUE;
+ }
+ if (tlv_type == EXTENSION) {
+ pext_tlv = (MrvlIEtypes_He_cap_t *)tlv;
+ if (pext_tlv->ext_id == HE_CAPABILITY) {
+ DBG_HEXDUMP(
+ MCMD_D, "HE_CAP tlv", tlv,
+ tlv_len + sizeof(MrvlIEtypesHeader_t));
+ priv->is_11ax_enabled = MTRUE;
+ }
+ }
+
+ if (tlv_type == VENDOR_SPECIFIC_221) {
+ if (!memcmp(priv->adapter,
+ (t_u8 *)tlv + sizeof(MrvlIEtypesHeader_t),
+ wmm_oui, sizeof(wmm_oui))) {
+ DBG_HEXDUMP(
+ MCMD_D, "wmm ie tlv", tlv,
+ tlv_len + sizeof(MrvlIEtypesHeader_t));
+ priv->wmm_enabled = MFALSE;
+ wlan_wmm_setup_ac_downgrade(priv);
+ priv->wmm_enabled = MTRUE;
+ memcpy_ext(priv->adapter, &wmm_param_ie,
+ ((t_u8 *)tlv + 2),
+ sizeof(IEEEtypes_WmmParameter_t),
+ sizeof(IEEEtypes_WmmParameter_t));
+ wmm_param_ie.vend_hdr.len = (t_u8)tlv_len;
+ wmm_param_ie.vend_hdr.element_id = WMM_IE;
+ wlan_wmm_setup_queue_priorities(priv,
+ &wmm_param_ie);
+ }
+ }
+ if (tlv_type == TLV_TYPE_UAP_PKT_FWD_CTL) {
+ DBG_HEXDUMP(MCMD_D, "pkt_fwd tlv", tlv,
+ tlv_len + sizeof(MrvlIEtypesHeader_t));
+ priv->pkt_fwd =
+ *((t_u8 *)tlv + sizeof(MrvlIEtypesHeader_t));
+ PRINTM(MCMND, "pkt_fwd FW: 0x%x\n", priv->pkt_fwd);
+ if (priv->pkt_fwd & PKT_FWD_FW_BIT)
+ priv->pkt_fwd = MFALSE;
+ else
+ priv->pkt_fwd |= PKT_FWD_ENABLE_BIT;
+ PRINTM(MCMND, "pkt_fwd DRV: 0x%x\n", priv->pkt_fwd);
+ }
+ if (tlv_type == TLV_TYPE_UAP_CHAN_BAND_CONFIG) {
+ DBG_HEXDUMP(MCMD_D, "chan_band_config tlv", tlv,
+ tlv_len + sizeof(MrvlIEtypesHeader_t));
+ pchan_info = (MrvlIEtypes_channel_band_t *)tlv;
+ priv->uap_channel = pchan_info->channel;
+ PRINTM(MCMND, "uap_channel FW: 0x%x\n",
+ priv->uap_channel);
+ event->bss_index = priv->bss_index;
+ event->event_id = MLAN_EVENT_ID_DRV_UAP_CHAN_INFO;
+ event->event_len = sizeof(chan_band_info);
+ memcpy_ext(priv->adapter,
+ (t_u8 *)&pchan_band_info->bandcfg,
+ (t_u8 *)&pchan_info->bandcfg, tlv_len,
+ tlv_len);
+ if (pchan_band_info->bandcfg.chanWidth == CHAN_BW_80MHZ)
+ pchan_band_info->center_chan =
+ wlan_get_center_freq_idx(
+ priv, BAND_AAC,
+ pchan_info->channel,
+ CHANNEL_BW_80MHZ);
+ if (priv->adapter->ecsa_enable) {
+ int ret;
+ t_u8 bandwidth = BW_20MHZ;
+
+ MrvlIEtypes_chan_bw_oper_t chan_bw_oper;
+ chan_bw_oper.header.type = REGULATORY_CLASS;
+ chan_bw_oper.header.len =
+ sizeof(MrvlIEtypes_chan_bw_oper_t);
+ chan_bw_oper.ds_chan_bw_oper.channel =
+ pchan_info->channel;
+
+ if (pchan_band_info->bandcfg.chanWidth ==
+ CHAN_BW_40MHZ)
+ bandwidth = BW_40MHZ;
+ else if (pchan_band_info->bandcfg.chanWidth ==
+ CHAN_BW_80MHZ)
+ bandwidth = BW_80MHZ;
+ chan_bw_oper.ds_chan_bw_oper.bandwidth =
+ bandwidth;
+
+ ret = wlan_prepare_cmd(
+ priv, HOST_CMD_APCMD_SYS_CONFIGURE,
+ HostCmd_ACT_GEN_SET, 0, MNULL,
+ &chan_bw_oper);
+ if (ret != MLAN_STATUS_SUCCESS &&
+ ret != MLAN_STATUS_PENDING) {
+ PRINTM(MERROR,
+ "%s(): Could not set supported operating class IE for priv=%p [priv_bss_idx=%d]!\n",
+ __func__, priv, priv->bss_index);
+ }
+ }
+ }
+
+ tlv_buf_left -= (sizeof(MrvlIEtypesHeader_t) + tlv_len);
+ tlv = (MrvlIEtypesHeader_t *)((t_u8 *)tlv + tlv_len +
+ sizeof(MrvlIEtypesHeader_t));
+ }
+ if (priv->wmm_enabled == MFALSE) {
+ /* Since WMM is not enabled, setup the queues with the defaults
+ */
+ wlan_wmm_setup_queues(priv);
+ }
+ if (event->event_id == MLAN_EVENT_ID_DRV_UAP_CHAN_INFO) {
+ pchan_band_info->is_11n_enabled = priv->is_11n_enabled;
+ wlan_recv_event(priv, MLAN_EVENT_ID_DRV_UAP_CHAN_INFO, event);
+ }
+
+ LEAVE();
+}
+
+/**
+ * @brief This function will update WAPI PN in statation assoc event
+ *
+ * @param priv A pointer to mlan_private
+ * @param pevent A pointer to event buf
+ *
+ * @return MFALSE
+ */
+static t_u32 wlan_update_wapi_info_tlv(pmlan_private priv, pmlan_buffer pevent)
+{
+ t_u32 ret = MFALSE;
+ t_u16 tlv_type, tlv_len;
+ t_u32 tx_pn[4];
+ t_u32 i = 0;
+ int tlv_buf_left = pevent->data_len - ASSOC_EVENT_FIX_SIZE;
+ MrvlIEtypesHeader_t *tlv =
+ (MrvlIEtypesHeader_t *)(pevent->pbuf + pevent->data_offset +
+ ASSOC_EVENT_FIX_SIZE);
+ MrvlIEtypes_wapi_info_t *wapi_tlv = MNULL;
+
+ ENTER();
+ while (tlv_buf_left >= (int)sizeof(MrvlIEtypesHeader_t)) {
+ tlv_type = wlan_le16_to_cpu(tlv->type);
+ tlv_len = wlan_le16_to_cpu(tlv->len);
+ if ((sizeof(MrvlIEtypesHeader_t) + tlv_len) >
+ (unsigned int)tlv_buf_left) {
+ PRINTM(MERROR, "wrong tlv: tlvLen=%d, tlvBufLeft=%d\n",
+ tlv_len, tlv_buf_left);
+ break;
+ }
+ if (tlv_type == TLV_TYPE_AP_WAPI_INFO) {
+ wapi_tlv = (MrvlIEtypes_wapi_info_t *)tlv;
+ DBG_HEXDUMP(MCMD_D, "Fw:multicast_PN",
+ wapi_tlv->multicast_PN, PN_SIZE);
+ memcpy_ext(priv->adapter, (t_u8 *)tx_pn,
+ wapi_tlv->multicast_PN, PN_SIZE,
+ sizeof(tx_pn));
+ for (i = 0; i < 4; i++)
+ tx_pn[i] = mlan_ntohl(tx_pn[i]);
+ memcpy_ext(priv->adapter, wapi_tlv->multicast_PN,
+ (t_u8 *)tx_pn, PN_SIZE,
+ sizeof(wapi_tlv->multicast_PN));
+ DBG_HEXDUMP(MCMD_D, "Host:multicast_PN",
+ wapi_tlv->multicast_PN, PN_SIZE);
+ break;
+ }
+ tlv_buf_left -= (sizeof(MrvlIEtypesHeader_t) + tlv_len);
+ tlv = (MrvlIEtypesHeader_t *)((t_u8 *)tlv + tlv_len +
+ sizeof(MrvlIEtypesHeader_t));
+ }
+ LEAVE();
+
+ return ret;
+}
+
+/**
+ * @brief This function send sta_assoc_event to moal
+ * payload with sta mac address and assoc ie.
+ *
+ * @param priv A pointer to mlan_private
+ * @param pevent A pointer to mlan_event buffer
+ * @param pbuf A pointer to mlan_buffer which has event content.
+ *
+ * @return MFALSE
+ */
+static t_u32 wlan_process_sta_assoc_event(pmlan_private priv,
+ mlan_event *pevent,
+ pmlan_buffer pmbuf)
+{
+ t_u32 ret = MFALSE;
+ t_u16 tlv_type, tlv_len;
+ t_u16 frame_control, frame_sub_type = 0;
+ t_u8 *assoc_req_ie = MNULL;
+ t_u8 ie_len = 0, assoc_ie_len = 0;
+ int tlv_buf_left = pmbuf->data_len - ASSOC_EVENT_FIX_SIZE;
+ MrvlIEtypesHeader_t *tlv =
+ (MrvlIEtypesHeader_t *)(pmbuf->pbuf + pmbuf->data_offset +
+ ASSOC_EVENT_FIX_SIZE);
+ MrvlIETypes_MgmtFrameSet_t *mgmt_tlv = MNULL;
+
+ ENTER();
+ pevent->event_id = MLAN_EVENT_ID_UAP_FW_STA_CONNECT;
+ pevent->bss_index = priv->bss_index;
+ pevent->event_len = MLAN_MAC_ADDR_LENGTH;
+ memcpy_ext(priv->adapter, pevent->event_buf,
+ pmbuf->pbuf + pmbuf->data_offset + 6, pevent->event_len,
+ pevent->event_len);
+ while (tlv_buf_left >= (int)sizeof(MrvlIEtypesHeader_t)) {
+ tlv_type = wlan_le16_to_cpu(tlv->type);
+ tlv_len = wlan_le16_to_cpu(tlv->len);
+ if ((sizeof(MrvlIEtypesHeader_t) + tlv_len) >
+ (unsigned int)tlv_buf_left) {
+ PRINTM(MERROR, "wrong tlv: tlvLen=%d, tlvBufLeft=%d\n",
+ tlv_len, tlv_buf_left);
+ break;
+ }
+ if (tlv_type == TLV_TYPE_MGMT_FRAME) {
+ mgmt_tlv = (MrvlIETypes_MgmtFrameSet_t *)tlv;
+ memcpy_ext(priv->adapter, &frame_control,
+ (t_u8 *)&(mgmt_tlv->frame_control),
+ sizeof(frame_control),
+ sizeof(frame_control));
+ frame_sub_type = IEEE80211_GET_FC_MGMT_FRAME_SUBTYPE(
+ frame_control);
+ if ((mgmt_tlv->frame_control.type == 0) &&
+ ((frame_sub_type == SUBTYPE_ASSOC_REQUEST) ||
+ (frame_sub_type == SUBTYPE_REASSOC_REQUEST))) {
+ if (frame_sub_type == SUBTYPE_ASSOC_REQUEST)
+ assoc_ie_len =
+ sizeof(IEEEtypes_AssocRqst_t);
+ else if (frame_sub_type ==
+ SUBTYPE_REASSOC_REQUEST)
+ assoc_ie_len =
+ sizeof(IEEEtypes_ReAssocRqst_t);
+
+ ie_len = tlv_len -
+ sizeof(IEEEtypes_FrameCtl_t) -
+ assoc_ie_len;
+ assoc_req_ie =
+ (t_u8 *)tlv +
+ sizeof(MrvlIETypes_MgmtFrameSet_t) +
+ assoc_ie_len;
+ memcpy_ext(priv->adapter,
+ pevent->event_buf +
+ pevent->event_len,
+ assoc_req_ie, ie_len, ie_len);
+ pevent->event_len += ie_len;
+ break;
+ }
+ }
+ tlv_buf_left -= (sizeof(MrvlIEtypesHeader_t) + tlv_len);
+ tlv = (MrvlIEtypesHeader_t *)((t_u8 *)tlv + tlv_len +
+ sizeof(MrvlIEtypesHeader_t));
+ }
+ PRINTM(MEVENT, "STA assoc event len=%d\n", pevent->event_len);
+ DBG_HEXDUMP(MCMD_D, "STA assoc event", pevent->event_buf,
+ pevent->event_len);
+ wlan_recv_event(priv, pevent->event_id, pevent);
+ LEAVE();
+ return ret;
+}
+
+/**
+ * @brief This function handles repsonse of acs_scan.
+ *
+ * @param pmpriv A pointer to mlan_private structure
+ * @param pcmd A pointer to HostCmd_DS_COMMAND structure
+ * @param pioctl_buf A pointer to mlan_ioctl_req structure
+ *
+ * @return MLAN_STATUS_SUCCESS
+ */
+mlan_status wlan_ret_cmd_uap_acs_scan(pmlan_private pmpriv,
+ const HostCmd_DS_COMMAND *resp,
+ mlan_ioctl_req *pioctl_buf)
+{
+ HostCMD_DS_APCMD_ACS_SCAN *acs_scan =
+ (HostCMD_DS_APCMD_ACS_SCAN *)&resp->params.acs_scan;
+ mlan_ds_bss *bss = MNULL;
+
+ ENTER();
+ PRINTM(MCMND, "ACS scan done: bandcfg=%x, channel=%d\n",
+ acs_scan->bandcfg, acs_scan->chan);
+ if (pioctl_buf) {
+ bss = (mlan_ds_bss *)pioctl_buf->pbuf;
+ bss->param.ap_acs_scan.chan = acs_scan->chan;
+ bss->param.ap_acs_scan.bandcfg = acs_scan->bandcfg;
+ pioctl_buf->data_read_written = sizeof(mlan_ds_bss);
+ }
+
+ LEAVE();
+ return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ * @brief This function prepares command of uap operation control
+ *
+ * @param pmpriv A pointer to mlan_private structure
+ * @param cmd A pointer to HostCmd_DS_COMMAND structure
+ * @param cmd_action the action: GET or SET
+ * @param pdata_buf A pointer to data buffer
+ * @return MLAN_STATUS_SUCCESS
+ */
+static mlan_status wlan_uap_cmd_oper_ctrl(pmlan_private pmpriv,
+ HostCmd_DS_COMMAND *cmd,
+ t_u16 cmd_action, t_void *pdata_buf)
+{
+ HostCmd_DS_UAP_OPER_CTRL *poper_ctl =
+ (HostCmd_DS_UAP_OPER_CTRL *)&cmd->params.uap_oper_ctrl;
+ mlan_ds_bss *bss = (mlan_ds_bss *)pdata_buf;
+ mlan_uap_oper_ctrl *uap_oper_ctrl = &bss->param.ap_oper_ctrl;
+ Band_Config_t *bandcfg = MNULL;
+
+ ENTER();
+
+ cmd->command = wlan_cpu_to_le16(HOST_CMD_APCMD_OPER_CTRL);
+ cmd->size =
+ wlan_cpu_to_le16(sizeof(HostCmd_DS_UAP_OPER_CTRL) + S_DS_GEN);
+ poper_ctl->action = wlan_cpu_to_le16(cmd_action);
+
+ if (cmd_action == HostCmd_ACT_GEN_SET) {
+ poper_ctl->ctrl = wlan_cpu_to_le16(uap_oper_ctrl->ctrl_value);
+ if (uap_oper_ctrl->ctrl_value == 2) {
+ poper_ctl->chan_opt =
+ wlan_cpu_to_le16(uap_oper_ctrl->chan_opt);
+ if (uap_oper_ctrl->chan_opt == 3) {
+ poper_ctl->channel_band.header.type =
+ wlan_cpu_to_le16(
+ TLV_TYPE_UAP_CHAN_BAND_CONFIG);
+ poper_ctl->channel_band.header
+ .len = wlan_cpu_to_le16(
+ sizeof(MrvlIEtypes_channel_band_t) -
+ sizeof(MrvlIEtypesHeader_t));
+ bandcfg = &poper_ctl->channel_band.bandcfg;
+ if (uap_oper_ctrl->channel > 14)
+ bandcfg->chanBand = BAND_5GHZ;
+ bandcfg->chanWidth = uap_oper_ctrl->band_cfg;
+ if (bandcfg->chanWidth)
+ bandcfg->chan2Offset =
+ wlan_get_second_channel_offset(
+ uap_oper_ctrl->channel);
+ bandcfg->scanMode = SCAN_MODE_MANUAL;
+ poper_ctl->channel_band.channel =
+ uap_oper_ctrl->channel;
+ }
+ }
+ }
+
+ LEAVE();
+ return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ * @brief This function handles the command response of uap operation control
+ *
+ * @param pmpriv A pointer to mlan_private structure
+ * @param resp A pointer to HostCmd_DS_COMMAND
+ * @param pioctl_buf A pointer to mlan_ioctl_req structure
+ *
+ * @return MLAN_STATUS_SUCCESS
+ */
+static mlan_status wlan_uap_ret_oper_ctrl(pmlan_private pmpriv,
+ HostCmd_DS_COMMAND *resp,
+ mlan_ioctl_req *pioctl_buf)
+{
+ HostCmd_DS_UAP_OPER_CTRL *poper_ctl =
+ (HostCmd_DS_UAP_OPER_CTRL *)&resp->params.uap_oper_ctrl;
+ mlan_ds_bss *bss = MNULL;
+ mlan_uap_oper_ctrl *uap_oper_ctrl = MNULL;
+ Band_Config_t *bandcfg = MNULL;
+
+ ENTER();
+
+ if (pioctl_buf && pioctl_buf->action == MLAN_ACT_GET) {
+ bss = (mlan_ds_bss *)pioctl_buf->pbuf;
+ uap_oper_ctrl = (mlan_uap_oper_ctrl *)&bss->param.ap_oper_ctrl;
+ uap_oper_ctrl->ctrl_value = wlan_le16_to_cpu(poper_ctl->ctrl);
+ uap_oper_ctrl->chan_opt = wlan_le16_to_cpu(poper_ctl->chan_opt);
+ uap_oper_ctrl->channel = poper_ctl->channel_band.channel;
+ bandcfg = &poper_ctl->channel_band.bandcfg;
+ uap_oper_ctrl->band_cfg = bandcfg->chanWidth;
+ }
+
+ LEAVE();
+ return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ * @brief Check 11B support Rates
+ *
+ *
+ * @param pmadapter Private mlan adapter structure
+ *
+ * @return MTRUE/MFALSE
+ *
+ */
+t_u8 wlan_check_11B_support_rates(MrvlIEtypes_RatesParamSet_t *prates_tlv)
+{
+ int i;
+ t_u8 rate;
+ t_u8 ret = MTRUE;
+ for (i = 0; i < prates_tlv->header.len; i++) {
+ rate = prates_tlv->rates[i] & 0x7f;
+ if ((rate != 0x02) && (rate != 0x04) && (rate != 0x0b) &&
+ (rate != 0x16)) {
+ ret = MFALSE;
+ break;
+ }
+ }
+ return ret;
+}
+
+/**
+ * @brief This function prepares command of sys_config
+ *
+ * @param pmpriv A pointer to mlan_private structure
+ * @param cmd A pointer to HostCmd_DS_COMMAND structure
+ * @param cmd_action cmd action
+ * @param pioctl_buf A pointer to mlan_ioctl_req structure
+ * @return MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ */
+static mlan_status wlan_uap_cmd_add_station(pmlan_private pmpriv,
+ HostCmd_DS_COMMAND *cmd,
+ t_u16 cmd_action,
+ pmlan_ioctl_req pioctl_buf)
+{
+ mlan_ds_bss *bss = MNULL;
+ HostCmd_DS_ADD_STATION *new_sta =
+ (HostCmd_DS_ADD_STATION *)&cmd->params.sta_info;
+ sta_node *sta_ptr = MNULL;
+ t_u16 tlv_buf_left;
+ t_u8 *pos = MNULL;
+ t_u8 *tlv_buf = MNULL;
+ t_u16 travel_len = 0;
+ MrvlIEtypesHeader_t *tlv;
+ t_u16 tlv_len = 0;
+ t_u8 b_only = MFALSE;
+ mlan_adapter *pmadapter = pmpriv->adapter;
+ MrvlIETypes_HTCap_t *phtcap;
+ MrvlIETypes_VHTCap_t *pvhtcap;
+ MrvlIEtypes_Extension_t *pext_tlv;
+ MrvlIEtypes_StaFlag_t *pstaflag;
+ int i;
+
+ ENTER();
+
+ if (!pioctl_buf) {
+ LEAVE();
+ return MLAN_STATUS_FAILURE;
+ }
+ bss = (mlan_ds_bss *)pioctl_buf->pbuf;
+ cmd->command = wlan_cpu_to_le16(HostCmd_CMD_ADD_NEW_STATION);
+ new_sta->action = wlan_cpu_to_le16(cmd_action);
+ cmd->size = sizeof(HostCmd_DS_ADD_STATION) + S_DS_GEN;
+ if (cmd_action == HostCmd_ACT_ADD_STA) {
+ sta_ptr = wlan_get_station_entry(pmpriv,
+ bss->param.sta_info.peer_mac);
+ if (!sta_ptr)
+ sta_ptr = wlan_add_station_entry(
+ pmpriv, bss->param.sta_info.peer_mac);
+ } else {
+ sta_ptr = wlan_add_station_entry(pmpriv,
+ bss->param.sta_info.peer_mac);
+ }
+ if (!sta_ptr) {
+ LEAVE();
+ return MLAN_STATUS_FAILURE;
+ }
+ memcpy_ext(pmadapter, new_sta->peer_mac, bss->param.sta_info.peer_mac,
+ MLAN_MAC_ADDR_LENGTH, MLAN_MAC_ADDR_LENGTH);
+ if (cmd_action != HostCmd_ACT_ADD_STA)
+ goto done;
+ new_sta->aid = wlan_cpu_to_le16(bss->param.sta_info.aid);
+ new_sta->listen_interval =
+ wlan_cpu_to_le32(bss->param.sta_info.listen_interval);
+ if (bss->param.sta_info.cap_info)
+ new_sta->cap_info =
+ wlan_cpu_to_le16(bss->param.sta_info.cap_info);
+ else
+ new_sta->cap_info = wlan_cpu_to_le16(sta_ptr->capability);
+ tlv_buf_left = bss->param.sta_info.tlv_len;
+ pos = new_sta->tlv;
+ tlv_buf = bss->param.sta_info.tlv;
+ tlv = (MrvlIEtypesHeader_t *)tlv_buf;
+ if (bss->param.sta_info.sta_flags & STA_FLAG_WME) {
+ PRINTM(MCMND, "STA flags supports wmm \n");
+ sta_ptr->is_wmm_enabled = MTRUE;
+ }
+ // append sta_flag_flags.
+ pstaflag = (MrvlIEtypes_StaFlag_t *)pos;
+ pstaflag->header.type = wlan_cpu_to_le16(TLV_TYPE_UAP_STA_FLAGS);
+ pstaflag->header.len = wlan_cpu_to_le16(sizeof(t_u32));
+ pstaflag->sta_flags = wlan_cpu_to_le32(bss->param.sta_info.sta_flags);
+ pos += sizeof(MrvlIEtypes_StaFlag_t);
+ cmd->size += sizeof(MrvlIEtypes_StaFlag_t);
+
+ while (tlv_buf_left >= sizeof(MrvlIEtypesHeader_t)) {
+ if (tlv_buf_left < (sizeof(MrvlIEtypesHeader_t) + tlv->len))
+ break;
+ switch (tlv->type) {
+ case EXT_CAPABILITY:
+ break;
+ case SUPPORTED_RATES:
+ b_only = wlan_check_11B_support_rates(
+ (MrvlIEtypes_RatesParamSet_t *)tlv);
+ break;
+ case QOS_INFO:
+ PRINTM(MCMND, "STA supports wmm\n");
+ sta_ptr->is_wmm_enabled = MTRUE;
+ break;
+ case HT_CAPABILITY:
+ PRINTM(MCMND, "STA supports 11n\n");
+ sta_ptr->is_11n_enabled = MTRUE;
+ phtcap = (MrvlIETypes_HTCap_t *)tlv;
+ if (sta_ptr->HTcap.ieee_hdr.element_id ==
+ HT_CAPABILITY) {
+ if (GETHT_40MHZ_INTOLARANT(
+ sta_ptr->HTcap.ht_cap.ht_cap_info)) {
+ PRINTM(MCMND,
+ "SETHT_40MHZ_INTOLARANT\n");
+ SETHT_40MHZ_INTOLARANT(
+ phtcap->ht_cap.ht_cap_info);
+ }
+ }
+ if (GETHT_MAXAMSDU(phtcap->ht_cap.ht_cap_info))
+ sta_ptr->max_amsdu = MLAN_TX_DATA_BUF_SIZE_8K;
+ else
+ sta_ptr->max_amsdu = MLAN_TX_DATA_BUF_SIZE_4K;
+ break;
+ case VHT_CAPABILITY:
+ PRINTM(MCMND, "STA supports 11ac\n");
+ sta_ptr->is_11ac_enabled = MTRUE;
+ pvhtcap = (MrvlIETypes_VHTCap_t *)tlv;
+ if (GET_VHTCAP_MAXMPDULEN(
+ pvhtcap->vht_cap.vht_cap_info) == 2)
+ sta_ptr->max_amsdu = MLAN_TX_DATA_BUF_SIZE_12K;
+ else if (GET_VHTCAP_MAXMPDULEN(
+ pvhtcap->vht_cap.vht_cap_info) == 1)
+ sta_ptr->max_amsdu = MLAN_TX_DATA_BUF_SIZE_8K;
+ else
+ sta_ptr->max_amsdu = MLAN_TX_DATA_BUF_SIZE_4K;
+ break;
+ case OPER_MODE_NTF:
+ break;
+ case EXTENSION:
+ pext_tlv = (MrvlIEtypes_Extension_t *)tlv;
+ if (pext_tlv->ext_id == HE_CAPABILITY) {
+ sta_ptr->is_11ax_enabled = MTRUE;
+ PRINTM(MCMND, "STA supports 11ax\n");
+ }
+ break;
+ default:
+ break;
+ }
+ tlv_len = tlv->len;
+ tlv->type = wlan_cpu_to_le16(tlv->type);
+ tlv->len = wlan_cpu_to_le16(tlv->len);
+ memcpy_ext(pmadapter, pos, (t_u8 *)tlv,
+ sizeof(MrvlIEtypesHeader_t) + tlv_len,
+ sizeof(MrvlIEtypesHeader_t) + tlv_len);
+ pos += sizeof(MrvlIEtypesHeader_t) + tlv_len;
+ tlv_buf += sizeof(MrvlIEtypesHeader_t) + tlv_len;
+ tlv = (MrvlIEtypesHeader_t *)tlv_buf;
+ travel_len += sizeof(MrvlIEtypesHeader_t) + tlv_len;
+ tlv_buf_left -= sizeof(MrvlIEtypesHeader_t) + tlv_len;
+ }
+
+ if (sta_ptr->is_11n_enabled) {
+ if (pmpriv->uap_channel <= 14)
+ sta_ptr->bandmode = BAND_GN;
+ else
+ sta_ptr->bandmode = BAND_AN;
+ } else if (!b_only) {
+ if (pmpriv->uap_channel <= 14)
+ sta_ptr->bandmode = BAND_G;
+ else
+ sta_ptr->bandmode = BAND_A;
+ } else
+ sta_ptr->bandmode = BAND_B;
+ if (sta_ptr->is_11ac_enabled) {
+ if (pmpriv->uap_channel <= 14)
+ sta_ptr->bandmode = BAND_GAC;
+ else
+ sta_ptr->bandmode = BAND_AAC;
+ }
+ if (sta_ptr->is_11ax_enabled) {
+ if (pmpriv->uap_channel <= 14)
+ sta_ptr->bandmode = BAND_GAX;
+ else
+ sta_ptr->bandmode = BAND_AAX;
+ }
+
+ for (i = 0; i < MAX_NUM_TID; i++) {
+ if (sta_ptr->is_11n_enabled)
+ sta_ptr->ampdu_sta[i] =
+ pmpriv->aggr_prio_tbl[i].ampdu_user;
+ else
+ sta_ptr->ampdu_sta[i] = BA_STREAM_NOT_ALLOWED;
+ }
+ memset(pmadapter, sta_ptr->rx_seq, 0xff, sizeof(sta_ptr->rx_seq));
+done:
+ cmd->size += travel_len;
+ cmd->size = wlan_cpu_to_le16(cmd->size);
+ LEAVE();
+ return MLAN_STATUS_SUCCESS;
+}
+
+/********************************************************
+ Global Functions
+********************************************************/
+/**
+ * @brief This function prepare the command before sending to firmware.
+ *
+ * @param priv A pointer to mlan_private structure
+ * @param cmd_no Command number
+ * @param cmd_action Command action: GET or SET
+ * @param cmd_oid Cmd oid: treated as sub command
+ * @param pioctl_buf A pointer to MLAN IOCTL Request buffer
+ * @param pdata_buf A pointer to information buffer
+ * @param pcmd_buf A pointer to cmd buf
+ *
+ * @return MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ */
+mlan_status wlan_ops_uap_prepare_cmd(t_void *priv, t_u16 cmd_no,
+ t_u16 cmd_action, t_u32 cmd_oid,
+ t_void *pioctl_buf, t_void *pdata_buf,
+ t_void *pcmd_buf)
+{
+ HostCmd_DS_COMMAND *cmd_ptr = (HostCmd_DS_COMMAND *)pcmd_buf;
+ mlan_private *pmpriv = (mlan_private *)priv;
+ mlan_status ret = MLAN_STATUS_SUCCESS;
+ pmlan_ioctl_req pioctl_req = (mlan_ioctl_req *)pioctl_buf;
+
+ ENTER();
+
+ /* Prepare command */
+ switch (cmd_no) {
+ case HostCMD_APCMD_ACS_SCAN:
+ case HostCmd_CMD_SOFT_RESET:
+ case HOST_CMD_APCMD_BSS_STOP:
+ case HOST_CMD_APCMD_SYS_INFO:
+ case HOST_CMD_APCMD_SYS_RESET:
+ case HOST_CMD_APCMD_STA_LIST:
+ cmd_ptr->command = wlan_cpu_to_le16(cmd_no);
+ cmd_ptr->size = wlan_cpu_to_le16(S_DS_GEN);
+ break;
+ case HOST_CMD_APCMD_BSS_START:
+ ret = wlan_uap_cmd_bss_start(pmpriv, cmd_ptr);
+#ifdef DRV_EMBEDDED_AUTHENTICATOR
+ if (IsAuthenticatorEnabled(pmpriv->psapriv))
+ AuthenticatorBssConfig(pmpriv->psapriv, MNULL, 1, 0, 0);
+#endif
+ break;
+ case HOST_CMD_APCMD_SYS_CONFIGURE:
+ ret = wlan_uap_cmd_sys_configure(pmpriv, cmd_ptr, cmd_action,
+ (pmlan_ioctl_req)pioctl_buf,
+ pdata_buf);
+ break;
+ case HostCmd_CMD_802_11_PS_MODE_ENH:
+ ret = wlan_cmd_enh_power_mode(pmpriv, cmd_ptr, cmd_action,
+ (t_u16)cmd_oid, pdata_buf);
+ break;
+#if defined(SDIO)
+ case HostCmd_CMD_SDIO_GPIO_INT_CONFIG:
+ ret = wlan_cmd_sdio_gpio_int(pmpriv, cmd_ptr, cmd_action,
+ pdata_buf);
+ break;
+#endif
+ case HostCmd_CMD_FUNC_INIT:
+ if (pmpriv->adapter->hw_status == WlanHardwareStatusReset)
+ pmpriv->adapter->hw_status =
+ WlanHardwareStatusInitializing;
+ cmd_ptr->command = wlan_cpu_to_le16(cmd_no);
+ cmd_ptr->size = wlan_cpu_to_le16(S_DS_GEN);
+ break;
+ case HostCmd_CMD_FUNC_SHUTDOWN:
+ pmpriv->adapter->hw_status = WlanHardwareStatusReset;
+ cmd_ptr->command = wlan_cpu_to_le16(cmd_no);
+ cmd_ptr->size = wlan_cpu_to_le16(S_DS_GEN);
+ break;
+ case HostCmd_CMD_CFG_DATA:
+ ret = wlan_cmd_cfg_data(pmpriv, cmd_ptr, cmd_action, cmd_oid,
+ pdata_buf);
+ break;
+ case HostCmd_CMD_MAC_CONTROL:
+ ret = wlan_cmd_mac_control(pmpriv, cmd_ptr, cmd_action,
+ pdata_buf);
+ break;
+ case HostCmd_CMD_802_11_SNMP_MIB:
+ ret = wlan_uap_cmd_snmp_mib(pmpriv, cmd_ptr, cmd_action,
+ cmd_oid,
+ (pmlan_ioctl_req)pioctl_buf,
+ pdata_buf);
+ break;
+ case HostCmd_CMD_802_11_GET_LOG:
+ ret = wlan_uap_cmd_802_11_get_log(pmpriv, cmd_ptr);
+ break;
+ case HostCmd_CMD_802_11D_DOMAIN_INFO:
+ ret = wlan_cmd_802_11d_domain_info(pmpriv, cmd_ptr, cmd_action);
+ break;
+ case HostCmd_CMD_CHAN_REPORT_REQUEST:
+ ret = wlan_11h_cmd_process(pmpriv, cmd_ptr, pdata_buf);
+ break;
+ case HOST_CMD_APCMD_STA_DEAUTH:
+ ret = wlan_uap_cmd_sta_deauth(pmpriv, cmd_ptr, pdata_buf);
+ break;
+ case HOST_CMD_APCMD_REPORT_MIC:
+ ret = wlan_uap_cmd_report_mic(pmpriv, cmd_ptr, pdata_buf);
+ break;
+ case HostCmd_CMD_802_11_KEY_MATERIAL:
+ ret = wlan_uap_cmd_key_material(pmpriv, cmd_ptr, cmd_action,
+ cmd_oid, pdata_buf);
+ break;
+ case HostCmd_CMD_GET_HW_SPEC:
+ ret = wlan_cmd_get_hw_spec(pmpriv, cmd_ptr);
+ break;
+#ifdef SDIO
+ case HostCmd_CMD_SDIO_SP_RX_AGGR_CFG:
+ ret = wlan_cmd_sdio_rx_aggr_cfg(cmd_ptr, cmd_action, pdata_buf);
+ break;
+#endif
+ case HostCmd_CMD_802_11_HS_CFG_ENH:
+ ret = wlan_uap_cmd_802_11_hs_cfg(pmpriv, cmd_ptr, cmd_action,
+ (hs_config_param *)pdata_buf);
+ break;
+ case HostCmd_CMD_HS_WAKEUP_REASON:
+ ret = wlan_cmd_hs_wakeup_reason(pmpriv, cmd_ptr, pdata_buf);
+ break;
+ case HostCmd_CMD_802_11_ROBUSTCOEX:
+ ret = wlan_cmd_robustcoex(pmpriv, cmd_ptr, cmd_action,
+ (t_u16 *)pdata_buf);
+ break;
+ case HostCmd_CMD_DMCS_CONFIG:
+ ret = wlan_cmd_dmcs_config(pmpriv, cmd_ptr, cmd_action,
+ pdata_buf);
+ break;
+ case HostCmd_CMD_RECONFIGURE_TX_BUFF:
+ ret = wlan_cmd_recfg_tx_buf(pmpriv, cmd_ptr, cmd_action,
+ pdata_buf);
+ break;
+ case HostCmd_CMD_AMSDU_AGGR_CTRL:
+ ret = wlan_cmd_amsdu_aggr_ctrl(pmpriv, cmd_ptr, cmd_action,
+ pdata_buf);
+ break;
+ case HostCmd_CMD_11N_CFG:
+ ret = wlan_cmd_11n_cfg(pmpriv, cmd_ptr, cmd_action, pdata_buf);
+ break;
+ case HostCmd_CMD_11N_ADDBA_REQ:
+ ret = wlan_cmd_11n_addba_req(pmpriv, cmd_ptr, pdata_buf);
+ break;
+ case HostCmd_CMD_11N_DELBA:
+ ret = wlan_cmd_11n_delba(pmpriv, cmd_ptr, pdata_buf);
+ break;
+ case HostCmd_CMD_11N_ADDBA_RSP:
+ ret = wlan_cmd_11n_addba_rspgen(pmpriv, cmd_ptr, pdata_buf);
+ break;
+ case HostCmd_CMD_REJECT_ADDBA_REQ:
+ ret = wlan_cmd_reject_addba_req(pmpriv, cmd_ptr, cmd_action,
+ pdata_buf);
+ break;
+ case HostCmd_CMD_TX_BF_CFG:
+ ret = wlan_cmd_tx_bf_cfg(pmpriv, cmd_ptr, cmd_action,
+ pdata_buf);
+ break;
+#if defined(WIFI_DIRECT_SUPPORT)
+ case HostCmd_CMD_SET_BSS_MODE:
+ cmd_ptr->command = wlan_cpu_to_le16(cmd_no);
+ if (pdata_buf)
+ cmd_ptr->params.bss_mode.con_type = *(t_u8 *)pdata_buf;
+ else
+ cmd_ptr->params.bss_mode.con_type =
+ BSS_MODE_WIFIDIRECT_GO;
+ cmd_ptr->size = wlan_cpu_to_le16(
+ sizeof(HostCmd_DS_SET_BSS_MODE) + S_DS_GEN);
+ ret = MLAN_STATUS_SUCCESS;
+ break;
+#endif
+ case HostCmd_CMD_VERSION_EXT:
+ cmd_ptr->command = wlan_cpu_to_le16(cmd_no);
+ cmd_ptr->params.verext.version_str_sel =
+ (t_u8)(*((t_u32 *)pdata_buf));
+ cmd_ptr->size = wlan_cpu_to_le16(
+ sizeof(HostCmd_DS_VERSION_EXT) + S_DS_GEN);
+ ret = MLAN_STATUS_SUCCESS;
+ break;
+ case HostCmd_CMD_RX_MGMT_IND:
+ cmd_ptr->command = wlan_cpu_to_le16(cmd_no);
+ cmd_ptr->params.rx_mgmt_ind.action =
+ wlan_cpu_to_le16(cmd_action);
+ cmd_ptr->params.rx_mgmt_ind.mgmt_subtype_mask =
+ (t_u32)(*((t_u32 *)pdata_buf));
+ cmd_ptr->size = wlan_cpu_to_le16(
+ sizeof(HostCmd_DS_RX_MGMT_IND) + S_DS_GEN);
+ break;
+ case HostCmd_CMD_CFG_TX_DATA_PAUSE:
+ ret = wlan_uap_cmd_txdatapause(pmpriv, cmd_ptr, cmd_action,
+ pdata_buf);
+ break;
+ case HostCmd_CMD_802_11_RADIO_CONTROL:
+ ret = wlan_cmd_802_11_radio_control(pmpriv, cmd_ptr, cmd_action,
+ pdata_buf);
+ break;
+ case HostCmd_CMD_TX_RATE_CFG:
+ ret = wlan_cmd_tx_rate_cfg(pmpriv, cmd_ptr, cmd_action,
+ pdata_buf, pioctl_buf);
+ break;
+ case HostCmd_CMD_802_11_TX_RATE_QUERY:
+ cmd_ptr->command =
+ wlan_cpu_to_le16(HostCmd_CMD_802_11_TX_RATE_QUERY);
+ cmd_ptr->size = wlan_cpu_to_le16(sizeof(HostCmd_TX_RATE_QUERY) +
+ S_DS_GEN);
+ pmpriv->tx_rate = 0;
+ ret = MLAN_STATUS_SUCCESS;
+ break;
+ case HostCmd_CMD_802_11_REMAIN_ON_CHANNEL:
+ ret = wlan_cmd_remain_on_channel(pmpriv, cmd_ptr, cmd_action,
+ pdata_buf);
+ break;
+#ifdef WIFI_DIRECT_SUPPORT
+ case HOST_CMD_WIFI_DIRECT_MODE_CONFIG:
+ ret = wlan_cmd_wifi_direct_mode(pmpriv, cmd_ptr, cmd_action,
+ pdata_buf);
+ break;
+ case HOST_CMD_P2P_PARAMS_CONFIG:
+ ret = wlan_cmd_p2p_params_config(pmpriv, cmd_ptr, cmd_action,
+ pdata_buf);
+ break;
+#endif
+ case HostCmd_CMD_802_11_RF_ANTENNA:
+ ret = wlan_cmd_802_11_rf_antenna(pmpriv, cmd_ptr, cmd_action,
+ pdata_buf);
+ break;
+ case HostCmd_CMD_802_11_MIMO_SWITCH:
+ ret = wlan_cmd_802_11_mimo_switch(pmpriv, cmd_ptr, pdata_buf);
+ break;
+ case HostCmd_CMD_11AC_CFG:
+ ret = wlan_cmd_11ac_cfg(pmpriv, cmd_ptr, cmd_action, pdata_buf);
+ break;
+ case HostCmd_CMD_DYN_BW:
+ ret = wlan_cmd_config_dyn_bw(pmpriv, cmd_ptr, cmd_action,
+ pdata_buf);
+ break;
+ case HostCmd_CMD_MAC_REG_ACCESS:
+ case HostCmd_CMD_BBP_REG_ACCESS:
+ case HostCmd_CMD_RF_REG_ACCESS:
+ case HostCmd_CMD_CAU_REG_ACCESS:
+ case HostCmd_CMD_TARGET_ACCESS:
+ case HostCmd_CMD_802_11_EEPROM_ACCESS:
+ case HostCmd_CMD_BCA_REG_ACCESS:
+ ret = wlan_cmd_reg_access(pmpriv, cmd_ptr, cmd_action,
+ pdata_buf);
+ break;
+ case HostCmd_CMD_MEM_ACCESS:
+ ret = wlan_cmd_mem_access(cmd_ptr, cmd_action, pdata_buf);
+ break;
+ case HostCmd_CMD_WMM_QUEUE_CONFIG:
+ ret = wlan_cmd_wmm_queue_config(pmpriv, cmd_ptr, pdata_buf);
+ break;
+#ifdef RX_PACKET_COALESCE
+ case HostCmd_CMD_RX_PKT_COALESCE_CFG:
+ ret = wlan_cmd_rx_pkt_coalesce_cfg(pmpriv, cmd_ptr, cmd_action,
+ pdata_buf);
+ break;
+#endif
+ case HOST_CMD_APCMD_OPER_CTRL:
+ ret = wlan_uap_cmd_oper_ctrl(pmpriv, cmd_ptr, cmd_action,
+ pdata_buf);
+ break;
+
+ case HostCmd_CMD_INDEPENDENT_RESET_CFG:
+ ret = wlan_cmd_ind_rst_cfg(cmd_ptr, cmd_action, pdata_buf);
+ break;
+ case HostCmd_CMD_GET_TSF:
+ ret = wlan_cmd_get_tsf(pmpriv, cmd_ptr, cmd_action);
+ break;
+
+ case HostCmd_CMD_802_11_PS_INACTIVITY_TIMEOUT:
+ ret = wlan_cmd_ps_inactivity_timeout(pmpriv, cmd_ptr,
+ cmd_action, pdata_buf);
+ break;
+
+ case HostCmd_CMD_CHAN_REGION_CFG:
+ cmd_ptr->command = wlan_cpu_to_le16(cmd_no);
+ cmd_ptr->size = wlan_cpu_to_le16(
+ sizeof(HostCmd_DS_CHAN_REGION_CFG) + S_DS_GEN);
+ cmd_ptr->params.reg_cfg.action = wlan_cpu_to_le16(cmd_action);
+ break;
+ case HostCmd_CMD_PACKET_AGGR_CTRL:
+ ret = wlan_cmd_packet_aggr_ctrl(pmpriv, cmd_ptr, cmd_action,
+ pdata_buf);
+ break;
+#if defined(PCIE)
+#if defined(PCIE8997) || defined(PCIE8897)
+ case HostCmd_CMD_PCIE_HOST_BUF_DETAILS:
+ ret = wlan_cmd_pcie_host_buf_cfg(pmpriv, cmd_ptr, cmd_action,
+ pdata_buf);
+ break;
+#endif
+#endif
+ case HOST_CMD_TX_RX_PKT_STATS:
+ ret = wlan_cmd_tx_rx_pkt_stats(pmpriv, cmd_ptr,
+ (pmlan_ioctl_req)pioctl_buf,
+ pdata_buf);
+ break;
+ case HostCmd_CMD_FW_DUMP_EVENT:
+ ret = wlan_cmd_fw_dump_event(pmpriv, cmd_ptr, cmd_action,
+ pdata_buf);
+ break;
+ case HostCmd_CMD_802_11_LINK_STATS:
+ ret = wlan_cmd_802_11_link_statistic(pmpriv, cmd_ptr,
+ cmd_action, pioctl_buf);
+ break;
+ case HostCmd_CMD_ADD_NEW_STATION:
+ ret = wlan_uap_cmd_add_station(pmpriv, cmd_ptr, cmd_action,
+ (pmlan_ioctl_req)pioctl_buf);
+ break;
+ case HostCmd_CMD_BOOT_SLEEP:
+ ret = wlan_cmd_boot_sleep(pmpriv, cmd_ptr, cmd_action,
+ pdata_buf);
+ break;
+#if defined(DRV_EMBEDDED_AUTHENTICATOR)
+ case HostCmd_CMD_CRYPTO:
+ ret = wlan_cmd_crypto(pmpriv, cmd_ptr, cmd_action, pdata_buf);
+ break;
+#endif
+ case HostCmd_CMD_11AX_CFG:
+ ret = wlan_cmd_11ax_cfg(pmpriv, cmd_ptr, cmd_action, pdata_buf);
+ break;
+ case HostCmd_CMD_11AX_CMD:
+ ret = wlan_cmd_11ax_cmd(pmpriv, cmd_ptr, cmd_action, pdata_buf);
+ break;
+ case HostCmd_CMD_RANGE_EXT:
+ ret = wlan_cmd_range_ext(pmpriv, cmd_ptr, cmd_action,
+ pdata_buf);
+ break;
+ case HostCmd_CMD_RX_ABORT_CFG:
+ ret = wlan_cmd_rxabortcfg(pmpriv, cmd_ptr, cmd_action,
+ pdata_buf);
+ break;
+ case HostCmd_CMD_RX_ABORT_CFG_EXT:
+ ret = wlan_cmd_rxabortcfg_ext(pmpriv, cmd_ptr, cmd_action,
+ pdata_buf);
+ break;
+ case HostCmd_CMD_TX_AMPDU_PROT_MODE:
+ ret = wlan_cmd_tx_ampdu_prot_mode(pmpriv, cmd_ptr, cmd_action,
+ pdata_buf);
+ break;
+ case HostCmd_CMD_DOT11MC_UNASSOC_FTM_CFG:
+ ret = wlan_cmd_dot11mc_unassoc_ftm_cfg(pmpriv, cmd_ptr,
+ cmd_action, pdata_buf);
+ break;
+ case HostCmd_CMD_RATE_ADAPT_CFG:
+ ret = wlan_cmd_rate_adapt_cfg(pmpriv, cmd_ptr, cmd_action,
+ pdata_buf);
+ break;
+ case HostCmd_CMD_CCK_DESENSE_CFG:
+ ret = wlan_cmd_cck_desense_cfg(pmpriv, cmd_ptr, cmd_action,
+ pdata_buf);
+ break;
+ case HostCmd_CHANNEL_TRPC_CONFIG:
+ ret = wlan_cmd_get_chan_trpc_config(pmpriv, cmd_ptr, cmd_action,
+ pdata_buf);
+ break;
+ case HostCmd_CMD_LOW_POWER_MODE_CFG:
+ ret = wlan_cmd_set_get_low_power_mode_cfg(
+ pmpriv, cmd_ptr, cmd_action, pdata_buf);
+ break;
+ case HostCmd_CMD_802_11_BAND_STEERING:
+ ret = wlan_cmd_set_get_band_steering_cfg(pmpriv, cmd_ptr,
+ cmd_action, pdata_buf);
+ break;
+ case HostCmd_CMD_UAP_BEACON_STUCK_CFG:
+ ret = wlan_cmd_set_get_beacon_stuck_cfg(pmpriv, cmd_ptr,
+ cmd_action, pdata_buf);
+ break;
+ default:
+ PRINTM(MERROR, "PREP_CMD: unknown command- %#x\n", cmd_no);
+ if (pioctl_req)
+ pioctl_req->status_code = MLAN_ERROR_CMD_INVALID;
+ ret = MLAN_STATUS_FAILURE;
+ break;
+ }
+ LEAVE();
+ return ret;
+}
+
+/**
+ * @brief This function handles the AP mode command response
+ *
+ * @param priv A pointer to mlan_private structure
+ * @param cmdresp_no cmd no
+ * @param pcmd_buf cmdresp buf
+ * @param pioctl A pointer to ioctl buf
+ *
+ * @return MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ */
+mlan_status wlan_ops_uap_process_cmdresp(t_void *priv, t_u16 cmdresp_no,
+ t_void *pcmd_buf, t_void *pioctl)
+{
+ mlan_status ret = MLAN_STATUS_SUCCESS;
+ mlan_private *pmpriv = (mlan_private *)priv;
+ HostCmd_DS_COMMAND *resp = (HostCmd_DS_COMMAND *)pcmd_buf;
+ mlan_ioctl_req *pioctl_buf = (mlan_ioctl_req *)pioctl;
+ mlan_adapter *pmadapter = pmpriv->adapter;
+#ifdef SDIO
+ int ctr;
+#endif
+ wlan_dfs_device_state_t *pstate_dfs =
+ (wlan_dfs_device_state_t *)&pmpriv->adapter->state_dfs;
+ t_u32 sec, usec;
+ ENTER();
+
+ /* If the command is not successful, cleanup and return failure */
+ if (resp->result != HostCmd_RESULT_OK) {
+ ret = uap_process_cmdresp_error(pmpriv, resp, pioctl_buf);
+ LEAVE();
+ return ret;
+ }
+
+ /* Command successful, handle response */
+ switch (cmdresp_no) {
+ case HOST_CMD_APCMD_BSS_STOP:
+ pmpriv->uap_bss_started = MFALSE;
+ /* Timestamp update is required because bss_start after skip_cac
+ * enabled should not select non-current channel just because
+ * timestamp got expired
+ */
+ if (!pmpriv->intf_state_11h.is_11h_host &&
+ !pstate_dfs->dfs_check_pending &&
+ pstate_dfs->dfs_check_channel) {
+ pmpriv->adapter->callbacks.moal_get_system_time(
+ pmpriv->adapter->pmoal_handle, &sec, &usec);
+ pstate_dfs->dfs_report_time_sec = sec;
+ }
+ if (pmpriv->intf_state_11h.is_11h_host)
+ pmpriv->intf_state_11h.tx_disabled = MFALSE;
+ else {
+ if (pmpriv->adapter->ecsa_enable)
+ wlan_11h_remove_custom_ie(pmpriv->adapter,
+ pmpriv);
+ wlan_11h_check_update_radar_det_state(pmpriv);
+ }
+
+ if (pmpriv->adapter->state_rdh.stage == RDH_STOP_INTFS)
+ wlan_11h_radar_detected_callback((t_void *)pmpriv);
+ wlan_coex_ampdu_rxwinsize(pmadapter);
+#ifdef DRV_EMBEDDED_AUTHENTICATOR
+ if (IsAuthenticatorEnabled(pmpriv->psapriv)) {
+ AuthenticatorBssConfig(pmpriv->psapriv, MNULL, 0, 1, 0);
+ AuthenticatorkeyClear(pmpriv->psapriv);
+ }
+#endif
+ pmpriv->uap_host_based = 0;
+ break;
+ case HOST_CMD_APCMD_BSS_START:
+ if (!pmpriv->intf_state_11h.is_11h_host &&
+ pmpriv->adapter->state_rdh.stage == RDH_RESTART_INTFS)
+ wlan_11h_radar_detected_callback((t_void *)pmpriv);
+ /* Stop pps_uapsd_mode once bss_start */
+ pmpriv->adapter->tx_lock_flag = MFALSE;
+ pmpriv->adapter->pps_uapsd_mode = MFALSE;
+ pmpriv->adapter->delay_null_pkt = MFALSE;
+ /* Clear AMSDU statistics*/
+ pmpriv->amsdu_rx_cnt = 0;
+ pmpriv->amsdu_tx_cnt = 0;
+ pmpriv->msdu_in_rx_amsdu_cnt = 0;
+ pmpriv->msdu_in_tx_amsdu_cnt = 0;
+ break;
+ case HOST_CMD_APCMD_SYS_RESET:
+ pmpriv->uap_bss_started = MFALSE;
+ pmpriv->uap_host_based = 0;
+#ifdef DRV_EMBEDDED_AUTHENTICATOR
+ AuthenitcatorInitBssConfig(pmpriv->psapriv);
+#endif
+ ret = wlan_uap_ret_sys_reset(pmpriv, resp, pioctl_buf);
+ wlan_11h_check_update_radar_det_state(pmpriv);
+ wlan_coex_ampdu_rxwinsize(pmadapter);
+ break;
+ case HOST_CMD_APCMD_SYS_INFO:
+ break;
+ case HOST_CMD_APCMD_SYS_CONFIGURE:
+ ret = wlan_uap_ret_sys_config(pmpriv, resp, pioctl_buf);
+ break;
+ case HostCmd_CMD_802_11_PS_MODE_ENH:
+ ret = wlan_ret_enh_power_mode(pmpriv, resp, pioctl_buf);
+ break;
+#if defined(SDIO)
+ case HostCmd_CMD_SDIO_GPIO_INT_CONFIG:
+ break;
+#endif
+ case HostCmd_CMD_FUNC_INIT:
+ case HostCmd_CMD_FUNC_SHUTDOWN:
+ break;
+ case HostCmd_CMD_802_11_SNMP_MIB:
+ ret = wlan_uap_ret_snmp_mib(pmpriv, resp, pioctl_buf);
+ break;
+ case HostCmd_CMD_802_11_GET_LOG:
+ ret = wlan_uap_ret_get_log(pmpriv, resp, pioctl_buf);
+ break;
+ case HostCmd_CMD_802_11D_DOMAIN_INFO:
+ ret = wlan_ret_802_11d_domain_info(pmpriv, resp);
+ break;
+ case HostCmd_CMD_CHAN_REPORT_REQUEST:
+ ret = wlan_11h_cmdresp_process(pmpriv, resp);
+ break;
+ case HOST_CMD_APCMD_STA_DEAUTH:
+ break;
+ case HOST_CMD_APCMD_REPORT_MIC:
+ break;
+ case HostCmd_CMD_802_11_KEY_MATERIAL:
+ break;
+ case HOST_CMD_APCMD_STA_LIST:
+ ret = wlan_uap_ret_sta_list(pmpriv, resp, pioctl_buf);
+ break;
+ case HostCmd_CMD_GET_HW_SPEC:
+ ret = wlan_ret_get_hw_spec(pmpriv, resp, pioctl_buf);
+ break;
+#ifdef SDIO
+ case HostCmd_CMD_SDIO_SP_RX_AGGR_CFG:
+ ret = wlan_ret_sdio_rx_aggr_cfg(pmpriv, resp);
+ break;
+#endif
+ case HostCmd_CMD_CFG_DATA:
+ ret = wlan_ret_cfg_data(pmpriv, resp, pioctl_buf);
+ break;
+ case HostCmd_CMD_MAC_CONTROL:
+ ret = wlan_ret_mac_control(pmpriv, resp, pioctl_buf);
+ break;
+ case HostCmd_CMD_802_11_HS_CFG_ENH:
+ ret = wlan_ret_802_11_hs_cfg(pmpriv, resp, pioctl_buf);
+ break;
+ case HostCmd_CMD_HS_WAKEUP_REASON:
+ ret = wlan_ret_hs_wakeup_reason(pmpriv, resp, pioctl_buf);
+ break;
+ case HostCmd_CMD_802_11_ROBUSTCOEX:
+ break;
+ case HostCmd_CMD_DMCS_CONFIG:
+ ret = wlan_ret_dmcs_config(pmpriv, resp, pioctl_buf);
+ break;
+ case HostCmd_CMD_11N_ADDBA_REQ:
+ ret = wlan_ret_11n_addba_req(pmpriv, resp);
+ break;
+ case HostCmd_CMD_11N_DELBA:
+ ret = wlan_ret_11n_delba(pmpriv, resp);
+ break;
+ case HostCmd_CMD_11N_ADDBA_RSP:
+ ret = wlan_ret_11n_addba_resp(pmpriv, resp);
+ break;
+ case HostCmd_CMD_SET_BSS_MODE:
+ break;
+ case HostCmd_CMD_RECONFIGURE_TX_BUFF:
+ wlan_set_tx_pause_flag(pmpriv, MFALSE);
+
+ pmadapter->tx_buf_size =
+ (t_u16)wlan_le16_to_cpu(resp->params.tx_buf.buff_size);
+#ifdef SDIO
+ if (IS_SD(pmadapter->card_type)) {
+ pmadapter->tx_buf_size = (pmadapter->tx_buf_size /
+ MLAN_SDIO_BLOCK_SIZE) *
+ MLAN_SDIO_BLOCK_SIZE;
+ pmadapter->pcard_sd->mp_end_port = wlan_le16_to_cpu(
+ resp->params.tx_buf.mp_end_port);
+ pmadapter->pcard_sd->mp_data_port_mask =
+ pmadapter->pcard_sd->reg->data_port_mask;
+
+ for (ctr = 1;
+ ctr <= MAX_PORT - pmadapter->pcard_sd->mp_end_port;
+ ctr++) {
+ pmadapter->pcard_sd->mp_data_port_mask &=
+ ~(1 << (MAX_PORT - ctr));
+ }
+
+ pmadapter->pcard_sd->curr_wr_port = 0;
+ pmadapter->pcard_sd->mpa_tx.pkt_aggr_limit =
+ MIN(SDIO_MP_AGGR_DEF_PKT_LIMIT,
+ (pmadapter->pcard_sd->mp_end_port >> 1));
+ PRINTM(MCMND, "end port %d, data port mask %x\n",
+ wlan_le16_to_cpu(
+ resp->params.tx_buf.mp_end_port),
+ pmadapter->pcard_sd->mp_data_port_mask);
+ }
+#endif
+ pmadapter->curr_tx_buf_size = pmadapter->tx_buf_size;
+ PRINTM(MCMND, "max_tx_buf_size=%d, tx_buf_size=%d\n",
+ pmadapter->max_tx_buf_size, pmadapter->tx_buf_size);
+ break;
+ case HostCmd_CMD_AMSDU_AGGR_CTRL:
+ ret = wlan_ret_amsdu_aggr_ctrl(pmpriv, resp, pioctl_buf);
+ break;
+ case HostCmd_CMD_11N_CFG:
+ ret = wlan_ret_11n_cfg(pmpriv, resp, pioctl_buf);
+ break;
+ case HostCmd_CMD_REJECT_ADDBA_REQ:
+ ret = wlan_ret_reject_addba_req(pmpriv, resp, pioctl_buf);
+ break;
+ case HostCmd_CMD_TX_BF_CFG:
+ ret = wlan_ret_tx_bf_cfg(pmpriv, resp, pioctl_buf);
+ break;
+ case HostCmd_CMD_VERSION_EXT:
+ ret = wlan_ret_ver_ext(pmpriv, resp, pioctl_buf);
+ break;
+ case HostCmd_CMD_RX_MGMT_IND:
+ ret = wlan_ret_rx_mgmt_ind(pmpriv, resp, pioctl_buf);
+ break;
+ case HostCmd_CMD_CFG_TX_DATA_PAUSE:
+ ret = wlan_uap_ret_txdatapause(pmpriv, resp, pioctl_buf);
+ break;
+ case HostCmd_CMD_802_11_RADIO_CONTROL:
+ ret = wlan_ret_802_11_radio_control(pmpriv, resp, pioctl_buf);
+ break;
+ case HostCmd_CMD_TX_RATE_CFG:
+ ret = wlan_ret_tx_rate_cfg(pmpriv, resp, pioctl_buf);
+ break;
+ case HostCmd_CMD_802_11_TX_RATE_QUERY:
+ ret = wlan_ret_802_11_tx_rate_query(pmpriv, resp, pioctl_buf);
+ break;
+ case HostCmd_CMD_802_11_REMAIN_ON_CHANNEL:
+ ret = wlan_ret_remain_on_channel(pmpriv, resp, pioctl_buf);
+ break;
+#ifdef WIFI_DIRECT_SUPPORT
+ case HOST_CMD_WIFI_DIRECT_MODE_CONFIG:
+ ret = wlan_ret_wifi_direct_mode(pmpriv, resp, pioctl_buf);
+ break;
+ case HOST_CMD_P2P_PARAMS_CONFIG:
+ ret = wlan_ret_p2p_params_config(pmpriv, resp, pioctl_buf);
+ break;
+#endif
+ case HostCmd_CMD_802_11_RF_ANTENNA:
+ ret = wlan_ret_802_11_rf_antenna(pmpriv, resp, pioctl_buf);
+ break;
+ case HostCmd_CMD_802_11_MIMO_SWITCH:
+ break;
+ case HostCmd_CMD_11AC_CFG:
+ ret = wlan_ret_11ac_cfg(pmpriv, resp, pioctl_buf);
+ break;
+ case HostCmd_CMD_DYN_BW:
+ ret = wlan_ret_dyn_bw(pmpriv, resp, pioctl_buf);
+ break;
+ case HostCmd_CMD_MAC_REG_ACCESS:
+ case HostCmd_CMD_BBP_REG_ACCESS:
+ case HostCmd_CMD_RF_REG_ACCESS:
+ case HostCmd_CMD_CAU_REG_ACCESS:
+ case HostCmd_CMD_TARGET_ACCESS:
+ case HostCmd_CMD_802_11_EEPROM_ACCESS:
+ case HostCmd_CMD_BCA_REG_ACCESS:
+ ret = wlan_ret_reg_access(pmpriv->adapter, cmdresp_no, resp,
+ pioctl_buf);
+ break;
+ case HostCmd_CMD_MEM_ACCESS:
+ ret = wlan_ret_mem_access(pmpriv, resp, pioctl_buf);
+ break;
+ case HostCmd_CMD_WMM_QUEUE_CONFIG:
+ ret = wlan_ret_wmm_queue_config(pmpriv, resp, pioctl_buf);
+ break;
+#ifdef RX_PACKET_COALESCE
+ case HostCmd_CMD_RX_PKT_COALESCE_CFG:
+ ret = wlan_ret_rx_pkt_coalesce_cfg(pmpriv, resp, pioctl_buf);
+ break;
+#endif
+ case HostCMD_APCMD_ACS_SCAN:
+ ret = wlan_ret_cmd_uap_acs_scan(pmpriv, resp, pioctl_buf);
+ break;
+ case HOST_CMD_APCMD_OPER_CTRL:
+ ret = wlan_uap_ret_oper_ctrl(pmpriv, resp, pioctl_buf);
+ break;
+ case HostCmd_CMD_INDEPENDENT_RESET_CFG:
+ ret = wlan_ret_ind_rst_cfg(pmpriv, resp, pioctl_buf);
+ break;
+ case HostCmd_CMD_802_11_PS_INACTIVITY_TIMEOUT:
+ break;
+ case HostCmd_CMD_GET_TSF:
+ ret = wlan_ret_get_tsf(pmpriv, resp, pioctl_buf);
+ break;
+
+ case HostCmd_CMD_CHAN_REGION_CFG:
+ ret = wlan_ret_chan_region_cfg(pmpriv, resp, pioctl_buf);
+ break;
+ case HostCmd_CMD_PACKET_AGGR_CTRL:
+ ret = wlan_ret_packet_aggr_ctrl(pmpriv, resp, pioctl_buf);
+ break;
+#if defined(PCIE)
+#if defined(PCIE8997) || defined(PCIE8897)
+ case HostCmd_CMD_PCIE_HOST_BUF_DETAILS:
+ PRINTM(MINFO, "PCIE host buffer configuration successful.\n");
+ break;
+#endif
+#endif
+ case HOST_CMD_TX_RX_PKT_STATS:
+ ret = wlan_ret_tx_rx_pkt_stats(pmpriv, resp, pioctl_buf);
+ break;
+ case HostCmd_CMD_802_11_LINK_STATS:
+ ret = wlan_ret_get_link_statistic(pmpriv, resp, pioctl_buf);
+ break;
+ case HostCmd_CMD_BOOT_SLEEP:
+ ret = wlan_ret_boot_sleep(pmpriv, resp, pioctl_buf);
+ break;
+ case HostCmd_CMD_ADD_NEW_STATION:
+ break;
+#if defined(DRV_EMBEDDED_AUTHENTICATOR)
+ case HostCmd_CMD_CRYPTO:
+ ret = wlan_ret_crypto(pmpriv, resp, pioctl_buf);
+ break;
+#endif
+ case HostCmd_CMD_11AX_CFG:
+ ret = wlan_ret_11ax_cfg(pmpriv, resp, pioctl_buf);
+ break;
+ case HostCmd_CMD_11AX_CMD:
+ ret = wlan_ret_11ax_cmd(pmpriv, resp, pioctl_buf);
+ break;
+ case HostCmd_CMD_RANGE_EXT:
+ ret = wlan_ret_range_ext(pmpriv, resp, pioctl_buf);
+ break;
+ case HostCmd_CMD_RX_ABORT_CFG:
+ ret = wlan_ret_rxabortcfg(pmpriv, resp, pioctl_buf);
+ break;
+ case HostCmd_CMD_RX_ABORT_CFG_EXT:
+ ret = wlan_ret_rxabortcfg_ext(pmpriv, resp, pioctl_buf);
+ break;
+ case HostCmd_CMD_TX_AMPDU_PROT_MODE:
+ ret = wlan_ret_tx_ampdu_prot_mode(pmpriv, resp, pioctl_buf);
+ break;
+ case HostCmd_CMD_DOT11MC_UNASSOC_FTM_CFG:
+ ret = wlan_ret_dot11mc_unassoc_ftm_cfg(pmpriv, resp,
+ pioctl_buf);
+ break;
+ case HostCmd_CMD_RATE_ADAPT_CFG:
+ ret = wlan_ret_rate_adapt_cfg(pmpriv, resp, pioctl_buf);
+ break;
+ case HostCmd_CMD_CCK_DESENSE_CFG:
+ ret = wlan_ret_cck_desense_cfg(pmpriv, resp, pioctl_buf);
+ break;
+ case HostCmd_CHANNEL_TRPC_CONFIG:
+ ret = wlan_ret_get_chan_trpc_config(pmpriv, resp, pioctl_buf);
+ break;
+ case HostCmd_CMD_LOW_POWER_MODE_CFG:
+ ret = wlan_ret_set_get_low_power_mode_cfg(pmpriv, resp,
+ pioctl_buf);
+ break;
+ case HostCmd_CMD_802_11_BAND_STEERING:
+ ret = wlan_ret_set_get_band_steering_cfg(pmpriv, resp,
+ pioctl_buf);
+ break;
+ case HostCmd_CMD_UAP_BEACON_STUCK_CFG:
+ ret = wlan_ret_set_get_beacon_stuck_cfg(pmpriv, resp,
+ pioctl_buf);
+ break;
+ default:
+ PRINTM(MERROR, "CMD_RESP: Unknown command response %#x\n",
+ resp->command);
+ if (pioctl_buf)
+ pioctl_buf->status_code = MLAN_ERROR_CMD_RESP_FAIL;
+ break;
+ }
+ LEAVE();
+ return ret;
+}
+
+/**
+ * @brief This function handles events generated by firmware
+ *
+ * @param priv A pointer to mlan_private structure
+ *
+ * @return MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ */
+mlan_status wlan_ops_uap_process_event(t_void *priv)
+{
+ pmlan_private pmpriv = (pmlan_private)priv;
+ pmlan_adapter pmadapter = pmpriv->adapter;
+ pmlan_callbacks pcb = &pmadapter->callbacks;
+ mlan_status ret = MLAN_STATUS_SUCCESS;
+ t_u32 eventcause = pmadapter->event_cause;
+ pmlan_buffer pmbuf = pmadapter->pmlan_buffer_event;
+ t_u8 *event_buf = MNULL;
+ mlan_event *pevent = MNULL;
+ t_u8 sta_addr[MLAN_MAC_ADDR_LENGTH];
+ sta_node *sta_ptr = MNULL;
+ t_u8 i = 0;
+ t_u8 channel = 0;
+ MrvlIEtypes_channel_band_t *pchan_info = MNULL;
+ chan_band_info *pchan_band_info = MNULL;
+ event_exceed_max_p2p_conn *event_excd_p2p = MNULL;
+ t_u16 enable;
+
+ ENTER();
+
+ if (!pmbuf) {
+ LEAVE();
+ return MLAN_STATUS_FAILURE;
+ }
+ /* Event length check */
+ if (pmbuf && (pmbuf->data_len - sizeof(eventcause)) > MAX_EVENT_SIZE) {
+ pmbuf->status_code = MLAN_ERROR_PKT_SIZE_INVALID;
+ LEAVE();
+ return MLAN_STATUS_FAILURE;
+ }
+
+ /* Allocate memory for event buffer */
+ ret = pcb->moal_malloc(pmadapter->pmoal_handle,
+ MAX_EVENT_SIZE + sizeof(mlan_event),
+ MLAN_MEM_DEF, &event_buf);
+ if ((ret != MLAN_STATUS_SUCCESS) || !event_buf) {
+ PRINTM(MERROR, "Could not allocate buffer for event buf\n");
+ if (pmbuf)
+ pmbuf->status_code = MLAN_ERROR_NO_MEM;
+ goto done;
+ }
+ pevent = (pmlan_event)event_buf;
+ memset(pmadapter, &pevent->event_id, 0, sizeof(pevent->event_id));
+
+ if (eventcause != EVENT_PS_SLEEP && eventcause != EVENT_PS_AWAKE &&
+ pmbuf->data_len > sizeof(eventcause))
+ DBG_HEXDUMP(MEVT_D, "EVENT", pmbuf->pbuf + pmbuf->data_offset,
+ pmbuf->data_len);
+
+ switch (eventcause) {
+ case EVENT_MICRO_AP_BSS_START:
+ PRINTM(MEVENT, "EVENT: MICRO_AP_BSS_START\n");
+ pmpriv->uap_bss_started = MTRUE;
+ pmpriv->is_data_rate_auto = MTRUE;
+ memcpy_ext(pmadapter, pmpriv->curr_addr,
+ pmadapter->event_body + 2, MLAN_MAC_ADDR_LENGTH,
+ MLAN_MAC_ADDR_LENGTH);
+ pevent->event_id = MLAN_EVENT_ID_UAP_FW_BSS_START;
+ wlan_check_uap_capability(pmpriv, pmbuf);
+ wlan_coex_ampdu_rxwinsize(pmadapter);
+#ifdef DRV_EMBEDDED_AUTHENTICATOR
+ if (IsAuthenticatorEnabled(pmpriv->psapriv)) {
+ pmadapter->authenticator_priv = pmpriv;
+ wlan_recv_event(pmpriv, MLAN_EVENT_ID_DRV_DEFER_RX_WORK,
+ MNULL);
+ }
+#endif
+ break;
+ case EVENT_MICRO_AP_BSS_ACTIVE:
+ PRINTM(MEVENT, "EVENT: MICRO_AP_BSS_ACTIVE\n");
+ pmpriv->media_connected = MTRUE;
+ pmpriv->port_open = MTRUE;
+ pevent->event_id = MLAN_EVENT_ID_UAP_FW_BSS_ACTIVE;
+ break;
+ case EVENT_MICRO_AP_BSS_IDLE:
+ PRINTM(MEVENT, "EVENT: MICRO_AP_BSS_IDLE\n");
+ pevent->event_id = MLAN_EVENT_ID_UAP_FW_BSS_IDLE;
+ pmpriv->media_connected = MFALSE;
+ wlan_clean_txrx(pmpriv);
+ wlan_notify_station_deauth(pmpriv);
+ wlan_delete_station_list(pmpriv);
+ pmpriv->port_open = MFALSE;
+ pmpriv->amsdu_disable = MFALSE;
+ pmpriv->tx_pause = MFALSE;
+ break;
+ case EVENT_MICRO_AP_MIC_COUNTERMEASURES:
+ PRINTM(MEVENT, "EVENT: MICRO_AP_MIC_COUNTERMEASURES\n");
+ pevent->event_id = MLAN_EVENT_ID_UAP_FW_MIC_COUNTERMEASURES;
+ break;
+ case EVENT_PS_AWAKE:
+ PRINTM(MINFO, "EVENT: AWAKE\n");
+ PRINTM_NETINTF(MEVENT, pmpriv);
+ PRINTM(MEVENT, "||");
+ /* Handle unexpected PS AWAKE event */
+ if (pmadapter->ps_state == PS_STATE_SLEEP_CFM)
+ break;
+ pmadapter->pm_wakeup_card_req = MFALSE;
+ pmadapter->pm_wakeup_fw_try = MFALSE;
+ pmadapter->ps_state = PS_STATE_AWAKE;
+
+ break;
+ case EVENT_PS_SLEEP:
+ PRINTM(MINFO, "EVENT: SLEEP\n");
+ PRINTM_NETINTF(MEVENT, pmpriv);
+ PRINTM(MEVENT, "__");
+ /* Handle unexpected PS SLEEP event */
+ if (pmadapter->ps_state == PS_STATE_SLEEP_CFM)
+ break;
+ pmadapter->ps_state = PS_STATE_PRE_SLEEP;
+ wlan_check_ps_cond(pmadapter);
+ break;
+ case EVENT_MICRO_AP_STA_ASSOC:
+ wlan_process_sta_assoc_event(pmpriv, pevent, pmbuf);
+ memcpy_ext(pmadapter, sta_addr, pmadapter->event_body + 2,
+ MLAN_MAC_ADDR_LENGTH, MLAN_MAC_ADDR_LENGTH);
+ sta_ptr = wlan_add_station_entry(pmpriv, sta_addr);
+ PRINTM_NETINTF(MMSG, pmpriv);
+ PRINTM(MMSG, "wlan: EVENT: MICRO_AP_STA_ASSOC " MACSTR "\n",
+ MAC2STR(sta_addr));
+ if (!sta_ptr)
+ break;
+ if (pmpriv->is_11n_enabled
+#ifdef DRV_EMBEDDED_AUTHENTICATOR
+ || IsAuthenticatorEnabled(pmpriv->psapriv)
+#endif
+ ) {
+ wlan_check_sta_capability(pmpriv, pmbuf, sta_ptr);
+ for (i = 0; i < MAX_NUM_TID; i++) {
+ if (sta_ptr->is_11n_enabled)
+ sta_ptr->ampdu_sta[i] =
+ pmpriv->aggr_prio_tbl[i]
+ .ampdu_user;
+ else
+ sta_ptr->ampdu_sta[i] =
+ BA_STREAM_NOT_ALLOWED;
+ }
+ memset(pmadapter, sta_ptr->rx_seq, 0xff,
+ sizeof(sta_ptr->rx_seq));
+ }
+ if (pmpriv->sec_info.wapi_enabled)
+ wlan_update_wapi_info_tlv(pmpriv, pmbuf);
+#ifdef DRV_EMBEDDED_AUTHENTICATOR
+ /**enter authenticator*/
+ if (IsAuthenticatorEnabled(pmpriv->psapriv))
+ AuthenticatorSendEapolPacket(
+ pmpriv->psapriv, sta_ptr->cm_connectioninfo);
+#endif
+ pevent->event_id = MLAN_EVENT_ID_DRV_PASSTHRU;
+ break;
+ case EVENT_MICRO_AP_STA_DEAUTH:
+ pevent->event_id = MLAN_EVENT_ID_UAP_FW_STA_DISCONNECT;
+ pevent->bss_index = pmpriv->bss_index;
+ pevent->event_len = pmbuf->data_len - 4;
+ /* skip event length field */
+ memcpy_ext(pmadapter, (t_u8 *)pevent->event_buf,
+ pmbuf->pbuf + pmbuf->data_offset + 4,
+ pevent->event_len, pevent->event_len);
+ wlan_recv_event(pmpriv, pevent->event_id, pevent);
+ memcpy_ext(pmadapter, sta_addr, pmadapter->event_body + 2,
+ MLAN_MAC_ADDR_LENGTH, MLAN_MAC_ADDR_LENGTH);
+ PRINTM_NETINTF(MMSG, pmpriv);
+ PRINTM(MMSG, "wlan: EVENT: MICRO_AP_STA_DEAUTH " MACSTR "\n",
+ MAC2STR(sta_addr));
+ if (pmpriv->is_11n_enabled) {
+ wlan_cleanup_reorder_tbl(pmpriv, sta_addr);
+ wlan_11n_cleanup_txbastream_tbl(pmpriv, sta_addr);
+ }
+ wlan_wmm_delete_peer_ralist(pmpriv, sta_addr);
+ wlan_delete_station_entry(pmpriv, sta_addr);
+ pevent->event_id = MLAN_EVENT_ID_DRV_PASSTHRU;
+ break;
+ case EVENT_HS_ACT_REQ:
+ PRINTM(MEVENT, "EVENT: HS_ACT_REQ\n");
+ ret = wlan_prepare_cmd(pmpriv, HostCmd_CMD_802_11_HS_CFG_ENH, 0,
+ 0, MNULL, MNULL);
+ break;
+ case EVENT_ADDBA:
+ PRINTM(MEVENT, "EVENT: ADDBA Request\n");
+ if (pmpriv->media_connected == MTRUE)
+ ret = wlan_prepare_cmd(pmpriv,
+ HostCmd_CMD_11N_ADDBA_RSP,
+ HostCmd_ACT_GEN_SET, 0, MNULL,
+ pmadapter->event_body);
+ else
+ PRINTM(MERROR,
+ "Ignore ADDBA Request event in BSS idle state\n");
+ break;
+ case EVENT_DELBA:
+ PRINTM(MEVENT, "EVENT: DELBA Request\n");
+ if (pmpriv->media_connected == MTRUE)
+ wlan_11n_delete_bastream(pmpriv, pmadapter->event_body);
+ else
+ PRINTM(MERROR,
+ "Ignore DELBA Request event in BSS idle state\n");
+ break;
+ case EVENT_BA_STREAM_TIMEOUT:
+ PRINTM(MEVENT, "EVENT: BA Stream timeout\n");
+ if (pmpriv->media_connected == MTRUE)
+ wlan_11n_ba_stream_timeout(
+ pmpriv, (HostCmd_DS_11N_BATIMEOUT *)
+ pmadapter->event_body);
+ else
+ PRINTM(MERROR,
+ "Ignore BA Stream timeout event in BSS idle state\n");
+ break;
+ case EVENT_RXBA_SYNC:
+ PRINTM(MEVENT, "EVENT: RXBA_SYNC\n");
+ wlan_11n_rxba_sync_event(pmpriv, pmadapter->event_body,
+ pmbuf->data_len - sizeof(eventcause));
+ break;
+ case EVENT_AMSDU_AGGR_CTRL:
+ PRINTM(MEVENT, "EVENT: AMSDU_AGGR_CTRL %d\n",
+ *(t_u16 *)pmadapter->event_body);
+ pmadapter->tx_buf_size =
+ MIN(pmadapter->curr_tx_buf_size,
+ wlan_le16_to_cpu(*(t_u16 *)pmadapter->event_body));
+ if (pmbuf->data_len == sizeof(eventcause) + sizeof(t_u32)) {
+ enable = wlan_le16_to_cpu(
+ *(t_u16 *)(pmadapter->event_body +
+ sizeof(t_u16)));
+ if (enable)
+ pmpriv->amsdu_disable = MFALSE;
+ else
+ pmpriv->amsdu_disable = MTRUE;
+ PRINTM(MEVENT, "amsdu_disable=%d\n",
+ pmpriv->amsdu_disable);
+ }
+ PRINTM(MEVENT, "tx_buf_size %d\n", pmadapter->tx_buf_size);
+ break;
+ case EVENT_TX_DATA_PAUSE:
+ PRINTM(MEVENT, "EVENT: TX_DATA_PAUSE\n");
+ wlan_process_tx_pause_event(priv, pmbuf);
+ break;
+ case EVENT_RADAR_DETECTED:
+ PRINTM_NETINTF(MEVENT, pmpriv);
+ PRINTM(MEVENT, "EVENT: Radar Detected\n");
+ if (pmpriv->adapter->dfs_test_params.cac_restart &&
+ pmpriv->adapter->state_dfs.dfs_check_pending) {
+ wlan_11h_cancel_radar_detect(pmpriv);
+ wlan_11h_issue_radar_detect(
+ pmpriv, MNULL,
+ pmpriv->adapter->dfs_test_params.chan,
+ pmpriv->adapter->dfs_test_params.bandcfg);
+ pevent->event_id = 0;
+ break;
+ }
+ /* Send as passthru first, this event can cause other events */
+ memset(pmadapter, event_buf, 0x00, MAX_EVENT_SIZE);
+ pevent->bss_index = pmpriv->bss_index;
+ pevent->event_id = MLAN_EVENT_ID_DRV_PASSTHRU;
+ pevent->event_len = pmbuf->data_len;
+ memcpy_ext(pmadapter, (t_u8 *)pevent->event_buf,
+ pmbuf->pbuf + pmbuf->data_offset, pevent->event_len,
+ pevent->event_len);
+ wlan_recv_event(pmpriv, pevent->event_id, pevent);
+ pevent->event_id = 0; /* clear to avoid resending at end of fcn
+ */
+
+ /* Print event data */
+ pevent->event_id = MLAN_EVENT_ID_FW_RADAR_DETECTED;
+ pevent->event_len = pmbuf->data_len - sizeof(eventcause);
+ memcpy_ext(pmadapter, (t_u8 *)pevent->event_buf,
+ pmbuf->pbuf + pmbuf->data_offset +
+ sizeof(eventcause),
+ pevent->event_len, pevent->event_len);
+ wlan_11h_print_event_radar_detected(pmpriv, pevent, &channel);
+ *((t_u8 *)pevent->event_buf) = channel;
+ if (!pmpriv->intf_state_11h.is_11h_host) {
+ if (pmadapter->state_rdh.stage == RDH_OFF) {
+ pmadapter->state_rdh.stage = RDH_CHK_INTFS;
+ wlan_11h_radar_detected_handling(pmadapter,
+ pmpriv);
+ if (pmpriv->uap_host_based)
+ wlan_recv_event(
+ priv,
+ MLAN_EVENT_ID_FW_RADAR_DETECTED,
+ pevent);
+ } else {
+ PRINTM(MEVENT,
+ "Ignore Event Radar Detected - handling"
+ " already in progress.\n");
+ }
+ } else {
+ if (pmpriv->adapter->dfs_test_params
+ .no_channel_change_on_radar ||
+ pmpriv->adapter->dfs_test_params
+ .fixed_new_channel_on_radar) {
+ if (pmadapter->state_rdh.stage == RDH_OFF ||
+ pmadapter->state_rdh.stage ==
+ RDH_SET_CUSTOM_IE) {
+ pmadapter->state_rdh.stage =
+ RDH_CHK_INTFS;
+ wlan_11h_radar_detected_handling(
+ pmadapter, pmpriv);
+ } else
+ PRINTM(MEVENT,
+ "Ignore Event Radar Detected - handling already in progress.\n");
+ } else {
+ pmpriv->intf_state_11h.tx_disabled = MTRUE;
+ wlan_recv_event(priv,
+ MLAN_EVENT_ID_FW_RADAR_DETECTED,
+ pevent);
+ }
+ }
+
+ pevent->event_id = 0; /* clear to avoid resending at end of fcn
+ */
+ break;
+ case EVENT_CHANNEL_REPORT_RDY:
+ PRINTM_NETINTF(MEVENT, pmpriv);
+ PRINTM(MEVENT, "EVENT: Channel Report Ready\n");
+ pmpriv->adapter->dfs_test_params.cac_restart = MFALSE;
+ memset(pmadapter, event_buf, 0x00, MAX_EVENT_SIZE);
+ /* Setup event buffer */
+ pevent->bss_index = pmpriv->bss_index;
+ pevent->event_id = MLAN_EVENT_ID_FW_CHANNEL_REPORT_RDY;
+ pevent->event_len = pmbuf->data_len - sizeof(eventcause);
+ /* Copy event data */
+ memcpy_ext(pmadapter, (t_u8 *)pevent->event_buf,
+ pmbuf->pbuf + pmbuf->data_offset +
+ sizeof(eventcause),
+ pevent->event_len, pevent->event_len);
+ /* Handle / pass event data, and free buffer */
+ ret = wlan_11h_handle_event_chanrpt_ready(pmpriv, pevent,
+ &channel);
+ if (pmpriv->intf_state_11h.is_11h_host) {
+ *((t_u8 *)pevent->event_buf) =
+ pmpriv->adapter->state_dfs.dfs_radar_found;
+ *((t_u8 *)pevent->event_buf + 1) = channel;
+ wlan_recv_event(pmpriv,
+ MLAN_EVENT_ID_FW_CHANNEL_REPORT_RDY,
+ pevent);
+ } else {
+ /* Send up this Event to unblock MOAL waitqueue */
+ wlan_recv_event(pmpriv, MLAN_EVENT_ID_DRV_MEAS_REPORT,
+ MNULL);
+ }
+ pevent->event_id = MLAN_EVENT_ID_DRV_PASSTHRU;
+ break;
+ case EVENT_CHANNEL_SWITCH:
+ pchan_info =
+ (MrvlIEtypes_channel_band_t *)(pmadapter->event_body);
+ channel = pchan_info->channel;
+ PRINTM_NETINTF(MEVENT, pmpriv);
+ PRINTM(MEVENT, "EVENT: CHANNEL_SWITCH new channel %d\n",
+ channel);
+ pmpriv->uap_channel = channel;
+ pmpriv->uap_state_chan_cb.channel = pchan_info->channel;
+ pmpriv->uap_state_chan_cb.bandcfg = pchan_info->bandcfg;
+ if (wlan_11h_radar_detect_required(pmpriv,
+ pchan_info->channel)) {
+ if (!wlan_11h_is_active(pmpriv)) {
+ /* active 11h extention in Fw */
+ ret = wlan_11h_activate(pmpriv, MNULL, MTRUE);
+ ret = wlan_11h_config_master_radar_det(pmpriv,
+ MTRUE);
+ ret = wlan_11h_check_update_radar_det_state(
+ pmpriv);
+ }
+ if (pmpriv->uap_host_based)
+ pmpriv->intf_state_11h.is_11h_host = MTRUE;
+ wlan_11h_set_dfs_check_chan(pmpriv,
+ pchan_info->channel);
+ }
+ if ((pmpriv->adapter->state_rdh.stage != RDH_OFF &&
+ !pmpriv->intf_state_11h.is_11h_host) ||
+ pmpriv->adapter->dfs_test_params.no_channel_change_on_radar ||
+ pmpriv->adapter->dfs_test_params.fixed_new_channel_on_radar) {
+ /* Handle embedded DFS */
+ if (pmpriv->adapter->state_rdh.stage ==
+ RDH_SET_CUSTOM_IE) {
+ pmadapter->state_rdh.stage =
+ RDH_RESTART_TRAFFIC;
+ wlan_11h_radar_detected_handling(pmadapter,
+ pmpriv);
+ }
+
+ } else {
+ /* Handle Host-based DFS and non-DFS(normal uap) case */
+ pmpriv->intf_state_11h.tx_disabled = MFALSE;
+ memset(pmadapter, event_buf, 0x00, MAX_EVENT_SIZE);
+ /* Setup event buffer */
+ pevent->bss_index = pmpriv->bss_index;
+ pevent->event_id =
+ MLAN_EVENT_ID_FW_CHAN_SWITCH_COMPLETE;
+ pevent->event_len = sizeof(chan_band_info);
+ pchan_band_info = (chan_band_info *)pevent->event_buf;
+ /* Copy event data */
+ memcpy_ext(pmadapter, (t_u8 *)&pchan_band_info->bandcfg,
+ (t_u8 *)&pchan_info->bandcfg,
+ sizeof(pchan_info->bandcfg),
+ sizeof(pchan_info->bandcfg));
+ pchan_band_info->channel = pchan_info->channel;
+ if (pchan_band_info->bandcfg.chanWidth == CHAN_BW_80MHZ)
+ pchan_band_info->center_chan =
+ wlan_get_center_freq_idx(
+ priv, BAND_AAC,
+ pchan_info->channel,
+ CHANNEL_BW_80MHZ);
+ pchan_band_info->is_11n_enabled =
+ pmpriv->is_11n_enabled;
+ wlan_recv_event(pmpriv,
+ MLAN_EVENT_ID_FW_CHAN_SWITCH_COMPLETE,
+ pevent);
+ pevent->event_id = 0;
+ }
+ break;
+ case EVENT_REMAIN_ON_CHANNEL_EXPIRED:
+ PRINTM_NETINTF(MEVENT, pmpriv);
+ PRINTM(MEVENT, "EVENT: REMAIN_ON_CHANNEL_EXPIRED reason=%d\n",
+ *(t_u16 *)pmadapter->event_body);
+ wlan_recv_event(pmpriv, MLAN_EVENT_ID_DRV_FLUSH_RX_WORK, MNULL);
+ pevent->event_id = MLAN_EVENT_ID_FW_REMAIN_ON_CHAN_EXPIRED;
+ break;
+
+ case EVENT_FW_DEBUG_INFO:
+ memset(pmadapter, event_buf, 0x00, MAX_EVENT_SIZE);
+ pevent->bss_index = pmpriv->bss_index;
+ pevent->event_id = MLAN_EVENT_ID_FW_DEBUG_INFO;
+ pevent->event_len = pmbuf->data_len - sizeof(eventcause);
+ memcpy_ext(pmadapter, (t_u8 *)pevent->event_buf,
+ pmbuf->pbuf + pmbuf->data_offset +
+ sizeof(eventcause),
+ pevent->event_len, pevent->event_len);
+ PRINTM(MEVENT, "EVENT: FW Debug Info %s\n",
+ (t_u8 *)pevent->event_buf);
+ wlan_recv_event(pmpriv, pevent->event_id, pevent);
+ pevent->event_id = 0; /* clear to avoid resending at end of fcn
+ */
+ break;
+ case EVENT_TX_STATUS_REPORT:
+ PRINTM(MINFO, "EVENT: TX_STATUS\n");
+ pevent->event_id = MLAN_EVENT_ID_FW_TX_STATUS;
+ break;
+ case EVENT_BT_COEX_WLAN_PARA_CHANGE:
+ PRINTM(MEVENT, "EVENT: BT coex wlan param update\n");
+ wlan_bt_coex_wlan_param_update_event(pmpriv, pmbuf);
+ break;
+ case EVENT_EXCEED_MAX_P2P_CONN:
+ event_excd_p2p =
+ (event_exceed_max_p2p_conn *)(pmbuf->pbuf +
+ pmbuf->data_offset);
+ PRINTM(MEVENT, "EVENT: EXCEED MAX P2P CONNECTION\n");
+ PRINTM(MEVENT, "REQUEST P2P MAC: " MACSTR "\n",
+ MAC2STR(event_excd_p2p->peer_mac_addr));
+ pevent->event_id = MLAN_EVENT_ID_DRV_PASSTHRU;
+ break;
+ case EVENT_VDLL_IND:
+ wlan_process_vdll_event(pmpriv, pmbuf);
+ break;
+
+ case EVENT_FW_HANG_REPORT:
+ if (pmbuf->data_len < (sizeof(eventcause) + sizeof(t_u16))) {
+ PRINTM(MEVENT,
+ "EVENT: EVENT_FW_HANG_REPORT skip for len too short: %d\n",
+ pmbuf->data_len);
+ break;
+ }
+ PRINTM(MEVENT, "EVENT: EVENT_FW_HANG_REPORT reasoncode=%d\n",
+ wlan_le16_to_cpu(*(t_u16 *)(pmbuf->pbuf +
+ pmbuf->data_offset +
+ sizeof(eventcause))));
+ pmadapter->fw_hang_report = MTRUE;
+ wlan_recv_event(pmpriv, MLAN_EVENT_ID_DRV_DBG_DUMP, MNULL);
+ break;
+ case EVENT_WATCHDOG_TMOUT:
+ PRINTM(MEVENT, "EVENT: EVENT_WATCHDOG_TMOUT reasoncode=%d\n",
+ wlan_le16_to_cpu(*(t_u16 *)(pmbuf->pbuf +
+ pmbuf->data_offset +
+ sizeof(eventcause))));
+ pevent->event_id = MLAN_EVENT_ID_DRV_WIFI_STATUS;
+ pevent->event_len = sizeof(pevent->event_id) + sizeof(t_u16);
+ memcpy_ext(pmadapter, (t_u8 *)pevent->event_buf,
+ pmbuf->pbuf + pmbuf->data_offset +
+ sizeof(eventcause),
+ sizeof(t_u16), sizeof(t_u16));
+ break;
+ default:
+ pevent->event_id = MLAN_EVENT_ID_DRV_PASSTHRU;
+ break;
+ }
+
+ if (pevent->event_id) {
+ pevent->bss_index = pmpriv->bss_index;
+ pevent->event_len = pmbuf->data_len;
+ memcpy_ext(pmadapter, (t_u8 *)pevent->event_buf,
+ pmbuf->pbuf + pmbuf->data_offset, pevent->event_len,
+ pevent->event_len);
+ wlan_recv_event(pmpriv, pevent->event_id, pevent);
+ }
+done:
+ if (event_buf)
+ pcb->moal_mfree(pmadapter->pmoal_handle, event_buf);
+ LEAVE();
+ return ret;
+}
+
+/**
+ * @brief This function issues commands to set uap max sta number
+ *
+ * @param priv A pointer to mlan_private structure
+ * @param uap_max_sta Max station number uAP can supported (per chip)
+ *
+ * @return MLAN_STATUS_SUCCESS or MLAN_STATUS_PENDING or MLAN_STATUS_FAILURE
+ */
+mlan_status wlan_uap_set_uap_max_sta(pmlan_private pmpriv, t_u8 uap_max_sta)
+{
+ MrvlIEtypes_uap_max_sta_cnt_t tlv_uap_max_sta;
+ mlan_status ret = MLAN_STATUS_SUCCESS;
+
+ ENTER();
+ memset(pmpriv->adapter, &tlv_uap_max_sta, 0, sizeof(tlv_uap_max_sta));
+ tlv_uap_max_sta.header.type =
+ wlan_cpu_to_le16(TLV_TYPE_UAP_MAX_STA_CNT_PER_CHIP);
+ tlv_uap_max_sta.header.len = wlan_cpu_to_le16(sizeof(t_u16));
+ tlv_uap_max_sta.uap_max_sta = wlan_cpu_to_le16(uap_max_sta);
+ ret = wlan_prepare_cmd(pmpriv, HOST_CMD_APCMD_SYS_CONFIGURE,
+ HostCmd_ACT_GEN_SET, 0, MNULL, &tlv_uap_max_sta);
+ LEAVE();
+ return ret;
+}
+
+/**
+ * @brief This function issues commands to initialize firmware
+ *
+ * @param priv A pointer to mlan_private structure
+ * @param first_bss flag for first BSS
+ *
+ * @return MLAN_STATUS_SUCCESS or MLAN_STATUS_PENDING or MLAN_STATUS_FAILURE
+ */
+mlan_status wlan_ops_uap_init_cmd(t_void *priv, t_u8 first_bss)
+{
+ mlan_status ret = MLAN_STATUS_SUCCESS;
+ pmlan_private pmpriv = (pmlan_private)priv;
+ t_u16 last_cmd = 0;
+
+ ENTER();
+ if (!pmpriv) {
+ LEAVE();
+ return MLAN_STATUS_FAILURE;
+ }
+
+ if (first_bss) {
+ if (wlan_adapter_init_cmd(pmpriv->adapter) ==
+ MLAN_STATUS_FAILURE) {
+ ret = MLAN_STATUS_FAILURE;
+ goto done;
+ }
+ }
+ if (pmpriv->adapter->init_para.uap_max_sta &&
+ (pmpriv->adapter->init_para.uap_max_sta <= MAX_STA_COUNT))
+ wlan_uap_set_uap_max_sta(
+ pmpriv, pmpriv->adapter->init_para.uap_max_sta);
+
+ ret = wlan_prepare_cmd(pmpriv, HOST_CMD_APCMD_SYS_CONFIGURE,
+ HostCmd_ACT_GEN_GET, 0, MNULL, MNULL);
+ if (ret) {
+ ret = MLAN_STATUS_FAILURE;
+ goto done;
+ }
+ last_cmd = HOST_CMD_APCMD_SYS_CONFIGURE;
+ /** set last_init_cmd */
+ if (last_cmd) {
+ pmpriv->adapter->last_init_cmd = last_cmd;
+ ret = MLAN_STATUS_PENDING;
+ }
+done:
+ LEAVE();
+ return ret;
+}
diff --git a/drivers/net/wireless/nxp/mxm_wifiex/wlan_src/mlan/mlan_uap_ioctl.c b/drivers/net/wireless/nxp/mxm_wifiex/wlan_src/mlan/mlan_uap_ioctl.c
new file mode 100644
index 000000000000..2610627c123b
--- /dev/null
+++ b/drivers/net/wireless/nxp/mxm_wifiex/wlan_src/mlan/mlan_uap_ioctl.c
@@ -0,0 +1,2240 @@
+/** @file mlan_uap_ioctl.c
+ *
+ * @brief This file contains the handling of AP mode ioctls
+ *
+ *
+ * Copyright 2014-2020 NXP
+ *
+ * This software file (the File) is distributed by NXP
+ * under the terms of the GNU General Public License Version 2, June 1991
+ * (the License). You may use, redistribute and/or modify the 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.
+ *
+ */
+
+/********************************************************
+Change log:
+ 02/05/2009: initial version
+********************************************************/
+
+#include "mlan.h"
+#include "mlan_util.h"
+#include "mlan_fw.h"
+#ifdef STA_SUPPORT
+#include "mlan_join.h"
+#endif
+#include "mlan_main.h"
+#include "mlan_uap.h"
+#include "mlan_11n.h"
+#include "mlan_fw.h"
+#include "mlan_11h.h"
+#include "mlan_11ac.h"
+#include "mlan_11ax.h"
+
+/********************************************************
+ Global Variables
+********************************************************/
+extern t_u8 tos_to_tid_inv[];
+
+/********************************************************
+ Local Functions
+********************************************************/
+/**
+ * @brief Stop BSS
+ *
+ * @param pmadapter A pointer to mlan_adapter structure
+ * @param pioctl_req A pointer to ioctl request buffer
+ *
+ * @return MLAN_STATUS_PENDING --success, otherwise fail
+ */
+static mlan_status wlan_uap_bss_ioctl_stop(pmlan_adapter pmadapter,
+ pmlan_ioctl_req pioctl_req)
+{
+ mlan_status ret = MLAN_STATUS_SUCCESS;
+ pmlan_private pmpriv = pmadapter->priv[pioctl_req->bss_index];
+
+ ENTER();
+
+ ret = wlan_prepare_cmd(pmpriv, HOST_CMD_APCMD_BSS_STOP,
+ HostCmd_ACT_GEN_SET, 0, (t_void *)pioctl_req,
+ MNULL);
+ if (ret == MLAN_STATUS_SUCCESS)
+ ret = MLAN_STATUS_PENDING;
+
+ LEAVE();
+ return ret;
+}
+
+static t_bool wlan_can_radar_det_skip(mlan_private *priv)
+{
+ mlan_private *priv_list[MLAN_MAX_BSS_NUM];
+ mlan_private *pmpriv;
+ mlan_adapter *pmadapter = priv->adapter;
+ t_u8 pcount, i;
+
+ /* In MBSS environment, if one of the BSS is already beaconing and DRCS
+ * is off then 11n_radar detection is not required for subsequent BSSes
+ * since they will follow the primary bss.
+ */
+ if ((GET_BSS_ROLE(priv) == MLAN_BSS_ROLE_UAP)) {
+ memset(pmadapter, priv_list, 0x00, sizeof(priv_list));
+ pcount = wlan_get_privs_by_cond(pmadapter, wlan_is_intf_active,
+ priv_list);
+ for (i = 0; i < pcount; i++) {
+ pmpriv = priv_list[i];
+ if (GET_BSS_ROLE(pmpriv) == MLAN_BSS_ROLE_UAP)
+ return MTRUE;
+ }
+ }
+ return MFALSE;
+}
+/**
+ * @brief Callback to finish BSS IOCTL START
+ * Not to be called directly to initiate bss_start
+ *
+ * @param priv A pointer to mlan_private structure (cast from t_void*)
+ *
+ * @return MLAN_STATUS_PENDING --success, otherwise fail
+ * @sa wlan_uap_bss_ioctl_start
+ */
+static mlan_status wlan_uap_callback_bss_ioctl_start(t_void *priv)
+{
+ mlan_status ret = MLAN_STATUS_SUCCESS;
+ mlan_private *pmpriv = (mlan_private *)priv;
+ mlan_callbacks *pcb = (mlan_callbacks *)&pmpriv->adapter->callbacks;
+ wlan_uap_get_info_cb_t *puap_state_chan_cb = &pmpriv->uap_state_chan_cb;
+ t_u8 old_channel;
+ t_bool under_nop = MFALSE;
+ ENTER();
+ /* clear callback now that we're here */
+ puap_state_chan_cb->get_chan_callback = MNULL;
+
+ /*
+ * Check if the region and channel requires we check for radar.
+ */
+ if ((puap_state_chan_cb->bandcfg.chanBand == BAND_5GHZ) &&
+ !wlan_can_radar_det_skip(pmpriv) &&
+ wlan_11h_radar_detect_required(pmpriv,
+ puap_state_chan_cb->channel)) {
+ /* If DFS repeater mode is on then before starting the uAP
+ * make sure that mlan0 is connected to some external AP
+ * for DFS channel operations.
+ */
+ if (pmpriv->adapter->dfs_repeater) {
+ pmlan_private tmpriv = MNULL;
+ tmpriv = wlan_get_priv(pmpriv->adapter,
+ MLAN_BSS_ROLE_STA);
+
+ if (tmpriv && !tmpriv->media_connected) {
+ PRINTM(MERROR,
+ "BSS start is blocked when DFS-repeater\n"
+ "mode is on and STA is not connected\n");
+ pcb->moal_ioctl_complete(
+ pmpriv->adapter->pmoal_handle,
+ puap_state_chan_cb->pioctl_req_curr,
+ MLAN_STATUS_FAILURE);
+ goto done;
+ } else {
+ /* STA is connected.
+ * Skip DFS check for bss_start since its a
+ * repeater mode
+ */
+ goto prep_bss_start;
+ }
+ }
+
+ /* first check if channel is under NOP */
+ if (wlan_11h_is_channel_under_nop(
+ pmpriv->adapter, puap_state_chan_cb->channel)) {
+ /* recently we've seen radar on this channel */
+ ret = MLAN_STATUS_FAILURE;
+ under_nop = MTRUE;
+ }
+
+ /* Check cached radar check on the channel */
+ if (ret == MLAN_STATUS_SUCCESS)
+ ret = wlan_11h_check_chan_report(
+ pmpriv, puap_state_chan_cb->channel);
+
+ /* Found radar: try to switch to a non-dfs channel */
+ if (ret != MLAN_STATUS_SUCCESS) {
+ old_channel = puap_state_chan_cb->channel;
+ ret = wlan_11h_switch_non_dfs_chan(
+ pmpriv, &puap_state_chan_cb->channel);
+
+ if (ret == MLAN_STATUS_SUCCESS) {
+ wlan_11h_update_bandcfg(
+ &pmpriv->uap_state_chan_cb.bandcfg,
+ puap_state_chan_cb->channel);
+ PRINTM(MCMD_D,
+ "NOP: uap band config:0x%x channel=%d\n",
+ pmpriv->uap_state_chan_cb.bandcfg,
+ puap_state_chan_cb->channel);
+
+ ret = wlan_uap_set_channel(
+ pmpriv,
+ pmpriv->uap_state_chan_cb.bandcfg,
+ puap_state_chan_cb->channel);
+ if (ret == MLAN_STATUS_SUCCESS) {
+ if (under_nop) {
+ PRINTM(MMSG,
+ "Channel %d under NOP,"
+ " switched to new channel %d successfully.\n",
+ old_channel,
+ puap_state_chan_cb
+ ->channel);
+ } else {
+ PRINTM(MMSG,
+ "Radar found on channel %d,"
+ " switched to new channel %d successfully.\n",
+ old_channel,
+ puap_state_chan_cb
+ ->channel);
+ }
+ } else {
+ if (under_nop) {
+ PRINTM(MMSG,
+ "Channel %d under NOP,"
+ " switch to new channel %d failed.\n",
+ old_channel,
+ puap_state_chan_cb
+ ->channel);
+ } else {
+ PRINTM(MMSG,
+ "Radar found on channel %d,"
+ " switch to new channel %d failed.\n",
+ old_channel,
+ puap_state_chan_cb
+ ->channel);
+ }
+ pcb->moal_ioctl_complete(
+ pmpriv->adapter->pmoal_handle,
+ puap_state_chan_cb
+ ->pioctl_req_curr,
+ MLAN_STATUS_FAILURE);
+ goto done;
+ }
+ } else {
+ if (under_nop) {
+ PRINTM(MMSG,
+ "Channel %d under NOP, no switch channel available.\n",
+ old_channel);
+ } else {
+ PRINTM(MMSG,
+ "Radar found on channel %d, no switch channel available.\n",
+ old_channel);
+ }
+ /* No command sent with the ioctl, need manually
+ * signal completion */
+ pcb->moal_ioctl_complete(
+ pmpriv->adapter->pmoal_handle,
+ puap_state_chan_cb->pioctl_req_curr,
+ MLAN_STATUS_FAILURE);
+ goto done;
+ }
+ } else {
+ PRINTM(MINFO, "No Radar found on channel %d\n",
+ puap_state_chan_cb->channel);
+ }
+ }
+
+prep_bss_start:
+ /* else okay to send command: not DFS channel or no radar */
+ ret = wlan_prepare_cmd(pmpriv, HOST_CMD_APCMD_BSS_START,
+ HostCmd_ACT_GEN_SET, 0,
+ (t_void *)puap_state_chan_cb->pioctl_req_curr,
+ MNULL);
+ if (ret == MLAN_STATUS_SUCCESS)
+ ret = MLAN_STATUS_PENDING;
+
+done:
+ puap_state_chan_cb->pioctl_req_curr = MNULL; /* prevent re-use */
+ LEAVE();
+ return ret;
+}
+
+/**
+ * @brief Start BSS
+ *
+ * @param pmadapter A pointer to mlan_adapter structure
+ * @param pioctl_req A pointer to ioctl request buffer
+ *
+ * @return MLAN_STATUS_PENDING --success, otherwise fail
+ */
+/**
+ * @sa wlan_uap_callback_bss_ioctl_start
+ */
+static mlan_status wlan_uap_bss_ioctl_start(pmlan_adapter pmadapter,
+ pmlan_ioctl_req pioctl_req)
+{
+ mlan_status ret = MLAN_STATUS_SUCCESS;
+ pmlan_private pmpriv = pmadapter->priv[pioctl_req->bss_index];
+ mlan_ds_bss *bss = MNULL;
+
+ ENTER();
+
+ bss = (mlan_ds_bss *)pioctl_req->pbuf;
+ pmpriv->uap_host_based = bss->param.host_based;
+ if (!pmpriv->intf_state_11h.is_11h_host &&
+ pmpriv->intf_state_11h.is_11h_active) {
+ /* if FW supports ACS+DFS then sequence is different */
+
+ /* First check channel report, defer BSS_START CMD to callback.
+ */
+ /* store params, issue command to get UAP channel, whose
+ * CMD_RESP will callback remainder of bss_start handling */
+ pmpriv->uap_state_chan_cb.pioctl_req_curr = pioctl_req;
+ pmpriv->uap_state_chan_cb.get_chan_callback =
+ wlan_uap_callback_bss_ioctl_start;
+ pmpriv->intf_state_11h.is_11h_host = MFALSE;
+ ret = wlan_uap_get_channel(pmpriv);
+ if (ret == MLAN_STATUS_SUCCESS)
+ ret = MLAN_STATUS_PENDING;
+ } else {
+ ret = wlan_prepare_cmd(pmpriv, HOST_CMD_APCMD_BSS_START,
+ HostCmd_ACT_GEN_SET, 0,
+ (t_void *)pioctl_req, MNULL);
+ if (ret == MLAN_STATUS_SUCCESS)
+ ret = MLAN_STATUS_PENDING;
+ }
+
+ LEAVE();
+ return ret;
+}
+
+/**
+ * @brief reset BSS
+ *
+ * @param pmadapter A pointer to mlan_adapter structure
+ * @param pioctl_req A pointer to ioctl request buffer
+ *
+ * @return MLAN_STATUS_PENDING --success, otherwise fail
+ */
+static mlan_status wlan_uap_bss_ioctl_reset(pmlan_adapter pmadapter,
+ pmlan_ioctl_req pioctl_req)
+{
+ mlan_status ret = MLAN_STATUS_SUCCESS;
+ pmlan_private pmpriv = pmadapter->priv[pioctl_req->bss_index];
+ t_u8 i = 0;
+
+ ENTER();
+
+ /*
+ * Reset any uap private parameters here
+ */
+ for (i = 0; i < pmadapter->max_mgmt_ie_index; i++)
+ memset(pmadapter, &pmpriv->mgmt_ie[i], 0, sizeof(custom_ie));
+ pmpriv->add_ba_param.timeout = MLAN_DEFAULT_BLOCK_ACK_TIMEOUT;
+ pmpriv->add_ba_param.tx_win_size = MLAN_UAP_AMPDU_DEF_TXWINSIZE;
+ pmpriv->add_ba_param.rx_win_size = MLAN_UAP_AMPDU_DEF_RXWINSIZE;
+ pmpriv->user_rxwinsize = pmpriv->add_ba_param.rx_win_size;
+
+ for (i = 0; i < MAX_NUM_TID; i++) {
+ pmpriv->aggr_prio_tbl[i].ampdu_user = tos_to_tid_inv[i];
+ pmpriv->aggr_prio_tbl[i].amsdu = tos_to_tid_inv[i];
+ pmpriv->addba_reject[i] = ADDBA_RSP_STATUS_ACCEPT;
+ }
+ pmpriv->aggr_prio_tbl[6].ampdu_user =
+ pmpriv->aggr_prio_tbl[7].ampdu_user = BA_STREAM_NOT_ALLOWED;
+ pmpriv->addba_reject[6] = pmpriv->addba_reject[7] =
+ ADDBA_RSP_STATUS_REJECT;
+
+ /* hs_configured, hs_activated are reset by main loop */
+ pmadapter->hs_cfg.conditions = HOST_SLEEP_DEF_COND;
+ pmadapter->hs_cfg.gpio = HOST_SLEEP_DEF_GPIO;
+ pmadapter->hs_cfg.gap = HOST_SLEEP_DEF_GAP;
+
+ ret = wlan_prepare_cmd(pmpriv, HOST_CMD_APCMD_SYS_RESET,
+ HostCmd_ACT_GEN_SET, 0, (t_void *)pioctl_req,
+ MNULL);
+ if (ret == MLAN_STATUS_SUCCESS)
+ ret = MLAN_STATUS_PENDING;
+
+ LEAVE();
+ return ret;
+}
+
+/**
+ * @brief This function to process add station.
+ *
+ * @param pmadapter A pointer to pmadapter.
+ *
+ * @param pioctl_req A pointer to pioctl_req
+ *
+ * @return MLAN_STATUS_SUCCESS/MLAN_STATUS_FAILURE
+ */
+mlan_status wlan_uap_bss_ioctl_add_station(pmlan_adapter pmadapter,
+ pmlan_ioctl_req pioctl_req)
+{
+ mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index];
+ mlan_status ret = MLAN_STATUS_SUCCESS;
+
+ ENTER();
+ ret = wlan_prepare_cmd(pmpriv, HostCmd_CMD_ADD_NEW_STATION,
+ HostCmd_ACT_ADD_STA, 0, (t_void *)pioctl_req,
+ MNULL);
+
+ if (ret == MLAN_STATUS_SUCCESS)
+ ret = MLAN_STATUS_PENDING;
+
+ LEAVE();
+ return ret;
+}
+
+/**
+ * @brief Set/Get MAC address
+ *
+ * @param pmadapter A pointer to mlan_adapter structure
+ * @param pioctl_req A pointer to ioctl request buffer
+ *
+ * @return MLAN_STATUS_PENDING --success, otherwise fail
+ */
+static mlan_status wlan_uap_bss_ioctl_mac_address(pmlan_adapter pmadapter,
+ pmlan_ioctl_req pioctl_req)
+{
+ mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index];
+ mlan_ds_bss *bss = MNULL;
+ mlan_status ret = MLAN_STATUS_SUCCESS;
+ t_u16 cmd_action = 0;
+
+ ENTER();
+
+ bss = (mlan_ds_bss *)pioctl_req->pbuf;
+ if (pioctl_req->action == MLAN_ACT_SET) {
+ memcpy_ext(pmadapter, pmpriv->curr_addr, &bss->param.mac_addr,
+ MLAN_MAC_ADDR_LENGTH, MLAN_MAC_ADDR_LENGTH);
+ cmd_action = HostCmd_ACT_GEN_SET;
+ } else
+ cmd_action = HostCmd_ACT_GEN_GET;
+ /* Send request to firmware */
+ ret = wlan_prepare_cmd(pmpriv, HOST_CMD_APCMD_SYS_CONFIGURE, cmd_action,
+ 0, (t_void *)pioctl_req, MNULL);
+
+ if (ret == MLAN_STATUS_SUCCESS)
+ ret = MLAN_STATUS_PENDING;
+
+ LEAVE();
+ return ret;
+}
+
+/**
+ * @brief Set/Get wmm param
+ *
+ * @param pmadapter A pointer to mlan_adapter structure
+ * @param pioctl_req A pointer to ioctl request buffer
+ *
+ * @return MLAN_STATUS_PENDING --success, otherwise fail
+ */
+static mlan_status wlan_uap_bss_ioctl_uap_wmm_param(pmlan_adapter pmadapter,
+ pmlan_ioctl_req pioctl_req)
+{
+ mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index];
+ mlan_ds_bss *bss = MNULL;
+ mlan_status ret = MLAN_STATUS_SUCCESS;
+ t_u16 cmd_action = 0;
+
+ ENTER();
+
+ bss = (mlan_ds_bss *)pioctl_req->pbuf;
+ if (pioctl_req->action == MLAN_ACT_SET)
+ cmd_action = HostCmd_ACT_GEN_SET;
+ else
+ cmd_action = HostCmd_ACT_GEN_GET;
+ /* Send request to firmware */
+ ret = wlan_prepare_cmd(pmpriv, HOST_CMD_APCMD_SYS_CONFIGURE, cmd_action,
+ 0, (t_void *)pioctl_req, MNULL);
+
+ if (ret == MLAN_STATUS_SUCCESS)
+ ret = MLAN_STATUS_PENDING;
+
+ LEAVE();
+ return ret;
+}
+
+/**
+ * @brief Set/Get scan channels
+ *
+ * @param pmadapter A pointer to mlan_adapter structure
+ * @param pioctl_req A pointer to ioctl request buffer
+ *
+ * @return MLAN_STATUS_PENDING --success, otherwise fail
+ */
+static mlan_status
+wlan_uap_bss_ioctl_uap_scan_channels(pmlan_adapter pmadapter,
+ pmlan_ioctl_req pioctl_req)
+{
+ mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index];
+ mlan_ds_bss *bss = MNULL;
+ mlan_status ret = MLAN_STATUS_SUCCESS;
+ t_u16 cmd_action = 0;
+
+ ENTER();
+
+ bss = (mlan_ds_bss *)pioctl_req->pbuf;
+ if (pioctl_req->action == MLAN_ACT_SET)
+ cmd_action = HostCmd_ACT_GEN_SET;
+ else
+ cmd_action = HostCmd_ACT_GEN_GET;
+ /* Send request to firmware */
+ ret = wlan_prepare_cmd(pmpriv, HOST_CMD_APCMD_SYS_CONFIGURE, cmd_action,
+ 0, (t_void *)pioctl_req, MNULL);
+
+ if (ret == MLAN_STATUS_SUCCESS)
+ ret = MLAN_STATUS_PENDING;
+
+ LEAVE();
+ return ret;
+}
+
+/**
+ * @brief Set/Get UAP channel
+ *
+ * @param pmadapter A pointer to mlan_adapter structure
+ * @param pioctl_req A pointer to ioctl request buffer
+ *
+ * @return MLAN_STATUS_PENDING --success, otherwise fail
+ */
+static mlan_status wlan_uap_bss_ioctl_uap_channel(pmlan_adapter pmadapter,
+ pmlan_ioctl_req pioctl_req)
+{
+ mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index];
+ mlan_ds_bss *bss = MNULL;
+ mlan_status ret = MLAN_STATUS_SUCCESS;
+ t_u16 cmd_action = 0;
+
+ ENTER();
+
+ bss = (mlan_ds_bss *)pioctl_req->pbuf;
+ if (pioctl_req->action == MLAN_ACT_SET)
+ cmd_action = HostCmd_ACT_GEN_SET;
+ else
+ cmd_action = HostCmd_ACT_GEN_GET;
+ /* Send request to firmware */
+ ret = wlan_prepare_cmd(pmpriv, HOST_CMD_APCMD_SYS_CONFIGURE, cmd_action,
+ 0, (t_void *)pioctl_req, MNULL);
+
+ if (ret == MLAN_STATUS_SUCCESS)
+ ret = MLAN_STATUS_PENDING;
+
+ LEAVE();
+ return ret;
+}
+
+/**
+ * @brief Set/Get UAP operation control vaule
+ *
+ * @param pmadapter A pointer to mlan_adapter structure
+ * @param pioctl_req A pointer to ioctl request buffer
+ *
+ * @return MLAN_STATUS_PENDING --success, otherwise fail
+ */
+static mlan_status wlan_uap_bss_ioctl_uap_oper_ctrl(pmlan_adapter pmadapter,
+ pmlan_ioctl_req pioctl_req)
+{
+ mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index];
+ mlan_ds_bss *bss = MNULL;
+ mlan_status ret = MLAN_STATUS_SUCCESS;
+ t_u16 cmd_action = 0;
+
+ ENTER();
+
+ if (pmadapter->fw_ver == HOST_API_VERSION_V15 &&
+ pmadapter->fw_min_ver >= FW_MINOR_VERSION_1) {
+ bss = (mlan_ds_bss *)pioctl_req->pbuf;
+ if (pioctl_req->action == MLAN_ACT_SET)
+ cmd_action = HostCmd_ACT_GEN_SET;
+ else
+ cmd_action = HostCmd_ACT_GEN_GET;
+ /* Send request to firmware */
+ ret = wlan_prepare_cmd(pmpriv, HOST_CMD_APCMD_OPER_CTRL,
+ cmd_action, 0, (t_void *)pioctl_req,
+ (t_void *)pioctl_req->pbuf);
+
+ if (ret == MLAN_STATUS_SUCCESS)
+ ret = MLAN_STATUS_PENDING;
+ } else {
+ PRINTM(MMSG, "FW don't support uap oper ctrl\n");
+ }
+ LEAVE();
+ return ret;
+}
+
+/**
+ * @brief Get Uap statistics
+ *
+ * @param pmadapter A pointer to mlan_adapter structure
+ * @param pioctl_req A pointer to ioctl request buffer
+ *
+ * @return MLAN_STATUS_PENDING --success, otherwise fail
+ */
+static mlan_status wlan_uap_get_stats(pmlan_adapter pmadapter,
+ pmlan_ioctl_req pioctl_req)
+{
+ mlan_status ret = MLAN_STATUS_SUCCESS;
+ pmlan_private pmpriv = pmadapter->priv[pioctl_req->bss_index];
+
+ ENTER();
+
+ ret = wlan_prepare_cmd(pmpriv, HostCmd_CMD_802_11_SNMP_MIB,
+ HostCmd_ACT_GEN_GET, 0, (t_void *)pioctl_req,
+ MNULL);
+ if (ret == MLAN_STATUS_SUCCESS)
+ ret = MLAN_STATUS_PENDING;
+
+ LEAVE();
+ return ret;
+}
+
+/**
+ * @brief Get Uap MIB counters
+ *
+ * @param pmadapter A pointer to mlan_adapter structure
+ * @param pioctl_req A pointer to ioctl request buffer
+ *
+ * @return MLAN_STATUS_PENDING --success, otherwise fail
+ */
+static mlan_status wlan_uap_get_stats_log(pmlan_adapter pmadapter,
+ pmlan_ioctl_req pioctl_req)
+{
+ pmlan_private pmpriv = MNULL;
+ mlan_status ret = MLAN_STATUS_SUCCESS;
+
+ ENTER();
+
+ if (pioctl_req != MNULL) {
+ pmpriv = pmadapter->priv[pioctl_req->bss_index];
+ } else {
+ PRINTM(MERROR, "MLAN IOCTL information is not present\n");
+ ret = MLAN_STATUS_FAILURE;
+ goto exit;
+ }
+
+ /* Check information buffer length of MLAN IOCTL */
+ if (pioctl_req->buf_len < sizeof(mlan_ds_get_stats)) {
+ PRINTM(MWARN,
+ "MLAN IOCTL information buffer length is too short.\n");
+ pioctl_req->data_read_written = 0;
+ pioctl_req->buf_len_needed = sizeof(mlan_ds_get_stats);
+ pioctl_req->status_code = MLAN_ERROR_INVALID_PARAMETER;
+ ret = MLAN_STATUS_RESOURCE;
+ goto exit;
+ }
+
+ /* Send request to firmware */
+ ret = wlan_prepare_cmd(pmpriv, HostCmd_CMD_802_11_GET_LOG,
+ HostCmd_ACT_GEN_GET, 0, (t_void *)pioctl_req,
+ MNULL);
+
+ if (ret == MLAN_STATUS_SUCCESS)
+ ret = MLAN_STATUS_PENDING;
+
+exit:
+ LEAVE();
+ return ret;
+}
+
+/**
+ * @brief Set/Get AP config
+ *
+ * @param pmadapter A pointer to mlan_adapter structure
+ * @param pioctl_req A pointer to ioctl request buffer
+ *
+ * @return MLAN_STATUS_PENDING --success, otherwise fail
+ */
+static mlan_status wlan_uap_bss_ioctl_config(pmlan_adapter pmadapter,
+ pmlan_ioctl_req pioctl_req)
+{
+ mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index];
+ mlan_status ret = MLAN_STATUS_SUCCESS;
+ t_u16 cmd_action = 0;
+
+ ENTER();
+
+ if (pioctl_req->action == MLAN_ACT_SET)
+ cmd_action = HostCmd_ACT_GEN_SET;
+ else
+ cmd_action = HostCmd_ACT_GEN_GET;
+
+ /* Send request to firmware */
+ ret = wlan_prepare_cmd(pmpriv, HOST_CMD_APCMD_SYS_CONFIGURE, cmd_action,
+ 0, (t_void *)pioctl_req, MNULL);
+
+ if (ret == MLAN_STATUS_SUCCESS)
+ ret = MLAN_STATUS_PENDING;
+
+ LEAVE();
+ return ret;
+}
+
+/**
+ * @brief deauth sta
+ *
+ * @param pmadapter A pointer to mlan_adapter structure
+ * @param pioctl_req A pointer to ioctl request buffer
+ *
+ * @return MLAN_STATUS_PENDING --success, otherwise fail
+ */
+static mlan_status wlan_uap_bss_ioctl_deauth_sta(pmlan_adapter pmadapter,
+ pmlan_ioctl_req pioctl_req)
+{
+ mlan_status ret = MLAN_STATUS_SUCCESS;
+ pmlan_private pmpriv = pmadapter->priv[pioctl_req->bss_index];
+ mlan_ds_bss *bss = MNULL;
+ const t_u8 bc_mac[] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
+ sta_node *sta_ptr = MNULL;
+
+ ENTER();
+
+ bss = (mlan_ds_bss *)pioctl_req->pbuf;
+ if (pmpriv->uap_host_based & UAP_FLAG_HOST_MLME) {
+ if (memcmp(pmpriv->adapter, bss->param.deauth_param.mac_addr,
+ bc_mac, MLAN_MAC_ADDR_LENGTH)) {
+ sta_ptr = wlan_get_station_entry(
+ pmpriv, bss->param.deauth_param.mac_addr);
+ if (!sta_ptr) {
+ PRINTM(MCMND,
+ "Skip deauth to station " MACSTR "\n",
+ MAC2STR(bss->param.deauth_param
+ .mac_addr));
+ LEAVE();
+ return ret;
+ }
+ }
+ }
+ ret = wlan_prepare_cmd(pmpriv, HOST_CMD_APCMD_STA_DEAUTH,
+ HostCmd_ACT_GEN_SET, 0, (t_void *)pioctl_req,
+ (t_void *)&bss->param.deauth_param);
+ if (ret == MLAN_STATUS_SUCCESS)
+ ret = MLAN_STATUS_PENDING;
+
+ LEAVE();
+ return ret;
+}
+
+/**
+ * @brief Get station list
+ *
+ * @param pmadapter A pointer to mlan_adapter structure
+ * @param pioctl_req A pointer to ioctl request buffer
+ *
+ * @return MLAN_STATUS_PENDING --success, otherwise fail
+ */
+static mlan_status wlan_uap_get_sta_list(pmlan_adapter pmadapter,
+ pmlan_ioctl_req pioctl_req)
+{
+ pmlan_private pmpriv = pmadapter->priv[pioctl_req->bss_index];
+ mlan_status ret = MLAN_STATUS_SUCCESS;
+
+ ENTER();
+
+ /* Send request to firmware */
+ ret = wlan_prepare_cmd(pmpriv, HOST_CMD_APCMD_STA_LIST,
+ HostCmd_ACT_GEN_GET, 0, (t_void *)pioctl_req,
+ MNULL);
+
+ if (ret == MLAN_STATUS_SUCCESS)
+ ret = MLAN_STATUS_PENDING;
+
+ LEAVE();
+ return ret;
+}
+
+/**
+ * @brief soft_reset
+ *
+ * @param pmadapter A pointer to mlan_adapter structure
+ * @param pioctl_req A pointer to ioctl request buffer
+ *
+ * @return MLAN_STATUS_PENDING --success, otherwise fail
+ */
+static mlan_status wlan_uap_misc_ioctl_soft_reset(pmlan_adapter pmadapter,
+ pmlan_ioctl_req pioctl_req)
+{
+ mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index];
+ mlan_status ret = MLAN_STATUS_SUCCESS;
+
+ ENTER();
+
+ ret = wlan_prepare_cmd(pmpriv, HostCmd_CMD_SOFT_RESET,
+ HostCmd_ACT_GEN_SET, 0, (t_void *)pioctl_req,
+ MNULL);
+ if (ret == MLAN_STATUS_SUCCESS)
+ ret = MLAN_STATUS_PENDING;
+
+ LEAVE();
+ return ret;
+}
+
+/**
+ * @brief Tx data pause
+ *
+ * @param pmadapter A pointer to mlan_adapter structure
+ * @param pioctl_req A pointer to ioctl request buffer
+ *
+ * @return MLAN_STATUS_PENDING --success, otherwise fail
+ */
+static mlan_status wlan_uap_misc_ioctl_txdatapause(pmlan_adapter pmadapter,
+ pmlan_ioctl_req pioctl_req)
+{
+ mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index];
+ mlan_ds_misc_cfg *pmisc = (mlan_ds_misc_cfg *)pioctl_req->pbuf;
+ mlan_status ret = MLAN_STATUS_SUCCESS;
+ t_u16 cmd_action = 0;
+
+ ENTER();
+
+ if (pioctl_req->action == MLAN_ACT_SET)
+ cmd_action = HostCmd_ACT_GEN_SET;
+ else
+ cmd_action = HostCmd_ACT_GEN_GET;
+ ret = wlan_prepare_cmd(pmpriv, HostCmd_CMD_CFG_TX_DATA_PAUSE,
+ cmd_action, 0, (t_void *)pioctl_req,
+ &(pmisc->param.tx_datapause));
+ if (ret == MLAN_STATUS_SUCCESS)
+ ret = MLAN_STATUS_PENDING;
+
+ LEAVE();
+ return ret;
+}
+
+/**
+ * @brief Set/Get Power mode
+ *
+ * @param pmadapter A pointer to mlan_adapter structure
+ * @param pioctl_req A pointer to ioctl request buffer
+ *
+ * @return MLAN_STATUS_PENDING --success, otherwise fail
+ */
+static mlan_status wlan_uap_pm_ioctl_mode(pmlan_adapter pmadapter,
+ pmlan_ioctl_req pioctl_req)
+{
+ mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index];
+ mlan_ds_pm_cfg *pm = MNULL;
+ mlan_status ret = MLAN_STATUS_SUCCESS;
+ t_u16 cmd_action = 0;
+ t_u32 cmd_oid = 0;
+
+ ENTER();
+
+ pm = (mlan_ds_pm_cfg *)pioctl_req->pbuf;
+ if (pioctl_req->action == MLAN_ACT_SET) {
+ if (pm->param.ps_mgmt.ps_mode == PS_MODE_INACTIVITY) {
+ cmd_action = EN_AUTO_PS;
+ cmd_oid = BITMAP_UAP_INACT_PS;
+ } else if (pm->param.ps_mgmt.ps_mode == PS_MODE_PERIODIC_DTIM) {
+ cmd_action = EN_AUTO_PS;
+ cmd_oid = BITMAP_UAP_DTIM_PS;
+ } else {
+ cmd_action = DIS_AUTO_PS;
+ cmd_oid = BITMAP_UAP_INACT_PS | BITMAP_UAP_DTIM_PS;
+ }
+ } else {
+ cmd_action = GET_PS;
+ cmd_oid = BITMAP_UAP_INACT_PS | BITMAP_UAP_DTIM_PS;
+ }
+ /* Send request to firmware */
+ ret = wlan_prepare_cmd(pmpriv, HostCmd_CMD_802_11_PS_MODE_ENH,
+ cmd_action, cmd_oid, (t_void *)pioctl_req,
+ (t_void *)&pm->param.ps_mgmt);
+ if ((ret == MLAN_STATUS_SUCCESS) &&
+ (pioctl_req->action == MLAN_ACT_SET) &&
+ (cmd_action == DIS_AUTO_PS)) {
+ ret = wlan_prepare_cmd(pmpriv, HostCmd_CMD_802_11_PS_MODE_ENH,
+ GET_PS, 0, MNULL, MNULL);
+ }
+ if (ret == MLAN_STATUS_SUCCESS)
+ ret = MLAN_STATUS_PENDING;
+
+ LEAVE();
+ return ret;
+}
+
+/**
+ * @brief Set WAPI IE
+ *
+ * @param priv A pointer to mlan_private structure
+ * @param pioctl_req A pointer to ioctl request buffer
+ *
+ * @return MLAN_STATUS_PENDING --success, otherwise fail
+ */
+static mlan_status wlan_uap_set_wapi_ie(mlan_private *priv,
+ pmlan_ioctl_req pioctl_req)
+{
+ mlan_ds_misc_cfg *misc = MNULL;
+ mlan_status ret = MLAN_STATUS_SUCCESS;
+
+ ENTER();
+ misc = (mlan_ds_misc_cfg *)pioctl_req->pbuf;
+ if (misc->param.gen_ie.len) {
+ if (misc->param.gen_ie.len > sizeof(priv->wapi_ie)) {
+ PRINTM(MWARN, "failed to copy WAPI IE, too big\n");
+ pioctl_req->status_code = MLAN_ERROR_INVALID_PARAMETER;
+ LEAVE();
+ return MLAN_STATUS_FAILURE;
+ }
+ memcpy_ext(priv->adapter, priv->wapi_ie,
+ misc->param.gen_ie.ie_data, misc->param.gen_ie.len,
+ sizeof(priv->wapi_ie));
+ priv->wapi_ie_len = misc->param.gen_ie.len;
+ PRINTM(MIOCTL, "Set wapi_ie_len=%d IE=%#x\n", priv->wapi_ie_len,
+ priv->wapi_ie[0]);
+ DBG_HEXDUMP(MCMD_D, "wapi_ie", priv->wapi_ie,
+ priv->wapi_ie_len);
+ if (priv->wapi_ie[0] == WAPI_IE)
+ priv->sec_info.wapi_enabled = MTRUE;
+ } else {
+ memset(priv->adapter, priv->wapi_ie, 0, sizeof(priv->wapi_ie));
+ priv->wapi_ie_len = misc->param.gen_ie.len;
+ PRINTM(MINFO, "Reset wapi_ie_len=%d IE=%#x\n",
+ priv->wapi_ie_len, priv->wapi_ie[0]);
+ priv->sec_info.wapi_enabled = MFALSE;
+ }
+
+ /* Send request to firmware */
+ ret = wlan_prepare_cmd(priv, HOST_CMD_APCMD_SYS_CONFIGURE,
+ HostCmd_ACT_GEN_SET, 0, (t_void *)pioctl_req,
+ MNULL);
+
+ if (ret == MLAN_STATUS_SUCCESS)
+ ret = MLAN_STATUS_PENDING;
+
+ LEAVE();
+ return ret;
+}
+
+/**
+ * @brief Set generic IE
+ *
+ * @param pmadapter A pointer to mlan_adapter structure
+ * @param pioctl_req A pointer to ioctl request buffer
+ *
+ * @return MLAN_STATUS_SUCCESS/MLAN_STATUS_PENDING --success,
+ * otherwise fail
+ */
+static mlan_status wlan_uap_misc_ioctl_gen_ie(pmlan_adapter pmadapter,
+ pmlan_ioctl_req pioctl_req)
+{
+ mlan_status ret = MLAN_STATUS_SUCCESS;
+ mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index];
+ mlan_ds_misc_cfg *misc = MNULL;
+ IEEEtypes_VendorHeader_t *pvendor_ie = MNULL;
+
+ ENTER();
+
+ misc = (mlan_ds_misc_cfg *)pioctl_req->pbuf;
+
+ if ((misc->param.gen_ie.type == MLAN_IE_TYPE_GEN_IE) &&
+ (pioctl_req->action == MLAN_ACT_SET)) {
+ if (misc->param.gen_ie.len) {
+ pvendor_ie = (IEEEtypes_VendorHeader_t *)
+ misc->param.gen_ie.ie_data;
+ if (pvendor_ie->element_id == WAPI_IE) {
+ /* IE is a WAPI IE so call set_wapi function */
+ ret = wlan_uap_set_wapi_ie(pmpriv, pioctl_req);
+ }
+ } else {
+ /* clear WAPI IE */
+ ret = wlan_uap_set_wapi_ie(pmpriv, pioctl_req);
+ }
+ }
+ LEAVE();
+ return ret;
+}
+
+/**
+ * @brief Set/Get WAPI status
+ *
+ * @param pmadapter A pointer to mlan_adapter structure
+ * @param pioctl_req A pointer to ioctl request buffer
+ *
+ * @return MLAN_STATUS_SUCCESS --success
+ */
+static mlan_status wlan_uap_sec_ioctl_wapi_enable(pmlan_adapter pmadapter,
+ pmlan_ioctl_req pioctl_req)
+{
+ mlan_status ret = MLAN_STATUS_SUCCESS;
+ mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index];
+ mlan_ds_sec_cfg *sec = MNULL;
+ ENTER();
+ sec = (mlan_ds_sec_cfg *)pioctl_req->pbuf;
+ if (pioctl_req->action == MLAN_ACT_GET) {
+ if (pmpriv->wapi_ie_len)
+ sec->param.wapi_enabled = MTRUE;
+ else
+ sec->param.wapi_enabled = MFALSE;
+ } else {
+ if (sec->param.wapi_enabled == MFALSE) {
+ memset(pmpriv->adapter, pmpriv->wapi_ie, 0,
+ sizeof(pmpriv->wapi_ie));
+ pmpriv->wapi_ie_len = 0;
+ PRINTM(MINFO, "Reset wapi_ie_len=%d IE=%#x\n",
+ pmpriv->wapi_ie_len, pmpriv->wapi_ie[0]);
+ pmpriv->sec_info.wapi_enabled = MFALSE;
+ }
+ }
+ pioctl_req->data_read_written = sizeof(t_u32) + MLAN_SUB_COMMAND_SIZE;
+ LEAVE();
+ return ret;
+}
+
+/**
+ * @brief report mic error
+ *
+ * @param pmadapter A pointer to mlan_adapter structure
+ * @param pioctl_req A pointer to ioctl request buffer
+ *
+ * @return MLAN_STATUS_PENDING --success, otherwise fail
+ */
+static mlan_status
+wlan_uap_sec_ioctl_report_mic_error(pmlan_adapter pmadapter,
+ pmlan_ioctl_req pioctl_req)
+{
+ mlan_status ret = MLAN_STATUS_SUCCESS;
+ pmlan_private pmpriv = pmadapter->priv[pioctl_req->bss_index];
+ mlan_ds_sec_cfg *sec = MNULL;
+
+ ENTER();
+
+ sec = (mlan_ds_sec_cfg *)pioctl_req->pbuf;
+ ret = wlan_prepare_cmd(pmpriv, HOST_CMD_APCMD_REPORT_MIC,
+ HostCmd_ACT_GEN_SET, 0, (t_void *)pioctl_req,
+ (t_void *)sec->param.sta_mac);
+ if (ret == MLAN_STATUS_SUCCESS)
+ ret = MLAN_STATUS_PENDING;
+
+ LEAVE();
+ return ret;
+}
+
+/**
+ * @brief Set encrypt key
+ *
+ * @param pmadapter A pointer to mlan_adapter structure
+ * @param pioctl_req A pointer to ioctl request buffer
+ *
+ * @return MLAN_STATUS_SUCCESS/MLAN_STATUS_PENDING --success,
+ * otherwise fail
+ */
+static mlan_status
+wlan_uap_sec_ioctl_set_encrypt_key(pmlan_adapter pmadapter,
+ pmlan_ioctl_req pioctl_req)
+{
+ mlan_status ret = MLAN_STATUS_SUCCESS;
+ mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index];
+ mlan_ds_sec_cfg *sec = MNULL;
+
+ ENTER();
+ sec = (mlan_ds_sec_cfg *)pioctl_req->pbuf;
+ if (pioctl_req->action != MLAN_ACT_SET) {
+ pioctl_req->status_code = MLAN_ERROR_IOCTL_INVALID;
+ LEAVE();
+ return MLAN_STATUS_FAILURE;
+ }
+ if (!sec->param.encrypt_key.key_remove &&
+ !sec->param.encrypt_key.key_len) {
+ PRINTM(MCMND, "Skip set key with key_len = 0\n");
+ LEAVE();
+ return ret;
+ }
+ ret = wlan_prepare_cmd(pmpriv, HostCmd_CMD_802_11_KEY_MATERIAL,
+ HostCmd_ACT_GEN_SET, KEY_INFO_ENABLED,
+ (t_void *)pioctl_req, &sec->param.encrypt_key);
+
+ if (ret == MLAN_STATUS_SUCCESS)
+ ret = MLAN_STATUS_PENDING;
+ LEAVE();
+ return ret;
+}
+
+/**
+ * @brief Get BSS information
+ *
+ * @param pmadapter A pointer to mlan_adapter structure
+ * @param pioctl_req A pointer to ioctl request buffer
+ *
+ * @return MLAN_STATUS_SUCCESS --success
+ */
+static mlan_status wlan_uap_get_bss_info(pmlan_adapter pmadapter,
+ pmlan_ioctl_req pioctl_req)
+{
+ pmlan_private pmpriv = pmadapter->priv[pioctl_req->bss_index];
+ mlan_status ret = MLAN_STATUS_SUCCESS;
+ mlan_ds_get_info *info;
+
+ ENTER();
+
+ info = (mlan_ds_get_info *)pioctl_req->pbuf;
+ /* Connection status */
+ info->param.bss_info.media_connected = pmpriv->media_connected;
+
+ /* Radio status */
+ info->param.bss_info.radio_on = pmadapter->radio_on;
+
+ /* BSSID */
+ memcpy_ext(pmadapter, &info->param.bss_info.bssid, pmpriv->curr_addr,
+ MLAN_MAC_ADDR_LENGTH, MLAN_MAC_ADDR_LENGTH);
+ info->param.bss_info.scan_block = pmadapter->scan_block;
+
+ info->param.bss_info.is_hs_configured = pmadapter->is_hs_configured;
+ info->param.bss_info.is_11h_active =
+ pmpriv->intf_state_11h.is_11h_active;
+ info->param.bss_info.dfs_check_channel =
+ pmpriv->adapter->state_dfs.dfs_check_channel;
+ pioctl_req->data_read_written =
+ sizeof(mlan_bss_info) + MLAN_SUB_COMMAND_SIZE;
+
+ LEAVE();
+ return ret;
+}
+
+/**
+ * @brief Set Host Sleep configurations
+ *
+ * @param pmadapter A pointer to mlan_adapter structure
+ * @param pioctl_req A pointer to ioctl request buffer
+ *
+ * @return MLAN_STATUS_SUCCES/MLAN_STATUS_PENDING --success,
+ * otherwise fail
+ */
+static mlan_status wlan_uap_pm_ioctl_deepsleep(pmlan_adapter pmadapter,
+ pmlan_ioctl_req pioctl_req)
+{
+ mlan_status ret = MLAN_STATUS_SUCCESS;
+ mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index];
+ mlan_ds_pm_cfg *pm = MNULL;
+ mlan_ds_auto_ds auto_ds;
+ t_u32 mode;
+
+ ENTER();
+
+ if (pioctl_req->buf_len < sizeof(mlan_ds_pm_cfg)) {
+ PRINTM(MWARN, "MLAN bss IOCTL length is too short.\n");
+ pioctl_req->data_read_written = 0;
+ pioctl_req->buf_len_needed = sizeof(mlan_ds_pm_cfg);
+ pioctl_req->status_code = MLAN_ERROR_INVALID_PARAMETER;
+ LEAVE();
+ return MLAN_STATUS_RESOURCE;
+ }
+ pm = (mlan_ds_pm_cfg *)pioctl_req->pbuf;
+
+ if (pioctl_req->action == MLAN_ACT_GET) {
+ if (pmadapter->is_deep_sleep) {
+ pm->param.auto_deep_sleep.auto_ds = DEEP_SLEEP_ON;
+ pm->param.auto_deep_sleep.idletime =
+ pmadapter->idle_time;
+ } else
+ pm->param.auto_deep_sleep.auto_ds = DEEP_SLEEP_OFF;
+ } else {
+ if (pmadapter->is_deep_sleep &&
+ pm->param.auto_deep_sleep.auto_ds == DEEP_SLEEP_ON) {
+ PRINTM(MMSG, "uAP already in deep sleep mode\n");
+ LEAVE();
+ return MLAN_STATUS_FAILURE;
+ }
+ if (((mlan_ds_pm_cfg *)pioctl_req->pbuf)
+ ->param.auto_deep_sleep.auto_ds == DEEP_SLEEP_ON) {
+ auto_ds.auto_ds = DEEP_SLEEP_ON;
+ mode = EN_AUTO_PS;
+ PRINTM(MINFO, "Auto Deep Sleep: on\n");
+ } else {
+ mode = DIS_AUTO_PS;
+ auto_ds.auto_ds = DEEP_SLEEP_OFF;
+ PRINTM(MINFO, "Auto Deep Sleep: off\n");
+ }
+ if (((mlan_ds_pm_cfg *)pioctl_req->pbuf)
+ ->param.auto_deep_sleep.idletime)
+ auto_ds.idletime =
+ ((mlan_ds_pm_cfg *)pioctl_req->pbuf)
+ ->param.auto_deep_sleep.idletime;
+ else
+ auto_ds.idletime = pmadapter->idle_time;
+ ret = wlan_prepare_cmd(pmpriv, HostCmd_CMD_802_11_PS_MODE_ENH,
+ (t_u16)mode, BITMAP_AUTO_DS,
+ (t_void *)pioctl_req, &auto_ds);
+ if (ret == MLAN_STATUS_SUCCESS)
+ ret = MLAN_STATUS_PENDING;
+ }
+ LEAVE();
+ return ret;
+}
+
+/**
+ * @brief Set Band Steering configurations
+ *
+ * @param pmadapter A pointer to mlan_adapter structure
+ * @param pioctl_req A pointer to ioctl request buffer
+ *
+ * @return MLAN_STATUS_SUCCES/MLAN_STATUS_PENDING --success,
+ * otherwise fail
+ */
+static mlan_status wlan_misc_band_steering_cfg(pmlan_adapter pmadapter,
+ pmlan_ioctl_req pioctl_req)
+{
+ mlan_status ret = MLAN_STATUS_SUCCESS;
+ mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index];
+ mlan_ds_misc_cfg *pm = MNULL;
+
+ ENTER();
+
+ if (pioctl_req->buf_len < sizeof(mlan_ds_band_steer_cfg)) {
+ PRINTM(MWARN, "MLAN bss IOCTL length is too short.\n");
+ pioctl_req->data_read_written = 0;
+ pioctl_req->buf_len_needed = sizeof(mlan_ds_band_steer_cfg);
+ pioctl_req->status_code = MLAN_ERROR_INVALID_PARAMETER;
+ LEAVE();
+ return MLAN_STATUS_RESOURCE;
+ }
+ pm = (mlan_ds_misc_cfg *)pioctl_req->pbuf;
+
+ ret = wlan_prepare_cmd(pmpriv, HostCmd_CMD_802_11_BAND_STEERING,
+ (t_u16)pm->param.band_steer_cfg.action, 0,
+ (t_void *)pioctl_req,
+ (t_void *)&pm->param.band_steer_cfg);
+ LEAVE();
+ if (ret == MLAN_STATUS_SUCCESS)
+ ret = MLAN_STATUS_PENDING;
+ return ret;
+}
+
+/**
+ * @brief Set Beacon Stuck Detect Mechanism Configurations
+ *
+ * @param pmadapter A pointer to mlan_adapter structure
+ * @param pioctl_req A pointer to ioctl request buffer
+ *
+ * @return MLAN_STATUS_SUCCES/MLAN_STATUS_PENDING --success,
+ * otherwise fail
+ */
+static mlan_status wlan_misc_beacon_stuck_cfg(IN pmlan_adapter pmadapter,
+ IN pmlan_ioctl_req pioctl_req)
+{
+ mlan_status ret = MLAN_STATUS_SUCCESS;
+ mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index];
+ mlan_ds_misc_cfg *pm = MNULL;
+
+ ENTER();
+
+ if (pioctl_req->buf_len < sizeof(mlan_ds_beacon_stuck_param_cfg)) {
+ PRINTM(MWARN, "MLAN bss IOCTL length is too short.\n");
+ pioctl_req->data_read_written = 0;
+ pioctl_req->buf_len_needed =
+ sizeof(mlan_ds_beacon_stuck_param_cfg);
+ pioctl_req->status_code = MLAN_ERROR_INVALID_PARAMETER;
+ LEAVE();
+ return MLAN_STATUS_RESOURCE;
+ }
+ pm = (mlan_ds_misc_cfg *)pioctl_req->pbuf;
+
+ ret = wlan_prepare_cmd(pmpriv, HostCmd_CMD_UAP_BEACON_STUCK_CFG,
+ (t_u16)pm->param.beacon_stuck_cfg.action, 0,
+ (t_void *)pioctl_req,
+ (t_void *)&pm->param.beacon_stuck_cfg);
+
+ LEAVE();
+
+ if (ret == MLAN_STATUS_SUCCESS)
+ ret = MLAN_STATUS_PENDING;
+
+ return ret;
+}
+
+/**
+ * @brief Set SNMP MIB for 11D
+ *
+ * @param pmadapter A pointer to mlan_adapter structure
+ * @param pioctl_req A pointer to ioctl request buffer
+ *
+ * @return MLAN_STATUS_PENDING --success, otherwise fail
+ */
+static mlan_status wlan_uap_snmp_mib_11d(pmlan_adapter pmadapter,
+ pmlan_ioctl_req pioctl_req)
+{
+ mlan_status ret = MLAN_STATUS_SUCCESS;
+ mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index];
+ mlan_ds_snmp_mib *snmp = MNULL;
+ state_11d_t flag;
+
+ ENTER();
+
+ if (pioctl_req->buf_len < sizeof(mlan_ds_snmp_mib)) {
+ PRINTM(MWARN, "MLAN snmp_mib IOCTL length is too short.\n");
+ pioctl_req->data_read_written = 0;
+ pioctl_req->buf_len_needed = sizeof(mlan_ds_snmp_mib);
+ LEAVE();
+ return MLAN_STATUS_RESOURCE;
+ }
+
+ if ((pioctl_req->action == MLAN_ACT_SET) && pmpriv->uap_bss_started) {
+ PRINTM(MIOCTL,
+ "11D setting cannot be changed while UAP bss is started.\n");
+ pioctl_req->data_read_written = 0;
+ LEAVE();
+ return MLAN_STATUS_FAILURE;
+ }
+
+ snmp = (mlan_ds_snmp_mib *)pioctl_req->pbuf;
+ flag = (snmp->param.oid_value) ? ENABLE_11D : DISABLE_11D;
+
+ ret = wlan_11d_enable(pmpriv, (t_void *)pioctl_req, flag);
+ if (ret == MLAN_STATUS_SUCCESS)
+ ret = MLAN_STATUS_PENDING;
+
+ LEAVE();
+ return ret;
+}
+
+/**
+ * @brief Callback to finish domain_info handling
+ * Not to be called directly to initiate domain_info setting.
+ *
+ * @param pmpriv A pointer to mlan_private structure (cast from t_void*)
+ *
+ * @return MLAN_STATUS_PENDING --success, otherwise fail
+ * @sa wlan_uap_domain_info
+ */
+static mlan_status wlan_uap_callback_domain_info(t_void *priv)
+{
+ mlan_status ret = MLAN_STATUS_SUCCESS;
+ mlan_private *pmpriv = (mlan_private *)priv;
+ wlan_uap_get_info_cb_t *puap_state_chan_cb = &pmpriv->uap_state_chan_cb;
+ mlan_ds_11d_cfg *cfg11d;
+ t_u8 band;
+ pmlan_adapter pmadapter = pmpriv->adapter;
+ pmlan_callbacks pcb = &pmadapter->callbacks;
+
+ ENTER();
+ /* clear callback now that we're here */
+ puap_state_chan_cb->get_chan_callback = MNULL;
+
+ if (!puap_state_chan_cb->pioctl_req_curr) {
+ PRINTM(MERROR, "pioctl_req_curr is null\n");
+ LEAVE();
+ return ret;
+ }
+ cfg11d = (mlan_ds_11d_cfg *)puap_state_chan_cb->pioctl_req_curr->pbuf;
+ band = (puap_state_chan_cb->bandcfg.chanBand == BAND_5GHZ) ? BAND_A :
+ BAND_B;
+
+ ret = wlan_11d_handle_uap_domain_info(
+ pmpriv, band, cfg11d->param.domain_tlv,
+ puap_state_chan_cb->pioctl_req_curr);
+ if (ret == MLAN_STATUS_SUCCESS)
+ ret = MLAN_STATUS_PENDING;
+ else {
+ puap_state_chan_cb->pioctl_req_curr->status_code =
+ MLAN_STATUS_FAILURE;
+ pcb->moal_ioctl_complete(pmadapter->pmoal_handle,
+ puap_state_chan_cb->pioctl_req_curr,
+ MLAN_STATUS_FAILURE);
+ }
+
+ puap_state_chan_cb->pioctl_req_curr = MNULL; /* prevent re-use */
+ LEAVE();
+ return ret;
+}
+
+/**
+ * @brief Set Domain Info for 11D
+ *
+ * @param pmadapter A pointer to mlan_adapter structure
+ * @param pioctl_req A pointer to ioctl request buffer
+ *
+ * @return MLAN_STATUS_PENDING --success, otherwise fail
+ * @sa wlan_uap_callback_domain_info
+ */
+static mlan_status wlan_uap_domain_info(pmlan_adapter pmadapter,
+ pmlan_ioctl_req pioctl_req)
+{
+ mlan_status ret = MLAN_STATUS_SUCCESS;
+ mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index];
+
+ ENTER();
+
+ if (pioctl_req->buf_len < sizeof(mlan_ds_11d_cfg)) {
+ PRINTM(MWARN, "MLAN 11d_cfg IOCTL length is too short.\n");
+ pioctl_req->data_read_written = 0;
+ pioctl_req->buf_len_needed = sizeof(mlan_ds_11d_cfg);
+ LEAVE();
+ return MLAN_STATUS_RESOURCE;
+ }
+
+ if ((pioctl_req->action == MLAN_ACT_SET) && pmpriv->uap_bss_started) {
+ PRINTM(MIOCTL,
+ "Domain_info cannot be changed while UAP bss is started.\n");
+ pioctl_req->data_read_written = 0;
+ LEAVE();
+ return MLAN_STATUS_FAILURE;
+ }
+
+ /* store params, issue command to get UAP channel, whose CMD_RESP will
+ * callback remainder of domain_info handling */
+ pmpriv->uap_state_chan_cb.pioctl_req_curr = pioctl_req;
+ pmpriv->uap_state_chan_cb.get_chan_callback =
+ wlan_uap_callback_domain_info;
+
+ ret = wlan_uap_get_channel(pmpriv);
+ if (ret == MLAN_STATUS_SUCCESS)
+ ret = MLAN_STATUS_PENDING;
+
+ LEAVE();
+ return ret;
+}
+
+/**
+ * @brief Callback to finish 11H channel check handling.
+ * Not to be called directly to initiate channel check.
+ *
+ * @param priv A pointer to mlan_private structure (cast from t_void*)
+ *
+ * @return MLAN_STATUS_SUCCESS/PENDING --success, otherwise fail
+ * @sa wlan_uap_11h_channel_check_req
+ */
+static mlan_status wlan_uap_callback_11h_channel_check_req(t_void *priv)
+{
+ mlan_status ret = MLAN_STATUS_FAILURE;
+ mlan_private *pmpriv = (mlan_private *)priv;
+ mlan_callbacks *pcb = (mlan_callbacks *)&pmpriv->adapter->callbacks;
+ wlan_uap_get_info_cb_t *puap_state_chan_cb = &pmpriv->uap_state_chan_cb;
+ Band_Config_t *pband_cfg = &puap_state_chan_cb->bandcfg;
+ /* keep copy as local variable */
+ pmlan_ioctl_req pioctl = puap_state_chan_cb->pioctl_req_curr;
+ ENTER();
+ /* clear callback now that we're here */
+ puap_state_chan_cb->get_chan_callback = MNULL;
+ /* clear early to avoid race condition */
+ puap_state_chan_cb->pioctl_req_curr = MNULL;
+
+ /*
+ * Check if the region and channel requires a channel availability
+ * check.
+ */
+ if ((puap_state_chan_cb->bandcfg.chanBand == BAND_5GHZ) &&
+ !wlan_can_radar_det_skip(pmpriv) &&
+ wlan_11h_radar_detect_required(pmpriv,
+ puap_state_chan_cb->channel) &&
+ !wlan_11h_is_channel_under_nop(pmpriv->adapter,
+ puap_state_chan_cb->channel)) {
+ /*
+ * Radar detection is required for this channel, make sure
+ * 11h is activated in the firmware
+ */
+ ret = wlan_11h_activate(pmpriv, MNULL, MTRUE);
+ ret = wlan_11h_config_master_radar_det(pmpriv, MTRUE);
+ ret = wlan_11h_check_update_radar_det_state(pmpriv);
+
+ /* Check for radar on the channel */
+ ret = wlan_11h_issue_radar_detect(pmpriv, pioctl,
+ puap_state_chan_cb->channel,
+ *pband_cfg);
+ if (ret == MLAN_STATUS_SUCCESS)
+ ret = MLAN_STATUS_PENDING;
+ } else {
+ /* No command sent with the ioctl, need manually signal
+ * completion */
+ pcb->moal_ioctl_complete(pmpriv->adapter->pmoal_handle, pioctl,
+ MLAN_STATUS_COMPLETE);
+ }
+
+ LEAVE();
+ return ret;
+}
+
+/**
+ * @brief 802.11h uap start channel check
+ *
+ * @param pmadapter A pointer to mlan_adapter structure
+ * @param pioctl_req A pointer to ioctl request buffer
+ *
+ * @return MLAN_STATUS_PENDING --success, otherwise fail
+ * @sa wlan_uap_callback_11h_channel_check_req
+ */
+static mlan_status wlan_uap_11h_channel_check_req(pmlan_adapter pmadapter,
+ pmlan_ioctl_req pioctl_req)
+{
+ mlan_status ret = MLAN_STATUS_SUCCESS;
+ mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index];
+ mlan_ds_11h_cfg *p11h_cfg;
+
+ ENTER();
+
+ if (pioctl_req->buf_len < sizeof(mlan_ds_11h_cfg)) {
+ PRINTM(MWARN, "MLAN 11h_cfg IOCTL length is too short.\n");
+ pioctl_req->data_read_written = 0;
+ pioctl_req->buf_len_needed = sizeof(mlan_ds_11h_cfg);
+ LEAVE();
+ return MLAN_STATUS_RESOURCE;
+ }
+ p11h_cfg = (mlan_ds_11h_cfg *)pioctl_req->pbuf;
+ pmpriv->intf_state_11h.is_11h_host =
+ p11h_cfg->param.chan_rpt_req.host_based;
+
+ if (!pmpriv->intf_state_11h.is_11h_host) {
+ /* store params, issue command to get UAP channel, whose
+ * CMD_RESP will callback remainder of 11H channel check
+ * handling */
+ pmpriv->uap_state_chan_cb.pioctl_req_curr = pioctl_req;
+ pmpriv->uap_state_chan_cb.get_chan_callback =
+ wlan_uap_callback_11h_channel_check_req;
+
+ ret = wlan_uap_get_channel(pmpriv);
+ if (ret == MLAN_STATUS_SUCCESS)
+ ret = MLAN_STATUS_PENDING;
+ } else {
+ if (!wlan_11h_is_active(pmpriv)) {
+ /* active 11h extention in Fw */
+ ret = wlan_11h_activate(pmpriv, MNULL, MTRUE);
+ ret = wlan_11h_config_master_radar_det(pmpriv, MTRUE);
+ ret = wlan_11h_check_update_radar_det_state(pmpriv);
+ }
+ if (p11h_cfg->param.chan_rpt_req.millisec_dwell_time) {
+ if (pmpriv->adapter->dfs_test_params
+ .user_cac_period_msec) {
+ PRINTM(MCMD_D,
+ "cfg80211 dfs_testing - user CAC period=%d (msec)\n",
+ pmpriv->adapter->dfs_test_params
+ .user_cac_period_msec);
+ p11h_cfg->param.chan_rpt_req
+ .millisec_dwell_time =
+ pmpriv->adapter->dfs_test_params
+ .user_cac_period_msec;
+ }
+ ret = wlan_prepare_cmd(
+ pmpriv, HostCmd_CMD_CHAN_REPORT_REQUEST,
+ HostCmd_ACT_GEN_SET, 0, (t_void *)pioctl_req,
+ (t_void *)&p11h_cfg->param.chan_rpt_req);
+
+ if (ret == MLAN_STATUS_SUCCESS)
+ ret = MLAN_STATUS_PENDING;
+ }
+ }
+
+ LEAVE();
+ return ret;
+}
+
+/**
+ * @brief Callback to finish 11H handling
+ * Not to be called directly to initiate 11H setting.
+ *
+ * @param pmpriv A pointer to mlan_private structure (cast from t_void*)
+ *
+ * @return MLAN_STATUS_PENDING --success, otherwise fail
+ * @sa wlan_uap_snmp_mib_11h
+ */
+static mlan_status wlan_uap_callback_snmp_mib_11h(t_void *priv)
+{
+ mlan_status ret = MLAN_STATUS_SUCCESS;
+ mlan_private *pmpriv = (mlan_private *)priv;
+ wlan_uap_get_info_cb_t *puap_state_chan_cb = &pmpriv->uap_state_chan_cb;
+ mlan_callbacks *pcb = (mlan_callbacks *)&pmpriv->adapter->callbacks;
+ mlan_ds_snmp_mib *snmp;
+ t_bool enable_11h;
+
+ ENTER();
+ /* clear callback now that we're here */
+ puap_state_chan_cb->get_chan_callback = MNULL;
+
+ snmp = (mlan_ds_snmp_mib *)puap_state_chan_cb->pioctl_req_curr->pbuf;
+ enable_11h = (snmp->param.oid_value) ? MTRUE : MFALSE;
+
+ if (enable_11h) {
+ if ((puap_state_chan_cb->bandcfg.chanBand == BAND_5GHZ) &&
+ !wlan_can_radar_det_skip(pmpriv) &&
+ wlan_11h_radar_detect_required(
+ pmpriv, puap_state_chan_cb->channel)) {
+ if (!wlan_11h_is_master_radar_det_active(pmpriv))
+ wlan_11h_config_master_radar_det(pmpriv, MTRUE);
+ } else {
+ puap_state_chan_cb->pioctl_req_curr->status_code =
+ MLAN_STATUS_SUCCESS;
+ pcb->moal_ioctl_complete(
+ pmpriv->adapter->pmoal_handle,
+ puap_state_chan_cb->pioctl_req_curr,
+ MLAN_STATUS_SUCCESS);
+ goto done;
+ }
+ }
+
+ ret = wlan_11h_activate(pmpriv,
+ (t_void *)puap_state_chan_cb->pioctl_req_curr,
+ enable_11h);
+ wlan_11h_check_update_radar_det_state(pmpriv);
+ if (ret == MLAN_STATUS_SUCCESS)
+ ret = MLAN_STATUS_PENDING;
+done:
+ puap_state_chan_cb->pioctl_req_curr = MNULL; /* prevent re-use */
+ LEAVE();
+ return ret;
+}
+
+/**
+ * @brief Set SNMP MIB for 11H
+ *
+ * @param pmadapter A pointer to mlan_adapter structure
+ * @param pioctl_req A pointer to ioctl request buffer
+ *
+ * @return MLAN_STATUS_PENDING --success, otherwise fail
+ * @sa wlan_uap_callback_snmp_mib_11h
+ */
+static mlan_status wlan_uap_snmp_mib_11h(pmlan_adapter pmadapter,
+ pmlan_ioctl_req pioctl_req)
+{
+ mlan_status ret = MLAN_STATUS_SUCCESS;
+ mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index];
+ mlan_ds_snmp_mib *snmp = MNULL;
+ t_bool enable;
+
+ ENTER();
+
+ if (pioctl_req->buf_len < sizeof(mlan_ds_snmp_mib)) {
+ PRINTM(MWARN, "MLAN snmp_mib IOCTL length is too short.\n");
+ pioctl_req->data_read_written = 0;
+ pioctl_req->buf_len_needed = sizeof(mlan_ds_snmp_mib);
+ LEAVE();
+ return MLAN_STATUS_RESOURCE;
+ }
+ snmp = (mlan_ds_snmp_mib *)pioctl_req->pbuf;
+ enable = (snmp->param.oid_value) ? MTRUE : MFALSE;
+
+ if (enable) {
+ /* first enable 11D if it is not enabled */
+ if (!wlan_fw_11d_is_enabled(pmpriv)) {
+ ret = wlan_11d_enable(pmpriv, MNULL, ENABLE_11D);
+ if (ret != MLAN_STATUS_SUCCESS) {
+ PRINTM(MERROR,
+ "Failed to first enable 11D before enabling 11H.\n");
+ LEAVE();
+ return ret;
+ }
+ }
+ }
+
+ /* store params, issue command to get UAP channel, whose CMD_RESP will
+ * callback remainder of 11H handling (and radar detect if DFS chan) */
+ pmpriv->uap_state_chan_cb.pioctl_req_curr = pioctl_req;
+ pmpriv->uap_state_chan_cb.get_chan_callback =
+ wlan_uap_callback_snmp_mib_11h;
+
+ ret = wlan_uap_get_channel(pmpriv);
+ if (ret == MLAN_STATUS_SUCCESS)
+ ret = MLAN_STATUS_PENDING;
+
+ LEAVE();
+ return ret;
+}
+
+/**
+ * @brief ACS scan
+ *
+ * @param pmadapter A pointer to mlan_adapter structure
+ * @param pioctl_req A pointer to ioctl request buffer
+ *
+ * @return MLAN_STATUS_PENDING --success, otherwise fail
+ */
+static mlan_status wlan_uap_bss_ioctl_acs_scan(pmlan_adapter pmadapter,
+ pmlan_ioctl_req pioctl_req)
+{
+ mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index];
+ mlan_status ret = MLAN_STATUS_SUCCESS;
+
+ ENTER();
+ if (pmadapter->uap_fw_ver < UAP_FW_VERSION_2) {
+ PRINTM(MIOCTL, "FW don't support ACS SCAN API\n");
+ return MLAN_STATUS_FAILURE;
+ }
+ /* Send request to firmware */
+ ret = wlan_prepare_cmd(pmpriv, HostCMD_APCMD_ACS_SCAN,
+ HostCmd_ACT_GEN_SET, 0, (t_void *)pioctl_req,
+ MNULL);
+
+ if (ret == MLAN_STATUS_SUCCESS)
+ ret = MLAN_STATUS_PENDING;
+
+ LEAVE();
+ return ret;
+}
+
+/********************************************************
+ Global Functions
+********************************************************/
+
+/**
+ * @brief Issue CMD to UAP firmware to get current channel
+ *
+ * @param pmpriv A pointer to mlan_private structure
+ *
+ * @return MLAN_STATUS_SUCCESS --success, otherwise fail
+ */
+mlan_status wlan_uap_get_channel(pmlan_private pmpriv)
+{
+ MrvlIEtypes_channel_band_t tlv_chan_band;
+ mlan_status ret = MLAN_STATUS_SUCCESS;
+
+ ENTER();
+ memset(pmpriv->adapter, &tlv_chan_band, 0, sizeof(tlv_chan_band));
+ tlv_chan_band.header.type = TLV_TYPE_UAP_CHAN_BAND_CONFIG;
+ tlv_chan_band.header.len = sizeof(MrvlIEtypes_channel_band_t) -
+ sizeof(MrvlIEtypesHeader_t);
+
+ ret = wlan_prepare_cmd(pmpriv, HOST_CMD_APCMD_SYS_CONFIGURE,
+ HostCmd_ACT_GEN_GET, 0, MNULL, &tlv_chan_band);
+ LEAVE();
+ return ret;
+}
+
+/**
+ * @brief Issue CMD to UAP firmware to set current channel
+ *
+ * @param pmpriv A pointer to mlan_private structure
+ * @param uap_band_cfg UAP band configuration
+ * @param channel New channel
+ *
+ * @return MLAN_STATUS_SUCCESS --success, otherwise fail
+ */
+mlan_status wlan_uap_set_channel(pmlan_private pmpriv,
+ Band_Config_t uap_band_cfg, t_u8 channel)
+{
+ MrvlIEtypes_channel_band_t tlv_chan_band;
+ mlan_status ret = MLAN_STATUS_SUCCESS;
+
+ ENTER();
+ memset(pmpriv->adapter, &tlv_chan_band, 0, sizeof(tlv_chan_band));
+ tlv_chan_band.header.type = TLV_TYPE_UAP_CHAN_BAND_CONFIG;
+ tlv_chan_band.header.len = sizeof(MrvlIEtypes_channel_band_t) -
+ sizeof(MrvlIEtypesHeader_t);
+ tlv_chan_band.bandcfg = uap_band_cfg;
+ tlv_chan_band.channel = channel;
+
+ ret = wlan_prepare_cmd(pmpriv, HOST_CMD_APCMD_SYS_CONFIGURE,
+ HostCmd_ACT_GEN_SET, 0, MNULL, &tlv_chan_band);
+ LEAVE();
+ return ret;
+}
+
+/**
+ * @brief Issue CMD to UAP firmware to get current beacon and dtim periods
+ *
+ * @param pmpriv A pointer to mlan_private structure
+ *
+ * @return MLAN_STATUS_SUCCESS --success, otherwise fail
+ */
+mlan_status wlan_uap_get_beacon_dtim(pmlan_private pmpriv)
+{
+ t_u8 tlv_buffer[sizeof(MrvlIEtypes_beacon_period_t) +
+ sizeof(MrvlIEtypes_dtim_period_t)];
+ MrvlIEtypes_beacon_period_t *ptlv_beacon_pd;
+ MrvlIEtypes_dtim_period_t *ptlv_dtim_pd;
+ mlan_status ret = MLAN_STATUS_SUCCESS;
+
+ ENTER();
+
+ memset(pmpriv->adapter, &tlv_buffer, 0, sizeof(tlv_buffer));
+ ptlv_beacon_pd = (MrvlIEtypes_beacon_period_t *)tlv_buffer;
+ ptlv_beacon_pd->header.type = TLV_TYPE_UAP_BEACON_PERIOD;
+ ptlv_beacon_pd->header.len = sizeof(MrvlIEtypes_beacon_period_t) -
+ sizeof(MrvlIEtypesHeader_t);
+
+ ptlv_dtim_pd =
+ (MrvlIEtypes_dtim_period_t
+ *)(tlv_buffer + sizeof(MrvlIEtypes_beacon_period_t));
+ ptlv_dtim_pd->header.type = TLV_TYPE_UAP_DTIM_PERIOD;
+ ptlv_dtim_pd->header.len =
+ sizeof(MrvlIEtypes_dtim_period_t) - sizeof(MrvlIEtypesHeader_t);
+
+ ret = wlan_prepare_cmd(pmpriv, HOST_CMD_APCMD_SYS_CONFIGURE,
+ HostCmd_ACT_GEN_GET, 0, MNULL, tlv_buffer);
+ LEAVE();
+ return ret;
+}
+
+/**
+ * @brief Set/Get deauth control.
+ *
+ * @param pmadapter A pointer to mlan_adapter structure
+ * @param pioctl_req A pointer to ioctl request buffer
+ *
+ * @return MLAN_STATUS_PENDING --success, otherwise fail
+ */
+mlan_status wlan_uap_snmp_mib_ctrl_deauth(pmlan_adapter pmadapter,
+ pmlan_ioctl_req pioctl_req)
+{
+ mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index];
+ mlan_status ret = MLAN_STATUS_SUCCESS;
+ mlan_ds_snmp_mib *mib = (mlan_ds_snmp_mib *)pioctl_req->pbuf;
+ t_u16 cmd_action = 0;
+
+ ENTER();
+
+ mib = (mlan_ds_snmp_mib *)pioctl_req->pbuf;
+ if (pioctl_req->action == MLAN_ACT_SET) {
+ cmd_action = HostCmd_ACT_GEN_SET;
+ } else {
+ cmd_action = HostCmd_ACT_GEN_GET;
+ }
+
+ /* Send command to firmware */
+ ret = wlan_prepare_cmd(pmpriv, HostCmd_CMD_802_11_SNMP_MIB, cmd_action,
+ StopDeauth_i, (t_void *)pioctl_req,
+ &mib->param.deauthctrl);
+
+ if (ret == MLAN_STATUS_SUCCESS)
+ ret = MLAN_STATUS_PENDING;
+
+ LEAVE();
+ return ret;
+}
+
+/**
+ * @brief MLAN uap ioctl handler
+ *
+ * @param adapter A pointer to mlan_adapter structure
+ * @param pioctl_req A pointer to ioctl request buffer
+ *
+ * @return MLAN_STATUS_SUCCESS --success, otherwise fail
+ */
+mlan_status wlan_ops_uap_ioctl(t_void *adapter, pmlan_ioctl_req pioctl_req)
+{
+ pmlan_adapter pmadapter = (pmlan_adapter)adapter;
+ mlan_status status = MLAN_STATUS_SUCCESS;
+ mlan_ds_bss *bss = MNULL;
+ mlan_ds_get_info *pget_info = MNULL;
+ mlan_ds_misc_cfg *misc = MNULL;
+ mlan_ds_sec_cfg *sec = MNULL;
+ mlan_ds_power_cfg *power = MNULL;
+ mlan_ds_pm_cfg *pm = MNULL;
+ mlan_ds_11d_cfg *cfg11d = MNULL;
+ mlan_ds_snmp_mib *snmp = MNULL;
+ mlan_ds_11h_cfg *cfg11h = MNULL;
+ mlan_ds_radio_cfg *radiocfg = MNULL;
+ mlan_ds_rate *rate = MNULL;
+ mlan_ds_reg_mem *reg_mem = MNULL;
+ mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index];
+#if defined(STA_SUPPORT) && defined(UAP_SUPPORT)
+ pmlan_ds_scan pscan;
+#endif
+
+ ENTER();
+ switch (pioctl_req->req_id) {
+ case MLAN_IOCTL_BSS:
+ bss = (mlan_ds_bss *)pioctl_req->pbuf;
+ if (bss->sub_command == MLAN_OID_BSS_MAC_ADDR)
+ status = wlan_uap_bss_ioctl_mac_address(pmadapter,
+ pioctl_req);
+ else if (bss->sub_command == MLAN_OID_BSS_STOP)
+ status = wlan_uap_bss_ioctl_stop(pmadapter, pioctl_req);
+ else if (bss->sub_command == MLAN_OID_BSS_START)
+ status =
+ wlan_uap_bss_ioctl_start(pmadapter, pioctl_req);
+ else if (bss->sub_command == MLAN_OID_UAP_BSS_CONFIG)
+ status = wlan_uap_bss_ioctl_config(pmadapter,
+ pioctl_req);
+ else if (bss->sub_command == MLAN_OID_UAP_DEAUTH_STA)
+ status = wlan_uap_bss_ioctl_deauth_sta(pmadapter,
+ pioctl_req);
+ else if (bss->sub_command == MLAN_OID_UAP_BSS_RESET)
+ status =
+ wlan_uap_bss_ioctl_reset(pmadapter, pioctl_req);
+#if defined(STA_SUPPORT) && defined(UAP_SUPPORT)
+ else if (bss->sub_command == MLAN_OID_BSS_ROLE) {
+ util_enqueue_list_tail(
+ pmadapter->pmoal_handle,
+ &pmadapter->ioctl_pending_q,
+ (pmlan_linked_list)pioctl_req,
+ pmadapter->callbacks.moal_spin_lock,
+ pmadapter->callbacks.moal_spin_unlock);
+ pmadapter->pending_ioctl = MTRUE;
+ status = MLAN_STATUS_PENDING;
+ }
+#endif
+#ifdef WIFI_DIRECT_SUPPORT
+ else if (bss->sub_command == MLAN_OID_WIFI_DIRECT_MODE)
+ status = wlan_bss_ioctl_wifi_direct_mode(pmadapter,
+ pioctl_req);
+#endif
+ else if (bss->sub_command == MLAN_OID_BSS_REMOVE)
+ status = wlan_bss_ioctl_bss_remove(pmadapter,
+ pioctl_req);
+ else if (bss->sub_command == MLAN_OID_UAP_CFG_WMM_PARAM)
+ status = wlan_uap_bss_ioctl_uap_wmm_param(pmadapter,
+ pioctl_req);
+ else if (bss->sub_command == MLAN_OID_UAP_SCAN_CHANNELS)
+ status = wlan_uap_bss_ioctl_uap_scan_channels(
+ pmadapter, pioctl_req);
+ else if (bss->sub_command == MLAN_OID_UAP_CHANNEL)
+ status = wlan_uap_bss_ioctl_uap_channel(pmadapter,
+ pioctl_req);
+ else if (bss->sub_command == MLAN_OID_UAP_ACS_SCAN)
+ status = wlan_uap_bss_ioctl_acs_scan(pmadapter,
+ pioctl_req);
+ else if (bss->sub_command == MLAN_OID_UAP_OPER_CTRL)
+ status = wlan_uap_bss_ioctl_uap_oper_ctrl(pmadapter,
+ pioctl_req);
+ else if (bss->sub_command == MLAN_OID_UAP_ADD_STATION)
+ status = wlan_uap_bss_ioctl_add_station(pmadapter,
+ pioctl_req);
+ break;
+#if defined(STA_SUPPORT) && defined(UAP_SUPPORT)
+ case MLAN_IOCTL_SCAN:
+ pscan = (mlan_ds_scan *)pioctl_req->pbuf;
+ if ((pscan->sub_command == MLAN_OID_SCAN_NORMAL) &&
+ (pioctl_req->action == MLAN_ACT_GET)) {
+ PRINTM(MIOCTL, "Get scan table in uap\n");
+ pscan->param.scan_resp.pscan_table =
+ (t_u8 *)pmadapter->pscan_table;
+ pscan->param.scan_resp.num_in_scan_table =
+ pmadapter->num_in_scan_table;
+ pscan->param.scan_resp.age_in_secs =
+ pmadapter->age_in_secs;
+ pioctl_req->data_read_written =
+ sizeof(mlan_scan_resp) + MLAN_SUB_COMMAND_SIZE;
+ pscan->param.scan_resp.pchan_stats =
+ (t_u8 *)pmadapter->pchan_stats;
+ pscan->param.scan_resp.num_in_chan_stats =
+ pmadapter->num_in_chan_stats;
+ }
+ break;
+#endif
+ case MLAN_IOCTL_GET_INFO:
+ pget_info = (mlan_ds_get_info *)pioctl_req->pbuf;
+ if (pget_info->sub_command == MLAN_OID_GET_VER_EXT)
+ status = wlan_get_info_ver_ext(pmadapter, pioctl_req);
+ else if (pget_info->sub_command == MLAN_OID_GET_DEBUG_INFO)
+ status =
+ wlan_get_info_debug_info(pmadapter, pioctl_req);
+ else if (pget_info->sub_command == MLAN_OID_GET_STATS)
+ status = wlan_uap_get_stats(pmadapter, pioctl_req);
+ else if (pget_info->sub_command == MLAN_OID_GET_UAP_STATS_LOG)
+ status = wlan_uap_get_stats_log(pmadapter, pioctl_req);
+ else if (pget_info->sub_command == MLAN_OID_UAP_STA_LIST)
+ status = wlan_uap_get_sta_list(pmadapter, pioctl_req);
+ else if (pget_info->sub_command == MLAN_OID_GET_BSS_INFO)
+ status = wlan_uap_get_bss_info(pmadapter, pioctl_req);
+ else if (pget_info->sub_command == MLAN_OID_GET_FW_INFO) {
+ pioctl_req->data_read_written =
+ sizeof(mlan_fw_info) + MLAN_SUB_COMMAND_SIZE;
+ memcpy_ext(pmadapter,
+ &pget_info->param.fw_info.mac_addr,
+ pmpriv->curr_addr, MLAN_MAC_ADDR_LENGTH,
+ MLAN_MAC_ADDR_LENGTH);
+ pget_info->param.fw_info.fw_ver =
+ pmadapter->fw_release_number;
+ pget_info->param.fw_info.fw_bands = pmadapter->fw_bands;
+ pget_info->param.fw_info.ecsa_enable =
+ pmadapter->ecsa_enable;
+ pget_info->param.fw_info.getlog_enable =
+ pmadapter->getlog_enable;
+ pget_info->param.fw_info.hw_dev_mcs_support =
+ pmadapter->hw_dev_mcs_support;
+ pget_info->param.fw_info.hw_dot_11n_dev_cap =
+ pmadapter->hw_dot_11n_dev_cap;
+ pget_info->param.fw_info.usr_dev_mcs_support =
+ pmpriv->usr_dev_mcs_support;
+ if (IS_FW_SUPPORT_NO_80MHZ(pmadapter))
+ pget_info->param.fw_info.prohibit_80mhz = MTRUE;
+ else
+ pget_info->param.fw_info.prohibit_80mhz =
+ MFALSE;
+ pget_info->param.fw_info.hw_dot_11ac_mcs_support =
+ pmadapter->hw_dot_11ac_mcs_support;
+ pget_info->param.fw_info.hw_dot_11ac_dev_cap =
+ pmadapter->hw_dot_11ac_dev_cap;
+ pget_info->param.fw_info.usr_dot_11ac_dev_cap_bg =
+ pmpriv->usr_dot_11ac_dev_cap_bg;
+ pget_info->param.fw_info.usr_dot_11ac_mcs_support =
+ pmpriv->usr_dot_11ac_mcs_support;
+ pget_info->param.fw_info.usr_dot_11ac_dev_cap_a =
+ pmpriv->usr_dot_11ac_dev_cap_a;
+ pget_info->param.fw_info.hw_hecap_len =
+ pmadapter->hw_hecap_len;
+ pget_info->param.fw_info.hw_2g_hecap_len =
+ pmadapter->hw_2g_hecap_len;
+ memcpy_ext(pmadapter,
+ pget_info->param.fw_info.hw_he_cap,
+ pmadapter->hw_he_cap,
+ pmadapter->hw_hecap_len,
+ sizeof(pget_info->param.fw_info.hw_he_cap));
+ memcpy_ext(
+ pmadapter,
+ pget_info->param.fw_info.hw_2g_he_cap,
+ pmadapter->hw_2g_he_cap,
+ pmadapter->hw_2g_hecap_len,
+ sizeof(pget_info->param.fw_info.hw_2g_he_cap));
+ pget_info->param.fw_info.region_code =
+ pmadapter->region_code;
+ if (pmadapter->otp_region &&
+ pmadapter->otp_region->force_reg)
+ pget_info->param.fw_info.force_reg = MTRUE;
+ else
+ pget_info->param.fw_info.force_reg = MFALSE;
+ pget_info->param.fw_info.fw_supplicant_support =
+ IS_FW_SUPPORT_SUPPLICANT(pmadapter) ? 0x01 :
+ 0x00;
+ pget_info->param.fw_info.antinfo = pmadapter->antinfo;
+ pget_info->param.fw_info.max_ap_assoc_sta =
+ pmadapter->max_sta_conn;
+ } else if (pget_info->sub_command == MLAN_OID_LINK_STATS)
+ status = wlan_ioctl_link_statistic(pmpriv, pioctl_req);
+ break;
+ case MLAN_IOCTL_MISC_CFG:
+ misc = (mlan_ds_misc_cfg *)pioctl_req->pbuf;
+ if (misc->sub_command == MLAN_OID_MISC_INIT_SHUTDOWN)
+ status = wlan_misc_ioctl_init_shutdown(pmadapter,
+ pioctl_req);
+ if (misc->sub_command == MLAN_OID_MISC_SOFT_RESET)
+ status = wlan_uap_misc_ioctl_soft_reset(pmadapter,
+ pioctl_req);
+ if (misc->sub_command == MLAN_OID_MISC_HOST_CMD)
+ status =
+ wlan_misc_ioctl_host_cmd(pmadapter, pioctl_req);
+ if (misc->sub_command == MLAN_OID_MISC_REGION)
+ status = wlan_misc_ioctl_region(pmadapter, pioctl_req);
+ if (misc->sub_command == MLAN_OID_MISC_GEN_IE)
+ status = wlan_uap_misc_ioctl_gen_ie(pmadapter,
+ pioctl_req);
+ if (misc->sub_command == MLAN_OID_MISC_CUSTOM_IE)
+ status = wlan_misc_ioctl_custom_ie_list(
+ pmadapter, pioctl_req, MTRUE);
+ if (misc->sub_command == MLAN_OID_MISC_TX_DATAPAUSE)
+ status = wlan_uap_misc_ioctl_txdatapause(pmadapter,
+ pioctl_req);
+ if (misc->sub_command == MLAN_OID_MISC_RX_MGMT_IND)
+ status = wlan_reg_rx_mgmt_ind(pmadapter, pioctl_req);
+#ifdef DEBUG_LEVEL1
+ if (misc->sub_command == MLAN_OID_MISC_DRVDBG)
+ status = wlan_set_drvdbg(pmadapter, pioctl_req);
+#endif
+
+ if (misc->sub_command == MLAN_OID_MISC_TXCONTROL)
+ status = wlan_misc_ioctl_txcontrol(pmadapter,
+ pioctl_req);
+ if (misc->sub_command == MLAN_OID_MISC_MAC_CONTROL)
+ status = wlan_misc_ioctl_mac_control(pmadapter,
+ pioctl_req);
+#ifdef RX_PACKET_COALESCE
+ if (misc->sub_command == MLAN_OID_MISC_RX_PACKET_COALESCE)
+ status = wlan_misc_ioctl_rx_pkt_coalesce_config(
+ pmadapter, pioctl_req);
+#endif
+#ifdef WIFI_DIRECT_SUPPORT
+ if (misc->sub_command == MLAN_OID_MISC_WIFI_DIRECT_CONFIG)
+ status = wlan_misc_p2p_config(pmadapter, pioctl_req);
+#endif
+
+ if (misc->sub_command == MLAN_OID_MISC_DFS_REAPTER_MODE) {
+ mlan_ds_misc_cfg *misc_cfg = MNULL;
+
+ misc_cfg = (mlan_ds_misc_cfg *)pioctl_req->pbuf;
+ misc_cfg->param.dfs_repeater.mode =
+ pmadapter->dfs_repeater;
+ pioctl_req->data_read_written =
+ sizeof(mlan_ds_misc_dfs_repeater);
+
+ status = MLAN_STATUS_SUCCESS;
+ }
+ if (misc->sub_command == MLAN_OID_MISC_IND_RST_CFG)
+ status = wlan_misc_ioctl_ind_rst_cfg(pmadapter,
+ pioctl_req);
+ if (misc->sub_command == MLAN_OID_MISC_GET_TSF)
+ status = wlan_misc_ioctl_get_tsf(pmadapter, pioctl_req);
+ if (misc->sub_command == MLAN_OID_MISC_GET_CHAN_REGION_CFG)
+ status = wlan_misc_chan_reg_cfg(pmadapter, pioctl_req);
+ if (misc->sub_command == MLAN_OID_MISC_OPER_CLASS_CHECK)
+ status = wlan_misc_ioctl_operclass_validation(
+ pmadapter, pioctl_req);
+ if (misc->sub_command == MLAN_OID_MISC_OPER_CLASS)
+ status = wlan_misc_ioctl_oper_class(pmadapter,
+ pioctl_req);
+ if (misc->sub_command == MLAN_OID_MISC_AGGR_CTRL)
+ status = wlan_misc_ioctl_aggr_ctrl(pmadapter,
+ pioctl_req);
+ if (misc->sub_command == MLAN_OID_MISC_PER_PKT_CFG)
+ status = wlan_misc_per_pkt_cfg(pmadapter, pioctl_req);
+ if (misc->sub_command == MLAN_OID_MISC_FW_DUMP_EVENT)
+ status = wlan_misc_ioctl_fw_dump_event(pmadapter,
+ pioctl_req);
+ if (misc->sub_command == MLAN_OID_MISC_RX_ABORT_CFG)
+ status = wlan_misc_ioctl_rxabortcfg(pmadapter,
+ pioctl_req);
+ if (misc->sub_command == MLAN_OID_MISC_RX_ABORT_CFG_EXT)
+ status = wlan_misc_ioctl_rxabortcfg_ext(pmadapter,
+ pioctl_req);
+ if (misc->sub_command == MLAN_OID_MISC_TX_AMPDU_PROT_MODE)
+ status = wlan_misc_ioctl_tx_ampdu_prot_mode(pmadapter,
+ pioctl_req);
+ if (misc->sub_command == MLAN_OID_MISC_DOT11MC_UNASSOC_FTM_CFG)
+ status = wlan_misc_ioctl_dot11mc_unassoc_ftm_cfg(
+ pmadapter, pioctl_req);
+ if (misc->sub_command == MLAN_OID_MISC_RATE_ADAPT_CFG)
+ status = wlan_misc_ioctl_rate_adapt_cfg(pmadapter,
+ pioctl_req);
+ if (misc->sub_command == MLAN_OID_MISC_CCK_DESENSE_CFG)
+ status = wlan_misc_ioctl_cck_desense_cfg(pmadapter,
+ pioctl_req);
+ if (misc->sub_command == MLAN_OID_MISC_ROBUSTCOEX)
+ status = wlan_misc_robustcoex(pmadapter, pioctl_req);
+ if (misc->sub_command == MLAN_OID_MISC_DMCS_CONFIG)
+ status = wlan_misc_dmcs_config(pmadapter, pioctl_req);
+ if (misc->sub_command == MLAN_OID_MISC_GET_TX_RX_HISTOGRAM)
+ status =
+ wlan_get_tx_rx_histogram(pmadapter, pioctl_req);
+ if (misc->sub_command == MLAN_OID_MISC_CFP_INFO)
+ status = wlan_get_cfpinfo(pmadapter, pioctl_req);
+ if (misc->sub_command == MLAN_OID_MISC_BOOT_SLEEP)
+ status = wlan_misc_bootsleep(pmadapter, pioctl_req);
+ if (misc->sub_command == MLAN_OID_MISC_DYN_BW)
+ status = wlan_misc_ioctl_dyn_bw(pmadapter, pioctl_req);
+ if (misc->sub_command == MLAN_OID_MISC_GET_CHAN_TRPC_CFG)
+ status = wlan_get_chan_trpc_cfg(pmadapter, pioctl_req);
+ if (misc->sub_command == MLAN_OID_MISC_BAND_STEERING)
+ status = wlan_misc_band_steering_cfg(pmadapter,
+ pioctl_req);
+ if (misc->sub_command == MLAN_OID_MISC_BEACON_STUCK)
+ status = wlan_misc_beacon_stuck_cfg(pmadapter,
+ pioctl_req);
+ if (misc->sub_command == MLAN_OID_MISC_GET_REGIONPWR_CFG)
+ status = wlan_get_rgchnpwr_cfg(pmadapter, pioctl_req);
+ if (misc->sub_command == MLAN_OID_MISC_CFP_TABLE)
+ status = wlan_get_cfp_table(pmadapter, pioctl_req);
+ if (misc->sub_command == MLAN_OID_MISC_RANGE_EXT)
+ status = wlan_misc_ioctl_range_ext(pmadapter,
+ pioctl_req);
+ break;
+ case MLAN_IOCTL_POWER_CFG:
+ power = (mlan_ds_power_cfg *)pioctl_req->pbuf;
+ if (power->sub_command == MLAN_OID_POWER_LOW_POWER_MODE)
+ status = wlan_power_ioctl_set_get_lpm(pmadapter,
+ pioctl_req);
+ break;
+ case MLAN_IOCTL_PM_CFG:
+ pm = (mlan_ds_pm_cfg *)pioctl_req->pbuf;
+ if (pm->sub_command == MLAN_OID_PM_CFG_PS_MODE)
+ status = wlan_uap_pm_ioctl_mode(pmadapter, pioctl_req);
+ if (pm->sub_command == MLAN_OID_PM_CFG_DEEP_SLEEP)
+ status = wlan_uap_pm_ioctl_deepsleep(pmadapter,
+ pioctl_req);
+ if (pm->sub_command == MLAN_OID_PM_CFG_HS_CFG)
+ status = wlan_pm_ioctl_hscfg(pmadapter, pioctl_req);
+ if (pm->sub_command == MLAN_OID_PM_HS_WAKEUP_REASON)
+ status = wlan_get_hs_wakeup_reason(pmadapter,
+ pioctl_req);
+ if (pm->sub_command == MLAN_OID_PM_MGMT_FILTER)
+ status = wlan_config_mgmt_filter(pmadapter, pioctl_req);
+ if (pm->sub_command == MLAN_OID_PM_INFO)
+ status = wlan_get_pm_info(pmadapter, pioctl_req);
+ break;
+ case MLAN_IOCTL_SNMP_MIB:
+ snmp = (mlan_ds_snmp_mib *)pioctl_req->pbuf;
+ if (snmp->sub_command == MLAN_OID_SNMP_MIB_CTRL_DEAUTH)
+ status = wlan_uap_snmp_mib_ctrl_deauth(pmadapter,
+ pioctl_req);
+ if (snmp->sub_command == MLAN_OID_SNMP_MIB_DOT11D)
+ status = wlan_uap_snmp_mib_11d(pmadapter, pioctl_req);
+ if (snmp->sub_command == MLAN_OID_SNMP_MIB_DOT11H)
+ status = wlan_uap_snmp_mib_11h(pmadapter, pioctl_req);
+ break;
+ case MLAN_IOCTL_SEC_CFG:
+ sec = (mlan_ds_sec_cfg *)pioctl_req->pbuf;
+ if (sec->sub_command == MLAN_OID_SEC_CFG_ENCRYPT_KEY)
+ status = wlan_uap_sec_ioctl_set_encrypt_key(pmadapter,
+ pioctl_req);
+ if (sec->sub_command == MLAN_OID_SEC_CFG_WAPI_ENABLED)
+ status = wlan_uap_sec_ioctl_wapi_enable(pmadapter,
+ pioctl_req);
+ if (sec->sub_command == MLAN_OID_SEC_CFG_REPORT_MIC_ERR)
+ status = wlan_uap_sec_ioctl_report_mic_error(
+ pmadapter, pioctl_req);
+ break;
+ case MLAN_IOCTL_11N_CFG:
+ status = wlan_11n_cfg_ioctl(pmadapter, pioctl_req);
+ break;
+ case MLAN_IOCTL_11D_CFG:
+ cfg11d = (mlan_ds_11d_cfg *)pioctl_req->pbuf;
+ if (cfg11d->sub_command == MLAN_OID_11D_DOMAIN_INFO)
+ status = wlan_uap_domain_info(pmadapter, pioctl_req);
+ else if (cfg11d->sub_command == MLAN_OID_11D_DOMAIN_INFO_EXT)
+ status =
+ wlan_11d_cfg_domain_info(pmadapter, pioctl_req);
+ break;
+ case MLAN_IOCTL_11H_CFG:
+ cfg11h = (mlan_ds_11h_cfg *)pioctl_req->pbuf;
+ if (cfg11h->sub_command == MLAN_OID_11H_CHANNEL_CHECK)
+ status = wlan_uap_11h_channel_check_req(pmadapter,
+ pioctl_req);
+ if (cfg11h->sub_command == MLAN_OID_11H_DFS_TESTING)
+ status = wlan_11h_ioctl_dfs_testing(pmadapter,
+ pioctl_req);
+ if (cfg11h->sub_command == MLAN_OID_11H_CHAN_NOP_INFO)
+ status = wlan_11h_ioctl_get_channel_nop_info(
+ pmadapter, pioctl_req);
+ if (cfg11h->sub_command == MLAN_OID_11H_CHAN_REPORT_REQUEST)
+ status = wlan_11h_ioctl_dfs_chan_report(pmpriv,
+ pioctl_req);
+ if (cfg11h->sub_command == MLAN_OID_11H_CHAN_SWITCH_COUNT)
+ status = wlan_11h_ioctl_chan_switch_count(pmadapter,
+ pioctl_req);
+ if (cfg11h->sub_command == MLAN_OID_11H_DFS_W53_CFG)
+ status = wlan_11h_ioctl_dfs_w53_cfg(pmadapter,
+ pioctl_req);
+ break;
+ case MLAN_IOCTL_RADIO_CFG:
+ radiocfg = (mlan_ds_radio_cfg *)pioctl_req->pbuf;
+ if (radiocfg->sub_command == MLAN_OID_MIMO_SWITCH)
+ status = wlan_radio_ioctl_mimo_switch_cfg(pmadapter,
+ pioctl_req);
+ if (radiocfg->sub_command == MLAN_OID_RADIO_CTRL)
+ status = wlan_radio_ioctl_radio_ctl(pmadapter,
+ pioctl_req);
+ if (radiocfg->sub_command == MLAN_OID_REMAIN_CHAN_CFG)
+ status = wlan_radio_ioctl_remain_chan_cfg(pmadapter,
+ pioctl_req);
+ if (radiocfg->sub_command == MLAN_OID_ANT_CFG)
+ status =
+ wlan_radio_ioctl_ant_cfg(pmadapter, pioctl_req);
+ if (radiocfg->sub_command == MLAN_OID_BAND_CFG)
+ status = wlan_radio_ioctl_band_cfg(pmadapter,
+ pioctl_req);
+ break;
+ case MLAN_IOCTL_RATE:
+ rate = (mlan_ds_rate *)pioctl_req->pbuf;
+ if (rate->sub_command == MLAN_OID_RATE_CFG)
+ status = wlan_rate_ioctl_cfg(pmadapter, pioctl_req);
+ else if (rate->sub_command == MLAN_OID_GET_DATA_RATE)
+ status = wlan_rate_ioctl_get_data_rate(pmadapter,
+ pioctl_req);
+ break;
+ case MLAN_IOCTL_11AC_CFG:
+ status = wlan_11ac_cfg_ioctl(pmadapter, pioctl_req);
+ break;
+ case MLAN_IOCTL_11AX_CFG:
+ status = wlan_11ax_cfg_ioctl(pmadapter, pioctl_req);
+ break;
+ case MLAN_IOCTL_REG_MEM:
+ reg_mem = (mlan_ds_reg_mem *)pioctl_req->pbuf;
+ if (reg_mem->sub_command == MLAN_OID_REG_RW)
+ status = wlan_reg_mem_ioctl_reg_rw(pmadapter,
+ pioctl_req);
+ else if (reg_mem->sub_command == MLAN_OID_EEPROM_RD)
+ status = wlan_reg_mem_ioctl_read_eeprom(pmadapter,
+ pioctl_req);
+ else if (reg_mem->sub_command == MLAN_OID_MEM_RW)
+ status = wlan_reg_mem_ioctl_mem_rw(pmadapter,
+ pioctl_req);
+ break;
+ case MLAN_IOCTL_WMM_CFG:
+ status = wlan_wmm_cfg_ioctl(pmadapter, pioctl_req);
+ break;
+ default:
+ pioctl_req->status_code = MLAN_ERROR_IOCTL_INVALID;
+ break;
+ }
+ LEAVE();
+ return status;
+}
diff --git a/drivers/net/wireless/nxp/mxm_wifiex/wlan_src/mlan/mlan_uap_txrx.c b/drivers/net/wireless/nxp/mxm_wifiex/wlan_src/mlan/mlan_uap_txrx.c
new file mode 100644
index 000000000000..5ea637fa26d8
--- /dev/null
+++ b/drivers/net/wireless/nxp/mxm_wifiex/wlan_src/mlan/mlan_uap_txrx.c
@@ -0,0 +1,820 @@
+/** @file mlan_uap_txrx.c
+ *
+ * @brief This file contains AP mode transmit and receive functions
+ *
+ *
+ * Copyright 2014-2020 NXP
+ *
+ * This software file (the File) is distributed by NXP
+ * under the terms of the GNU General Public License Version 2, June 1991
+ * (the License). You may use, redistribute and/or modify the 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.
+ *
+ */
+
+/********************************************************
+Change log:
+ 02/05/2009: initial version
+********************************************************/
+
+#include "mlan.h"
+#include "mlan_util.h"
+#include "mlan_fw.h"
+#ifdef STA_SUPPORT
+#include "mlan_join.h"
+#endif
+#include "mlan_main.h"
+#include "mlan_uap.h"
+#include "mlan_wmm.h"
+#include "mlan_11n_aggr.h"
+#include "mlan_11n_rxreorder.h"
+#ifdef DRV_EMBEDDED_AUTHENTICATOR
+#include "authenticator_api.h"
+#endif
+
+/********************************************************
+ Local Functions
+********************************************************/
+
+/**
+ * @brief This function processes received packet and forwards it
+ * to kernel/upper layer
+ *
+ * @param pmadapter A pointer to mlan_adapter
+ * @param pmbuf A pointer to mlan_buffer which includes the received packet
+ *
+ * @return MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ */
+static mlan_status wlan_upload_uap_rx_packet(pmlan_adapter pmadapter,
+ pmlan_buffer pmbuf)
+{
+ mlan_status ret = MLAN_STATUS_SUCCESS;
+#ifdef DEBUG_LEVEL1
+ pmlan_private priv = pmadapter->priv[pmbuf->bss_index];
+#endif
+ PRxPD prx_pd;
+ ENTER();
+ prx_pd = (RxPD *)(pmbuf->pbuf + pmbuf->data_offset);
+
+ /* Chop off RxPD */
+ pmbuf->data_len -= prx_pd->rx_pkt_offset;
+ pmbuf->data_offset += prx_pd->rx_pkt_offset;
+ pmbuf->pparent = MNULL;
+
+ DBG_HEXDUMP(MDAT_D, "uAP RxPD", (t_u8 *)prx_pd,
+ MIN(sizeof(RxPD), MAX_DATA_DUMP_LEN));
+ DBG_HEXDUMP(MDAT_D, "uAP Rx Payload",
+ ((t_u8 *)prx_pd + prx_pd->rx_pkt_offset),
+ MIN(prx_pd->rx_pkt_length, MAX_DATA_DUMP_LEN));
+
+ pmadapter->callbacks.moal_get_system_time(pmadapter->pmoal_handle,
+ &pmbuf->out_ts_sec,
+ &pmbuf->out_ts_usec);
+ PRINTM_NETINTF(MDATA, priv);
+ PRINTM(MDATA, "%lu.%06lu : Data => kernel seq_num=%d tid=%d\n",
+ pmbuf->out_ts_sec, pmbuf->out_ts_usec, prx_pd->seq_num,
+ prx_pd->priority);
+ ret = pmadapter->callbacks.moal_recv_packet(pmadapter->pmoal_handle,
+ pmbuf);
+ if (ret == MLAN_STATUS_FAILURE) {
+ PRINTM(MERROR,
+ "uAP Rx Error: moal_recv_packet returned error\n");
+ pmbuf->status_code = MLAN_ERROR_PKT_INVALID;
+ }
+
+ if (ret != MLAN_STATUS_PENDING)
+ pmadapter->ops.data_complete(pmadapter, pmbuf, ret);
+#ifdef USB
+ else if (IS_USB(pmadapter->card_type))
+ pmadapter->callbacks.moal_recv_complete(pmadapter->pmoal_handle,
+ MNULL,
+ pmadapter->rx_data_ep,
+ ret);
+#endif
+ LEAVE();
+
+ return ret;
+}
+
+/**
+ * @brief This function will check if unicast packet need be dropped
+ *
+ * @param priv A pointer to mlan_private
+ * @param mac mac address to find in station list table
+ *
+ * @return MLAN_STATUS_FAILURE -- drop packet, otherwise forward to
+ * network stack
+ */
+static mlan_status wlan_check_unicast_packet(mlan_private *priv, t_u8 *mac)
+{
+ int j;
+ sta_node *sta_ptr = MNULL;
+ pmlan_adapter pmadapter = priv->adapter;
+ pmlan_private pmpriv = MNULL;
+ t_u8 pkt_type = 0;
+ mlan_status ret = MLAN_STATUS_SUCCESS;
+ ENTER();
+ for (j = 0; j < MLAN_MAX_BSS_NUM; ++j) {
+ pmpriv = pmadapter->priv[j];
+ if (pmpriv) {
+ if (GET_BSS_ROLE(pmpriv) == MLAN_BSS_ROLE_STA)
+ continue;
+ sta_ptr = wlan_get_station_entry(pmpriv, mac);
+ if (sta_ptr) {
+ if (pmpriv == priv)
+ pkt_type = PKT_INTRA_UCAST;
+ else
+ pkt_type = PKT_INTER_UCAST;
+ break;
+ }
+ }
+ }
+ if ((pkt_type == PKT_INTRA_UCAST) &&
+ (priv->pkt_fwd & PKT_FWD_INTRA_UCAST)) {
+ PRINTM(MDATA, "Drop INTRA_UCAST packet\n");
+ ret = MLAN_STATUS_FAILURE;
+ } else if ((pkt_type == PKT_INTER_UCAST) &&
+ (priv->pkt_fwd & PKT_FWD_INTER_UCAST)) {
+ PRINTM(MDATA, "Drop INTER_UCAST packet\n");
+ ret = MLAN_STATUS_FAILURE;
+ }
+ LEAVE();
+ return ret;
+}
+/********************************************************
+ Global Functions
+********************************************************/
+/**
+ * @brief This function fill the txpd for tx packet
+ *
+ * @param priv A pointer to mlan_private structure
+ * @param pmbuf A pointer to the mlan_buffer for process
+ *
+ * @return headptr or MNULL
+ */
+t_void *wlan_ops_uap_process_txpd(t_void *priv, pmlan_buffer pmbuf)
+{
+ pmlan_private pmpriv = (pmlan_private)priv;
+ TxPD *plocal_tx_pd;
+ t_u8 *head_ptr = MNULL;
+ t_u32 pkt_type;
+ t_u32 tx_control;
+ t_u8 dst_mac[MLAN_MAC_ADDR_LENGTH];
+
+ ENTER();
+
+ if (!pmbuf->data_len) {
+ PRINTM(MERROR, "uAP Tx Error: Invalid packet length: %d\n",
+ pmbuf->data_len);
+ pmbuf->status_code = MLAN_ERROR_PKT_SIZE_INVALID;
+ goto done;
+ }
+ if (pmbuf->buf_type == MLAN_BUF_TYPE_RAW_DATA) {
+ memcpy_ext(pmpriv->adapter, &pkt_type,
+ pmbuf->pbuf + pmbuf->data_offset, sizeof(pkt_type),
+ sizeof(pkt_type));
+ memcpy_ext(pmpriv->adapter, &tx_control,
+ pmbuf->pbuf + pmbuf->data_offset + sizeof(pkt_type),
+ sizeof(tx_control), sizeof(tx_control));
+ pmbuf->data_offset += sizeof(pkt_type) + sizeof(tx_control);
+ pmbuf->data_len -= sizeof(pkt_type) + sizeof(tx_control);
+ }
+ if (pmbuf->data_offset <
+ (sizeof(TxPD) + pmpriv->intf_hr_len + DMA_ALIGNMENT)) {
+ PRINTM(MERROR,
+ "not enough space for TxPD: headroom=%d pkt_len=%d, required=%d\n",
+ pmbuf->data_offset, pmbuf->data_len,
+ sizeof(TxPD) + pmpriv->intf_hr_len + DMA_ALIGNMENT);
+ DBG_HEXDUMP(MDAT_D, "drop pkt",
+ pmbuf->pbuf + pmbuf->data_offset, pmbuf->data_len);
+ pmbuf->status_code = MLAN_ERROR_PKT_SIZE_INVALID;
+ goto done;
+ }
+
+ /* head_ptr should be aligned */
+ head_ptr = pmbuf->pbuf + pmbuf->data_offset - sizeof(TxPD) -
+ pmpriv->intf_hr_len;
+ head_ptr = (t_u8 *)((t_ptr)head_ptr & ~((t_ptr)(DMA_ALIGNMENT - 1)));
+
+ plocal_tx_pd = (TxPD *)(head_ptr + pmpriv->intf_hr_len);
+ memset(pmpriv->adapter, plocal_tx_pd, 0, sizeof(TxPD));
+
+ /* Set the BSS number to TxPD */
+ plocal_tx_pd->bss_num = GET_BSS_NUM(pmpriv);
+ plocal_tx_pd->bss_type = pmpriv->bss_type;
+
+ plocal_tx_pd->tx_pkt_length = (t_u16)pmbuf->data_len;
+
+ plocal_tx_pd->priority = (t_u8)pmbuf->priority;
+ plocal_tx_pd->pkt_delay_2ms =
+ wlan_wmm_compute_driver_packet_delay(pmpriv, pmbuf);
+
+ if (plocal_tx_pd->priority <
+ NELEMENTS(pmpriv->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
+ */
+ plocal_tx_pd->tx_control =
+ pmpriv->wmm.user_pri_pkt_tx_ctrl[plocal_tx_pd->priority];
+
+ if (pmbuf->flags & MLAN_BUF_FLAG_TX_STATUS) {
+ plocal_tx_pd->tx_control_1 |= pmbuf->tx_seq_num << 8;
+ plocal_tx_pd->flags |= MRVDRV_TxPD_FLAGS_TX_PACKET_STATUS;
+ }
+
+ /* Offset of actual data */
+ plocal_tx_pd->tx_pkt_offset = (t_u16)(
+ (t_ptr)pmbuf->pbuf + pmbuf->data_offset - (t_ptr)plocal_tx_pd);
+
+ if (!plocal_tx_pd->tx_control) {
+ /* TxCtrl set by user or default */
+ plocal_tx_pd->tx_control = pmpriv->pkt_tx_ctrl;
+ }
+
+ if (pmbuf->buf_type == MLAN_BUF_TYPE_RAW_DATA) {
+ plocal_tx_pd->tx_pkt_type = (t_u16)pkt_type;
+ plocal_tx_pd->tx_control = tx_control;
+ }
+ if (pmbuf->flags & MLAN_BUF_FLAG_TX_CTRL) {
+ if (pmbuf->u.tx_info.data_rate) {
+ memcpy_ext(pmpriv->adapter, dst_mac,
+ pmbuf->pbuf + pmbuf->data_offset,
+ sizeof(dst_mac), sizeof(dst_mac));
+ plocal_tx_pd->tx_control |=
+ (wlan_ieee_rateid_to_mrvl_rateid(
+ pmpriv, pmbuf->u.tx_info.data_rate,
+ dst_mac)
+ << 16);
+ plocal_tx_pd->tx_control |= TXPD_TXRATE_ENABLE;
+ }
+ plocal_tx_pd->tx_control_1 |= pmbuf->u.tx_info.channel << 21;
+ if (pmbuf->u.tx_info.bw) {
+ plocal_tx_pd->tx_control_1 |= pmbuf->u.tx_info.bw << 16;
+ plocal_tx_pd->tx_control_1 |= TXPD_BW_ENABLE;
+ }
+ if (pmbuf->u.tx_info.tx_power.tp.hostctl)
+ plocal_tx_pd->tx_control |=
+ (t_u32)pmbuf->u.tx_info.tx_power.val;
+ if (pmbuf->u.tx_info.retry_limit) {
+ plocal_tx_pd->tx_control |= pmbuf->u.tx_info.retry_limit
+ << 8;
+ plocal_tx_pd->tx_control |= TXPD_RETRY_ENABLE;
+ }
+ }
+
+ endian_convert_TxPD(plocal_tx_pd);
+
+ /* Adjust the data offset and length to include TxPD in pmbuf */
+ pmbuf->data_len += pmbuf->data_offset;
+ pmbuf->data_offset = (t_u32)((t_ptr)head_ptr - (t_ptr)pmbuf->pbuf);
+ pmbuf->data_len -= pmbuf->data_offset;
+
+done:
+ LEAVE();
+ return head_ptr;
+}
+
+/**
+ * @brief This function processes received packet and forwards it
+ * to kernel/upper layer
+ *
+ * @param adapter A pointer to mlan_adapter
+ * @param pmbuf A pointer to mlan_buffer which includes the received packet
+ *
+ * @return MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ */
+mlan_status wlan_ops_uap_process_rx_packet(t_void *adapter, pmlan_buffer pmbuf)
+{
+ pmlan_adapter pmadapter = (pmlan_adapter)adapter;
+ mlan_status ret = MLAN_STATUS_SUCCESS;
+ RxPD *prx_pd;
+ wlan_mgmt_pkt *puap_pkt_hdr = MNULL;
+
+ RxPacketHdr_t *prx_pkt;
+ pmlan_private priv = pmadapter->priv[pmbuf->bss_index];
+ t_u8 ta[MLAN_MAC_ADDR_LENGTH];
+ t_u16 rx_pkt_type = 0;
+ sta_node *sta_ptr = MNULL;
+#ifdef DRV_EMBEDDED_AUTHENTICATOR
+ t_u8 eapol_type[2] = {0x88, 0x8e};
+#endif
+ t_u16 adj_rx_rate = 0;
+ t_u8 antenna = 0;
+
+ t_u32 last_rx_sec = 0;
+ t_u32 last_rx_usec = 0;
+ t_u8 ext_rate_info = 0;
+
+ ENTER();
+
+ prx_pd = (RxPD *)(pmbuf->pbuf + pmbuf->data_offset);
+ /* Endian conversion */
+ endian_convert_RxPD(prx_pd);
+
+ if (priv->rx_pkt_info) {
+ ext_rate_info = (t_u8)(prx_pd->rx_info >> 16);
+ pmbuf->u.rx_info.data_rate =
+ wlan_index_to_data_rate(priv->adapter, prx_pd->rx_rate,
+ prx_pd->rate_info,
+ ext_rate_info);
+ pmbuf->u.rx_info.channel =
+ (prx_pd->rx_info & RXPD_CHAN_MASK) >> 5;
+ pmbuf->u.rx_info.antenna = prx_pd->antenna;
+ pmbuf->u.rx_info.rssi = prx_pd->snr - prx_pd->nf;
+ }
+
+ rx_pkt_type = prx_pd->rx_pkt_type;
+ prx_pkt = (RxPacketHdr_t *)((t_u8 *)prx_pd + prx_pd->rx_pkt_offset);
+
+ PRINTM(MINFO,
+ "RX Data: data_len - prx_pd->rx_pkt_offset = %d - %d = %d\n",
+ pmbuf->data_len, prx_pd->rx_pkt_offset,
+ pmbuf->data_len - prx_pd->rx_pkt_offset);
+
+ if ((prx_pd->rx_pkt_offset + prx_pd->rx_pkt_length) !=
+ (t_u16)pmbuf->data_len) {
+ PRINTM(MERROR,
+ "Wrong rx packet: len=%d,rx_pkt_offset=%d,"
+ " rx_pkt_length=%d\n",
+ pmbuf->data_len, prx_pd->rx_pkt_offset,
+ prx_pd->rx_pkt_length);
+ pmbuf->status_code = MLAN_ERROR_PKT_SIZE_INVALID;
+ ret = MLAN_STATUS_FAILURE;
+ pmadapter->ops.data_complete(pmadapter, pmbuf, ret);
+ goto done;
+ }
+ pmbuf->data_len = prx_pd->rx_pkt_offset + prx_pd->rx_pkt_length;
+
+ if (pmadapter->priv[pmbuf->bss_index]->mgmt_frame_passthru_mask &&
+ prx_pd->rx_pkt_type == PKT_TYPE_MGMT_FRAME) {
+ /* Check if this is mgmt packet and needs to
+ * forwarded to app as an event
+ */
+ puap_pkt_hdr = (wlan_mgmt_pkt *)((t_u8 *)prx_pd +
+ prx_pd->rx_pkt_offset);
+ puap_pkt_hdr->frm_len = wlan_le16_to_cpu(puap_pkt_hdr->frm_len);
+ if ((puap_pkt_hdr->wlan_header.frm_ctl &
+ IEEE80211_FC_MGMT_FRAME_TYPE_MASK) == 0)
+ wlan_process_802dot11_mgmt_pkt(
+ pmadapter->priv[pmbuf->bss_index],
+ (t_u8 *)&puap_pkt_hdr->wlan_header,
+ puap_pkt_hdr->frm_len + sizeof(wlan_mgmt_pkt) -
+ sizeof(puap_pkt_hdr->frm_len),
+ (RxPD *)prx_pd);
+ pmadapter->ops.data_complete(pmadapter, pmbuf, ret);
+ goto done;
+ }
+ if (rx_pkt_type != PKT_TYPE_BAR) {
+ priv->rxpd_rate = prx_pd->rx_rate;
+ priv->rxpd_rate_info = prx_pd->rate_info;
+ priv->rxpd_rx_info = (t_u8)(prx_pd->rx_info >> 16);
+
+ if (priv->bss_type == MLAN_BSS_TYPE_UAP) {
+ antenna = wlan_adjust_antenna(priv, (RxPD *)prx_pd);
+ adj_rx_rate = wlan_adjust_data_rate(
+ priv, priv->rxpd_rate, priv->rxpd_rate_info);
+ pmadapter->callbacks.moal_hist_data_add(
+ pmadapter->pmoal_handle, pmbuf->bss_index,
+ adj_rx_rate, prx_pd->snr, prx_pd->nf, antenna);
+ }
+ }
+
+ sta_ptr = wlan_get_station_entry(priv, prx_pkt->eth803_hdr.src_addr);
+ if (sta_ptr) {
+ sta_ptr->snr = prx_pd->snr;
+ sta_ptr->nf = prx_pd->nf;
+ pmadapter->callbacks.moal_get_system_time(
+ pmadapter->pmoal_handle, &last_rx_sec, &last_rx_usec);
+ sta_ptr->stats.last_rx_in_msec =
+ (t_u64)last_rx_sec * 1000 + (t_u64)last_rx_usec / 1000;
+ }
+
+#ifdef DRV_EMBEDDED_AUTHENTICATOR
+ /**process eapol packet for uap*/
+ if (IsAuthenticatorEnabled(priv->psapriv) &&
+ (!memcmp(pmadapter, &prx_pkt->eth803_hdr.h803_len, eapol_type,
+ sizeof(eapol_type)))) {
+ ret = AuthenticatorProcessEapolPacket(
+ priv->psapriv, ((t_u8 *)prx_pd + prx_pd->rx_pkt_offset),
+ prx_pd->rx_pkt_length);
+ if (ret == MLAN_STATUS_SUCCESS) {
+ pmadapter->ops.data_complete(pmadapter, pmbuf, ret);
+ goto done;
+ }
+ }
+#endif
+
+ pmbuf->priority = prx_pd->priority;
+ memcpy_ext(pmadapter, ta, prx_pkt->eth803_hdr.src_addr,
+ MLAN_MAC_ADDR_LENGTH, MLAN_MAC_ADDR_LENGTH);
+ if ((rx_pkt_type != PKT_TYPE_BAR) && (prx_pd->priority < MAX_NUM_TID)) {
+ sta_ptr = wlan_get_station_entry(priv, ta);
+ if (sta_ptr) {
+ sta_ptr->rx_seq[prx_pd->priority] = prx_pd->seq_num;
+ sta_ptr->snr = prx_pd->snr;
+ sta_ptr->nf = prx_pd->nf;
+ }
+ }
+ /* check if UAP enable 11n */
+ if (!priv->is_11n_enabled ||
+ (!wlan_11n_get_rxreorder_tbl((mlan_private *)priv, prx_pd->priority,
+ ta) &&
+ (prx_pd->rx_pkt_type != PKT_TYPE_AMSDU))) {
+ if (priv->pkt_fwd)
+ wlan_process_uap_rx_packet(priv, pmbuf);
+ else
+ wlan_upload_uap_rx_packet(pmadapter, pmbuf);
+ goto done;
+ }
+ /* Reorder and send to OS */
+ ret = mlan_11n_rxreorder_pkt(priv, prx_pd->seq_num, prx_pd->priority,
+ ta, (t_u8)prx_pd->rx_pkt_type,
+ (void *)pmbuf);
+ if (ret || (rx_pkt_type == PKT_TYPE_BAR)) {
+ pmadapter->ops.data_complete(pmadapter, pmbuf, ret);
+ }
+done:
+ LEAVE();
+ return ret;
+}
+
+/**
+ * @brief This function processes received packet and forwards it
+ * to kernel/upper layer or send back to firmware
+ *
+ * @param priv A pointer to mlan_private
+ * @param pmbuf A pointer to mlan_buffer which includes the received packet
+ *
+ * @return MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ */
+mlan_status wlan_uap_recv_packet(mlan_private *priv, pmlan_buffer pmbuf)
+{
+ pmlan_adapter pmadapter = priv->adapter;
+ mlan_status ret = MLAN_STATUS_SUCCESS;
+ RxPacketHdr_t *prx_pkt;
+ pmlan_buffer newbuf = MNULL;
+
+ ENTER();
+
+ prx_pkt = (RxPacketHdr_t *)((t_u8 *)pmbuf->pbuf + pmbuf->data_offset);
+
+ DBG_HEXDUMP(MDAT_D, "uap_recv_packet", pmbuf->pbuf + pmbuf->data_offset,
+ MIN(pmbuf->data_len, MAX_DATA_DUMP_LEN));
+
+ PRINTM(MDATA, "AMSDU dest " MACSTR "\n",
+ MAC2STR(prx_pkt->eth803_hdr.dest_addr));
+
+ /* don't do packet forwarding in disconnected state */
+ if ((priv->media_connected == MFALSE) ||
+ (pmbuf->data_len > MV_ETH_FRAME_LEN))
+ goto upload;
+
+ if (prx_pkt->eth803_hdr.dest_addr[0] & 0x01) {
+ if (!(priv->pkt_fwd & PKT_FWD_INTRA_BCAST)) {
+ /* Multicast pkt */
+ newbuf =
+ wlan_alloc_mlan_buffer(pmadapter,
+ MLAN_TX_DATA_BUF_SIZE_2K,
+ 0, MOAL_MALLOC_BUFFER);
+ if (newbuf) {
+ newbuf->bss_index = pmbuf->bss_index;
+ newbuf->buf_type = pmbuf->buf_type;
+ newbuf->priority = pmbuf->priority;
+ newbuf->in_ts_sec = pmbuf->in_ts_sec;
+ newbuf->in_ts_usec = pmbuf->in_ts_usec;
+ newbuf->data_offset =
+ (sizeof(TxPD) + priv->intf_hr_len +
+ DMA_ALIGNMENT);
+ util_scalar_increment(
+ pmadapter->pmoal_handle,
+ &pmadapter->pending_bridge_pkts,
+ pmadapter->callbacks.moal_spin_lock,
+ pmadapter->callbacks.moal_spin_unlock);
+
+ newbuf->flags |= MLAN_BUF_FLAG_BRIDGE_BUF;
+
+ /* copy the data */
+ memcpy_ext(pmadapter,
+ (t_u8 *)newbuf->pbuf +
+ newbuf->data_offset,
+ pmbuf->pbuf + pmbuf->data_offset,
+ pmbuf->data_len,
+ MLAN_TX_DATA_BUF_SIZE_2K);
+ newbuf->data_len = pmbuf->data_len;
+ wlan_wmm_add_buf_txqueue(pmadapter, newbuf);
+ if (util_scalar_read(
+ pmadapter->pmoal_handle,
+ &pmadapter->pending_bridge_pkts,
+ pmadapter->callbacks.moal_spin_lock,
+ pmadapter->callbacks
+ .moal_spin_unlock) >
+ RX_HIGH_THRESHOLD)
+ wlan_drop_tx_pkts(priv);
+ wlan_recv_event(
+ priv, MLAN_EVENT_ID_DRV_DEFER_HANDLING,
+ MNULL);
+ }
+ }
+ } else {
+ if ((!(priv->pkt_fwd & PKT_FWD_INTRA_UCAST)) &&
+ (wlan_get_station_entry(priv,
+ prx_pkt->eth803_hdr.dest_addr))) {
+ /* Intra BSS packet */
+ newbuf =
+ wlan_alloc_mlan_buffer(pmadapter,
+ MLAN_TX_DATA_BUF_SIZE_2K,
+ 0, MOAL_MALLOC_BUFFER);
+ if (newbuf) {
+ newbuf->bss_index = pmbuf->bss_index;
+ newbuf->buf_type = pmbuf->buf_type;
+ newbuf->priority = pmbuf->priority;
+ newbuf->in_ts_sec = pmbuf->in_ts_sec;
+ newbuf->in_ts_usec = pmbuf->in_ts_usec;
+ newbuf->data_offset =
+ (sizeof(TxPD) + priv->intf_hr_len +
+ DMA_ALIGNMENT);
+ util_scalar_increment(
+ pmadapter->pmoal_handle,
+ &pmadapter->pending_bridge_pkts,
+ pmadapter->callbacks.moal_spin_lock,
+ pmadapter->callbacks.moal_spin_unlock);
+ newbuf->flags |= MLAN_BUF_FLAG_BRIDGE_BUF;
+
+ /* copy the data */
+ memcpy_ext(pmadapter,
+ (t_u8 *)newbuf->pbuf +
+ newbuf->data_offset,
+ pmbuf->pbuf + pmbuf->data_offset,
+ pmbuf->data_len,
+ MLAN_TX_DATA_BUF_SIZE_2K);
+ newbuf->data_len = pmbuf->data_len;
+ wlan_wmm_add_buf_txqueue(pmadapter, newbuf);
+ if (util_scalar_read(
+ pmadapter->pmoal_handle,
+ &pmadapter->pending_bridge_pkts,
+ pmadapter->callbacks.moal_spin_lock,
+ pmadapter->callbacks
+ .moal_spin_unlock) >
+ RX_HIGH_THRESHOLD)
+ wlan_drop_tx_pkts(priv);
+ wlan_recv_event(
+ priv, MLAN_EVENT_ID_DRV_DEFER_HANDLING,
+ MNULL);
+ }
+ goto done;
+ } else if (MLAN_STATUS_FAILURE ==
+ wlan_check_unicast_packet(
+ priv, prx_pkt->eth803_hdr.dest_addr)) {
+ /* drop packet */
+ PRINTM(MDATA, "Drop AMSDU dest " MACSTR "\n",
+ MAC2STR(prx_pkt->eth803_hdr.dest_addr));
+ goto done;
+ }
+ }
+upload:
+ /** send packet to moal */
+ ret = pmadapter->callbacks.moal_recv_packet(pmadapter->pmoal_handle,
+ pmbuf);
+done:
+ LEAVE();
+ return ret;
+}
+
+/**
+ * @brief This function processes received packet and forwards it
+ * to kernel/upper layer or send back to firmware
+ *
+ * @param priv A pointer to mlan_private
+ * @param pmbuf A pointer to mlan_buffer which includes the received packet
+ *
+ * @return MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ */
+mlan_status wlan_process_uap_rx_packet(mlan_private *priv, pmlan_buffer pmbuf)
+{
+ pmlan_adapter pmadapter = priv->adapter;
+ mlan_status ret = MLAN_STATUS_SUCCESS;
+ RxPD *prx_pd;
+ RxPacketHdr_t *prx_pkt;
+ pmlan_buffer newbuf = MNULL;
+
+ ENTER();
+
+ prx_pd = (RxPD *)(pmbuf->pbuf + pmbuf->data_offset);
+ prx_pkt = (RxPacketHdr_t *)((t_u8 *)prx_pd + prx_pd->rx_pkt_offset);
+
+ DBG_HEXDUMP(MDAT_D, "uAP RxPD", prx_pd,
+ MIN(sizeof(RxPD), MAX_DATA_DUMP_LEN));
+ DBG_HEXDUMP(MDAT_D, "uAP Rx Payload",
+ ((t_u8 *)prx_pd + prx_pd->rx_pkt_offset),
+ MIN(prx_pd->rx_pkt_length, MAX_DATA_DUMP_LEN));
+
+ PRINTM(MINFO,
+ "RX Data: data_len - prx_pd->rx_pkt_offset = %d - %d = %d\n",
+ pmbuf->data_len, prx_pd->rx_pkt_offset,
+ pmbuf->data_len - prx_pd->rx_pkt_offset);
+ PRINTM(MDATA, "Rx dest " MACSTR "\n",
+ MAC2STR(prx_pkt->eth803_hdr.dest_addr));
+
+ /* don't do packet forwarding in disconnected state */
+ /* don't do packet forwarding when packet > 1514 */
+ if ((priv->media_connected == MFALSE) ||
+ ((pmbuf->data_len - prx_pd->rx_pkt_offset) > MV_ETH_FRAME_LEN))
+ goto upload;
+
+ if (prx_pkt->eth803_hdr.dest_addr[0] & 0x01) {
+ if (!(priv->pkt_fwd & PKT_FWD_INTRA_BCAST)) {
+ /* Multicast pkt */
+ newbuf =
+ wlan_alloc_mlan_buffer(pmadapter,
+ MLAN_TX_DATA_BUF_SIZE_2K,
+ 0, MOAL_MALLOC_BUFFER);
+ if (newbuf) {
+ newbuf->bss_index = pmbuf->bss_index;
+ newbuf->buf_type = pmbuf->buf_type;
+ newbuf->priority = pmbuf->priority;
+ newbuf->in_ts_sec = pmbuf->in_ts_sec;
+ newbuf->in_ts_usec = pmbuf->in_ts_usec;
+ newbuf->data_offset =
+ (sizeof(TxPD) + priv->intf_hr_len +
+ DMA_ALIGNMENT);
+ util_scalar_increment(
+ pmadapter->pmoal_handle,
+ &pmadapter->pending_bridge_pkts,
+ pmadapter->callbacks.moal_spin_lock,
+ pmadapter->callbacks.moal_spin_unlock);
+ newbuf->flags |= MLAN_BUF_FLAG_BRIDGE_BUF;
+
+ /* copy the data, skip rxpd */
+ memcpy_ext(pmadapter,
+ (t_u8 *)newbuf->pbuf +
+ newbuf->data_offset,
+ pmbuf->pbuf + pmbuf->data_offset +
+ prx_pd->rx_pkt_offset,
+ pmbuf->data_len -
+ prx_pd->rx_pkt_offset,
+ MLAN_TX_DATA_BUF_SIZE_2K);
+ newbuf->data_len =
+ pmbuf->data_len - prx_pd->rx_pkt_offset;
+ wlan_wmm_add_buf_txqueue(pmadapter, newbuf);
+ if (util_scalar_read(
+ pmadapter->pmoal_handle,
+ &pmadapter->pending_bridge_pkts,
+ pmadapter->callbacks.moal_spin_lock,
+ pmadapter->callbacks
+ .moal_spin_unlock) >
+ RX_HIGH_THRESHOLD)
+ wlan_drop_tx_pkts(priv);
+ wlan_recv_event(
+ priv, MLAN_EVENT_ID_DRV_DEFER_HANDLING,
+ MNULL);
+ }
+ }
+ } else {
+ if ((!(priv->pkt_fwd & PKT_FWD_INTRA_UCAST)) &&
+ (wlan_get_station_entry(priv,
+ prx_pkt->eth803_hdr.dest_addr))) {
+ /* Forwarding Intra-BSS packet */
+#ifdef USB
+ if (IS_USB(pmadapter->card_type)) {
+ if (pmbuf->flags & MLAN_BUF_FLAG_RX_DEAGGR) {
+ newbuf = wlan_alloc_mlan_buffer(
+ pmadapter,
+ MLAN_TX_DATA_BUF_SIZE_2K, 0,
+ MOAL_MALLOC_BUFFER);
+ if (newbuf) {
+ newbuf->bss_index =
+ pmbuf->bss_index;
+ newbuf->buf_type =
+ pmbuf->buf_type;
+ newbuf->priority =
+ pmbuf->priority;
+ newbuf->in_ts_sec =
+ pmbuf->in_ts_sec;
+ newbuf->in_ts_usec =
+ pmbuf->in_ts_usec;
+ newbuf->data_offset =
+ (sizeof(TxPD) +
+ priv->intf_hr_len +
+ DMA_ALIGNMENT);
+ util_scalar_increment(
+ pmadapter->pmoal_handle,
+ &pmadapter->pending_bridge_pkts,
+ pmadapter->callbacks
+ .moal_spin_lock,
+ pmadapter->callbacks
+ .moal_spin_unlock);
+ newbuf->flags |=
+ MLAN_BUF_FLAG_BRIDGE_BUF;
+
+ /* copy the data, skip rxpd */
+ memcpy_ext(
+ pmadapter,
+ (t_u8 *)newbuf->pbuf +
+ newbuf->data_offset,
+ pmbuf->pbuf +
+ pmbuf->data_offset +
+ prx_pd->rx_pkt_offset,
+ pmbuf->data_len -
+ prx_pd->rx_pkt_offset,
+ pmbuf->data_len -
+ prx_pd->rx_pkt_offset);
+ newbuf->data_len =
+ pmbuf->data_len -
+ prx_pd->rx_pkt_offset;
+ wlan_wmm_add_buf_txqueue(
+ pmadapter, newbuf);
+ if (util_scalar_read(
+ pmadapter->pmoal_handle,
+ &pmadapter->pending_bridge_pkts,
+ pmadapter->callbacks
+ .moal_spin_lock,
+ pmadapter->callbacks
+ .moal_spin_unlock) >
+ RX_HIGH_THRESHOLD)
+ wlan_drop_tx_pkts(priv);
+ wlan_recv_event(
+ priv,
+ MLAN_EVENT_ID_DRV_DEFER_HANDLING,
+ MNULL);
+ }
+ pmadapter->callbacks.moal_recv_complete(
+ pmadapter->pmoal_handle, pmbuf,
+ pmadapter->rx_data_ep, ret);
+ goto done;
+ }
+ }
+#endif
+ pmbuf->data_len -= prx_pd->rx_pkt_offset;
+ pmbuf->data_offset += prx_pd->rx_pkt_offset;
+ pmbuf->flags |= MLAN_BUF_FLAG_BRIDGE_BUF;
+ util_scalar_increment(
+ pmadapter->pmoal_handle,
+ &pmadapter->pending_bridge_pkts,
+ pmadapter->callbacks.moal_spin_lock,
+ pmadapter->callbacks.moal_spin_unlock);
+ wlan_wmm_add_buf_txqueue(pmadapter, pmbuf);
+ if (util_scalar_read(
+ pmadapter->pmoal_handle,
+ &pmadapter->pending_bridge_pkts,
+ pmadapter->callbacks.moal_spin_lock,
+ pmadapter->callbacks.moal_spin_unlock) >
+ RX_HIGH_THRESHOLD)
+ wlan_drop_tx_pkts(priv);
+ wlan_recv_event(priv, MLAN_EVENT_ID_DRV_DEFER_HANDLING,
+ MNULL);
+ goto done;
+ } else if (MLAN_STATUS_FAILURE ==
+ wlan_check_unicast_packet(
+ priv, prx_pkt->eth803_hdr.dest_addr)) {
+ PRINTM(MDATA, "Drop Pkts: Rx dest " MACSTR "\n",
+ MAC2STR(prx_pkt->eth803_hdr.dest_addr));
+ pmbuf->status_code = MLAN_ERROR_PKT_INVALID;
+ pmadapter->ops.data_complete(pmadapter, pmbuf, ret);
+ goto done;
+ }
+ }
+
+upload:
+ /* Chop off RxPD */
+ pmbuf->data_len -= prx_pd->rx_pkt_offset;
+ pmbuf->data_offset += prx_pd->rx_pkt_offset;
+ pmbuf->pparent = MNULL;
+
+ pmadapter->callbacks.moal_get_system_time(pmadapter->pmoal_handle,
+ &pmbuf->out_ts_sec,
+ &pmbuf->out_ts_usec);
+ PRINTM_NETINTF(MDATA, priv);
+ PRINTM(MDATA, "%lu.%06lu : Data => kernel seq_num=%d tid=%d\n",
+ pmbuf->out_ts_sec, pmbuf->out_ts_usec, prx_pd->seq_num,
+ prx_pd->priority);
+
+ ret = pmadapter->callbacks.moal_recv_packet(pmadapter->pmoal_handle,
+ pmbuf);
+ if (ret == MLAN_STATUS_FAILURE) {
+ PRINTM(MERROR,
+ "uAP Rx Error: moal_recv_packet returned error\n");
+ pmbuf->status_code = MLAN_ERROR_PKT_INVALID;
+ }
+
+ if (ret != MLAN_STATUS_PENDING)
+ pmadapter->ops.data_complete(pmadapter, pmbuf, ret);
+#ifdef USB
+ else if (IS_USB(pmadapter->card_type))
+ pmadapter->callbacks.moal_recv_complete(pmadapter->pmoal_handle,
+ MNULL,
+ pmadapter->rx_data_ep,
+ ret);
+#endif
+done:
+ LEAVE();
+ return ret;
+}
diff --git a/drivers/net/wireless/nxp/mxm_wifiex/wlan_src/mlan/mlan_usb.c b/drivers/net/wireless/nxp/mxm_wifiex/wlan_src/mlan/mlan_usb.c
new file mode 100644
index 000000000000..5a5f2d8aa71e
--- /dev/null
+++ b/drivers/net/wireless/nxp/mxm_wifiex/wlan_src/mlan/mlan_usb.c
@@ -0,0 +1,1264 @@
+/** @file mlan_usb.c
+ *
+ * @brief This file contains USB specific code
+ *
+ *
+ * Copyright 2014-2020 NXP
+ *
+ * This software file (the File) is distributed by NXP
+ * under the terms of the GNU General Public License Version 2, June 1991
+ * (the License). You may use, redistribute and/or modify the 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.
+ *
+ */
+
+/********************************************************
+Change log:
+ 04/21/2009: initial version
+********************************************************/
+
+#include "mlan.h"
+#ifdef STA_SUPPORT
+#include "mlan_join.h"
+#endif
+#include "mlan_util.h"
+#include "mlan_init.h"
+#include "mlan_fw.h"
+#include "mlan_main.h"
+
+/********************************************************
+ Local Variables
+********************************************************/
+#ifdef USB8897
+static const struct _mlan_card_info mlan_card_info_usb8897 = {
+ .max_tx_buf_size = MLAN_TX_DATA_BUF_SIZE_4K,
+ .v16_fw_api = 0,
+ .supp_ps_handshake = 1,
+ .default_11n_tx_bf_cap = DEFAULT_11N_TX_BF_CAP_2X2,
+};
+#endif
+
+#ifdef USB8997
+static const struct _mlan_card_info mlan_card_info_usb8997 = {
+ .max_tx_buf_size = MLAN_TX_DATA_BUF_SIZE_4K,
+ .v16_fw_api = 1,
+ .supp_ps_handshake = 1,
+ .default_11n_tx_bf_cap = DEFAULT_11N_TX_BF_CAP_2X2,
+};
+#endif
+
+#ifdef USB8978
+static const struct _mlan_card_info mlan_card_info_usb8978 = {
+ .max_tx_buf_size = MLAN_TX_DATA_BUF_SIZE_4K,
+ .v16_fw_api = 1,
+ .supp_ps_handshake = 1,
+ .default_11n_tx_bf_cap = DEFAULT_11N_TX_BF_CAP_2X2,
+};
+#endif
+
+#ifdef USB9098
+static const struct _mlan_card_info mlan_card_info_usb9098 = {
+ .max_tx_buf_size = MLAN_TX_DATA_BUF_SIZE_4K,
+ .v16_fw_api = 1,
+ .v17_fw_api = 1,
+ .supp_ps_handshake = 1,
+ .default_11n_tx_bf_cap = DEFAULT_11N_TX_BF_CAP_2X2,
+};
+#endif
+
+#ifdef USB9097
+static const struct _mlan_card_info mlan_card_info_usb9097 = {
+ .max_tx_buf_size = MLAN_TX_DATA_BUF_SIZE_4K,
+ .v16_fw_api = 1,
+ .v17_fw_api = 1,
+ .supp_ps_handshake = 1,
+ .default_11n_tx_bf_cap = DEFAULT_11N_TX_BF_CAP_2X2,
+};
+#endif
+
+/********************************************************
+ Global Variables
+********************************************************/
+
+/********************************************************
+ Local Functions
+********************************************************/
+#if defined(USB9098)
+/**
+ * @This function checks the chip revision id
+ *
+ * @param pmadapter A pointer to mlan_adapter structure
+ * @param rev_id A pointer to chip revision id
+ * @return MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ */
+mlan_status wlan_usb_check_revision(mlan_adapter *pmadapter, t_u32 *rev_id)
+{
+ mlan_status ret = MLAN_STATUS_SUCCESS;
+ pmlan_callbacks pcb = &pmadapter->callbacks;
+ mlan_buffer mbuf;
+ t_u8 *tx_buff = MNULL;
+ t_u8 *recv_buff = MNULL;
+ t_u8 tx_size = 16;
+ FWSyncPkt syncpkt;
+
+ ENTER();
+ /* Allocate memory for transmit */
+ ret = pcb->moal_malloc(pmadapter->pmoal_handle, FW_DNLD_TX_BUF_SIZE,
+ MLAN_MEM_DEF | MLAN_MEM_DMA, (t_u8 **)&tx_buff);
+ if ((ret != MLAN_STATUS_SUCCESS) || !tx_buff) {
+ PRINTM(MERROR, "Could not allocate buffer for FW download\n");
+ LEAVE();
+ return MLAN_STATUS_FAILURE;
+ }
+ /* Allocate memory for receive */
+ ret = pcb->moal_malloc(pmadapter->pmoal_handle, FW_DNLD_RX_BUF_SIZE,
+ MLAN_MEM_DEF | MLAN_MEM_DMA, &recv_buff);
+ if ((ret != MLAN_STATUS_SUCCESS) || !recv_buff) {
+ PRINTM(MERROR,
+ "Could not allocate buffer for FW download response\n");
+ goto cleanup;
+ }
+ memset(pmadapter, &syncpkt, 0, sizeof(FWSyncPkt));
+ memset(pmadapter, &mbuf, 0, sizeof(mlan_buffer));
+ mbuf.pbuf = (t_u8 *)tx_buff;
+ mbuf.data_len = tx_size;
+ ret = pcb->moal_write_data_sync(pmadapter->pmoal_handle, &mbuf,
+ pmadapter->tx_cmd_ep,
+ MLAN_USB_BULK_MSG_TIMEOUT);
+ if (ret != MLAN_STATUS_SUCCESS) {
+ PRINTM(MERROR, "check revision: write_data failed, ret %d\n",
+ ret);
+ goto cleanup;
+ }
+ memset(pmadapter, &mbuf, 0, sizeof(mlan_buffer));
+ mbuf.pbuf = (t_u8 *)recv_buff;
+ mbuf.data_len = 2048;
+ ret = pcb->moal_read_data_sync(pmadapter->pmoal_handle, &mbuf,
+ pmadapter->rx_cmd_ep,
+ MLAN_USB_BULK_MSG_TIMEOUT);
+ if (ret != MLAN_STATUS_SUCCESS) {
+ PRINTM(MERROR, "check revision: read_data failed, ret %d\n",
+ ret);
+ goto cleanup;
+ }
+ memcpy_ext(pmadapter, &syncpkt, recv_buff, sizeof(syncpkt),
+ sizeof(syncpkt));
+ syncpkt.chip_rev = wlan_le32_to_cpu(syncpkt.chip_rev);
+ *rev_id = syncpkt.chip_rev & 0x000000ff;
+ PRINTM(MERROR, "chip_revision_id = %d\n", syncpkt.chip_rev);
+cleanup:
+ if (recv_buff)
+ pcb->moal_mfree(pmadapter->pmoal_handle, recv_buff);
+ if (tx_buff)
+ pcb->moal_mfree(pmadapter->pmoal_handle, tx_buff);
+
+ LEAVE();
+ return ret;
+}
+#endif
+
+/**
+ * @brief This function downloads FW blocks to device
+ *
+ * @param pmadapter A pointer to mlan_adapter
+ * @param pmfw A pointer to firmware image
+ *
+ * @return MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ */
+static mlan_status wlan_usb_prog_fw_w_helper(pmlan_adapter pmadapter,
+ pmlan_fw_image pmfw)
+{
+ mlan_status ret = MLAN_STATUS_SUCCESS;
+ pmlan_callbacks pcb = &pmadapter->callbacks;
+ t_u8 *firmware = pmfw->pfw_buf, *RecvBuff;
+ t_u32 retries = MAX_FW_RETRY, DataLength;
+ t_u32 FWSeqNum = 0, TotalBytes = 0, DnldCmd = 0;
+ t_u8 *TxBuff = MNULL;
+ FWData *fwdata = MNULL;
+ FWSyncHeader SyncFWHeader;
+ t_u8 check_winner = 1;
+ t_u8 check_fw_status = MFALSE;
+ t_u8 mic_retry = MAX_FW_RETRY;
+#if defined(USB9098)
+ t_u32 revision_id = 0;
+#endif
+
+ ENTER();
+
+ if (!firmware && !pcb->moal_get_fw_data) {
+ PRINTM(MMSG, "No firmware image found! Terminating download\n");
+ ret = MLAN_STATUS_FAILURE;
+ goto fw_exit;
+ }
+
+ /* Allocate memory for transmit */
+ ret = pcb->moal_malloc(pmadapter->pmoal_handle, FW_DNLD_TX_BUF_SIZE,
+ MLAN_MEM_DEF | MLAN_MEM_DMA, (t_u8 **)&TxBuff);
+ if ((ret != MLAN_STATUS_SUCCESS) || !TxBuff) {
+ PRINTM(MERROR, "Could not allocate buffer for FW download\n");
+ goto fw_exit;
+ }
+ fwdata = (FWData *)TxBuff;
+
+ /* Allocate memory for receive */
+ ret = pcb->moal_malloc(pmadapter->pmoal_handle, FW_DNLD_RX_BUF_SIZE,
+ MLAN_MEM_DEF | MLAN_MEM_DMA, &RecvBuff);
+ if ((ret != MLAN_STATUS_SUCCESS) || !RecvBuff) {
+ PRINTM(MERROR,
+ "Could not allocate buffer for FW download response\n");
+ goto cleanup;
+ }
+
+ if (!IS_USB_NEW_INIT(pmadapter->feature_control))
+ check_winner = 0;
+#if defined(USB9098)
+ if (IS_USB9098(pmadapter->card_type)) {
+ ret = wlan_usb_check_revision(pmadapter, &revision_id);
+ if (ret != MLAN_STATUS_SUCCESS) {
+ PRINTM(MERROR, "Failed to get USB chip revision ID\n");
+ goto cleanup;
+ }
+ /* Skyhawk A0, need to check both CRC and MIC error */
+ if (revision_id >= CHIP_9098_REV_A0)
+ check_fw_status = MTRUE;
+ }
+#endif
+#if defined(USB9097)
+ if (IS_USB9097(pmadapter->card_type))
+ check_fw_status = MTRUE;
+#endif
+ do {
+ /* Send pseudo data to check winner status first */
+ if (check_winner) {
+ memset(pmadapter, &fwdata->fw_header, 0,
+ sizeof(FWHeader));
+ DataLength = 0;
+ } else {
+ /* Copy the header of the firmware data to get the
+ * length */
+ if (firmware)
+ memcpy_ext(pmadapter, &fwdata->fw_header,
+ &firmware[TotalBytes],
+ sizeof(FWHeader),
+ sizeof(fwdata->fw_header));
+ else
+ pcb->moal_get_fw_data(
+ pmadapter->pmoal_handle, TotalBytes,
+ sizeof(FWHeader),
+ (t_u8 *)&fwdata->fw_header);
+
+ DataLength =
+ wlan_le32_to_cpu(fwdata->fw_header.data_length);
+ DnldCmd = wlan_le32_to_cpu(fwdata->fw_header.dnld_cmd);
+ TotalBytes += sizeof(FWHeader);
+
+ /** CMD 7 don't have data_length field */
+ if (DnldCmd == FW_CMD_4 || DnldCmd == FW_CMD_6 ||
+ DnldCmd == FW_CMD_7 || DnldCmd == FW_CMD_10)
+ DataLength = 0;
+
+ if (DataLength >
+ (FW_DNLD_TX_BUF_SIZE - sizeof(FWHeader))) {
+ PRINTM(MERROR,
+ "Invalid Data Legth read from FW\n");
+ ret = MLAN_STATUS_FAILURE;
+ break;
+ }
+
+ /* Copy the firmware data */
+ if (firmware)
+ memcpy_ext(pmadapter, fwdata->data,
+ &firmware[TotalBytes], DataLength,
+ DataLength);
+ else
+ pcb->moal_get_fw_data(pmadapter->pmoal_handle,
+ TotalBytes, DataLength,
+ (t_u8 *)fwdata->data);
+
+ fwdata->seq_num = wlan_cpu_to_le32(FWSeqNum);
+ TotalBytes += DataLength;
+ }
+ /* If the send/receive fails or CRC occurs then retry */
+ while (retries) {
+ mlan_buffer mbuf;
+ int length = FW_DATA_XMIT_SIZE;
+ retries--;
+
+ memset(pmadapter, &mbuf, 0, sizeof(mlan_buffer));
+ mbuf.pbuf = (t_u8 *)fwdata;
+ mbuf.data_len = length;
+ /* Send the firmware block */
+ ret = pcb->moal_write_data_sync(
+ pmadapter->pmoal_handle, &mbuf,
+ pmadapter->tx_cmd_ep,
+ MLAN_USB_BULK_MSG_TIMEOUT);
+ if (ret != MLAN_STATUS_SUCCESS) {
+ PRINTM(MERROR,
+ "fw_dnld: write_data failed, ret %d\n",
+ ret);
+ continue;
+ }
+
+ memset(pmadapter, &mbuf, 0, sizeof(mlan_buffer));
+ mbuf.pbuf = RecvBuff;
+ mbuf.data_len = FW_DNLD_RX_BUF_SIZE;
+
+ /* Receive the firmware block response */
+ ret = pcb->moal_read_data_sync(
+ pmadapter->pmoal_handle, &mbuf,
+ pmadapter->rx_cmd_ep,
+ MLAN_USB_BULK_MSG_TIMEOUT);
+ if (ret != MLAN_STATUS_SUCCESS) {
+ PRINTM(MERROR,
+ "fw_dnld: read_data failed, ret %d\n",
+ ret);
+ continue;
+ }
+ memcpy_ext(pmadapter, &SyncFWHeader, RecvBuff,
+ sizeof(FWSyncHeader), sizeof(SyncFWHeader));
+ endian_convert_syncfwheader(&SyncFWHeader);
+ /* Check the first firmware block response for highest
+ * bit set */
+ if (check_winner) {
+ if (SyncFWHeader.cmd & 0x80000000) {
+ PRINTM(MMSG,
+ "USB is not the winner 0x%x, returning success\n",
+ SyncFWHeader.cmd);
+ ret = MLAN_STATUS_SUCCESS;
+ goto cleanup;
+ }
+ PRINTM(MINFO,
+ "USB is the winner, start to download FW\n");
+ check_winner = 0;
+ break;
+ }
+
+ /* Check the firmware block response for CRC errors */
+ if (SyncFWHeader.cmd) {
+ /* Check firmware block response for CRC and MIC
+ * errors */
+ if (check_fw_status) {
+ if (SyncFWHeader.status & MBIT(0)) {
+ PRINTM(MERROR,
+ "FW received Blk with CRC error 0x%x offset=%d\n",
+ SyncFWHeader.status,
+ SyncFWHeader.offset);
+ ret = MLAN_STATUS_FAILURE;
+ continue;
+ }
+ if (SyncFWHeader.status &
+ (MBIT(6) | MBIT(7))) {
+ PRINTM(MERROR,
+ "FW received Blk with MIC error 0x%x offset\n",
+ SyncFWHeader.status,
+ SyncFWHeader.offset);
+ mic_retry--;
+ FWSeqNum = 0;
+ TotalBytes = 0;
+ ret = MLAN_STATUS_FAILURE;
+ continue;
+ }
+ } else {
+ PRINTM(MERROR,
+ "FW received Blk with CRC error 0x%x\n",
+ SyncFWHeader.cmd);
+ ret = MLAN_STATUS_FAILURE;
+ continue;
+ }
+ }
+
+ retries = MAX_FW_RETRY;
+ break;
+ }
+
+ FWSeqNum++;
+ PRINTM(MINFO, ".\n");
+
+ } while ((DnldCmd != FW_HAS_LAST_BLOCK) && retries && mic_retry);
+
+cleanup:
+ PRINTM(MMSG, "fw_dnld: %d bytes downloaded\n", TotalBytes);
+
+ if (RecvBuff)
+ pcb->moal_mfree(pmadapter->pmoal_handle, RecvBuff);
+ if (TxBuff)
+ pcb->moal_mfree(pmadapter->pmoal_handle, TxBuff);
+ if (retries && mic_retry) {
+ ret = MLAN_STATUS_SUCCESS;
+ }
+
+fw_exit:
+ LEAVE();
+ return ret;
+}
+
+/**
+ * @brief Get number of packets when deaggregated
+ *
+ * @param pmadapter A pointer to mlan_adapter
+ * @param pdata A pointer to packet data
+ * @param aggr_pkt_len Aggregate packet length
+ *
+ * @return Number of packets
+ */
+static int wlan_usb_deaggr_rx_num_pkts(pmlan_adapter pmadapter, t_u8 *pdata,
+ int aggr_pkt_len)
+{
+ int pkt_count = 0, pkt_len;
+ RxPD *prx_pd;
+
+ ENTER();
+ while (aggr_pkt_len >= sizeof(RxPD)) {
+ prx_pd = (RxPD *)pdata;
+ pkt_len = wlan_le16_to_cpu(prx_pd->rx_pkt_length) +
+ wlan_le16_to_cpu(prx_pd->rx_pkt_offset);
+ if (pkt_len == 0) /* blank RxPD can be at the end */
+ break;
+
+ ++pkt_count;
+ if (aggr_pkt_len == pkt_len) /* last packet has no padding */
+ break;
+
+ /* skip padding and goto next */
+ if (pkt_len %
+ pmadapter->pcard_usb->usb_rx_deaggr.aggr_ctrl.aggr_align)
+ pkt_len +=
+ (pmadapter->pcard_usb->usb_rx_deaggr.aggr_ctrl
+ .aggr_align -
+ (pkt_len % pmadapter->pcard_usb->usb_rx_deaggr
+ .aggr_ctrl.aggr_align));
+ aggr_pkt_len -= pkt_len;
+ pdata += pkt_len;
+ }
+ LEAVE();
+ return pkt_count;
+}
+
+static inline t_u32 usb_tx_aggr_pad_len(t_u32 len,
+ usb_tx_aggr_params *pusb_tx_aggr)
+{
+ return (len % pusb_tx_aggr->aggr_ctrl.aggr_align) ?
+ (len + (pusb_tx_aggr->aggr_ctrl.aggr_align -
+ (len % pusb_tx_aggr->aggr_ctrl.aggr_align))) :
+ len;
+}
+
+/**
+ * @brief Copy pmbuf to aggregation buffer
+ *
+ * @param pmadapter Pointer to mlan_adapter structure
+ * @param pmbuf_aggr Pointer to aggregation buffer
+ * @param pmbuf Pointer to buffer to copy
+ * @param pusb_tx_aggr Pointer to usb_tx_aggr_params
+ *
+ * @return N/A
+ */
+static inline t_void
+wlan_usb_tx_copy_buf_to_aggr(pmlan_adapter pmadapter, pmlan_buffer pmbuf_aggr,
+ pmlan_buffer pmbuf,
+ usb_tx_aggr_params *pusb_tx_aggr)
+{
+ ENTER();
+ pmbuf_aggr->data_len =
+ usb_tx_aggr_pad_len(pmbuf_aggr->data_len, pusb_tx_aggr);
+ memcpy_ext(pmadapter,
+ pmbuf_aggr->pbuf + pmbuf_aggr->data_offset +
+ pmbuf_aggr->data_len,
+ pmbuf->pbuf + pmbuf->data_offset, pmbuf->data_len,
+ pmbuf->data_len);
+ pmbuf_aggr->data_len += pmbuf->data_len;
+ LEAVE();
+}
+
+#define MLAN_TYPE_AGGR_DATA_V2 11
+/**
+ * @brief Copy pmbuf to aggregation buffer
+ *
+ * @param pmadapter Pointer to mlan_adapter structure
+ * @param pmbuf_aggr Pointer to aggregation buffer
+ * @param pmbuf Pointer to buffer to copy
+ * @param last last packet flag
+ * @param pusb_tx_aggr Pointer to usb_tx_aggr_params
+ *
+ * @return N/A
+ */
+static inline t_void
+wlan_usb_tx_copy_buf_to_aggr_v2(pmlan_adapter pmadapter,
+ pmlan_buffer pmbuf_aggr, pmlan_buffer pmbuf,
+ t_u8 last, usb_tx_aggr_params *pusb_tx_aggr)
+{
+ t_u8 *payload;
+ t_u16 offset;
+
+ ENTER();
+ pmbuf_aggr->data_len =
+ usb_tx_aggr_pad_len(pmbuf_aggr->data_len, pusb_tx_aggr);
+ memcpy_ext(pmadapter,
+ pmbuf_aggr->pbuf + pmbuf_aggr->data_offset +
+ pmbuf_aggr->data_len,
+ pmbuf->pbuf + pmbuf->data_offset, pmbuf->data_len,
+ pmbuf->data_len);
+ payload = pmbuf_aggr->pbuf + pmbuf_aggr->data_offset +
+ pmbuf_aggr->data_len;
+ if (last) {
+ offset = pmbuf->data_len;
+ *(t_u16 *)&payload[2] =
+ wlan_cpu_to_le16(MLAN_TYPE_AGGR_DATA_V2 | 0x80);
+ } else {
+ offset = usb_tx_aggr_pad_len(pmbuf->data_len, pusb_tx_aggr);
+ *(t_u16 *)&payload[2] =
+ wlan_cpu_to_le16(MLAN_TYPE_AGGR_DATA_V2);
+ }
+ *(t_u16 *)&payload[0] = wlan_cpu_to_le16(offset);
+ pmbuf_aggr->data_len += pmbuf->data_len;
+ PRINTM(MIF_D, "offset=%d len=%d\n", offset, pmbuf->data_len);
+ LEAVE();
+}
+
+/**
+ * @brief Allocate Aggregation buffer and copy pending buffers to it.
+ *
+ * @param pmadapter Pointer to mlan_adapter structure
+ * @param pusb_tx_aggr Pointer to usb_tx_aggr_params
+ *
+ * @return Aggregation buffer
+ */
+static inline pmlan_buffer
+wlan_usb_copy_buf_to_aggr(pmlan_adapter pmadapter,
+ usb_tx_aggr_params *pusb_tx_aggr)
+{
+ pmlan_buffer pmbuf_aggr = MNULL;
+ t_u8 i, use_count;
+ pmlan_buffer pmbuf_curr, pmbuf_next;
+ pmbuf_aggr = wlan_alloc_mlan_buffer(pmadapter, pusb_tx_aggr->aggr_len,
+ 0, MOAL_MALLOC_BUFFER);
+ if (pmbuf_aggr) {
+ pmbuf_curr = pusb_tx_aggr->pmbuf_aggr;
+ pmbuf_aggr->bss_index = pmbuf_curr->bss_index;
+ pmbuf_aggr->buf_type = pmbuf_curr->buf_type;
+ pmbuf_aggr->priority = pmbuf_curr->priority;
+ pmbuf_aggr->data_len = 0;
+ PRINTM(MIF_D, "use_count=%d,aggr_len=%d\n",
+ pmbuf_curr->use_count, pusb_tx_aggr->aggr_len);
+ use_count = pmbuf_curr->use_count;
+ for (i = 0; i <= use_count; i++) {
+ pmbuf_next = pmbuf_curr->pnext;
+ if (pusb_tx_aggr->aggr_ctrl.aggr_mode ==
+ MLAN_USB_AGGR_MODE_LEN_V2) {
+ if (i == use_count)
+ wlan_usb_tx_copy_buf_to_aggr_v2(
+ pmadapter, pmbuf_aggr,
+ pmbuf_curr, MTRUE,
+ pusb_tx_aggr);
+ else
+ wlan_usb_tx_copy_buf_to_aggr_v2(
+ pmadapter, pmbuf_aggr,
+ pmbuf_curr, MFALSE,
+ pusb_tx_aggr);
+ } else
+ wlan_usb_tx_copy_buf_to_aggr(pmadapter,
+ pmbuf_aggr,
+ pmbuf_curr,
+ pusb_tx_aggr);
+ pmbuf_curr = pmbuf_next;
+ }
+ DBG_HEXDUMP(MIF_D, "USB AggrTx",
+ pmbuf_aggr->pbuf + pmbuf_aggr->data_offset,
+ pmbuf_aggr->data_len);
+ }
+ return pmbuf_aggr;
+}
+
+/**
+ * @brief Link buffer into aggregate head buffer
+ *
+ * @param pmbuf_aggr Pointer to aggregation buffer
+ * @param pmbuf Pointer to buffer to add to the buffer list
+ * @param pusb_tx_aggr Pointer to usb_tx_aggr_params
+ */
+static inline t_void
+wlan_usb_tx_link_buf_to_aggr(pmlan_buffer pmbuf_aggr, pmlan_buffer pmbuf,
+ usb_tx_aggr_params *pusb_tx_aggr)
+{
+ /* link new buf at end of list */
+ pmbuf->pnext = pmbuf_aggr;
+ pmbuf->pprev = pmbuf_aggr->pprev;
+ pmbuf->pparent = pmbuf_aggr;
+ pmbuf_aggr->pprev->pnext = pmbuf;
+ pmbuf_aggr->pprev = pmbuf;
+ pmbuf_aggr->use_count++;
+ pusb_tx_aggr->aggr_len =
+ usb_tx_aggr_pad_len(pusb_tx_aggr->aggr_len, pusb_tx_aggr);
+ pusb_tx_aggr->aggr_len += pmbuf->data_len;
+}
+
+/**
+ * @brief Send aggregated buffer
+ *
+ * @param pmadapter Pointer to mlan_adapter structure
+ * @param pusb_tx_aggr Pointer to usb_tx_aggr_params
+ */
+static inline t_void wlan_usb_tx_send_aggr(pmlan_adapter pmadapter,
+ usb_tx_aggr_params *pusb_tx_aggr)
+{
+ mlan_status ret;
+ pmlan_buffer pmbuf_aggr = pusb_tx_aggr->pmbuf_aggr;
+ ENTER();
+ if (!pusb_tx_aggr->pmbuf_aggr) {
+ LEAVE();
+ return;
+ }
+
+ if (pusb_tx_aggr->pmbuf_aggr->use_count) {
+ pmbuf_aggr = wlan_usb_copy_buf_to_aggr(pmadapter, pusb_tx_aggr);
+ /* allocate new buffer for aggregation if not exist */
+ if (!pmbuf_aggr) {
+ PRINTM(MERROR,
+ "Error allocating [usb_tx] aggr mlan_buffer.\n");
+ pmadapter->dbg.num_tx_host_to_card_failure +=
+ pusb_tx_aggr->pmbuf_aggr->use_count;
+ wlan_write_data_complete(pmadapter,
+ pusb_tx_aggr->pmbuf_aggr,
+ MLAN_STATUS_FAILURE);
+ pusb_tx_aggr->pmbuf_aggr = MNULL;
+ pusb_tx_aggr->aggr_len = 0;
+ LEAVE();
+ return;
+ } else {
+ wlan_write_data_complete(pmadapter,
+ pusb_tx_aggr->pmbuf_aggr,
+ MLAN_STATUS_SUCCESS);
+ pusb_tx_aggr->pmbuf_aggr = MNULL;
+ pusb_tx_aggr->aggr_len = 0;
+ }
+ } else if (pusb_tx_aggr->aggr_ctrl.aggr_mode ==
+ MLAN_USB_AGGR_MODE_LEN_V2) {
+ t_u8 *payload = pmbuf_aggr->pbuf + pmbuf_aggr->data_offset;
+ *(t_u16 *)&payload[0] = wlan_cpu_to_le16(pmbuf_aggr->data_len);
+ *(t_u16 *)&payload[2] =
+ wlan_cpu_to_le16(MLAN_TYPE_AGGR_DATA_V2 | 0x80);
+ PRINTM(MIF_D, "USB Send single packet len=%d\n",
+ pmbuf_aggr->data_len);
+ DBG_HEXDUMP(MIF_D, "USB Tx",
+ pmbuf_aggr->pbuf + pmbuf_aggr->data_offset,
+ pmbuf_aggr->data_len);
+ }
+
+ if (pmbuf_aggr && pmbuf_aggr->data_len) {
+ pmadapter->data_sent = MTRUE;
+ ret = pmadapter->callbacks.moal_write_data_async(
+ pmadapter->pmoal_handle, pmbuf_aggr,
+ pusb_tx_aggr->port);
+ switch (ret) {
+ case MLAN_STATUS_PRESOURCE:
+ PRINTM(MINFO, "MLAN_STATUS_PRESOURCE is returned\n");
+ break;
+ case MLAN_STATUS_RESOURCE:
+ /* Shouldn't reach here due to next condition. */
+ /* TODO: (maybe) How to requeue the aggregate? */
+ /* It may occur when the pending tx urbs reach the high
+ * mark */
+ /* Thus, block further pkts for a bit */
+ PRINTM(MERROR,
+ "Error: moal_write_data_async failed: 0x%X\n",
+ ret);
+ pmadapter->dbg.num_tx_host_to_card_failure++;
+ pmbuf_aggr->status_code = MLAN_ERROR_DATA_TX_FAIL;
+ wlan_write_data_complete(pmadapter, pmbuf_aggr, ret);
+ break;
+ case MLAN_STATUS_FAILURE:
+ pmadapter->data_sent = MFALSE;
+ PRINTM(MERROR,
+ "Error: moal_write_data_async failed: 0x%X\n",
+ ret);
+ pmadapter->dbg.num_tx_host_to_card_failure++;
+ pmbuf_aggr->status_code = MLAN_ERROR_DATA_TX_FAIL;
+ wlan_write_data_complete(pmadapter, pmbuf_aggr, ret);
+ break;
+ case MLAN_STATUS_PENDING:
+ pmadapter->data_sent = MFALSE;
+ break;
+ case MLAN_STATUS_SUCCESS:
+ wlan_write_data_complete(pmadapter, pmbuf_aggr, ret);
+ break;
+ default:
+ break;
+ }
+
+ /* aggr_buf now sent to bus, prevent others from using it */
+ pusb_tx_aggr->pmbuf_aggr = MNULL;
+ pusb_tx_aggr->aggr_len = 0;
+ }
+ LEAVE();
+}
+
+/********************************************************
+ Global Functions
+********************************************************/
+
+/**
+ * @brief This function get pcie device from card type
+ *
+ * @param pmadapter A pointer to mlan_adapter structure
+ * @return MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ */
+mlan_status wlan_get_usb_device(pmlan_adapter pmadapter)
+{
+ mlan_status ret = MLAN_STATUS_SUCCESS;
+ t_u16 card_type = pmadapter->card_type;
+
+ ENTER();
+
+ ret = pmadapter->callbacks.moal_malloc(pmadapter->pmoal_handle,
+ sizeof(mlan_usb_card),
+ MLAN_MEM_DEF,
+ (t_u8 **)&pmadapter->pcard_usb);
+ if (ret != MLAN_STATUS_SUCCESS || !pmadapter->pcard_usb) {
+ PRINTM(MERROR, "Failed to allocate pcard_usb\n");
+ LEAVE();
+ return MLAN_STATUS_FAILURE;
+ }
+
+ switch (card_type) {
+#ifdef USB8897
+ case CARD_TYPE_USB8897:
+ pmadapter->pcard_info = &mlan_card_info_usb8897;
+ break;
+#endif
+#ifdef USB8997
+ case CARD_TYPE_USB8997:
+ pmadapter->pcard_info = &mlan_card_info_usb8997;
+ break;
+#endif
+#ifdef USB8978
+ case CARD_TYPE_USB8978:
+ pmadapter->pcard_info = &mlan_card_info_usb8978;
+ break;
+#endif
+#ifdef USB9098
+ case CARD_TYPE_USB9098:
+ pmadapter->pcard_info = &mlan_card_info_usb9098;
+ break;
+#endif
+#ifdef USB9097
+ case CARD_TYPE_USB9097:
+ pmadapter->pcard_info = &mlan_card_info_usb9097;
+ break;
+#endif
+ default:
+ PRINTM(MERROR, "can't get right USB card type \n");
+ ret = MLAN_STATUS_FAILURE;
+ break;
+ }
+
+ LEAVE();
+ return ret;
+}
+
+/**
+ * @brief This function downloads firmware to card
+ *
+ * @param pmadapter A pointer to mlan_adapter
+ * @param pmfw A pointer to firmware image
+ *
+ * @return MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ */
+mlan_status wlan_usb_dnld_fw(pmlan_adapter pmadapter, pmlan_fw_image pmfw)
+{
+ mlan_status ret = MLAN_STATUS_SUCCESS;
+
+ ENTER();
+
+ ret = wlan_usb_prog_fw_w_helper(pmadapter, pmfw);
+ if (ret != MLAN_STATUS_SUCCESS) {
+ LEAVE();
+ return MLAN_STATUS_FAILURE;
+ }
+
+ LEAVE();
+ return ret;
+}
+
+/**
+ * @brief This function deaggregates USB RX Data Packet from device
+ *
+ * @param pmadapter A pointer to mlan_adapter
+ * @param pmbuf A pointer to the received buffer
+ *
+ * @return MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ */
+mlan_status wlan_usb_deaggr_rx_pkt(pmlan_adapter pmadapter, pmlan_buffer pmbuf)
+{
+ const t_u8 zero_rx_pd[sizeof(RxPD)] = {0};
+ mlan_status ret = MLAN_STATUS_SUCCESS;
+ t_u32 curr_pkt_len;
+ RxPD *prx_pd;
+ t_u8 *pdata;
+ t_s32 aggr_len;
+ pmlan_buffer pdeaggr_buf;
+
+ ENTER();
+
+ pdata = pmbuf->pbuf + pmbuf->data_offset;
+ prx_pd = (RxPD *)pdata;
+ curr_pkt_len = wlan_le16_to_cpu(prx_pd->rx_pkt_length) +
+ wlan_le16_to_cpu(prx_pd->rx_pkt_offset);
+ /* if non-aggregate, just send through, don’t process here */
+ aggr_len = pmbuf->data_len;
+ if ((aggr_len == curr_pkt_len) ||
+ (wlan_usb_deaggr_rx_num_pkts(pmadapter, pdata, aggr_len) == 1) ||
+ (pmadapter->pcard_usb->usb_rx_deaggr.aggr_ctrl.enable != MTRUE)) {
+ ret = wlan_handle_rx_packet(pmadapter, pmbuf);
+ LEAVE();
+ return ret;
+ }
+
+ while (aggr_len >= sizeof(RxPD)) {
+ /* check for (all-zeroes) termination RxPD */
+ if (!memcmp(pmadapter, pdata, zero_rx_pd, sizeof(RxPD))) {
+ break;
+ }
+
+ /* make new buffer and copy packet to it (including RxPD).
+ * Also, reserve headroom so that there must have space
+ * to change RxPD to TxPD for bridge packet in uAP mode */
+ pdeaggr_buf = wlan_alloc_mlan_buffer(pmadapter, curr_pkt_len,
+ MLAN_RX_HEADER_LEN,
+ MOAL_ALLOC_MLAN_BUFFER);
+ if (pdeaggr_buf == MNULL) {
+ PRINTM(MERROR,
+ "Error allocating [usb_rx] deaggr mlan_buffer\n");
+ ret = MLAN_STATUS_FAILURE;
+ break;
+ }
+ pdeaggr_buf->bss_index = pmbuf->bss_index;
+ pdeaggr_buf->buf_type = pmbuf->buf_type;
+ pdeaggr_buf->data_len = curr_pkt_len;
+ pdeaggr_buf->in_ts_sec = pmbuf->in_ts_sec;
+ pdeaggr_buf->in_ts_usec = pmbuf->in_ts_usec;
+ pdeaggr_buf->priority = pmbuf->priority;
+ memcpy_ext(pmadapter,
+ pdeaggr_buf->pbuf + pdeaggr_buf->data_offset, pdata,
+ curr_pkt_len, pdeaggr_buf->data_len);
+
+ /* send new packet to processing */
+ ret = wlan_handle_rx_packet(pmadapter, pdeaggr_buf);
+ if (ret == MLAN_STATUS_FAILURE) {
+ break;
+ }
+ /* last block has no padding bytes */
+ if (aggr_len == curr_pkt_len) {
+ break;
+ }
+
+ /* round up to next block boundary */
+ if (curr_pkt_len %
+ pmadapter->pcard_usb->usb_rx_deaggr.aggr_ctrl.aggr_align)
+ curr_pkt_len += (pmadapter->pcard_usb->usb_rx_deaggr
+ .aggr_ctrl.aggr_align -
+ (curr_pkt_len %
+ pmadapter->pcard_usb->usb_rx_deaggr
+ .aggr_ctrl.aggr_align));
+ /* point to next packet */
+ aggr_len -= curr_pkt_len;
+ pdata += curr_pkt_len;
+ prx_pd = (RxPD *)pdata;
+ curr_pkt_len = wlan_le16_to_cpu(prx_pd->rx_pkt_length) +
+ wlan_le16_to_cpu(prx_pd->rx_pkt_offset);
+ }
+
+ /* free original pmbuf (since not sent for processing) */
+ pmadapter->callbacks.moal_recv_complete(pmadapter->pmoal_handle, pmbuf,
+ pmadapter->rx_data_ep, ret);
+ LEAVE();
+ return ret;
+}
+
+/**
+ * @brief This function restore tx_pause flag
+ *
+ * @param pmadapter A pointer to mlan_adapter structure
+ * @param pusb_tx_aggr A pointer to usb_tx_aggr_params
+ *
+ * @return MTRUE/MFALSE
+ */
+t_u8 wlan_is_port_tx_paused(pmlan_adapter pmadapter,
+ usb_tx_aggr_params *pusb_tx_aggr)
+{
+ mlan_private *pmpriv = MNULL;
+ t_u8 i;
+ t_u8 ret = MFALSE;
+ for (i = 0; i < pmadapter->priv_num; i++) {
+ pmpriv = pmadapter->priv[i];
+ if (pmpriv && pmpriv->tx_pause &&
+ (pmpriv->port == pusb_tx_aggr->port)) {
+ ret = MTRUE;
+ break;
+ }
+ }
+ return ret;
+}
+
+/**
+ * @brief This function handles the timeout of usb tx aggregation.
+ * It will send the aggregate buffer being held.
+ *
+ * @param function_context A pointer to function_context
+ * @return N/A
+ */
+t_void wlan_usb_tx_aggr_timeout_func(t_void *function_context)
+{
+ usb_tx_aggr_params *pusb_tx_aggr =
+ (usb_tx_aggr_params *)function_context;
+ pmlan_adapter pmadapter = (mlan_adapter *)pusb_tx_aggr->phandle;
+ pmlan_callbacks pcb = &pmadapter->callbacks;
+
+ ENTER();
+ pcb->moal_spin_lock(pmadapter->pmoal_handle, pusb_tx_aggr->paggr_lock);
+ pusb_tx_aggr->aggr_hold_timer_is_set = MFALSE;
+ if (pusb_tx_aggr->pmbuf_aggr && !pmadapter->data_sent &&
+ !wlan_is_port_tx_paused(pmadapter, pusb_tx_aggr))
+ wlan_usb_tx_send_aggr(pmadapter, pusb_tx_aggr);
+ pcb->moal_spin_unlock(pmadapter->pmoal_handle,
+ pusb_tx_aggr->paggr_lock);
+ LEAVE();
+}
+
+/**
+ * @brief This function aggregates USB TX Data Packet to send to device
+ *
+ * @param pmadapter A pointer to mlan_adapter
+ * @param pmbuf A pointer to the transmit buffer
+ * @param tx_param A pointer to mlan_tx_param
+ * @param pusb_tx_aggr A pointer to usb_tx_aggr_params
+ *
+ * @return MLAN_STATUS_PENDING or MLAN_STATUS_FAILURE
+ */
+/*
+ * Non Scatter-Gather code creates a new large buffer where each incoming
+ * buffer's data contents are copied to (aligned to USB boundaries).
+ * The individual buffers are ALSO linked to the large buffer,
+ * in order to handle complete AFTER the aggregate is sent.
+ * pmbuf_aggr->data_len is used to keep track of bytes aggregated so far.
+ */
+mlan_status wlan_usb_host_to_card_aggr(pmlan_adapter pmadapter,
+ pmlan_buffer pmbuf,
+ mlan_tx_param *tx_param,
+ usb_tx_aggr_params *pusb_tx_aggr)
+{
+ pmlan_callbacks pcb = &pmadapter->callbacks;
+ pmlan_buffer pmbuf_aggr;
+ mlan_status ret = MLAN_STATUS_PENDING;
+ t_u32 next_pkt_len = (tx_param) ? tx_param->next_pkt_len : 0;
+ t_u32 aggr_len_counter = 0;
+ /* indicators */
+ t_u8 f_precopy_cur_buf = 0;
+ t_u8 f_send_aggr_buf = 0;
+ t_u8 f_postcopy_cur_buf = 0;
+ t_u32 max_aggr_size = 0, max_aggr_num = 0;
+
+ ENTER();
+
+ pcb->moal_spin_lock(pmadapter->pmoal_handle, pusb_tx_aggr->paggr_lock);
+
+ /* stop timer while we process */
+ if (pusb_tx_aggr->aggr_hold_timer_is_set) {
+ pcb->moal_stop_timer(pmadapter->pmoal_handle,
+ pusb_tx_aggr->paggr_hold_timer);
+ pusb_tx_aggr->aggr_hold_timer_is_set = MFALSE;
+ }
+
+ pmbuf_aggr = pusb_tx_aggr->pmbuf_aggr;
+
+ if (pusb_tx_aggr->aggr_ctrl.aggr_tmo == MLAN_USB_TX_AGGR_TIMEOUT_DYN) {
+ if (!pmbuf_aggr) {
+ /* Start aggr from min timeout value in micro sec */
+ pusb_tx_aggr->hold_timeout_msec =
+ MLAN_USB_TX_MIN_AGGR_TIMEOUT;
+ } else {
+ /* Increase timeout in milisecond if pkts are
+ * consecutive */
+ if (pusb_tx_aggr->hold_timeout_msec <
+ MLAN_USB_TX_MAX_AGGR_TIMEOUT)
+ pusb_tx_aggr->hold_timeout_msec++;
+ }
+ } else {
+ if (pusb_tx_aggr->aggr_ctrl.aggr_tmo)
+ pusb_tx_aggr->hold_timeout_msec =
+ pusb_tx_aggr->aggr_ctrl.aggr_tmo / 1000;
+ }
+
+ max_aggr_size = max_aggr_num = pusb_tx_aggr->aggr_ctrl.aggr_max;
+ if (pusb_tx_aggr->aggr_ctrl.aggr_mode == MLAN_USB_AGGR_MODE_NUM) {
+ max_aggr_size *= MAX(MLAN_USB_MAX_PKT_SIZE,
+ pusb_tx_aggr->aggr_ctrl.aggr_align);
+ }
+ if (pusb_tx_aggr->aggr_ctrl.aggr_mode == MLAN_USB_AGGR_MODE_LEN)
+ max_aggr_num /= pusb_tx_aggr->aggr_ctrl.aggr_align;
+ else if (pusb_tx_aggr->aggr_ctrl.aggr_mode == MLAN_USB_AGGR_MODE_LEN_V2)
+ max_aggr_num = MLAN_USB_TX_AGGR_MAX_NUM;
+ if (!pmbuf_aggr) {
+ /* use this buf to start linked list, that's it */
+ pmbuf->pnext = pmbuf->pprev = pmbuf;
+ pmbuf_aggr = pmbuf;
+ pusb_tx_aggr->pmbuf_aggr = pmbuf_aggr;
+ pusb_tx_aggr->aggr_len = pmbuf->data_len;
+ pmbuf->flags |= MLAN_BUF_FLAG_USB_TX_AGGR;
+
+ } else {
+ /* DECIDE what to do */
+ aggr_len_counter = usb_tx_aggr_pad_len(pusb_tx_aggr->aggr_len,
+ pusb_tx_aggr);
+
+ if ((aggr_len_counter + pmbuf->data_len) < max_aggr_size) {
+ f_precopy_cur_buf = 1; /* can fit current packet in aggr
+ */
+ if (next_pkt_len) {
+ aggr_len_counter += usb_tx_aggr_pad_len(
+ pmbuf->data_len, pusb_tx_aggr);
+ if ((aggr_len_counter + next_pkt_len) >=
+ max_aggr_size)
+ f_send_aggr_buf = 1; /* can't fit next
+ packet, send now
+ */
+ }
+ } else {
+ /* can't fit current packet */
+ if (pusb_tx_aggr->aggr_len)
+ f_send_aggr_buf = 1; /* send aggr first */
+ f_postcopy_cur_buf = 1; /* then copy into new aggr_buf
+ */
+ }
+ }
+
+ /* For zero timeout and zero next packet length send pkt now */
+ if (!pusb_tx_aggr->aggr_ctrl.aggr_tmo && !next_pkt_len)
+ f_send_aggr_buf = 1;
+
+ /* PERFORM ACTIONS as decided */
+ if (f_precopy_cur_buf) {
+ PRINTM(MIF_D, "%s: Precopy current buffer.\n", __FUNCTION__);
+ wlan_usb_tx_link_buf_to_aggr(pmbuf_aggr, pmbuf, pusb_tx_aggr);
+ }
+ if (pmbuf_aggr->use_count + 1 >= max_aggr_num)
+ f_send_aggr_buf = 1;
+
+ if (pmbuf->flags & MLAN_BUF_FLAG_NULL_PKT ||
+ pmbuf->flags & MLAN_BUF_FLAG_TCP_ACK)
+ f_send_aggr_buf = 1;
+
+ if (f_send_aggr_buf) {
+ PRINTM(MIF_D, "%s: Send aggregate buffer.\n", __FUNCTION__);
+ wlan_usb_tx_send_aggr(pmadapter, pusb_tx_aggr);
+ pmbuf_aggr = pusb_tx_aggr->pmbuf_aggr; /* update ptr */
+ }
+
+ if (f_postcopy_cur_buf) {
+ PRINTM(MIF_D, "%s: Postcopy current buffer.\n", __FUNCTION__);
+ if (!pmbuf_aggr) { /* this is possible if just sent (above) */
+ /* use this buf to start linked list */
+ pmbuf->pnext = pmbuf->pprev = pmbuf;
+ pmbuf_aggr = pmbuf;
+ pusb_tx_aggr->pmbuf_aggr = pmbuf_aggr;
+ pusb_tx_aggr->aggr_len = pmbuf->data_len;
+ pmbuf->flags |= MLAN_BUF_FLAG_USB_TX_AGGR;
+ }
+ }
+ /* (re)start timer if there is something in the aggregation buffer */
+ if (pmbuf_aggr && pmbuf_aggr->data_len) {
+ if (pusb_tx_aggr->aggr_ctrl.aggr_tmo) {
+ pcb->moal_start_timer(pmadapter->pmoal_handle,
+ pusb_tx_aggr->paggr_hold_timer,
+ MFALSE,
+ pusb_tx_aggr->hold_timeout_msec);
+ pusb_tx_aggr->aggr_hold_timer_is_set = MTRUE;
+ }
+ }
+
+ pcb->moal_spin_unlock(pmadapter->pmoal_handle,
+ pusb_tx_aggr->paggr_lock);
+ LEAVE();
+ return ret;
+}
+
+/**
+ * @brief This function wakes up the card.
+ *
+ * @param pmadapter A pointer to mlan_adapter structure
+ * @param timeout set timeout flag
+ *
+ * @return MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ */
+mlan_status wlan_pm_usb_wakeup_card(pmlan_adapter pmadapter, t_u8 timeout)
+{
+ mlan_status ret = MLAN_STATUS_SUCCESS;
+ t_u32 age_ts_usec;
+
+ ENTER();
+ PRINTM(MEVENT, "Wakeup device...\n");
+ pmadapter->callbacks.moal_get_system_time(pmadapter->pmoal_handle,
+ &pmadapter->pm_wakeup_in_secs,
+ &age_ts_usec);
+
+ /* Simulation of HS_AWAKE event */
+ pmadapter->pm_wakeup_fw_try = MFALSE;
+ pmadapter->pm_wakeup_card_req = MFALSE;
+ /* TODO USB suspend/resume */
+ pmadapter->ps_state = PS_STATE_AWAKE;
+ LEAVE();
+ return ret;
+}
+
+/**
+ * @brief 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.
+ *
+ * @param pmpriv A pointer to pmlan_private structure
+ * @param type data or command
+ * @param pmbuf A pointer to mlan_buffer (pmbuf->data_len should include
+ * PCIE header)
+ * @param tx_param A pointer to mlan_tx_param (can be MNULL if type is
+ * command)
+ *
+ * @return MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ */
+mlan_status wlan_usb_host_to_card(pmlan_private pmpriv, t_u8 type,
+ mlan_buffer *pmbuf, mlan_tx_param *tx_param)
+{
+ mlan_status ret = MLAN_STATUS_SUCCESS;
+ usb_tx_aggr_params *pusb_tx_aggr = MNULL;
+ pmlan_adapter pmadapter = pmpriv->adapter;
+
+ ENTER();
+
+ if (!pmbuf) {
+ PRINTM(MERROR, "Passed NULL pmbuf to %s\n", __FUNCTION__);
+ return MLAN_STATUS_FAILURE;
+ }
+ if (type == MLAN_TYPE_CMD
+#if (defined(USB9098) || defined(USB9097))
+ || type == MLAN_TYPE_VDLL
+#endif
+ ) {
+ pmadapter->cmd_sent = MTRUE;
+ ret = pmadapter->callbacks.moal_write_data_async(
+ pmadapter->pmoal_handle, pmbuf, pmadapter->tx_cmd_ep);
+ if (ret == MLAN_STATUS_FAILURE)
+ pmadapter->cmd_sent = MFALSE;
+ LEAVE();
+ return ret;
+ }
+ pusb_tx_aggr = wlan_get_usb_tx_aggr_params(pmadapter, pmpriv->port);
+ if (pusb_tx_aggr) {
+ ret = wlan_usb_host_to_card_aggr(pmadapter, pmbuf, tx_param,
+ pusb_tx_aggr);
+ } else {
+ pmadapter->data_sent = MTRUE;
+ ret = pmadapter->callbacks.moal_write_data_async(
+ pmadapter->pmoal_handle, pmbuf, pmpriv->port);
+ switch (ret) {
+ case MLAN_STATUS_PRESOURCE:
+ PRINTM(MINFO, "MLAN_STATUS_PRESOURCE is returned\n");
+ break;
+ case MLAN_STATUS_RESOURCE:
+
+ break;
+ case MLAN_STATUS_FAILURE:
+ pmadapter->data_sent = MFALSE;
+ break;
+ case MLAN_STATUS_PENDING:
+ pmadapter->data_sent = MFALSE;
+ break;
+ case MLAN_STATUS_SUCCESS:
+ break;
+ default:
+ break;
+ }
+ }
+
+ LEAVE();
+ return ret;
+}
+
+/**
+ * @brief This function handle event/cmd complete
+ *
+ * @param pmadapter A pointer to mlan_adapter structure
+ * @param pmbuf A pointer to the mlan_buffer
+ * @return N/A
+ */
+mlan_status wlan_usb_cmdevt_complete(pmlan_adapter pmadapter,
+ mlan_buffer *pmbuf, mlan_status status)
+{
+ ENTER();
+
+ pmadapter->callbacks.moal_recv_complete(pmadapter->pmoal_handle, pmbuf,
+ pmadapter->rx_cmd_ep, status);
+
+ LEAVE();
+ return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ * @brief This function handle data complete
+ *
+ * @param pmadapter A pointer to mlan_adapter structure
+ * @param pmbuf A pointer to the mlan_buffer
+ * @return N/A
+ */
+mlan_status wlan_usb_data_complete(pmlan_adapter pmadapter, mlan_buffer *pmbuf,
+ mlan_status status)
+{
+ ENTER();
+
+ pmadapter->callbacks.moal_recv_complete(pmadapter->pmoal_handle, pmbuf,
+ pmadapter->rx_data_ep, status);
+
+ LEAVE();
+ return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ * @brief This function handle receive packet
+ *
+ * @param pmadapter A pointer to mlan_adapter structure
+ * @param pmbuf A pointer to the mlan_buffer
+ * @return
+ */
+mlan_status wlan_usb_handle_rx_packet(mlan_adapter *pmadapter,
+ pmlan_buffer pmbuf)
+{
+ ENTER();
+
+ if (pmadapter->pcard_usb->usb_rx_deaggr.aggr_ctrl.enable == MTRUE)
+ return wlan_usb_deaggr_rx_pkt(pmadapter, pmbuf);
+ else
+ return wlan_handle_rx_packet(pmadapter, pmbuf);
+
+ LEAVE();
+}
+
+mlan_adapter_operations mlan_usb_ops = {
+ .dnld_fw = wlan_usb_dnld_fw,
+ .host_to_card = wlan_usb_host_to_card,
+ .wakeup_card = wlan_pm_usb_wakeup_card,
+ .event_complete = wlan_usb_cmdevt_complete,
+ .data_complete = wlan_usb_data_complete,
+ .cmdrsp_complete = wlan_usb_cmdevt_complete,
+ .handle_rx_packet = wlan_usb_handle_rx_packet,
+
+ .intf_header_len = USB_INTF_HEADER_LEN,
+};
diff --git a/drivers/net/wireless/nxp/mxm_wifiex/wlan_src/mlan/mlan_util.h b/drivers/net/wireless/nxp/mxm_wifiex/wlan_src/mlan/mlan_util.h
new file mode 100644
index 000000000000..c86269e2b155
--- /dev/null
+++ b/drivers/net/wireless/nxp/mxm_wifiex/wlan_src/mlan/mlan_util.h
@@ -0,0 +1,492 @@
+/** @file mlan_util.h
+ *
+ * @brief This file contains wrappers for linked-list,
+ * spinlock and timer defines.
+ *
+ *
+ * Copyright 2014-2020 NXP
+ *
+ * This software file (the File) is distributed by NXP
+ * under the terms of the GNU General Public License Version 2, June 1991
+ * (the License). You may use, redistribute and/or modify the 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.
+ *
+ */
+
+/******************************************************
+Change log:
+ 10/28/2008: initial version
+******************************************************/
+
+#ifndef _MLAN_UTIL_H_
+#define _MLAN_UTIL_H_
+
+/** Circular doubly linked list */
+typedef struct _mlan_linked_list {
+ /** Pointer to previous node */
+ struct _mlan_linked_list *pprev;
+ /** Pointer to next node */
+ struct _mlan_linked_list *pnext;
+} mlan_linked_list, *pmlan_linked_list;
+
+/** List head */
+typedef struct _mlan_list_head {
+ /** Pointer to previous node */
+ struct _mlan_linked_list *pprev;
+ /** Pointer to next node */
+ struct _mlan_linked_list *pnext;
+ /** Pointer to lock */
+ t_void *plock;
+} mlan_list_head, *pmlan_list_head;
+
+/**
+ * @brief This function initializes a list without locking
+ *
+ * @param phead List head
+ *
+ * @return N/A
+ */
+static INLINE t_void util_init_list(pmlan_linked_list phead)
+{
+ /* Both next and prev point to self */
+ phead->pprev = phead->pnext = (pmlan_linked_list)phead;
+}
+
+/**
+ * @brief This function initializes a list
+ *
+ * @param phead List head
+ * @param lock_required A flag for spinlock requirement
+ * @param moal_init_lock A pointer to init lock handler
+ *
+ * @return N/A
+ */
+static INLINE t_void util_init_list_head(
+ t_void *pmoal_handle, pmlan_list_head phead, t_u8 lock_required,
+ mlan_status (*moal_init_lock)(t_void *handle, t_void **pplock))
+{
+ /* Both next and prev point to self */
+ util_init_list((pmlan_linked_list)phead);
+ if (lock_required)
+ moal_init_lock(pmoal_handle, &phead->plock);
+ else
+ phead->plock = 0;
+}
+
+/**
+ * @brief This function frees a list
+ *
+ * @param phead List head
+ * @param moal_free_lock A pointer to free lock handler
+ *
+ * @return N/A
+ */
+static INLINE t_void util_free_list_head(
+ t_void *pmoal_handle, pmlan_list_head phead,
+ mlan_status (*moal_free_lock)(t_void *handle, t_void *plock))
+{
+ phead->pprev = phead->pnext = 0;
+ if (phead->plock)
+ moal_free_lock(pmoal_handle, phead->plock);
+}
+
+/**
+ * @brief This function peeks into a list
+ *
+ * @param phead List head
+ * @param moal_spin_lock A pointer to spin lock handler
+ * @param moal_spin_unlock A pointer to spin unlock handler
+ *
+ * @return List node
+ */
+static INLINE pmlan_linked_list
+util_peek_list(t_void *pmoal_handle, pmlan_list_head phead,
+ mlan_status (*moal_spin_lock)(t_void *handle, t_void *plock),
+ mlan_status (*moal_spin_unlock)(t_void *handle, t_void *plock))
+{
+ pmlan_linked_list pnode = 0;
+
+ if (moal_spin_lock)
+ moal_spin_lock(pmoal_handle, phead->plock);
+ if (phead->pnext != (pmlan_linked_list)phead)
+ pnode = phead->pnext;
+ if (moal_spin_unlock)
+ moal_spin_unlock(pmoal_handle, phead->plock);
+ return pnode;
+}
+
+/**
+ * @brief This function queues a node at the list tail
+ *
+ * @param phead List head
+ * @param pnode List node to queue
+ * @param moal_spin_lock A pointer to spin lock handler
+ * @param moal_spin_unlock A pointer to spin unlock handler
+ *
+ * @return N/A
+ */
+static INLINE t_void util_enqueue_list_tail(
+ t_void *pmoal_handle, pmlan_list_head phead, pmlan_linked_list pnode,
+ mlan_status (*moal_spin_lock)(t_void *handle, t_void *plock),
+ mlan_status (*moal_spin_unlock)(t_void *handle, t_void *plock))
+{
+ pmlan_linked_list pold_last;
+
+ if (moal_spin_lock)
+ moal_spin_lock(pmoal_handle, phead->plock);
+ pold_last = phead->pprev;
+ pnode->pprev = pold_last;
+ pnode->pnext = (pmlan_linked_list)phead;
+
+ phead->pprev = pold_last->pnext = pnode;
+ if (moal_spin_unlock)
+ moal_spin_unlock(pmoal_handle, phead->plock);
+}
+
+/**
+ * @brief This function adds a node at the list head
+ *
+ * @param phead List head
+ * @param pnode List node to add
+ * @param moal_spin_lock A pointer to spin lock handler
+ * @param moal_spin_unlock A pointer to spin unlock handler
+ *
+ * @return N/A
+ */
+static INLINE t_void util_enqueue_list_head(
+ t_void *pmoal_handle, pmlan_list_head phead, pmlan_linked_list pnode,
+ mlan_status (*moal_spin_lock)(t_void *handle, t_void *plock),
+ mlan_status (*moal_spin_unlock)(t_void *handle, t_void *plock))
+{
+ pmlan_linked_list pold_first;
+
+ if (moal_spin_lock)
+ moal_spin_lock(pmoal_handle, phead->plock);
+ pold_first = phead->pnext;
+ pnode->pprev = (pmlan_linked_list)phead;
+ pnode->pnext = pold_first;
+
+ phead->pnext = pold_first->pprev = pnode;
+ if (moal_spin_unlock)
+ moal_spin_unlock(pmoal_handle, phead->plock);
+}
+
+/**
+ * @brief This function removes a node from the list
+ *
+ * @param phead List head
+ * @param pnode List node to remove
+ * @param moal_spin_lock A pointer to spin lock handler
+ * @param moal_spin_unlock A pointer to spin unlock handler
+ *
+ * @return N/A
+ */
+static INLINE t_void util_unlink_list(
+ t_void *pmoal_handle, pmlan_list_head phead, pmlan_linked_list pnode,
+ mlan_status (*moal_spin_lock)(t_void *handle, t_void *plock),
+ mlan_status (*moal_spin_unlock)(t_void *handle, t_void *plock))
+{
+ pmlan_linked_list pmy_prev;
+ pmlan_linked_list pmy_next;
+
+ if (moal_spin_lock)
+ moal_spin_lock(pmoal_handle, phead->plock);
+ pmy_prev = pnode->pprev;
+ pmy_next = pnode->pnext;
+ pmy_next->pprev = pmy_prev;
+ pmy_prev->pnext = pmy_next;
+
+ pnode->pnext = pnode->pprev = 0;
+ if (moal_spin_unlock)
+ moal_spin_unlock(pmoal_handle, phead->plock);
+}
+
+/**
+ * @brief This function dequeues a node from the list
+ *
+ * @param phead List head
+ * @param moal_spin_lock A pointer to spin lock handler
+ * @param moal_spin_unlock A pointer to spin unlock handler
+ *
+ * @return List node
+ */
+static INLINE pmlan_linked_list util_dequeue_list(
+ t_void *pmoal_handle, pmlan_list_head phead,
+ mlan_status (*moal_spin_lock)(t_void *handle, t_void *plock),
+ mlan_status (*moal_spin_unlock)(t_void *handle, t_void *plock))
+{
+ pmlan_linked_list pnode;
+
+ if (moal_spin_lock)
+ moal_spin_lock(pmoal_handle, phead->plock);
+ pnode = phead->pnext;
+ if (pnode && (pnode != (pmlan_linked_list)phead))
+ util_unlink_list(pmoal_handle, phead, pnode, 0, 0);
+ else
+ pnode = 0;
+ if (moal_spin_unlock)
+ moal_spin_unlock(pmoal_handle, phead->plock);
+ return pnode;
+}
+
+/** Access controlled scalar variable */
+typedef struct _mlan_scalar {
+ /** Value */
+ t_s32 value;
+ /** Pointer to lock */
+ t_void *plock;
+ /** Control flags */
+ t_u32 flags;
+} mlan_scalar, *pmlan_scalar;
+
+/** Flag to scalar lock acquired */
+#define MLAN_SCALAR_FLAG_UNIQUE_LOCK MBIT(16)
+
+/** scalar conditional value list */
+typedef enum _MLAN_SCALAR_CONDITIONAL {
+ MLAN_SCALAR_COND_EQUAL,
+ MLAN_SCALAR_COND_NOT_EQUAL,
+ MLAN_SCALAR_COND_GREATER_THAN,
+ MLAN_SCALAR_COND_GREATER_OR_EQUAL,
+ MLAN_SCALAR_COND_LESS_THAN,
+ MLAN_SCALAR_COND_LESS_OR_EQUAL
+} MLAN_SCALAR_CONDITIONAL;
+
+/**
+ * @brief This function initializes a scalar
+ *
+ * @param pscalar Pointer to scalar
+ * @param val Initial scalar value
+ * @param plock_to_use A new lock is created if NULL, else lock to use
+ * @param moal_init_lock A pointer to init lock handler
+ *
+ * @return N/A
+ */
+static INLINE t_void
+util_scalar_init(t_void *pmoal_handle, pmlan_scalar pscalar, t_s32 val,
+ t_void *plock_to_use,
+ mlan_status (*moal_init_lock)(t_void *handle, t_void **pplock))
+{
+ pscalar->value = val;
+ pscalar->flags = 0;
+ if (plock_to_use) {
+ pscalar->flags &= ~MLAN_SCALAR_FLAG_UNIQUE_LOCK;
+ pscalar->plock = plock_to_use;
+ } else {
+ pscalar->flags |= MLAN_SCALAR_FLAG_UNIQUE_LOCK;
+ moal_init_lock(pmoal_handle, &pscalar->plock);
+ }
+}
+
+/**
+ * @brief This function frees a scalar
+ *
+ * @param pscalar Pointer to scalar
+ * @param moal_free_lock A pointer to free lock handler
+ *
+ * @return N/A
+ */
+static INLINE t_void
+util_scalar_free(t_void *pmoal_handle, pmlan_scalar pscalar,
+ mlan_status (*moal_free_lock)(t_void *handle, t_void *plock))
+{
+ if (pscalar->flags & MLAN_SCALAR_FLAG_UNIQUE_LOCK)
+ moal_free_lock(pmoal_handle, pscalar->plock);
+}
+
+/**
+ * @brief This function reads value from scalar
+ *
+ * @param pscalar Pointer to scalar
+ * @param moal_spin_lock A pointer to spin lock handler
+ * @param moal_spin_unlock A pointer to spin unlock handler
+ *
+ * @return Stored value
+ */
+static INLINE t_s32
+util_scalar_read(t_void *pmoal_handle, pmlan_scalar pscalar,
+ mlan_status (*moal_spin_lock)(t_void *handle, t_void *plock),
+ mlan_status (*moal_spin_unlock)(t_void *handle, t_void *plock))
+{
+ t_s32 val;
+
+ if (moal_spin_lock)
+ moal_spin_lock(pmoal_handle, pscalar->plock);
+ val = pscalar->value;
+ if (moal_spin_unlock)
+ moal_spin_unlock(pmoal_handle, pscalar->plock);
+
+ return val;
+}
+
+/**
+ * @brief This function writes value to scalar
+ *
+ * @param pscalar Pointer to scalar
+ * @param val Value to write
+ * @param moal_spin_lock A pointer to spin lock handler
+ * @param moal_spin_unlock A pointer to spin unlock handler
+ *
+ * @return N/A
+ */
+static INLINE t_void util_scalar_write(
+ t_void *pmoal_handle, pmlan_scalar pscalar, t_s32 val,
+ mlan_status (*moal_spin_lock)(t_void *handle, t_void *plock),
+ mlan_status (*moal_spin_unlock)(t_void *handle, t_void *plock))
+{
+ if (moal_spin_lock)
+ moal_spin_lock(pmoal_handle, pscalar->plock);
+ pscalar->value = val;
+ if (moal_spin_unlock)
+ moal_spin_unlock(pmoal_handle, pscalar->plock);
+}
+
+/**
+ * @brief This function increments the value in scalar
+ *
+ * @param pscalar Pointer to scalar
+ * @param moal_spin_lock A pointer to spin lock handler
+ * @param moal_spin_unlock A pointer to spin unlock handler
+ *
+ * @return N/A
+ */
+static INLINE t_void util_scalar_increment(
+ t_void *pmoal_handle, pmlan_scalar pscalar,
+ mlan_status (*moal_spin_lock)(t_void *handle, t_void *plock),
+ mlan_status (*moal_spin_unlock)(t_void *handle, t_void *plock))
+{
+ if (moal_spin_lock)
+ moal_spin_lock(pmoal_handle, pscalar->plock);
+ pscalar->value++;
+ if (moal_spin_unlock)
+ moal_spin_unlock(pmoal_handle, pscalar->plock);
+}
+
+/**
+ * @brief This function decrements the value in scalar
+ *
+ * @param pscalar Pointer to scalar
+ * @param moal_spin_lock A pointer to spin lock handler
+ * @param moal_spin_unlock A pointer to spin unlock handler
+ *
+ * @return N/A
+ */
+static INLINE t_void util_scalar_decrement(
+ t_void *pmoal_handle, pmlan_scalar pscalar,
+ mlan_status (*moal_spin_lock)(t_void *handle, t_void *plock),
+ mlan_status (*moal_spin_unlock)(t_void *handle, t_void *plock))
+{
+ if (moal_spin_lock)
+ moal_spin_lock(pmoal_handle, pscalar->plock);
+ pscalar->value--;
+ if (moal_spin_unlock)
+ moal_spin_unlock(pmoal_handle, pscalar->plock);
+}
+
+/**
+ * @brief This function adds an offset to the value in scalar,
+ * and returns the new value
+ *
+ * @param pscalar Pointer to scalar
+ * @param offset Offset value (can be negative)
+ * @param moal_spin_lock A pointer to spin lock handler
+ * @param moal_spin_unlock A pointer to spin unlock handler
+ *
+ * @return Value after offset
+ */
+static INLINE t_s32 util_scalar_offset(
+ t_void *pmoal_handle, pmlan_scalar pscalar, t_s32 offset,
+ mlan_status (*moal_spin_lock)(t_void *handle, t_void *plock),
+ mlan_status (*moal_spin_unlock)(t_void *handle, t_void *plock))
+{
+ t_s32 newval;
+
+ if (moal_spin_lock)
+ moal_spin_lock(pmoal_handle, pscalar->plock);
+ newval = (pscalar->value += offset);
+ if (moal_spin_unlock)
+ moal_spin_unlock(pmoal_handle, pscalar->plock);
+
+ return newval;
+}
+
+/**
+ * @brief This function writes the value to the scalar
+ * if existing value compared with other value is true.
+ *
+ * @param pscalar Pointer to scalar
+ * @param condition Condition to check
+ * @param val_compare Value to compare against current value
+ * ((A X B), where B = val_compare)
+ * @param val_to_set Value to set if comparison is true
+ * @param moal_spin_lock A pointer to spin lock handler
+ * @param moal_spin_unlock A pointer to spin unlock handler
+ *
+ * @return Comparison result (MTRUE or MFALSE)
+ */
+static INLINE t_u8 util_scalar_conditional_write(
+ t_void *pmoal_handle, pmlan_scalar pscalar,
+ MLAN_SCALAR_CONDITIONAL condition, t_s32 val_compare, t_s32 val_to_set,
+ mlan_status (*moal_spin_lock)(t_void *handle, t_void *plock),
+ mlan_status (*moal_spin_unlock)(t_void *handle, t_void *plock))
+{
+ t_u8 update;
+ if (moal_spin_lock)
+ moal_spin_lock(pmoal_handle, pscalar->plock);
+
+ switch (condition) {
+ case MLAN_SCALAR_COND_EQUAL:
+ update = (pscalar->value == val_compare);
+ break;
+ case MLAN_SCALAR_COND_NOT_EQUAL:
+ update = (pscalar->value != val_compare);
+ break;
+ case MLAN_SCALAR_COND_GREATER_THAN:
+ update = (pscalar->value > val_compare);
+ break;
+ case MLAN_SCALAR_COND_GREATER_OR_EQUAL:
+ update = (pscalar->value >= val_compare);
+ break;
+ case MLAN_SCALAR_COND_LESS_THAN:
+ update = (pscalar->value < val_compare);
+ break;
+ case MLAN_SCALAR_COND_LESS_OR_EQUAL:
+ update = (pscalar->value <= val_compare);
+ break;
+ default:
+ update = MFALSE;
+ break;
+ }
+ if (update)
+ pscalar->value = val_to_set;
+
+ if (moal_spin_unlock)
+ moal_spin_unlock(pmoal_handle, pscalar->plock);
+ return (update) ? MTRUE : MFALSE;
+}
+
+/**
+ * @brief This function counts the bits of unsigned int number
+ *
+ * @param num number
+ * @return number of bits
+ */
+static INLINE t_u32 bitcount(t_u32 num)
+{
+ t_u32 count = 0;
+ static t_u32 nibblebits[] = {0, 1, 1, 2, 1, 2, 2, 3,
+ 1, 2, 2, 3, 2, 3, 3, 4};
+ for (; num != 0; num >>= 4)
+ count += nibblebits[num & 0x0f];
+ return count;
+}
+
+#endif /* !_MLAN_UTIL_H_ */
diff --git a/drivers/net/wireless/nxp/mxm_wifiex/wlan_src/mlan/mlan_wmm.c b/drivers/net/wireless/nxp/mxm_wifiex/wlan_src/mlan/mlan_wmm.c
new file mode 100644
index 000000000000..f32a16687090
--- /dev/null
+++ b/drivers/net/wireless/nxp/mxm_wifiex/wlan_src/mlan/mlan_wmm.c
@@ -0,0 +1,3282 @@
+/** @file mlan_wmm.c
+ *
+ * @brief This file contains functions for WMM.
+ *
+ *
+ * Copyright 2014-2020 NXP
+ *
+ * This software file (the File) is distributed by NXP
+ * under the terms of the GNU General Public License Version 2, June 1991
+ * (the License). You may use, redistribute and/or modify the 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.
+ *
+ */
+
+/********************************************************
+Change log:
+ 10/24/2008: initial version
+********************************************************/
+
+#include "mlan.h"
+#ifdef STA_SUPPORT
+#include "mlan_join.h"
+#endif
+#include "mlan_util.h"
+#include "mlan_fw.h"
+#include "mlan_main.h"
+#include "mlan_wmm.h"
+#include "mlan_11n.h"
+#ifdef SDIO
+#include "mlan_sdio.h"
+#endif /* SDIO */
+#ifdef PCIE
+#include "mlan_pcie.h"
+#endif /* PCIE */
+
+/********************************************************
+ Local Variables
+********************************************************/
+
+/** Maximum value FW can accept for driver delay in packet transmission */
+#define DRV_PKT_DELAY_TO_FW_MAX 512
+
+/*
+ * Upper and Lower threshold for packet queuing in the driver
+
+ * - When the number of packets queued reaches the upper limit,
+ * the driver will stop the net queue in the app/kernel space.
+
+ * - When the number of packets drops beneath the lower limit after
+ * having reached the upper limit, the driver will restart the net
+ * queue.
+ */
+
+/** Lower threshold for packet queuing in the driver.
+ * When the number of packets drops beneath the lower limit after having
+ * reached the upper limit, the driver will restart the net queue.
+ */
+#define WMM_QUEUED_PACKET_LOWER_LIMIT 180
+
+/** Upper threshold for packet queuing in the driver.
+ * When the number of packets queued reaches the upper limit, the driver
+ * will stop the net queue in the app/kernel space.
+ */
+#define WMM_QUEUED_PACKET_UPPER_LIMIT 200
+
+/** Offset for TOS field in the IP header */
+#define IPTOS_OFFSET 5
+
+/** WMM information IE */
+static const t_u8 wmm_info_ie[] = {WMM_IE, 0x07, 0x00, 0x50, 0xf2,
+ 0x02, 0x00, 0x01, 0x00};
+
+/** Type enumeration of WMM AC_QUEUES */
+typedef MLAN_PACK_START enum _wmm_ac_e {
+ AC_BE,
+ AC_BK,
+ AC_VI,
+ AC_VO
+} MLAN_PACK_END wmm_ac_e;
+
+/**
+ * AC Priorities go from AC_BK to AC_VO. The ACI enumeration for AC_BK (1)
+ * is higher than the enumeration for AC_BE (0); hence the needed
+ * mapping conversion for wmm AC to priority Queue Index
+ */
+static const t_u8 wmm_aci_to_qidx_map[] = {WMM_AC_BE, WMM_AC_BK, WMM_AC_VI,
+ WMM_AC_VO};
+/**
+ * This table will be used to store the tid values based on ACs.
+ * It is initialized to default values per TID.
+ */
+t_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 */
+};
+
+/**
+ * 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.
+ */
+t_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 table will provide the tid value for given ac. This table does not
+ * change and will be used to copy back the default values to tos_to_tid in
+ * case of disconnect.
+ */
+const t_u8 ac_to_tid[4][2] = {{1, 2}, {0, 3}, {4, 5}, {6, 7}};
+
+/* Map of TOS UP values to WMM AC */
+static const mlan_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};
+
+raListTbl *wlan_wmm_get_ralist_node(pmlan_private priv, t_u8 tid,
+ t_u8 *ra_addr);
+
+/********************************************************
+ Local Functions
+********************************************************/
+#ifdef DEBUG_LEVEL2
+/**
+ * @brief Debug print function to display the priority parameters for a WMM AC
+ *
+ * @param pac_param Pointer to the AC parameters to display
+ *
+ * @return N/A
+ */
+static void
+wlan_wmm_ac_debug_print(const IEEEtypes_WmmAcParameters_t *pac_param)
+{
+ const char *ac_str[] = {"BK", "BE", "VI", "VO"};
+
+ ENTER();
+
+ PRINTM(MINFO,
+ "WMM AC_%s: ACI=%d, ACM=%d, Aifsn=%d, "
+ "EcwMin=%d, EcwMax=%d, TxopLimit=%d\n",
+ ac_str[wmm_aci_to_qidx_map[pac_param->aci_aifsn.aci]],
+ pac_param->aci_aifsn.aci, pac_param->aci_aifsn.acm,
+ pac_param->aci_aifsn.aifsn, pac_param->ecw.ecw_min,
+ pac_param->ecw.ecw_max,
+ wlan_le16_to_cpu(pac_param->tx_op_limit));
+
+ LEAVE();
+}
+/** Print the WMM AC for debug purpose */
+#define PRINTM_AC(pac_param) wlan_wmm_ac_debug_print(pac_param)
+#else
+/** Print the WMM AC for debug purpose */
+#define PRINTM_AC(pac_param)
+#endif
+
+/**
+ * @brief Allocate route address
+ *
+ * @param pmadapter Pointer to the mlan_adapter structure
+ * @param ra Pointer to the route address
+ *
+ * @return ra_list
+ */
+static raListTbl *wlan_wmm_allocate_ralist_node(pmlan_adapter pmadapter,
+ t_u8 *ra)
+{
+ raListTbl *ra_list = MNULL;
+
+ ENTER();
+
+ if (pmadapter->callbacks.moal_malloc(pmadapter->pmoal_handle,
+ sizeof(raListTbl), MLAN_MEM_DEF,
+ (t_u8 **)&ra_list)) {
+ PRINTM(MERROR, "Fail to allocate ra_list\n");
+ goto done;
+ }
+ util_init_list((pmlan_linked_list)ra_list);
+ util_init_list_head((t_void *)pmadapter->pmoal_handle,
+ &ra_list->buf_head, MFALSE,
+ pmadapter->callbacks.moal_init_lock);
+
+ memcpy_ext(pmadapter, ra_list->ra, ra, MLAN_MAC_ADDR_LENGTH,
+ MLAN_MAC_ADDR_LENGTH);
+
+ ra_list->del_ba_count = 0;
+ ra_list->total_pkts = 0;
+ ra_list->tx_pause = 0;
+ PRINTM(MINFO, "RAList: Allocating buffers for TID %p\n", ra_list);
+done:
+ LEAVE();
+ return ra_list;
+}
+
+/**
+ * @brief Map ACs to TID
+ *
+ * @param priv Pointer to the mlan_private driver data struct
+ * @param queue_priority Queue_priority structure
+ *
+ * @return N/A
+ */
+static void wlan_wmm_queue_priorities_tid(pmlan_private priv,
+ t_u8 queue_priority[])
+{
+ int i;
+
+ ENTER();
+
+ 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++)
+ tos_to_tid_inv[tos_to_tid[i]] = (t_u8)i;
+
+ /* in case priorities have changed, force highest priority so
+ * next packet will check from top to re-establish the highest
+ */
+ util_scalar_write(priv->adapter->pmoal_handle,
+ &priv->wmm.highest_queued_prio, HIGH_PRIO_TID,
+ priv->adapter->callbacks.moal_spin_lock,
+ priv->adapter->callbacks.moal_spin_unlock);
+
+ LEAVE();
+}
+
+/**
+ * @brief Evaluate whether or not an AC is to be downgraded
+ *
+ * @param priv Pointer to the mlan_private driver data struct
+ * @param eval_ac AC to evaluate for downgrading
+ *
+ * @return WMM AC The eval_ac traffic is to be sent on.
+ */
+static mlan_wmm_ac_e wlan_wmm_eval_downgrade_ac(pmlan_private priv,
+ mlan_wmm_ac_e eval_ac)
+{
+ int down_ac;
+ mlan_wmm_ac_e ret_ac;
+ WmmAcStatus_t *pac_status;
+
+ ENTER();
+
+ pac_status = &priv->wmm.ac_status[eval_ac];
+
+ if (pac_status->disabled == MFALSE) {
+ LEAVE();
+ /* 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++) {
+ pac_status = &priv->wmm.ac_status[down_ac];
+
+ if ((pac_status->disabled == MFALSE) &&
+ (pac_status->flow_required == MFALSE))
+ /* AC is enabled and does not require admission control
+ */
+ ret_ac = (mlan_wmm_ac_e)down_ac;
+ }
+
+ LEAVE();
+ return ret_ac;
+}
+
+/**
+ * @brief Convert the IP TOS field to an WMM AC Queue assignment
+ *
+ * @param pmadapter A pointer to mlan_adapter structure
+ * @param tos IP TOS field
+ *
+ * @return WMM AC Queue mapping of the IP TOS field
+ */
+static INLINE mlan_wmm_ac_e wlan_wmm_convert_tos_to_ac(pmlan_adapter pmadapter,
+ t_u32 tos)
+{
+ ENTER();
+
+ if (tos >= NELEMENTS(tos_to_ac)) {
+ LEAVE();
+ return WMM_AC_BE;
+ }
+
+ LEAVE();
+ return tos_to_ac[tos];
+}
+
+/**
+ * @brief Evaluate a given TID and downgrade 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 internally
+ *
+ * @param priv Pointer to the mlan_private data struct
+ * @param tid tid to evaluate for downgrading
+ *
+ * @return Same tid as input if downgrading not required or
+ * the tid the traffic for the given tid should be downgraded to
+ */
+static INLINE t_u8 wlan_wmm_downgrade_tid(pmlan_private priv, t_u32 tid)
+{
+ mlan_wmm_ac_e ac_down;
+ pmlan_adapter pmadapter = priv->adapter;
+
+ ENTER();
+
+ ac_down = priv->wmm.ac_down_graded_vals[wlan_wmm_convert_tos_to_ac(
+ pmadapter, tid)];
+ LEAVE();
+ /*
+ * Send the index to tid array, picking from the array will be
+ * taken care by dequeuing function
+ */
+ if (tid == 1 || tid == 2)
+ return ac_to_tid[ac_down][(tid + 1) % 2];
+ else if (tid >= MAX_NUM_TID)
+ return ac_to_tid[ac_down][0];
+ else
+ return ac_to_tid[ac_down][tid % 2];
+}
+
+/**
+ * @brief Delete packets in RA node
+ *
+ * @param priv Pointer to the mlan_private driver data struct
+ * @param ra_list Pointer to raListTbl
+ *
+ * @return N/A
+ */
+static INLINE void wlan_wmm_del_pkts_in_ralist_node(pmlan_private priv,
+ raListTbl *ra_list)
+{
+ pmlan_buffer pmbuf;
+ pmlan_adapter pmadapter = priv->adapter;
+
+ ENTER();
+ while ((pmbuf = (pmlan_buffer)util_peek_list(pmadapter->pmoal_handle,
+ &ra_list->buf_head, MNULL,
+ MNULL))) {
+ util_unlink_list(pmadapter->pmoal_handle, &ra_list->buf_head,
+ (pmlan_linked_list)pmbuf, MNULL, MNULL);
+ wlan_write_data_complete(pmadapter, pmbuf, MLAN_STATUS_FAILURE);
+ }
+ util_free_list_head((t_void *)pmadapter->pmoal_handle,
+ &ra_list->buf_head,
+ pmadapter->callbacks.moal_free_lock);
+
+ LEAVE();
+}
+
+/**
+ * @brief Delete packets in RA list
+ *
+ * @param priv Pointer to the mlan_private driver data struct
+ * @param ra_list_head ra list header
+ *
+ * @return N/A
+ */
+static INLINE void wlan_wmm_del_pkts_in_ralist(pmlan_private priv,
+ mlan_list_head *ra_list_head)
+{
+ raListTbl *ra_list;
+
+ ENTER();
+
+ ra_list = (raListTbl *)util_peek_list(priv->adapter->pmoal_handle,
+ ra_list_head, MNULL, MNULL);
+
+ while (ra_list && ra_list != (raListTbl *)ra_list_head) {
+ wlan_wmm_del_pkts_in_ralist_node(priv, ra_list);
+
+ ra_list = ra_list->pnext;
+ }
+
+ LEAVE();
+}
+
+/**
+ * @brief Clean up the wmm queue
+ *
+ * @param priv Pointer to the mlan_private driver data struct
+ *
+ * @return N/A
+ */
+static void wlan_wmm_cleanup_queues(pmlan_private priv)
+{
+ int i;
+
+ ENTER();
+
+ for (i = 0; i < MAX_NUM_TID; i++) {
+ wlan_wmm_del_pkts_in_ralist(priv,
+ &priv->wmm.tid_tbl_ptr[i].ra_list);
+ priv->wmm.pkts_queued[i] = 0;
+ priv->wmm.pkts_paused[i] = 0;
+ }
+ util_scalar_write(priv->adapter->pmoal_handle,
+ &priv->wmm.tx_pkts_queued, 0, MNULL, MNULL);
+ util_scalar_write(priv->adapter->pmoal_handle,
+ &priv->wmm.highest_queued_prio, HIGH_PRIO_TID, MNULL,
+ MNULL);
+
+ LEAVE();
+}
+
+/**
+ * @brief Delete all route address from RA list
+ *
+ * @param priv Pointer to the mlan_private driver data struct
+ *
+ * @return N/A
+ */
+static void wlan_wmm_delete_all_ralist(pmlan_private priv)
+{
+ raListTbl *ra_list;
+ int i;
+ pmlan_adapter pmadapter = priv->adapter;
+
+ ENTER();
+
+ for (i = 0; i < MAX_NUM_TID; ++i) {
+ PRINTM(MINFO, "RAList: Freeing buffers for TID %d\n", i);
+ while ((ra_list = (raListTbl *)util_peek_list(
+ pmadapter->pmoal_handle,
+ &priv->wmm.tid_tbl_ptr[i].ra_list, MNULL,
+ MNULL))) {
+ util_unlink_list(pmadapter->pmoal_handle,
+ &priv->wmm.tid_tbl_ptr[i].ra_list,
+ (pmlan_linked_list)ra_list, MNULL,
+ MNULL);
+
+ pmadapter->callbacks.moal_mfree(pmadapter->pmoal_handle,
+ (t_u8 *)ra_list);
+ }
+
+ util_init_list(
+ (pmlan_linked_list)&priv->wmm.tid_tbl_ptr[i].ra_list);
+ priv->wmm.tid_tbl_ptr[i].ra_list_curr = MNULL;
+ }
+
+ LEAVE();
+}
+
+/**
+ * @brief Get queue RA pointer
+ *
+ * @param priv Pointer to the mlan_private driver data struct
+ * @param tid TID
+ * @param ra_addr Pointer to the route address
+ *
+ * @return ra_list
+ */
+static raListTbl *wlan_wmm_get_queue_raptr(pmlan_private priv, t_u8 tid,
+ t_u8 *ra_addr)
+{
+ raListTbl *ra_list;
+#ifdef UAP_SUPPORT
+ t_u8 bcast_addr[] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
+#endif
+
+ ENTER();
+ ra_list = wlan_wmm_get_ralist_node(priv, tid, ra_addr);
+ if (ra_list) {
+ LEAVE();
+ return ra_list;
+ }
+#ifdef UAP_SUPPORT
+ if ((GET_BSS_ROLE(priv) == MLAN_BSS_ROLE_UAP) &&
+ (0 !=
+ memcmp(priv->adapter, ra_addr, bcast_addr, sizeof(bcast_addr)))) {
+ if (MNULL == wlan_get_station_entry(priv, ra_addr)) {
+ PRINTM_NETINTF(MERROR, priv);
+ PRINTM(MERROR,
+ "Drop packets to unknow station " MACSTR "\n",
+ MAC2STR(ra_addr));
+ LEAVE();
+ return MNULL;
+ }
+ }
+#endif
+ wlan_ralist_add(priv, ra_addr);
+
+ ra_list = wlan_wmm_get_ralist_node(priv, tid, ra_addr);
+ LEAVE();
+ return ra_list;
+}
+
+#ifdef STA_SUPPORT
+/**
+ * @brief Sends wmmac host event
+ *
+ * @param priv Pointer to the mlan_private driver data struct
+ * @param type_str Type of host event
+ * @param src_addr Pointer to the source Address
+ * @param tid TID
+ * @param up User priority
+ * @param status Status code or Reason code
+ *
+ * @return N/A
+ */
+static void wlan_send_wmmac_host_event(pmlan_private priv, char *type_str,
+ t_u8 *src_addr, t_u8 tid, t_u8 up,
+ t_u8 status)
+{
+ t_u8 event_buf[100];
+ mlan_event *pevent;
+ t_u8 *pout_buf;
+
+ ENTER();
+
+ /* Format one of the following two output strings:
+ ** - TSPEC:ADDTS_RSP:[<status code>]:TID=X:UP=Y
+ ** - TSPEC:DELTS_RX:[<reason code>]:TID=X:UP=Y
+ */
+ pevent = (mlan_event *)event_buf;
+ pout_buf = pevent->event_buf;
+
+ memcpy_ext(priv->adapter, pout_buf, (t_u8 *)"TSPEC:", 6, 6);
+ pout_buf += 6;
+
+ memcpy_ext(priv->adapter, pout_buf, (t_u8 *)type_str,
+ wlan_strlen(type_str), wlan_strlen(type_str));
+ pout_buf += wlan_strlen(type_str);
+
+ *pout_buf++ = ':';
+ *pout_buf++ = '[';
+
+ if (status >= 100) {
+ *pout_buf++ = (status / 100) + '0';
+ status = (status % 100);
+ }
+
+ if (status >= 10) {
+ *pout_buf++ = (status / 10) + '0';
+ status = (status % 10);
+ }
+
+ *pout_buf++ = status + '0';
+
+ memcpy_ext(priv->adapter, pout_buf, (t_u8 *)"]:TID", 5, 5);
+ pout_buf += 5;
+ *pout_buf++ = tid + '0';
+
+ memcpy_ext(priv->adapter, pout_buf, (t_u8 *)":UP", 3, 3);
+ pout_buf += 3;
+ *pout_buf++ = up + '0';
+
+ *pout_buf = '\0';
+
+ pevent->bss_index = priv->bss_index;
+ pevent->event_id = MLAN_EVENT_ID_DRV_REPORT_STRING;
+ pevent->event_len = wlan_strlen((const char *)(pevent->event_buf));
+
+ wlan_recv_event(priv, MLAN_EVENT_ID_DRV_REPORT_STRING, pevent);
+ LEAVE();
+}
+#endif /* STA_SUPPORT */
+
+/**
+ * @brief This function gets the highest priority list pointer
+ *
+ * @param pmadapter A pointer to mlan_adapter
+ * @param priv A pointer to mlan_private
+ * @param tid A pointer to return tid
+ *
+ * @return raListTbl
+ */
+static raListTbl *wlan_wmm_get_highest_priolist_ptr(pmlan_adapter pmadapter,
+ pmlan_private *priv,
+ int *tid)
+{
+ pmlan_private priv_tmp;
+ raListTbl *ptr, *head;
+ mlan_bssprio_node *bssprio_node, *bssprio_head;
+ tid_tbl_t *tid_ptr;
+ int i, j;
+ int next_prio = 0;
+ int next_tid = 0;
+ ENTER();
+
+ PRINTM(MDAT_D, "POP\n");
+ for (j = pmadapter->priv_num - 1; j >= 0; --j) {
+ if (!(util_peek_list(pmadapter->pmoal_handle,
+ &pmadapter->bssprio_tbl[j].bssprio_head,
+ MNULL, MNULL)))
+ continue;
+
+ if (pmadapter->bssprio_tbl[j].bssprio_cur ==
+ (mlan_bssprio_node *)&pmadapter->bssprio_tbl[j]
+ .bssprio_head) {
+ pmadapter->bssprio_tbl[j].bssprio_cur =
+ pmadapter->bssprio_tbl[j].bssprio_cur->pnext;
+ }
+
+ bssprio_head = bssprio_node =
+ pmadapter->bssprio_tbl[j].bssprio_cur;
+
+ do {
+ priv_tmp = bssprio_node->priv;
+ if ((priv_tmp->port_ctrl_mode == MTRUE) &&
+ (priv_tmp->port_open == MFALSE)) {
+ PRINTM(MINFO,
+ "get_highest_prio_ptr(): "
+ "PORT_CLOSED Ignore pkts from BSS%d\n",
+ priv_tmp->bss_index);
+ /* Ignore data pkts from a BSS if port is closed
+ */
+ goto next_intf;
+ }
+ if (priv_tmp->tx_pause == MTRUE) {
+ PRINTM(MINFO,
+ "get_highest_prio_ptr(): "
+ "TX PASUE Ignore pkts from BSS%d\n",
+ priv_tmp->bss_index);
+ /* Ignore data pkts from a BSS if tx pause */
+ goto next_intf;
+ }
+
+ pmadapter->callbacks.moal_spin_lock(
+ pmadapter->pmoal_handle,
+ priv_tmp->wmm.ra_list_spinlock);
+
+ for (i = util_scalar_read(
+ pmadapter->pmoal_handle,
+ &priv_tmp->wmm.highest_queued_prio, MNULL,
+ MNULL);
+ i >= LOW_PRIO_TID; --i) {
+ tid_ptr = &(priv_tmp)
+ ->wmm
+ .tid_tbl_ptr[tos_to_tid[i]];
+ if (!util_peek_list(pmadapter->pmoal_handle,
+ &tid_ptr->ra_list, MNULL,
+ MNULL))
+ continue;
+
+ /*
+ * Always choose the next ra we transmitted
+ * last time, this way we pick the ra's in
+ * round robin fashion.
+ */
+ head = ptr = tid_ptr->ra_list_curr->pnext;
+ if (ptr == (raListTbl *)&tid_ptr->ra_list)
+ head = ptr = ptr->pnext;
+
+ do {
+ if (!ptr->tx_pause &&
+ util_peek_list(
+ pmadapter->pmoal_handle,
+ &ptr->buf_head, MNULL,
+ MNULL)) {
+ /* Because WMM only support
+ * BK/BE/VI/VO, we have 8 tid
+ * We should balance the traffic
+ * of the same AC */
+ if (i % 2)
+ next_prio = i - 1;
+ else
+ next_prio = i + 1;
+ next_tid =
+ tos_to_tid[next_prio];
+ if (priv_tmp->wmm.pkts_queued
+ [next_tid] &&
+ (priv_tmp->wmm.pkts_queued
+ [next_tid] >
+ priv_tmp->wmm.pkts_paused
+ [next_tid]))
+ util_scalar_write(
+ pmadapter->pmoal_handle,
+ &priv_tmp->wmm
+ .highest_queued_prio,
+ next_prio,
+ MNULL, MNULL);
+ else
+ /* if
+ * highest_queued_prio >
+ * i, set it to i */
+ util_scalar_conditional_write(
+ pmadapter->pmoal_handle,
+ &priv_tmp->wmm
+ .highest_queued_prio,
+ MLAN_SCALAR_COND_GREATER_THAN,
+ i, i, MNULL,
+ MNULL);
+ *priv = priv_tmp;
+ *tid = tos_to_tid[i];
+ /* hold priv->ra_list_spinlock
+ * to maintain ptr */
+ PRINTM(MDAT_D,
+ "get highest prio ptr %p, tid %d\n",
+ ptr, *tid);
+ LEAVE();
+ return ptr;
+ }
+
+ ptr = ptr->pnext;
+ if (ptr ==
+ (raListTbl *)&tid_ptr->ra_list)
+ ptr = ptr->pnext;
+ } while (ptr != head);
+ }
+
+ /* If priv still has packets queued, reset to
+ * HIGH_PRIO_TID */
+ if (util_scalar_read(pmadapter->pmoal_handle,
+ &priv_tmp->wmm.tx_pkts_queued,
+ MNULL, MNULL))
+ util_scalar_write(
+ pmadapter->pmoal_handle,
+ &priv_tmp->wmm.highest_queued_prio,
+ HIGH_PRIO_TID, MNULL, MNULL);
+ else
+ /* No packet at any TID for this priv. Mark as
+ * such to skip checking TIDs for this priv
+ * (until pkt is added). */
+ util_scalar_write(
+ pmadapter->pmoal_handle,
+ &priv_tmp->wmm.highest_queued_prio,
+ NO_PKT_PRIO_TID, MNULL, MNULL);
+
+ pmadapter->callbacks.moal_spin_unlock(
+ pmadapter->pmoal_handle,
+ priv_tmp->wmm.ra_list_spinlock);
+
+ next_intf:
+ bssprio_node = bssprio_node->pnext;
+ if (bssprio_node ==
+ (mlan_bssprio_node *)&pmadapter->bssprio_tbl[j]
+ .bssprio_head)
+ bssprio_node = bssprio_node->pnext;
+ pmadapter->bssprio_tbl[j].bssprio_cur = bssprio_node;
+ } while (bssprio_node != bssprio_head);
+ }
+
+ LEAVE();
+ return MNULL;
+}
+
+/**
+ * @brief This function gets the number of packets in the Tx queue
+ *
+ * @param priv A pointer to mlan_private
+ * @param ptr A pointer to RA list table
+ * @param max_buf_size Maximum buffer size
+ *
+ * @return Packet count
+ */
+static int wlan_num_pkts_in_txq(mlan_private *priv, raListTbl *ptr,
+ int max_buf_size)
+{
+ int count = 0, total_size = 0;
+ pmlan_buffer pmbuf;
+
+ ENTER();
+
+ for (pmbuf = (pmlan_buffer)ptr->buf_head.pnext;
+ pmbuf != (pmlan_buffer)(&ptr->buf_head); pmbuf = pmbuf->pnext) {
+ total_size += pmbuf->data_len;
+ if (total_size < max_buf_size)
+ ++count;
+ else
+ break;
+ }
+
+ LEAVE();
+ return count;
+}
+
+/**
+ * @brief This function sends a single packet
+ *
+ * @param priv A pointer to mlan_private
+ * @param ptr A pointer to RA list table
+ * @param ptrindex ptr's TID index
+ *
+ * @return N/A
+ */
+static INLINE void wlan_send_single_packet(pmlan_private priv, raListTbl *ptr,
+ int ptrindex)
+{
+ pmlan_buffer pmbuf;
+ pmlan_buffer pmbuf_next;
+ mlan_tx_param tx_param;
+ pmlan_adapter pmadapter = priv->adapter;
+ mlan_status status = MLAN_STATUS_SUCCESS;
+
+ ENTER();
+
+ pmbuf = (pmlan_buffer)util_dequeue_list(pmadapter->pmoal_handle,
+ &ptr->buf_head, MNULL, MNULL);
+ if (pmbuf) {
+ PRINTM(MINFO, "Dequeuing the packet %p %p\n", ptr, pmbuf);
+ priv->wmm.pkts_queued[ptrindex]--;
+ util_scalar_decrement(pmadapter->pmoal_handle,
+ &priv->wmm.tx_pkts_queued, MNULL, MNULL);
+ ptr->total_pkts--;
+ pmbuf_next = (pmlan_buffer)util_peek_list(
+ pmadapter->pmoal_handle, &ptr->buf_head, MNULL, MNULL);
+ pmadapter->callbacks.moal_spin_unlock(
+ pmadapter->pmoal_handle, priv->wmm.ra_list_spinlock);
+
+ tx_param.next_pkt_len =
+ ((pmbuf_next) ? pmbuf_next->data_len + sizeof(TxPD) :
+ 0);
+ status = wlan_process_tx(priv, pmbuf, &tx_param);
+
+ if (status == MLAN_STATUS_RESOURCE) {
+ /** Queue the packet back at the head */
+ PRINTM(MDAT_D, "Queuing pkt back to raList %p %p\n",
+ ptr, pmbuf);
+ pmadapter->callbacks.moal_spin_lock(
+ pmadapter->pmoal_handle,
+ priv->wmm.ra_list_spinlock);
+
+ if (!wlan_is_ralist_valid(priv, ptr, ptrindex)) {
+ pmadapter->callbacks.moal_spin_unlock(
+ pmadapter->pmoal_handle,
+ priv->wmm.ra_list_spinlock);
+ wlan_write_data_complete(pmadapter, pmbuf,
+ MLAN_STATUS_FAILURE);
+ LEAVE();
+ return;
+ }
+ priv->wmm.pkts_queued[ptrindex]++;
+ util_scalar_increment(pmadapter->pmoal_handle,
+ &priv->wmm.tx_pkts_queued, MNULL,
+ MNULL);
+ util_enqueue_list_head(pmadapter->pmoal_handle,
+ &ptr->buf_head,
+ (pmlan_linked_list)pmbuf, MNULL,
+ MNULL);
+
+ ptr->total_pkts++;
+ pmbuf->flags |= MLAN_BUF_FLAG_REQUEUED_PKT;
+ pmadapter->callbacks.moal_spin_unlock(
+ pmadapter->pmoal_handle,
+ priv->wmm.ra_list_spinlock);
+ } else {
+ pmadapter->callbacks.moal_spin_lock(
+ pmadapter->pmoal_handle,
+ priv->wmm.ra_list_spinlock);
+ if (wlan_is_ralist_valid(priv, ptr, ptrindex)) {
+ priv->wmm.packets_out[ptrindex]++;
+ priv->wmm.tid_tbl_ptr[ptrindex].ra_list_curr =
+ ptr;
+ }
+ pmadapter->bssprio_tbl[priv->bss_priority].bssprio_cur =
+ pmadapter->bssprio_tbl[priv->bss_priority]
+ .bssprio_cur->pnext;
+ pmadapter->callbacks.moal_spin_unlock(
+ pmadapter->pmoal_handle,
+ priv->wmm.ra_list_spinlock);
+ }
+ } else {
+ pmadapter->callbacks.moal_spin_unlock(
+ pmadapter->pmoal_handle, priv->wmm.ra_list_spinlock);
+ PRINTM(MINFO, "Nothing to send\n");
+ }
+
+ LEAVE();
+}
+
+/**
+ * @brief This function checks if this mlan_buffer is already processed.
+ *
+ * @param priv A pointer to mlan_private
+ * @param ptr A pointer to RA list table
+ *
+ * @return MTRUE or MFALSE
+ */
+static INLINE int wlan_is_ptr_processed(mlan_private *priv, raListTbl *ptr)
+{
+ pmlan_buffer pmbuf;
+
+ pmbuf = (pmlan_buffer)util_peek_list(priv->adapter->pmoal_handle,
+ &ptr->buf_head, MNULL, MNULL);
+ if (pmbuf && (pmbuf->flags & MLAN_BUF_FLAG_REQUEUED_PKT))
+ return MTRUE;
+
+ return MFALSE;
+}
+
+/**
+ * @brief This function sends a single packet that has been processed
+ *
+ * @param priv A pointer to mlan_private
+ * @param ptr A pointer to RA list table
+ * @param ptrindex ptr's TID index
+ *
+ * @return N/A
+ */
+static INLINE void wlan_send_processed_packet(pmlan_private priv,
+ raListTbl *ptr, int ptrindex)
+{
+ pmlan_buffer pmbuf_next = MNULL;
+ mlan_tx_param tx_param;
+ pmlan_buffer pmbuf;
+ pmlan_adapter pmadapter = priv->adapter;
+ mlan_status ret = MLAN_STATUS_FAILURE;
+
+ pmbuf = (pmlan_buffer)util_dequeue_list(pmadapter->pmoal_handle,
+ &ptr->buf_head, MNULL, MNULL);
+ if (pmbuf) {
+ pmbuf_next = (pmlan_buffer)util_peek_list(
+ pmadapter->pmoal_handle, &ptr->buf_head, MNULL, MNULL);
+ pmadapter->callbacks.moal_spin_unlock(
+ pmadapter->pmoal_handle, priv->wmm.ra_list_spinlock);
+ tx_param.next_pkt_len =
+ ((pmbuf_next) ? pmbuf_next->data_len + sizeof(TxPD) :
+ 0);
+
+ ret = pmadapter->ops.host_to_card(priv, MLAN_TYPE_DATA, pmbuf,
+ &tx_param);
+ switch (ret) {
+#ifdef USB
+ case MLAN_STATUS_PRESOURCE:
+ PRINTM(MINFO, "MLAN_STATUS_PRESOURCE is returned\n");
+ break;
+#endif
+ case MLAN_STATUS_RESOURCE:
+ PRINTM(MINFO, "MLAN_STATUS_RESOURCE is returned\n");
+ pmadapter->callbacks.moal_spin_lock(
+ pmadapter->pmoal_handle,
+ priv->wmm.ra_list_spinlock);
+
+ if (!wlan_is_ralist_valid(priv, ptr, ptrindex)) {
+ pmadapter->callbacks.moal_spin_unlock(
+ pmadapter->pmoal_handle,
+ priv->wmm.ra_list_spinlock);
+ wlan_write_data_complete(pmadapter, pmbuf,
+ MLAN_STATUS_FAILURE);
+ LEAVE();
+ return;
+ }
+ util_enqueue_list_head(pmadapter->pmoal_handle,
+ &ptr->buf_head,
+ (pmlan_linked_list)pmbuf, MNULL,
+ MNULL);
+
+ pmbuf->flags |= MLAN_BUF_FLAG_REQUEUED_PKT;
+ pmadapter->callbacks.moal_spin_unlock(
+ pmadapter->pmoal_handle,
+ priv->wmm.ra_list_spinlock);
+ break;
+ case MLAN_STATUS_FAILURE:
+ PRINTM(MERROR, "Error: Failed to write data\n");
+ pmadapter->dbg.num_tx_host_to_card_failure++;
+ pmbuf->status_code = MLAN_ERROR_DATA_TX_FAIL;
+ wlan_write_data_complete(pmadapter, pmbuf, ret);
+ break;
+ case MLAN_STATUS_PENDING:
+ break;
+ case MLAN_STATUS_SUCCESS:
+ DBG_HEXDUMP(MDAT_D, "Tx",
+ pmbuf->pbuf + pmbuf->data_offset,
+ MIN(pmbuf->data_len + sizeof(TxPD),
+ MAX_DATA_DUMP_LEN));
+ wlan_write_data_complete(pmadapter, pmbuf, ret);
+ break;
+ default:
+ break;
+ }
+ if (ret != MLAN_STATUS_RESOURCE) {
+ pmadapter->callbacks.moal_spin_lock(
+ pmadapter->pmoal_handle,
+ priv->wmm.ra_list_spinlock);
+ if (wlan_is_ralist_valid(priv, ptr, ptrindex)) {
+ priv->wmm.packets_out[ptrindex]++;
+ priv->wmm.tid_tbl_ptr[ptrindex].ra_list_curr =
+ ptr;
+ ptr->total_pkts--;
+ }
+ pmadapter->bssprio_tbl[priv->bss_priority].bssprio_cur =
+ pmadapter->bssprio_tbl[priv->bss_priority]
+ .bssprio_cur->pnext;
+ priv->wmm.pkts_queued[ptrindex]--;
+ util_scalar_decrement(pmadapter->pmoal_handle,
+ &priv->wmm.tx_pkts_queued, MNULL,
+ MNULL);
+ pmadapter->callbacks.moal_spin_unlock(
+ pmadapter->pmoal_handle,
+ priv->wmm.ra_list_spinlock);
+ }
+ } else {
+ pmadapter->callbacks.moal_spin_unlock(
+ pmadapter->pmoal_handle, priv->wmm.ra_list_spinlock);
+ }
+}
+
+/**
+ * @brief This function dequeues a packet
+ *
+ * @param pmadapter A pointer to mlan_adapter
+ *
+ * @return MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ */
+static int wlan_dequeue_tx_packet(pmlan_adapter pmadapter)
+{
+ raListTbl *ptr;
+ pmlan_private priv = MNULL;
+ int ptrindex = 0;
+ t_u8 ra[MLAN_MAC_ADDR_LENGTH];
+ int tid_del = 0;
+ int tid = 0;
+ mlan_buffer *pmbuf = MNULL;
+
+ ENTER();
+
+ ptr = wlan_wmm_get_highest_priolist_ptr(pmadapter, &priv, &ptrindex);
+ if (!ptr) {
+ LEAVE();
+ return MLAN_STATUS_FAILURE;
+ }
+
+ /* Note:- Spinlock is locked in wlan_wmm_get_highest_priolist_ptr
+ * when it returns a pointer (for the priv it returns),
+ * and is unlocked in wlan_send_processed_packet,
+ * wlan_send_single_packet or wlan_11n_aggregate_pkt.
+ * The spinlock would be required for some parts of both of function.
+ * But, the the bulk of these function will execute w/o spinlock.
+ * Unlocking the spinlock inside these function will help us avoid
+ * taking the spinlock again, check to see if the ptr is still
+ * valid and then proceed. This is done purely to increase
+ * execution time. */
+
+ /* Note:- Also, anybody adding code which does not get into
+ * wlan_send_processed_packet, wlan_send_single_packet, or
+ * wlan_11n_aggregate_pkt should make sure ra_list_spinlock
+ * is freed. Otherwise there would be a lock up. */
+
+ tid = wlan_get_tid(priv->adapter, ptr);
+ if (tid >= MAX_NUM_TID)
+ tid = wlan_wmm_downgrade_tid(priv, tid);
+
+ if (wlan_is_ptr_processed(priv, ptr)) {
+ wlan_send_processed_packet(priv, ptr, ptrindex);
+ LEAVE();
+ return MLAN_STATUS_SUCCESS;
+ }
+ if (ptr->del_ba_count >= DEL_BA_THRESHOLD)
+ wlan_update_del_ba_count(priv, ptr);
+ if (pmadapter->tp_state_on) {
+ pmbuf = (pmlan_buffer)util_peek_list(
+ pmadapter->pmoal_handle, &ptr->buf_head, MNULL, MNULL);
+ if (pmbuf) {
+ pmadapter->callbacks.moal_tp_accounting(
+ pmadapter->pmoal_handle, pmbuf->pdesc, 3);
+ if (pmadapter->tp_state_drop_point == 3) {
+ pmbuf = (pmlan_buffer)util_dequeue_list(
+ pmadapter->pmoal_handle, &ptr->buf_head,
+ MNULL, MNULL);
+ PRINTM(MERROR, "Dequeuing the packet %p %p\n",
+ ptr, pmbuf);
+ priv->wmm.pkts_queued[ptrindex]--;
+ util_scalar_decrement(pmadapter->pmoal_handle,
+ &priv->wmm.tx_pkts_queued,
+ MNULL, MNULL);
+ ptr->total_pkts--;
+ pmadapter->callbacks.moal_spin_unlock(
+ pmadapter->pmoal_handle,
+ priv->wmm.ra_list_spinlock);
+ wlan_write_data_complete(pmadapter, pmbuf,
+ MLAN_STATUS_SUCCESS);
+ LEAVE();
+ return MLAN_STATUS_SUCCESS;
+ }
+ }
+ }
+ if (!ptr->is_11n_enabled ||
+ (ptr->ba_status || ptr->del_ba_count >= DEL_BA_THRESHOLD)
+#ifdef STA_SUPPORT
+ || priv->wps.session_enable
+#endif /* STA_SUPPORT */
+ ) {
+ if (ptr->is_11n_enabled && ptr->ba_status &&
+ ptr->amsdu_in_ampdu &&
+ wlan_is_amsdu_allowed(priv, ptr, tid) &&
+ (wlan_num_pkts_in_txq(priv, ptr, pmadapter->tx_buf_size) >=
+ MIN_NUM_AMSDU)) {
+ wlan_11n_aggregate_pkt(priv, ptr, priv->intf_hr_len,
+ ptrindex);
+ } else
+ wlan_send_single_packet(priv, ptr, ptrindex);
+ } else {
+ if (wlan_is_ampdu_allowed(priv, ptr, tid) &&
+ (ptr->packet_count > ptr->ba_packet_threshold)) {
+ if (wlan_is_bastream_avail(priv)) {
+ PRINTM(MINFO,
+ "BA setup threshold %d reached. tid=%d\n",
+ ptr->packet_count, tid);
+ if (!wlan_11n_get_txbastream_tbl(
+ priv, tid, ptr->ra, MFALSE)) {
+ wlan_11n_create_txbastream_tbl(
+ priv, ptr->ra, tid,
+ BA_STREAM_SETUP_INPROGRESS);
+ wlan_send_addba(priv, tid, ptr->ra);
+ }
+ } else if (wlan_find_stream_to_delete(priv, ptr, tid,
+ &tid_del, ra)) {
+ PRINTM(MDAT_D, "tid_del=%d tid=%d\n", tid_del,
+ tid);
+ if (!wlan_11n_get_txbastream_tbl(
+ priv, tid, ptr->ra, MFALSE)) {
+ wlan_11n_create_txbastream_tbl(
+ priv, ptr->ra, tid,
+ BA_STREAM_SETUP_INPROGRESS);
+ wlan_send_delba(priv, MNULL, tid_del,
+ ra, 1);
+ }
+ }
+ }
+ if (wlan_is_amsdu_allowed(priv, ptr, tid) &&
+ (wlan_num_pkts_in_txq(priv, ptr, pmadapter->tx_buf_size) >=
+ MIN_NUM_AMSDU)) {
+ wlan_11n_aggregate_pkt(priv, ptr, priv->intf_hr_len,
+ ptrindex);
+ } else {
+ wlan_send_single_packet(priv, ptr, ptrindex);
+ }
+ }
+
+ LEAVE();
+ return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ * @brief update tx_pause flag in ra_list
+ *
+ * @param priv A pointer to mlan_private
+ * @param mac peer mac address
+ * @param tx_pause tx_pause flag (0/1)
+ *
+ *
+ * @return packets queued for this mac
+ */
+t_u16 wlan_update_ralist_tx_pause(pmlan_private priv, t_u8 *mac, t_u8 tx_pause)
+{
+ raListTbl *ra_list;
+ int i;
+ pmlan_adapter pmadapter = priv->adapter;
+ t_u32 pkt_cnt = 0;
+ t_u32 tx_pkts_queued = 0;
+ ENTER();
+
+ pmadapter->callbacks.moal_spin_lock(pmadapter->pmoal_handle,
+ priv->wmm.ra_list_spinlock);
+ for (i = 0; i < MAX_NUM_TID; ++i) {
+ ra_list = wlan_wmm_get_ralist_node(priv, i, mac);
+ if (ra_list && ra_list->tx_pause != tx_pause) {
+ pkt_cnt += ra_list->total_pkts;
+ ra_list->tx_pause = tx_pause;
+ if (tx_pause)
+ priv->wmm.pkts_paused[i] += ra_list->total_pkts;
+ else
+ priv->wmm.pkts_paused[i] -= ra_list->total_pkts;
+ }
+ }
+ if (pkt_cnt) {
+ tx_pkts_queued = util_scalar_read(pmadapter->pmoal_handle,
+ &priv->wmm.tx_pkts_queued,
+ MNULL, MNULL);
+ if (tx_pause)
+ tx_pkts_queued -= pkt_cnt;
+ else
+ tx_pkts_queued += pkt_cnt;
+ util_scalar_write(priv->adapter->pmoal_handle,
+ &priv->wmm.tx_pkts_queued, tx_pkts_queued,
+ MNULL, MNULL);
+ util_scalar_write(priv->adapter->pmoal_handle,
+ &priv->wmm.highest_queued_prio, HIGH_PRIO_TID,
+ MNULL, MNULL);
+ }
+ pmadapter->callbacks.moal_spin_unlock(pmadapter->pmoal_handle,
+ priv->wmm.ra_list_spinlock);
+ LEAVE();
+ return pkt_cnt;
+}
+
+#ifdef STA_SUPPORT
+#endif /* STA_SUPPORT */
+/********************************************************
+ Global Functions
+********************************************************/
+
+/**
+ * @brief Get the threshold value for BA setup using system time.
+ *
+ * @param pmadapter Pointer to the mlan_adapter structure
+ *
+ * @return threshold value.
+ */
+t_u8 wlan_get_random_ba_threshold(pmlan_adapter pmadapter)
+{
+ t_u32 sec, usec;
+ t_u8 ba_threshold = 0;
+
+ ENTER();
+
+ /* setup ba_packet_threshold here random number between
+ [BA_SETUP_PACKET_OFFSET,
+ BA_SETUP_PACKET_OFFSET+BA_SETUP_MAX_PACKET_THRESHOLD-1] */
+
+#define BA_SETUP_MAX_PACKET_THRESHOLD 16
+
+ pmadapter->callbacks.moal_get_system_time(pmadapter->pmoal_handle, &sec,
+ &usec);
+ sec = (sec & 0xFFFF) + (sec >> 16);
+ usec = (usec & 0xFFFF) + (usec >> 16);
+
+ ba_threshold = (((sec << 16) + usec) % BA_SETUP_MAX_PACKET_THRESHOLD) +
+ pmadapter->min_ba_threshold;
+ PRINTM(MINFO, "pmadapter->min_ba_threshold = %d\n",
+ pmadapter->min_ba_threshold);
+ PRINTM(MINFO, "setup BA after %d packets\n", ba_threshold);
+
+ LEAVE();
+ return ba_threshold;
+}
+
+/**
+ * @brief This function cleans Tx/Rx queues
+ *
+ * @param priv A pointer to mlan_private
+ *
+ * @return N/A
+ */
+t_void wlan_clean_txrx(pmlan_private priv)
+{
+ mlan_adapter *pmadapter = priv->adapter;
+ t_u8 i = 0;
+
+ ENTER();
+ wlan_cleanup_bypass_txq(priv);
+ wlan_11n_cleanup_reorder_tbl(priv);
+ wlan_11n_deleteall_txbastream_tbl(priv);
+#if defined(USB)
+ if (IS_USB(pmadapter->card_type))
+ wlan_reset_usb_tx_aggr(priv->adapter);
+#endif
+#ifdef PCIE
+ if (IS_PCIE(pmadapter->card_type))
+ wlan_clean_pcie_ring_buf(priv->adapter);
+#endif
+ pmadapter->callbacks.moal_spin_lock(pmadapter->pmoal_handle,
+ priv->wmm.ra_list_spinlock);
+ wlan_wmm_cleanup_queues(priv);
+ wlan_wmm_delete_all_ralist(priv);
+ memcpy_ext(pmadapter, tos_to_tid, ac_to_tid, sizeof(tos_to_tid),
+ sizeof(tos_to_tid));
+ for (i = 0; i < MAX_NUM_TID; i++)
+ tos_to_tid_inv[tos_to_tid[i]] = (t_u8)i;
+#ifdef UAP_SUPPORT
+ priv->num_drop_pkts = 0;
+#endif
+#ifdef SDIO
+ if (IS_SD(pmadapter->card_type)) {
+ memset(pmadapter, pmadapter->pcard_sd->mpa_tx_count, 0,
+ sizeof(pmadapter->pcard_sd->mpa_tx_count));
+ pmadapter->pcard_sd->mpa_sent_no_ports = 0;
+ pmadapter->pcard_sd->mpa_sent_last_pkt = 0;
+ memset(pmadapter, pmadapter->pcard_sd->mpa_rx_count, 0,
+ sizeof(pmadapter->pcard_sd->mpa_rx_count));
+ }
+#endif
+ pmadapter->callbacks.moal_spin_unlock(pmadapter->pmoal_handle,
+ priv->wmm.ra_list_spinlock);
+
+ LEAVE();
+}
+
+/**
+ * @brief Set the WMM queue priorities to their default values
+ *
+ * @param priv Pointer to the mlan_private driver data struct
+ *
+ * @return N/A
+ */
+void wlan_wmm_default_queue_priorities(pmlan_private priv)
+{
+ ENTER();
+
+ /* 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;
+
+ LEAVE();
+}
+
+/**
+ * @brief Initialize WMM priority queues
+ *
+ * @param priv Pointer to the mlan_private driver data struct
+ * @param pwmm_ie Pointer to the IEEEtypes_WmmParameter_t data struct
+ *
+ * @return N/A
+ */
+void wlan_wmm_setup_queue_priorities(pmlan_private priv,
+ IEEEtypes_WmmParameter_t *pwmm_ie)
+{
+ t_u16 cw_min, avg_back_off, tmp[4];
+ t_u32 i, j, num_ac;
+ t_u8 ac_idx;
+
+ ENTER();
+
+ if (!pwmm_ie || priv->wmm_enabled == MFALSE) {
+ /* WMM is not enabled, just set the defaults and return */
+ wlan_wmm_default_queue_priorities(priv);
+ LEAVE();
+ return;
+ }
+ memset(priv->adapter, tmp, 0, sizeof(tmp));
+
+ HEXDUMP("WMM: setup_queue_priorities: param IE", (t_u8 *)pwmm_ie,
+ sizeof(IEEEtypes_WmmParameter_t));
+
+ PRINTM(MINFO,
+ "WMM Parameter IE: version=%d, "
+ "qos_info Parameter Set Count=%d, Reserved=%#x\n",
+ pwmm_ie->vend_hdr.version, pwmm_ie->qos_info.para_set_count,
+ pwmm_ie->reserved);
+
+ for (num_ac = 0; num_ac < NELEMENTS(pwmm_ie->ac_params); num_ac++) {
+ cw_min = (1 << pwmm_ie->ac_params[num_ac].ecw.ecw_min) - 1;
+ avg_back_off = (cw_min >> 1) +
+ pwmm_ie->ac_params[num_ac].aci_aifsn.aifsn;
+
+ ac_idx = wmm_aci_to_qidx_map[pwmm_ie->ac_params[num_ac]
+ .aci_aifsn.aci];
+ priv->wmm.queue_priority[ac_idx] = ac_idx;
+ tmp[ac_idx] = avg_back_off;
+
+ PRINTM(MCMND, "WMM: CWmax=%d CWmin=%d Avg Back-off=%d\n",
+ (1 << pwmm_ie->ac_params[num_ac].ecw.ecw_max) - 1,
+ cw_min, avg_back_off);
+ PRINTM_AC(&pwmm_ie->ac_params[num_ac]);
+ }
+
+ HEXDUMP("WMM: avg_back_off", (t_u8 *)tmp, sizeof(tmp));
+ HEXDUMP("WMM: queue_priority", priv->wmm.queue_priority,
+ sizeof(priv->wmm.queue_priority));
+
+ /* Bubble sort */
+ for (i = 0; i < num_ac; i++) {
+ for (j = 1; j < num_ac - i; j++) {
+ if (tmp[j - 1] > tmp[j]) {
+ SWAP_U16(tmp[j - 1], tmp[j]);
+ SWAP_U8(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_U8(priv->wmm.queue_priority[j - 1],
+ priv->wmm.queue_priority[j]);
+ }
+ }
+ }
+ }
+
+ wlan_wmm_queue_priorities_tid(priv, priv->wmm.queue_priority);
+
+ HEXDUMP("WMM: avg_back_off, sort", (t_u8 *)tmp, sizeof(tmp));
+ DBG_HEXDUMP(MCMD_D, "WMM: queue_priority, sort",
+ priv->wmm.queue_priority, sizeof(priv->wmm.queue_priority));
+ LEAVE();
+}
+
+/**
+ * @brief Downgrade WMM priority queue
+ *
+ * @param priv Pointer to the mlan_private driver data struct
+ *
+ * @return N/A
+ */
+void wlan_wmm_setup_ac_downgrade(pmlan_private priv)
+{
+ int ac_val;
+
+ ENTER();
+
+ PRINTM(MINFO, "WMM: AC Priorities: BK(0), BE(1), VI(2), VO(3)\n");
+
+ if (priv->wmm_enabled == MFALSE) {
+ /* 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] =
+ (mlan_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] =
+ wlan_wmm_eval_downgrade_ac(
+ priv, (mlan_wmm_ac_e)ac_val);
+ PRINTM(MINFO, "WMM: AC PRIO %d maps to %d\n", ac_val,
+ priv->wmm.ac_down_graded_vals[ac_val]);
+ }
+ }
+
+ LEAVE();
+}
+
+/**
+ * @brief Allocate and add a RA list for all TIDs with the given RA
+ *
+ * @param priv Pointer to the mlan_private driver data struct
+ * @param ra Address of the receiver STA (AP in case of infra)
+ *
+ * @return N/A
+ */
+void wlan_ralist_add(mlan_private *priv, t_u8 *ra)
+{
+ int i;
+ raListTbl *ra_list;
+ pmlan_adapter pmadapter = priv->adapter;
+
+ ENTER();
+
+ for (i = 0; i < MAX_NUM_TID; ++i) {
+ ra_list = wlan_wmm_allocate_ralist_node(pmadapter, ra);
+ PRINTM(MINFO, "Creating RA List %p for tid %d\n", ra_list, i);
+ if (!ra_list)
+ break;
+ ra_list->max_amsdu = 0;
+ ra_list->ba_status = BA_STREAM_NOT_SETUP;
+ ra_list->amsdu_in_ampdu = MFALSE;
+ if (queuing_ra_based(priv)) {
+ ra_list->is_11n_enabled = wlan_is_11n_enabled(priv, ra);
+ if (ra_list->is_11n_enabled)
+ ra_list->max_amsdu =
+ get_station_max_amsdu_size(priv, ra);
+ ra_list->tx_pause = wlan_is_tx_pause(priv, ra);
+ } else {
+ ra_list->is_11n_enabled = IS_11N_ENABLED(priv);
+ if (ra_list->is_11n_enabled)
+ ra_list->max_amsdu = priv->max_amsdu;
+ }
+
+ PRINTM_NETINTF(MDATA, priv);
+ PRINTM(MDATA, "ralist %p: is_11n_enabled=%d max_amsdu=%d\n",
+ ra_list, ra_list->is_11n_enabled, ra_list->max_amsdu);
+
+ if (ra_list->is_11n_enabled) {
+ ra_list->packet_count = 0;
+ ra_list->ba_packet_threshold =
+ wlan_get_random_ba_threshold(pmadapter);
+ }
+
+ util_enqueue_list_tail(pmadapter->pmoal_handle,
+ &priv->wmm.tid_tbl_ptr[i].ra_list,
+ (pmlan_linked_list)ra_list, MNULL,
+ MNULL);
+
+ if (!priv->wmm.tid_tbl_ptr[i].ra_list_curr)
+ priv->wmm.tid_tbl_ptr[i].ra_list_curr = ra_list;
+ }
+
+ LEAVE();
+}
+
+/**
+ * @brief Initialize the WMM parameter.
+ *
+ * @param pmadapter Pointer to the mlan_adapter data structure
+ *
+ * @return N/A
+ */
+t_void wlan_init_wmm_param(pmlan_adapter pmadapter)
+{
+ /* Reuse the same structure of WmmAcParameters_t for configuration
+ * purpose here. the definition of acm bit is changed to ucm (user
+ * configuration mode) FW will take the setting of
+ * aifsn,ecw_max,ecw_min, tx_op_limit only when ucm is set to 1.
+ * othewise the default setting/behavoir in firmware will be used.
+ */
+ pmadapter->ac_params[AC_BE].aci_aifsn.acm = 0;
+ pmadapter->ac_params[AC_BE].aci_aifsn.aci = AC_BE;
+ pmadapter->ac_params[AC_BE].aci_aifsn.aifsn = 3;
+ pmadapter->ac_params[AC_BE].ecw.ecw_max = 10;
+ pmadapter->ac_params[AC_BE].ecw.ecw_min = 4;
+ pmadapter->ac_params[AC_BE].tx_op_limit = 0;
+
+ pmadapter->ac_params[AC_BK].aci_aifsn.acm = 0;
+ pmadapter->ac_params[AC_BK].aci_aifsn.aci = AC_BK;
+ pmadapter->ac_params[AC_BK].aci_aifsn.aifsn = 7;
+ pmadapter->ac_params[AC_BK].ecw.ecw_max = 10;
+ pmadapter->ac_params[AC_BK].ecw.ecw_min = 4;
+ pmadapter->ac_params[AC_BK].tx_op_limit = 0;
+
+ pmadapter->ac_params[AC_VI].aci_aifsn.acm = 0;
+ pmadapter->ac_params[AC_VI].aci_aifsn.aci = AC_VI;
+ pmadapter->ac_params[AC_VI].aci_aifsn.aifsn = 2;
+ pmadapter->ac_params[AC_VI].ecw.ecw_max = 4;
+ pmadapter->ac_params[AC_VI].ecw.ecw_min = 3;
+ pmadapter->ac_params[AC_VI].tx_op_limit = 188;
+
+ pmadapter->ac_params[AC_VO].aci_aifsn.acm = 0;
+ pmadapter->ac_params[AC_VO].aci_aifsn.aci = AC_VO;
+ pmadapter->ac_params[AC_VO].aci_aifsn.aifsn = 2;
+ pmadapter->ac_params[AC_VO].ecw.ecw_max = 3;
+ pmadapter->ac_params[AC_VO].ecw.ecw_min = 2;
+ pmadapter->ac_params[AC_VO].tx_op_limit = 102;
+}
+
+/**
+ * @brief Initialize the WMM state information and the WMM data path queues.
+ *
+ * @param pmadapter Pointer to the mlan_adapter data structure
+ *
+ * @return N/A
+ */
+t_void wlan_wmm_init(pmlan_adapter pmadapter)
+{
+ int i, j;
+ pmlan_private priv;
+
+ ENTER();
+
+ for (j = 0; j < pmadapter->priv_num; ++j) {
+ priv = pmadapter->priv[j];
+ if (priv) {
+ for (i = 0; i < MAX_NUM_TID; ++i) {
+ priv->aggr_prio_tbl[i].amsdu =
+ tos_to_tid_inv[i];
+ priv->aggr_prio_tbl[i].ampdu_ap =
+ priv->aggr_prio_tbl[i].ampdu_user =
+ tos_to_tid_inv[i];
+ priv->ibss_ampdu[i] =
+ priv->aggr_prio_tbl[i].ampdu_user;
+ priv->wmm.pkts_queued[i] = 0;
+ priv->wmm.pkts_paused[i] = 0;
+ priv->wmm.tid_tbl_ptr[i].ra_list_curr = MNULL;
+ }
+ priv->wmm.drv_pkt_delay_max = WMM_DRV_DELAY_MAX;
+
+ priv->aggr_prio_tbl[6].amsdu = BA_STREAM_NOT_ALLOWED;
+ priv->aggr_prio_tbl[7].amsdu = BA_STREAM_NOT_ALLOWED;
+ priv->aggr_prio_tbl[6].ampdu_ap =
+ priv->aggr_prio_tbl[6].ampdu_user =
+ BA_STREAM_NOT_ALLOWED;
+ priv->ibss_ampdu[6] = BA_STREAM_NOT_ALLOWED;
+
+ priv->aggr_prio_tbl[7].ampdu_ap =
+ priv->aggr_prio_tbl[7].ampdu_user =
+ BA_STREAM_NOT_ALLOWED;
+ priv->ibss_ampdu[7] = BA_STREAM_NOT_ALLOWED;
+
+ priv->add_ba_param.timeout =
+ MLAN_DEFAULT_BLOCK_ACK_TIMEOUT;
+#ifdef STA_SUPPORT
+ if (priv->bss_type == MLAN_BSS_TYPE_STA) {
+ priv->add_ba_param.tx_win_size =
+ MLAN_STA_AMPDU_DEF_TXWINSIZE;
+ priv->add_ba_param.rx_win_size =
+ MLAN_STA_AMPDU_DEF_RXWINSIZE;
+ }
+#endif
+#ifdef WIFI_DIRECT_SUPPORT
+ if (priv->bss_type == MLAN_BSS_TYPE_WIFIDIRECT) {
+ priv->add_ba_param.tx_win_size =
+ MLAN_WFD_AMPDU_DEF_TXRXWINSIZE;
+ priv->add_ba_param.rx_win_size =
+ MLAN_WFD_AMPDU_DEF_TXRXWINSIZE;
+ }
+#endif
+#ifdef UAP_SUPPORT
+ if (priv->bss_type == MLAN_BSS_TYPE_UAP) {
+ priv->add_ba_param.tx_win_size =
+ MLAN_UAP_AMPDU_DEF_TXWINSIZE;
+ priv->add_ba_param.rx_win_size =
+ MLAN_UAP_AMPDU_DEF_RXWINSIZE;
+ }
+#endif
+ priv->user_rxwinsize = priv->add_ba_param.rx_win_size;
+ priv->add_ba_param.tx_amsdu = MTRUE;
+ priv->add_ba_param.rx_amsdu = MTRUE;
+ memset(priv->adapter, priv->rx_seq, 0xff,
+ sizeof(priv->rx_seq));
+ wlan_wmm_default_queue_priorities(priv);
+ }
+ }
+
+ LEAVE();
+}
+
+/**
+ * @brief Setup the queue priorities and downgrade any queues as required
+ * by the WMM info. Setups default values if WMM is not active
+ * for this association.
+ *
+ * @param priv Pointer to the mlan_private driver data struct
+ *
+ * @return N/A
+ */
+void wlan_wmm_setup_queues(pmlan_private priv)
+{
+ ENTER();
+ wlan_wmm_setup_queue_priorities(priv, MNULL);
+ wlan_wmm_setup_ac_downgrade(priv);
+ LEAVE();
+}
+
+#ifdef STA_SUPPORT
+/**
+ * @brief Send a command to firmware to retrieve the current WMM status
+ *
+ * @param priv Pointer to the mlan_private driver data struct
+ *
+ * @return MLAN_STATUS_SUCCESS; MLAN_STATUS_FAILURE
+ */
+mlan_status wlan_cmd_wmm_status_change(pmlan_private priv)
+{
+ mlan_status ret = MLAN_STATUS_SUCCESS;
+
+ ENTER();
+
+ ret = wlan_prepare_cmd(priv, HostCmd_CMD_WMM_GET_STATUS, 0, 0, 0,
+ MNULL);
+ LEAVE();
+ return ret;
+}
+#endif
+
+/**
+ * @brief Check if wmm TX queue is empty
+ *
+ * @param pmadapter Pointer to the mlan_adapter driver data struct
+ *
+ * @return MFALSE if not empty; MTRUE if empty
+ */
+int wlan_wmm_lists_empty(pmlan_adapter pmadapter)
+{
+ int j;
+ pmlan_private priv;
+
+ ENTER();
+
+ for (j = 0; j < pmadapter->priv_num; ++j) {
+ priv = pmadapter->priv[j];
+ if (priv) {
+ if ((priv->port_ctrl_mode == MTRUE) &&
+ (priv->port_open == MFALSE)) {
+ PRINTM(MINFO,
+ "wmm_lists_empty: PORT_CLOSED Ignore pkts from BSS%d\n",
+ j);
+ continue;
+ }
+ if (priv->tx_pause)
+ continue;
+
+ if (util_scalar_read(
+ pmadapter->pmoal_handle,
+ &priv->wmm.tx_pkts_queued,
+ pmadapter->callbacks.moal_spin_lock,
+ pmadapter->callbacks.moal_spin_unlock)) {
+ LEAVE();
+ return MFALSE;
+ }
+ }
+ }
+
+ LEAVE();
+ return MTRUE;
+}
+
+/**
+ * @brief Get ralist node
+ *
+ * @param priv Pointer to the mlan_private driver data struct
+ * @param tid TID
+ * @param ra_addr Pointer to the route address
+ *
+ * @return ra_list or MNULL
+ */
+raListTbl *wlan_wmm_get_ralist_node(pmlan_private priv, t_u8 tid, t_u8 *ra_addr)
+{
+ raListTbl *ra_list;
+ ENTER();
+ ra_list =
+ (raListTbl *)util_peek_list(priv->adapter->pmoal_handle,
+ &priv->wmm.tid_tbl_ptr[tid].ra_list,
+ MNULL, MNULL);
+ while (ra_list &&
+ (ra_list != (raListTbl *)&priv->wmm.tid_tbl_ptr[tid].ra_list)) {
+ if (!memcmp(priv->adapter, ra_list->ra, ra_addr,
+ MLAN_MAC_ADDR_LENGTH)) {
+ LEAVE();
+ return ra_list;
+ }
+ ra_list = ra_list->pnext;
+ }
+ LEAVE();
+ return MNULL;
+}
+
+/**
+ * @brief Check if RA list is valid or not
+ *
+ * @param priv Pointer to the mlan_private driver data struct
+ * @param ra_list Pointer to raListTbl
+ * @param ptrindex TID pointer index
+ *
+ * @return MTRUE- valid. MFALSE- invalid.
+ */
+int wlan_is_ralist_valid(mlan_private *priv, raListTbl *ra_list, int ptrindex)
+{
+ raListTbl *rlist;
+
+ ENTER();
+
+ rlist = (raListTbl *)util_peek_list(
+ priv->adapter->pmoal_handle,
+ &priv->wmm.tid_tbl_ptr[ptrindex].ra_list, MNULL, MNULL);
+
+ while (rlist &&
+ (rlist !=
+ (raListTbl *)&priv->wmm.tid_tbl_ptr[ptrindex].ra_list)) {
+ if (rlist == ra_list) {
+ LEAVE();
+ return MTRUE;
+ }
+
+ rlist = rlist->pnext;
+ }
+ LEAVE();
+ return MFALSE;
+}
+
+/**
+ * @brief Update an existing raList with a new RA and 11n capability
+ *
+ * @param priv Pointer to the mlan_private driver data struct
+ * @param old_ra Old receiver address
+ * @param new_ra New receiver address
+ *
+ * @return integer count of updated nodes
+ */
+int wlan_ralist_update(mlan_private *priv, t_u8 *old_ra, t_u8 *new_ra)
+{
+ t_u8 tid;
+ int update_count;
+ raListTbl *ra_list;
+
+ ENTER();
+
+ update_count = 0;
+
+ for (tid = 0; tid < MAX_NUM_TID; ++tid) {
+ ra_list = wlan_wmm_get_ralist_node(priv, tid, old_ra);
+
+ if (ra_list) {
+ update_count++;
+
+ if (queuing_ra_based(priv)) {
+ ra_list->is_11n_enabled =
+ wlan_is_11n_enabled(priv, new_ra);
+ if (ra_list->is_11n_enabled)
+ ra_list->max_amsdu =
+ get_station_max_amsdu_size(
+ priv, new_ra);
+ } else {
+ ra_list->is_11n_enabled = IS_11N_ENABLED(priv);
+ if (ra_list->is_11n_enabled)
+ ra_list->max_amsdu = priv->max_amsdu;
+ }
+
+ ra_list->tx_pause = MFALSE;
+ ra_list->packet_count = 0;
+ ra_list->ba_packet_threshold =
+ wlan_get_random_ba_threshold(priv->adapter);
+ ra_list->amsdu_in_ampdu = MFALSE;
+ ra_list->ba_status = BA_STREAM_NOT_SETUP;
+ PRINTM(MINFO,
+ "ralist_update: %p, %d, " MACSTR "-->" MACSTR
+ "\n",
+ ra_list, ra_list->is_11n_enabled,
+ MAC2STR(ra_list->ra), MAC2STR(new_ra));
+
+ memcpy_ext(priv->adapter, ra_list->ra, new_ra,
+ MLAN_MAC_ADDR_LENGTH, MLAN_MAC_ADDR_LENGTH);
+ }
+ }
+
+ LEAVE();
+ return update_count;
+}
+
+/**
+ * @brief Add packet to WMM queue
+ *
+ * @param pmadapter Pointer to the mlan_adapter driver data struct
+ * @param pmbuf Pointer to the mlan_buffer data struct
+ *
+ * @return N/A
+ */
+t_void wlan_wmm_add_buf_txqueue(pmlan_adapter pmadapter, pmlan_buffer pmbuf)
+{
+ pmlan_private priv = pmadapter->priv[pmbuf->bss_index];
+ t_u32 tid;
+ raListTbl *ra_list;
+ t_u8 ra[MLAN_MAC_ADDR_LENGTH], tid_down;
+#ifdef UAP_SUPPORT
+ psta_node sta_ptr = MNULL;
+#endif
+
+ ENTER();
+
+ pmbuf->buf_type = MLAN_BUF_TYPE_DATA;
+ if (!priv->media_connected) {
+ PRINTM_NETINTF(MWARN, priv);
+ PRINTM(MWARN, "Drop packet %p in disconnect state\n", pmbuf);
+ wlan_write_data_complete(pmadapter, pmbuf, MLAN_STATUS_FAILURE);
+ LEAVE();
+ return;
+ }
+ tid = pmbuf->priority;
+ pmadapter->callbacks.moal_spin_lock(pmadapter->pmoal_handle,
+ priv->wmm.ra_list_spinlock);
+ tid_down = wlan_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 (!queuing_ra_based(priv)) {
+ ra_list = (raListTbl *)util_peek_list(
+ pmadapter->pmoal_handle,
+ &priv->wmm.tid_tbl_ptr[tid_down].ra_list, MNULL, MNULL);
+ } else {
+ memcpy_ext(pmadapter, ra, pmbuf->pbuf + pmbuf->data_offset,
+ MLAN_MAC_ADDR_LENGTH, MLAN_MAC_ADDR_LENGTH);
+ /** put multicast/broadcast packet in the same ralist */
+ if (ra[0] & 0x01)
+ memset(pmadapter, ra, 0xff, sizeof(ra));
+#ifdef UAP_SUPPORT
+ else if (priv->bss_type == MLAN_BSS_TYPE_UAP) {
+ sta_ptr = wlan_get_station_entry(priv, ra);
+ if (sta_ptr) {
+ if (!sta_ptr->is_wmm_enabled &&
+ !priv->is_11ac_enabled) {
+ tid_down = wlan_wmm_downgrade_tid(priv,
+ 0xff);
+ }
+ }
+ }
+#endif
+ ra_list = wlan_wmm_get_queue_raptr(priv, tid_down, ra);
+ }
+
+ if (!ra_list) {
+ PRINTM_NETINTF(MWARN, priv);
+ PRINTM(MWARN,
+ "Drop packet %p, ra_list=%p, media_connected=%d\n",
+ pmbuf, ra_list, priv->media_connected);
+ pmadapter->callbacks.moal_spin_unlock(
+ pmadapter->pmoal_handle, priv->wmm.ra_list_spinlock);
+ wlan_write_data_complete(pmadapter, pmbuf, MLAN_STATUS_FAILURE);
+ LEAVE();
+ return;
+ }
+
+ PRINTM_NETINTF(MDATA, priv);
+ PRINTM(MDATA,
+ "Adding pkt %p (priority=%d, tid_down=%d) to ra_list %p\n",
+ pmbuf, pmbuf->priority, tid_down, ra_list);
+ util_enqueue_list_tail(pmadapter->pmoal_handle, &ra_list->buf_head,
+ (pmlan_linked_list)pmbuf, MNULL, MNULL);
+
+ ra_list->total_pkts++;
+ ra_list->packet_count++;
+
+ priv->wmm.pkts_queued[tid_down]++;
+ if (ra_list->tx_pause) {
+ priv->wmm.pkts_paused[tid_down]++;
+ } else {
+ util_scalar_increment(pmadapter->pmoal_handle,
+ &priv->wmm.tx_pkts_queued, MNULL, MNULL);
+ /* if highest_queued_prio < prio(tid_down), set it to
+ * prio(tid_down) */
+ util_scalar_conditional_write(
+ pmadapter->pmoal_handle, &priv->wmm.highest_queued_prio,
+ MLAN_SCALAR_COND_LESS_THAN, tos_to_tid_inv[tid_down],
+ tos_to_tid_inv[tid_down], MNULL, MNULL);
+ }
+ /* 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.
+ */
+ pmadapter->callbacks.moal_get_system_time(
+ pmadapter->pmoal_handle, &pmbuf->in_ts_sec, &pmbuf->in_ts_usec);
+ pmadapter->callbacks.moal_spin_unlock(pmadapter->pmoal_handle,
+ priv->wmm.ra_list_spinlock);
+
+ LEAVE();
+}
+
+#ifdef STA_SUPPORT
+/**
+ * @brief Process the GET_WMM_STATUS command response from firmware
+ *
+ * The GET_WMM_STATUS response may contain multiple TLVs for:
+ * - AC Queue status TLVs
+ * - Current WMM Parameter IE TLV
+ * - Admission Control action frame TLVs
+ *
+ * This function parses the TLVs and then calls further functions
+ * to process any changes in the queue prioritize or state.
+ *
+ * @param priv Pointer to the mlan_private driver data struct
+ * @param ptlv Pointer to the tlv block returned in the response.
+ * @param resp_len Length of TLV block
+ *
+ * @return MLAN_STATUS_SUCCESS
+ */
+mlan_status wlan_ret_wmm_get_status(pmlan_private priv, t_u8 *ptlv,
+ int resp_len)
+{
+ t_u8 *pcurrent = ptlv;
+ t_u32 tlv_len;
+ t_u8 send_wmm_event;
+ MrvlIEtypes_Data_t *ptlv_hdr;
+ MrvlIEtypes_WmmQueueStatus_t *ptlv_wmm_q_status;
+ IEEEtypes_WmmParameter_t *pwmm_param_ie = MNULL;
+ WmmAcStatus_t *pac_status;
+
+ MrvlIETypes_ActionFrame_t *ptlv_action;
+ IEEEtypes_Action_WMM_AddTsRsp_t *padd_ts_rsp;
+ IEEEtypes_Action_WMM_DelTs_t *pdel_ts;
+
+ ENTER();
+
+ send_wmm_event = MFALSE;
+
+ PRINTM(MINFO, "WMM: WMM_GET_STATUS cmdresp received: %d\n", resp_len);
+ HEXDUMP("CMD_RESP: WMM_GET_STATUS", pcurrent, resp_len);
+
+ while (resp_len >= sizeof(ptlv_hdr->header)) {
+ ptlv_hdr = (MrvlIEtypes_Data_t *)pcurrent;
+ tlv_len = wlan_le16_to_cpu(ptlv_hdr->header.len);
+ if ((tlv_len + sizeof(ptlv_hdr->header)) > resp_len) {
+ PRINTM(MERROR,
+ "WMM get status: Error in processing TLV buffer\n");
+ resp_len = 0;
+ continue;
+ }
+
+ switch (wlan_le16_to_cpu(ptlv_hdr->header.type)) {
+ case TLV_TYPE_WMMQSTATUS:
+ ptlv_wmm_q_status =
+ (MrvlIEtypes_WmmQueueStatus_t *)ptlv_hdr;
+ PRINTM(MEVENT, "WMM_STATUS: QSTATUS TLV: %d\n",
+ ptlv_wmm_q_status->queue_index);
+
+ PRINTM(MINFO,
+ "CMD_RESP: WMM_GET_STATUS: QSTATUS TLV: %d, %d, %d\n",
+ ptlv_wmm_q_status->queue_index,
+ ptlv_wmm_q_status->flow_required,
+ ptlv_wmm_q_status->disabled);
+
+ pac_status =
+ &priv->wmm.ac_status[ptlv_wmm_q_status
+ ->queue_index];
+ pac_status->disabled = ptlv_wmm_q_status->disabled;
+ pac_status->flow_required =
+ ptlv_wmm_q_status->flow_required;
+ pac_status->flow_created =
+ ptlv_wmm_q_status->flow_created;
+ break;
+
+ case TLV_TYPE_VENDOR_SPECIFIC_IE: /* WMM_IE */
+ /*
+ * Point the regular IEEE IE 2 bytes into the NXP IE
+ * and setup the IEEE IE type and length byte fields
+ */
+
+ PRINTM(MEVENT, "WMM STATUS: WMM IE\n");
+
+ HEXDUMP("WMM: WMM TLV:", (t_u8 *)ptlv_hdr, tlv_len + 4);
+
+ pwmm_param_ie =
+ (IEEEtypes_WmmParameter_t *)(pcurrent + 2);
+ pwmm_param_ie->vend_hdr.len = (t_u8)tlv_len;
+ pwmm_param_ie->vend_hdr.element_id = WMM_IE;
+
+ PRINTM(MINFO,
+ "CMD_RESP: WMM_GET_STATUS: WMM Parameter Set: %d\n",
+ pwmm_param_ie->qos_info.para_set_count);
+
+ memcpy_ext(priv->adapter,
+ (t_u8 *)&priv->curr_bss_params.bss_descriptor
+ .wmm_ie,
+ pwmm_param_ie,
+ (pwmm_param_ie->vend_hdr.len + 2),
+ sizeof(IEEEtypes_WmmParameter_t));
+ send_wmm_event = MTRUE;
+ break;
+
+ case TLV_TYPE_IEEE_ACTION_FRAME:
+ PRINTM(MEVENT, "WMM_STATUS: IEEE Action Frame\n");
+ ptlv_action = (MrvlIETypes_ActionFrame_t *)pcurrent;
+
+ ptlv_action->actionFrame.wmmAc.tspecAct.category =
+ wlan_le32_to_cpu(ptlv_action->actionFrame.wmmAc
+ .tspecAct.category);
+ if (ptlv_action->actionFrame.wmmAc.tspecAct.category ==
+ IEEE_MGMT_ACTION_CATEGORY_WMM_TSPEC) {
+ ptlv_action->actionFrame.wmmAc.tspecAct.action =
+ wlan_le32_to_cpu(
+ ptlv_action->actionFrame.wmmAc
+ .tspecAct.action);
+ switch (ptlv_action->actionFrame.wmmAc.tspecAct
+ .action) {
+ case TSPEC_ACTION_CODE_ADDTS_RSP:
+ padd_ts_rsp = &ptlv_action->actionFrame
+ .wmmAc.addTsRsp;
+ wlan_send_wmmac_host_event(
+ priv, "ADDTS_RSP",
+ ptlv_action->srcAddr,
+ padd_ts_rsp->tspecIE.TspecBody
+ .TSInfo.TID,
+ padd_ts_rsp->tspecIE.TspecBody
+ .TSInfo.UserPri,
+ padd_ts_rsp->statusCode);
+ break;
+
+ case TSPEC_ACTION_CODE_DELTS:
+ pdel_ts = &ptlv_action->actionFrame
+ .wmmAc.delTs;
+ wlan_send_wmmac_host_event(
+ priv, "DELTS_RX",
+ ptlv_action->srcAddr,
+ pdel_ts->tspecIE.TspecBody
+ .TSInfo.TID,
+ pdel_ts->tspecIE.TspecBody
+ .TSInfo.UserPri,
+ pdel_ts->reasonCode);
+ break;
+
+ case TSPEC_ACTION_CODE_ADDTS_REQ:
+ default:
+ break;
+ }
+ }
+ break;
+
+ default:
+ break;
+ }
+
+ pcurrent += (tlv_len + sizeof(ptlv_hdr->header));
+ resp_len -= (tlv_len + sizeof(ptlv_hdr->header));
+ }
+
+ wlan_wmm_setup_queue_priorities(priv, pwmm_param_ie);
+ wlan_wmm_setup_ac_downgrade(priv);
+
+ if (send_wmm_event) {
+ wlan_recv_event(priv, MLAN_EVENT_ID_FW_WMM_CONFIG_CHANGE,
+ MNULL);
+ }
+
+ LEAVE();
+ return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ * @brief Call back from the command module to allow insertion of a WMM TLV
+ *
+ * If the BSS we are associating to supports WMM, add the required WMM
+ * Information IE to the association request command buffer in the form
+ * of a NXP extended IEEE IE.
+ *
+ * @param priv Pointer to the mlan_private driver data struct
+ * @param ppassoc_buf Output parameter: Pointer to the TLV output buffer,
+ * modified on return to point after the appended WMM TLV
+ * @param pwmm_ie Pointer to the WMM IE for the BSS we are joining
+ * @param pht_cap Pointer to the HT IE for the BSS we are joining
+ *
+ * @return Length of data appended to the association tlv buffer
+ */
+t_u32 wlan_wmm_process_association_req(pmlan_private priv, t_u8 **ppassoc_buf,
+ IEEEtypes_WmmParameter_t *pwmm_ie,
+ IEEEtypes_HTCap_t *pht_cap)
+{
+ MrvlIEtypes_WmmParamSet_t *pwmm_tlv;
+ t_u32 ret_len = 0;
+
+ ENTER();
+
+ /* Null checks */
+ if (!ppassoc_buf) {
+ LEAVE();
+ return 0;
+ }
+ if (!(*ppassoc_buf)) {
+ LEAVE();
+ return 0;
+ }
+
+ if (!pwmm_ie) {
+ LEAVE();
+ return 0;
+ }
+
+ PRINTM(MINFO, "WMM: process assoc req: bss->wmmIe=0x%x\n",
+ pwmm_ie->vend_hdr.element_id);
+
+ if ((priv->wmm_required ||
+ (pht_cap && (pht_cap->ieee_hdr.element_id == HT_CAPABILITY) &&
+ (priv->config_bands & BAND_GN || priv->config_bands & BAND_AN))) &&
+ pwmm_ie->vend_hdr.element_id == WMM_IE) {
+ pwmm_tlv = (MrvlIEtypes_WmmParamSet_t *)*ppassoc_buf;
+ pwmm_tlv->header.type = (t_u16)wmm_info_ie[0];
+ pwmm_tlv->header.type = wlan_cpu_to_le16(pwmm_tlv->header.type);
+ pwmm_tlv->header.len = (t_u16)wmm_info_ie[1];
+ memcpy_ext(priv->adapter, pwmm_tlv->wmm_ie, &wmm_info_ie[2],
+ pwmm_tlv->header.len, pwmm_tlv->header.len);
+ if (pwmm_ie->qos_info.qos_uapsd)
+ memcpy_ext(priv->adapter,
+ (t_u8 *)(pwmm_tlv->wmm_ie +
+ pwmm_tlv->header.len -
+ sizeof(priv->wmm_qosinfo)),
+ &priv->wmm_qosinfo,
+ sizeof(priv->wmm_qosinfo),
+ sizeof(priv->wmm_qosinfo));
+
+ ret_len = sizeof(pwmm_tlv->header) + pwmm_tlv->header.len;
+ pwmm_tlv->header.len = wlan_cpu_to_le16(pwmm_tlv->header.len);
+
+ HEXDUMP("ASSOC_CMD: WMM IE", (t_u8 *)pwmm_tlv, ret_len);
+ *ppassoc_buf += ret_len;
+ }
+
+ LEAVE();
+ return ret_len;
+}
+#endif /* STA_SUPPORT */
+
+/**
+ * @brief Compute 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.
+ *
+ * @param priv Ptr to the mlan_private driver data struct
+ * @param pmbuf Ptr to the mlan_buffer which has been previously timestamped
+ *
+ * @return Time delay of the packet in 2ms units after having limit applied
+ */
+t_u8 wlan_wmm_compute_driver_packet_delay(pmlan_private priv,
+ const pmlan_buffer pmbuf)
+{
+ t_u8 ret_val = 0;
+ t_u32 out_ts_sec, out_ts_usec;
+ t_s32 queue_delay;
+
+ ENTER();
+
+ priv->adapter->callbacks.moal_get_system_time(
+ priv->adapter->pmoal_handle, &out_ts_sec, &out_ts_usec);
+
+ queue_delay = (t_s32)(out_ts_sec - pmbuf->in_ts_sec) * 1000;
+ queue_delay += (t_s32)(out_ts_usec - pmbuf->in_ts_usec) / 1000;
+
+ /*
+ * 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 = (t_u8)(MIN(queue_delay, priv->wmm.drv_pkt_delay_max) >> 1);
+
+ PRINTM(MINFO, "WMM: Pkt Delay: %d ms, %d ms sent to FW\n", queue_delay,
+ ret_val);
+
+ LEAVE();
+ return ret_val;
+}
+
+/**
+ * @brief Transmit the highest priority packet awaiting in the WMM Queues
+ *
+ * @param pmadapter Pointer to the mlan_adapter driver data struct
+ *
+ * @return N/A
+ */
+void wlan_wmm_process_tx(pmlan_adapter pmadapter)
+{
+ ENTER();
+
+ do {
+ if (wlan_dequeue_tx_packet(pmadapter))
+ break;
+#ifdef SDIO
+ if (IS_SD(pmadapter->card_type) &&
+ (pmadapter->ireg & UP_LD_CMD_PORT_HOST_INT_STATUS)) {
+ wlan_send_mp_aggr_buf(pmadapter);
+ break;
+ }
+#endif
+
+#ifdef PCIE
+ if (IS_PCIE(pmadapter->card_type) &&
+ (pmadapter->ireg &
+ pmadapter->pcard_pcie->reg->host_intr_event_rdy))
+ break;
+#endif
+#ifdef USB
+ if (IS_USB(pmadapter->card_type) && pmadapter->event_received)
+ break;
+#endif
+ /* Check if busy */
+ } while (!pmadapter->data_sent && !pmadapter->tx_lock_flag &&
+ !wlan_wmm_lists_empty(pmadapter));
+
+ LEAVE();
+ return;
+}
+
+/**
+ * @brief select wmm queue
+ *
+ * @param pmpriv A pointer to mlan_private structure
+ * @param tid TID 0-7
+ *
+ * @return wmm_queue priority (0-3)
+ */
+t_u8 wlan_wmm_select_queue(mlan_private *pmpriv, t_u8 tid)
+{
+ pmlan_adapter pmadapter = pmpriv->adapter;
+ t_u8 i;
+ mlan_wmm_ac_e ac_down =
+ pmpriv->wmm.ac_down_graded_vals[wlan_wmm_convert_tos_to_ac(
+ pmadapter, tid)];
+
+ ENTER();
+
+ for (i = 0; i < 4; i++) {
+ if (pmpriv->wmm.queue_priority[i] == ac_down) {
+ LEAVE();
+ return i;
+ }
+ }
+ LEAVE();
+ return 0;
+}
+
+/**
+ * @brief Delete tx packets in RA list
+ *
+ * @param priv Pointer to the mlan_private driver data struct
+ * @param ra_list_head ra list header
+ * @param tid tid
+ *
+ * @return N/A
+ */
+static INLINE t_u8 wlan_del_tx_pkts_in_ralist(pmlan_private priv,
+ mlan_list_head *ra_list_head,
+ int tid)
+{
+ raListTbl *ra_list = MNULL;
+ pmlan_adapter pmadapter = priv->adapter;
+ pmlan_buffer pmbuf = MNULL;
+ t_u8 ret = MFALSE;
+ ENTER();
+ ra_list = (raListTbl *)util_peek_list(priv->adapter->pmoal_handle,
+ ra_list_head, MNULL, MNULL);
+ while (ra_list && ra_list != (raListTbl *)ra_list_head) {
+ if (ra_list->total_pkts &&
+ (ra_list->tx_pause ||
+ (ra_list->total_pkts > RX_LOW_THRESHOLD))) {
+ pmbuf = (pmlan_buffer)util_dequeue_list(
+ pmadapter->pmoal_handle, &ra_list->buf_head,
+ MNULL, MNULL);
+ if (pmbuf) {
+ PRINTM(MDATA,
+ "Drop pkts: tid=%d tx_pause=%d pkts=%d " MACSTR
+ "\n",
+ tid, ra_list->tx_pause,
+ ra_list->total_pkts,
+ MAC2STR(ra_list->ra));
+ wlan_write_data_complete(pmadapter, pmbuf,
+ MLAN_STATUS_FAILURE);
+ priv->wmm.pkts_queued[tid]--;
+ priv->num_drop_pkts++;
+ ra_list->total_pkts--;
+ if (ra_list->tx_pause)
+ priv->wmm.pkts_paused[tid]--;
+ else
+ util_scalar_decrement(
+ pmadapter->pmoal_handle,
+ &priv->wmm.tx_pkts_queued,
+ MNULL, MNULL);
+ ret = MTRUE;
+ break;
+ }
+ }
+ ra_list = ra_list->pnext;
+ }
+
+ LEAVE();
+ return ret;
+}
+
+/**
+ * @brief Drop tx pkts
+ *
+ * @param priv Pointer to the mlan_private driver data struct
+ *
+ * @return N/A
+ */
+t_void wlan_drop_tx_pkts(pmlan_private priv)
+{
+ int j;
+ static int i;
+ pmlan_adapter pmadapter = priv->adapter;
+ pmadapter->callbacks.moal_spin_lock(pmadapter->pmoal_handle,
+ priv->wmm.ra_list_spinlock);
+ for (j = 0; j < MAX_NUM_TID; j++, i++) {
+ if (i == MAX_NUM_TID)
+ i = 0;
+ if (wlan_del_tx_pkts_in_ralist(
+ priv, &priv->wmm.tid_tbl_ptr[i].ra_list, i)) {
+ i++;
+ break;
+ }
+ }
+ pmadapter->callbacks.moal_spin_unlock(pmadapter->pmoal_handle,
+ priv->wmm.ra_list_spinlock);
+ return;
+}
+
+/**
+ * @brief Remove peer ralist
+ *
+ * @param priv A pointer to mlan_private
+ * @param mac peer mac address
+ *
+ * @return N/A
+ */
+t_void wlan_wmm_delete_peer_ralist(pmlan_private priv, t_u8 *mac)
+{
+ raListTbl *ra_list;
+ int i;
+ pmlan_adapter pmadapter = priv->adapter;
+ t_u32 pkt_cnt = 0;
+ t_u32 tx_pkts_queued = 0;
+
+ ENTER();
+ pmadapter->callbacks.moal_spin_lock(pmadapter->pmoal_handle,
+ priv->wmm.ra_list_spinlock);
+ for (i = 0; i < MAX_NUM_TID; ++i) {
+ ra_list = wlan_wmm_get_ralist_node(priv, i, mac);
+ if (ra_list) {
+ PRINTM(MINFO, "delete sta ralist %p\n", ra_list);
+ priv->wmm.pkts_queued[i] -= ra_list->total_pkts;
+ if (ra_list->tx_pause)
+ priv->wmm.pkts_paused[i] -= ra_list->total_pkts;
+ else
+ pkt_cnt += ra_list->total_pkts;
+ wlan_wmm_del_pkts_in_ralist_node(priv, ra_list);
+
+ util_unlink_list(pmadapter->pmoal_handle,
+ &priv->wmm.tid_tbl_ptr[i].ra_list,
+ (pmlan_linked_list)ra_list, MNULL,
+ MNULL);
+ pmadapter->callbacks.moal_mfree(pmadapter->pmoal_handle,
+ (t_u8 *)ra_list);
+ if (priv->wmm.tid_tbl_ptr[i].ra_list_curr == ra_list)
+ priv->wmm.tid_tbl_ptr[i].ra_list_curr =
+ (raListTbl *)&priv->wmm.tid_tbl_ptr[i]
+ .ra_list;
+ }
+ }
+ if (pkt_cnt) {
+ tx_pkts_queued = util_scalar_read(pmadapter->pmoal_handle,
+ &priv->wmm.tx_pkts_queued,
+ MNULL, MNULL);
+ tx_pkts_queued -= pkt_cnt;
+ util_scalar_write(priv->adapter->pmoal_handle,
+ &priv->wmm.tx_pkts_queued, tx_pkts_queued,
+ MNULL, MNULL);
+ util_scalar_write(priv->adapter->pmoal_handle,
+ &priv->wmm.highest_queued_prio, HIGH_PRIO_TID,
+ MNULL, MNULL);
+ }
+ pmadapter->callbacks.moal_spin_unlock(pmadapter->pmoal_handle,
+ priv->wmm.ra_list_spinlock);
+ LEAVE();
+}
+
+#ifdef STA_SUPPORT
+
+/**
+ * @brief This function prepares the command of ADDTS
+ *
+ * @param pmpriv A pointer to mlan_private structure
+ * @param cmd A pointer to HostCmd_DS_COMMAND structure
+ * @param pdata_buf A pointer to data buffer
+ * @return MLAN_STATUS_SUCCESS
+ */
+mlan_status wlan_cmd_wmm_addts_req(pmlan_private pmpriv,
+ HostCmd_DS_COMMAND *cmd, t_void *pdata_buf)
+{
+ mlan_ds_wmm_addts *paddts = (mlan_ds_wmm_addts *)pdata_buf;
+ HostCmd_DS_WMM_ADDTS_REQ *pcmd_addts = &cmd->params.add_ts;
+
+ ENTER();
+
+ cmd->command = wlan_cpu_to_le16(HostCmd_CMD_WMM_ADDTS_REQ);
+ cmd->size = wlan_cpu_to_le16(sizeof(pcmd_addts->dialog_token) +
+ sizeof(pcmd_addts->timeout_ms) +
+ sizeof(pcmd_addts->command_result) +
+ sizeof(pcmd_addts->ieee_status_code) +
+ paddts->ie_data_len + S_DS_GEN);
+ cmd->result = 0;
+
+ pcmd_addts->timeout_ms = wlan_cpu_to_le32(paddts->timeout);
+ pcmd_addts->dialog_token = paddts->dialog_tok;
+ memcpy_ext(pmpriv->adapter, pcmd_addts->tspec_data, paddts->ie_data,
+ paddts->ie_data_len, WMM_TSPEC_SIZE);
+
+ LEAVE();
+
+ return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ * @brief This function handles the command response of ADDTS
+ *
+ * @param pmpriv A pointer to mlan_private structure
+ * @param resp A pointer to HostCmd_DS_COMMAND
+ * @param pioctl_buf A pointer to mlan_ioctl_req structure
+ *
+ * @return MLAN_STATUS_SUCCESS
+ */
+mlan_status wlan_ret_wmm_addts_req(pmlan_private pmpriv,
+ const HostCmd_DS_COMMAND *resp,
+ mlan_ioctl_req *pioctl_buf)
+{
+ mlan_ds_wmm_cfg *pwmm = MNULL;
+ mlan_ds_wmm_addts *paddts = MNULL;
+ const HostCmd_DS_WMM_ADDTS_REQ *presp_addts = &resp->params.add_ts;
+
+ ENTER();
+
+ if (pioctl_buf) {
+ pwmm = (mlan_ds_wmm_cfg *)pioctl_buf->pbuf;
+ paddts = (mlan_ds_wmm_addts *)&pwmm->param.addts;
+ paddts->result = wlan_le32_to_cpu(presp_addts->command_result);
+ paddts->dialog_tok = presp_addts->dialog_token;
+ paddts->status_code = (t_u32)presp_addts->ieee_status_code;
+
+ if (paddts->result == MLAN_CMD_RESULT_SUCCESS) {
+ /* The tspecData field is potentially variable in size
+ * due to extra IEs that may have been in the ADDTS
+ * response action frame. Calculate the data length from
+ * the firmware command response.
+ */
+ paddts->ie_data_len =
+ (t_u8)(resp->size -
+ sizeof(presp_addts->command_result) -
+ sizeof(presp_addts->timeout_ms) -
+ sizeof(presp_addts->dialog_token) -
+ sizeof(presp_addts->ieee_status_code) -
+ S_DS_GEN);
+
+ /* Copy the TSPEC data include any extra IEs after the
+ * TSPEC */
+ memcpy_ext(pmpriv->adapter, paddts->ie_data,
+ presp_addts->tspec_data, paddts->ie_data_len,
+ sizeof(paddts->ie_data));
+ } else {
+ paddts->ie_data_len = 0;
+ }
+ PRINTM(MINFO, "TSPEC: ADDTS ret = %d,%d sz=%d\n",
+ paddts->result, paddts->status_code,
+ paddts->ie_data_len);
+
+ HEXDUMP("TSPEC: ADDTS data", paddts->ie_data,
+ paddts->ie_data_len);
+ }
+
+ LEAVE();
+ return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ * @brief This function prepares the command of DELTS
+ *
+ * @param pmpriv A pointer to mlan_private structure
+ * @param cmd A pointer to HostCmd_DS_COMMAND structure
+ * @param pdata_buf A pointer to data buffer
+ * @return MLAN_STATUS_SUCCESS
+ */
+mlan_status wlan_cmd_wmm_delts_req(pmlan_private pmpriv,
+ HostCmd_DS_COMMAND *cmd, t_void *pdata_buf)
+{
+ mlan_ds_wmm_delts *pdelts = (mlan_ds_wmm_delts *)pdata_buf;
+ HostCmd_DS_WMM_DELTS_REQ *pcmd_delts = &cmd->params.del_ts;
+
+ ENTER();
+
+ cmd->command = wlan_cpu_to_le16(HostCmd_CMD_WMM_DELTS_REQ);
+ cmd->size = wlan_cpu_to_le16(sizeof(pcmd_delts->dialog_token) +
+ sizeof(pcmd_delts->command_result) +
+ sizeof(pcmd_delts->ieee_reason_code) +
+ pdelts->ie_data_len + S_DS_GEN);
+ cmd->result = 0;
+ pcmd_delts->ieee_reason_code = (t_u8)pdelts->status_code;
+ memcpy_ext(pmpriv->adapter, pcmd_delts->tspec_data, pdelts->ie_data,
+ pdelts->ie_data_len, WMM_TSPEC_SIZE);
+
+ LEAVE();
+
+ return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ * @brief This function handles the command response of DELTS
+ *
+ * @param pmpriv A pointer to mlan_private structure
+ * @param resp A pointer to HostCmd_DS_COMMAND
+ * @param pioctl_buf A pointer to mlan_ioctl_req structure
+ *
+ * @return MLAN_STATUS_SUCCESS
+ */
+mlan_status wlan_ret_wmm_delts_req(pmlan_private pmpriv,
+ const HostCmd_DS_COMMAND *resp,
+ mlan_ioctl_req *pioctl_buf)
+{
+ mlan_ds_wmm_cfg *pwmm;
+ IEEEtypes_WMM_TSPEC_t *ptspec_ie;
+ const HostCmd_DS_WMM_DELTS_REQ *presp_delts = &resp->params.del_ts;
+
+ ENTER();
+
+ if (pioctl_buf) {
+ pwmm = (mlan_ds_wmm_cfg *)pioctl_buf->pbuf;
+ pwmm->param.delts.result =
+ wlan_le32_to_cpu(presp_delts->command_result);
+
+ PRINTM(MINFO, "TSPEC: DELTS result = %d\n",
+ presp_delts->command_result);
+
+ if (pwmm->param.delts.result == 0) {
+ ptspec_ie = (IEEEtypes_WMM_TSPEC_t *)
+ presp_delts->tspec_data;
+ wlan_send_wmmac_host_event(
+ pmpriv, "DELTS_TX", MNULL,
+ ptspec_ie->TspecBody.TSInfo.TID,
+ ptspec_ie->TspecBody.TSInfo.UserPri,
+ presp_delts->ieee_reason_code);
+ }
+ }
+
+ LEAVE();
+ return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ * @brief This function prepares the command of WMM_QUEUE_STATS
+ *
+ * @param pmpriv A pointer to mlan_private structure
+ * @param cmd A pointer to HostCmd_DS_COMMAND structure
+ * @param pdata_buf A pointer to data buffer
+ * @return MLAN_STATUS_SUCCESS
+ */
+mlan_status wlan_cmd_wmm_queue_stats(pmlan_private pmpriv,
+ HostCmd_DS_COMMAND *cmd, t_void *pdata_buf)
+{
+ mlan_ds_wmm_queue_stats *pqstats = (mlan_ds_wmm_queue_stats *)pdata_buf;
+ HostCmd_DS_WMM_QUEUE_STATS *pcmd_qstats = &cmd->params.queue_stats;
+ t_u8 id;
+
+ ENTER();
+
+ cmd->command = wlan_cpu_to_le16(HostCmd_CMD_WMM_QUEUE_STATS);
+ cmd->size =
+ wlan_cpu_to_le16(sizeof(HostCmd_DS_WMM_QUEUE_STATS) + S_DS_GEN);
+ cmd->result = 0;
+
+ pcmd_qstats->action = pqstats->action;
+ pcmd_qstats->select_is_userpri = 1;
+ pcmd_qstats->select_bin = pqstats->user_priority;
+ pcmd_qstats->pkt_count = wlan_cpu_to_le16(pqstats->pkt_count);
+ pcmd_qstats->pkt_loss = wlan_cpu_to_le16(pqstats->pkt_loss);
+ pcmd_qstats->avg_queue_delay =
+ wlan_cpu_to_le32(pqstats->avg_queue_delay);
+ pcmd_qstats->avg_tx_delay = wlan_cpu_to_le32(pqstats->avg_tx_delay);
+ pcmd_qstats->used_time = wlan_cpu_to_le16(pqstats->used_time);
+ pcmd_qstats->policed_time = wlan_cpu_to_le16(pqstats->policed_time);
+ for (id = 0; id < MLAN_WMM_STATS_PKTS_HIST_BINS; id++) {
+ pcmd_qstats->delay_histogram[id] =
+ wlan_cpu_to_le16(pqstats->delay_histogram[id]);
+ }
+
+ LEAVE();
+ return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ * @brief This function handles the command response of WMM_QUEUE_STATS
+ *
+ * @param pmpriv A pointer to mlan_private structure
+ * @param resp A pointer to HostCmd_DS_COMMAND
+ * @param pioctl_buf A pointer to mlan_ioctl_req structure
+ *
+ * @return MLAN_STATUS_SUCCESS
+ */
+mlan_status wlan_ret_wmm_queue_stats(pmlan_private pmpriv,
+ const HostCmd_DS_COMMAND *resp,
+ mlan_ioctl_req *pioctl_buf)
+{
+ mlan_ds_wmm_cfg *pwmm = MNULL;
+ mlan_ds_wmm_queue_stats *pqstats = MNULL;
+ const HostCmd_DS_WMM_QUEUE_STATS *presp_qstats =
+ &resp->params.queue_stats;
+ t_u8 id;
+
+ ENTER();
+
+ if (pioctl_buf) {
+ pwmm = (mlan_ds_wmm_cfg *)pioctl_buf->pbuf;
+ pqstats = (mlan_ds_wmm_queue_stats *)&pwmm->param.q_stats;
+
+ pqstats->action = presp_qstats->action;
+ pqstats->user_priority = presp_qstats->select_bin;
+ pqstats->pkt_count = wlan_le16_to_cpu(presp_qstats->pkt_count);
+ pqstats->pkt_loss = wlan_le16_to_cpu(presp_qstats->pkt_loss);
+ pqstats->avg_queue_delay =
+ wlan_le32_to_cpu(presp_qstats->avg_queue_delay);
+ pqstats->avg_tx_delay =
+ wlan_le32_to_cpu(presp_qstats->avg_tx_delay);
+ pqstats->used_time = wlan_le16_to_cpu(presp_qstats->used_time);
+ pqstats->policed_time =
+ wlan_le16_to_cpu(presp_qstats->policed_time);
+ for (id = 0; id < MLAN_WMM_STATS_PKTS_HIST_BINS; id++) {
+ pqstats->delay_histogram[id] = wlan_le16_to_cpu(
+ presp_qstats->delay_histogram[id]);
+ }
+ }
+
+ LEAVE();
+ return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ * @brief This function prepares the command of WMM_TS_STATUS
+ *
+ * @param pmpriv A pointer to mlan_private structure
+ * @param cmd A pointer to HostCmd_DS_COMMAND structure
+ * @param pdata_buf A pointer to data buffer
+ * @return MLAN_STATUS_SUCCESS
+ */
+mlan_status wlan_cmd_wmm_ts_status(pmlan_private pmpriv,
+ HostCmd_DS_COMMAND *cmd, t_void *pdata_buf)
+{
+ mlan_ds_wmm_ts_status *pts_status = (mlan_ds_wmm_ts_status *)pdata_buf;
+ HostCmd_DS_WMM_TS_STATUS *pcmd_ts_status = &cmd->params.ts_status;
+
+ ENTER();
+
+ cmd->command = wlan_cpu_to_le16(HostCmd_CMD_WMM_TS_STATUS);
+ cmd->size =
+ wlan_cpu_to_le16(sizeof(HostCmd_DS_WMM_TS_STATUS) + S_DS_GEN);
+ cmd->result = 0;
+
+ memcpy_ext(pmpriv->adapter, (t_void *)pcmd_ts_status,
+ (t_void *)pts_status, sizeof(HostCmd_DS_WMM_TS_STATUS),
+ sizeof(HostCmd_DS_WMM_TS_STATUS));
+
+ LEAVE();
+ return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ * @brief This function handles the command response of WMM_TS_STATUS
+ *
+ * @param pmpriv A pointer to mlan_private structure
+ * @param resp A pointer to HostCmd_DS_COMMAND
+ * @param pioctl_buf A pointer to mlan_ioctl_req structure
+ *
+ * @return MLAN_STATUS_SUCCESS
+ */
+mlan_status wlan_ret_wmm_ts_status(pmlan_private pmpriv,
+ HostCmd_DS_COMMAND *resp,
+ mlan_ioctl_req *pioctl_buf)
+{
+ mlan_ds_wmm_cfg *pwmm = MNULL;
+ HostCmd_DS_WMM_TS_STATUS *presp_ts_status = &resp->params.ts_status;
+
+ ENTER();
+
+ if (pioctl_buf) {
+ pwmm = (mlan_ds_wmm_cfg *)pioctl_buf->pbuf;
+ presp_ts_status->medium_time =
+ wlan_le16_to_cpu(presp_ts_status->medium_time);
+ memcpy_ext(pmpriv->adapter, (t_void *)&pwmm->param.ts_status,
+ (t_void *)presp_ts_status,
+ sizeof(mlan_ds_wmm_ts_status),
+ sizeof(mlan_ds_wmm_ts_status));
+ }
+
+ LEAVE();
+ return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ * @brief Set/Get WMM status
+ *
+ * @param pmadapter A pointer to mlan_adapter structure
+ * @param pioctl_req A pointer to ioctl request buffer
+ *
+ * @return MLAN_STATUS_SUCCESS --success
+ */
+static mlan_status wlan_wmm_ioctl_enable(pmlan_adapter pmadapter,
+ pmlan_ioctl_req pioctl_req)
+{
+ mlan_status ret = MLAN_STATUS_SUCCESS;
+ mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index];
+ mlan_ds_wmm_cfg *wmm = MNULL;
+ ENTER();
+ wmm = (mlan_ds_wmm_cfg *)pioctl_req->pbuf;
+ if (pioctl_req->action == MLAN_ACT_GET)
+ wmm->param.wmm_enable = (t_u32)pmpriv->wmm_required;
+ else
+ pmpriv->wmm_required = (t_u8)wmm->param.wmm_enable;
+ pioctl_req->data_read_written = sizeof(t_u32) + MLAN_SUB_COMMAND_SIZE;
+ LEAVE();
+ return ret;
+}
+
+/**
+ * @brief Set/Get WMM QoS configuration
+ *
+ * @param pmadapter A pointer to mlan_adapter structure
+ * @param pioctl_req A pointer to ioctl request buffer
+ *
+ * @return MLAN_STATUS_SUCCESS --success
+ */
+static mlan_status wlan_wmm_ioctl_qos(pmlan_adapter pmadapter,
+ pmlan_ioctl_req pioctl_req)
+{
+ mlan_status ret = MLAN_STATUS_SUCCESS;
+ mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index];
+ mlan_ds_wmm_cfg *wmm = MNULL;
+
+ ENTER();
+
+ wmm = (mlan_ds_wmm_cfg *)pioctl_req->pbuf;
+
+ if (pioctl_req->action == MLAN_ACT_GET)
+ wmm->param.qos_cfg = pmpriv->wmm_qosinfo;
+ else {
+ pmpriv->wmm_qosinfo = wmm->param.qos_cfg;
+ }
+
+ pioctl_req->data_read_written = sizeof(t_u8) + MLAN_SUB_COMMAND_SIZE;
+
+ LEAVE();
+ return ret;
+}
+
+/**
+ * @brief Request for add a TSPEC
+ *
+ * @param pmadapter A pointer to mlan_adapter structure
+ * @param pioctl_req A pointer to ioctl request buffer
+ *
+ * @return MLAN_STATUS_PENDING --success, otherwise fail
+ */
+static mlan_status wlan_wmm_ioctl_addts_req(pmlan_adapter pmadapter,
+ pmlan_ioctl_req pioctl_req)
+{
+ mlan_status ret = MLAN_STATUS_SUCCESS;
+ pmlan_private pmpriv = pmadapter->priv[pioctl_req->bss_index];
+ mlan_ds_wmm_cfg *cfg = MNULL;
+
+ ENTER();
+ cfg = (mlan_ds_wmm_cfg *)pioctl_req->pbuf;
+
+ /* Send request to firmware */
+ ret = wlan_prepare_cmd(pmpriv, HostCmd_CMD_WMM_ADDTS_REQ, 0, 0,
+ (t_void *)pioctl_req,
+ (t_void *)&cfg->param.addts);
+
+ if (ret == MLAN_STATUS_SUCCESS)
+ ret = MLAN_STATUS_PENDING;
+
+ LEAVE();
+ return ret;
+}
+
+/**
+ * @brief Request for delete a TSPEC
+ *
+ * @param pmadapter A pointer to mlan_adapter structure
+ * @param pioctl_req A pointer to ioctl request buffer
+ *
+ * @return MLAN_STATUS_PENDING --success, otherwise fail
+ */
+static mlan_status wlan_wmm_ioctl_delts_req(pmlan_adapter pmadapter,
+ pmlan_ioctl_req pioctl_req)
+{
+ mlan_status ret = MLAN_STATUS_SUCCESS;
+ pmlan_private pmpriv = pmadapter->priv[pioctl_req->bss_index];
+ mlan_ds_wmm_cfg *cfg = MNULL;
+
+ ENTER();
+ cfg = (mlan_ds_wmm_cfg *)pioctl_req->pbuf;
+
+ /* Send request to firmware */
+ ret = wlan_prepare_cmd(pmpriv, HostCmd_CMD_WMM_DELTS_REQ, 0, 0,
+ (t_void *)pioctl_req,
+ (t_void *)&cfg->param.delts);
+
+ if (ret == MLAN_STATUS_SUCCESS)
+ ret = MLAN_STATUS_PENDING;
+
+ LEAVE();
+ return ret;
+}
+
+/**
+ * @brief To get and start/stop queue stats on a WMM AC
+ *
+ * @param pmadapter A pointer to mlan_adapter structure
+ * @param pioctl_req A pointer to ioctl request buffer
+ *
+ * @return MLAN_STATUS_PENDING --success, otherwise fail
+ */
+static mlan_status wlan_wmm_ioctl_queue_stats(pmlan_adapter pmadapter,
+ pmlan_ioctl_req pioctl_req)
+{
+ mlan_status ret = MLAN_STATUS_SUCCESS;
+ pmlan_private pmpriv = pmadapter->priv[pioctl_req->bss_index];
+ mlan_ds_wmm_cfg *cfg = MNULL;
+
+ ENTER();
+ cfg = (mlan_ds_wmm_cfg *)pioctl_req->pbuf;
+
+ /* Send request to firmware */
+ ret = wlan_prepare_cmd(pmpriv, HostCmd_CMD_WMM_QUEUE_STATS, 0, 0,
+ (t_void *)pioctl_req,
+ (t_void *)&cfg->param.q_stats);
+
+ if (ret == MLAN_STATUS_SUCCESS)
+ ret = MLAN_STATUS_PENDING;
+
+ LEAVE();
+ return ret;
+}
+
+/**
+ * @brief Get the status of the WMM AC queues
+ *
+ * @param pmadapter A pointer to mlan_adapter structure
+ * @param pioctl_req A pointer to ioctl request buffer
+ *
+ * @return MLAN_STATUS_SUCCESS --success
+ */
+static mlan_status wlan_wmm_ioctl_queue_status(pmlan_adapter pmadapter,
+ pmlan_ioctl_req pioctl_req)
+{
+ mlan_status ret = MLAN_STATUS_SUCCESS;
+ pmlan_private pmpriv = pmadapter->priv[pioctl_req->bss_index];
+ mlan_ds_wmm_cfg *cfg = MNULL;
+ mlan_ds_wmm_queue_status *pqstatus = MNULL;
+ WmmAcStatus_t *pac_status = MNULL;
+ mlan_wmm_ac_e ac_idx;
+
+ ENTER();
+
+ cfg = (mlan_ds_wmm_cfg *)pioctl_req->pbuf;
+ pqstatus = (mlan_ds_wmm_queue_status *)&cfg->param.q_status;
+
+ for (ac_idx = WMM_AC_BK; ac_idx <= WMM_AC_VO; ac_idx++) {
+ pac_status = &pmpriv->wmm.ac_status[ac_idx];
+
+ /* Firmware status */
+ pqstatus->ac_status[ac_idx].flow_required =
+ pac_status->flow_required;
+ pqstatus->ac_status[ac_idx].flow_created =
+ pac_status->flow_created;
+ pqstatus->ac_status[ac_idx].disabled = pac_status->disabled;
+
+ /* ACM bit reflected in firmware status (redundant) */
+ pqstatus->ac_status[ac_idx].wmm_acm = pac_status->flow_required;
+ }
+
+ LEAVE();
+ return ret;
+}
+
+/**
+ * @brief Get the status of the WMM Traffic Streams
+ *
+ * @param pmadapter A pointer to mlan_adapter structure
+ * @param pioctl_req A pointer to ioctl request buffer
+ *
+ * @return MLAN_STATUS_PENDING --success, otherwise fail
+ */
+static mlan_status wlan_wmm_ioctl_ts_status(pmlan_adapter pmadapter,
+ pmlan_ioctl_req pioctl_req)
+{
+ mlan_status ret = MLAN_STATUS_SUCCESS;
+ pmlan_private pmpriv = pmadapter->priv[pioctl_req->bss_index];
+ mlan_ds_wmm_cfg *cfg = MNULL;
+
+ ENTER();
+
+ cfg = (mlan_ds_wmm_cfg *)pioctl_req->pbuf;
+
+ /* Send request to firmware */
+ ret = wlan_prepare_cmd(pmpriv, HostCmd_CMD_WMM_TS_STATUS, 0, 0,
+ (t_void *)pioctl_req,
+ (t_void *)&cfg->param.ts_status);
+
+ if (ret == MLAN_STATUS_SUCCESS)
+ ret = MLAN_STATUS_PENDING;
+
+ LEAVE();
+ return ret;
+}
+#endif /* STA_SUPPORT */
+
+/**
+ * @brief This function prepares the command of WMM_PARAM_CONFIG
+ *
+ * @param pmpriv A pointer to mlan_private structure
+ * @param cmd A pointer to HostCmd_DS_COMMAND structure
+ * @param cmd_action cmd action.
+ * @param pdata_buf A pointer to data buffer
+ * @return MLAN_STATUS_SUCCESS
+ */
+mlan_status wlan_cmd_wmm_param_config(pmlan_private pmpriv,
+ HostCmd_DS_COMMAND *cmd, t_u8 cmd_action,
+ t_void *pdata_buf)
+{
+ wmm_ac_parameters_t *ac_params = (wmm_ac_parameters_t *)pdata_buf;
+ HostCmd_DS_WMM_PARAM_CONFIG *pcmd_cfg = &cmd->params.param_config;
+ t_u8 i = 0;
+
+ ENTER();
+
+ cmd->command = wlan_cpu_to_le16(HostCmd_CMD_WMM_PARAM_CONFIG);
+ cmd->size = wlan_cpu_to_le16(sizeof(HostCmd_DS_WMM_PARAM_CONFIG) +
+ S_DS_GEN);
+ cmd->result = 0;
+
+ pcmd_cfg->action = cmd_action;
+ if (cmd_action == HostCmd_ACT_GEN_SET) {
+ memcpy_ext(pmpriv->adapter, pcmd_cfg->ac_params, ac_params,
+ sizeof(wmm_ac_parameters_t) * MAX_AC_QUEUES,
+ sizeof(wmm_ac_parameters_t) * MAX_AC_QUEUES);
+ for (i = 0; i < MAX_AC_QUEUES; i++) {
+ pcmd_cfg->ac_params[i].tx_op_limit = wlan_cpu_to_le16(
+ pcmd_cfg->ac_params[i].tx_op_limit);
+ }
+ }
+ LEAVE();
+ return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ * @brief This function handles the command response of WMM_PARAM_CONFIG
+ *
+ * @param pmpriv A pointer to mlan_private structure
+ * @param resp A pointer to HostCmd_DS_COMMAND
+ * @param pioctl_buf A pointer to mlan_ioctl_req structure
+ *
+ * @return MLAN_STATUS_SUCCESS
+ */
+mlan_status wlan_ret_wmm_param_config(pmlan_private pmpriv,
+ const HostCmd_DS_COMMAND *resp,
+ mlan_ioctl_req *pioctl_buf)
+{
+ mlan_ds_wmm_cfg *pwmm = MNULL;
+ HostCmd_DS_WMM_PARAM_CONFIG *pcfg =
+ (HostCmd_DS_WMM_PARAM_CONFIG *)&resp->params.param_config;
+ t_u8 i;
+
+ ENTER();
+
+ if (pioctl_buf) {
+ pwmm = (mlan_ds_wmm_cfg *)pioctl_buf->pbuf;
+ for (i = 0; i < MAX_AC_QUEUES; i++) {
+ pcfg->ac_params[i].tx_op_limit = wlan_le16_to_cpu(
+ pcfg->ac_params[i].tx_op_limit);
+ }
+ memcpy_ext(pmpriv->adapter, pwmm->param.ac_params,
+ pcfg->ac_params,
+ sizeof(wmm_ac_parameters_t) * MAX_AC_QUEUES,
+ sizeof(wmm_ac_parameters_t) * MAX_AC_QUEUES);
+ }
+
+ LEAVE();
+ return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ * @brief This function prepares the command of WMM_QUEUE_CONFIG
+ *
+ * @param pmpriv A pointer to mlan_private structure
+ * @param cmd A pointer to HostCmd_DS_COMMAND structure
+ * @param pdata_buf A pointer to data buffer
+ * @return MLAN_STATUS_SUCCESS
+ */
+mlan_status wlan_cmd_wmm_queue_config(pmlan_private pmpriv,
+ HostCmd_DS_COMMAND *cmd,
+ t_void *pdata_buf)
+{
+ mlan_ds_wmm_queue_config *pqcfg = (mlan_ds_wmm_queue_config *)pdata_buf;
+ HostCmd_DS_WMM_QUEUE_CONFIG *pcmd_qcfg = &cmd->params.queue_config;
+
+ ENTER();
+
+ cmd->command = wlan_cpu_to_le16(HostCmd_CMD_WMM_QUEUE_CONFIG);
+ cmd->size = wlan_cpu_to_le16(
+ sizeof(pcmd_qcfg->action) + sizeof(pcmd_qcfg->access_category) +
+ sizeof(pcmd_qcfg->msdu_lifetime_expiry) + S_DS_GEN);
+ cmd->result = 0;
+
+ pcmd_qcfg->action = pqcfg->action;
+ pcmd_qcfg->access_category = pqcfg->access_category;
+ pcmd_qcfg->msdu_lifetime_expiry =
+ wlan_cpu_to_le16(pqcfg->msdu_lifetime_expiry);
+
+ LEAVE();
+ return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ * @brief This function handles the command response of WMM_QUEUE_CONFIG
+ *
+ * @param pmpriv A pointer to mlan_private structure
+ * @param resp A pointer to HostCmd_DS_COMMAND
+ * @param pioctl_buf A pointer to mlan_ioctl_req structure
+ *
+ * @return MLAN_STATUS_SUCCESS
+ */
+mlan_status wlan_ret_wmm_queue_config(pmlan_private pmpriv,
+ const HostCmd_DS_COMMAND *resp,
+ mlan_ioctl_req *pioctl_buf)
+{
+ mlan_ds_wmm_cfg *pwmm = MNULL;
+ const HostCmd_DS_WMM_QUEUE_CONFIG *presp_qcfg =
+ &resp->params.queue_config;
+
+ ENTER();
+
+ if (pioctl_buf) {
+ pwmm = (mlan_ds_wmm_cfg *)pioctl_buf->pbuf;
+ pwmm->param.q_cfg.action = wlan_le32_to_cpu(presp_qcfg->action);
+ pwmm->param.q_cfg.access_category =
+ wlan_le32_to_cpu(presp_qcfg->access_category);
+ pwmm->param.q_cfg.msdu_lifetime_expiry =
+ wlan_le16_to_cpu(presp_qcfg->msdu_lifetime_expiry);
+ }
+
+ LEAVE();
+ return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ * @brief Set/Get a specified AC Queue's parameters
+ *
+ * @param pmadapter A pointer to mlan_adapter structure
+ * @param pioctl_req A pointer to ioctl request buffer
+ *
+ * @return MLAN_STATUS_PENDING --success, otherwise fail
+ */
+static mlan_status wlan_wmm_ioctl_queue_config(pmlan_adapter pmadapter,
+ pmlan_ioctl_req pioctl_req)
+{
+ mlan_status ret = MLAN_STATUS_SUCCESS;
+ pmlan_private pmpriv = pmadapter->priv[pioctl_req->bss_index];
+ mlan_ds_wmm_cfg *cfg = MNULL;
+
+ ENTER();
+ cfg = (mlan_ds_wmm_cfg *)pioctl_req->pbuf;
+
+ /* Send request to firmware */
+ ret = wlan_prepare_cmd(pmpriv, HostCmd_CMD_WMM_QUEUE_CONFIG, 0, 0,
+ (t_void *)pioctl_req,
+ (t_void *)&cfg->param.q_cfg);
+
+ if (ret == MLAN_STATUS_SUCCESS)
+ ret = MLAN_STATUS_PENDING;
+
+ LEAVE();
+ return ret;
+}
+
+/**
+ * @brief WMM configuration handler
+ *
+ * @param pmadapter A pointer to mlan_adapter structure
+ * @param pioctl_req A pointer to ioctl request buffer
+ *
+ * @return MLAN_STATUS_SUCCESS --success, otherwise fail
+ */
+mlan_status wlan_wmm_cfg_ioctl(pmlan_adapter pmadapter,
+ pmlan_ioctl_req pioctl_req)
+{
+ mlan_status status = MLAN_STATUS_SUCCESS;
+ mlan_ds_wmm_cfg *wmm = MNULL;
+
+ ENTER();
+
+ if (pioctl_req->buf_len < sizeof(mlan_ds_wmm_cfg)) {
+ PRINTM(MWARN, "MLAN bss IOCTL length is too short.\n");
+ pioctl_req->data_read_written = 0;
+ pioctl_req->buf_len_needed = sizeof(mlan_ds_wmm_cfg);
+ pioctl_req->status_code = MLAN_ERROR_INVALID_PARAMETER;
+ LEAVE();
+ return MLAN_STATUS_RESOURCE;
+ }
+ wmm = (mlan_ds_wmm_cfg *)pioctl_req->pbuf;
+ switch (wmm->sub_command) {
+#ifdef STA_SUPPORT
+ case MLAN_OID_WMM_CFG_ENABLE:
+ status = wlan_wmm_ioctl_enable(pmadapter, pioctl_req);
+ break;
+ case MLAN_OID_WMM_CFG_QOS:
+ status = wlan_wmm_ioctl_qos(pmadapter, pioctl_req);
+ break;
+ case MLAN_OID_WMM_CFG_ADDTS:
+ status = wlan_wmm_ioctl_addts_req(pmadapter, pioctl_req);
+ break;
+ case MLAN_OID_WMM_CFG_DELTS:
+ status = wlan_wmm_ioctl_delts_req(pmadapter, pioctl_req);
+ break;
+ case MLAN_OID_WMM_CFG_QUEUE_STATS:
+ status = wlan_wmm_ioctl_queue_stats(pmadapter, pioctl_req);
+ break;
+ case MLAN_OID_WMM_CFG_QUEUE_STATUS:
+ status = wlan_wmm_ioctl_queue_status(pmadapter, pioctl_req);
+ break;
+ case MLAN_OID_WMM_CFG_TS_STATUS:
+ status = wlan_wmm_ioctl_ts_status(pmadapter, pioctl_req);
+ break;
+#endif
+ case MLAN_OID_WMM_CFG_QUEUE_CONFIG:
+ status = wlan_wmm_ioctl_queue_config(pmadapter, pioctl_req);
+ break;
+ default:
+ pioctl_req->status_code = MLAN_ERROR_IOCTL_INVALID;
+ status = MLAN_STATUS_FAILURE;
+ break;
+ }
+ LEAVE();
+ return status;
+}
+
+/**
+ * @brief Get ralist info
+ *
+ * @param priv A pointer to mlan_private structure
+ * @param buf A pointer to ralist_info structure
+ * @return number of ralist entry
+ *
+ */
+int wlan_get_ralist_info(mlan_private *priv, ralist_info *buf)
+{
+ ralist_info *plist = buf;
+ mlan_list_head *ra_list_head = MNULL;
+ raListTbl *ra_list;
+ int i;
+ int count = 0;
+ for (i = 0; i < MAX_NUM_TID; i++) {
+ ra_list_head = &priv->wmm.tid_tbl_ptr[i].ra_list;
+ ra_list =
+ (raListTbl *)util_peek_list(priv->adapter->pmoal_handle,
+ ra_list_head, MNULL, MNULL);
+ while (ra_list && ra_list != (raListTbl *)ra_list_head) {
+ if (ra_list->total_pkts) {
+ plist->total_pkts = ra_list->total_pkts;
+ plist->tid = i;
+ plist->tx_pause = ra_list->tx_pause;
+ memcpy_ext(priv->adapter, plist->ra,
+ ra_list->ra, MLAN_MAC_ADDR_LENGTH,
+ MLAN_MAC_ADDR_LENGTH);
+ plist++;
+ count++;
+ if (count >= MLAN_MAX_RALIST_NUM)
+ break;
+ }
+ ra_list = ra_list->pnext;
+ }
+ }
+ LEAVE();
+ return count;
+}
+
+/**
+ * @brief dump ralist info
+ *
+ * @param priv A pointer to mlan_private structure
+ *
+ * @return N/A
+ *
+ */
+void wlan_dump_ralist(mlan_private *priv)
+{
+ mlan_list_head *ra_list_head = MNULL;
+ raListTbl *ra_list;
+ mlan_adapter *pmadapter = priv->adapter;
+ int i;
+ t_u32 tx_pkts_queued;
+
+ tx_pkts_queued =
+ util_scalar_read(pmadapter->pmoal_handle,
+ &priv->wmm.tx_pkts_queued, MNULL, MNULL);
+ PRINTM(MERROR, "bss_index = %d, tx_pkts_queued = %d\n", priv->bss_index,
+ tx_pkts_queued);
+ if (!tx_pkts_queued)
+ return;
+ for (i = 0; i < MAX_NUM_TID; i++) {
+ ra_list_head = &priv->wmm.tid_tbl_ptr[i].ra_list;
+ ra_list =
+ (raListTbl *)util_peek_list(priv->adapter->pmoal_handle,
+ ra_list_head, MNULL, MNULL);
+ while (ra_list && ra_list != (raListTbl *)ra_list_head) {
+ if (ra_list->total_pkts) {
+ PRINTM(MERROR,
+ "ralist ra: %02x:%02x:%02x:%02x:%02x:%02x tid=%d pkts=%d pause=%d\n",
+ ra_list->ra[0], ra_list->ra[1],
+ ra_list->ra[2], ra_list->ra[3],
+ ra_list->ra[4], ra_list->ra[5], i,
+ ra_list->total_pkts, ra_list->tx_pause);
+ }
+ ra_list = ra_list->pnext;
+ }
+ }
+ return;
+}
+
+/**
+ * @brief get tid down
+ *
+ * @param priv A pointer to mlan_private structure
+ * @param tid tid
+ *
+ * @return tid_down
+ *
+ */
+int wlan_get_wmm_tid_down(mlan_private *priv, int tid)
+{
+ return wlan_wmm_downgrade_tid(priv, tid);
+}
diff --git a/drivers/net/wireless/nxp/mxm_wifiex/wlan_src/mlan/mlan_wmm.h b/drivers/net/wireless/nxp/mxm_wifiex/wlan_src/mlan/mlan_wmm.h
new file mode 100644
index 000000000000..33856f05935c
--- /dev/null
+++ b/drivers/net/wireless/nxp/mxm_wifiex/wlan_src/mlan/mlan_wmm.h
@@ -0,0 +1,242 @@
+/** @file mlan_wmm.h
+ *
+ * @brief This file contains related macros, enum, and struct
+ * of wmm functionalities
+ *
+ *
+ * Copyright 2014-2020 NXP
+ *
+ * This software file (the File) is distributed by NXP
+ * under the terms of the GNU General Public License Version 2, June 1991
+ * (the License). You may use, redistribute and/or modify the 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.
+ *
+ */
+
+/****************************************************
+Change log:
+ 10/24/2008: initial version
+****************************************************/
+
+#ifndef _MLAN_WMM_H_
+#define _MLAN_WMM_H_
+
+/**
+ * @brief This function gets the TID
+ *
+ * @param pmadapter A pointer to mlan_adapter structure
+ * @param ptr A pointer to RA list table
+ *
+ * @return TID
+ */
+static INLINE t_u32 wlan_get_tid(pmlan_adapter pmadapter, praListTbl ptr)
+{
+ pmlan_buffer mbuf;
+
+ ENTER();
+ mbuf = (pmlan_buffer)util_peek_list(pmadapter->pmoal_handle,
+ &ptr->buf_head, MNULL, MNULL);
+ LEAVE();
+
+ if (!mbuf) {
+ return 0; // The default TID,BE
+ } else
+ return mbuf->priority;
+}
+
+/**
+ * @brief This function gets the length of a list
+ *
+ * @param head A pointer to mlan_list_head
+ *
+ * @return Length of list
+ */
+static INLINE t_u32 wlan_wmm_list_len(pmlan_list_head head)
+{
+ pmlan_linked_list pos;
+ t_u32 count = 0;
+
+ ENTER();
+
+ pos = head->pnext;
+
+ while (pos != (pmlan_linked_list)head) {
+ ++count;
+ pos = pos->pnext;
+ }
+
+ LEAVE();
+ return count;
+}
+
+/**
+ * @brief This function requests a ralist lock
+ *
+ * @param priv A pointer to mlan_private structure
+ *
+ * @return N/A
+ */
+static INLINE t_void wlan_request_ralist_lock(pmlan_private priv)
+{
+ mlan_adapter *pmadapter = priv->adapter;
+ mlan_callbacks *pcb = (mlan_callbacks *)&pmadapter->callbacks;
+
+ ENTER();
+
+ /* Call MOAL spin lock callback function */
+ pcb->moal_spin_lock(pmadapter->pmoal_handle,
+ priv->wmm.ra_list_spinlock);
+
+ LEAVE();
+ return;
+}
+
+/**
+ * @brief This function releases a lock on ralist
+ *
+ * @param priv A pointer to mlan_private structure
+ *
+ * @return N/A
+ */
+static INLINE t_void wlan_release_ralist_lock(pmlan_private priv)
+{
+ mlan_adapter *pmadapter = priv->adapter;
+ mlan_callbacks *pcb = (mlan_callbacks *)&pmadapter->callbacks;
+
+ ENTER();
+
+ /* Call MOAL spin unlock callback function */
+ pcb->moal_spin_unlock(pmadapter->pmoal_handle,
+ priv->wmm.ra_list_spinlock);
+
+ LEAVE();
+ return;
+}
+
+/** Add buffer to WMM Tx queue */
+void wlan_wmm_add_buf_txqueue(pmlan_adapter pmadapter, pmlan_buffer pmbuf);
+/** Add to RA list */
+void wlan_ralist_add(mlan_private *priv, t_u8 *ra);
+/** Update the RA list */
+int wlan_ralist_update(mlan_private *priv, t_u8 *old_ra, t_u8 *new_ra);
+
+/** WMM status change command handler */
+mlan_status wlan_cmd_wmm_status_change(pmlan_private priv);
+/** Check if WMM lists are empty */
+int wlan_wmm_lists_empty(pmlan_adapter pmadapter);
+/** Process WMM transmission */
+t_void wlan_wmm_process_tx(pmlan_adapter pmadapter);
+/** Test to see if the ralist ptr is valid */
+int wlan_is_ralist_valid(mlan_private *priv, raListTbl *ra_list, int tid);
+
+raListTbl *wlan_wmm_get_ralist_node(pmlan_private priv, t_u8 tid,
+ t_u8 *ra_addr);
+t_u8 wlan_get_random_ba_threshold(pmlan_adapter pmadapter);
+
+/** Compute driver packet delay */
+t_u8 wlan_wmm_compute_driver_packet_delay(pmlan_private priv,
+ const pmlan_buffer pmbuf);
+/** Initialize WMM */
+t_void wlan_wmm_init(pmlan_adapter pmadapter);
+/** Initialize WMM paramter */
+t_void wlan_init_wmm_param(pmlan_adapter pmadapter);
+/** Setup WMM queues */
+extern void wlan_wmm_setup_queues(pmlan_private priv);
+/* Setup default queues */
+void wlan_wmm_default_queue_priorities(pmlan_private priv);
+/* process wmm_param_config command */
+mlan_status wlan_cmd_wmm_param_config(pmlan_private pmpriv,
+ HostCmd_DS_COMMAND *cmd, t_u8 cmd_action,
+ t_void *pdata_buf);
+
+/* process wmm_param_config command response */
+mlan_status wlan_ret_wmm_param_config(pmlan_private pmpriv,
+ const HostCmd_DS_COMMAND *resp,
+ mlan_ioctl_req *pioctl_buf);
+
+#ifdef STA_SUPPORT
+/** Process WMM association request */
+extern t_u32 wlan_wmm_process_association_req(pmlan_private priv,
+ t_u8 **ppAssocBuf,
+ IEEEtypes_WmmParameter_t *pWmmIE,
+ IEEEtypes_HTCap_t *pHTCap);
+#endif /* STA_SUPPORT */
+
+/** setup wmm queue priorities */
+void wlan_wmm_setup_queue_priorities(pmlan_private priv,
+ IEEEtypes_WmmParameter_t *wmm_ie);
+
+/* Get tid_down from tid */
+int wlan_get_wmm_tid_down(mlan_private *priv, int tid);
+/** Downgrade WMM priority queue */
+void wlan_wmm_setup_ac_downgrade(pmlan_private priv);
+/** select WMM queue */
+t_u8 wlan_wmm_select_queue(mlan_private *pmpriv, t_u8 tid);
+t_void wlan_wmm_delete_peer_ralist(pmlan_private priv, t_u8 *mac);
+
+#ifdef STA_SUPPORT
+/*
+ * Functions used in the cmd handling routine
+ */
+/** WMM ADDTS request command handler */
+extern mlan_status wlan_cmd_wmm_addts_req(pmlan_private pmpriv,
+ HostCmd_DS_COMMAND *cmd,
+ t_void *pdata_buf);
+/** WMM DELTS request command handler */
+extern mlan_status wlan_cmd_wmm_delts_req(pmlan_private pmpriv,
+ HostCmd_DS_COMMAND *cmd,
+ t_void *pdata_buf);
+/** WMM QUEUE_STATS command handler */
+extern mlan_status wlan_cmd_wmm_queue_stats(pmlan_private pmpriv,
+ HostCmd_DS_COMMAND *cmd,
+ t_void *pdata_buf);
+/** WMM TS_STATUS command handler */
+extern mlan_status wlan_cmd_wmm_ts_status(pmlan_private pmpriv,
+ HostCmd_DS_COMMAND *cmd,
+ t_void *pdata_buf);
+
+/*
+ * Functions used in the cmdresp handling routine
+ */
+/** WMM get status command response handler */
+extern mlan_status wlan_ret_wmm_get_status(pmlan_private priv, t_u8 *ptlv,
+ int resp_len);
+/** WMM ADDTS request command response handler */
+extern mlan_status wlan_ret_wmm_addts_req(pmlan_private pmpriv,
+ const HostCmd_DS_COMMAND *resp,
+ mlan_ioctl_req *pioctl_buf);
+/** WMM DELTS request command response handler */
+extern mlan_status wlan_ret_wmm_delts_req(pmlan_private pmpriv,
+ const HostCmd_DS_COMMAND *resp,
+ mlan_ioctl_req *pioctl_buf);
+/** WMM QUEUE_STATS command response handler */
+extern mlan_status wlan_ret_wmm_queue_stats(pmlan_private pmpriv,
+ const HostCmd_DS_COMMAND *resp,
+ mlan_ioctl_req *pioctl_buf);
+/** WMM TS_STATUS command response handler */
+extern mlan_status wlan_ret_wmm_ts_status(pmlan_private pmpriv,
+ HostCmd_DS_COMMAND *resp,
+ mlan_ioctl_req *pioctl_buf);
+#endif /* STA_SUPPORT */
+
+/** WMM QUEUE_CONFIG command handler */
+extern mlan_status wlan_cmd_wmm_queue_config(pmlan_private pmpriv,
+ HostCmd_DS_COMMAND *cmd,
+ t_void *pdata_buf);
+
+/** WMM QUEUE_CONFIG command response handler */
+extern mlan_status wlan_ret_wmm_queue_config(pmlan_private pmpriv,
+ const HostCmd_DS_COMMAND *resp,
+ mlan_ioctl_req *pioctl_buf);
+
+mlan_status wlan_wmm_cfg_ioctl(pmlan_adapter pmadapter,
+ pmlan_ioctl_req pioctl_req);
+#endif /* !_MLAN_WMM_H_ */