/** @file mlan_shim.c
 *
 *  @brief This file contains APIs to MOAL module.
 *
 *  Copyright 2008-2021 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
 *
 *
 */

/**
 *  @mainpage MLAN Driver
 *
 *  @section overview_sec Overview
 *
 *  The MLAN is an OS independent WLAN driver for NXP 802.11
 *  embedded chipset.
 *
 *
 *  Copyright 2008-2021 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.
 *
 */

/********************************************************
Change log:
    10/13/2008: initial version
********************************************************/

#include "mlan.h"
#ifdef STA_SUPPORT
#include "mlan_join.h"
#endif
#include "mlan_util.h"
#include "mlan_fw.h"
#include "mlan_main.h"
#include "mlan_wmm.h"
#ifdef SDIO
#include "mlan_sdio.h"
#endif /* SDIO */
#ifdef PCIE
#include "mlan_pcie.h"
#endif /* PCIE */
#ifdef UAP_SUPPORT
#include "mlan_uap.h"
#endif
#include "mlan_11h.h"
#include "mlan_11n_rxreorder.h"
#ifdef DRV_EMBEDDED_AUTHENTICATOR
#include "authenticator_api.h"
#endif

/********************************************************
			Local Variables
********************************************************/

/********************************************************
			Global Variables
********************************************************/
#ifdef STA_SUPPORT
static mlan_operations mlan_sta_ops = {
	/* init cmd handler */
	wlan_ops_sta_init_cmd,
	/* ioctl handler */
	wlan_ops_sta_ioctl,
	/* cmd handler */
	wlan_ops_sta_prepare_cmd,
	/* cmdresp handler */
	wlan_ops_sta_process_cmdresp,
	/* rx handler */
	wlan_ops_sta_process_rx_packet,
	/* Event handler */
	wlan_ops_sta_process_event,
	/* txpd handler */
	wlan_ops_sta_process_txpd,
	/* BSS role: STA */
	MLAN_BSS_ROLE_STA,
};
#endif
#ifdef UAP_SUPPORT
static mlan_operations mlan_uap_ops = {
	/* init cmd handler */
	wlan_ops_uap_init_cmd,
	/* ioctl handler */
	wlan_ops_uap_ioctl,
	/* cmd handler */
	wlan_ops_uap_prepare_cmd,
	/* cmdresp handler */
	wlan_ops_uap_process_cmdresp,
	/* rx handler */
	wlan_ops_uap_process_rx_packet,
	/* Event handler */
	wlan_ops_uap_process_event,
	/* txpd handler */
	wlan_ops_uap_process_txpd,
	/* BSS role: uAP */
	MLAN_BSS_ROLE_UAP,
};
#endif

/** mlan function table */
mlan_operations *mlan_ops[] = {
#ifdef STA_SUPPORT
	&mlan_sta_ops,
#endif
#ifdef UAP_SUPPORT
	&mlan_uap_ops,
#endif
	MNULL,
};

/** Global moal_assert callback */
t_void (*assert_callback)(t_pvoid pmoal_handle, t_u32 cond) = MNULL;
#ifdef DEBUG_LEVEL1
#ifdef DEBUG_LEVEL2
#define DEFAULT_DEBUG_MASK (0xffffffff)
#else
#define DEFAULT_DEBUG_MASK (MMSG | MFATAL | MERROR)
#endif

/** Global moal_print callback */
t_void (*print_callback)(t_pvoid pmoal_handle, t_u32 level, char *pformat,
			 IN...) = MNULL;

/** Global moal_get_system_time callback */
mlan_status (*get_sys_time_callback)(t_pvoid pmoal_handle, t_pu32 psec,
				     t_pu32 pusec) = MNULL;

/** Global driver debug mit masks */
t_u32 mlan_drvdbg = DEFAULT_DEBUG_MASK;
#endif

#ifdef USB
extern mlan_status wlan_get_usb_device(pmlan_adapter pmadapter);
#endif
/********************************************************
			Local Functions
*******************************************************/
/**
 *  @brief This function process pending ioctl
 *
 *  @param pmadapter  A pointer to mlan_adapter structure
 *
 */
static void wlan_process_pending_ioctl(mlan_adapter *pmadapter)
{
	pmlan_ioctl_req pioctl_buf;
	mlan_status status = MLAN_STATUS_SUCCESS;
	pmlan_callbacks pcb;
#if defined(STA_SUPPORT) && defined(UAP_SUPPORT)
	pmlan_ds_bss bss = MNULL;
#endif
#ifdef STA_SUPPORT
	pmlan_ds_misc_cfg misc = MNULL;
#endif
	ENTER();

	pcb = &pmadapter->callbacks;

	while ((pioctl_buf = (pmlan_ioctl_req)util_dequeue_list(
			pmadapter->pmoal_handle, &pmadapter->ioctl_pending_q,
			pcb->moal_spin_lock, pcb->moal_spin_unlock))) {
		switch (pioctl_buf->req_id) {
#if defined(STA_SUPPORT) && defined(UAP_SUPPORT)
		case MLAN_IOCTL_BSS:
			bss = (mlan_ds_bss *)pioctl_buf->pbuf;
			if (bss->sub_command == MLAN_OID_BSS_ROLE) {
				PRINTM(MCMND, "Role switch ioctl: %d\n",
				       bss->param.bss_role);
				status = wlan_bss_ioctl_bss_role(pmadapter,
								 pioctl_buf);
			}
			break;
#endif
		case MLAN_IOCTL_MISC_CFG:
			misc = (mlan_ds_misc_cfg *)pioctl_buf->pbuf;
			if (misc->sub_command == MLAN_OID_MISC_WARM_RESET) {
				PRINTM(MCMND, "Warm Reset ioctl\n");
				status = wlan_misc_ioctl_warm_reset(pmadapter,
								    pioctl_buf);
			}
			break;
		default:
			break;
		}
		if (status != MLAN_STATUS_PENDING)
			pcb->moal_ioctl_complete(pmadapter->pmoal_handle,
						 pioctl_buf, status);
	}
	LEAVE();
}
/********************************************************
			Global Functions
********************************************************/

/**
 *  @brief This function registers MOAL to MLAN module.
 *
 *  @param pmdevice        A pointer to a mlan_device structure
 *                         allocated in MOAL
 *  @param ppmlan_adapter  A pointer to a t_void pointer to store
 *                         mlan_adapter structure pointer as the context
 *
 *  @return                MLAN_STATUS_SUCCESS
 *                             The registration succeeded.
 *                         MLAN_STATUS_FAILURE
 *                             The registration failed.
 *
 * mlan_status mlan_register(
 *   pmlan_device     pmdevice,
 *   t_void           **ppmlan_adapter
 * );
 *
 * Comments
 *   MOAL constructs mlan_device data structure to pass moal_handle and
 *   mlan_callback table to MLAN. MLAN returns mlan_adapter pointer to
 *   the ppmlan_adapter buffer provided by MOAL.
 * Headers:
 *   declared in mlan_decl.h
 * See Also
 *   mlan_unregister
 */
mlan_status mlan_register(pmlan_device pmdevice, t_void **ppmlan_adapter)
{
	mlan_status ret = MLAN_STATUS_SUCCESS;
	pmlan_adapter pmadapter = MNULL;
	pmlan_callbacks pcb = MNULL;
	t_u8 i = 0;
	t_u32 j = 0;

	if (!pmdevice || !ppmlan_adapter) {
		return MLAN_STATUS_FAILURE;
	}
	MASSERT(ppmlan_adapter);
	MASSERT(pmdevice->callbacks.moal_print);
#ifdef DEBUG_LEVEL1
	print_callback = pmdevice->callbacks.moal_print;
	get_sys_time_callback = pmdevice->callbacks.moal_get_system_time;
#endif
	assert_callback = pmdevice->callbacks.moal_assert;

	ENTER();

	MASSERT(pmdevice->callbacks.moal_malloc);
	MASSERT(pmdevice->callbacks.moal_mfree);
	MASSERT(pmdevice->callbacks.moal_memset);
	MASSERT(pmdevice->callbacks.moal_memmove);
	MASSERT(pmdevice->callbacks.moal_udelay);
	MASSERT(pmdevice->callbacks.moal_usleep_range);

	if (!pmdevice->callbacks.moal_malloc ||
	    !pmdevice->callbacks.moal_mfree ||
	    !pmdevice->callbacks.moal_memset ||
	    !pmdevice->callbacks.moal_udelay ||
	    !pmdevice->callbacks.moal_usleep_range ||
	    !pmdevice->callbacks.moal_memmove) {
		LEAVE();
		return MLAN_STATUS_FAILURE;
	}
	if (pmdevice->callbacks.moal_recv_amsdu_packet)
		PRINTM(MMSG, "Enable moal_recv_amsdu_packet\n");

	/* Allocate memory for adapter structure */
	if (pmdevice->callbacks.moal_vmalloc && pmdevice->callbacks.moal_vfree)
		ret = pmdevice->callbacks.moal_vmalloc(pmdevice->pmoal_handle,
						       sizeof(mlan_adapter),
						       (t_u8 **)&pmadapter);
	else
		ret = pmdevice->callbacks.moal_malloc(pmdevice->pmoal_handle,
						      sizeof(mlan_adapter),
						      MLAN_MEM_DEF,
						      (t_u8 **)&pmadapter);
	if ((ret != MLAN_STATUS_SUCCESS) || !pmadapter) {
		ret = MLAN_STATUS_FAILURE;
		goto exit_register;
	}

	pmdevice->callbacks.moal_memset(pmdevice->pmoal_handle, pmadapter, 0,
					sizeof(mlan_adapter));

	pcb = &pmadapter->callbacks;

	/* Save callback functions */
	pmdevice->callbacks.moal_memmove(pmadapter->pmoal_handle, pcb,
					 &pmdevice->callbacks,
					 sizeof(mlan_callbacks));

	/* Assertion for all callback functions */
	MASSERT(pcb->moal_get_hw_spec_complete);
	MASSERT(pcb->moal_init_fw_complete);
	MASSERT(pcb->moal_shutdown_fw_complete);
	MASSERT(pcb->moal_send_packet_complete);
	MASSERT(pcb->moal_recv_packet);
	MASSERT(pcb->moal_recv_event);
	MASSERT(pcb->moal_ioctl_complete);

#if defined(SDIO) || defined(PCIE)
	if (!IS_USB(pmadapter->card_type)) {
		MASSERT(pcb->moal_write_reg);
		MASSERT(pcb->moal_read_reg);
		MASSERT(pcb->moal_alloc_mlan_buffer);
		MASSERT(pcb->moal_free_mlan_buffer);
	}
#endif
	MASSERT(pcb->moal_get_vdll_data);
	MASSERT(pcb->moal_write_data_sync);
	MASSERT(pcb->moal_read_data_sync);
	MASSERT(pcb->moal_mfree);
	MASSERT(pcb->moal_memcpy);
	MASSERT(pcb->moal_memcpy_ext);
	MASSERT(pcb->moal_memcmp);
	MASSERT(pcb->moal_get_system_time);
	MASSERT(pcb->moal_init_timer);
	MASSERT(pcb->moal_free_timer);
	MASSERT(pcb->moal_get_boot_ktime);
	MASSERT(pcb->moal_start_timer);
	MASSERT(pcb->moal_stop_timer);
	MASSERT(pcb->moal_init_lock);
	MASSERT(pcb->moal_free_lock);
	MASSERT(pcb->moal_spin_lock);
	MASSERT(pcb->moal_spin_unlock);
	MASSERT(pcb->moal_hist_data_add);
	MASSERT(pcb->moal_updata_peer_signal);
	MASSERT(pcb->moal_do_div);
	/* Save pmoal_handle */
	pmadapter->pmoal_handle = pmdevice->pmoal_handle;

	pmadapter->feature_control = pmdevice->feature_control;

	pmadapter->card_type = pmdevice->card_type;
	pmadapter->card_rev = pmdevice->card_rev;
	pmadapter->init_para.uap_max_sta = pmdevice->uap_max_sta;
	pmadapter->init_para.mcs32 = pmdevice->mcs32;

#ifdef SDIO
	if (IS_SD(pmadapter->card_type)) {
		PRINTM(MMSG,
		       "Attach mlan adapter operations.card_type is 0x%x.\n",
		       pmdevice->card_type);
		memcpy_ext(pmadapter, &pmadapter->ops, &mlan_sdio_ops,
			   sizeof(mlan_adapter_operations),
			   sizeof(mlan_adapter_operations));
		ret = wlan_get_sdio_device(pmadapter);
		if (MLAN_STATUS_SUCCESS != ret) {
			ret = MLAN_STATUS_FAILURE;
			goto error;
		}
		if ((pmdevice->int_mode == INT_MODE_GPIO) &&
		    (pmdevice->gpio_pin == 0)) {
			PRINTM(MERROR,
			       "SDIO_GPIO_INT_CONFIG: Invalid GPIO Pin\n");
			ret = MLAN_STATUS_FAILURE;
			goto error;
		}
		pmadapter->init_para.int_mode = pmdevice->int_mode;
		pmadapter->init_para.gpio_pin = pmdevice->gpio_pin;
		/* card specific probing has been deferred until now .. */
		ret = wlan_sdio_probe(pmadapter);
		if (MLAN_STATUS_SUCCESS != ret) {
			ret = MLAN_STATUS_FAILURE;
			goto error;
		}
		pmadapter->pcard_sd->max_segs = pmdevice->max_segs;
		pmadapter->pcard_sd->max_seg_size = pmdevice->max_seg_size;

		pmadapter->init_para.mpa_tx_cfg = pmdevice->mpa_tx_cfg;
		pmadapter->init_para.mpa_rx_cfg = pmdevice->mpa_rx_cfg;
		pmadapter->pcard_sd->sdio_rx_aggr_enable =
			pmdevice->sdio_rx_aggr_enable;
	}
#endif

#ifdef PCIE
	if (IS_PCIE(pmadapter->card_type)) {
		MASSERT(pcb->moal_malloc_consistent);
		MASSERT(pcb->moal_mfree_consistent);
		MASSERT(pcb->moal_map_memory);
		MASSERT(pcb->moal_unmap_memory);
		PRINTM(MMSG,
		       "Attach mlan adapter operations.card_type is 0x%x.\n",
		       pmdevice->card_type);
		memcpy_ext(pmadapter, &pmadapter->ops, &mlan_pcie_ops,
			   sizeof(mlan_adapter_operations),
			   sizeof(mlan_adapter_operations));
		pmadapter->init_para.ring_size = pmdevice->ring_size;
		ret = wlan_get_pcie_device(pmadapter);
		if (MLAN_STATUS_SUCCESS != ret) {
			ret = MLAN_STATUS_FAILURE;
			goto error;
		}
	}
#endif

#ifdef USB
	if (IS_USB(pmadapter->card_type)) {
		MASSERT(pcb->moal_write_data_async);
		MASSERT(pcb->moal_recv_complete);
		PRINTM(MMSG,
		       "Attach mlan adapter operations.card_type is 0x%x.\n",
		       pmdevice->card_type);
		memcpy_ext(pmadapter, &pmadapter->ops, &mlan_usb_ops,
			   sizeof(mlan_adapter_operations),
			   sizeof(mlan_adapter_operations));
		ret = wlan_get_usb_device(pmadapter);
		if (MLAN_STATUS_SUCCESS != ret) {
			ret = MLAN_STATUS_FAILURE;
			goto error;
		}
	}
#endif

#ifdef DEBUG_LEVEL1
	mlan_drvdbg = pmdevice->drvdbg;
#endif

#ifdef MFG_CMD_SUPPORT
	pmadapter->init_para.mfg_mode = pmdevice->mfg_mode;
#endif
	pmadapter->init_para.auto_ds = pmdevice->auto_ds;
	pmadapter->init_para.ext_scan = pmdevice->ext_scan;
	pmadapter->init_para.ps_mode = pmdevice->ps_mode;
	if (pmdevice->max_tx_buf == MLAN_TX_DATA_BUF_SIZE_2K ||
	    pmdevice->max_tx_buf == MLAN_TX_DATA_BUF_SIZE_4K ||
	    pmdevice->max_tx_buf == MLAN_TX_DATA_BUF_SIZE_12K ||
	    pmdevice->max_tx_buf == MLAN_TX_DATA_BUF_SIZE_8K)
		pmadapter->init_para.max_tx_buf = pmdevice->max_tx_buf;
#ifdef STA_SUPPORT
	pmadapter->init_para.cfg_11d = pmdevice->cfg_11d;
#else
	pmadapter->init_para.cfg_11d = 0;
#endif
	if (IS_DFS_SUPPORT(pmadapter->feature_control))
		pmadapter->init_para.dfs_master_radar_det_en =
			DFS_MASTER_RADAR_DETECT_EN;
	pmadapter->init_para.dfs_slave_radar_det_en = DFS_SLAVE_RADAR_DETECT_EN;
	pmadapter->init_para.dev_cap_mask = pmdevice->dev_cap_mask;
	pmadapter->init_para.indrstcfg = pmdevice->indrstcfg;
	pmadapter->rx_work_flag = pmdevice->rx_work;
	pmadapter->init_para.passive_to_active_scan =
		pmdevice->passive_to_active_scan;
	pmadapter->fixed_beacon_buffer = pmdevice->fixed_beacon_buffer;

	pmadapter->multiple_dtim = pmdevice->multi_dtim;
	pmadapter->inact_tmo = pmdevice->inact_tmo;
	pmadapter->init_para.drcs_chantime_mode = pmdevice->drcs_chantime_mode;
	pmadapter->second_mac = pmdevice->second_mac;
	pmadapter->hs_wake_interval = pmdevice->hs_wake_interval;
	if (pmdevice->indication_gpio != 0xff) {
		pmadapter->ind_gpio = pmdevice->indication_gpio & 0x0f;
		pmadapter->level = (pmdevice->indication_gpio & 0xf0) >> 4;
		if (pmadapter->level != 0 && pmadapter->level != 1) {
			PRINTM(MERROR,
			       "Indication GPIO level is wrong and will use default value 0.\n");
			pmadapter->level = 0;
		}
	}
	pmadapter->hs_mimo_switch = pmdevice->hs_mimo_switch;
#ifdef USB
	if (IS_USB(pmadapter->card_type)) {
		pmadapter->tx_cmd_ep = pmdevice->tx_cmd_ep;
		pmadapter->rx_cmd_ep = pmdevice->rx_cmd_ep;
		pmadapter->tx_data_ep = pmdevice->tx_data_ep;
		pmadapter->rx_data_ep = pmdevice->rx_data_ep;
		pmadapter->usb_tx_ports[0] = pmdevice->tx_data_ep;
		pmadapter->usb_tx_ports[1] = pmdevice->tx_data2_ep;
	}
#endif
	pmadapter->init_para.dfs53cfg = pmdevice->dfs53cfg;
	pmadapter->init_para.dfs_offload = pmdevice->dfs_offload;
	pmadapter->priv_num = 0;
	pmadapter->priv[0] = MNULL;

	if (pcb->moal_vmalloc && pcb->moal_vfree)
		ret = pcb->moal_vmalloc(pmadapter->pmoal_handle,
					sizeof(mlan_private),
					(t_u8 **)&pmadapter->priv[0]);
	else
		ret = pcb->moal_malloc(pmadapter->pmoal_handle,
				       sizeof(mlan_private), MLAN_MEM_DEF,
				       (t_u8 **)&pmadapter->priv[0]);
	if (ret != MLAN_STATUS_SUCCESS || !pmadapter->priv[0]) {
		ret = MLAN_STATUS_FAILURE;
		goto error;
	}

	pmadapter->priv_num++;
	memset(pmadapter, pmadapter->priv[0], 0, sizeof(mlan_private));

	pmadapter->priv[0]->adapter = pmadapter;
	if (pmdevice->drv_mode & DRV_MODE_MASK) {
		/* Save bss_type, frame_type & bss_priority */
		pmadapter->priv[0]->bss_type = 0xff;
		pmadapter->priv[0]->frame_type = MLAN_DATA_FRAME_TYPE_ETH_II;
		pmadapter->priv[0]->bss_priority = 0;
		pmadapter->priv[0]->bss_role = MLAN_BSS_ROLE_STA;

		/* Save bss_index and bss_num */
		pmadapter->priv[0]->bss_index = 0;
		pmadapter->priv[0]->bss_num = 0xff;
	} else {
		pmadapter->priv[0]->bss_type =
			(t_u8)pmdevice->bss_attr[0].bss_type;
		pmadapter->priv[0]->frame_type =
			(t_u8)pmdevice->bss_attr[0].frame_type;
		pmadapter->priv[0]->bss_priority =
			(t_u8)pmdevice->bss_attr[0].bss_priority;
		if (pmdevice->bss_attr[0].bss_type == MLAN_BSS_TYPE_STA)
			pmadapter->priv[0]->bss_role = MLAN_BSS_ROLE_STA;
		else if (pmdevice->bss_attr[0].bss_type == MLAN_BSS_TYPE_UAP)
			pmadapter->priv[0]->bss_role = MLAN_BSS_ROLE_UAP;
#ifdef WIFI_DIRECT_SUPPORT
		else if (pmdevice->bss_attr[0].bss_type ==
			 MLAN_BSS_TYPE_WIFIDIRECT) {
			pmadapter->priv[0]->bss_role = MLAN_BSS_ROLE_STA;
			if (pmdevice->bss_attr[0].bss_virtual)
				pmadapter->priv[0]->bss_virtual = MTRUE;
		}
#endif
		/* Save bss_index and bss_num */
		pmadapter->priv[0]->bss_index = 0;
		pmadapter->priv[0]->bss_num =
			(t_u8)pmdevice->bss_attr[0].bss_num;
	}

	/* init function table */
	for (j = 0; mlan_ops[j]; j++) {
		if (mlan_ops[j]->bss_role == GET_BSS_ROLE(pmadapter->priv[0])) {
			memcpy_ext(pmadapter, &pmadapter->priv[0]->ops,
				   mlan_ops[j], sizeof(mlan_operations),
				   sizeof(mlan_operations));
			break;
		}
	}
	/** back up bss_attr table */
	memcpy_ext(pmadapter, pmadapter->bss_attr, pmdevice->bss_attr,
		   sizeof(pmadapter->bss_attr), sizeof(pmadapter->bss_attr));

	/* Initialize lock variables */
	if (wlan_init_lock_list(pmadapter) != MLAN_STATUS_SUCCESS) {
		ret = MLAN_STATUS_FAILURE;
		goto error;
	}

	/** init lock varible for first priv */
	if (wlan_init_priv_lock_list(pmadapter, 0) != MLAN_STATUS_SUCCESS) {
		ret = MLAN_STATUS_FAILURE;
		goto error;
	}

	/* Allocate memory for member of adapter structure */
	if (wlan_allocate_adapter(pmadapter)) {
		ret = MLAN_STATUS_FAILURE;
		goto error;
	}

	/* Initialize timers */
	if (wlan_init_timer(pmadapter) != MLAN_STATUS_SUCCESS) {
		ret = MLAN_STATUS_FAILURE;
		goto error;
	}
	/* Return pointer of mlan_adapter to MOAL */
	*ppmlan_adapter = pmadapter;

	goto exit_register;

error:
	PRINTM(MINFO, "Leave mlan_register with error\n");
	/* Free adapter structure */
	wlan_free_adapter(pmadapter);

	for (i = 0; i < MLAN_MAX_BSS_NUM; i++) {
		if (pmadapter->priv[i]) {
			if (pcb->moal_vmalloc && pcb->moal_vfree)
				pcb->moal_vfree(pmadapter->pmoal_handle,
						(t_u8 *)pmadapter->priv[i]);
			else if (pcb->moal_mfree)
				pcb->moal_mfree(pmadapter->pmoal_handle,
						(t_u8 *)pmadapter->priv[i]);
		}
	}
	if (pcb->moal_vmalloc && pcb->moal_vfree)
		pcb->moal_vfree(pmadapter->pmoal_handle, (t_u8 *)pmadapter);
	else if (pcb->moal_mfree)
		pcb->moal_mfree(pmadapter->pmoal_handle, (t_u8 *)pmadapter);

exit_register:
	LEAVE();
	return ret;
}

/**
 *  @brief This function unregisters MOAL from MLAN module.
 *
 *  @param padapter  A pointer to a mlan_device structure
 *                         allocated in MOAL
 *
 *  @return                MLAN_STATUS_SUCCESS
 *                             The deregistration succeeded.
 */
mlan_status mlan_unregister(t_void *padapter)
{
	mlan_status ret = MLAN_STATUS_SUCCESS;
	mlan_adapter *pmadapter = (mlan_adapter *)padapter;
	pmlan_callbacks pcb;
	t_s32 i = 0;

	MASSERT(padapter);

	ENTER();

	pcb = &pmadapter->callbacks;

	/* Free adapter structure */
	wlan_free_adapter(pmadapter);

	/* Free private structures */
	for (i = 0; i < pmadapter->priv_num; i++) {
		if (pmadapter->priv[i]) {
			if (pcb->moal_vmalloc && pcb->moal_vfree)
				pcb->moal_vfree(pmadapter->pmoal_handle,
						(t_u8 *)pmadapter->priv[i]);
			else if (pcb->moal_mfree)
				pcb->moal_mfree(pmadapter->pmoal_handle,
						(t_u8 *)pmadapter->priv[i]);
		}
	}

	/* Free mlan_adapter */
	if (pcb->moal_vmalloc && pcb->moal_vfree)
		pcb->moal_vfree(pmadapter->pmoal_handle, (t_u8 *)pmadapter);
	else if (pcb->moal_mfree)
		pcb->moal_mfree(pmadapter->pmoal_handle, (t_u8 *)pmadapter);

	LEAVE();
	return ret;
}

/**
 *  @brief This function downloads the firmware
 *
 *  @param padapter   A pointer to a t_void pointer to store
 *                         mlan_adapter structure pointer
 *  @param pmfw            A pointer to firmware image
 *
 *  @return                MLAN_STATUS_SUCCESS
 *                             The firmware download succeeded.
 *                         MLAN_STATUS_FAILURE
 *                             The firmware download failed.
 */
mlan_status mlan_dnld_fw(t_void *padapter, pmlan_fw_image pmfw)
{
	mlan_status ret = MLAN_STATUS_FAILURE;
	mlan_adapter *pmadapter = (mlan_adapter *)padapter;

	ENTER();
	MASSERT(padapter);

	/* Download helper/firmware */
	if (pmfw) {
		ret = pmadapter->ops.dnld_fw(pmadapter, pmfw);
		if (ret != MLAN_STATUS_SUCCESS) {
			PRINTM(MERROR, "wlan_dnld_fw fail ret=0x%x\n", ret);
			LEAVE();
			return ret;
		}
	}

	LEAVE();
	return ret;
}

/**
 *  @brief This function mask host interrupt from firmware
 *
 *  @param padapter   A pointer to a t_void pointer to store
 *                         mlan_adapter structure pointer
 *
 *  @return                MLAN_STATUS_SUCCESS
 *                             The firmware download succeeded.
 *                         MLAN_STATUS_FAILURE
 *                             The firmware download failed.
 */
mlan_status mlan_disable_host_int(t_void *padapter)
{
	mlan_status ret = MLAN_STATUS_FAILURE;
	mlan_adapter *pmadapter = (mlan_adapter *)padapter;

	ENTER();
	MASSERT(padapter);

	/* mask host interrupt from firmware */
	if (pmadapter->ops.disable_host_int) {
		ret = pmadapter->ops.disable_host_int(pmadapter);
		if (ret != MLAN_STATUS_SUCCESS) {
			PRINTM(MERROR,
			       "mlan_disable_host_int fail ret = 0x%x\n", ret);
			LEAVE();
			return ret;
		}
	}

	LEAVE();
	return ret;
}

/**
 *  @brief This function unmask host interrupt from firmware
 *
 *  @param padapter   A pointer to a t_void pointer to store
 *                         mlan_adapter structure pointer
 *
 *  @return                MLAN_STATUS_SUCCESS
 *                             The firmware download succeeded.
 *                         MLAN_STATUS_FAILURE
 *                             The firmware download failed.
 */
mlan_status mlan_enable_host_int(t_void *padapter)
{
	mlan_status ret = MLAN_STATUS_FAILURE;
	mlan_adapter *pmadapter = (mlan_adapter *)padapter;

	ENTER();
	MASSERT(padapter);

	/* unmask host interrupt from firmware */
	if (pmadapter->ops.enable_host_int) {
		ret = pmadapter->ops.enable_host_int(pmadapter);
		if (ret != MLAN_STATUS_SUCCESS) {
			PRINTM(MERROR, "mlan_enable_host_int fail ret = 0x%x\n",
			       ret);
			LEAVE();
			return ret;
		}
	}

	LEAVE();
	return ret;
}

/**
 *  @brief This function pass init param to MLAN
 *
 *  @param padapter  A pointer to a t_void pointer to store
 *                        mlan_adapter structure pointer
 *  @param pparam         A pointer to mlan_init_param structure
 *
 *  @return               MLAN_STATUS_SUCCESS
 *
 */
mlan_status mlan_set_init_param(t_void *padapter, pmlan_init_param pparam)
{
	mlan_status ret = MLAN_STATUS_SUCCESS;
	mlan_adapter *pmadapter = (mlan_adapter *)padapter;

	ENTER();
	MASSERT(padapter);

	/** Save DPD data in MLAN */
	if ((pparam->pdpd_data_buf) || (pparam->dpd_data_len > 0)) {
		pmadapter->pdpd_data = pparam->pdpd_data_buf;
		pmadapter->dpd_data_len = pparam->dpd_data_len;
	}
	if (pparam->ptxpwr_data_buf && (pparam->txpwr_data_len > 0)) {
		pmadapter->ptxpwr_data = pparam->ptxpwr_data_buf;
		pmadapter->txpwr_data_len = pparam->txpwr_data_len;
	}
	/** Save cal data in MLAN */
	if ((pparam->pcal_data_buf) && (pparam->cal_data_len > 0)) {
		pmadapter->pcal_data = pparam->pcal_data_buf;
		pmadapter->cal_data_len = pparam->cal_data_len;
	}

	LEAVE();
	return ret;
}

/**
 *  @brief This function initializes the firmware
 *
 *  @param padapter   A pointer to a t_void pointer to store
 *                         mlan_adapter structure pointer
 *
 *  @return                MLAN_STATUS_SUCCESS
 *                             The firmware initialization succeeded.
 *                         MLAN_STATUS_PENDING
 *                             The firmware initialization is pending.
 *                         MLAN_STATUS_FAILURE
 *                             The firmware initialization failed.
 */
mlan_status mlan_init_fw(t_void *padapter)
{
	mlan_status ret = MLAN_STATUS_SUCCESS;
	mlan_adapter *pmadapter = (mlan_adapter *)padapter;

	ENTER();
	MASSERT(padapter);

	pmadapter->hw_status = WlanHardwareStatusGetHwSpec;

	/* Initialize firmware, may return PENDING */
	ret = wlan_init_fw(pmadapter);
	PRINTM(MINFO, "wlan_init_fw returned ret=0x%x\n", ret);

	LEAVE();
	return ret;
}

/**
 *  @brief Shutdown firmware
 *
 *  @param padapter    A pointer to mlan_adapter structure
 *
 *  @return     MLAN_STATUS_SUCCESS
 *                              The firmware shutdown call succeeded.
 *              MLAN_STATUS_PENDING
 *                              The firmware shutdown call is pending.
 *              MLAN_STATUS_FAILURE
 *                              The firmware shutdown call failed.
 */
mlan_status mlan_shutdown_fw(t_void *padapter)
{
	mlan_status ret = MLAN_STATUS_PENDING;
	mlan_adapter *pmadapter = (mlan_adapter *)padapter;
	pmlan_buffer pmbuf;
	pmlan_ioctl_req pioctl_buf;
	pmlan_callbacks pcb;
	t_s32 i = 0;

	ENTER();

	MASSERT(padapter);
	/* MLAN already shutdown */
	if (pmadapter->hw_status == WlanHardwareStatusNotReady) {
		LEAVE();
		return MLAN_STATUS_SUCCESS;
	}

	pmadapter->hw_status = WlanHardwareStatusClosing;
	/* Wait for mlan_process to complete */
	if (pmadapter->mlan_processing) {
		PRINTM(MWARN, "MLAN main processing is still running\n");
		LEAVE();
		return ret;
	}

	/* Shut down MLAN */
	PRINTM(MINFO, "Shutdown MLAN...\n");

	/* Cancel all pending commands and complete ioctls */
	wlan_cancel_all_pending_cmd(pmadapter, MTRUE);

	/* Clean up priv structures */
	for (i = 0; i < pmadapter->priv_num; i++) {
		if (pmadapter->priv[i])
			wlan_free_priv(pmadapter->priv[i]);
	}

	pcb = &pmadapter->callbacks;
	/** cancel pending ioctl */
	while ((pioctl_buf = (pmlan_ioctl_req)util_dequeue_list(
			pmadapter->pmoal_handle, &pmadapter->ioctl_pending_q,
			pcb->moal_spin_lock, pcb->moal_spin_unlock))) {
		pioctl_buf->status_code = MLAN_ERROR_CMD_CANCEL;
		pcb->moal_ioctl_complete(pmadapter->pmoal_handle, pioctl_buf,
					 MLAN_STATUS_FAILURE);
	}

	while ((pmbuf = (pmlan_buffer)util_dequeue_list(
			pmadapter->pmoal_handle, &pmadapter->rx_data_queue,
			pcb->moal_spin_lock, pcb->moal_spin_unlock))) {
#ifdef USB
		if (IS_USB(pmadapter->card_type))
			pcb->moal_recv_complete(pmadapter->pmoal_handle, pmbuf,
						pmadapter->rx_data_ep,
						MLAN_STATUS_FAILURE);
#endif
#if defined(SDIO) || defined(PCIE)
		if (!IS_USB(pmadapter->card_type))
			wlan_free_mlan_buffer(pmadapter, pmbuf);
#endif
	}
	pmadapter->rx_pkts_queued = 0;
#ifdef PCIE
	if (IS_PCIE(pmadapter->card_type) &&
	    wlan_set_drv_ready_reg(pmadapter, 0)) {
		PRINTM(MERROR, "Failed to write driver not-ready signature\n");
	}
#endif

	/* Notify completion */
	ret = wlan_shutdown_fw_complete(pmadapter);

	LEAVE();
	return ret;
}

/**
 *  @brief queue main work
 *
 *  @param pmadapter	A pointer to mlan_adapter structure
 *
 *  @return			N/A
 */
static t_void mlan_queue_main_work(mlan_adapter *pmadapter)
{
	pmlan_callbacks pcb = &pmadapter->callbacks;
	ENTER();
	pcb->moal_spin_lock(pmadapter->pmoal_handle,
			    pmadapter->pmain_proc_lock);

	/* Check if already processing */
	if (pmadapter->mlan_processing) {
		pmadapter->more_task_flag = MTRUE;
		pcb->moal_spin_unlock(pmadapter->pmoal_handle,
				      pmadapter->pmain_proc_lock);
	} else {
		pcb->moal_spin_unlock(pmadapter->pmoal_handle,
				      pmadapter->pmain_proc_lock);
		wlan_recv_event(wlan_get_priv(pmadapter, MLAN_BSS_ROLE_ANY),
				MLAN_EVENT_ID_DRV_DEFER_HANDLING, MNULL);
	}
	LEAVE();
	return;
}

/**
 *  @brief queue rx_work
 *
 *  @param pmadapter	A pointer to mlan_adapter structure
 *
 *  @return			N/A
 */
static t_void mlan_queue_rx_work(mlan_adapter *pmadapter)
{
	pmlan_callbacks pcb = &pmadapter->callbacks;
	ENTER();

	pcb->moal_spin_lock(pmadapter->pmoal_handle, pmadapter->prx_proc_lock);

	/* Check if already processing */
	if (pmadapter->mlan_rx_processing) {
		pmadapter->more_rx_task_flag = MTRUE;
		pcb->moal_spin_unlock(pmadapter->pmoal_handle,
				      pmadapter->prx_proc_lock);
	} else {
		pcb->moal_spin_unlock(pmadapter->pmoal_handle,
				      pmadapter->prx_proc_lock);
		wlan_recv_event(wlan_get_priv(pmadapter, MLAN_BSS_ROLE_ANY),
				MLAN_EVENT_ID_DRV_DEFER_RX_WORK, MNULL);
	}
	LEAVE();
	return;
}

/**
 *  @brief block main process
 *
 *  @param pmadapter	A pointer to mlan_adapter structure
 *  @param block            MTRUE/MFALSE
 *
 *  @return			N/A
 */
void mlan_block_main_process(mlan_adapter *pmadapter, t_u8 block)
{
	pmlan_callbacks pcb = &pmadapter->callbacks;
	pcb->moal_spin_lock(pmadapter->pmoal_handle,
			    pmadapter->pmain_proc_lock);
	if (!block) {
		pmadapter->main_lock_flag = MFALSE;
		pcb->moal_spin_unlock(pmadapter->pmoal_handle,
				      pmadapter->pmain_proc_lock);
	} else {
		pmadapter->main_lock_flag = MTRUE;
		if (pmadapter->mlan_processing) {
			pcb->moal_spin_unlock(pmadapter->pmoal_handle,
					      pmadapter->pmain_proc_lock);
			PRINTM(MEVENT, "wlan: wait main work done...\n");
			wlan_recv_event(
				wlan_get_priv(pmadapter, MLAN_BSS_ROLE_ANY),
				MLAN_EVENT_ID_DRV_FLUSH_MAIN_WORK, MNULL);
		} else {
			pcb->moal_spin_unlock(pmadapter->pmoal_handle,
					      pmadapter->pmain_proc_lock);
		}
	}
}

/**
 *  @brief block rx process
 *
 *  @param pmadapter	A pointer to mlan_adapter structure
 *  @param block            MTRUE/MFALSE;
 *
 *  @return			N/A
 */
void mlan_block_rx_process(mlan_adapter *pmadapter, t_u8 block)
{
	pmlan_callbacks pcb = &pmadapter->callbacks;
	pcb->moal_spin_lock(pmadapter->pmoal_handle, pmadapter->prx_proc_lock);
	if (!block) {
		pmadapter->rx_lock_flag = MFALSE;
		pcb->moal_spin_unlock(pmadapter->pmoal_handle,
				      pmadapter->prx_proc_lock);
	} else {
		pmadapter->rx_lock_flag = MTRUE;
		if (pmadapter->mlan_rx_processing) {
			pcb->moal_spin_unlock(pmadapter->pmoal_handle,
					      pmadapter->prx_proc_lock);
			PRINTM(MEVENT, "wlan: wait rx work done...\n");
			wlan_recv_event(wlan_get_priv(pmadapter,
						      MLAN_BSS_ROLE_ANY),
					MLAN_EVENT_ID_DRV_FLUSH_RX_WORK, MNULL);
		} else {
			pcb->moal_spin_unlock(pmadapter->pmoal_handle,
					      pmadapter->prx_proc_lock);
		}
	}
}

/**
 *  @brief The receive process
 *
 *  @param padapter	A pointer to mlan_adapter structure
 *  @param rx_pkts              A pointer to save receive pkts number
 *
 *  @return			MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
 */
mlan_status mlan_rx_process(t_void *padapter, t_u8 *rx_pkts)
{
	mlan_status ret = MLAN_STATUS_SUCCESS;
	mlan_adapter *pmadapter = (mlan_adapter *)padapter;
	pmlan_callbacks pcb;
	pmlan_buffer pmbuf;
	t_u8 limit = 0;
	t_u8 rx_num = 0;
	t_u32 in_ts_sec, in_ts_usec;

	ENTER();

	MASSERT(padapter);
	pcb = &pmadapter->callbacks;
	pcb->moal_spin_lock(pmadapter->pmoal_handle, pmadapter->prx_proc_lock);
	if (pmadapter->mlan_rx_processing || pmadapter->rx_lock_flag) {
		pmadapter->more_rx_task_flag = MTRUE;
		pcb->moal_spin_unlock(pmadapter->pmoal_handle,
				      pmadapter->prx_proc_lock);
		goto exit_rx_proc;
	} else {
		pmadapter->mlan_rx_processing = MTRUE;
		pcb->moal_spin_unlock(pmadapter->pmoal_handle,
				      pmadapter->prx_proc_lock);
	}
	if (rx_pkts)
		limit = *rx_pkts;

rx_process_start:
	/* Check for Rx data */
	while (MTRUE) {
#ifdef DRV_EMBEDDED_AUTHENTICATOR
		if (pmadapter->authenticator_priv) {
			if (IsAuthenticatorEnabled(
				    pmadapter->authenticator_priv->psapriv)) {
				AuthenticatorKeyMgmtInit(
					pmadapter->authenticator_priv->psapriv,
					pmadapter->authenticator_priv
						->curr_addr);
				pmadapter->authenticator_priv = MNULL;
			}
		}
#endif
		if (pmadapter->flush_data) {
			pmadapter->flush_data = MFALSE;
			wlan_flush_rxreorder_tbl(pmadapter);
		}
		pmadapter->callbacks.moal_spin_lock(
			pmadapter->pmoal_handle,
			pmadapter->rx_data_queue.plock);
		pmbuf = (pmlan_buffer)util_dequeue_list(
			pmadapter->pmoal_handle, &pmadapter->rx_data_queue,
			MNULL, MNULL);
		if (!pmbuf) {
			pmadapter->callbacks.moal_spin_unlock(
				pmadapter->pmoal_handle,
				pmadapter->rx_data_queue.plock);
			break;
		}
		pmadapter->rx_pkts_queued--;
		rx_num++;
		pmadapter->callbacks.moal_spin_unlock(
			pmadapter->pmoal_handle,
			pmadapter->rx_data_queue.plock);

		// rx_trace 6
		if (pmadapter->tp_state_on) {
			pmadapter->callbacks.moal_tp_accounting(
				pmadapter->pmoal_handle, pmbuf,
				6 /*RX_DROP_P2*/);
			pcb->moal_get_system_time(pmadapter->pmoal_handle,
						  &in_ts_sec, &in_ts_usec);
			pmbuf->extra_ts_sec = in_ts_sec;
			pmbuf->extra_ts_usec = in_ts_usec;
		}
		if (pmadapter->tp_state_drop_point == 6 /*RX_DROP_P2*/) {
			pmadapter->ops.data_complete(pmadapter, pmbuf, ret);
			goto rx_process_start;
		}

		if (pmadapter->delay_task_flag &&
		    (pmadapter->rx_pkts_queued < LOW_RX_PENDING)) {
			PRINTM(MEVENT, "Run\n");
			pmadapter->delay_task_flag = MFALSE;
			mlan_queue_main_work(pmadapter);
		}
		pmadapter->ops.handle_rx_packet(pmadapter, pmbuf);
		if (limit && rx_num >= limit)
			break;
	}
	if (rx_pkts)
		*rx_pkts = rx_num;
	pcb->moal_spin_lock(pmadapter->pmoal_handle, pmadapter->prx_proc_lock);
	if (pmadapter->more_rx_task_flag) {
		pmadapter->more_rx_task_flag = MFALSE;
		pcb->moal_spin_unlock(pmadapter->pmoal_handle,
				      pmadapter->prx_proc_lock);
		goto rx_process_start;
	}
	pmadapter->mlan_rx_processing = MFALSE;
	pcb->moal_spin_unlock(pmadapter->pmoal_handle,
			      pmadapter->prx_proc_lock);
exit_rx_proc:
	LEAVE();
	return ret;
}

/**
 *  @brief The main process
 *
 *  @param padapter	A pointer to mlan_adapter structure
 *
 *  @return			MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
 */
mlan_status mlan_main_process(t_void *padapter)
{
	mlan_status ret = MLAN_STATUS_SUCCESS;
	mlan_adapter *pmadapter = (mlan_adapter *)padapter;
	pmlan_callbacks pcb;

	ENTER();

	MASSERT(padapter);

	pcb = &pmadapter->callbacks;

	pcb->moal_spin_lock(pmadapter->pmoal_handle,
			    pmadapter->pmain_proc_lock);

	/* Check if already processing */
	if (pmadapter->mlan_processing || pmadapter->main_lock_flag) {
		pmadapter->more_task_flag = MTRUE;
		pcb->moal_spin_unlock(pmadapter->pmoal_handle,
				      pmadapter->pmain_proc_lock);
		goto exit_main_proc;
	} else {
		pmadapter->mlan_processing = MTRUE;
		pmadapter->main_process_cnt++;
		pcb->moal_spin_unlock(pmadapter->pmoal_handle,
				      pmadapter->pmain_proc_lock);
	}
process_start:
	do {
		/* Is MLAN shutting down or not ready? */
		if ((pmadapter->hw_status == WlanHardwareStatusClosing) ||
		    (pmadapter->hw_status == WlanHardwareStatusNotReady))
			break;
		if (pmadapter->pending_ioctl) {
			wlan_process_pending_ioctl(pmadapter);
			pmadapter->pending_ioctl = MFALSE;
		}
		if (pmadapter->pending_disconnect_priv) {
			PRINTM(MEVENT, "Reset connect state\n");
			wlan_reset_connect_state(
				pmadapter->pending_disconnect_priv, MTRUE);
			pmadapter->pending_disconnect_priv = MNULL;
		}
#if defined(SDIO) || defined(PCIE)
		if (!IS_USB(pmadapter->card_type)) {
			if (pmadapter->rx_pkts_queued > HIGH_RX_PENDING) {
				pcb->moal_tp_accounting_rx_param(
					pmadapter->pmoal_handle, 2, 0);
				PRINTM(MEVENT, "Pause\n");
				pmadapter->delay_task_flag = MTRUE;
				mlan_queue_rx_work(pmadapter);
				break;
			}
			/* Handle pending interrupts if any */
			if (pmadapter->ireg) {
				if (pmadapter->hs_activated == MTRUE)
					wlan_process_hs_config(pmadapter);
				pmadapter->ops.process_int_status(pmadapter);
				if (pmadapter->data_received)
					mlan_queue_rx_work(pmadapter);
			}
		}
#endif

		/* Need to wake up the card ? */
		if ((pmadapter->ps_state == PS_STATE_SLEEP) &&
		    (pmadapter->pm_wakeup_card_req &&
		     !pmadapter->pm_wakeup_fw_try) &&
		    (wlan_is_cmd_pending(pmadapter) ||
		     !wlan_bypass_tx_list_empty(pmadapter) ||
		     !wlan_wmm_lists_empty(pmadapter))) {
			pmadapter->ops.wakeup_card(pmadapter, MTRUE);
			pmadapter->pm_wakeup_fw_try = MTRUE;
			continue;
		}
		if (IS_CARD_RX_RCVD(pmadapter) ||
		    (!pmadapter->cmd_sent &&
		     pmadapter->vdll_ctrl.pending_block)) {
			pmadapter->data_received = MFALSE;
			if (pmadapter->hs_activated == MTRUE) {
				pmadapter->is_hs_configured = MFALSE;
				wlan_host_sleep_activated_event(
					wlan_get_priv(pmadapter,
						      MLAN_BSS_ROLE_ANY),
					MFALSE);
			}
			pmadapter->pm_wakeup_fw_try = MFALSE;
			if (pmadapter->ps_state == PS_STATE_SLEEP)
				pmadapter->ps_state = PS_STATE_AWAKE;
			if (pmadapter->wakeup_fw_timer_is_set) {
				pcb->moal_stop_timer(
					pmadapter->pmoal_handle,
					pmadapter->pwakeup_fw_timer);
				pmadapter->wakeup_fw_timer_is_set = MFALSE;
			}
		} else {
			/* We have tried to wakeup the card already */
			if (pmadapter->pm_wakeup_fw_try)
				break;
			/* Check if we need to confirm Sleep Request received
			 * previously */
			if (pmadapter->ps_state == PS_STATE_PRE_SLEEP)
				if (!pmadapter->cmd_sent &&
				    !pmadapter->curr_cmd &&
				    !pmadapter->vdll_ctrl.pending_block)
					wlan_check_ps_cond(pmadapter);
			if (pmadapter->ps_state != PS_STATE_AWAKE ||
			    (pmadapter->tx_lock_flag == MTRUE))
				break;

			if (pmadapter->data_sent ||
			    wlan_is_tdls_link_chan_switching(
				    pmadapter->tdls_status) ||
			    (wlan_bypass_tx_list_empty(pmadapter) &&
			     wlan_wmm_lists_empty(pmadapter)) ||
			    wlan_11h_radar_detected_tx_blocked(pmadapter)) {
				if (pmadapter->cmd_sent ||
				    pmadapter->curr_cmd ||
				    !wlan_is_send_cmd_allowed(
					    pmadapter->tdls_status) ||
				    !wlan_is_cmd_pending(pmadapter)) {
					break;
				}
			}
		}

		/* Check for Cmd Resp */
		wlan_request_cmd_lock(pmadapter);
		if (pmadapter->cmd_resp_received) {
			pmadapter->cmd_resp_received = MFALSE;
			wlan_release_cmd_lock(pmadapter);

			wlan_process_cmdresp(pmadapter);

			/* call moal back when init_fw is done */
			if (pmadapter->hw_status ==
			    WlanHardwareStatusInitdone) {
				pmadapter->hw_status = WlanHardwareStatusReady;
				wlan_init_fw_complete(pmadapter);
			} else if (pmadapter->hw_status ==
				   WlanHardwareStatusGetHwSpecdone) {
				pmadapter->hw_status =
					WlanHardwareStatusInitializing;
				wlan_get_hw_spec_complete(pmadapter);
			}
		} else {
			wlan_release_cmd_lock(pmadapter);
		}

		/* Check for event */
		if (pmadapter->event_received) {
			pmadapter->event_received = MFALSE;
			wlan_process_event(pmadapter);
		}

		/* Check if we need to confirm Sleep Request received previously
		 */
		if (pmadapter->ps_state == PS_STATE_PRE_SLEEP)
			if (!pmadapter->cmd_sent && !pmadapter->curr_cmd &&
			    !pmadapter->vdll_ctrl.pending_block)
				wlan_check_ps_cond(pmadapter);

		/*
		 * The ps_state may have been changed during processing of
		 * Sleep Request event.
		 */
		if ((pmadapter->ps_state == PS_STATE_SLEEP) ||
		    (pmadapter->ps_state == PS_STATE_PRE_SLEEP) ||
		    (pmadapter->ps_state == PS_STATE_SLEEP_CFM) ||
		    (pmadapter->tx_lock_flag == MTRUE)) {
			continue;
		}

		/* in a case of race condition, download the VDLL block here */
		if (!pmadapter->cmd_sent &&
		    pmadapter->vdll_ctrl.pending_block) {
			wlan_download_vdll_block(
				pmadapter, pmadapter->vdll_ctrl.pending_block,
				pmadapter->vdll_ctrl.pending_block_len);
			pmadapter->vdll_ctrl.pending_block = MNULL;
		}
		if (!pmadapter->cmd_sent && !pmadapter->curr_cmd &&
		    wlan_is_send_cmd_allowed(pmadapter->tdls_status)) {
			if (wlan_exec_next_cmd(pmadapter) ==
			    MLAN_STATUS_FAILURE) {
				ret = MLAN_STATUS_FAILURE;
				break;
			}
		}

		if (!pmadapter->data_sent &&
		    !wlan_11h_radar_detected_tx_blocked(pmadapter) &&
		    !wlan_is_tdls_link_chan_switching(pmadapter->tdls_status) &&
		    !wlan_bypass_tx_list_empty(pmadapter)) {
			PRINTM(MINFO, "mlan_send_pkt(): deq(bybass_txq)\n");
			wlan_process_bypass_tx(pmadapter);
			if (pmadapter->hs_activated == MTRUE) {
				pmadapter->is_hs_configured = MFALSE;
				wlan_host_sleep_activated_event(
					wlan_get_priv(pmadapter,
						      MLAN_BSS_ROLE_ANY),
					MFALSE);
			}
		}

		if (!pmadapter->data_sent && !wlan_wmm_lists_empty(pmadapter) &&
		    !wlan_11h_radar_detected_tx_blocked(pmadapter) &&
		    !wlan_is_tdls_link_chan_switching(pmadapter->tdls_status)) {
			wlan_wmm_process_tx(pmadapter);
			if (pmadapter->hs_activated == MTRUE) {
				pmadapter->is_hs_configured = MFALSE;
				wlan_host_sleep_activated_event(
					wlan_get_priv(pmadapter,
						      MLAN_BSS_ROLE_ANY),
					MFALSE);
			}
		}

#ifdef STA_SUPPORT
		if (pmadapter->delay_null_pkt && !pmadapter->cmd_sent &&
		    !pmadapter->curr_cmd && !wlan_is_cmd_pending(pmadapter) &&
		    wlan_bypass_tx_list_empty(pmadapter) &&
		    wlan_wmm_lists_empty(pmadapter)) {
			if (wlan_send_null_packet(
				    wlan_get_priv(pmadapter, MLAN_BSS_ROLE_STA),
				    MRVDRV_TxPD_POWER_MGMT_NULL_PACKET |
					    MRVDRV_TxPD_POWER_MGMT_LAST_PACKET) ==
			    MLAN_STATUS_SUCCESS) {
				pmadapter->delay_null_pkt = MFALSE;
			}
			break;
		}
#endif

	} while (MTRUE);

	pcb->moal_spin_lock(pmadapter->pmoal_handle,
			    pmadapter->pmain_proc_lock);
	if (pmadapter->more_task_flag == MTRUE) {
		pmadapter->more_task_flag = MFALSE;
		pcb->moal_spin_unlock(pmadapter->pmoal_handle,
				      pmadapter->pmain_proc_lock);
		goto process_start;
	}
	pmadapter->mlan_processing = MFALSE;
	pcb->moal_spin_unlock(pmadapter->pmoal_handle,
			      pmadapter->pmain_proc_lock);

exit_main_proc:
	if (pmadapter->hw_status == WlanHardwareStatusClosing)
		if (MLAN_STATUS_SUCCESS != mlan_shutdown_fw(pmadapter))
			PRINTM(MERROR, "ERR:mlan_shutdown_fw failed\n");
	LEAVE();
	return ret;
}

/**
 *  @brief Function to send packet
 *
 *  @param padapter	A pointer to mlan_adapter structure
 *  @param pmbuf		A pointer to mlan_buffer structure
 *
 *  @return			MLAN_STATUS_PENDING
 */
mlan_status mlan_send_packet(t_void *padapter, pmlan_buffer pmbuf)
{
	mlan_status ret = MLAN_STATUS_PENDING;
	mlan_adapter *pmadapter = (mlan_adapter *)padapter;
	mlan_private *pmpriv;
	t_u16 eth_type = 0;
	t_u8 ra[MLAN_MAC_ADDR_LENGTH];
	tdlsStatus_e tdls_status;

	ENTER();
	MASSERT(padapter && pmbuf);

	if (!padapter || !pmbuf) {
		return MLAN_STATUS_FAILURE;
	}

	MASSERT(pmbuf->bss_index < pmadapter->priv_num);
	pmbuf->flags |= MLAN_BUF_FLAG_MOAL_TX_BUF;
	pmpriv = pmadapter->priv[pmbuf->bss_index];

	eth_type =
		mlan_ntohs(*(t_u16 *)&pmbuf->pbuf[pmbuf->data_offset +
						  MLAN_ETHER_PKT_TYPE_OFFSET]);
	if (((pmadapter->priv[pmbuf->bss_index]->port_ctrl_mode == MTRUE) &&
	     ((eth_type == MLAN_ETHER_PKT_TYPE_EAPOL) ||
	      (eth_type == MLAN_ETHER_PKT_TYPE_ARP) ||
	      (eth_type == MLAN_ETHER_PKT_TYPE_WAPI))) ||
	    (eth_type == MLAN_ETHER_PKT_TYPE_TDLS_ACTION) ||
	    (pmbuf->buf_type == MLAN_BUF_TYPE_RAW_DATA)

	) {
		if (eth_type == MLAN_ETHER_PKT_TYPE_TDLS_ACTION) {
			memcpy_ext(pmadapter, ra,
				   pmbuf->pbuf + pmbuf->data_offset,
				   MLAN_MAC_ADDR_LENGTH, MLAN_MAC_ADDR_LENGTH);
			tdls_status = wlan_get_tdls_link_status(pmpriv, ra);
			if (MTRUE == wlan_is_tdls_link_setup(tdls_status) ||
			    !pmpriv->media_connected)
				pmbuf->flags |= MLAN_BUF_FLAG_TDLS;
		}
		if (eth_type == MLAN_ETHER_PKT_TYPE_EAPOL) {
			PRINTM_NETINTF(MMSG, pmpriv);
			PRINTM(MMSG, "wlan: Send EAPOL pkt to " MACSTR "\n",
			       MAC2STR(pmbuf->pbuf + pmbuf->data_offset));
		}
		if (pmadapter->tp_state_on)
			pmadapter->callbacks.moal_tp_accounting(
				pmadapter->pmoal_handle, pmbuf->pdesc, 2);
		if (pmadapter->tp_state_drop_point == 2)
			return 0;
		else
			wlan_add_buf_bypass_txqueue(pmadapter, pmbuf);
	} else {
		if (pmadapter->tp_state_on)
			pmadapter->callbacks.moal_tp_accounting(
				pmadapter->pmoal_handle, pmbuf->pdesc, 2);
		if (pmadapter->tp_state_drop_point == 2)
			return 0;
		else
			/* Transmit the packet*/
			wlan_wmm_add_buf_txqueue(pmadapter, pmbuf);
	}

	LEAVE();
	return ret;
}

/**
 *  @brief MLAN ioctl handler
 *
 *  @param adapter	A pointer to mlan_adapter structure
 *  @param pioctl_req	A pointer to ioctl request buffer
 *
 *  @return		MLAN_STATUS_SUCCESS/MLAN_STATUS_PENDING --success,
 * otherwise fail
 */
mlan_status mlan_ioctl(t_void *adapter, pmlan_ioctl_req pioctl_req)
{
	mlan_status ret = MLAN_STATUS_SUCCESS;
	pmlan_adapter pmadapter = (pmlan_adapter)adapter;
	pmlan_private pmpriv = MNULL;

	ENTER();

	if (pioctl_req == MNULL) {
		PRINTM(MMSG, "Cancel all pending cmd!\n");
		wlan_cancel_all_pending_cmd(pmadapter, MFALSE);
		goto exit;
	}
	pmpriv = pmadapter->priv[pioctl_req->bss_index];
	ret = pmpriv->ops.ioctl(adapter, pioctl_req);
exit:
	LEAVE();
	return ret;
}

#ifdef USB
/**
 *  @brief Packet send completion callback
 *
 *  @param padapter	A pointer to mlan_adapter structure
 *  @param pmbuf		A pointer to mlan_buffer structure
 *  @param port			Data port
 *  @param status		Callback status
 *
 *  @return			MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
 */
mlan_status mlan_write_data_async_complete(t_void *padapter, pmlan_buffer pmbuf,
					   t_u32 port, mlan_status status)
{
	mlan_status ret = MLAN_STATUS_SUCCESS;
	mlan_adapter *pmadapter = (mlan_adapter *)padapter;

	ENTER();

	if (port == pmadapter->tx_cmd_ep) {
		pmadapter->cmd_sent = MFALSE;
		PRINTM(MCMND, "mlan_write_data_async_complete: CMD\n");
		/* pmbuf was allocated by MLAN */
		wlan_free_mlan_buffer(pmadapter, pmbuf);
	} else {
		pmadapter->data_sent = MFALSE;
		wlan_update_port_status(pmadapter, port, MFALSE);
		PRINTM(MDATA, "mlan_write_data_async_complete: DATA(%d)\n",
		       port);
		ret = wlan_write_data_complete(pmadapter, pmbuf, status);
	}

	LEAVE();
	return ret;
}

/**
 *  @brief Packet receive handler
 *
 *  @param padapter	A pointer to mlan_adapter structure
 *  @param pmbuf		A pointer to mlan_buffer structure
 *  @param port			Data port
 *
 *  @return			MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE or
 * MLAN_STATUS_PENDING
 */
mlan_status mlan_recv(t_void *padapter, pmlan_buffer pmbuf, t_u32 port)
{
	mlan_status ret = MLAN_STATUS_PENDING;
	mlan_adapter *pmadapter = (mlan_adapter *)padapter;
	t_u8 *pbuf;
	t_u32 len, recv_type;
	t_u32 event_cause = 0;
#ifdef DEBUG_LEVEL1
	t_u32 sec = 0, usec = 0;
#endif
	t_u32 max_rx_data_size = MLAN_RX_DATA_BUF_SIZE;

	ENTER();

	MASSERT(padapter && pmbuf);

	if (pmadapter->hs_activated == MTRUE)
		wlan_process_hs_config(pmadapter);
	pbuf = pmbuf->pbuf + pmbuf->data_offset;
	len = pmbuf->data_len;

	MASSERT(len >= MLAN_TYPE_LEN);
	recv_type = *(t_u32 *)pbuf;
	recv_type = wlan_le32_to_cpu(recv_type);
	pbuf += MLAN_TYPE_LEN;
	len -= MLAN_TYPE_LEN;

	if (port == pmadapter->rx_cmd_ep) {
		switch (recv_type) {
		case MLAN_USB_TYPE_CMD:
			PRINTM_GET_SYS_TIME(MCMND, &sec, &usec);
			PRINTM(MCMND, "mlan_recv: CMD (%lu.%06lu)\n", sec,
			       usec);
			if (len > MRVDRV_SIZE_OF_CMD_BUFFER) {
				pmbuf->status_code = MLAN_ERROR_CMD_RESP_FAIL;
				ret = MLAN_STATUS_FAILURE;
				PRINTM(MERROR, "mlan_recv: CMD too large\n");
			} else if (!pmadapter->curr_cmd) {
				if (pmadapter->ps_state == PS_STATE_SLEEP_CFM) {
					pmbuf->data_offset += MLAN_TYPE_LEN;
					pmbuf->data_len -= MLAN_TYPE_LEN;
					wlan_process_sleep_confirm_resp(
						pmadapter,
						pmbuf->pbuf +
							pmbuf->data_offset,
						pmbuf->data_len);
					pmbuf->flags |=
						MLAN_BUF_FLAG_SLEEPCFM_RESP;
					ret = MLAN_STATUS_SUCCESS;

				} else {
					pmbuf->status_code =
						MLAN_ERROR_CMD_RESP_FAIL;
					ret = MLAN_STATUS_FAILURE;
				}
				PRINTM(MINFO, "mlan_recv: no curr_cmd\n");
			} else {
				wlan_request_cmd_lock(pmadapter);
				pmadapter->upld_len = len;
				pmbuf->data_offset += MLAN_TYPE_LEN;
				pmbuf->data_len -= MLAN_TYPE_LEN;
				pmadapter->curr_cmd->respbuf = pmbuf;
				pmadapter->cmd_resp_received = MTRUE;
				wlan_release_cmd_lock(pmadapter);
			}
			break;
		case MLAN_USB_TYPE_EVENT:
			MASSERT(len >= sizeof(t_u32));
			memmove(pmadapter, &event_cause, pbuf, sizeof(t_u32));
			pmadapter->event_cause = wlan_le32_to_cpu(event_cause);
			PRINTM_GET_SYS_TIME(MEVENT, &sec, &usec);
			PRINTM(MEVENT, "mlan_recv: EVENT 0x%x (%lu.%06lu)\n",
			       pmadapter->event_cause, sec, usec);
			pbuf += sizeof(t_u32);
			len -= sizeof(t_u32);
			if ((len > 0) && (len < MAX_EVENT_SIZE))
				memmove(pmadapter, pmadapter->event_body, pbuf,
					len);
			pmadapter->event_received = MTRUE;
			pmadapter->pmlan_buffer_event = pmbuf;
			/* remove 4 byte recv_type */
			pmbuf->data_offset += MLAN_TYPE_LEN;
			pmbuf->data_len -= MLAN_TYPE_LEN;
			/* MOAL to call mlan_main_process for processing */
			break;
		default:
			pmbuf->status_code = MLAN_ERROR_PKT_INVALID;
			ret = MLAN_STATUS_FAILURE;
			PRINTM(MERROR, "mlan_recv: unknown recv_type 0x%x\n",
			       recv_type);
			break;
		}
	} else if (port == pmadapter->rx_data_ep) {
		PRINTM_GET_SYS_TIME(MDATA, &sec, &usec);
		PRINTM(MDATA, "mlan_recv: DATA (%lu.%06lu)\n", sec, usec);
#if defined(USB)
		if (pmadapter->pcard_usb->usb_rx_deaggr.aggr_ctrl.enable) {
			max_rx_data_size = pmadapter->pcard_usb->usb_rx_deaggr
						   .aggr_ctrl.aggr_max;
			if (pmadapter->pcard_usb->usb_rx_deaggr.aggr_ctrl
				    .aggr_mode == MLAN_USB_AGGR_MODE_NUM) {
				max_rx_data_size *=
					MAX(MLAN_USB_MAX_PKT_SIZE,
					    pmadapter->pcard_usb->usb_rx_deaggr
						    .aggr_ctrl.aggr_align);
				max_rx_data_size = MAX(max_rx_data_size,
						       MLAN_RX_DATA_BUF_SIZE);
			}
		}
#endif
		if (len > max_rx_data_size) {
			pmbuf->status_code = MLAN_ERROR_PKT_SIZE_INVALID;
			ret = MLAN_STATUS_FAILURE;
			PRINTM(MERROR, "mlan_recv: DATA too large\n");
		} else {
			pmadapter->upld_len = len;
			pmadapter->callbacks.moal_get_system_time(
				pmadapter->pmoal_handle, &pmbuf->in_ts_sec,
				&pmbuf->in_ts_usec);
			pmadapter->callbacks.moal_spin_lock(
				pmadapter->pmoal_handle,
				pmadapter->rx_data_queue.plock);
			util_enqueue_list_tail(pmadapter->pmoal_handle,
					       &pmadapter->rx_data_queue,
					       (pmlan_linked_list)pmbuf, MNULL,
					       MNULL);
			pmadapter->rx_pkts_queued++;
			pmadapter->callbacks.moal_spin_unlock(
				pmadapter->pmoal_handle,
				pmadapter->rx_data_queue.plock);
			pmadapter->data_received = MTRUE;
			mlan_queue_rx_work(pmadapter);
		}
	} else {
		pmbuf->status_code = MLAN_ERROR_PKT_INVALID;
		ret = MLAN_STATUS_FAILURE;
		PRINTM(MERROR, "mlan_recv: unknown port number 0x%x\n", port);
	}

	LEAVE();
	return ret;
}
#endif /* USB */

/**
 *  @brief Packet receive completion callback handler
 *
 *  @param padapter	A pointer to mlan_adapter structure
 *  @param pmbuf		A pointer to mlan_buffer structure
 *  @param status		Callback status
 *
 *  @return			MLAN_STATUS_SUCCESS
 */
mlan_status mlan_recv_packet_complete(t_void *padapter, pmlan_buffer pmbuf,
				      mlan_status status)
{
	mlan_adapter *pmadapter = (mlan_adapter *)padapter;

	ENTER();
	wlan_recv_packet_complete(pmadapter, pmbuf, status);
	LEAVE();
	return MLAN_STATUS_SUCCESS;
}

/**
 *  @brief select wmm queue
 *
 *  @param padapter	A pointer to mlan_adapter structure
 *  @param bss_num		BSS number
 *  @param tid			TID
 *
 *  @return			wmm queue priority (0 - 3)
 */
t_u8 mlan_select_wmm_queue(t_void *padapter, t_u8 bss_num, t_u8 tid)
{
	mlan_adapter *pmadapter = (mlan_adapter *)padapter;
	pmlan_private pmpriv = pmadapter->priv[bss_num];
	t_u8 ret;
	ENTER();
	ret = wlan_wmm_select_queue(pmpriv, tid);
	LEAVE();
	return ret;
}

/**
 *  @brief this function handle the amsdu packet after deaggreate.
 *
 *  @param padapter	A pointer to mlan_adapter structure
 *  @param pmbuf    A pointer to the deaggreated buf
 *  @param drop	    A pointer to return the drop flag.
 *
 *  @return			N/A
 */
void mlan_process_deaggr_pkt(t_void *padapter, pmlan_buffer pmbuf, t_u8 *drop)
{
	mlan_adapter *pmadapter = (mlan_adapter *)padapter;
	mlan_private *pmpriv;
	t_u16 eth_type = 0;

	*drop = MFALSE;
	pmpriv = pmadapter->priv[pmbuf->bss_index];
	eth_type =
		mlan_ntohs(*(t_u16 *)&pmbuf->pbuf[pmbuf->data_offset +
						  MLAN_ETHER_PKT_TYPE_OFFSET]);
	switch (eth_type) {
	case MLAN_ETHER_PKT_TYPE_EAPOL:
		PRINTM(MEVENT, "Recevie AMSDU EAPOL frame\n");
		if (pmpriv->sec_info.ewpa_enabled) {
			*drop = MTRUE;
			if (MLAN_STATUS_FAILURE ==
			    wlan_prepare_cmd(pmpriv,
					     HostCmd_CMD_802_11_EAPOL_PKT, 0, 0,
					     MNULL, pmbuf)) {
				PRINTM(MERROR, "Preparing the CMD failed\n");
			}
			wlan_recv_event(pmpriv,
					MLAN_EVENT_ID_DRV_DEFER_HANDLING,
					MNULL);
		}
		break;
	case MLAN_ETHER_PKT_TYPE_TDLS_ACTION:
		PRINTM(MEVENT, "Recevie AMSDU TDLS action frame\n");
		wlan_process_tdls_action_frame(pmpriv,
					       pmbuf->pbuf + pmbuf->data_offset,
					       pmbuf->data_len);
		break;
	default:
		break;
	}
	return;
}

#if defined(SDIO) || defined(PCIE)
/**
 *  @brief This function gets interrupt status.
 *  @param msg_id only used for PCIE
 */
/**
 *  @param msg_id  A message id
 *  @param adapter  A pointer to mlan_adapter structure
 *  @return         MLAN_STATUS_FAILURE -- if the intererupt is not for us
 */
mlan_status mlan_interrupt(t_u16 msg_id, t_void *adapter)
{
	mlan_adapter *pmadapter = (mlan_adapter *)adapter;
	mlan_status ret;

	ENTER();
	ret = pmadapter->ops.interrupt(msg_id, pmadapter);
	LEAVE();
	return ret;
}
#endif

/**
 *  @brief This function wakeup firmware.
 *
 *  @param adapter  A pointer to mlan_adapter structure
 *  @param keep_wakeup   keep wake up flag
 *  @return         N/A
 */
t_void mlan_pm_wakeup_card(t_void *adapter, t_u8 keep_wakeup)
{
	mlan_adapter *pmadapter = (mlan_adapter *)adapter;

	ENTER();
	if (keep_wakeup)
		pmadapter->ops.wakeup_card(pmadapter, MFALSE);
	pmadapter->keep_wakeup = keep_wakeup;

	LEAVE();
}

/**
 *  @brief This function check main_process status.
 *
 *  @param adapter  A pointer to mlan_adapter structure
 *  @return         MTRUE/MFALSE
 */
t_u8 mlan_is_main_process_running(t_void *adapter)
{
	mlan_adapter *pmadapter = (mlan_adapter *)adapter;
	pmlan_callbacks pcb = &pmadapter->callbacks;
	t_u8 ret = MFALSE;
	ENTER();
	pcb->moal_spin_lock(pmadapter->pmoal_handle,
			    pmadapter->pmain_proc_lock);

	/* Check if already processing */
	if (pmadapter->mlan_processing) {
		pmadapter->more_task_flag = MTRUE;
		ret = MTRUE;
	}
	pcb->moal_spin_unlock(pmadapter->pmoal_handle,
			      pmadapter->pmain_proc_lock);
	LEAVE();
	return ret;
}

#ifdef PCIE
/**
 *  @brief This function sets the PCIE interrupt mode.
 *
 *  @param adapter  A pointer to mlan_adapter structure
 *  @param int_mode PCIE interrupt type active
 *  @param func_num PCIE function num
 *  @return         N/A
 */
t_void mlan_set_int_mode(t_void *adapter, t_u32 int_mode, t_u8 func_num)
{
	mlan_adapter *pmadapter = (mlan_adapter *)adapter;
	ENTER();
	pmadapter->pcard_pcie->pcie_int_mode = int_mode;
	pmadapter->pcard_pcie->func_num = func_num;
	LEAVE();
}
#endif
