/** @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 2008-2022 NXP
 *
 *  NXP CONFIDENTIAL
 *  The source code contained or described herein and all documents related to
 *  the source code (Materials) are owned by NXP, its
 *  suppliers and/or its licensors. Title to the Materials remains with NXP,
 *  its suppliers and/or its licensors. The Materials contain
 *  trade secrets and proprietary and confidential information of NXP, its
 *  suppliers and/or its licensors. The Materials are protected by worldwide
 *  copyright and trade secret laws and treaty provisions. No part of the
 *  Materials may be used, copied, reproduced, modified, published, uploaded,
 *  posted, transmitted, distributed, or disclosed in any way without NXP's
 *  prior express written permission.
 *
 *  No license under any patent, copyright, trade secret or other intellectual
 *  property right is granted to or conferred upon you by disclosure or delivery
 *  of the Materials, either expressly, by implication, inducement, estoppel or
 *  otherwise. Any license under such intellectual property rights must be
 *  express and approved by NXP in writing.
 *
 *  Alternatively, this software may be distributed under the terms of GPL v2.
 *  SPDX-License-Identifier:    GPL-2.0
 *
 *
 */

/******************************************************
 * 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;
	case ChanTrackParam_i:
		psnmp_mib->oid = wlan_cpu_to_le16((t_u16)ChanTrackParam_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);
		mcmd->NumPkt = wlan_cpu_to_le32(cfg->NumPkt);
		mcmd->MaxPE = wlan_cpu_to_le32(cfg->MaxPE);
		mcmd->BeamChange = wlan_cpu_to_le32(cfg->BeamChange);
		mcmd->Dcm = wlan_cpu_to_le32(cfg->Dcm);
		mcmd->Doppler = wlan_cpu_to_le32(cfg->Doppler);
		mcmd->MidP = wlan_cpu_to_le32(cfg->MidP);
		mcmd->QNum = wlan_cpu_to_le32(cfg->QNum);
		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 config trigger 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_config_trigger_frame(pmlan_private pmpriv,
						     HostCmd_DS_COMMAND *cmd,
						     t_u16 action,
						     t_void *pdata_buf)
{
	mfg_Cmd_IEEEtypes_CtlBasicTrigHdr_t *mcmd =
		(mfg_Cmd_IEEEtypes_CtlBasicTrigHdr_t *)&cmd->params
			.mfg_tx_trigger_config;
	mfg_Cmd_IEEEtypes_CtlBasicTrigHdr_t *cfg =
		(mfg_Cmd_IEEEtypes_CtlBasicTrigHdr_t *)pdata_buf;

	ENTER();
	cmd->command = wlan_cpu_to_le16(HostCmd_CMD_MFG_COMMAND);
	cmd->size = wlan_cpu_to_le16(
		sizeof(mfg_Cmd_IEEEtypes_CtlBasicTrigHdr_t) + 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->standalone_hetb = wlan_cpu_to_le32(cfg->standalone_hetb);
		mcmd->frmCtl.type = wlan_cpu_to_le16(cfg->frmCtl.type);
		mcmd->frmCtl.sub_type = wlan_cpu_to_le16(cfg->frmCtl.sub_type);
		mcmd->duration = wlan_cpu_to_le16(cfg->duration);

		mcmd->trig_common_field =
			wlan_cpu_to_le64(cfg->trig_common_field);

		memcpy_ext(pmpriv->adapter, &mcmd->trig_user_info_field,
			   &cfg->trig_user_info_field,
			   sizeof(cfg->trig_user_info_field),
			   sizeof(mcmd->trig_user_info_field));

		mcmd->basic_trig_user_info =
			wlan_cpu_to_le16(cfg->basic_trig_user_info);
	}
	LEAVE();
	return MLAN_STATUS_SUCCESS;
}

/**
 *  @brief This function prepares command of MFG HE TB Tx.
 *
 *  @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_he_tb_tx(pmlan_private pmpriv, HostCmd_DS_COMMAND *cmd,
				  t_u16 action, t_void *pdata_buf)
{
	struct mfg_Cmd_HE_TBTx_t *mcmd =
		(struct mfg_Cmd_HE_TBTx_t *)&cmd->params.mfg_he_power;
	struct mfg_Cmd_HE_TBTx_t *cfg = (struct mfg_Cmd_HE_TBTx_t *)pdata_buf;
	ENTER();
	cmd->command = wlan_cpu_to_le16(HostCmd_CMD_MFG_COMMAND);
	cmd->size =
		wlan_cpu_to_le16(sizeof(struct mfg_Cmd_HE_TBTx_t) + 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_le16(cfg->enable);
		mcmd->qnum = wlan_cpu_to_le16(cfg->qnum);
		mcmd->aid = wlan_cpu_to_le16(cfg->aid);
		mcmd->axq_mu_timer = wlan_cpu_to_le16(cfg->axq_mu_timer);
		mcmd->tx_power = wlan_cpu_to_le16(cfg->tx_power);
	}

	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_CONFIG_MAC_HE_TB_TX:
		ret = wlan_cmd_mfg_he_tb_tx(pmpriv, cmd, action, pdata_buf);
		goto cmd_mfg_done;
	case MFG_CMD_CONFIG_TRIGGER_FRAME:
		ret = wlan_cmd_mfg_config_trigger_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_RADIO_MODE_CFG:
	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);

	if (!hs_activate && (pdata_buf->conditions != HOST_SLEEP_CFG_CANCEL) &&
	    ((pmadapter->arp_filter_size > 0) &&
	     (pmadapter->arp_filter_size <= ARP_FILTER_MAX_BUF_SIZE))) {
		PRINTM(MINFO, "Attach %d bytes ArpFilter to HSCfg cmd\n",
		       pmadapter->arp_filter_size);
		memcpy_ext(pmpriv->adapter,
			   ((t_u8 *)phs_cfg) +
				   sizeof(HostCmd_DS_802_11_HS_CFG_ENH),
			   pmadapter->arp_filter, pmadapter->arp_filter_size,
			   pmadapter->arp_filter_size);
		cmd->size = pmadapter->arp_filter_size +
			    sizeof(HostCmd_DS_802_11_HS_CFG_ENH) + S_DS_GEN;
		tlv = (t_u8 *)phs_cfg + sizeof(HostCmd_DS_802_11_HS_CFG_ENH) +
		      pmadapter->arp_filter_size;
	} else
		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();
	if (!pdata_buf) {
		LEAVE();
		return MLAN_STATUS_FAILURE;
	}
	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));
		PRINTM(MCMND, "Set GCMP Key\n");
		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));
		PRINTM(MCMND, "Set CCMP256 Key\n");
		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);
		if (pkey->key_flags & KEY_FLAG_GMAC_128)
			pkey_material->key_param_set.key_type =
				KEY_TYPE_ID_BIP_GMAC_128;
		else
			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));
		if (pkey->key_flags & KEY_FLAG_GMAC_128)
			PRINTM(MCMND, "Set AES 128 GMAC Key\n");
		else
			PRINTM(MCMND, "Set CMAC AES Key\n");
		goto done;
	}
	if (pkey->key_len == WPA_IGTK_256_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
					   .gmac_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_BIP_GMAC_256;
		pkey_material->key_param_set.key_params.gmac_aes.key_len =
			wlan_cpu_to_le16(pkey->key_len);
		memcpy_ext(pmpriv->adapter,
			   pkey_material->key_param_set.key_params.gmac_aes.key,
			   pkey->key_material, pkey->key_len,
			   WPA_IGTK_256_KEY_LEN);
		pkey_material->key_param_set.length = wlan_cpu_to_le16(
			KEY_PARAMS_FIXED_LEN + sizeof(gmac_aes_256_param));
		cmd->size = wlan_cpu_to_le16(sizeof(MrvlIEtypesHeader_t) +
					     S_DS_GEN + KEY_PARAMS_FIXED_LEN +
					     sizeof(gmac_aes_256_param) +
					     sizeof(pkey_material->action));
		PRINTM(MCMND, "Set AES 256 GMAC 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;
	if (req_len > sizeof(cust_ie->ie_data_list)) {
		PRINTM(MERROR, "Invalid cust_ie->len=%d\n", req_len);
		LEAVE();
		return MLAN_STATUS_FAILURE;
	}
	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 command of TDLS 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 or MLAN_STATUS_FAILURE
 */
static mlan_status wlan_cmd_tdls_config(pmlan_private pmpriv,
					HostCmd_DS_COMMAND *cmd,
					t_u16 cmd_action, t_void *pdata_buf)
{
	t_u16 travel_len = 0;
	mlan_ds_misc_tdls_config *tdls_config = MNULL;
	tdls_all_config *tdls_all_cfg = MNULL;
	HostCmd_DS_TDLS_CONFIG *ptdls_config_data =
		&(cmd->params.tdls_config_data);
	t_u8 zero_mac[] = {0, 0, 0, 0, 0, 0};

	ENTER();

	cmd->command = wlan_cpu_to_le16(HostCmd_CMD_TDLS_CONFIG);
	cmd->size = sizeof(HostCmd_DS_TDLS_CONFIG) + S_DS_GEN;
	cmd->result = 0;

	tdls_config = (mlan_ds_misc_tdls_config *)pdata_buf;
	ptdls_config_data->tdls_info.tdls_action =
		wlan_cpu_to_le16(tdls_config->tdls_action);

	tdls_all_cfg = (tdls_all_config *)tdls_config->tdls_data;

	switch (tdls_config->tdls_action) {
	case WLAN_TDLS_CONFIG:
		travel_len = sizeof(tdls_all_cfg->u.tdls_config);
		tdls_all_cfg->u.tdls_config.enable =
			wlan_cpu_to_le16(tdls_all_cfg->u.tdls_config.enable);
		memcpy_ext(pmpriv->adapter,
			   ptdls_config_data->tdls_info.tdls_data,
			   &tdls_all_cfg->u.tdls_setup, travel_len,
			   MAX_TDLS_DATA_LEN);
		break;

	case WLAN_TDLS_SET_INFO:
		travel_len = tdls_all_cfg->u.tdls_set.tlv_length;
		if ((travel_len + sizeof(t_u16)) > MAX_TDLS_DATA_LEN) {
			PRINTM(MERROR, "TDLS configuration overflow\n");
			LEAVE();
			return MLAN_STATUS_FAILURE;
		}
		memcpy_ext(pmpriv->adapter,
			   ptdls_config_data->tdls_info.tdls_data,
			   (t_u8 *)&tdls_all_cfg->u.tdls_set.cap_info,
			   sizeof(t_u16), sizeof(t_u16));
		memcpy_ext(pmpriv->adapter,
			   (t_u8 *)ptdls_config_data->tdls_info.tdls_data +
				   sizeof(t_u16),
			   &tdls_all_cfg->u.tdls_set.tlv_buffer, travel_len,
			   MAX_TDLS_DATA_LEN - sizeof(t_u16));
		travel_len += sizeof(t_u16);
		break;
	case WLAN_TDLS_DISCOVERY_REQ:
		travel_len = MLAN_MAC_ADDR_LENGTH;
		memcpy_ext(pmpriv->adapter,
			   ptdls_config_data->tdls_info.tdls_data,
			   tdls_all_cfg->u.tdls_discovery.peer_mac_addr,
			   travel_len, MAX_TDLS_DATA_LEN);
		break;

	case WLAN_TDLS_SETUP_REQ:
		travel_len = sizeof(tdls_all_cfg->u.tdls_setup);
		tdls_all_cfg->u.tdls_setup.setup_timeout = wlan_cpu_to_le32(
			tdls_all_cfg->u.tdls_setup.setup_timeout);
		tdls_all_cfg->u.tdls_setup.key_lifetime = wlan_cpu_to_le32(
			tdls_all_cfg->u.tdls_setup.key_lifetime);
		memcpy_ext(pmpriv->adapter,
			   ptdls_config_data->tdls_info.tdls_data,
			   &tdls_all_cfg->u.tdls_setup, travel_len,
			   MAX_TDLS_DATA_LEN);
		break;

	case WLAN_TDLS_TEAR_DOWN_REQ:
		travel_len = sizeof(tdls_all_cfg->u.tdls_tear_down);
		tdls_all_cfg->u.tdls_tear_down.reason_code = wlan_cpu_to_le16(
			tdls_all_cfg->u.tdls_tear_down.reason_code);
		memcpy_ext(pmpriv->adapter,
			   ptdls_config_data->tdls_info.tdls_data,
			   &tdls_all_cfg->u.tdls_tear_down, travel_len,
			   MAX_TDLS_DATA_LEN);
		break;
	case WLAN_TDLS_STOP_CHAN_SWITCH:
		travel_len = MLAN_MAC_ADDR_LENGTH;
		memcpy_ext(pmpriv->adapter,
			   ptdls_config_data->tdls_info.tdls_data,
			   tdls_all_cfg->u.tdls_stop_chan_switch.peer_mac_addr,
			   travel_len, MAX_TDLS_DATA_LEN);
		break;
	case WLAN_TDLS_INIT_CHAN_SWITCH:
		travel_len = sizeof(tdls_all_cfg->u.tdls_chan_switch);
		tdls_all_cfg->u.tdls_chan_switch.switch_time = wlan_cpu_to_le16(
			tdls_all_cfg->u.tdls_chan_switch.switch_time);
		tdls_all_cfg->u.tdls_chan_switch.switch_timeout =
			wlan_cpu_to_le16(
				tdls_all_cfg->u.tdls_chan_switch.switch_timeout);
		memcpy_ext(pmpriv->adapter,
			   ptdls_config_data->tdls_info.tdls_data,
			   &tdls_all_cfg->u.tdls_chan_switch, travel_len,
			   MAX_TDLS_DATA_LEN);
		break;
	case WLAN_TDLS_CS_PARAMS:
		travel_len = sizeof(tdls_all_cfg->u.tdls_cs_params);
		memcpy_ext(pmpriv->adapter,
			   ptdls_config_data->tdls_info.tdls_data,
			   &tdls_all_cfg->u.tdls_cs_params, travel_len,
			   MAX_TDLS_DATA_LEN);
		break;
	case WLAN_TDLS_CS_DISABLE:
		travel_len = sizeof(tdls_all_cfg->u.tdls_disable_cs);
		tdls_all_cfg->u.tdls_disable_cs.data =
			wlan_cpu_to_le16(tdls_all_cfg->u.tdls_disable_cs.data);
		memcpy_ext(pmpriv->adapter,
			   ptdls_config_data->tdls_info.tdls_data,
			   &tdls_all_cfg->u.tdls_disable_cs, travel_len,
			   MAX_TDLS_DATA_LEN);
		break;
	case WLAN_TDLS_POWER_MODE:
		travel_len = sizeof(tdls_all_cfg->u.tdls_power_mode);
		tdls_all_cfg->u.tdls_power_mode.power_mode = wlan_cpu_to_le16(
			tdls_all_cfg->u.tdls_power_mode.power_mode);
		memcpy_ext(pmpriv->adapter,
			   ptdls_config_data->tdls_info.tdls_data,
			   &tdls_all_cfg->u.tdls_power_mode, travel_len,
			   MAX_TDLS_DATA_LEN);
		break;

	case WLAN_TDLS_LINK_STATUS:
		travel_len = 0;
		if (memcmp(pmpriv->adapter,
			   tdls_all_cfg->u.tdls_link_status_req.peer_mac_addr,
			   zero_mac, sizeof(zero_mac))) {
			travel_len =
				sizeof(tdls_all_cfg->u.tdls_link_status_req);
			memcpy_ext(pmpriv->adapter,
				   ptdls_config_data->tdls_info.tdls_data,
				   tdls_all_cfg->u.tdls_link_status_req
					   .peer_mac_addr,
				   travel_len, MAX_TDLS_DATA_LEN);
		}
		break;

	case WLAN_TDLS_DEBUG_ALLOW_WEAK_SECURITY:
	case WLAN_TDLS_DEBUG_SETUP_SAME_LINK:
	case WLAN_TDLS_DEBUG_FAIL_SETUP_CONFIRM:
	case WLAN_TDLS_DEBUG_WRONG_BSS:
	case WLAN_TDLS_DEBUG_SETUP_PROHIBITED:
	case WLAN_TDLS_DEBUG_HIGHER_LOWER_MAC:
	case WLAN_TDLS_DEBUG_IGNORE_KEY_EXPIRY:
	case WLAN_TDLS_DEBUG_STOP_RX:
	case WLAN_TDLS_DEBUG_CS_RET_IM:
		travel_len = sizeof(tdls_all_cfg->u.tdls_debug_data);
		tdls_all_cfg->u.tdls_debug_data.debug_data = wlan_cpu_to_le16(
			tdls_all_cfg->u.tdls_debug_data.debug_data);
		memcpy_ext(pmpriv->adapter,
			   ptdls_config_data->tdls_info.tdls_data,
			   &tdls_all_cfg->u.tdls_debug_data, travel_len,
			   MAX_TDLS_DATA_LEN);
		break;

	default:
		LEAVE();
		return MLAN_STATUS_FAILURE;
	}

	cmd->size += travel_len;
	cmd->size -= MAX_TDLS_DATA_LEN;
	cmd->size = wlan_cpu_to_le16(cmd->size);

	LEAVE();
	return MLAN_STATUS_SUCCESS;
}

/**
 *  @brief This function prepares command of TDLS create/config/delete
 *
 *  @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_tdls_oper(pmlan_private pmpriv,
				      HostCmd_DS_COMMAND *cmd, t_u16 cmd_action,
				      t_void *pdata_buf)
{
	t_u16 travel_len = 0;
	mlan_ds_misc_tdls_oper *tdls_oper = MNULL;
	HostCmd_DS_TDLS_OPER *ptdls_oper = &(cmd->params.tdls_oper_data);
	sta_node *sta_ptr;
	t_u8 *pos;
	MrvlIEtypes_RatesParamSet_t *Rate_tlv = MNULL;
	MrvlIETypes_HTCap_t *HTcap_tlv = MNULL;
	MrvlIETypes_HTInfo_t *HTInfo_tlv = MNULL;
	MrvlIETypes_2040BSSCo_t *BSSCo = MNULL;
	MrvlIETypes_ExtCap_t *ExCap = MNULL;
	MrvlIEtypes_RsnParamSet_t *Rsn_ie = MNULL;
	MrvlIETypes_qosinfo_t *qos_info = MNULL;
	MrvlIETypes_LinkIDElement_t *LinkID = MNULL;
	BSSDescriptor_t *pbss_desc = &pmpriv->curr_bss_params.bss_descriptor;
	MrvlIETypes_VHTCap_t *VHTcap_tlv = MNULL;
	MrvlIETypes_VHTOprat_t *VHTOper_tlv = MNULL;
	MrvlIETypes_AID_t *AidInfo = MNULL;
	MrvlIEtypes_Extension_t *hecap_tlv = MNULL;
	MrvlIEtypes_He_Op_t *heop_tlv = MNULL;
	MrvlIEtypes_TDLS_Idle_Timeout_t *TdlsIdleTimeout = MNULL;

	ENTER();

	cmd->command = wlan_cpu_to_le16(HostCmd_CMD_TDLS_OPERATION);
	cmd->size = sizeof(HostCmd_DS_TDLS_OPER) + S_DS_GEN;
	cmd->result = 0;

	tdls_oper = (mlan_ds_misc_tdls_oper *)pdata_buf;
	ptdls_oper->reason = 0;
	memcpy_ext(pmpriv->adapter, ptdls_oper->peer_mac, tdls_oper->peer_mac,
		   MLAN_MAC_ADDR_LENGTH, MLAN_MAC_ADDR_LENGTH);
	sta_ptr = wlan_get_station_entry(pmpriv, tdls_oper->peer_mac);
	pos = (t_u8 *)ptdls_oper + sizeof(HostCmd_DS_TDLS_OPER);
	switch (tdls_oper->tdls_action) {
	case WLAN_TDLS_CREATE_LINK:
		if (sta_ptr)
			sta_ptr->status = TDLS_SETUP_INPROGRESS;
		ptdls_oper->tdls_action = wlan_cpu_to_le16(TDLS_CREATE);
		break;
	case WLAN_TDLS_CONFIG_LINK:
		if (sta_ptr) {
			ptdls_oper->tdls_action = wlan_cpu_to_le16(TDLS_CONFIG);
			/*capability*/
			*(t_u16 *)pos = wlan_cpu_to_le16(sta_ptr->capability);
			travel_len += sizeof(sta_ptr->capability);

			/*supported rate*/
			Rate_tlv = (MrvlIEtypes_RatesParamSet_t *)(pos +
								   travel_len);
			Rate_tlv->header.type =
				wlan_cpu_to_le16(TLV_TYPE_RATES);
			Rate_tlv->header.len =
				wlan_cpu_to_le16(sta_ptr->rate_len);
			memcpy_ext(pmpriv->adapter,
				   pos + travel_len +
					   sizeof(MrvlIEtypesHeader_t),
				   sta_ptr->support_rate, sta_ptr->rate_len,
				   sta_ptr->rate_len);
			travel_len +=
				sizeof(MrvlIEtypesHeader_t) + sta_ptr->rate_len;

			/*Extended capability */
			if (sta_ptr->ExtCap.ieee_hdr.element_id ==
			    EXT_CAPABILITY) {
				ExCap = (MrvlIETypes_ExtCap_t *)(pos +
								 travel_len);
				ExCap->header.type =
					wlan_cpu_to_le16(TLV_TYPE_EXTCAP);
				ExCap->header.len = wlan_cpu_to_le16(
					sta_ptr->ExtCap.ieee_hdr.len);
				memcpy_ext(pmpriv->adapter, &ExCap->ext_cap,
					   &sta_ptr->ExtCap.ext_cap,
					   sta_ptr->ExtCap.ieee_hdr.len,
					   sta_ptr->ExtCap.ieee_hdr.len);
				travel_len += sta_ptr->ExtCap.ieee_hdr.len +
					      sizeof(MrvlIEtypesHeader_t);
			}
			if (ExCap) {
				if (pmpriv->host_tdls_uapsd_support &&
				    ISSUPP_EXTCAP_TDLS_UAPSD(ExCap->ext_cap)) {
					/* qos_info */
					qos_info =
						(MrvlIETypes_qosinfo_t
							 *)(pos + travel_len);
					qos_info->header.type =
						wlan_cpu_to_le16(QOS_INFO);
					qos_info->header.len =
						wlan_cpu_to_le16(sizeof(t_u8));
					qos_info->qos_info = sta_ptr->qos_info;
					travel_len +=
						sizeof(MrvlIETypes_qosinfo_t);
				} else {
					RESET_EXTCAP_TDLS_UAPSD(ExCap->ext_cap);
				}

				if (!(pmpriv->host_tdls_cs_support &&
				      ISSUPP_EXTCAP_TDLS_CHAN_SWITCH(
					      ExCap->ext_cap)))
					RESET_EXTCAP_TDLS_CHAN_SWITCH(
						ExCap->ext_cap);
			}

			/*RSN ie*/
			if (sta_ptr->rsn_ie.ieee_hdr.element_id == RSN_IE) {
				Rsn_ie = (MrvlIEtypes_RsnParamSet_t
						  *)(pos + travel_len);
				Rsn_ie->header.type = wlan_cpu_to_le16(
					sta_ptr->rsn_ie.ieee_hdr.element_id);
				Rsn_ie->header.len = wlan_cpu_to_le16(
					sta_ptr->rsn_ie.ieee_hdr.len);
				memcpy_ext(pmpriv->adapter, Rsn_ie->rsn_ie,
					   sta_ptr->rsn_ie.data,
					   sta_ptr->rsn_ie.ieee_hdr.len,
					   sta_ptr->rsn_ie.ieee_hdr.len);
				travel_len += sta_ptr->rsn_ie.ieee_hdr.len +
					      sizeof(MrvlIEtypesHeader_t);
			}
			/*Link ID*/
			if (sta_ptr->link_ie.element_id == LINK_ID) {
				LinkID = (MrvlIETypes_LinkIDElement_t
						  *)(pos + travel_len);
				LinkID->header.type = wlan_cpu_to_le16(LINK_ID);
				LinkID->header.len =
					wlan_cpu_to_le16(sta_ptr->link_ie.len);
				memcpy_ext(pmpriv->adapter, &LinkID->bssid,
					   &sta_ptr->link_ie.bssid,
					   sta_ptr->link_ie.len,
					   sizeof(LinkID->bssid));
				travel_len += sta_ptr->link_ie.len +
					      sizeof(MrvlIEtypesHeader_t);
			}
			/*HT capability*/
			if (sta_ptr->HTcap.ieee_hdr.element_id ==
			    HT_CAPABILITY) {
				HTcap_tlv = (MrvlIETypes_HTCap_t *)(pos +
								    travel_len);
				HTcap_tlv->header.type =
					wlan_cpu_to_le16(TLV_TYPE_HT_CAP);
				HTcap_tlv->header.len = wlan_cpu_to_le16(
					sta_ptr->HTcap.ieee_hdr.len);
				memcpy_ext(pmpriv->adapter, &HTcap_tlv->ht_cap,
					   &sta_ptr->HTcap.ht_cap,
					   sta_ptr->HTcap.ieee_hdr.len,
					   sizeof(HTcap_tlv->ht_cap));
				travel_len += sta_ptr->HTcap.ieee_hdr.len +
					      sizeof(MrvlIEtypesHeader_t);
			}
			if (HTcap_tlv) {
				if (pmpriv->host_tdls_cs_support &&
				    (pmpriv->adapter->fw_bands & BAND_A))
					wlan_fill_ht_cap_tlv(pmpriv, HTcap_tlv,
							     BAND_A, MFALSE);
				else
					wlan_fill_ht_cap_tlv(
						pmpriv, HTcap_tlv,
						pbss_desc->bss_band, MFALSE);
				DBG_HEXDUMP(MCMD_D, "FW htcap",
					    (t_u8 *)HTcap_tlv,
					    sizeof(MrvlIETypes_HTCap_t));
			}

			/*HT info*/
			if (sta_ptr->HTInfo.ieee_hdr.element_id ==
			    HT_OPERATION) {
				HTInfo_tlv =
					(MrvlIETypes_HTInfo_t *)(pos +
								 travel_len);
				HTInfo_tlv->header.type =
					wlan_cpu_to_le16(TLV_TYPE_HT_INFO);
				HTInfo_tlv->header.len = wlan_cpu_to_le16(
					sta_ptr->HTInfo.ieee_hdr.len);
				memcpy_ext(pmpriv->adapter,
					   &HTInfo_tlv->ht_info,
					   &sta_ptr->HTInfo.ht_info,
					   sta_ptr->HTInfo.ieee_hdr.len,
					   sizeof(HTInfo_tlv->ht_info));
				travel_len += sta_ptr->HTInfo.ieee_hdr.len +
					      sizeof(MrvlIEtypesHeader_t);
				DBG_HEXDUMP(MCMD_D, "HT Info",
					    (t_u8 *)HTInfo_tlv,
					    sizeof(MrvlIETypes_HTInfo_t));
			}
			/*20/40 BSS co-exist*/
			if (sta_ptr->BSSCO_20_40.ieee_hdr.element_id ==
			    BSSCO_2040) {
				BSSCo = (MrvlIETypes_2040BSSCo_t *)(pos +
								    travel_len);
				BSSCo->header.type = wlan_cpu_to_le16(
					TLV_TYPE_2040BSS_COEXISTENCE);
				BSSCo->header.len = wlan_cpu_to_le16(
					sta_ptr->BSSCO_20_40.ieee_hdr.len);
				memcpy_ext(pmpriv->adapter, &BSSCo->bss_co_2040,
					   &sta_ptr->BSSCO_20_40.bss_co_2040,
					   sta_ptr->BSSCO_20_40.ieee_hdr.len,
					   sizeof(BSSCo->bss_co_2040));
				travel_len +=
					sta_ptr->BSSCO_20_40.ieee_hdr.len +
					sizeof(MrvlIEtypesHeader_t);
			}
			/* Check if we need enable the 11AC */
			if (sta_ptr && sta_ptr->vht_oprat.ieee_hdr.element_id ==
					       VHT_OPERATION) {
				/** AID */
				if (sta_ptr->aid_info.ieee_hdr.element_id ==
				    AID_INFO) {
					AidInfo = (MrvlIETypes_AID_t
							   *)(pos + travel_len);
					AidInfo->header.type =
						wlan_cpu_to_le16(AID_INFO);
					AidInfo->header.len = wlan_cpu_to_le16(
						sta_ptr->aid_info.ieee_hdr.len);
					AidInfo->AID = wlan_cpu_to_le16(
						sta_ptr->aid_info.AID);
					travel_len += sizeof(MrvlIETypes_AID_t);
				}
				/* Vht capability */
				if (sta_ptr->vht_cap.ieee_hdr.element_id ==
				    VHT_CAPABILITY) {
					VHTcap_tlv =
						(MrvlIETypes_VHTCap_t
							 *)(pos + travel_len);
					VHTcap_tlv->header.type =
						wlan_cpu_to_le16(
							VHT_CAPABILITY);
					VHTcap_tlv->header
						.len = wlan_cpu_to_le16(
						sta_ptr->vht_cap.ieee_hdr.len);
					memcpy_ext(
						pmpriv->adapter,
						&VHTcap_tlv->vht_cap,
						&sta_ptr->vht_cap.vht_cap,
						sta_ptr->vht_cap.ieee_hdr.len,
						sizeof(VHTcap_tlv->vht_cap));
					travel_len +=
						sta_ptr->vht_cap.ieee_hdr.len +
						sizeof(MrvlIEtypesHeader_t);
				}
				if (VHTcap_tlv) {
					wlan_fill_vht_cap_tlv(
						pmpriv, VHTcap_tlv,
						pbss_desc->bss_band, MTRUE,
						MTRUE);
					DBG_HEXDUMP(
						MCMD_D,
						"TDLS Config Link: VHT Capability",
						(t_u8 *)VHTcap_tlv,
						sizeof(MrvlIETypes_VHTCap_t));
				}

				/*Vht operation*/
				VHTOper_tlv =
					(MrvlIETypes_VHTOprat_t *)(pos +
								   travel_len);
				VHTOper_tlv->header.type =
					wlan_cpu_to_le16(VHT_OPERATION);
				VHTOper_tlv->header.len = wlan_cpu_to_le16(
					sta_ptr->vht_oprat.ieee_hdr.len);
				memcpy_ext(pmpriv->adapter,
					   &VHTOper_tlv->chan_width,
					   &sta_ptr->vht_oprat.chan_width,
					   sta_ptr->vht_oprat.ieee_hdr.len,
					   (sizeof(MrvlIETypes_VHTOprat_t) -
					    sizeof(MrvlIEtypesHeader_t)));
				VHTOper_tlv->basic_MCS_map = wlan_cpu_to_le16(
					VHTOper_tlv->basic_MCS_map);
				travel_len += sta_ptr->vht_oprat.ieee_hdr.len +
					      sizeof(MrvlIEtypesHeader_t);
				DBG_HEXDUMP(MCMD_D,
					    "TDLS Config Link: VHT operation",
					    (t_u8 *)VHTOper_tlv,
					    sizeof(MrvlIETypes_VHTOprat_t));
			}
			/* Check if we need enable the 11AX */
			if (sta_ptr &&
			    (sta_ptr->he_op.ieee_hdr.element_id == EXTENSION) &&
			    (sta_ptr->he_op.ext_id == HE_OPERATION)) {
				/* HE Capability */
				hecap_tlv =
					(MrvlIEtypes_Extension_t *)(pos +
								    travel_len);
				/* fill the peer HE CAP IE */
				memcpy_ext(pmpriv->adapter, &hecap_tlv->ext_id,
					   &sta_ptr->tdls_he_cap.ext_id,
					   sta_ptr->tdls_he_cap.ieee_hdr.len,
					   sizeof(MrvlIEtypes_He_cap_t) -
						   sizeof(MrvlIEtypesHeader_t));
				hecap_tlv->type =
					wlan_cpu_to_le16(TLV_TYPE_EXTENSION_ID);
				hecap_tlv->len = MIN(
					sta_ptr->tdls_he_cap.ieee_hdr.len,
					sizeof(MrvlIEtypes_He_cap_t) -
						sizeof(MrvlIEtypesHeader_t));
				hecap_tlv->len =
					wlan_cpu_to_le16(hecap_tlv->len);
#if 0
			    wlan_fill_he_cap_tlv(pmpriv,
			            pmpriv->config_bands,
			            hecap_tlv, MFALSE);
#endif

				travel_len += wlan_le16_to_cpu(hecap_tlv->len) +
					      sizeof(MrvlIEtypesHeader_t);

				DBG_HEXDUMP(
					MCMD_D,
					"TDLS Config Link: HE Capability",
					(t_u8 *)hecap_tlv,
					wlan_le16_to_cpu(hecap_tlv->len) +
						sizeof(MrvlIEtypesHeader_t));

				/* HE Operation */
				heop_tlv = (MrvlIEtypes_He_Op_t *)(pos +
								   travel_len);
				heop_tlv->header.type =
					wlan_cpu_to_le16(EXTENSION);
				heop_tlv->header.len = wlan_cpu_to_le16(
					sta_ptr->he_op.ieee_hdr.len);
				memcpy_ext(pmpriv->adapter, &heop_tlv->ext_id,
					   &sta_ptr->he_op.ext_id,
					   sta_ptr->he_op.ieee_hdr.len,
					   sizeof(MrvlIEtypes_He_Op_t) -
						   sizeof(MrvlIEtypesHeader_t));
				heop_tlv->he_op_param1 = wlan_cpu_to_le16(
					heop_tlv->he_op_param1);
				heop_tlv->basic_he_mcs_nss = wlan_cpu_to_le16(
					heop_tlv->basic_he_mcs_nss);
				travel_len +=
					wlan_le16_to_cpu(heop_tlv->header.len) +
					sizeof(MrvlIEtypesHeader_t);
				DBG_HEXDUMP(
					MCMD_D,
					"TDLS Config Link: HE Operation",
					(t_u8 *)heop_tlv,
					wlan_le16_to_cpu(heop_tlv->header.len) +
						sizeof(MrvlIEtypesHeader_t));
			}

			TdlsIdleTimeout =
				(MrvlIEtypes_TDLS_Idle_Timeout_t *)(pos +
								    travel_len);
			TdlsIdleTimeout->header.type =
				wlan_cpu_to_le16(TLV_TYPE_TDLS_IDLE_TIMEOUT);
			TdlsIdleTimeout->header.len =
				sizeof(TdlsIdleTimeout->value);
			TdlsIdleTimeout->header.len =
				wlan_cpu_to_le16(TdlsIdleTimeout->header.len);
			TdlsIdleTimeout->value =
				wlan_cpu_to_le16(pmpriv->tdls_idle_time);
			travel_len += sizeof(MrvlIEtypes_TDLS_Idle_Timeout_t);
		}
		break;
	case WLAN_TDLS_DISABLE_LINK:
		ptdls_oper->tdls_action = wlan_cpu_to_le16(TDLS_DELETE);
		break;
	default:
		break;
	}
	cmd->size += travel_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;
}

/**
 *  @brief This function prepares command of fw auto re-connect.
 *
 *  @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_fw_auto_reconnect(pmlan_private pmpriv,
					      HostCmd_DS_COMMAND *cmd,
					      t_u16 cmd_action,
					      t_void *pdata_buf)
{
	HostCmd_DS_FW_AUTO_RECONNECT *fw_auto_reconnect =
		&cmd->params.fw_auto_reconnect_cmd;
	mlan_ds_fw_reconnect *fw_auto_reconn =
		(mlan_ds_fw_reconnect *)pdata_buf;

	ENTER();

	cmd->command = wlan_cpu_to_le16(HostCmd_CMD_FW_AUTO_RECONNECT);
	cmd->size = wlan_cpu_to_le16((sizeof(HostCmd_DS_FW_AUTO_RECONNECT)) +
				     S_DS_GEN);

	fw_auto_reconnect->action = wlan_cpu_to_le16(cmd_action);

	if (cmd_action == HostCmd_ACT_GEN_SET) {
		fw_auto_reconnect->reconnect_counter =
			fw_auto_reconn->fw_reconn_counter;
		fw_auto_reconnect->reconnect_interval =
			fw_auto_reconn->fw_reconn_interval;
		fw_auto_reconnect->flags =
			wlan_cpu_to_le16(fw_auto_reconn->fw_reconn_flags);
	}

	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 network monitor 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_net_monitor(pmlan_private pmpriv, HostCmd_DS_COMMAND *cmd,
				 t_u16 cmd_action, t_void *pdata_buf)
{
	mlan_ds_misc_net_monitor *net_mon;
	HostCmd_DS_802_11_NET_MONITOR *cmd_net_mon = &cmd->params.net_mon;
	ChanBandParamSet_t *pchan_band = MNULL;
	t_u8 sec_chan_offset = 0;
	t_u32 bw_offset = 0;

	ENTER();

	net_mon = (mlan_ds_misc_net_monitor *)pdata_buf;

	cmd->size = wlan_cpu_to_le16(S_DS_GEN +
				     sizeof(HostCmd_DS_802_11_NET_MONITOR));
	cmd->command = wlan_cpu_to_le16(cmd->command);
	cmd_net_mon->action = wlan_cpu_to_le16(cmd_action);
	if (cmd_action == HostCmd_ACT_GEN_SET) {
		if (net_mon->enable_net_mon) {
			cmd_net_mon->enable_net_mon =
				wlan_cpu_to_le16((t_u16)NET_MON_MODE3);
			cmd_net_mon->filter_flag =
				wlan_cpu_to_le16((t_u16)net_mon->filter_flag);
		}
		if (net_mon->enable_net_mon && net_mon->channel) {
			pchan_band =
				&cmd_net_mon->monitor_chan.chan_band_param[0];
			cmd_net_mon->monitor_chan.header.type =
				wlan_cpu_to_le16(TLV_TYPE_CHANNELBANDLIST);
			cmd_net_mon->monitor_chan.header.len =
				wlan_cpu_to_le16(sizeof(ChanBandParamSet_t));
			pchan_band->chan_number = (t_u8)net_mon->channel;
			pchan_band->bandcfg.chanBand =
				wlan_band_to_radio_type((t_u16)net_mon->band);

			if (net_mon->band & BAND_GN ||
			    net_mon->band & BAND_AN ||
			    net_mon->band & BAND_GAC ||
			    net_mon->band & BAND_AAC) {
				bw_offset = net_mon->chan_bandwidth;
				if (bw_offset == CHANNEL_BW_40MHZ_ABOVE) {
					pchan_band->bandcfg.chan2Offset =
						SEC_CHAN_ABOVE;
					pchan_band->bandcfg.chanWidth =
						CHAN_BW_40MHZ;
				} else if (bw_offset ==
					   CHANNEL_BW_40MHZ_BELOW) {
					pchan_band->bandcfg.chan2Offset =
						SEC_CHAN_BELOW;
					pchan_band->bandcfg.chanWidth =
						CHAN_BW_40MHZ;
				} else if (bw_offset == CHANNEL_BW_80MHZ) {
					sec_chan_offset =
						wlan_get_second_channel_offset(
							pmpriv,
							net_mon->channel);
					if (sec_chan_offset == SEC_CHAN_ABOVE)
						pchan_band->bandcfg.chan2Offset =
							SEC_CHAN_ABOVE;
					else if (sec_chan_offset ==
						 SEC_CHAN_BELOW)
						pchan_band->bandcfg.chan2Offset =
							SEC_CHAN_BELOW;
					pchan_band->bandcfg.chanWidth =
						CHAN_BW_80MHZ;
				}
			}
		}
	}

	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
 */
static 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) -
		     sizeof(struct coalesce_receive_filt_rule)) +
		    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
 ********************************************************/

/**
 *  @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 set ipv6 ra offload configuration.
 *
 *  @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 information buffer
 *  @return             N/A
 */

mlan_status wlan_cmd_ipv6_ra_offload(mlan_private *pmpriv,
				     HostCmd_DS_COMMAND *pcmd, t_u16 cmd_action,
				     void *pdata_buf)
{
	HostCmd_DS_IPV6_RA_OFFLOAD *ipv6_ra_cfg = &pcmd->params.ipv6_ra_offload;
	mlan_ds_misc_ipv6_ra_offload *ipv6_ra_offload =
		(mlan_ds_misc_ipv6_ra_offload *)pdata_buf;
	MrvlIEtypesHeader_t *ie = &ipv6_ra_cfg->ipv6_addr_param.Header;

	ENTER();

	pcmd->command = wlan_cpu_to_le16(HostCmd_CMD_IPV6_RA_OFFLOAD_CFG);
	ipv6_ra_cfg->action = wlan_cpu_to_le16(cmd_action);
	if (cmd_action == HostCmd_ACT_GEN_SET) {
		ipv6_ra_cfg->enable = ipv6_ra_offload->enable;
		ie->type = wlan_cpu_to_le16(TLV_TYPE_IPV6_RA_OFFLOAD);
		ie->len = wlan_cpu_to_le16(16);
		memcpy_ext(pmpriv->adapter,
			   ipv6_ra_cfg->ipv6_addr_param.ipv6_addr,
			   ipv6_ra_offload->ipv6_addr, 16,
			   sizeof(ipv6_ra_cfg->ipv6_addr_param.ipv6_addr));
		pcmd->size = wlan_cpu_to_le16(
			S_DS_GEN + sizeof(HostCmd_DS_IPV6_RA_OFFLOAD));
	} else if (cmd_action == HostCmd_ACT_GEN_GET)
		pcmd->size = wlan_cpu_to_le16(S_DS_GEN +
					      sizeof(ipv6_ra_cfg->action));

	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 prepare the config tlvs of roam offload.
 *
 *  @param priv         A pointer to mlan_private structure
 *  @param tlv_no       TLV type
 *  @param value        Pointer to mlan_ds_misc_roam_offload structure
 *  @param pointer      Value of trigger_condition
 *  @param size         Pointer to the buffer of HostCmd_DS_ROAM_OFFLOAD
 *  @return             N/A
 */
static t_u16 mlan_prepare_roam_offload_tlv(pmlan_private pmpriv, t_u32 type,
					   mlan_ds_misc_roam_offload *roam,
					   t_u8 trigger_condition, t_u8 *pos)
{
	MrvlIEtypes_fw_roam_enable_t *enable_tlv = MNULL;
	MrvlIEtypes_fw_roam_trigger_condition_t *trigger_condition_tlv = MNULL;
	MrvlIEtypes_Bssid_t *bssid_tlv = MNULL;
	MrvlIEtypes_SsIdParamSet_t *ssid_tlv = MNULL;
	MrvlIEtypes_fw_roam_retry_count_t *retry_count_tlv = MNULL;
	MrvlIEtypes_para_rssi_t *rssi_para_tlv = MNULL;
	MrvlIEtypes_fw_roam_bgscan_setting_t *bgscan_set_tlv = MNULL;
	MrvlIEtypes_roam_blacklist_t *blacklist_tlv = MNULL;
	MrvlIEtypes_ees_param_set_t *ees_param_tlv = MNULL;
	MrvlIEtypes_band_rssi_t *band_rssi_tlv = MNULL;
	MrvlIEtypes_beacon_miss_threshold_t *bcn_miss_threshold_tlv = MNULL;
	MrvlIEtypes_pre_beacon_miss_threshold_t *pre_bcn_miss_threshold_tlv =
		MNULL;
	MrvlIEtypes_RepeatCount_t *tlv_repeat = MNULL;
	t_u8 zero_mac[MLAN_MAC_ADDR_LENGTH] = {0}, *begin;
	int i = 0;

	ENTER();

	begin = pos;
	if (type & FW_ROAM_ENABLE) {
		enable_tlv = (MrvlIEtypes_fw_roam_enable_t *)pos;
		enable_tlv->header.type = wlan_cpu_to_le16(TLV_TYPE_ROAM);
		enable_tlv->header.len =
			wlan_cpu_to_le16(sizeof(MrvlIEtypes_fw_roam_enable_t) -
					 sizeof(MrvlIEtypesHeader_t));
		if (roam->enable <= ROAM_OFFLOAD_WITHOUT_APLIST)
			enable_tlv->roam_enable = roam->enable;
		else
			enable_tlv->roam_enable = ROAM_OFFLOAD_WITHOUT_APLIST;
		pos += sizeof(MrvlIEtypes_fw_roam_enable_t);
	}
	if (type & FW_ROAM_TRIGGER_COND) {
		trigger_condition_tlv =
			(MrvlIEtypes_fw_roam_trigger_condition_t *)pos;
		trigger_condition_tlv->header.type =
			wlan_cpu_to_le16(TLV_TYPE_ROM_TRIGGER);
		trigger_condition_tlv->header.len = wlan_cpu_to_le16(
			sizeof(trigger_condition_tlv->trigger_condition));
		trigger_condition_tlv->trigger_condition =
			wlan_cpu_to_le16(trigger_condition);
		pos += sizeof(trigger_condition_tlv->header) +
		       sizeof(trigger_condition_tlv->trigger_condition);
	}
	if (type & FW_ROAM_BSSID) {
		bssid_tlv = (MrvlIEtypes_Bssid_t *)pos;
		bssid_tlv->header.type = wlan_cpu_to_le16(TLV_TYPE_BSSID);
		bssid_tlv->header.len =
			wlan_cpu_to_le16(sizeof(bssid_tlv->bssid));
		if (memcmp(pmpriv->adapter, roam->bssid_reconnect, zero_mac,
			   sizeof(zero_mac)) != 0)
			memcpy_ext(pmpriv->adapter, bssid_tlv->bssid,
				   roam->bssid_reconnect,
				   sizeof(bssid_tlv->bssid),
				   sizeof(bssid_tlv->bssid));
		else {
			if (roam->config_mode == ROAM_OFFLOAD_SUSPEND_CFG)
				memcpy_ext(pmpriv->adapter, bssid_tlv->bssid,
					   pmpriv->curr_bss_params
						   .bss_descriptor.mac_address,
					   sizeof(bssid_tlv->bssid),
					   sizeof(bssid_tlv->bssid));
			else if (roam->config_mode == ROAM_OFFLOAD_RESUME_CFG)
				memcpy_ext(pmpriv->adapter, bssid_tlv->bssid,
					   zero_mac, sizeof(bssid_tlv->bssid),
					   sizeof(bssid_tlv->bssid));
		}
		pos += sizeof(bssid_tlv->header) + sizeof(bssid_tlv->bssid);
	}
	if (type & FW_ROAM_SSID) {
		for (i = 0; i < roam->ssid_list.ssid_num; i++) {
			ssid_tlv = (MrvlIEtypes_SsIdParamSet_t *)pos;
			ssid_tlv->header.type = wlan_cpu_to_le16(TLV_TYPE_SSID);
			memcpy_ext(pmpriv->adapter, ssid_tlv->ssid,
				   roam->ssid_list.ssids[i].ssid,
				   roam->ssid_list.ssids[i].ssid_len,
				   roam->ssid_list.ssids[i].ssid_len);
			pos += sizeof(ssid_tlv->header) +
			       wlan_strlen(ssid_tlv->ssid);
			ssid_tlv->header.len =
				wlan_cpu_to_le16(wlan_strlen(ssid_tlv->ssid));
		}
		if (!roam->ssid_list.ssid_num) {
			ssid_tlv = (MrvlIEtypes_SsIdParamSet_t *)pos;
			ssid_tlv->header.type = wlan_cpu_to_le16(TLV_TYPE_SSID);
			memcpy_ext(
				pmpriv->adapter, ssid_tlv->ssid,
				pmpriv->curr_bss_params.bss_descriptor.ssid.ssid,
				pmpriv->curr_bss_params.bss_descriptor.ssid
					.ssid_len,
				pmpriv->curr_bss_params.bss_descriptor.ssid
					.ssid_len);
			ssid_tlv->header.len =
				wlan_cpu_to_le16(wlan_strlen(ssid_tlv->ssid));
			pos += sizeof(ssid_tlv->header) + ssid_tlv->header.len;
		}
	}
	if (type & FW_ROAM_RETRY_COUNT) {
		retry_count_tlv = (MrvlIEtypes_fw_roam_retry_count_t *)pos;
		retry_count_tlv->header.type =
			wlan_cpu_to_le16(TLV_TYPE_ROM_RETRY_COUNT);
		retry_count_tlv->header.len =
			wlan_cpu_to_le16(sizeof(retry_count_tlv->retry_count));
		if (roam->retry_count)
			retry_count_tlv->retry_count =
				wlan_cpu_to_le16(roam->retry_count);
		else
			retry_count_tlv->retry_count =
				wlan_cpu_to_le16(RETRY_UNLIMITED_TIME);
		pos += sizeof(retry_count_tlv->header) +
		       sizeof(retry_count_tlv->retry_count);
	}
	if (type & FW_ROAM_RSSI_PARA) {
		rssi_para_tlv = (MrvlIEtypes_para_rssi_t *)pos;
		rssi_para_tlv->header.type =
			wlan_cpu_to_le16(TLV_TYPE_ROM_PARA_RSSI);
		rssi_para_tlv->header.len =
			wlan_cpu_to_le16(sizeof(rssi_para_tlv->max_rssi) +
					 sizeof(rssi_para_tlv->min_rssi) +
					 sizeof(rssi_para_tlv->step_rssi));
		rssi_para_tlv->max_rssi = roam->para_rssi.max_rssi;
		rssi_para_tlv->min_rssi = roam->para_rssi.min_rssi;
		rssi_para_tlv->step_rssi = roam->para_rssi.step_rssi;
		pos += sizeof(rssi_para_tlv->header) +
		       sizeof(rssi_para_tlv->max_rssi) +
		       sizeof(rssi_para_tlv->min_rssi) +
		       sizeof(rssi_para_tlv->step_rssi);
	}
	if (type & FW_ROAM_BAND_RSSI) {
		band_rssi_tlv = (MrvlIEtypes_band_rssi_t *)pos;
		band_rssi_tlv->header.type =
			wlan_cpu_to_le16(TLV_TYPE_BAND_RSSI);
		band_rssi_tlv->header.len =
			wlan_cpu_to_le16(sizeof(MrvlIEtypes_band_rssi_t) -
					 sizeof(MrvlIEtypesHeader_t));
		band_rssi_tlv->band_rssi.band_preferred =
			roam->band_rssi.band_preferred;
		band_rssi_tlv->band_rssi.rssi_hysteresis =
			roam->band_rssi.rssi_hysteresis;
		pos += sizeof(MrvlIEtypes_band_rssi_t);
	}

	if (type & FW_ROAM_BGSCAN_PARAM) {
		bgscan_set_tlv = (MrvlIEtypes_fw_roam_bgscan_setting_t *)pos;
		bgscan_set_tlv->header.type =
			wlan_cpu_to_le16(TLV_TYPE_ROM_BGSCAN);
		bgscan_set_tlv->header.len = wlan_cpu_to_le16(
			sizeof(MrvlIEtypes_fw_roam_bgscan_setting_t) -
			sizeof(MrvlIEtypesHeader_t));
		bgscan_set_tlv->bss_type = roam->bgscan_cfg.bss_type;
		bgscan_set_tlv->channels_perscan =
			roam->bgscan_cfg.channels_per_scan;
		bgscan_set_tlv->scan_interval =
			wlan_cpu_to_le32(roam->bgscan_cfg.scan_interval);
		bgscan_set_tlv->report_condition =
			wlan_cpu_to_le32(roam->bgscan_cfg.bg_rpt_condition);
		pos += sizeof(MrvlIEtypes_fw_roam_bgscan_setting_t);
	}

	if (type & FW_ROAM_EES_PARAM) {
		ees_param_tlv = (MrvlIEtypes_ees_param_set_t *)pos;
		ees_param_tlv->header.type =
			wlan_cpu_to_le16(TLV_TYPE_ENERGYEFFICIENTSCAN);
		ees_param_tlv->header.len =
			wlan_cpu_to_le16(sizeof(MrvlIEtypes_ees_param_set_t) -
					 sizeof(MrvlIEtypesHeader_t));
		ees_param_tlv->ees_cfg.ees_mode =
			wlan_cpu_to_le16(roam->ees_cfg.ees_mode);
		ees_param_tlv->ees_cfg.ees_rpt_condition =
			wlan_cpu_to_le16(roam->ees_cfg.ees_rpt_condition);
		ees_param_tlv->ees_cfg.high_scan_period =
			wlan_cpu_to_le16(roam->ees_cfg.high_scan_period);
		ees_param_tlv->ees_cfg.high_scan_count =
			wlan_cpu_to_le16(roam->ees_cfg.high_scan_count);
		ees_param_tlv->ees_cfg.mid_scan_period =
			wlan_cpu_to_le16(roam->ees_cfg.mid_scan_period);
		ees_param_tlv->ees_cfg.mid_scan_count =
			wlan_cpu_to_le16(roam->ees_cfg.mid_scan_count);
		ees_param_tlv->ees_cfg.low_scan_period =
			wlan_cpu_to_le16(roam->ees_cfg.low_scan_period);
		ees_param_tlv->ees_cfg.low_scan_count =
			wlan_cpu_to_le16(roam->ees_cfg.low_scan_count);
		pos += sizeof(MrvlIEtypes_ees_param_set_t);
	}

	if (type & FW_ROAM_BCN_MISS_THRESHOLD) {
		bcn_miss_threshold_tlv =
			(MrvlIEtypes_beacon_miss_threshold_t *)pos;
		bcn_miss_threshold_tlv->header.type =
			wlan_cpu_to_le16(TLV_TYPE_BCNMISS);
		bcn_miss_threshold_tlv->header.len = wlan_cpu_to_le16(
			sizeof(MrvlIEtypes_beacon_miss_threshold_t) -
			sizeof(MrvlIEtypesHeader_t));
		bcn_miss_threshold_tlv->bcn_miss_threshold =
			roam->bcn_miss_threshold;
		pos += sizeof(MrvlIEtypes_beacon_miss_threshold_t);
	}

	if (type & FW_ROAM_PRE_BCN_MISS_THRESHOLD) {
		pre_bcn_miss_threshold_tlv =
			(MrvlIEtypes_pre_beacon_miss_threshold_t *)pos;
		pre_bcn_miss_threshold_tlv->header.type =
			wlan_cpu_to_le16(TLV_TYPE_PRE_BCNMISS);
		pre_bcn_miss_threshold_tlv->header.len = wlan_cpu_to_le16(
			sizeof(MrvlIEtypes_pre_beacon_miss_threshold_t) -
			sizeof(MrvlIEtypesHeader_t));
		pre_bcn_miss_threshold_tlv->pre_bcn_miss_threshold =
			roam->pre_bcn_miss_threshold;
		pos += sizeof(MrvlIEtypes_pre_beacon_miss_threshold_t);
	}

	if (type & FW_ROAM_BLACKLIST) {
		blacklist_tlv = (MrvlIEtypes_roam_blacklist_t *)pos;
		blacklist_tlv->header.type =
			wlan_cpu_to_le16(TLV_TYPE_BLACKLIST_BSSID);
		blacklist_tlv->header.len =
			roam->black_list.ap_num * MLAN_MAC_ADDR_LENGTH +
			sizeof(roam->black_list.ap_num);
		memcpy_ext(pmpriv->adapter, (t_u8 *)&blacklist_tlv->blacklist,
			   (t_u8 *)&roam->black_list, blacklist_tlv->header.len,
			   sizeof(blacklist_tlv->blacklist));
		pos += sizeof(MrvlIEtypesHeader_t) + blacklist_tlv->header.len;
		blacklist_tlv->header.len =
			wlan_cpu_to_le16(blacklist_tlv->header.len);
	}

	if (type & FW_ROAM_REPEAT_CNT) {
		tlv_repeat = (MrvlIEtypes_RepeatCount_t *)pos;
		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(roam->repeat_count);
		pos += sizeof(MrvlIEtypes_RepeatCount_t);
	}
	LEAVE();
	return ((t_u16)(pos - begin));
}
/**
 *  @brief This function sends enable/disable roam offload command to firmware.
 *
 *  @param pmpriv         A pointer to mlan_private structure
 *  @param pcmd          Hostcmd ID
 *  @param cmd_action   Command action
 *  @return             N/A
 */
static mlan_status wlan_cmd_roam_offload(pmlan_private pmpriv,
					 HostCmd_DS_COMMAND *cmd,
					 t_u16 cmd_action, t_void *pdata_buf)
{
	HostCmd_DS_ROAM_OFFLOAD *roam_cmd = &cmd->params.roam_offload;
	MrvlIEtypes_roam_aplist_t *aplist = MNULL;
	t_u8 *pos = (t_u8 *)roam_cmd + sizeof(roam_cmd->action);
	mlan_ds_misc_roam_offload *roam = MNULL;
	t_u8 zero_mac[MLAN_MAC_ADDR_LENGTH] = {0};
	t_u32 type = 0;
	t_u8 trigger_condition = 0;

	ENTER();

	cmd->command = wlan_cpu_to_le16(HostCmd_CMD_ROAM_OFFLOAD);
	cmd->size = S_DS_GEN + sizeof(HostCmd_DS_ROAM_OFFLOAD);
	roam_cmd->action = wlan_cpu_to_le16(cmd_action);

	roam = (mlan_ds_misc_roam_offload *)pdata_buf;

	if (roam->config_mode) {
		switch (roam->config_mode) {
		case ROAM_OFFLOAD_ENABLE:
			type |= FW_ROAM_ENABLE;
			if (roam->enable && roam->enable != AUTO_RECONNECT) {
				type |= FW_ROAM_TRIGGER_COND;
				trigger_condition |= RSSI_LOW_TRIGGER |
						     PRE_BEACON_LOST_TRIGGER;
			}
			break;
		case ROAM_OFFLOAD_SUSPEND_CFG:
			type |= FW_ROAM_TRIGGER_COND | FW_ROAM_RETRY_COUNT;
			if (roam->enable == AUTO_RECONNECT) {
				type |= FW_ROAM_BSSID | FW_ROAM_SSID;
				trigger_condition = LINK_LOST_TRIGGER |
						    DEAUTH_WITH_EXT_AP_TRIGGER;
			} else
				trigger_condition = LINK_LOST_TRIGGER |
						    DEAUTH_WITH_EXT_AP_TRIGGER |
						    RSSI_LOW_TRIGGER |
						    PRE_BEACON_LOST_TRIGGER;

			if (roam->enable == ROAM_OFFLOAD_WITH_BSSID)
				type |= FW_ROAM_BSSID;
			if (roam->enable == ROAM_OFFLOAD_WITH_SSID)
				type |= FW_ROAM_SSID;
			break;
		case ROAM_OFFLOAD_RESUME_CFG:
			type |= FW_ROAM_TRIGGER_COND;
			if (roam->enable == AUTO_RECONNECT)
				trigger_condition = NO_TRIGGER;
			else
				trigger_condition = RSSI_LOW_TRIGGER |
						    PRE_BEACON_LOST_TRIGGER;
			if (roam->enable == ROAM_OFFLOAD_WITH_BSSID ||
			    roam->enable == AUTO_RECONNECT)
				type |= FW_ROAM_BSSID;
			break;
		case ROAM_OFFLOAD_PARAM_CFG:
			if (roam->enable && roam->enable != AUTO_RECONNECT) {
				if (roam->retry_count != 0)
					type |= FW_ROAM_RETRY_COUNT;
				if (roam->ssid_list.ssid_num)
					type |= FW_ROAM_SSID;
				if (roam->para_rssi.set_flag)
					type |= FW_ROAM_RSSI_PARA;
				if (memcmp(pmpriv->adapter,
					   roam->bssid_reconnect, zero_mac,
					   sizeof(zero_mac)) != 0)
					type |= FW_ROAM_BSSID;
				if (roam->band_rssi_flag)
					type |= FW_ROAM_BAND_RSSI;
				if (roam->bgscan_set_flag)
					type |= FW_ROAM_BGSCAN_PARAM;
				if (roam->ees_param_set_flag)
					type |= FW_ROAM_EES_PARAM;
				if (roam->bcn_miss_threshold)
					type |= FW_ROAM_BCN_MISS_THRESHOLD;
				if (roam->pre_bcn_miss_threshold)
					type |= FW_ROAM_PRE_BCN_MISS_THRESHOLD;
				if (roam->black_list.ap_num)
					type |= FW_ROAM_BLACKLIST;
				if (roam->trigger_condition != 0xff) {
					type |= FW_ROAM_TRIGGER_COND;
					trigger_condition =
						roam->trigger_condition;
				}
				if (roam->repeat_count)
					type |= FW_ROAM_REPEAT_CNT;
			}
			break;
		}
		cmd->size += mlan_prepare_roam_offload_tlv(
			pmpriv, type, roam, trigger_condition, pos);
	}
	if (roam->aplist.ap_num) {
		aplist = (MrvlIEtypes_roam_aplist_t *)pos;
		aplist->header.type = wlan_cpu_to_le16(TLV_TYPE_APLIST);
		aplist->header.len = roam->aplist.ap_num * MLAN_MAC_ADDR_LENGTH;
		memcpy_ext(pmpriv->adapter, aplist->ap_mac, roam->aplist.ap_mac,
			   roam->aplist.ap_num * MLAN_MAC_ADDR_LENGTH,
			   roam->aplist.ap_num * MLAN_MAC_ADDR_LENGTH);
		pos += sizeof(aplist->header) + aplist->header.len;
		cmd->size += sizeof(aplist->header) + aplist->header.len;
		aplist->header.len = wlan_cpu_to_le16(aplist->header.len);
	}
	cmd->size = wlan_cpu_to_le16(cmd->size);

	LEAVE();
	return MLAN_STATUS_SUCCESS;
}

/**
 *  @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;
	MrvlIEtypes_Cloud_Keep_Alive_Rx_t *keep_alive_Rx_tlv = MNULL;
	mlan_ds_misc_keep_alive_rx *misc_keep_alive_rx = 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));
				memcpy_ext(pmpriv->adapter,
					   (t_u8 *)&pkt_tlv->ip_packet,
					   misc_keep_alive->packet,
					   misc_keep_alive->pkt_len,
					   MKEEP_ALIVE_IP_PKT_MAX);
				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;
	case OID_CLOUD_KEEP_ALIVE_ACK:
		misc_keep_alive_rx = (mlan_ds_misc_keep_alive_rx *)pdata_buf;
		keep_alive_Rx_tlv = (MrvlIEtypes_Cloud_Keep_Alive_Rx_t *)pos;
		keep_alive_Rx_tlv->header.type =
			wlan_cpu_to_le16(TLV_TYPE_CLOUD_KEEP_ALIVE_ACK);
		keep_alive_Rx_tlv->keep_alive_id =
			misc_keep_alive_rx->mkeep_alive_id;
		keep_alive_Rx_tlv->enable = misc_keep_alive_rx->enable;
		memcpy_ext(pmpriv->adapter,
			   keep_alive_Rx_tlv->eth_header.dest_addr,
			   misc_keep_alive_rx->dst_mac, MLAN_MAC_ADDR_LENGTH,
			   MLAN_MAC_ADDR_LENGTH);
		memcpy_ext(pmpriv->adapter,
			   keep_alive_Rx_tlv->eth_header.src_addr,
			   misc_keep_alive_rx->src_mac, MLAN_MAC_ADDR_LENGTH,
			   MLAN_MAC_ADDR_LENGTH);
		memcpy_ext(pmpriv->adapter,
			   (t_u8 *)&keep_alive_Rx_tlv->eth_header.h803_len,
			   eth_ip, sizeof(t_u16), sizeof(t_u16));
		if (misc_keep_alive_rx->ether_type)
			keep_alive_Rx_tlv->eth_header.h803_len =
				mlan_htons(misc_keep_alive_rx->ether_type);
		else
			memcpy_ext(
				pmpriv->adapter,
				(t_u8 *)&keep_alive_Rx_tlv->eth_header.h803_len,
				eth_ip, sizeof(t_u16), sizeof(t_u16));
		memcpy_ext(pmpriv->adapter,
			   (t_u8 *)&keep_alive_Rx_tlv->ip_packet,
			   misc_keep_alive_rx->packet,
			   misc_keep_alive_rx->pkt_len,
			   MKEEP_ALIVE_ACK_PKT_MAX);

		len = sizeof(MrvlIEtypes_Cloud_Keep_Alive_Rx_t) +
		      misc_keep_alive_rx->pkt_len - sizeof(MrvlIEtypesHeader_t);
		keep_alive_Rx_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
 */
static 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 enable/disable CSI 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
 */
static mlan_status wlan_cmd_csi(pmlan_private pmpriv, HostCmd_DS_COMMAND *cmd,
				t_u16 cmd_action, t_u16 *pdata_buf)
{
	HostCmd_DS_CSI_CFG *csi_cfg_cmd = &cmd->params.csi_params;
	mlan_ds_csi_params *csi_params = MNULL;

	ENTER();

	cmd->command = wlan_cpu_to_le16(HostCmd_CMD_CSI);
	cmd->size = sizeof(HostCmd_DS_CSI_CFG) + S_DS_GEN;
	csi_cfg_cmd->action = wlan_cpu_to_le16(cmd_action);
	switch (cmd_action) {
	case CSI_CMD_ENABLE:
		csi_params = (mlan_ds_csi_params *)pdata_buf;
		csi_cfg_cmd->head_id = wlan_cpu_to_le32(csi_params->head_id);
		csi_cfg_cmd->tail_id = wlan_cpu_to_le32(csi_params->tail_id);
		csi_cfg_cmd->chip_id = csi_params->chip_id;
		csi_cfg_cmd->csi_filter_cnt = csi_params->csi_filter_cnt;
		if (csi_cfg_cmd->csi_filter_cnt > CSI_FILTER_MAX)
			csi_cfg_cmd->csi_filter_cnt = CSI_FILTER_MAX;
		memcpy_ext(pmpriv->adapter, (t_u8 *)csi_cfg_cmd->csi_filter,
			   (t_u8 *)csi_params->csi_filter,
			   sizeof(mlan_csi_filter_t) *
				   csi_cfg_cmd->csi_filter_cnt,
			   sizeof(csi_cfg_cmd->csi_filter));
		DBG_HEXDUMP(MCMD_D, "Enable CSI", csi_cfg_cmd,
			    sizeof(HostCmd_DS_CSI_CFG));
		break;
	case CSI_CMD_DISABLE:
		DBG_HEXDUMP(MCMD_D, "Disable CSI", csi_cfg_cmd,
			    sizeof(HostCmd_DS_CSI_CFG));
	default:
		break;
	}
	cmd->size = wlan_cpu_to_le16(cmd->size);
	LEAVE();
	return MLAN_STATUS_SUCCESS;
}

/**
 *  @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 HostCmd_CMD_CSI:
		ret = wlan_cmd_csi(pmpriv, cmd_ptr, cmd_action, pdata_buf);
		break;
	case HostCmd_CMD_HAL_PHY_CFG:
		ret = wlan_cmd_hal_phy_cfg(pmpriv, cmd_ptr, cmd_action,
					   pdata_buf);
		break;
	case HostCmd_CMD_IPS_CONFIG:
		ret = wlan_cmd_ips_config(pmpriv, cmd_ptr, cmd_action,
					  pdata_buf);
		break;
	case HostCmd_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_FTM_CONFIG_SESSION_PARAMS:
		ret = wlan_cmd_802_11_ftm_config_session_params(
			pmpriv, cmd_ptr, cmd_action, cmd_oid, pdata_buf);
		break;
	case HostCmd_CMD_FTM_CONFIG_RESPONDER:
		ret = wlan_cmd_802_11_ftm_config_responder(
			pmpriv, cmd_ptr, cmd_action, cmd_oid, pdata_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_TDLS_CONFIG:
		ret = wlan_cmd_tdls_config(pmpriv, cmd_ptr, cmd_action,
					   pdata_buf);
		break;
	case HostCmd_CMD_TDLS_OPERATION:
		ret = wlan_cmd_tdls_oper(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:
	case HostCmd_CMD_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_802_11_NET_MONITOR:
		ret = wlan_cmd_net_monitor(pmpriv, cmd_ptr, cmd_action,
					   pdata_buf);
		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 HostCmd_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_FW_AUTO_RECONNECT:
		ret = wlan_cmd_fw_auto_reconnect(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
	case HostCmd_CMD_MULTI_CHAN_CONFIG:
		ret = wlan_cmd_multi_chan_cfg(pmpriv, cmd_ptr, cmd_action,
					      pdata_buf);
		break;
	case HostCmd_CMD_MULTI_CHAN_POLICY:
		ret = wlan_cmd_multi_chan_policy(pmpriv, cmd_ptr, cmd_action,
						 pdata_buf);
		break;
	case HostCmd_CMD_DRCS_CONFIG:
		ret = wlan_cmd_drcs_cfg(pmpriv, cmd_ptr, cmd_action, pdata_buf);
		break;
	case HostCmd_CMD_CONFIG_LOW_POWER_MODE:
		ret = wlan_cmd_low_pwr_mode(pmpriv, cmd_ptr, pdata_buf);
		break;
	case HostCmd_CMD_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_CMD_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_IPV6_RA_OFFLOAD_CFG:
		ret = wlan_cmd_ipv6_ra_offload(pmpriv, cmd_ptr, cmd_action,
					       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_ROAM_OFFLOAD:
		ret = wlan_cmd_roam_offload(pmpriv, 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 HostCmd_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_GPIO_TSF_LATCH_PARAM_CONFIG:
		ret = wlan_cmd_gpio_tsf_latch(pmpriv, cmd_ptr, cmd_action,
					      pioctl_buf, pdata_buf);
		break;
	case HostCmd_CMD_RX_ABORT_CFG:
		ret = wlan_cmd_rxabortcfg(pmpriv, cmd_ptr, cmd_action,
					  pdata_buf);
		break;
	case HostCmd_CMD_OFDM_DESENSE_CFG:
		ret = wlan_cmd_ofdmdesense_cfg(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_NAV_MITIGATION_CFG:
		ret = wlan_cmd_nav_mitigation(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_CMD_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;
	case HostCmd_CMD_MC_AGGR_CFG:
		ret = wlan_cmd_mc_aggr_cfg(pmpriv, cmd_ptr, cmd_action,
					   pdata_buf);
		break;
	case HostCmd_CMD_GET_CH_LOAD:
		ret = wlan_cmd_get_ch_load(pmpriv, cmd_ptr, cmd_action,
					   pdata_buf);
		break;
	case HostCmd_CMD_CROSS_CHIP_SYNCH:
		ret = wlan_cmd_cross_chip_synch(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;
}
